corrreciones al formulario de las osp
This commit is contained in:
@@ -213,6 +213,8 @@ export class CreateTrainingDto {
|
|||||||
@IsString()
|
@IsString()
|
||||||
communalCouncilEmail: string;
|
communalCouncilEmail: string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// === 6. LISTAS (Arrays JSON) ===
|
// === 6. LISTAS (Arrays JSON) ===
|
||||||
// Reciben un string JSON '[{...}]' y lo convierten a Objeto JS real
|
// Reciben un string JSON '[{...}]' y lo convierten a Objeto JS real
|
||||||
|
|
||||||
@@ -260,4 +262,19 @@ export class CreateTrainingDto {
|
|||||||
return value;
|
return value;
|
||||||
})
|
})
|
||||||
productList?: any[];
|
productList?: any[];
|
||||||
|
|
||||||
|
|
||||||
|
//ubicacion
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
state: string;
|
||||||
|
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
municipality: string;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
@IsString()
|
||||||
|
parish: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ export class TrainingService {
|
|||||||
|
|
||||||
// 2. Extraer solo visitDate para formatearlo.
|
// 2. Extraer solo visitDate para formatearlo.
|
||||||
// Ya NO extraemos state, municipality, etc. porque no vienen en el DTO.
|
// Ya NO extraemos state, municipality, etc. porque no vienen en el DTO.
|
||||||
const { visitDate, ...rest } = createTrainingDto;
|
const { visitDate, state, municipality, parish, ...rest } = createTrainingDto;
|
||||||
|
|
||||||
const [newRecord] = await this.drizzle
|
const [newRecord] = await this.drizzle
|
||||||
.insert(trainingSurveys)
|
.insert(trainingSurveys)
|
||||||
@@ -286,6 +286,9 @@ export class TrainingService {
|
|||||||
photo1: photoPaths[0] ?? null,
|
photo1: photoPaths[0] ?? null,
|
||||||
photo2: photoPaths[1] ?? null,
|
photo2: photoPaths[1] ?? null,
|
||||||
photo3: photoPaths[2] ?? null,
|
photo3: photoPaths[2] ?? null,
|
||||||
|
state: Number(state) ?? null,
|
||||||
|
municipality: Number(municipality) ?? null,
|
||||||
|
parish: Number(parish) ?? null,
|
||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
|
|||||||
@@ -42,15 +42,17 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|||||||
</div>
|
</div>
|
||||||
</SidebarHeader>
|
</SidebarHeader>
|
||||||
<SidebarContent>
|
<SidebarContent>
|
||||||
<GeneralMain titleGroup={'General'} items={GeneralItems} role={userRole} />
|
{AdministrationItems[0]?.role?.includes(userRole) &&
|
||||||
|
<AdministrationMain titleGroup={'Administracion'} items={AdministrationItems} role={userRole} />
|
||||||
|
}
|
||||||
{StatisticsItems[0]?.role?.includes(userRole) &&
|
{StatisticsItems[0]?.role?.includes(userRole) &&
|
||||||
<StatisticsMain titleGroup={'Estadisticas'} items={StatisticsItems} role={userRole} />
|
<StatisticsMain titleGroup={'Estadisticas'} items={StatisticsItems} role={userRole} />
|
||||||
}
|
}
|
||||||
|
|
||||||
{AdministrationItems[0]?.role?.includes(userRole) &&
|
<GeneralMain titleGroup={'General'} items={GeneralItems} role={userRole} />
|
||||||
<AdministrationMain titleGroup={'Administracion'} items={AdministrationItems} role={userRole} />
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* <NavProjects projects={data.projects} /> */}
|
{/* <NavProjects projects={data.projects} /> */}
|
||||||
</SidebarContent>
|
</SidebarContent>
|
||||||
<SidebarRail />
|
<SidebarRail />
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
CardTitle,
|
CardTitle,
|
||||||
} from '@repo/shadcn/components/ui/card';
|
} from '@repo/shadcn/components/ui/card';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { SelectSearchable } from '@repo/shadcn/components/ui/select-searchable';
|
||||||
|
|
||||||
const OSP_TYPES = ['EPSIC', 'EPSDC', 'UPF', 'OTROS', 'COOPERATIVA'];
|
const OSP_TYPES = ['EPSIC', 'EPSDC', 'UPF', 'OTROS', 'COOPERATIVA'];
|
||||||
const STATUS_OPTIONS = ['ACTIVA', 'INACTIVA'];
|
const STATUS_OPTIONS = ['ACTIVA', 'INACTIVA'];
|
||||||
@@ -158,10 +159,14 @@ export function CreateTrainingForm({
|
|||||||
equipmentList: defaultValues?.equipmentList || [],
|
equipmentList: defaultValues?.equipmentList || [],
|
||||||
productionList: defaultValues?.productionList || [],
|
productionList: defaultValues?.productionList || [],
|
||||||
productList: defaultValues?.productList || [],
|
productList: defaultValues?.productList || [],
|
||||||
|
state: defaultValues?.state || undefined,
|
||||||
|
municipality: defaultValues?.municipality || undefined,
|
||||||
|
parish: defaultValues?.parish || undefined,
|
||||||
},
|
},
|
||||||
mode: 'onChange',
|
mode: 'onChange',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Cascading Select Logic
|
// Cascading Select Logic
|
||||||
const ecoSector = useWatch({ control: form.control, name: 'ecoSector' });
|
const ecoSector = useWatch({ control: form.control, name: 'ecoSector' });
|
||||||
const productiveSector = useWatch({
|
const productiveSector = useWatch({
|
||||||
@@ -217,7 +222,7 @@ export function CreateTrainingForm({
|
|||||||
: [{ id: 0, stateId: 0, name: 'Sin Municipios' }];
|
: [{ id: 0, stateId: 0, name: 'Sin Municipios' }];
|
||||||
|
|
||||||
const coorParishOptions =
|
const coorParishOptions =
|
||||||
Array.isArray(dataCoorParish?.data) && dataCoorParish.data.length > 0
|
Array.isArray(dataCoorParish?.data) && dataCoorParish?.data.length > 0
|
||||||
? dataCoorParish.data
|
? dataCoorParish.data
|
||||||
: [{ id: 0, stateId: 0, name: 'Sin Parroquias' }];
|
: [{ id: 0, stateId: 0, name: 'Sin Parroquias' }];
|
||||||
|
|
||||||
@@ -263,7 +268,7 @@ export function CreateTrainingForm({
|
|||||||
// 1. Definimos las claves que NO queremos enviar en el bucle general
|
// 1. Definimos las claves que NO queremos enviar en el bucle general
|
||||||
// 'files' se procesa aparte.
|
// 'files' se procesa aparte.
|
||||||
// 'photo1/2/3' son strings (urls viejas) que no queremos reenviar como texto.
|
// 'photo1/2/3' son strings (urls viejas) que no queremos reenviar como texto.
|
||||||
const excludedKeys = ['files', 'photo1', 'photo2', 'photo3'];
|
const excludedKeys = ['files', 'photo1', 'photo2', 'photo3', 'coorState', 'coorMunicipality', 'coorParish'];
|
||||||
|
|
||||||
Object.entries(formData).forEach(([key, value]) => {
|
Object.entries(formData).forEach(([key, value]) => {
|
||||||
// 2. Condición actualizada: Si la key está en la lista de excluidos, la saltamos
|
// 2. Condición actualizada: Si la key está en la lista de excluidos, la saltamos
|
||||||
@@ -282,6 +287,17 @@ export function CreateTrainingForm({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 2. Mapeo manual y conversión a numérico
|
||||||
|
// if (formData.state) {
|
||||||
|
// data.append('state', Number(formData.state).toString());
|
||||||
|
// }
|
||||||
|
// if (formData.municipality) {
|
||||||
|
// data.append('municipality', Number(formData.municipality).toString());
|
||||||
|
// }
|
||||||
|
// if (formData.parish) {
|
||||||
|
// data.append('parish', Number(formData.parish).toString());
|
||||||
|
// }
|
||||||
if (defaultValues?.id) {
|
if (defaultValues?.id) {
|
||||||
data.append('id', defaultValues.id.toString());
|
data.append('id', defaultValues.id.toString());
|
||||||
}
|
}
|
||||||
@@ -290,23 +306,23 @@ export function CreateTrainingForm({
|
|||||||
selectedFiles.forEach((file) => {
|
selectedFiles.forEach((file) => {
|
||||||
data.append('files', file);
|
data.append('files', file);
|
||||||
});
|
});
|
||||||
|
console.log(data);
|
||||||
const mutation = defaultValues?.id ? updateTraining : createTraining;
|
const mutation = defaultValues?.id ? updateTraining : createTraining;
|
||||||
|
|
||||||
mutation(data as any, {
|
// mutation(data as any, {
|
||||||
onSuccess: () => {
|
// onSuccess: () => {
|
||||||
form.reset();
|
// form.reset();
|
||||||
setSelectedFiles([]);
|
// setSelectedFiles([]);
|
||||||
onSuccess?.();
|
// onSuccess?.();
|
||||||
},
|
// },
|
||||||
onError: (e) => {
|
// onError: (e) => {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
form.setError('root', {
|
// form.setError('root', {
|
||||||
type: 'manual',
|
// type: 'manual',
|
||||||
message: 'Error al guardar el registro',
|
// message: 'Error al guardar el registro',
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -382,6 +398,8 @@ export function CreateTrainingForm({
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="visitDate"
|
name="visitDate"
|
||||||
@@ -399,6 +417,76 @@ export function CreateTrainingForm({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="state"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Estado</FormLabel>
|
||||||
|
<SelectSearchable
|
||||||
|
options={stateOptions.map((item) => ({
|
||||||
|
value: item.id.toString(),
|
||||||
|
label: item.name,
|
||||||
|
}))}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
field.onChange(Number(value));
|
||||||
|
setState(Number(value));
|
||||||
|
setDisabledMunicipality(false);
|
||||||
|
setDisabledParish(true);
|
||||||
|
}}
|
||||||
|
placeholder="Selecciona un estado"
|
||||||
|
defaultValue={field.value?.toString()}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="municipality"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Municipio</FormLabel>
|
||||||
|
<SelectSearchable
|
||||||
|
options={municipalityOptions.map((item) => ({
|
||||||
|
value: item.id.toString(),
|
||||||
|
label: item.name,
|
||||||
|
}))}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
field.onChange(Number(value));
|
||||||
|
setMunicipality(Number(value));
|
||||||
|
setDisabledParish(false);
|
||||||
|
}}
|
||||||
|
placeholder="Selecciona un municipio"
|
||||||
|
disabled={disabledMunicipality}
|
||||||
|
defaultValue={field.value?.toString()}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="parish"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Parroquia</FormLabel>
|
||||||
|
<SelectSearchable
|
||||||
|
options={parishOptions.map((item) => ({
|
||||||
|
value: item.id.toString(),
|
||||||
|
label: item.name,
|
||||||
|
}))}
|
||||||
|
onValueChange={(value) => field.onChange(Number(value))}
|
||||||
|
placeholder="Selecciona una parroquia"
|
||||||
|
disabled={disabledParish}
|
||||||
|
defaultValue={field.value?.toString()}
|
||||||
|
/>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -833,6 +921,7 @@ export function CreateTrainingForm({
|
|||||||
<CardTitle>3. Detalles de la ubicación</CardTitle>
|
<CardTitle>3. Detalles de la ubicación</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
|
<CardContent className="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="ospAddress"
|
name="ospAddress"
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ export const CellAction: React.FC<CellActionProps> = ({ data, apiUrl }) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
|
|
||||||
<TooltipProvider>
|
{/* <TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
@@ -92,7 +92,7 @@ export const CellAction: React.FC<CellActionProps> = ({ data, apiUrl }) => {
|
|||||||
<p>Exportar Excel</p>
|
<p>Exportar Excel</p>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider> */}
|
||||||
|
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { TrainingSchema } from '../schemas/training';
|
import { TrainingSchema } from '../schemas/training';
|
||||||
|
import {
|
||||||
|
useMunicipalityQuery,
|
||||||
|
useParishQuery,
|
||||||
|
useStateQuery,
|
||||||
|
} from '@/feactures/location/hooks/use-query-location';
|
||||||
|
|
||||||
interface TrainingViewModalProps {
|
interface TrainingViewModalProps {
|
||||||
data: TrainingSchema | null;
|
data: TrainingSchema | null;
|
||||||
@@ -42,8 +47,20 @@ export function TrainingViewModal({
|
|||||||
}: TrainingViewModalProps) {
|
}: TrainingViewModalProps) {
|
||||||
const [selectedImage, setSelectedImage] = useState<string | null>(null);
|
const [selectedImage, setSelectedImage] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const { data: statesData } = useStateQuery();
|
||||||
|
const { data: municipalitiesData } = useMunicipalityQuery(data?.state || 0);
|
||||||
|
const { data: parishesData } = useParishQuery(data?.municipality || 0);
|
||||||
|
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
|
|
||||||
|
const stateName = statesData?.data?.find((s: any) => s.id === data.state)?.name;
|
||||||
|
const municipalityName = municipalitiesData?.data?.find(
|
||||||
|
(m: any) => m.id === data.municipality,
|
||||||
|
)?.name;
|
||||||
|
const parishName = parishesData?.data?.find(
|
||||||
|
(p: any) => p.id === data.parish,
|
||||||
|
)?.name;
|
||||||
|
|
||||||
const DetailItem = ({ label, value }: { label: string; value: any }) => (
|
const DetailItem = ({ label, value }: { label: string; value: any }) => (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
|
||||||
@@ -123,6 +140,9 @@ export function TrainingViewModal({
|
|||||||
: 'N/A'
|
: 'N/A'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<DetailItem label="Estado" value={stateName} />
|
||||||
|
<DetailItem label="Municipio" value={municipalityName} />
|
||||||
|
<DetailItem label="Parroquia" value={parishName} />
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
{/* 2. Sectores y Actividad */}
|
{/* 2. Sectores y Actividad */}
|
||||||
|
|||||||
Reference in New Issue
Block a user