import React, { useEffect } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Modal } from '../ui/Modal'; import { HelpTooltip } from '../ui/HelpTooltip'; import { useToast } from '../ui/Toast'; import { createProject, updateProject } from '../../services/api'; import { Project, Programme, IndustrySector, ProjectType, CreateProjectRequest, } from '../../types'; import { INDUSTRY_SECTOR_OPTIONS, PROJECT_TYPE_OPTIONS } from '../../lib/formatters'; const projectSchema = z.object({ name: z.string().min(4, 'Project name must be at least 4 characters'), description: z.string().min(10, 'Provide a meaningful implementation description (min 10 chars)'), programmeId: z.coerce.number().min(1, 'Select a parent programme'), sector: z.coerce.number().min(1), projectType: z.coerce.number().min(1), startedAt: z.string().optional().nullable(), endedAt: z.string().optional().nullable(), }); type ProjectFormValues = z.infer; interface ProjectFormModalProps { isOpen: boolean; onClose: () => void; editingProject: Project | null; programmes: Programme[]; defaultProgrammeId?: number | string; } export const ProjectFormModal: React.FC = ({ isOpen, onClose, editingProject, programmes, defaultProgrammeId, }) => { const queryClient = useQueryClient(); const { success, error: toastError } = useToast(); const form = useForm({ resolver: zodResolver(projectSchema) as any, defaultValues: { name: '', description: '', programmeId: defaultProgrammeId ? Number(defaultProgrammeId) : (programmes[0]?.id ? Number(programmes[0].id) : 1), sector: IndustrySector.AgriTech, projectType: ProjectType.Innovation, startedAt: '', endedAt: '', }, }); useEffect(() => { if (isOpen) { if (editingProject) { form.reset({ name: editingProject.name || '', description: editingProject.description || '', programmeId: editingProject.programmeId ? Number(editingProject.programmeId) : (programmes[0]?.id ? Number(programmes[0].id) : 1), sector: editingProject.sector || IndustrySector.AgriTech, projectType: editingProject.projectType || ProjectType.Innovation, startedAt: editingProject.startedAt ? editingProject.startedAt.slice(0, 10) : '', endedAt: editingProject.endedAt ? editingProject.endedAt.slice(0, 10) : '', }); } else { form.reset({ name: '', description: '', programmeId: defaultProgrammeId ? Number(defaultProgrammeId) : (programmes[0]?.id ? Number(programmes[0].id) : 1), sector: IndustrySector.AgriTech, projectType: ProjectType.Innovation, startedAt: new Date().toISOString().slice(0, 10), endedAt: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10), }); } } }, [isOpen, editingProject, defaultProgrammeId, programmes, form]); const mutation = useMutation({ mutationFn: async (data: ProjectFormValues) => { if (editingProject) { return updateProject({ projectId: editingProject.id, name: data.name, description: data.description, startedAt: data.startedAt ? new Date(data.startedAt).toISOString() : null, endedAt: data.endedAt ? new Date(data.endedAt).toISOString() : null, sector: Number(data.sector), projectType: Number(data.projectType), }); } return createProject(data as CreateProjectRequest); }, onSuccess: (savedProj) => { queryClient.invalidateQueries({ queryKey: ['projects'] }); success( editingProject ? 'Project Updated' : 'Project Registered', `Project "${savedProj.name}" was successfully saved.` ); onClose(); form.reset(); }, onError: (err: unknown) => { toastError(editingProject ? 'Failed to update project' : 'Failed to create project', err); }, }); return (
mutation.mutate(data as any))} className="space-y-4">
{form.formState.errors.name && (

{form.formState.errors.name.message}

)}
{!editingProject && (
)}