260330:1630 Addied correspondence_revieion_attcahments table table #04
CI / CD Pipeline / build (push) Successful in 17m50s
CI / CD Pipeline / deploy (push) Successful in 7m12s

This commit is contained in:
admin
2026-03-30 16:30:24 +07:00
parent f9dbff7811
commit 4538c83010
+30 -17
View File
@@ -16,7 +16,7 @@ import { useCreateCorrespondence, useUpdateCorrespondence } from '@/hooks/use-co
import { Organization } from '@/types/organization'; import { Organization } from '@/types/organization';
import { useOrganizations, useProjects, useCorrespondenceTypes, useDisciplines, useContracts } from '@/hooks/use-master-data'; import { useOrganizations, useProjects, useCorrespondenceTypes, useDisciplines, useContracts } from '@/hooks/use-master-data';
import { CreateCorrespondenceDto } from '@/types/dto/correspondence/create-correspondence.dto'; import { CreateCorrespondenceDto } from '@/types/dto/correspondence/create-correspondence.dto';
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef, useMemo } from 'react';
import { numberingApi } from '@/lib/api/numbering'; import { numberingApi } from '@/lib/api/numbering';
import { filesApi } from '@/lib/api/files'; import { filesApi } from '@/lib/api/files';
import { toast } from 'sonner'; import { toast } from 'sonner';
@@ -81,8 +81,11 @@ interface InitialCorrespondenceData {
project?: { publicId?: string }; project?: { publicId?: string };
contract?: { publicId?: string }; contract?: { publicId?: string };
correspondenceTypeId?: number; correspondenceTypeId?: number;
type?: { id?: number; publicId?: string };
disciplineId?: number; disciplineId?: number;
discipline?: { discipline?: {
id?: number;
publicId?: string;
contract?: { publicId?: string }; contract?: { publicId?: string };
}; };
revisions?: Array<{ revisions?: Array<{
@@ -167,7 +170,8 @@ export function CorrespondenceForm({
const selectedRevision = normalizedSelectedRevisionId const selectedRevision = normalizedSelectedRevisionId
? initialData?.revisions?.find((r) => normalizeUuid(r.publicId) === normalizedSelectedRevisionId) ? initialData?.revisions?.find((r) => normalizeUuid(r.publicId) === normalizedSelectedRevisionId)
: undefined; : undefined;
const currentRev = selectedRevision || initialData?.revisions?.find((r) => r.isCurrent) || initialData?.revisions?.[0]; const defaultValues = useMemo<Partial<FormData>>(() => {
const currentRevision = selectedRevision || initialData?.revisions?.find((r) => r.isCurrent) || initialData?.revisions?.[0];
const initialToRecipient = initialData?.recipients?.find((r) => r.recipientType === 'TO'); const initialToRecipient = initialData?.recipients?.find((r) => r.recipientType === 'TO');
const initialCcRecipientIds = const initialCcRecipientIds =
initialData?.recipients initialData?.recipients
@@ -175,43 +179,52 @@ export function CorrespondenceForm({
.map((r) => normalizePublicId(r.recipientOrganization?.publicId)) .map((r) => normalizePublicId(r.recipientOrganization?.publicId))
.filter((value): value is string => Boolean(value)) ?? []; .filter((value): value is string => Boolean(value)) ?? [];
const defaultValues: Partial<FormData> = { return {
projectId: projectId:
normalizePublicId(initialData?.project?.publicId) ?? normalizePublicId(initialData?.project?.publicId) ??
normalizePublicId(initialData?.projectId), normalizePublicId((initialData as Record<string, unknown>)?.projectId),
// [FIX v1.8.1] correspondences ไม่มี contract_id โดยตรง → จะ auto-populate จาก discipline useEffect หรือจาก object contract เองในกรณี mock/test
contractId: contractId:
normalizePublicId(initialData?.contract?.publicId) ?? normalizePublicId(initialData?.contract?.publicId) ??
normalizePublicId(initialData?.discipline?.contract?.publicId) ?? normalizePublicId(initialData?.discipline?.contract?.publicId) ??
normalizePublicId((initialData as Record<string, unknown>)?.contractId as string), normalizePublicId((initialData as Record<string, unknown>)?.contractId as string),
documentTypeId: initialData?.correspondenceTypeId || undefined, documentTypeId: initialData?.type?.id ?? initialData?.correspondenceTypeId,
disciplineId: initialData?.disciplineId || undefined, disciplineId: initialData?.discipline?.id ?? initialData?.disciplineId,
subject: currentRev?.subject || currentRev?.title || '', subject: currentRevision?.subject || currentRevision?.title || '',
description: currentRev?.description || '', description: currentRevision?.description || '',
body: currentRev?.body || '', body: currentRevision?.body || '',
remarks: currentRev?.remarks || '', remarks: currentRevision?.remarks || '',
dueDate: currentRev?.dueDate ? new Date(currentRev.dueDate).toISOString().split('T')[0] : undefined, dueDate: currentRevision?.dueDate ? new Date(currentRevision.dueDate).toISOString().split('T')[0] : undefined,
documentDate: currentRev?.documentDate ? new Date(currentRev.documentDate).toISOString().split('T')[0] : undefined, documentDate: currentRevision?.documentDate ? new Date(currentRevision.documentDate).toISOString().split('T')[0] : undefined,
issuedDate: currentRev?.issuedDate ? new Date(currentRev.issuedDate).toISOString().split('T')[0] : undefined, issuedDate: currentRevision?.issuedDate ? new Date(currentRevision.issuedDate).toISOString().split('T')[0] : undefined,
receivedDate: currentRev?.receivedDate ? new Date(currentRev.receivedDate).toISOString().split('T')[0] : undefined, receivedDate: currentRevision?.receivedDate ? new Date(currentRevision.receivedDate).toISOString().split('T')[0] : undefined,
fromOrganizationId: fromOrganizationId:
normalizePublicId(initialData?.originator?.publicId) ?? normalizePublicId(initialData?.originatorId), normalizePublicId(initialData?.originator?.publicId) ??
normalizePublicId((initialData as Record<string, unknown>)?.originatorId as string),
toOrganizationId: normalizePublicId(initialToRecipient?.recipientOrganization?.publicId), toOrganizationId: normalizePublicId(initialToRecipient?.recipientOrganization?.publicId),
ccOrganizationIds: initialCcRecipientIds, ccOrganizationIds: initialCcRecipientIds,
importance: currentRev?.details?.importance || 'NORMAL', importance: currentRevision?.details?.importance || 'NORMAL',
} as Partial<FormData>; } as Partial<FormData>;
}, [initialData, selectedRevision]);
const { const {
register, register,
handleSubmit, handleSubmit,
setValue, setValue,
watch, watch,
reset,
formState: { errors }, formState: { errors },
} = useForm<FormData>({ } = useForm<FormData>({
resolver: zodResolver(correspondenceSchema) as Resolver<FormData>, resolver: zodResolver(correspondenceSchema) as Resolver<FormData>,
defaultValues: defaultValues as FormData, defaultValues: defaultValues as FormData,
}); });
// Watch for dynamic updates of initialData to ensure form correctly populates
useEffect(() => {
if (initialData) {
reset(defaultValues as FormData);
}
}, [initialData, selectedRevisionId, reset, defaultValues]);
// Watch for controlled inputs // Watch for controlled inputs
const projectId = watch('projectId'); const projectId = watch('projectId');
const contractId = watch('contractId'); const contractId = watch('contractId');