i18n support added to all form validations
This commit is contained in:
11
app/i18n.ts
11
app/i18n.ts
@@ -1,11 +1,20 @@
|
|||||||
import {notFound} from 'next/navigation';
|
import {notFound} from 'next/navigation';
|
||||||
import {getRequestConfig} from 'next-intl/server';
|
import {getRequestConfig} from 'next-intl/server';
|
||||||
|
import { Formats, TranslationValues } from 'next-intl';
|
||||||
|
|
||||||
// Can be imported from a shared config
|
// Can be imported from a shared config
|
||||||
export const locales = ['en', 'hr'];
|
export const locales = ['en', 'hr'];
|
||||||
|
|
||||||
export const defaultLocale = 'en';
|
export const defaultLocale = 'en';
|
||||||
|
|
||||||
|
/** Templating function type as returned by `useTemplate` and `getTranslations` */
|
||||||
|
export type IntlTemplateFn =
|
||||||
|
// this function type if returned by `useTransations`
|
||||||
|
(<TargetKey extends any>(key: TargetKey, values?: TranslationValues | undefined, formats?: Partial<Formats> | undefined) => string) |
|
||||||
|
// this functon type if returned by `getTranslations`
|
||||||
|
(<TargetKey extends any>(key: [TargetKey] extends [never] ? string : TargetKey, values?: TranslationValues | undefined, formats?: Partial<Formats> | undefined) => string);
|
||||||
|
|
||||||
|
|
||||||
export default getRequestConfig(async ({locale}) => {
|
export default getRequestConfig(async ({locale}) => {
|
||||||
// Validate that the incoming `locale` parameter is valid
|
// Validate that the incoming `locale` parameter is valid
|
||||||
if (!locales.includes(locale as any)) notFound();
|
if (!locales.includes(locale as any)) notFound();
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { ObjectId } from 'mongodb';
|
|||||||
import { withUser } from '@/app/lib/auth';
|
import { withUser } from '@/app/lib/auth';
|
||||||
import { AuthenticatedUser } from '../types/next-auth';
|
import { AuthenticatedUser } from '../types/next-auth';
|
||||||
import { gotoHome } from './navigationActions';
|
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 = {
|
export type State = {
|
||||||
errors?: {
|
errors?: {
|
||||||
@@ -19,10 +20,11 @@ export type State = {
|
|||||||
message?:string | null;
|
message?:string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type IntlTemplate = <TargetKey extends any>(key: TargetKey, values?: TranslationValues | undefined, formats?: Partial<Formats> | undefined) => string;
|
/**
|
||||||
|
* 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:IntlTemplate) => z.object({
|
*/
|
||||||
|
const FormSchema = (t:IntlTemplateFn) => z.object({
|
||||||
_id: z.string(),
|
_id: z.string(),
|
||||||
billName: z.coerce.string().min(1, t("bill-name-required")),
|
billName: z.coerce.string().min(1, t("bill-name-required")),
|
||||||
billNotes: z.string(),
|
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
|
* converts the file to a format stored in the database
|
||||||
* @param billAttachment
|
* @param billAttachment
|
||||||
@@ -117,10 +115,10 @@ export const updateOrAddBill = withUser(async (user:AuthenticatedUser, locationI
|
|||||||
|
|
||||||
const { id: userId } = user;
|
const { id: userId } = user;
|
||||||
|
|
||||||
const t = useTranslations("bill-edit-form.validation");
|
const t = await getTranslations("bill-edit-form.validation");
|
||||||
|
|
||||||
// FormSchema
|
// FormSchema
|
||||||
const validatedFields = UpdateBill(t)
|
const validatedFields = FormSchema(t)
|
||||||
.omit({ _id: true })
|
.omit({ _id: true })
|
||||||
.safeParse({
|
.safeParse({
|
||||||
billName: formData.get('billName'),
|
billName: formData.get('billName'),
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import { withUser } from '@/app/lib/auth';
|
|||||||
import { AuthenticatedUser } from '../types/next-auth';
|
import { AuthenticatedUser } from '../types/next-auth';
|
||||||
import { gotoHome } from './navigationActions';
|
import { gotoHome } from './navigationActions';
|
||||||
import { unstable_noStore as noStore } from 'next/cache';
|
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 = {
|
export type State = {
|
||||||
errors?: {
|
errors?: {
|
||||||
@@ -18,13 +19,17 @@ export type State = {
|
|||||||
message?:string | null;
|
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(),
|
_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(),
|
locationNotes: z.string(),
|
||||||
});
|
})
|
||||||
|
// dont include the _id field in the response
|
||||||
const UpdateLocation = FormSchema.omit({ _id: true });
|
.omit({ _id: true });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server-side action which adds or updates a bill
|
* Server-side action which adds or updates a bill
|
||||||
@@ -37,7 +42,9 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
|
|||||||
|
|
||||||
noStore();
|
noStore();
|
||||||
|
|
||||||
const validatedFields = UpdateLocation.safeParse({
|
const t = await getTranslations("location-edit-form.validation");
|
||||||
|
|
||||||
|
const validatedFields = FormSchema(t).safeParse({
|
||||||
locationName: formData.get('locationName'),
|
locationName: formData.get('locationName'),
|
||||||
locationNotes: formData.get('locationNotes'),
|
locationNotes: formData.get('locationNotes'),
|
||||||
});
|
});
|
||||||
@@ -84,8 +91,6 @@ export const updateOrAddLocation = withUser(async (user:AuthenticatedUser, locat
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// await asyncTimeout(1000);
|
|
||||||
|
|
||||||
if(yearMonth) await gotoHome(yearMonth);
|
if(yearMonth) await gotoHome(yearMonth);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -124,8 +129,6 @@ export const fetchAllLocations = withUser(async (user:AuthenticatedUser, year:nu
|
|||||||
})
|
})
|
||||||
.toArray();
|
.toArray();
|
||||||
|
|
||||||
// await asyncTimeout(1000);
|
|
||||||
|
|
||||||
return(locations)
|
return(locations)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -154,8 +157,6 @@ export const fetchLocationById = withUser(async (user:AuthenticatedUser, locatio
|
|||||||
return(null);
|
return(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// await asyncTimeout(1000);
|
|
||||||
|
|
||||||
return(billLocation);
|
return(billLocation);
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -170,7 +171,5 @@ export const deleteLocationById = withUser(async (user:AuthenticatedUser, locati
|
|||||||
// find a location with the given locationID
|
// find a location with the given locationID
|
||||||
const post = await dbClient.collection<BillingLocation>("lokacije").deleteOne({ _id: locationID, userId });
|
const post = await dbClient.collection<BillingLocation>("lokacije").deleteOne({ _id: locationID, userId });
|
||||||
|
|
||||||
// await asyncTimeout(1000);
|
|
||||||
|
|
||||||
await gotoHome(yearMonth)
|
await gotoHome(yearMonth)
|
||||||
})
|
})
|
||||||
@@ -95,7 +95,9 @@
|
|||||||
"notes-placeholder": "Notes",
|
"notes-placeholder": "Notes",
|
||||||
"save-button": "Save",
|
"save-button": "Save",
|
||||||
"cancel-button": "Cancel",
|
"cancel-button": "Cancel",
|
||||||
"delete-tooltip": "Delete realestate"
|
"delete-tooltip": "Delete realestate",
|
||||||
|
"validation": {
|
||||||
}
|
"location-name-required": "Relaestate name is required"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user