From 30b3da9c318f54e14e59555f672ba9ccc34eedda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Dere=C5=BEi=C4=87?= Date: Sat, 17 Feb 2024 07:28:47 +0100 Subject: [PATCH] i18n support added to all form validations --- app/i18n.ts | 11 ++++++++++- app/lib/actions/billActions.ts | 20 +++++++++----------- app/lib/actions/locationActions.ts | 29 ++++++++++++++--------------- messages/en.json | 8 +++++--- 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/app/i18n.ts b/app/i18n.ts index d93ff27..a539866 100644 --- a/app/i18n.ts +++ b/app/i18n.ts @@ -1,11 +1,20 @@ import {notFound} from 'next/navigation'; import {getRequestConfig} from 'next-intl/server'; +import { Formats, TranslationValues } from 'next-intl'; // Can be imported from a shared config export const locales = ['en', 'hr']; export const defaultLocale = 'en'; - + +/** Templating function type as returned by `useTemplate` and `getTranslations` */ +export type IntlTemplateFn = + // this function type if returned by `useTransations` + ((key: TargetKey, values?: TranslationValues | undefined, formats?: Partial | undefined) => string) | + // this functon type if returned by `getTranslations` + ((key: [TargetKey] extends [never] ? string : TargetKey, values?: TranslationValues | undefined, formats?: Partial | undefined) => string); + + export default getRequestConfig(async ({locale}) => { // Validate that the incoming `locale` parameter is valid if (!locales.includes(locale as any)) notFound(); diff --git a/app/lib/actions/billActions.ts b/app/lib/actions/billActions.ts index 257cf07..0db48ab 100644 --- a/app/lib/actions/billActions.ts +++ b/app/lib/actions/billActions.ts @@ -7,7 +7,8 @@ import { ObjectId } from 'mongodb'; import { withUser } from '@/app/lib/auth'; import { AuthenticatedUser } from '../types/next-auth'; import { gotoHome } from './navigationActions'; -import { Formats, TranslationValues, useTranslations } from "next-intl"; +import { getTranslations } from "next-intl/server"; +import { IntlTemplateFn } from '@/app/i18n'; export type State = { errors?: { @@ -19,10 +20,11 @@ export type State = { message?:string | null; } -type IntlTemplate = (key: TargetKey, values?: TranslationValues | undefined, formats?: Partial | undefined) => string; - - -const FormSchema = (t:IntlTemplate) => z.object({ +/** + * Schema for validating bill form fields + * @description this is defined as factory function so that it can be used with the next-intl library +*/ +const FormSchema = (t:IntlTemplateFn) => z.object({ _id: z.string(), billName: z.coerce.string().min(1, t("bill-name-required")), billNotes: z.string(), @@ -65,10 +67,6 @@ const FormSchema = (t:IntlTemplate) => z.object({ }), }); - parseFloat - -const UpdateBill = ; - /** * converts the file to a format stored in the database * @param billAttachment @@ -117,10 +115,10 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI const { id: userId } = user; - const t = useTranslations("bill-edit-form.validation"); + const t = await getTranslations("bill-edit-form.validation"); // FormSchema - const validatedFields = UpdateBill(t) + const validatedFields = FormSchema(t) .omit({ _id: true }) .safeParse({ billName: formData.get('billName'), diff --git a/app/lib/actions/locationActions.ts b/app/lib/actions/locationActions.ts index d90d792..635acfb 100644 --- a/app/lib/actions/locationActions.ts +++ b/app/lib/actions/locationActions.ts @@ -8,7 +8,8 @@ import { withUser } from '@/app/lib/auth'; import { AuthenticatedUser } from '../types/next-auth'; import { gotoHome } from './navigationActions'; import { unstable_noStore as noStore } from 'next/cache'; -import { asyncTimeout } from '../asyncTimeout'; +import { IntlTemplateFn } from '@/app/i18n'; +import { getTranslations } from "next-intl/server"; export type State = { errors?: { @@ -18,13 +19,17 @@ export type State = { message?:string | null; }; -const FormSchema = z.object({ +/** + * Schema for validating location form fields + * @description this is defined as factory function so that it can be used with the next-intl library +*/ +const FormSchema = (t:IntlTemplateFn) => z.object({ _id: z.string(), - locationName: z.coerce.string().min(1, "Location Name is required."), + locationName: z.coerce.string().min(1, t("location-name-required")), locationNotes: z.string(), - }); - -const UpdateLocation = FormSchema.omit({ _id: true }); + }) + // dont include the _id field in the response + .omit({ _id: true }); /** * Server-side action which adds or updates a bill @@ -37,7 +42,9 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat noStore(); - const validatedFields = UpdateLocation.safeParse({ + const t = await getTranslations("location-edit-form.validation"); + + const validatedFields = FormSchema(t).safeParse({ locationName: formData.get('locationName'), locationNotes: formData.get('locationNotes'), }); @@ -84,8 +91,6 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat }); } - // await asyncTimeout(1000); - if(yearMonth) await gotoHome(yearMonth); return { @@ -124,8 +129,6 @@ export const fetchAllLocations = withUser(async (user:AuthenticatedUser, year:nu }) .toArray(); - // await asyncTimeout(1000); - return(locations) }) @@ -154,8 +157,6 @@ export const fetchLocationById = withUser(async (user:AuthenticatedUser, locatio return(null); } - // await asyncTimeout(1000); - return(billLocation); }) @@ -170,7 +171,5 @@ export const deleteLocationById = withUser(async (user:AuthenticatedUser, locati // find a location with the given locationID const post = await dbClient.collection("lokacije").deleteOne({ _id: locationID, userId }); - // await asyncTimeout(1000); - await gotoHome(yearMonth) }) \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index 0652b45..3384c8a 100644 --- a/messages/en.json +++ b/messages/en.json @@ -95,7 +95,9 @@ "notes-placeholder": "Notes", "save-button": "Save", "cancel-button": "Cancel", - "delete-tooltip": "Delete realestate" - - } + "delete-tooltip": "Delete realestate", + "validation": { + "location-name-required": "Relaestate name is required" + } + } } \ No newline at end of file