reuse validation rule

This commit is contained in:
Athou
2026-01-16 01:08:25 +01:00
parent 5a95b95801
commit 5f30cb7e2e
32 changed files with 82 additions and 155 deletions

View File

@@ -13,6 +13,7 @@ import { useAppDispatch, useAppSelector } from "@/app/store"
import type { ProfileModificationRequest } from "@/app/types" import type { ProfileModificationRequest } from "@/app/types"
import { reloadProfile } from "@/app/user/thunks" import { reloadProfile } from "@/app/user/thunks"
import { Alert } from "@/components/Alert" import { Alert } from "@/components/Alert"
import { useValidationRules } from "@/hooks/useValidationRules"
interface FormData extends ProfileModificationRequest { interface FormData extends ProfileModificationRequest {
newPasswordConfirmation?: string newPasswordConfirmation?: string
@@ -23,13 +24,11 @@ export function ProfileSettings() {
const serverInfos = useAppSelector(state => state.server.serverInfos) const serverInfos = useAppSelector(state => state.server.serverInfos)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { _ } = useLingui() const { _ } = useLingui()
const validationRules = useValidationRules()
const form = useForm<FormData>({ const form = useForm<FormData>({
validate: { validate: {
newPassword: value => newPassword: validationRules.password,
value && serverInfos && value.length < serverInfos.minimumPasswordLength
? _(msg`Password must be at least ${serverInfos.minimumPasswordLength} characters`)
: null,
newPasswordConfirmation: (value, values) => (value !== values.newPassword ? _(msg`Passwords do not match`) : null), newPasswordConfirmation: (value, values) => (value !== values.newPassword ? _(msg`Passwords do not match`) : null),
}, },
validateInputOnChange: true, validateInputOnChange: true,

View File

@@ -0,0 +1,15 @@
import { msg } from "@lingui/core/macro"
import { useLingui } from "@lingui/react"
import { useAppSelector } from "@/app/store"
export function useValidationRules() {
const minimumPasswordLength = useAppSelector(state => state.server.serverInfos?.minimumPasswordLength)
const { _ } = useLingui()
return {
password: (value: string | undefined) =>
value && minimumPasswordLength && value.length < minimumPasswordLength
? _(msg`Password must be at least ${minimumPasswordLength} characters`)
: null,
}
}

View File

@@ -771,11 +771,8 @@ msgstr "الفئة الأصل"
msgid "Password" msgid "Password"
msgstr "كلمة المرور" msgstr "كلمة المرور"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Categoria pare"
msgid "Password" msgid "Password"
msgstr "Contrasenya" msgstr "Contrasenya"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Rodičovská kategorie"
msgid "Password" msgid "Password"
msgstr "Heslo" msgstr "Heslo"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Categori Rhiant"
msgid "Password" msgid "Password"
msgstr "cyfrinair" msgstr "cyfrinair"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Forældrekategori"
msgid "Password" msgid "Password"
msgstr "Adgangskode" msgstr "Adgangskode"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Übergeordnete Kategorie"
msgid "Password" msgid "Password"
msgstr "Passwort" msgstr "Passwort"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,12 +771,9 @@ msgstr "Parent Category"
msgid "Password" msgid "Password"
msgstr "Password" msgstr "Password"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx msgstr "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "Password must be at least {0} characters"
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery" msgid "Password Recovery"

View File

@@ -772,11 +772,8 @@ msgstr "Categoría principal"
msgid "Password" msgid "Password"
msgstr "Contraseña" msgstr "Contraseña"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "دسته والد"
msgid "Password" msgid "Password"
msgstr "رمز عبور" msgstr "رمز عبور"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Pääluokka"
msgid "Password" msgid "Password"
msgstr "Salasana" msgstr "Salasana"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Catégorie parente"
msgid "Password" msgid "Password"
msgstr "Mot de passe" msgstr "Mot de passe"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -772,11 +772,8 @@ msgstr "Categoría superior"
msgid "Password" msgid "Password"
msgstr "Contrasinal" msgstr "Contrasinal"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Szülő kategória"
msgid "Password" msgid "Password"
msgstr "Jelszó" msgstr "Jelszó"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Kategori Induk"
msgid "Password" msgid "Password"
msgstr "Kata Sandi" msgstr "Kata Sandi"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Categoria padre"
msgid "Password" msgid "Password"
msgstr "" msgstr ""
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "親カテゴリ"
msgid "Password" msgid "Password"
msgstr "パスワード" msgstr "パスワード"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "부모 카테고리"
msgid "Password" msgid "Password"
msgstr "비밀번호" msgstr "비밀번호"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Kategori Induk"
msgid "Password" msgid "Password"
msgstr "Kata Laluan" msgstr "Kata Laluan"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Overordnet kategori"
msgid "Password" msgid "Password"
msgstr "Passord" msgstr "Passord"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Oudercategorie"
msgid "Password" msgid "Password"
msgstr "Wachtwoord" msgstr "Wachtwoord"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Overordnet kategori"
msgid "Password" msgid "Password"
msgstr "Passord" msgstr "Passord"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Kategoria nadrzędna"
msgid "Password" msgid "Password"
msgstr "Hasło" msgstr "Hasło"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Categoria Pai"
msgid "Password" msgid "Password"
msgstr "Senha" msgstr "Senha"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Родительская категория"
msgid "Password" msgid "Password"
msgstr "Пароль" msgstr "Пароль"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Rodičovská kategória"
msgid "Password" msgid "Password"
msgstr "Heslo" msgstr "Heslo"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Föräldrakategori"
msgid "Password" msgid "Password"
msgstr "Lösenord" msgstr "Lösenord"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "Üst Kategori"
msgid "Password" msgid "Password"
msgstr "Şifre" msgstr "Şifre"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -771,11 +771,8 @@ msgstr "父类别"
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
#. placeholder {0}: serverInfos.minimumPasswordLength #: src/hooks/useValidationRules.ts
#: src/components/settings/ProfileSettings.tsx msgid "Password must be at least {minimumPasswordLength} characters"
#: src/pages/auth/InitialSetupPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password must be at least {0} characters"
msgstr "" msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx #: src/pages/auth/PasswordRecoveryPage.tsx

View File

@@ -6,15 +6,16 @@ import { useForm } from "@mantine/form"
import { useAsyncCallback } from "react-async-hook" import { useAsyncCallback } from "react-async-hook"
import { client, errorToStrings } from "@/app/client" import { client, errorToStrings } from "@/app/client"
import { redirectToRootCategory } from "@/app/redirect/thunks" import { redirectToRootCategory } from "@/app/redirect/thunks"
import { useAppDispatch, useAppSelector } from "@/app/store" import { useAppDispatch } from "@/app/store"
import type { InitialSetupRequest } from "@/app/types" import type { InitialSetupRequest } from "@/app/types"
import { Alert } from "@/components/Alert" import { Alert } from "@/components/Alert"
import { useValidationRules } from "@/hooks/useValidationRules"
import { PageTitle } from "@/pages/PageTitle" import { PageTitle } from "@/pages/PageTitle"
export function InitialSetupPage() { export function InitialSetupPage() {
const serverInfos = useAppSelector(state => state.server.serverInfos)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { _ } = useLingui() const { _ } = useLingui()
const validationRules = useValidationRules()
const form = useForm<InitialSetupRequest>({ const form = useForm<InitialSetupRequest>({
initialValues: { initialValues: {
@@ -23,10 +24,7 @@ export function InitialSetupPage() {
email: "", email: "",
}, },
validate: { validate: {
password: value => password: validationRules.password,
serverInfos && value.length < serverInfos.minimumPasswordLength
? _(msg`Password must be at least ${serverInfos.minimumPasswordLength} characters`)
: null,
}, },
validateInputOnChange: true, validateInputOnChange: true,
}) })

View File

@@ -10,12 +10,14 @@ import { redirectToRootCategory } from "@/app/redirect/thunks"
import { useAppDispatch, useAppSelector } from "@/app/store" import { useAppDispatch, useAppSelector } from "@/app/store"
import type { RegistrationRequest } from "@/app/types" import type { RegistrationRequest } from "@/app/types"
import { Alert } from "@/components/Alert" import { Alert } from "@/components/Alert"
import { useValidationRules } from "@/hooks/useValidationRules"
import { PageTitle } from "@/pages/PageTitle" import { PageTitle } from "@/pages/PageTitle"
export function RegistrationPage() { export function RegistrationPage() {
const serverInfos = useAppSelector(state => state.server.serverInfos) const serverInfos = useAppSelector(state => state.server.serverInfos)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const { _ } = useLingui() const { _ } = useLingui()
const validationRules = useValidationRules()
const form = useForm<RegistrationRequest>({ const form = useForm<RegistrationRequest>({
initialValues: { initialValues: {
@@ -24,10 +26,7 @@ export function RegistrationPage() {
email: "", email: "",
}, },
validate: { validate: {
password: value => password: validationRules.password,
serverInfos && value.length < serverInfos.minimumPasswordLength
? _(msg`Password must be at least ${serverInfos.minimumPasswordLength} characters`)
: null,
}, },
validateInputOnChange: true, validateInputOnChange: true,
}) })