// PrefixModal.tsx import React, { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/shared/common/ui/dialog"; import { Button } from "@/shared/common/ui/button"; import { Input } from "@/shared/common/ui/input"; import { Label } from "@radix-ui/react-label"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { CreatePrefixPayload, CreateSuffixPayload, prefixSuffixService, } from "@/user-management/services/api/prefixSuffixService"; import { t } from "i18next"; import { PrefixTabType } from "./PrefixAndSuffixCard"; import { toast } from "sonner"; import { useAddReferenceNumber, useGetReferenceNumbers, useUpdateExternalReferencePrefix, useUpdateInternalMemoReferencePrefix, } from "@/shared/hooks/useReferenceNumberPrefixes"; import { useErrorHandler } from "@/shared/hooks/useErrorHandler"; import { SingleSelect } from "@/shared/common/ui/single-select"; interface PrefixModalProps { open: boolean; onClose: () => void; onSuccess: () => void; unitId: string; cardType: string; // e.g., "prefix", "suffix", "prefixCC", "reference", "internalPrefix", etc. recordType: PrefixTabType; editingItem?: any; positions?: any[]; } export const PrefixModal = ({ open, onClose, onSuccess, unitId, cardType, recordType, editingItem, positions = [], }: PrefixModalProps) => { const queryClient = useQueryClient(); const isEditing = !!editingItem; // Form state const [nameAm, setNameAm] = useState(""); const [nameEn, setNameEn] = useState(""); const [positionId, setPositionId] = useState(""); // Determine if this is a reference type const isReference = [ "reference", "externalReference", "internalMemoReference", ].includes(cardType); const isPositionPrefix = recordType === "positionPrefix"; const isCC = cardType.includes("CC"); const isReferenceCard = cardType === "reference"; const isExternalReferenceCard = cardType === "externalReference"; const isInternalMemoReferenceCard = cardType === "internalMemoReference"; const positionOptions = positions .filter((pos) => Boolean(pos?.id)) .map((pos) => ({ value: pos.id, label: pos.name?.en || pos.name?.am || pos.id, })); const positionRecordTypeKey = cardType === "internalPrefix" ? "internal" : cardType === "externalPrefix" ? "external" : cardType === "internalMemoPrefix" ? "internal_memo" : editingItem?.recordTypeKey; const { data: referenceNumbersData } = useGetReferenceNumbers( isReference ? unitId : "", ); const addReferenceNumberMutation = useAddReferenceNumber(); const updateInternalMemoReferenceMutation = useUpdateInternalMemoReferencePrefix(); const updateExternalReferenceMutation = useUpdateExternalReferencePrefix(); const { handleError } = useErrorHandler(t); const referenceNumbers = ((referenceNumbersData?.data as any)?.items?.[0] as any) || referenceNumbersData?.data || {}; const isArray = Array.isArray(referenceNumbers); const referenceNumberPrefix = isArray && referenceNumbers?.find((rn: any) => rn.name === "referenceNumberPrefix"); const externalReferenceNumberPrefix = isArray && referenceNumbers?.find( (rn: any) => rn.name === "externalReferenceNumberPrefix", ); const internalMemoReferenceNumberPrefix = isArray && referenceNumbers?.find( (rn: any) => rn.name === "internalMemoReferenceNumberPrefix", ); // Populate form when editing useEffect(() => { if (editingItem) { if (isReference) { setNameAm(editingItem.name?.am || ""); setNameEn(editingItem.name?.en || ""); } else { setNameAm(editingItem.name?.am || ""); setNameEn(editingItem.name?.en || ""); } setPositionId(editingItem.positionId || ""); } else { // Reset setNameAm(""); setNameEn(""); setPositionId(""); } }, [editingItem, isReference]); useEffect(() => { if (!isReference || editingItem) return; if (isReferenceCard) { setNameAm(referenceNumbers.referenceNumberPrefix || ""); setNameEn(referenceNumbers.referenceNumberPrefix || ""); return; } if (isExternalReferenceCard) { setNameAm(referenceNumbers.externalReferenceNumberPrefix || ""); setNameEn(referenceNumbers.externalReferenceNumberPrefix || ""); return; } if (isInternalMemoReferenceCard) { setNameAm(referenceNumbers.internalMemoReferenceNumberPrefix || ""); setNameEn(referenceNumbers.internalMemoReferenceNumberPrefix || ""); } }, [ editingItem, isReference, isReferenceCard, isExternalReferenceCard, isInternalMemoReferenceCard, referenceNumbers.referenceNumberPrefix, referenceNumbers.externalReferenceNumberPrefix, referenceNumbers.internalMemoReferenceNumberPrefix, ]); // Mutation for saving const { mutate: save, isPending } = useMutation({ mutationFn: async () => { const baseRecordTypeKey = recordType; const isPrefixOperation = isReference || isPositionPrefix || cardType === "prefix" || cardType === "prefixCC" || cardType === "internalPrefix" || cardType === "externalPrefix" || cardType === "internalMemoPrefix"; let prefixPayload: CreatePrefixPayload | undefined; let suffixPayload: CreateSuffixPayload | undefined; if (isReference) { if (isReferenceCard) { await addReferenceNumberMutation.mutateAsync({ unitId, payload: { referenceNumberPrefix: { am: nameAm, en: nameEn, }, }, }); return; } if (isExternalReferenceCard) { await updateExternalReferenceMutation.mutateAsync({ unitId, payload: { externalReferenceNumberPrefix: { am: nameAm, en: nameEn, }, }, }); return; } if (isInternalMemoReferenceCard) { await updateInternalMemoReferenceMutation.mutateAsync({ unitId, payload: { internalMemoReferenceNumberPrefix: { am: nameAm, en: nameEn, }, }, }); return; } } else if (isPositionPrefix) { if ( positionRecordTypeKey !== "internal" && positionRecordTypeKey !== "external" && positionRecordTypeKey !== "internal_memo" ) { throw new Error( "Position prefix requires internal, external, or internal_memo recordTypeKey", ); } prefixPayload = { unitId, recordTypeKey: positionRecordTypeKey, isForCC: false, positionId, name: { am: nameAm, en: nameEn }, }; } else { const commonPayload = { unitId, recordTypeKey: baseRecordTypeKey, isForCC: isCC, name: { am: nameAm, en: nameEn }, }; if (cardType === "suffix" || cardType === "suffixCC") { suffixPayload = commonPayload; } else { prefixPayload = commonPayload; } } if (isEditing) { if (isPrefixOperation && prefixPayload) { return prefixSuffixService.editPrefix(editingItem.id, prefixPayload); } if (suffixPayload) { return prefixSuffixService.editSuffix(editingItem.id, suffixPayload); } throw new Error("Invalid prefix/suffix payload for update"); } if (isPrefixOperation && prefixPayload) { return prefixSuffixService.createPrefix(prefixPayload); } if (suffixPayload) { return prefixSuffixService.createSuffix(suffixPayload); } throw new Error("Invalid prefix/suffix payload for create"); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["prefixSuffix"] }); toast.success(t("msg.successfullyCompleted")); onSuccess(); }, onError: (error) => { handleError(error); }, }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); save(); }; const isValid = () => { if (isReference) return nameAm.trim() !== "" && nameEn.trim() !== ""; if (isPositionPrefix) return nameAm.trim() !== "" && nameEn.trim() !== "" && positionId; return nameAm.trim() !== "" && nameEn.trim() !== ""; }; return ( {isEditing ? t("contentManagement.edit") : t("contentManagement.add")}{" "} {t(`contentManagement.${cardType}`)}
{isReference ? (
setNameAm(e.target.value)} placeholder={t("contentManagement.amharicName")} disabled={isPending} className="dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
setNameEn(e.target.value)} placeholder={t("contentManagement.englishName")} disabled={isPending} className="dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
) : ( <>
setNameAm(e.target.value)} placeholder={t("contentManagement.amharicName")} disabled={isPending} className="dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
setNameEn(e.target.value)} placeholder={t("contentManagement.englishName")} disabled={isPending} className="dark:bg-gray-700 dark:border-gray-600 dark:text-white" />
)} {isPositionPrefix && (
)}
); };