'use server'; import { z } from 'zod'; import { getDbClient } from '../dbClient'; import { UserProfile } from '../db-types'; import { withUser } from '@/app/lib/auth'; import { AuthenticatedUser } from '../types/next-auth'; import { unstable_noStore as noStore } from 'next/cache'; import { IntlTemplateFn } from '@/app/i18n'; import { getTranslations, getLocale } from "next-intl/server"; import { revalidatePath } from 'next/cache'; import { gotoHomeWithMessage } from './navigationActions'; import * as IBAN from 'iban'; export type State = { errors?: { firstName?: string[]; lastName?: string[]; address?: string[]; iban?: string[]; }; message?: string | null; success?: boolean; }; /** * Schema for validating user profile form fields */ const FormSchema = (t: IntlTemplateFn) => z.object({ firstName: z.string().optional(), lastName: z.string().optional(), address: z.string().optional(), iban: z.string() .optional() .refine( (val) => { if (!val || val.trim() === '') return true; // Remove spaces and validate using iban.js library const cleaned = val.replace(/\s/g, '').toUpperCase(); return IBAN.isValid(cleaned); }, { message: t("iban-invalid") } ), }); /** * Get user profile */ export const getUserProfile = withUser(async (user: AuthenticatedUser) => { noStore(); const dbClient = await getDbClient(); const { id: userId } = user; const profile = await dbClient.collection("users") .findOne({ userId }); return profile; }); /** * Update user profile */ export const updateUserProfile = withUser(async (user: AuthenticatedUser, prevState: State, formData: FormData) => { noStore(); const t = await getTranslations("account-form.validation"); const validatedFields = FormSchema(t).safeParse({ firstName: formData.get('firstName') || undefined, lastName: formData.get('lastName') || undefined, address: formData.get('address') || undefined, iban: formData.get('iban') || undefined, }); // If form validation fails, return errors early. Otherwise, continue... if (!validatedFields.success) { return { errors: validatedFields.error.flatten().fieldErrors, message: "Validation failed", success: false, }; } const { firstName, lastName, address, iban } = validatedFields.data; // Normalize IBAN: remove spaces and convert to uppercase const normalizedIban = iban ? iban.replace(/\s/g, '').toUpperCase() : null; // Update the user profile in MongoDB const dbClient = await getDbClient(); const { id: userId } = user; const userProfile: UserProfile = { userId, firstName: firstName || null, lastName: lastName || null, address: address || null, iban: normalizedIban, }; await dbClient.collection("users") .updateOne( { userId }, { $set: userProfile }, { upsert: true } ); revalidatePath('/account'); // Get current locale and redirect to home with success message const locale = await getLocale(); await gotoHomeWithMessage(locale, 'profileSaved'); });