refactor: update zod imports to version 4 and adjust error handling
- Changed all zod imports from "zod" to "zod/v4" across multiple files. - Updated error handling in forms to use new zod error configuration. - Refactored custom error mapping to align with zod v4 changes. - Adjusted password validation logic to utilize new zod features. - Cleaned up unused locale error mapping code. - Enhanced type definitions for async iterables in zod utility functions.
This commit is contained in:
parent
e61b152986
commit
9314026817
53 changed files with 333 additions and 525 deletions
46
apps/infoalloggi/package-lock.json
generated
46
apps/infoalloggi/package-lock.json
generated
|
|
@ -78,7 +78,7 @@
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"yaml": "^2.8.1",
|
"yaml": "^2.8.1",
|
||||||
"zod": "^3.25.76"
|
"zod": "^4.0.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.3.1",
|
"@eslint/compat": "^1.3.1",
|
||||||
|
|
@ -127,7 +127,7 @@
|
||||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||||
"tailwind-scrollbar": "^4.0.2",
|
"tailwind-scrollbar": "^4.0.2",
|
||||||
"tailwindcss": "^4.1.11",
|
"tailwindcss": "^4.1.11",
|
||||||
"trpc-ui": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
"trpc-ui": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=%26%26%20npm%20install%20pnpm%20%26%26%20npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
||||||
"tw-animate-css": "^1.3.6",
|
"tw-animate-css": "^1.3.6",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"typescript-eslint": "^8.39.0"
|
"typescript-eslint": "^8.39.0"
|
||||||
|
|
@ -13830,6 +13830,16 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/knip/node_modules/zod": {
|
||||||
|
"version": "3.25.76",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
|
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kysely": {
|
"node_modules/kysely": {
|
||||||
"version": "0.28.4",
|
"version": "0.28.4",
|
||||||
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.4.tgz",
|
||||||
|
|
@ -20092,8 +20102,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/trpc-ui": {
|
"node_modules/trpc-ui": {
|
||||||
"version": "1.0.15",
|
"version": "1.0.15",
|
||||||
"resolved": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
"resolved": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=%26%26%20npm%20install%20pnpm%20%26%26%20npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
||||||
"integrity": "sha512-E1FvgLyMzBFneyBxmYaW4FV4IaUjOcfSyN1fRpMdc3160/fePfSkUVP015FW4qNAuLc4hhQyOVXqefWquR9FUg==",
|
"integrity": "sha512-3cw5HsTSl114eZQH1SGm3NWzb0JnDIdyB3Ins2kELHMFBax2Y7v2GLDAh5vkOc1IGqSwYg3gjbMLytKEug2B9w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
|
|
@ -20188,6 +20198,16 @@
|
||||||
"url": "https://github.com/sponsors/dcastil"
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/trpc-ui/node_modules/zod-to-json-schema": {
|
||||||
|
"version": "3.24.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
|
||||||
|
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"zod": "^3.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
||||||
|
|
@ -21279,24 +21299,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "3.25.76",
|
"version": "4.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.0.15.tgz",
|
||||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
"integrity": "sha512-2IVHb9h4Mt6+UXkyMs0XbfICUh1eUrlJJAOupBHUhLRnKkruawyDddYRCs0Eizt900ntIMk9/4RksYl+FgSpcQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/zod-to-json-schema": {
|
|
||||||
"version": "3.24.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz",
|
|
||||||
"integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"peerDependencies": {
|
|
||||||
"zod": "^3.24.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/zod-validation-error": {
|
"node_modules/zod-validation-error": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.5.3.tgz",
|
||||||
|
|
@ -21351,4 +21361,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"vaul": "^1.1.2",
|
"vaul": "^1.1.2",
|
||||||
"yaml": "^2.8.1",
|
"yaml": "^2.8.1",
|
||||||
"zod": "^3.25.76"
|
"zod": "^4.0.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.3.1",
|
"@eslint/compat": "^1.3.1",
|
||||||
|
|
@ -138,8 +138,8 @@
|
||||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||||
"tailwind-scrollbar": "^4.0.2",
|
"tailwind-scrollbar": "^4.0.2",
|
||||||
"tailwindcss": "^4.1.11",
|
"tailwindcss": "^4.1.11",
|
||||||
"tw-animate-css": "^1.3.6",
|
|
||||||
"trpc-ui": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=%26%26%20npm%20install%20pnpm%20%26%26%20npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
"trpc-ui": "https://gitpkg.vercel.app/jrhe/trpc-ui/packages/trpc-ui?feature/zod-v4-support&scripts.postinstall=%26%26%20npm%20install%20pnpm%20%26%26%20npm%20install%20--ignore-scripts%20%26%26%20npm%20run%20build",
|
||||||
|
"tw-animate-css": "^1.3.6",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
"typescript-eslint": "^8.39.0"
|
"typescript-eslint": "^8.39.0"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ import { LoadingPage } from "~/components/loading";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { Separator } from "~/components/ui/separator";
|
import { Separator } from "~/components/ui/separator";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -152,8 +152,8 @@ export const AnnuncioActions = () => {
|
||||||
|
|
||||||
const ContrattoImportSchema = z.object({
|
const ContrattoImportSchema = z.object({
|
||||||
gestionale_id: z.number().nullable(),
|
gestionale_id: z.number().nullable(),
|
||||||
contratto_decorrenza: z.coerce.date().nullable(),
|
contratto_decorrenza: z.date().nullable(),
|
||||||
contratto_scadenza: z.coerce.date().nullable(),
|
contratto_scadenza: z.date().nullable(),
|
||||||
contratto_tipo: z
|
contratto_tipo: z
|
||||||
.enum([
|
.enum([
|
||||||
"Transitorio",
|
"Transitorio",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
||||||
|
|
@ -9,7 +9,7 @@ import { z } from "zod";
|
||||||
*/
|
*/
|
||||||
const server = z.object({
|
const server = z.object({
|
||||||
NODE_ENV: z.enum(["development", "test", "production"]),
|
NODE_ENV: z.enum(["development", "test", "production"]),
|
||||||
INTERNAL_BASE_URL: z.string().url(),
|
INTERNAL_BASE_URL: z.url(),
|
||||||
PGHOST: z.string(),
|
PGHOST: z.string(),
|
||||||
POSTGRES_USER: z.string(),
|
POSTGRES_USER: z.string(),
|
||||||
POSTGRES_DB: z.string(),
|
POSTGRES_DB: z.string(),
|
||||||
|
|
@ -96,7 +96,7 @@ if (!!process.env.SKIP_ENV_VALIDATION === false) {
|
||||||
if (parsed.success === false) {
|
if (parsed.success === false) {
|
||||||
console.error(
|
console.error(
|
||||||
"❌ Invalid environment variables:",
|
"❌ Invalid environment variables:",
|
||||||
parsed.error.flatten().fieldErrors,
|
z.treeifyError(parsed.error).fieldErrors,
|
||||||
);
|
);
|
||||||
throw new Error("Invalid environment variables");
|
throw new Error("Invalid environment variables");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -54,10 +53,9 @@ export const FormBanlist = ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: Schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -73,10 +72,9 @@ export const FormBanners = ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: Schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { useStrongPassword } from "~/hooks/useStrongPassword";
|
import { useStrongPassword } from "~/hooks/useStrongPassword";
|
||||||
|
|
@ -45,10 +44,9 @@ export const ChangePasswordForm = () => {
|
||||||
|
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(ChangePasswordFormSchema, {
|
||||||
schema: ChangePasswordFormSchema,
|
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
oldpassword: "",
|
oldpassword: "",
|
||||||
newpassword: "",
|
newpassword: "",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -9,7 +9,6 @@ import {
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Textarea } from "~/components/custom_ui/textarea";
|
import { Textarea } from "~/components/custom_ui/textarea";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
@ -32,7 +31,7 @@ export const FormContattoAnnucio = ({ codice }: { codice: string }) => {
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
|
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
messaggio: z.string().nonempty("Inserisci un messaggio"),
|
messaggio: z.string().nonempty("Inserisci un messaggio"),
|
||||||
telefono: z.string().nonempty("Inserisci un numero di telefono"),
|
telefono: z.string().nonempty("Inserisci un numero di telefono"),
|
||||||
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
||||||
|
|
@ -47,8 +46,7 @@ export const FormContattoAnnucio = ({ codice }: { codice: string }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
type FromValues = z.infer<typeof schema>;
|
type FromValues = z.infer<typeof schema>;
|
||||||
const form = useZodForm({
|
const form = useZodForm(schema, {
|
||||||
schema: schema,
|
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
...value,
|
...value,
|
||||||
messaggio: "",
|
messaggio: "",
|
||||||
|
|
@ -89,7 +87,7 @@ export const FormContattoAnnucio = ({ codice }: { codice: string }) => {
|
||||||
codice,
|
codice,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto w-full">
|
<div className="mx-auto w-full">
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
|
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
|
|
@ -52,16 +51,15 @@ export const FormEtichette = ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: Schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(fields: FormValues) {
|
function onSubmit(fields: FormValues) {
|
||||||
const values = {
|
const values = {
|
||||||
id_etichetta: fields.id_etichetta as EtichetteIdEtichetta,
|
id_etichetta: fields.id_etichetta,
|
||||||
title: fields.title,
|
title: fields.title,
|
||||||
color_hex: fields.color_hex,
|
color_hex: fields.color_hex,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -46,10 +45,9 @@ export const FormFlags = ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: Schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
import { z } from "zod/v4";
|
||||||
import { z } from "zod";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -25,7 +24,7 @@ export const FormLogin = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { redirect } = router.query;
|
const { redirect } = router.query;
|
||||||
const LoginSchema = z.object({
|
const LoginSchema = z.object({
|
||||||
email: z.string().email("Inserisci una email valida"),
|
email: z.email(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
||||||
});
|
});
|
||||||
|
|
@ -38,10 +37,9 @@ export const FormLogin = () => {
|
||||||
checkbox: false, // Honeypot field
|
checkbox: false, // Honeypot field
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(LoginSchema, {
|
||||||
schema: LoginSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
import { z } from "zod/v4";
|
||||||
import { z } from "zod";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -20,7 +19,7 @@ import { useState } from "react";
|
||||||
export const FormPswReset = () => {
|
export const FormPswReset = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const LoginSchema = z.object({
|
const LoginSchema = z.object({
|
||||||
email: z.string().email("Inserisci una email valida"),
|
email: z.email(),
|
||||||
});
|
});
|
||||||
|
|
||||||
type LoginFormValues = z.infer<typeof LoginSchema>;
|
type LoginFormValues = z.infer<typeof LoginSchema>;
|
||||||
|
|
@ -29,10 +28,9 @@ export const FormPswReset = () => {
|
||||||
email: "",
|
email: "",
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(LoginSchema, {
|
||||||
schema: LoginSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -8,7 +8,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
@ -22,13 +21,13 @@ import { Label } from "~/components/ui/label";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import type { Servizio } from "~/schemas/public/Servizio";
|
import type { Servizio } from "~/schemas/public/Servizio";
|
||||||
|
|
||||||
const schema = z
|
const Schema = z
|
||||||
.object({
|
.object({
|
||||||
tipologia: z.custom<TipologiaPosizioneEnum>(),
|
tipologia: z.custom<TipologiaPosizioneEnum>(),
|
||||||
budget: z.coerce.number(),
|
budget: z.number(),
|
||||||
entromese: z.number().nullable(),
|
entromese: z.number().nullable(),
|
||||||
n_adulti: z.coerce.number().min(1),
|
n_adulti: z.number().min(1),
|
||||||
n_minori: z.coerce.number(),
|
n_minori: z.number(),
|
||||||
permanenza: z.number().nullable(),
|
permanenza: z.number().nullable(),
|
||||||
motivazione_transitorio: z.string().nullable(),
|
motivazione_transitorio: z.string().nullable(),
|
||||||
reddito: z.string().nullable(),
|
reddito: z.string().nullable(),
|
||||||
|
|
@ -43,15 +42,16 @@ const schema = z
|
||||||
})
|
})
|
||||||
.superRefine(({ n_adulti }, refinementContext) => {
|
.superRefine(({ n_adulti }, refinementContext) => {
|
||||||
if (n_adulti <= 0) {
|
if (n_adulti <= 0) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il numero di persone",
|
message: "Inserisci il numero di persone",
|
||||||
path: ["npersone"],
|
path: ["npersone"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FormValues = z.infer<typeof schema>;
|
export type FormValues = z.infer<typeof Schema>;
|
||||||
|
|
||||||
export const FormNewServizio = ({
|
export const FormNewServizio = ({
|
||||||
initialData,
|
initialData,
|
||||||
|
|
@ -91,10 +91,9 @@ export const FormNewServizio = ({
|
||||||
}
|
}
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -181,7 +180,7 @@ export const FormNewServizio = ({
|
||||||
step={50}
|
step={50}
|
||||||
defaultValue={[field.value]}
|
defaultValue={[field.value]}
|
||||||
onValueChange={(vals) => {
|
onValueChange={(vals) => {
|
||||||
field.onChange(vals[0]);
|
field.onChange(Number(vals[0]));
|
||||||
}}
|
}}
|
||||||
rangeClassName="bg-neutral-700"
|
rangeClassName="bg-neutral-700"
|
||||||
thumbClassName="border-neutral-700"
|
thumbClassName="border-neutral-700"
|
||||||
|
|
@ -313,8 +312,8 @@ export const FormNewServizio = ({
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Counter
|
<Counter
|
||||||
value={field.value}
|
value={Number(field.value)}
|
||||||
setValue={field.onChange}
|
setValue={(value) => field.onChange(Number(value))}
|
||||||
name="n_adulti"
|
name="n_adulti"
|
||||||
onlyPositive
|
onlyPositive
|
||||||
/>
|
/>
|
||||||
|
|
@ -338,8 +337,8 @@ export const FormNewServizio = ({
|
||||||
</div>
|
</div>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Counter
|
<Counter
|
||||||
value={field.value}
|
value={Number(field.value)}
|
||||||
setValue={field.onChange}
|
setValue={(value) => field.onChange(Number(value))}
|
||||||
name="n_minori"
|
name="n_minori"
|
||||||
onlyPositive
|
onlyPositive
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -10,7 +10,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -79,7 +78,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const schema = z
|
const Schema = z
|
||||||
.object({
|
.object({
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
|
|
@ -90,10 +89,10 @@ export const FormNewServizioAcquisto = ({
|
||||||
sede_legale: z.string().nullable(),
|
sede_legale: z.string().nullable(),
|
||||||
legale_rappresentante: z.string().nullable(),
|
legale_rappresentante: z.string().nullable(),
|
||||||
p_iva: z.string().nullable(),
|
p_iva: z.string().nullable(),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
telefono: z.string(),
|
telefono: z.string(),
|
||||||
sesso: z.string(),
|
sesso: z.string(),
|
||||||
data_nascita: z.coerce.date(),
|
data_nascita: z.date(),
|
||||||
luogo_nascita: z.string(),
|
luogo_nascita: z.string(),
|
||||||
nazione_nascita: z.string(),
|
nazione_nascita: z.string(),
|
||||||
codice_fiscale: z.string(),
|
codice_fiscale: z.string(),
|
||||||
|
|
@ -108,10 +107,10 @@ export const FormNewServizioAcquisto = ({
|
||||||
.string()
|
.string()
|
||||||
.refine((v) => v !== "", { params: { type: "nazione" } }),
|
.refine((v) => v !== "", { params: { type: "nazione" } }),
|
||||||
tipologia: z.custom<TipologiaPosizioneEnum>(),
|
tipologia: z.custom<TipologiaPosizioneEnum>(),
|
||||||
budget: z.coerce.number().positive(),
|
budget: z.number().positive(),
|
||||||
entromese: z.number().nullable(),
|
entromese: z.number().nullable(),
|
||||||
n_adulti: z.coerce.number().min(1),
|
n_adulti: z.number().min(1),
|
||||||
n_minori: z.coerce.number(),
|
n_minori: z.number(),
|
||||||
permanenza: z.number().nullable(),
|
permanenza: z.number().nullable(),
|
||||||
motivazione_transitorio: z.string().nullable(),
|
motivazione_transitorio: z.string().nullable(),
|
||||||
reddito: z.string().nullable(),
|
reddito: z.string().nullable(),
|
||||||
|
|
@ -152,57 +151,64 @@ export const FormNewServizioAcquisto = ({
|
||||||
refinementContext,
|
refinementContext,
|
||||||
) => {
|
) => {
|
||||||
if (entromese === null) {
|
if (entromese === null) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il mese di inizio",
|
message: "Inserisci il mese di inizio",
|
||||||
path: ["entromese"],
|
path: ["entromese"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (azienda) {
|
if (azienda) {
|
||||||
if (!ragione_sociale || ragione_sociale.length < 1) {
|
if (!ragione_sociale || ragione_sociale.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la ragione sociale",
|
message: "Inserisci la ragione sociale",
|
||||||
path: ["ragione_sociale"],
|
path: ["ragione_sociale"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!sede_legale || sede_legale.length < 1) {
|
if (!sede_legale || sede_legale.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la sede legale",
|
message: "Inserisci la sede legale",
|
||||||
path: ["sede_legale"],
|
path: ["sede_legale"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!p_iva || p_iva.length < 1) {
|
if (!p_iva || p_iva.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la partita iva",
|
message: "Inserisci la partita iva",
|
||||||
path: ["p_iva"],
|
path: ["p_iva"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il legale rappresentante",
|
message: "Inserisci il legale rappresentante",
|
||||||
path: ["legale_rappresentante"],
|
path: ["legale_rappresentante"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fatturazione_aziendale) {
|
if (fatturazione_aziendale) {
|
||||||
if (!codice_destinatario || codice_destinatario.length != 7) {
|
if (!codice_destinatario || codice_destinatario.length != 7) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci un codice destinatario valido",
|
message: "Inserisci un codice destinatario valido",
|
||||||
path: ["codice_destinatario"],
|
path: ["codice_destinatario"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!telefono || telefono.length < 10) {
|
if (!telefono || telefono.length < 10) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message:
|
message:
|
||||||
"Il numero di telefono deve essere lungo almeno 10 caratteri",
|
"Il numero di telefono deve essere lungo almeno 10 caratteri",
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
checkFiscalCodeValidity({
|
checkFiscalCodeValidity({
|
||||||
|
|
@ -217,20 +223,22 @@ export const FormNewServizioAcquisto = ({
|
||||||
nazioneNascita: nazione_nascita,
|
nazioneNascita: nazione_nascita,
|
||||||
});
|
});
|
||||||
if (n_adulti <= 0) {
|
if (n_adulti <= 0) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il numero di persone",
|
message: "Inserisci il numero di persone",
|
||||||
path: ["n_adulti"],
|
path: ["n_adulti"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
permanenza === null &&
|
permanenza === null &&
|
||||||
tipologia === TipologiaPosizioneEnum.Transitorio
|
tipologia === TipologiaPosizioneEnum.Transitorio
|
||||||
) {
|
) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci permanenza",
|
message: "Inserisci permanenza",
|
||||||
path: ["permanenza"],
|
path: ["permanenza"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tipologia === TipologiaPosizioneEnum.Transitorio) {
|
if (tipologia === TipologiaPosizioneEnum.Transitorio) {
|
||||||
|
|
@ -238,25 +246,27 @@ export const FormNewServizioAcquisto = ({
|
||||||
motivazione_transitorio === "" ||
|
motivazione_transitorio === "" ||
|
||||||
motivazione_transitorio === null
|
motivazione_transitorio === null
|
||||||
) {
|
) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la motivazione",
|
message: "Inserisci la motivazione",
|
||||||
path: ["motivazione_transitorio"],
|
path: ["motivazione_transitorio"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (reddito === "" || reddito === null) {
|
if (reddito === "" || reddito === null) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il reddito",
|
message: "Inserisci il reddito",
|
||||||
path: ["reddito"],
|
path: ["reddito"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
type FormValues = z.infer<typeof schema>;
|
type FormValues = z.infer<typeof Schema>;
|
||||||
|
|
||||||
// This can come from your database or API.
|
// This can come from your database or API.
|
||||||
const defaultValues: FormValues = {
|
const defaultValues: FormValues = {
|
||||||
|
|
@ -290,10 +300,9 @@ export const FormNewServizioAcquisto = ({
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
const nazioni_options = GetNazioni();
|
const nazioni_options = GetNazioni();
|
||||||
const comuni_options = getComuniNames();
|
const comuni_options = getComuniNames();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
const DatePickerLocale = locale === "it" ? it : enUS;
|
const DatePickerLocale = locale === "it" ? it : enUS;
|
||||||
|
|
@ -478,7 +487,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
step={50}
|
step={50}
|
||||||
defaultValue={[field.value]}
|
defaultValue={[field.value]}
|
||||||
onValueChange={(vals) => {
|
onValueChange={(vals) => {
|
||||||
field.onChange(vals[0]);
|
field.onChange(Number(vals[0]));
|
||||||
}}
|
}}
|
||||||
rangeClassName="bg-neutral-700"
|
rangeClassName="bg-neutral-700"
|
||||||
thumbClassName="border-neutral-700"
|
thumbClassName="border-neutral-700"
|
||||||
|
|
@ -593,7 +602,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Counter
|
<Counter
|
||||||
value={field.value}
|
value={field.value}
|
||||||
setValue={field.onChange}
|
setValue={(v) => field.onChange(Number(v))}
|
||||||
name="n_adulti"
|
name="n_adulti"
|
||||||
onlyPositive
|
onlyPositive
|
||||||
/>
|
/>
|
||||||
|
|
@ -615,7 +624,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Counter
|
<Counter
|
||||||
value={field.value}
|
value={field.value}
|
||||||
setValue={field.onChange}
|
setValue={(v) => field.onChange(Number(v))}
|
||||||
name="n_minori"
|
name="n_minori"
|
||||||
onlyPositive
|
onlyPositive
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -8,7 +8,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
|
|
@ -36,7 +35,7 @@ export const FormNewUser = ({
|
||||||
|
|
||||||
const NewUserSchema = z
|
const NewUserSchema = z
|
||||||
.object({
|
.object({
|
||||||
email: z.string().email("Inserisci una email valida"),
|
email: z.email(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
|
|
@ -61,10 +60,9 @@ export const FormNewUser = ({
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(NewUserSchema, {
|
||||||
schema: NewUserSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button, buttonVariants } from "~/components/ui/button";
|
import { Button, buttonVariants } from "~/components/ui/button";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
|
|
@ -57,10 +56,9 @@ export const OverridePasswordForm = ({ id }: { id: UsersId }) => {
|
||||||
|
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(OverridePasswordFormSchema, {
|
||||||
schema: OverridePasswordFormSchema,
|
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
password: "",
|
password: "",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -48,7 +47,7 @@ export const FormPrezzo = ({
|
||||||
const PrezzoSchema = z
|
const PrezzoSchema = z
|
||||||
.object({
|
.object({
|
||||||
idprezziario: z.custom<PrezziarioIdprezziario>(),
|
idprezziario: z.custom<PrezziarioIdprezziario>(),
|
||||||
prezzo_cent: z.coerce.number().positive(),
|
prezzo_cent: z.number().positive(),
|
||||||
testo_condizioni: z.string().nullable(),
|
testo_condizioni: z.string().nullable(),
|
||||||
isAcconto: z.boolean(),
|
isAcconto: z.boolean(),
|
||||||
isSaldo: z.boolean(),
|
isSaldo: z.boolean(),
|
||||||
|
|
@ -62,7 +61,7 @@ export const FormPrezzo = ({
|
||||||
isTransitorio: z.boolean(),
|
isTransitorio: z.boolean(),
|
||||||
isStabile: z.boolean(),
|
isStabile: z.boolean(),
|
||||||
})
|
})
|
||||||
.superRefine(({ testo_condizioni }, refinementContext) => {
|
.superRefine(({ testo_condizioni }, ctx) => {
|
||||||
if (testo_condizioni) {
|
if (testo_condizioni) {
|
||||||
if (
|
if (
|
||||||
stringhe_condizioni_options.length > 0 &&
|
stringhe_condizioni_options.length > 0 &&
|
||||||
|
|
@ -73,9 +72,11 @@ export const FormPrezzo = ({
|
||||||
"stringhe_condizioni_options",
|
"stringhe_condizioni_options",
|
||||||
stringhe_condizioni_options,
|
stringhe_condizioni_options,
|
||||||
);
|
);
|
||||||
return refinementContext.addIssue({
|
|
||||||
code: z.ZodIssueCode.custom,
|
ctx.addIssue({
|
||||||
|
code: "custom",
|
||||||
message: "Testo condizioni non valido",
|
message: "Testo condizioni non valido",
|
||||||
|
input: testo_condizioni,
|
||||||
path: ["testo_condizioni"],
|
path: ["testo_condizioni"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -102,10 +103,9 @@ export const FormPrezzo = ({
|
||||||
isStabile: false,
|
isStabile: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(PrezzoSchema, {
|
||||||
schema: PrezzoSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -238,7 +238,7 @@ export const FormPrezzo = ({
|
||||||
{...field}
|
{...field}
|
||||||
type="number"
|
type="number"
|
||||||
id="prezzo"
|
id="prezzo"
|
||||||
value={field.value / 100}
|
value={Number(field.value) / 100}
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
field.onChange(() => parseInt(v.target.value) * 100);
|
field.onChange(() => parseInt(v.target.value) * 100);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { Users, UsersId } from "~/schemas/public/Users";
|
import type { Users, UsersId } from "~/schemas/public/Users";
|
||||||
|
|
@ -36,7 +35,7 @@ export const ProfileFormAccount = ({
|
||||||
const profileFormSchema = z.object({
|
const profileFormSchema = z.object({
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
telefono: z.string().nonempty("Inserisci un numero di telefono"),
|
telefono: z.string().nonempty("Inserisci un numero di telefono"),
|
||||||
isAdmin: z.boolean().optional(),
|
isAdmin: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
@ -51,10 +50,9 @@ export const ProfileFormAccount = ({
|
||||||
isAdmin: isAdmin,
|
isAdmin: isAdmin,
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(profileFormSchema, {
|
||||||
schema: profileFormSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -11,7 +11,6 @@ import {
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { differenceInYears, format } from "date-fns";
|
import { differenceInYears, format } from "date-fns";
|
||||||
|
|
@ -44,7 +43,7 @@ export const ProfileFormAnagrafica = ({
|
||||||
}) => {
|
}) => {
|
||||||
const profileFormSchema = z
|
const profileFormSchema = z
|
||||||
.object({
|
.object({
|
||||||
data_nascita: z.coerce.date().optional(),
|
data_nascita: z.date().optional(),
|
||||||
luogo_nascita: z.string().optional(),
|
luogo_nascita: z.string().optional(),
|
||||||
sesso: z.string().optional(),
|
sesso: z.string().optional(),
|
||||||
nazione_nascita: z.string().optional(),
|
nazione_nascita: z.string().optional(),
|
||||||
|
|
@ -84,49 +83,55 @@ export const ProfileFormAnagrafica = ({
|
||||||
) => {
|
) => {
|
||||||
if (azienda) {
|
if (azienda) {
|
||||||
if (!ragione_sociale || ragione_sociale.length < 1) {
|
if (!ragione_sociale || ragione_sociale.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la ragione sociale",
|
message: "Inserisci la ragione sociale",
|
||||||
path: ["ragione_sociale"],
|
path: ["ragione_sociale"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!sede_legale || sede_legale.length < 1) {
|
if (!sede_legale || sede_legale.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la sede legale",
|
message: "Inserisci la sede legale",
|
||||||
path: ["sede_legale"],
|
path: ["sede_legale"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!p_iva || p_iva.length < 1) {
|
if (!p_iva || p_iva.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci la partita iva",
|
message: "Inserisci la partita iva",
|
||||||
path: ["p_iva"],
|
path: ["p_iva"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il legale rappresentante",
|
message: "Inserisci il legale rappresentante",
|
||||||
path: ["legale_rappresentante"],
|
path: ["legale_rappresentante"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fatturazione_aziendale) {
|
if (fatturazione_aziendale) {
|
||||||
if (!codice_destinatario || codice_destinatario.length != 7) {
|
if (!codice_destinatario || codice_destinatario.length != 7) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci il codice destinatario",
|
message: "Inserisci il codice destinatario",
|
||||||
path: ["codice_destinatario"],
|
path: ["codice_destinatario"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cap_residenza) {
|
if (cap_residenza) {
|
||||||
if (cap_residenza.length !== 5) {
|
if (cap_residenza.length !== 5) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci un CAP valido",
|
message: "Inserisci un CAP valido",
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,10 +139,11 @@ export const ProfileFormAnagrafica = ({
|
||||||
if (data_nascita) {
|
if (data_nascita) {
|
||||||
const diff = differenceInYears(data_nascita, new Date());
|
const diff = differenceInYears(data_nascita, new Date());
|
||||||
if (diff === 0) {
|
if (diff === 0) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci una data valida",
|
message: "Inserisci una data valida",
|
||||||
path: ["data_nascita"],
|
path: ["data_nascita"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -188,10 +194,9 @@ export const ProfileFormAnagrafica = ({
|
||||||
codice_destinatario: userData.codice_destinatario || null,
|
codice_destinatario: userData.codice_destinatario || null,
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(profileFormSchema, {
|
||||||
schema: profileFormSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
import { z } from "zod/v4";
|
||||||
import { z } from "zod";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
|
|
@ -40,7 +39,7 @@ export const FormPwSetup = ({ user, servizioId }: FormPwSetupProps) => {
|
||||||
toggleVisibility,
|
toggleVisibility,
|
||||||
} = useStrongPassword();
|
} = useStrongPassword();
|
||||||
|
|
||||||
const shema = z
|
const Schema = z
|
||||||
.object({
|
.object({
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
||||||
|
|
@ -53,17 +52,16 @@ export const FormPwSetup = ({ user, servizioId }: FormPwSetupProps) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
type LoginFormValues = z.infer<typeof shema>;
|
type LoginFormValues = z.infer<typeof Schema>;
|
||||||
|
|
||||||
const defaultValues: LoginFormValues = {
|
const defaultValues: LoginFormValues = {
|
||||||
password: "",
|
password: "",
|
||||||
checkbox: false, // Honeypot field
|
checkbox: false, // Honeypot field
|
||||||
};
|
};
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: shema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
@ -63,22 +62,24 @@ export const FormRstPwFromToken = (props: { token: string }) => {
|
||||||
const complexity = checkStrength(password);
|
const complexity = checkStrength(password);
|
||||||
|
|
||||||
if (complexity.filter((req) => req.met).length !== complexity.length) {
|
if (complexity.filter((req) => req.met).length !== complexity.length) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: complexity
|
message: complexity
|
||||||
.filter((req) => !req.met)
|
.filter((req) => !req.met)
|
||||||
.map((req) => req.text)
|
.map((req) => req.text)
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
path: ["password"],
|
path: ["password"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setStrengthScore(complexity.filter((req) => req.met).length);
|
setStrengthScore(complexity.filter((req) => req.met).length);
|
||||||
|
|
||||||
if (password !== repeat_password) {
|
if (password !== repeat_password) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
message: t.pwReset.pwDiverse,
|
message: t.pwReset.pwDiverse,
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
path: ["repeat_password"],
|
path: ["repeat_password"],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -93,8 +94,7 @@ export const FormRstPwFromToken = (props: { token: string }) => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(ResetFormSchema, {
|
||||||
schema: ResetFormSchema,
|
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
password: "",
|
password: "",
|
||||||
repeat_password: "",
|
repeat_password: "",
|
||||||
|
|
@ -106,7 +106,7 @@ export const FormRstPwFromToken = (props: { token: string }) => {
|
||||||
resetToken: props.token,
|
resetToken: props.token,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -7,7 +7,6 @@ import {
|
||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -48,10 +47,9 @@ export const FormStringhe = ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper("it"));
|
z.config(z.locales.it());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(Schema, {
|
||||||
schema: Schema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,18 @@ import type { ChatMessage } from "~/server/services/messages.service";
|
||||||
import { type OnlineStatus, type WhoIsTyping } from "~/server/sse";
|
import { type OnlineStatus, type WhoIsTyping } from "~/server/sse";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
|
type EditEvent = {
|
||||||
|
eventType: "edit";
|
||||||
|
data: { messageId: MessagesMessageid; message: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
type DeleteEvent = {
|
||||||
|
eventType: "delete";
|
||||||
|
data: MessagesMessageid;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MessageUpdate = EditEvent | DeleteEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set isTyping with a throttle of 1s
|
* Set isTyping with a throttle of 1s
|
||||||
* Triggers immediately if state changes
|
* Triggers immediately if state changes
|
||||||
|
|
@ -167,7 +179,7 @@ export const useLiveChat = (chatId: ChatsChatid, userData: Session) => {
|
||||||
api.messagesSSE.onMessageEvent.useSubscription(
|
api.messagesSSE.onMessageEvent.useSubscription(
|
||||||
{ chatId },
|
{ chatId },
|
||||||
{
|
{
|
||||||
onData(data) {
|
onData(data: { data: MessageUpdate }) {
|
||||||
switch (data.data.eventType) {
|
switch (data.data.eventType) {
|
||||||
case "edit":
|
case "edit":
|
||||||
handleEdit(data.data.data);
|
handleEdit(data.data.data);
|
||||||
|
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
import { eng, ita } from "~/i18n/FormErrorsTranslation";
|
|
||||||
|
|
||||||
import * as z from "zod";
|
|
||||||
|
|
||||||
const Capitalize = (s: string) => {
|
|
||||||
if (typeof s !== "string") return "";
|
|
||||||
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
type ErrorType = Record<string, any>;
|
|
||||||
function FormErrorTranslation(template: string, obj: ErrorType): string {
|
|
||||||
return template.replace(/{{[^}]*}}/g, (match) =>
|
|
||||||
typeof obj[match.replace(/{|}/g, "")] === "string"
|
|
||||||
? Capitalize(String(obj[match.replace(/{|}/g, "")]))
|
|
||||||
: String(obj[match.replace(/{|}/g, "")]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const customErrorMapWrapper = (locale: string) => {
|
|
||||||
const data = locale === "it" ? ita : eng;
|
|
||||||
|
|
||||||
const customErrorMap: z.ZodErrorMap = (issue, ctx) => {
|
|
||||||
let message = "";
|
|
||||||
|
|
||||||
switch (issue.code) {
|
|
||||||
case z.ZodIssueCode.invalid_type:
|
|
||||||
if (issue.received === z.ZodParsedType.undefined) {
|
|
||||||
message = data.errors.invalid_type_received_undefined;
|
|
||||||
} else {
|
|
||||||
message = FormErrorTranslation(data.errors.invalid_type, {
|
|
||||||
expected: data.local_types[issue.expected],
|
|
||||||
received: data.local_types[issue.received],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_literal:
|
|
||||||
message = FormErrorTranslation(data.errors.invalid_literal, {
|
|
||||||
expected: JSON.stringify(issue.expected, jsonStringifyReplacer),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.unrecognized_keys:
|
|
||||||
message = FormErrorTranslation(data.errors.unrecognized_keys, {
|
|
||||||
keys: joinValues(issue.keys, ", "),
|
|
||||||
count: issue.keys.length,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_union:
|
|
||||||
message = data.errors.invalid_union;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_union_discriminator:
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.invalid_union_discriminator,
|
|
||||||
{
|
|
||||||
options: joinValues(issue.options),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_enum_value:
|
|
||||||
message = FormErrorTranslation(data.errors.invalid_enum_value, {
|
|
||||||
options: joinValues(issue.options),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_arguments:
|
|
||||||
message = data.errors.invalid_arguments;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_return_type:
|
|
||||||
message = data.errors.invalid_return_type;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_date:
|
|
||||||
message = data.errors.invalid_date;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.invalid_string:
|
|
||||||
if (typeof issue.validation === "object") {
|
|
||||||
if ("startsWith" in issue.validation) {
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.invalid_string.startsWith,
|
|
||||||
{
|
|
||||||
startsWith: issue.validation.startsWith,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else if ("endsWith" in issue.validation) {
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.invalid_string.endsWith,
|
|
||||||
{
|
|
||||||
endsWith: issue.validation.endsWith,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.invalid_string[
|
|
||||||
issue.validation as keyof typeof data.errors.invalid_string
|
|
||||||
],
|
|
||||||
{
|
|
||||||
validation: FormErrorTranslation(
|
|
||||||
data.validations[
|
|
||||||
issue.validation as keyof typeof data.validations
|
|
||||||
],
|
|
||||||
{
|
|
||||||
defaultValue: issue.validation,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.too_small: {
|
|
||||||
const minimum =
|
|
||||||
issue.type === "date"
|
|
||||||
? new Date(issue.minimum as number)
|
|
||||||
: issue.minimum;
|
|
||||||
|
|
||||||
const incl_excl = issue.exact
|
|
||||||
? "exact"
|
|
||||||
: issue.inclusive
|
|
||||||
? "inclusive"
|
|
||||||
: "not_inclusive";
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.too_small[
|
|
||||||
issue.type as keyof typeof data.errors.too_small
|
|
||||||
][incl_excl],
|
|
||||||
{
|
|
||||||
minimum: minimum,
|
|
||||||
|
|
||||||
//count: typeof minimum === "number" ? minimum : undefined,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case z.ZodIssueCode.too_big: {
|
|
||||||
const maximum =
|
|
||||||
issue.type === "date"
|
|
||||||
? new Date(issue.maximum as number)
|
|
||||||
: issue.maximum;
|
|
||||||
message = FormErrorTranslation(
|
|
||||||
data.errors.too_big[issue.type as keyof typeof data.errors.too_big][
|
|
||||||
issue.exact
|
|
||||||
? "exact"
|
|
||||||
: issue.inclusive
|
|
||||||
? "inclusive"
|
|
||||||
: "not_inclusive"
|
|
||||||
],
|
|
||||||
{
|
|
||||||
maximum: maximum,
|
|
||||||
//count: typeof maximum === "number" ? maximum : undefined,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case z.ZodIssueCode.invalid_intersection_types:
|
|
||||||
message = data.errors.invalid_intersection_types;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.not_multiple_of:
|
|
||||||
message = FormErrorTranslation(data.errors.not_multiple_of, {
|
|
||||||
multipleOf: issue.multipleOf,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.not_finite:
|
|
||||||
message = data.errors.not_finite;
|
|
||||||
break;
|
|
||||||
case z.ZodIssueCode.custom:
|
|
||||||
message =
|
|
||||||
data.customErrors[
|
|
||||||
issue.params?.type as keyof typeof data.customErrors
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
message = ctx.defaultError;
|
|
||||||
}
|
|
||||||
return { message: message };
|
|
||||||
};
|
|
||||||
|
|
||||||
return customErrorMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const jsonStringifyReplacer = (_: string, value: any): any => {
|
|
||||||
if (typeof value === "bigint") {
|
|
||||||
return value.toString();
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
function joinValues<T extends any[]>(array: T, separator = " | "): string {
|
|
||||||
return (
|
|
||||||
array
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
||||||
.map((val) => (typeof val === "string" ? `'${val}'` : val))
|
|
||||||
.join(separator)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { z, type RefinementCtx } from "zod";
|
import { z, type RefinementCtx } from "zod/v4";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
||||||
export const zStrongPassword = z.string().superRefine((password) => {
|
export const zStrongPassword = z.string().superRefine((password, ctx) => {
|
||||||
return [/.{8,}/, /[0-9]/, /[a-z]/, /[A-Z]/].every((regex) =>
|
const test = [/.{8,}/, /[0-9]/, /[a-z]/, /[A-Z]/].every((regex) =>
|
||||||
regex.test(password),
|
regex.test(password),
|
||||||
);
|
);
|
||||||
|
if (!test) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: "custom",
|
||||||
|
message:
|
||||||
|
"La password deve contenere almeno 8 caratteri, un numero, una lettera minuscola e una maiuscola.",
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useStrongPassword = () => {
|
export const useStrongPassword = () => {
|
||||||
|
|
@ -57,13 +64,14 @@ export const useStrongPassword = () => {
|
||||||
const complexity = checkStrength(password);
|
const complexity = checkStrength(password);
|
||||||
|
|
||||||
if (complexity.filter((req) => req.met).length !== complexity.length) {
|
if (complexity.filter((req) => req.met).length !== complexity.length) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: complexity
|
message: complexity
|
||||||
.filter((req) => !req.met)
|
.filter((req) => !req.met)
|
||||||
.map((req) => req.text)
|
.map((req) => req.text)
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setStrengthScore(complexity.filter((req) => req.met).length);
|
setStrengthScore(complexity.filter((req) => req.met).length);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import type { z } from "zod/v4";
|
||||||
import { getComuneFromIndex } from "~/i18n/comuni";
|
import { getComuneFromIndex } from "~/i18n/comuni";
|
||||||
import { searchNazioneByIndex } from "~/i18n/nazioni";
|
import { searchNazioneByIndex } from "~/i18n/nazioni";
|
||||||
import type { ListOption } from "~/components/custom_ui/multiselect";
|
import type { ListOption } from "~/components/custom_ui/multiselect";
|
||||||
|
|
@ -185,26 +185,29 @@ export const checkFiscalCodeValidity = ({
|
||||||
console.log("gen", gen);
|
console.log("gen", gen);
|
||||||
console.log("codiceFiscale", codiceFiscale);
|
console.log("codiceFiscale", codiceFiscale);
|
||||||
console.log("alternative", getAlternativeCF(gen));
|
console.log("alternative", getAlternativeCF(gen));
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale non valido",
|
message: "Codice fiscale non valido",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control !== codiceFiscale.slice(-1)) {
|
if (control !== codiceFiscale.slice(-1)) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice di controllo non valido",
|
message: "Codice di controllo non valido",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codiceFiscale.length !== 16) {
|
if (codiceFiscale.length !== 16) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci un codice fiscale valido",
|
message: "Inserisci un codice fiscale valido",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|
@ -212,60 +215,67 @@ export const checkFiscalCodeValidity = ({
|
||||||
codiceFiscale,
|
codiceFiscale,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Inserisci un codice fiscale valido",
|
message: "Inserisci un codice fiscale valido",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codiceFiscale.slice(0, 3) !== getInizialiCF(cognomeUpper)) {
|
if (codiceFiscale.slice(0, 3) !== getInizialiCF(cognomeUpper)) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con cognome inserito",
|
message: "Codice fiscale incompatibile con cognome inserito",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (codiceFiscale.slice(3, 6) !== getInizialiCF(nomeUpper)) {
|
if (codiceFiscale.slice(3, 6) !== getInizialiCF(nomeUpper)) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con nome inserito",
|
message: "Codice fiscale incompatibile con nome inserito",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
codiceFiscale.slice(6, 8) !== dataNascita.getFullYear().toString().slice(-2)
|
codiceFiscale.slice(6, 8) !== dataNascita.getFullYear().toString().slice(-2)
|
||||||
) {
|
) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con anno di nascita",
|
message: "Codice fiscale incompatibile con anno di nascita",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (codiceFiscale.slice(8, 9) !== getMonthLetterCF(dataNascita.getMonth())) {
|
if (codiceFiscale.slice(8, 9) !== getMonthLetterCF(dataNascita.getMonth())) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con mese di nascita",
|
message: "Codice fiscale incompatibile con mese di nascita",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (codiceFiscale.slice(9, 11) !== getDayCF(dataNascita.getDate(), sesso)) {
|
if (codiceFiscale.slice(9, 11) !== getDayCF(dataNascita.getDate(), sesso)) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con giorno di nascita",
|
message: "Codice fiscale incompatibile con giorno di nascita",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (nazioneNascita === "0") {
|
if (nazioneNascita === "0") {
|
||||||
if (luogoNascita !== "") {
|
if (luogoNascita !== "") {
|
||||||
const comune = getComuneFromIndex(parseInt(luogoNascita));
|
const comune = getComuneFromIndex(parseInt(luogoNascita));
|
||||||
if (comune && codiceFiscale.slice(11, 15) !== comune.CATASTO) {
|
if (comune && codiceFiscale.slice(11, 15) !== comune.CATASTO) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con luogo di nascita",
|
message: "Codice fiscale incompatibile con luogo di nascita",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,10 +283,11 @@ export const checkFiscalCodeValidity = ({
|
||||||
if (nazioneNascita !== "") {
|
if (nazioneNascita !== "") {
|
||||||
const nazione = searchNazioneByIndex(parseInt(nazioneNascita));
|
const nazione = searchNazioneByIndex(parseInt(nazioneNascita));
|
||||||
if (nazione && codiceFiscale.slice(11, 15) !== nazione.CATASTO) {
|
if (nazione && codiceFiscale.slice(11, 15) !== nazione.CATASTO) {
|
||||||
refinementContext.addIssue({
|
refinementContext.issues.push({
|
||||||
code: z.ZodIssueCode.custom,
|
code: "custom",
|
||||||
message: "Codice fiscale incompatibile con luogo di nascita",
|
message: "Codice fiscale incompatibile con luogo di nascita",
|
||||||
path: [path],
|
path: [path],
|
||||||
|
input: "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { type UseFormProps, useForm } from "react-hook-form";
|
import { type FieldValues, type UseFormProps, useForm } from "react-hook-form";
|
||||||
import type { z, ZodTypeAny } from "zod";
|
|
||||||
|
|
||||||
export function useZodForm<TSchema extends ZodTypeAny>(
|
import type { z } from "zod";
|
||||||
props: Omit<UseFormProps<z.infer<TSchema>>, "resolver"> & {
|
|
||||||
schema: TSchema;
|
export function useZodForm<
|
||||||
},
|
T extends z.ZodType<FieldValues, FieldValues>,
|
||||||
|
TContext,
|
||||||
|
>(
|
||||||
|
schema: T,
|
||||||
|
props?: Omit<UseFormProps<z.input<T>, TContext, z.output<T>>, "resolver">,
|
||||||
) {
|
) {
|
||||||
const form = useForm<z.infer<TSchema>>({
|
return useForm({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
...props,
|
...props,
|
||||||
resolver: zodResolver(props.schema),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return form;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import { cn } from "~/lib/utils";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
import { generateSSGHelper } from "~/server/utils/ssgHelper";
|
import { generateSSGHelper } from "~/server/utils/ssgHelper";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -32,7 +32,6 @@ import {
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { CarouselAnnuncio } from "~/components/annuncio_card";
|
import { CarouselAnnuncio } from "~/components/annuncio_card";
|
||||||
import { zAnnuncioId } from "~/server/utils/zod_types";
|
import { zAnnuncioId } from "~/server/utils/zod_types";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
|
@ -76,7 +75,7 @@ const AnnuncioEditForm = ({ data }: { data: AnnunciWithCoverImage }) => {
|
||||||
desc_en: z.string().nonempty("Inserisci una descrizione valida"),
|
desc_en: z.string().nonempty("Inserisci una descrizione valida"),
|
||||||
status: z.string().nonempty("Seleziona uno stato"),
|
status: z.string().nonempty("Seleziona uno stato"),
|
||||||
locatore: z.string().nonempty("Inserisci il locatore"),
|
locatore: z.string().nonempty("Inserisci il locatore"),
|
||||||
email: z.string().email("Inserisci un'email valida"),
|
email: z.email(),
|
||||||
numero: z.string().nonempty("Inserisci un numero di telefono"),
|
numero: z.string().nonempty("Inserisci un numero di telefono"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -103,10 +102,9 @@ const AnnuncioEditForm = ({ data }: { data: AnnunciWithCoverImage }) => {
|
||||||
numero: data.numero || "",
|
numero: data.numero || "",
|
||||||
};
|
};
|
||||||
|
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(EdiAnnuncioSchema, {
|
||||||
schema: EdiAnnuncioSchema,
|
|
||||||
defaultValues: defaultValues,
|
defaultValues: defaultValues,
|
||||||
});
|
});
|
||||||
function onSubmit(fields: EditAnnuncioFormValues) {
|
function onSubmit(fields: EditAnnuncioFormValues) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { NextPage } from "next";
|
import type { NextPage } from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
|
|
@ -12,7 +12,6 @@ import {
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import { Textarea } from "~/components/custom_ui/textarea";
|
import { Textarea } from "~/components/custom_ui/textarea";
|
||||||
import { customErrorMapWrapper } from "~/hooks/locale";
|
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { DualInputLayout } from "~/components/custom_ui/inputLayouts";
|
import { DualInputLayout } from "~/components/custom_ui/inputLayouts";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
@ -27,14 +26,13 @@ const Contatto: NextPage = () => {
|
||||||
const ContactFormSchema = z.object({
|
const ContactFormSchema = z.object({
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
messaggio: z.string().nonempty("Inserisci un messaggio"),
|
messaggio: z.string().nonempty("Inserisci un messaggio"),
|
||||||
numero: z.string().nonempty("Inserisci un numero di telefono"),
|
numero: z.string().nonempty("Inserisci un numero di telefono"),
|
||||||
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
checkbox: z.boolean().refine((val) => val === false), // Honeypot field
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useZodForm({
|
const form = useZodForm(ContactFormSchema, {
|
||||||
schema: ContactFormSchema,
|
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
nome: "",
|
nome: "",
|
||||||
cognome: "",
|
cognome: "",
|
||||||
|
|
@ -60,7 +58,7 @@ const Contatto: NextPage = () => {
|
||||||
telefono: data.numero,
|
telefono: data.numero,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
z.setErrorMap(customErrorMapWrapper(locale));
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
@ -36,7 +36,7 @@ export const authRouter = createTRPCRouter({
|
||||||
loginUser: publicProcedure
|
loginUser: publicProcedure
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
email: z.string().email("Inserisci una email valida"),
|
email: z.email(),
|
||||||
password: z.string(),
|
password: z.string(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
@ -68,7 +68,7 @@ export const authRouter = createTRPCRouter({
|
||||||
addUserAdmin: adminProcedure
|
addUserAdmin: adminProcedure
|
||||||
.input(
|
.input(
|
||||||
z.object({
|
z.object({
|
||||||
email: z.string().email("Inserisci una email valida"),
|
email: z.email(),
|
||||||
password: zStrongPassword,
|
password: zStrongPassword,
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
updateBan,
|
updateBan,
|
||||||
} from "~/server/services/banlist.service";
|
} from "~/server/services/banlist.service";
|
||||||
import { adminProcedure, createTRPCRouter } from "~/server/api/trpc";
|
import { adminProcedure, createTRPCRouter } from "~/server/api/trpc";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { zBanlistId, zBanType } from "~/server/utils/zod_types";
|
import { zBanlistId, zBanType } from "~/server/utils/zod_types";
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||||
import { zUserId } from "~/server/utils/zod_types";
|
import { zUserId } from "~/server/utils/zod_types";
|
||||||
import { genMail, type MailsTemplates } from "~/server/services/mailer";
|
import { genMail, type MailsTemplates } from "~/server/services/mailer";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||||
import { NewMail } from "~/server/services/mailer";
|
import { NewMail } from "~/server/services/mailer";
|
||||||
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
||||||
|
|
@ -15,7 +15,7 @@ export const contactRouter = createTRPCRouter({
|
||||||
z.object({
|
z.object({
|
||||||
nome: z.string(),
|
nome: z.string(),
|
||||||
cognome: z.string(),
|
cognome: z.string(),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
telefono: z.string(),
|
telefono: z.string(),
|
||||||
messaggio: z.string(),
|
messaggio: z.string(),
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedApiProcedure,
|
protectedApiProcedure,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import {
|
||||||
RemoveInterest,
|
RemoveInterest,
|
||||||
} from "~/server/services/interests.service";
|
} from "~/server/services/interests.service";
|
||||||
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
||||||
import z from "zod";
|
import z from "zod/v4";
|
||||||
import { zAnnuncioId, zUserId } from "~/server/utils/zod_types";
|
import { zAnnuncioId, zUserId } from "~/server/utils/zod_types";
|
||||||
import { NewMail } from "~/server/services/mailer";
|
import { NewMail } from "~/server/services/mailer";
|
||||||
import { findUser_byId_MINI } from "~/server/services/user.service";
|
import { findUser_byId_MINI } from "~/server/services/user.service";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { tracked, TRPCError } from "@trpc/server";
|
import { tracked, TRPCError } from "@trpc/server";
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
// Create a new ratelimiter, that allows 10 requests per 10 seconds
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import type {
|
import type {
|
||||||
NewPrezziario,
|
NewPrezziario,
|
||||||
PrezziarioUpdate,
|
PrezziarioUpdate,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import type { BannersIdbanner } from "~/schemas/public/Banners";
|
import type { BannersIdbanner } from "~/schemas/public/Banners";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import {
|
import {
|
||||||
adminProcedure,
|
adminProcedure,
|
||||||
createTRPCRouter,
|
createTRPCRouter,
|
||||||
|
|
@ -78,7 +78,7 @@ export const usersRouter = createTRPCRouter({
|
||||||
nome: z.string(),
|
nome: z.string(),
|
||||||
cognome: z.string(),
|
cognome: z.string(),
|
||||||
telefono: z.string(),
|
telefono: z.string(),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
isAdmin: z.boolean().optional(),
|
isAdmin: z.boolean().optional(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { initTRPC, TRPCError } from "@trpc/server";
|
||||||
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
|
import type { CreateNextContextOptions } from "@trpc/server/adapters/next";
|
||||||
|
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import z, { ZodError } from "zod";
|
import z, { ZodError } from "zod/v4";
|
||||||
|
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { env } from "~/env.mjs";
|
import { env } from "~/env.mjs";
|
||||||
|
|
@ -28,7 +28,7 @@ import { ACCESS_TOKEN_COOKIE_NAME, verifyToken } from "~/server/auth/jwt";
|
||||||
export const sessionSchema = z.object({
|
export const sessionSchema = z.object({
|
||||||
id: zUserId,
|
id: zUserId,
|
||||||
username: z.string(),
|
username: z.string(),
|
||||||
email: z.string().email(),
|
email: z.email(),
|
||||||
isAdmin: z.boolean(),
|
isAdmin: z.boolean(),
|
||||||
isBlocked: z.boolean(),
|
isBlocked: z.boolean(),
|
||||||
nome: z.string(),
|
nome: z.string(),
|
||||||
|
|
@ -89,7 +89,7 @@ export const t = initTRPC.context<Context>().create({
|
||||||
data: {
|
data: {
|
||||||
...shape.data,
|
...shape.data,
|
||||||
zodError:
|
zodError:
|
||||||
error.cause instanceof ZodError ? error.cause.flatten() : null,
|
error.cause instanceof ZodError ? z.treeifyError(error.cause) : null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { TRPCError } from "@trpc/server";
|
||||||
import { createSrc, createSrcset } from "~/server/services/imageServer";
|
import { createSrc, createSrcset } from "~/server/services/imageServer";
|
||||||
import { AnnuncioObjectWithImages } from "~/server/services/annunci.service";
|
import { AnnuncioObjectWithImages } from "~/server/services/annunci.service";
|
||||||
import { zAnnuncioId } from "~/server/utils/zod_types";
|
import { zAnnuncioId } from "~/server/utils/zod_types";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import type { UsersAnagraficaUpdate } from "~/schemas/public/UsersAnagrafica";
|
||||||
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres";
|
import { jsonArrayFrom, jsonObjectFrom } from "kysely/helpers/postgres";
|
||||||
import type { AnnunciId } from "~/schemas/public/Annunci";
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import { add } from "date-fns";
|
import { add } from "date-fns";
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
||||||
import { NewMail, type NewMailProps } from "~/server/services/mailer";
|
import { NewMail, type NewMailProps } from "~/server/services/mailer";
|
||||||
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
|
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
const ClientTypeSchema = z.enum(["company", "person", "pa", "condo"]);
|
const ClientTypeSchema = z.enum(["company", "person", "pa", "condo"]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,64 +16,43 @@ const trackedEnvelopeSchema =
|
||||||
* 3. The return value of the async iterable, if any, also conforms to a specified type.
|
* 3. The return value of the async iterable, if any, also conforms to a specified type.
|
||||||
*/
|
*/
|
||||||
export function zAsyncIterable<
|
export function zAsyncIterable<
|
||||||
TYieldIn,
|
TYield,
|
||||||
TYieldOut,
|
TReturn = void,
|
||||||
TReturnIn = void,
|
|
||||||
TReturnOut = void,
|
|
||||||
Tracked extends boolean = false,
|
Tracked extends boolean = false,
|
||||||
>(opts: {
|
>(opts: {
|
||||||
/**
|
yield: z.ZodType<TYield, any, any>;
|
||||||
* Validate the value yielded by the async generator
|
return?: z.ZodType<TReturn, any, any>;
|
||||||
*/
|
|
||||||
yield: z.ZodType<TYieldIn, any, TYieldOut>;
|
|
||||||
/**
|
|
||||||
* Validate the return value of the async generator
|
|
||||||
* @remark not applicable for subscriptions
|
|
||||||
*/
|
|
||||||
return?: z.ZodType<TReturnIn, any, TReturnOut>;
|
|
||||||
/**
|
|
||||||
* Whether if the yielded values are tracked
|
|
||||||
* @remark only applicable for subscriptions
|
|
||||||
*/
|
|
||||||
tracked?: Tracked;
|
tracked?: Tracked;
|
||||||
}) {
|
}) {
|
||||||
return z
|
const baseSchema = z.custom<
|
||||||
.custom<
|
|
||||||
AsyncIterable<
|
|
||||||
Tracked extends true ? TrackedEnvelope<TYieldIn> : TYieldIn,
|
|
||||||
TReturnIn
|
|
||||||
>
|
|
||||||
>((val) => isAsyncIterable(val))
|
|
||||||
.transform(async function* (iter) {
|
|
||||||
const iterator = iter[Symbol.asyncIterator]();
|
|
||||||
try {
|
|
||||||
let next;
|
|
||||||
while ((next = await iterator.next()) && !next.done) {
|
|
||||||
if (opts.tracked) {
|
|
||||||
const [id, data] = trackedEnvelopeSchema.parse(next.value);
|
|
||||||
yield tracked(id, await opts.yield.parseAsync(data));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
yield opts.yield.parseAsync(next.value);
|
|
||||||
}
|
|
||||||
if (opts.return) {
|
|
||||||
return await opts.return.parseAsync(next.value);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} finally {
|
|
||||||
await iterator.return?.();
|
|
||||||
}
|
|
||||||
}) as z.ZodType<
|
|
||||||
AsyncIterable<
|
AsyncIterable<
|
||||||
Tracked extends true ? TrackedEnvelope<TYieldIn> : TYieldIn,
|
Tracked extends true
|
||||||
TReturnIn,
|
? TrackedEnvelope<z.input<typeof opts.yield>>
|
||||||
unknown
|
: z.input<typeof opts.yield>,
|
||||||
>,
|
z.input<typeof opts.return>
|
||||||
any,
|
|
||||||
AsyncIterable<
|
|
||||||
Tracked extends true ? TrackedEnvelope<TYieldOut> : TYieldOut,
|
|
||||||
TReturnOut,
|
|
||||||
unknown
|
|
||||||
>
|
>
|
||||||
>;
|
>((val: unknown): val is AsyncIterable<any, any> => isAsyncIterable(val), {
|
||||||
|
message: "Expected AsyncIterable",
|
||||||
|
});
|
||||||
|
|
||||||
|
return baseSchema.transform(async function* (iter) {
|
||||||
|
const iterator = iter[Symbol.asyncIterator]();
|
||||||
|
try {
|
||||||
|
let next;
|
||||||
|
while ((next = await iterator.next()) && !next.done) {
|
||||||
|
if (opts.tracked) {
|
||||||
|
const [id, data] = await trackedEnvelopeSchema.parseAsync(next.value);
|
||||||
|
yield tracked(id, await opts.yield.parseAsync(data));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield await opts.yield.parseAsync(next.value);
|
||||||
|
}
|
||||||
|
if (opts.return) {
|
||||||
|
return (await opts.return.parseAsync(next.value)) as TReturn;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
await iterator.return?.();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { z } from "zod";
|
import { z } from "zod/v4";
|
||||||
import type { AnnunciId } from "~/schemas/public/Annunci";
|
import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import type { ChatsChatid } from "~/schemas/public/Chats";
|
import type { ChatsChatid } from "~/schemas/public/Chats";
|
||||||
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
|
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
|
||||||
|
|
@ -75,10 +75,9 @@ export const zBanlistId = z.custom<BanlistId>(
|
||||||
"falied to validate BanlistId",
|
"falied to validate BanlistId",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const zBanType = z.custom<BanType>(
|
export const zBanType = z.enum(BanType, {
|
||||||
(val) => val in BanType,
|
error: "failed to validate BanType",
|
||||||
"falied to validate BanType",
|
});
|
||||||
);
|
|
||||||
|
|
||||||
export const zServizioId = z.custom<ServizioServizioId>(
|
export const zServizioId = z.custom<ServizioServizioId>(
|
||||||
(val) => typeof val === "string",
|
(val) => typeof val === "string",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue