import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Modal } from '@/components/ui/Modal'; import { Input } from '@/components/ui/Input'; import { Select } from '@/components/ui/Select'; import { Button } from '@/components/ui/Button'; import { useToast } from '@/components/ui/Toast'; import { type UnifiedContact, useCreateUnifiedContact, useUpdateUnifiedContact, } from '@/api/hooks'; export interface ContactEditModalProps { open: boolean; onClose: () => void; contact?: UnifiedContact | null; onSaved?: (id: string) => void; } // ── Zod Schema ── const phoneRegex = /^[+]?[\d\s\-().]{6,20}$/; const contactSchema = z.object({ type: z.enum(['company', 'person']), name: z.string().optional().default(''), firstname: z.string().optional().default(''), surname: z.string().optional().default(''), code: z.string().optional().default(''), email_1: z.string().email('Invalid email').or(z.literal('')).optional().default(''), email_2: z.string().email('Invalid email').or(z.literal('')).optional().default(''), phone_1: z.string().regex(phoneRegex, 'Invalid phone').or(z.literal('')).optional().default(''), phone_2: z.string().regex(phoneRegex, 'Invalid phone').or(z.literal('')).optional().default(''), website: z.string().optional().default(''), mailing_street: z.string().optional().default(''), mailing_number: z.string().optional().default(''), mailing_postalcode: z.string().optional().default(''), mailing_city: z.string().optional().default(''), mailing_country: z.string().optional().default(''), vat_code: z.string().optional().default(''), fiscal_code: z.string().optional().default(''), commerce_code: z.string().optional().default(''), bic: z.string().optional().default(''), bank_account: z.string().optional().default(''), tags: z.string().optional().default(''), projectnote: z.string().optional().default(''), contact_warning: z.string().optional().default(''), }).superRefine((data, ctx) => { if (data.type === 'company' && !data.name?.trim()) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Required', path: ['name'] }); } if (data.type === 'person' && !data.firstname?.trim() && !data.surname?.trim()) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Required', path: ['firstname'] }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Required', path: ['surname'] }); } }); type ContactFormData = z.infer; export function ContactEditModal({ open, onClose, contact, onSaved }: ContactEditModalProps) { const { t } = useTranslation(); const toast = useToast(); const createMutation = useCreateUnifiedContact(); const updateMutation = useUpdateUnifiedContact(); const isEdit = !!contact; const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(contactSchema), defaultValues: { type: 'company', name: '', firstname: '', surname: '', code: '', email_1: '', email_2: '', phone_1: '', phone_2: '', website: '', mailing_street: '', mailing_number: '', mailing_postalcode: '', mailing_city: '', mailing_country: '', vat_code: '', fiscal_code: '', commerce_code: '', bic: '', bank_account: '', tags: '', projectnote: '', contact_warning: '', }, }); const currentType = watch('type'); // Reset form when modal opens useEffect(() => { if (open) { reset({ type: (contact?.type as 'company' | 'person') || 'company', name: contact?.name || '', firstname: contact?.firstname || '', surname: contact?.surname || '', code: contact?.code || '', email_1: contact?.email_1 || '', email_2: contact?.email_2 || '', phone_1: contact?.phone_1 || '', phone_2: contact?.phone_2 || '', website: contact?.website || '', mailing_street: contact?.mailing_street || '', mailing_number: contact?.mailing_number || '', mailing_postalcode: contact?.mailing_postalcode || '', mailing_city: contact?.mailing_city || '', mailing_country: contact?.mailing_country || '', vat_code: contact?.vat_code || '', fiscal_code: contact?.fiscal_code || '', commerce_code: contact?.commerce_code || '', bic: contact?.bic || '', bank_account: contact?.bank_account || '', tags: contact?.tags || '', projectnote: contact?.projectnote || '', contact_warning: contact?.contact_warning || '', }); } }, [open, contact, reset]); const onSubmit = async (formData: ContactFormData) => { const data: Partial = { type: formData.type, name: formData.type === 'company' ? formData.name || null : null, firstname: formData.type === 'person' ? formData.firstname || null : null, surname: formData.type === 'person' ? formData.surname || null : null, code: formData.code || null, email_1: formData.email_1 || null, email_2: formData.email_2 || null, phone_1: formData.phone_1 || null, phone_2: formData.phone_2 || null, website: formData.website || null, mailing_street: formData.mailing_street || null, mailing_number: formData.mailing_number || null, mailing_postalcode: formData.mailing_postalcode || null, mailing_city: formData.mailing_city || null, mailing_country: formData.mailing_country || null, vat_code: formData.vat_code || null, fiscal_code: formData.fiscal_code || null, commerce_code: formData.commerce_code || null, bic: formData.bic || null, bank_account: formData.bank_account || null, tags: formData.tags || null, projectnote: formData.projectnote || null, contact_warning: formData.contact_warning || null, }; try { if (isEdit && contact) { await updateMutation.mutateAsync({ id: contact.id, data }); toast.success(t('contacts.updated')); onSaved?.(contact.id); } else { const result = await createMutation.mutateAsync(data) as { id: string }; toast.success(t('contacts.created')); onSaved?.(result.id); } onClose(); } catch (err: any) { toast.error(err.message || (isEdit ? t('contacts.updateFailed') : t('contacts.createFailed'))); } }; return (
{/* Type */} ) : (
)} {/* Code */} {/* Communication */}

{t('contacts.communication')}

{/* Mailing Address */}

{t('contacts.mailingAddress')}

{/* Financial */}

{t('contacts.financial')}

{/* Notes */}

{t('contacts.notes')}