-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented user sign-in and sign-out. (#82)
Co-authored-by: Francis Pion <francis.pion@akinox.com>
- Loading branch information
1 parent
d6a108e
commit 94bd929
Showing
31 changed files
with
528 additions
and
317 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import sleep from "./sleep"; | ||
import type { CurrentUser, SignInPayload } from "@/types/account"; | ||
import { useUserStore } from "@/stores/user"; | ||
|
||
export async function signIn(payload: SignInPayload): Promise<CurrentUser> { | ||
await sleep(2500); | ||
const users = useUserStore(); | ||
return users.signIn(payload); | ||
} | ||
|
||
export async function signOut(): Promise<void> { | ||
await sleep(2500); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export default function sleep(ms: number): Promise<void> { | ||
return new Promise((resolve) => setTimeout(resolve, ms)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<script setup lang="ts"> | ||
import { TarInput, inputUtils, parsingUtils, type InputOptions, type InputStatus } from "logitar-vue3-ui"; | ||
import { computed, ref } from "vue"; | ||
import { nanoid } from "nanoid"; | ||
import { useField } from "vee-validate"; | ||
import { useI18n } from "vue-i18n"; | ||
import type { ShowStatus, ValidationListeners, ValidationRules, ValidationType } from "@/types/validation"; | ||
import { isNullOrWhiteSpace } from "@/helpers/stringUtils"; | ||
const { isDateTimeInput, isNumericInput, isTextualInput } = inputUtils; | ||
const { parseBoolean, parseNumber } = parsingUtils; | ||
const { t } = useI18n(); | ||
const props = withDefaults( | ||
defineProps< | ||
InputOptions & { | ||
rules?: ValidationRules; | ||
showStatus?: ShowStatus; | ||
validation?: ValidationType; | ||
} | ||
>(), | ||
{ | ||
id: () => nanoid(), | ||
showStatus: "touched", | ||
validation: "client", | ||
}, | ||
); | ||
const inputRef = ref<InstanceType<typeof TarInput> | null>(null); | ||
const describedBy = computed<string>(() => `${props.id}_invalid-feedback`); | ||
const inputMax = computed<number | string | undefined>(() => (props.validation === "server" || isDateTimeInput(props.type) ? props.max : undefined)); | ||
const inputMin = computed<number | string | undefined>(() => (props.validation === "server" || isDateTimeInput(props.type) ? props.min : undefined)); | ||
const inputName = computed<string>(() => props.name ?? props.id); | ||
const inputRequired = computed<boolean | "label">(() => (parseBoolean(props.required) ? (props.validation === "server" ? true : "label") : false)); | ||
const validationRules = computed<ValidationRules>(() => { | ||
const rules: ValidationRules = {}; | ||
if (props.validation === "server") { | ||
return rules; | ||
} | ||
const required: boolean | undefined = parseBoolean(props.required); | ||
if (required) { | ||
rules.required = true; | ||
} | ||
const max: number | undefined = parseNumber(props.max); | ||
const min: number | undefined = parseNumber(props.min); | ||
if (isNumericInput(props.type)) { | ||
if (max) { | ||
rules.max_value = max; | ||
} | ||
if (min) { | ||
rules.min_value = min; | ||
} | ||
} else if (isTextualInput(props.type)) { | ||
if (max) { | ||
rules.max_length = max; | ||
} | ||
if (min) { | ||
rules.min_length = min; | ||
} | ||
} | ||
if (!isNullOrWhiteSpace(props.pattern)) { | ||
rules.regex = props.pattern; | ||
} | ||
switch (props.type) { | ||
case "email": | ||
rules.email = true; | ||
break; | ||
case "url": | ||
rules.url = true; | ||
break; | ||
} | ||
return { ...rules, ...props.rules }; | ||
}); | ||
const displayLabel = computed<string>(() => (props.label ? t(props.label).toLowerCase() : inputName.value)); | ||
const { errorMessage, handleChange, meta, value } = useField<string>(inputName, validationRules, { | ||
initialValue: props.modelValue, | ||
label: displayLabel, | ||
}); | ||
const inputStatus = computed<InputStatus | undefined>(() => { | ||
if (props.showStatus === "always" || (props.showStatus === "touched" && (meta.dirty || meta.touched))) { | ||
return props.status ?? (props.validation === "server" ? undefined : meta.valid ? "valid" : "invalid"); | ||
} | ||
return undefined; | ||
}); | ||
const validationListeners = computed<ValidationListeners>(() => ({ | ||
blur: handleChange, | ||
change: handleChange, | ||
input: errorMessage.value ? handleChange : (e: unknown) => handleChange(e, false), | ||
})); | ||
function focus(): void { | ||
inputRef.value?.focus(); | ||
} | ||
defineExpose({ focus }); | ||
</script> | ||
|
||
<template> | ||
<TarInput | ||
:described-by="describedBy" | ||
:disabled="disabled" | ||
:floating="floating" | ||
:id="id" | ||
:label="label ? t(label) : undefined" | ||
:max="inputMax" | ||
:min="inputMin" | ||
:model-value="validation === 'server' ? modelValue : value" | ||
:name="name" | ||
:pattern="validation === 'server' ? pattern : undefined" | ||
:placeholder="placeholder ? t(placeholder) : undefined" | ||
:plaintext="plaintext" | ||
:readonly="readonly" | ||
ref="inputRef" | ||
:required="inputRequired" | ||
:size="size" | ||
:status="inputStatus" | ||
:step="step" | ||
:type="type" | ||
v-on="validationListeners" | ||
> | ||
<template #before> | ||
<slot name="before"></slot> | ||
</template> | ||
<template #prepend> | ||
<slot name="prepend"></slot> | ||
</template> | ||
<template #append> | ||
<slot name="append"></slot> | ||
</template> | ||
<template #after> | ||
<div v-if="errorMessage" class="invalid-feedback" :id="describedBy">{{ errorMessage }}</div> | ||
<slot name="after"></slot> | ||
</template> | ||
</TarInput> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<script setup lang="ts"> | ||
import { computed, ref } from "vue"; | ||
import { useI18n } from "vue-i18n"; | ||
import AppInput from "@/components/shared/AppInput.vue"; | ||
import type { ConfirmedParams, ValidationRules } from "@/types/validation"; | ||
import type { PasswordSettings } from "@/types/settings"; | ||
const { t } = useI18n(); | ||
const props = withDefaults( | ||
defineProps<{ | ||
confirm?: ConfirmedParams<string>; | ||
id?: string; | ||
label?: string; | ||
modelValue?: string; | ||
required?: boolean | string; | ||
settings?: PasswordSettings; | ||
}>(), | ||
{ | ||
id: "password", | ||
label: "users.password.label", | ||
}, | ||
); | ||
const inputRef = ref<InstanceType<typeof AppInput> | null>(); | ||
const rules = computed<ValidationRules>(() => { | ||
const rules: ValidationRules = {}; | ||
if (props.confirm) { | ||
rules.confirmed = [props.confirm.value, t(props.confirm.label).toLowerCase()]; | ||
} else if (props.settings) { | ||
if (props.settings.minimumLength) { | ||
rules.min_length = props.settings.minimumLength; | ||
} | ||
if (props.settings.uniqueCharacters) { | ||
rules.unique_chars = props.settings.uniqueCharacters; | ||
} | ||
if (props.settings.requireNonAlphanumeric) { | ||
rules.require_non_alphanumeric = true; | ||
} | ||
if (props.settings.requireLowercase) { | ||
rules.require_lowercase = true; | ||
} | ||
if (props.settings.requireUppercase) { | ||
rules.require_uppercase = true; | ||
} | ||
if (props.settings.requireDigit) { | ||
rules.require_digit = true; | ||
} | ||
} | ||
return rules; | ||
}); | ||
defineEmits<{ | ||
(e: "update:model-value", value?: string): void; | ||
}>(); | ||
function focus(): void { | ||
inputRef.value?.focus(); | ||
} | ||
defineExpose({ focus }); | ||
</script> | ||
|
||
<template> | ||
<AppInput | ||
floating | ||
:id="id" | ||
:label="label" | ||
:model-value="modelValue" | ||
:placeholder="label" | ||
ref="inputRef" | ||
:required="required" | ||
:rules="rules" | ||
type="password" | ||
@update:model-value="$emit('update:model-value', $event)" | ||
/> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<script setup lang="ts"> | ||
import { computed } from "vue"; | ||
import { parsingUtils } from "logitar-vue3-ui"; | ||
import AppInput from "@/components/shared/AppInput.vue"; | ||
import type { UsernameSettings } from "@/types/settings"; | ||
import type { ValidationRules } from "@/types/validation"; | ||
const { parseBoolean } = parsingUtils; | ||
const props = defineProps<{ | ||
disabled?: boolean | string; | ||
modelValue?: string; | ||
noStatus?: boolean | string; | ||
required?: boolean | string; | ||
settings?: UsernameSettings; | ||
}>(); | ||
const rules = computed<ValidationRules>(() => { | ||
const rules: ValidationRules = {}; | ||
if (props.settings?.allowedCharacters) { | ||
rules.allowed_characters = props.settings.allowedCharacters; | ||
} | ||
return rules; | ||
}); | ||
defineEmits<{ | ||
(e: "update:model-value", value?: string): void; | ||
}>(); | ||
</script> | ||
|
||
<template> | ||
<AppInput | ||
:disabled="disabled" | ||
floating | ||
id="username" | ||
label="users.username" | ||
max="255" | ||
:model-value="modelValue" | ||
placeholder="users.username" | ||
:required="required" | ||
:rules="rules" | ||
:show-status="parseBoolean(noStatus) ? 'never' : undefined" | ||
@update:model-value="$emit('update:model-value', $event)" | ||
/> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import countries from "./countries.en.json"; | ||
import index from "./index.en.json"; | ||
import users from "./users.en.json"; | ||
|
||
export default { | ||
...index, | ||
countries, | ||
users, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"password": { | ||
"label": "Password" | ||
}, | ||
"signIn": { | ||
"failed": "Sign in failed!", | ||
"invalidCredentials": "Please check you provided the correct email username and password.", | ||
"submit": "Sign in", | ||
"title": "Sign In" | ||
}, | ||
"signOut": "Sign Out", | ||
"username": "Username" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
import countries from "./countries.fr.json"; | ||
import index from "./index.fr.json"; | ||
import users from "./users.fr.json"; | ||
|
||
export default { | ||
...index, | ||
countries, | ||
users, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"password": { | ||
"label": "Mot de passe" | ||
}, | ||
"signIn": { | ||
"failed": "Connexion échouée !", | ||
"invalidCredentials": "Veuillez vérifier que vous avez entré votre nom d’utilisateur et mot de passe.", | ||
"submit": "Se connecter", | ||
"title": "Connexion" | ||
}, | ||
"signOut": "Déconnexion", | ||
"username": "Nom d’utilisateur" | ||
} |
Oops, something went wrong.