545 lines
25 KiB
TypeScript
545 lines
25 KiB
TypeScript
'use client';
|
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { Button } from '@repo/shadcn/button';
|
|
import {
|
|
Form,
|
|
FormControl,
|
|
FormField,
|
|
FormItem,
|
|
FormLabel,
|
|
FormMessage,
|
|
} from '@repo/shadcn/form';
|
|
import { Input } from '@repo/shadcn/input';
|
|
import { Textarea } from '@repo/shadcn/textarea';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@repo/shadcn/select';
|
|
import { useForm } from 'react-hook-form';
|
|
import { useCreateTraining } from "../hooks/use-training";
|
|
import { TrainingSchema, trainingSchema } from '../schemas/training';
|
|
|
|
import { SelectSearchable } from '@repo/shadcn/select-searchable'
|
|
import React from 'react';
|
|
import { useStateQuery, useMunicipalityQuery, useParishQuery } from '@/feactures/location/hooks/use-query-location';
|
|
|
|
const PRODUCTIVE_ACTIVITIES = [
|
|
'Agricola',
|
|
'Textil',
|
|
'Bloquera',
|
|
'Carpinteria',
|
|
'Unidad de suministro'
|
|
];
|
|
|
|
interface CreateTrainingFormProps {
|
|
onSuccess?: () => void;
|
|
onCancel?: () => void;
|
|
defaultValues?: Partial<TrainingSchema>;
|
|
}
|
|
|
|
export function CreateTrainingForm({
|
|
onSuccess,
|
|
onCancel,
|
|
defaultValues,
|
|
}: CreateTrainingFormProps) {
|
|
const {
|
|
mutate: saveTraining,
|
|
isPending: isSaving,
|
|
} = useCreateTraining();
|
|
|
|
const [state, setState] = React.useState(0);
|
|
const [municipality, setMunicipality] = React.useState(0);
|
|
const [disabledMunicipality, setDisabledMunicipality] = React.useState(true);
|
|
const [disabledParish, setDisabledParish] = React.useState(true);
|
|
|
|
const { data: dataState } = useStateQuery()
|
|
const { data: dataMunicipality } = useMunicipalityQuery(state)
|
|
const { data: dataParish } = useParishQuery(municipality)
|
|
|
|
const stateOptions = dataState?.data || [{ id: 0, name: 'Sin estados' }]
|
|
|
|
const municipalityOptions = Array.isArray(dataMunicipality?.data) && dataMunicipality.data.length > 0
|
|
? dataMunicipality.data
|
|
: [{ id: 0, stateId: 0, name: 'Sin Municipios' }]
|
|
// const parishOptions = dataParish?.data || [{id:0,municipalityId:0,name:'Sin Parroquias'}]
|
|
const parishOptions = Array.isArray(dataParish?.data) && dataParish.data.length > 0
|
|
? dataParish.data
|
|
: [{ id: 0, stateId: 0, name: 'Sin Parroquias' }]
|
|
|
|
const form = useForm<TrainingSchema>({
|
|
resolver: zodResolver(trainingSchema),
|
|
defaultValues: {
|
|
firstname: defaultValues?.firstname || '',
|
|
lastname: defaultValues?.lastname || '',
|
|
visitDate: defaultValues?.visitDate || new Date().toISOString().split('T')[0],
|
|
productiveActivity: defaultValues?.productiveActivity || '',
|
|
financialRequirementDescription: defaultValues?.financialRequirementDescription || '',
|
|
siturCodeCommune: defaultValues?.siturCodeCommune || '',
|
|
communalCouncil: defaultValues?.communalCouncil || '',
|
|
siturCodeCommunalCouncil: defaultValues?.siturCodeCommunalCouncil || '',
|
|
ospName: defaultValues?.ospName || '',
|
|
ospAddress: defaultValues?.ospAddress || '',
|
|
ospRif: defaultValues?.ospRif || '',
|
|
ospType: defaultValues?.ospType || '',
|
|
currentStatus: defaultValues?.currentStatus || '',
|
|
companyConstitutionYear: defaultValues?.companyConstitutionYear || new Date().getFullYear(),
|
|
producerCount: defaultValues?.producerCount || 0,
|
|
productDescription: defaultValues?.productDescription || '',
|
|
installedCapacity: defaultValues?.installedCapacity || '',
|
|
operationalCapacity: defaultValues?.operationalCapacity || '',
|
|
ospResponsibleFullname: defaultValues?.ospResponsibleFullname || '',
|
|
ospResponsibleCedula: defaultValues?.ospResponsibleCedula || '',
|
|
ospResponsibleRif: defaultValues?.ospResponsibleRif || '',
|
|
ospResponsiblePhone: defaultValues?.ospResponsiblePhone || '',
|
|
civilState: defaultValues?.civilState || '',
|
|
familyBurden: defaultValues?.familyBurden || 0,
|
|
numberOfChildren: defaultValues?.numberOfChildren || 0,
|
|
generalObservations: defaultValues?.generalObservations || '',
|
|
ospResponsibleEmail: defaultValues?.ospResponsibleEmail || '',
|
|
photo1: defaultValues?.photo1 || '',
|
|
photo2: defaultValues?.photo2 || '',
|
|
photo3: defaultValues?.photo3 || '',
|
|
paralysisReason: defaultValues?.paralysisReason || '',
|
|
state: defaultValues?.state || undefined,
|
|
municipality: defaultValues?.municipality || undefined,
|
|
parish: defaultValues?.parish || undefined,
|
|
},
|
|
mode: 'onChange',
|
|
});
|
|
|
|
const onSubmit = async (formData: TrainingSchema) => {
|
|
saveTraining(formData, {
|
|
onSuccess: () => {
|
|
form.reset();
|
|
onSuccess?.();
|
|
},
|
|
onError: (e) => {
|
|
console.error(e);
|
|
form.setError('root', {
|
|
type: 'manual',
|
|
message: 'Error al guardar el registro',
|
|
});
|
|
},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Form {...form}>
|
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
{form.formState.errors.root && (
|
|
<div className="text-destructive text-sm">
|
|
{form.formState.errors.root.message}
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{/* Datos Personales */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2">Datos Básicos</h3>
|
|
</div>
|
|
|
|
<FormField control={form.control} name="firstname" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Nombre</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="lastname" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Apellido</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="visitDate" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Fecha de la visita</FormLabel>
|
|
<FormControl><Input type="date" {...field} value={field.value ? new Date(field.value).toISOString().split('T')[0] : ''} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
{/* Ubicación */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2 mt-4">Ubicación</h3>
|
|
</div>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="state"
|
|
render={({ field }) => (
|
|
<FormItem className="w-full">
|
|
<FormLabel>Estado</FormLabel>
|
|
|
|
<SelectSearchable
|
|
options={
|
|
stateOptions?.map((item) => ({
|
|
value: item.id.toString(),
|
|
label: item.name,
|
|
})) || []
|
|
}
|
|
onValueChange={(value: any) => { field.onChange(Number(value)); setState(value); setDisabledMunicipality(false); setDisabledParish(true) }
|
|
}
|
|
placeholder="Selecciona un estado"
|
|
defaultValue={field.value?.toString()}
|
|
// disabled={readOnly}
|
|
/>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="municipality"
|
|
render={({ field }) => (
|
|
<FormItem className="w-full">
|
|
<FormLabel>Municipio</FormLabel>
|
|
|
|
<SelectSearchable
|
|
options={
|
|
municipalityOptions?.map((item) => ({
|
|
value: item.id.toString(),
|
|
label: item.name,
|
|
})) || []
|
|
}
|
|
onValueChange={(value: any) => { field.onChange(Number(value)); setMunicipality(value); setDisabledParish(false) }
|
|
}
|
|
placeholder="Selecciona un Municipio"
|
|
defaultValue={field.value?.toString()}
|
|
disabled={disabledMunicipality}
|
|
/>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
<FormField
|
|
control={form.control}
|
|
name="parish"
|
|
render={({ field }) => (
|
|
<FormItem className="w-full">
|
|
<FormLabel>Parroquia</FormLabel>
|
|
|
|
<SelectSearchable
|
|
options={
|
|
parishOptions?.map((item) => ({
|
|
value: item.id.toString(),
|
|
label: item.name,
|
|
})) || []
|
|
}
|
|
onValueChange={(value: any) =>
|
|
field.onChange(Number(value))
|
|
}
|
|
placeholder="Selecciona una Parroquia"
|
|
defaultValue={field.value?.toString()}
|
|
disabled={disabledParish}
|
|
/>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)}
|
|
/>
|
|
|
|
{/* <FormField control={form.control} name="state" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Estado</FormLabel>
|
|
<FormControl><Input {...field} value={field.value || ''} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="municipality" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Municipio</FormLabel>
|
|
<FormControl><Input {...field} value={field.value || ''} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="parish" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Parroquia</FormLabel>
|
|
<FormControl><Input {...field} value={field.value || ''} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} /> */}
|
|
|
|
<FormField control={form.control} name="siturCodeCommune" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Código SITUR Comuna</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="communalCouncil" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Consejo Comunal</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="siturCodeCommunalCouncil" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Código SITUR Consejo Comunal</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
{/* Datos de la OSP */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2 mt-4">Datos de la Organización Socioproductiva (OSP)</h3>
|
|
</div>
|
|
|
|
<FormField control={form.control} name="ospName" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Nombre de la Organización</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospAddress" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Dirección</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospRif" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>RIF</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospType" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Tipo de Organización</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="productiveActivity" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Actividad Productiva</FormLabel>
|
|
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
<FormControl>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Seleccione actividad" />
|
|
</SelectTrigger>
|
|
</FormControl>
|
|
<SelectContent>
|
|
{PRODUCTIVE_ACTIVITIES.map((activity) => (
|
|
<SelectItem key={activity} value={activity}>
|
|
{activity}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="currentStatus" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Estatus Actual</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="companyConstitutionYear" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Año de Constitución</FormLabel>
|
|
<FormControl><Input type="number" {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="producerCount" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Cantidad de Productores</FormLabel>
|
|
<FormControl><Input type="number" {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="productDescription" render={({ field }) => (
|
|
<FormItem className="col-span-2">
|
|
<FormLabel>Breve descripción del producto o servicio</FormLabel>
|
|
<FormControl><Textarea {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="installedCapacity" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Capacidad Instalada</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="operationalCapacity" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Capacidad Operativa</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="financialRequirementDescription" render={({ field }) => (
|
|
<FormItem className="col-span-2">
|
|
<FormLabel>Descripción del Requerimiento Financiero</FormLabel>
|
|
<FormControl><Textarea {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="paralysisReason" render={({ field }) => (
|
|
<FormItem className="col-span-2">
|
|
<FormLabel>Razones de paralización (si aplica)</FormLabel>
|
|
<FormControl><Textarea {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
{/* Responsable */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2 mt-4">Datos del Responsable</h3>
|
|
</div>
|
|
|
|
<FormField control={form.control} name="ospResponsibleFullname" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Nombre y Apellido</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospResponsibleCedula" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Cédula (sin puntos)</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospResponsibleRif" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>RIF (sin puntos)</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospResponsiblePhone" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Teléfonos (2 números)</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="civilState" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Estado Civil</FormLabel>
|
|
<FormControl><Input {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="ospResponsibleEmail" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Correo Electrónico</FormLabel>
|
|
<FormControl><Input type="email" {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="familyBurden" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Carga Familiar</FormLabel>
|
|
<FormControl><Input type="number" {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="numberOfChildren" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Número de Hijos</FormLabel>
|
|
<FormControl><Input type="number" {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
{/* datos adicionales */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2 mt-4">Datos Adicionales</h3>
|
|
</div>
|
|
|
|
<FormField control={form.control} name="generalObservations" render={({ field }) => (
|
|
<FormItem className="col-span-2">
|
|
<FormLabel>Observaciones Generales</FormLabel>
|
|
<FormControl><Textarea {...field} /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
{/* Fotos */}
|
|
<div className="col-span-2">
|
|
<h3 className="text-lg font-medium mb-2 mt-4">Registro Fotográfico (URLs)</h3>
|
|
</div>
|
|
|
|
<FormField control={form.control} name="photo1" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Foto 1</FormLabel>
|
|
<FormControl><Input {...field} placeholder="URL de la imagen" /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="photo2" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Foto 2</FormLabel>
|
|
<FormControl><Input {...field} placeholder="URL de la imagen" /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
<FormField control={form.control} name="photo3" render={({ field }) => (
|
|
<FormItem>
|
|
<FormLabel>Foto 3</FormLabel>
|
|
<FormControl><Input {...field} placeholder="URL de la imagen" /></FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
)} />
|
|
|
|
</div>
|
|
|
|
<div className="flex justify-end gap-4 mt-6">
|
|
<Button variant="outline" type="button" onClick={onCancel}>
|
|
Cancelar
|
|
</Button>
|
|
<Button type="submit" disabled={isSaving}>
|
|
{isSaving ? 'Guardando...' : 'Guardar'}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</Form>
|
|
);
|
|
}
|