import React, { useEffect, useState } from "react"; import { Edit2Icon, Settings } from "lucide-react"; import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, } from "@/shared/common/ui/select"; import { useMyAdminOrganizations } from "@/user-management/hooks/useOrgAdminOrganizations"; import { useUnit } from "@/user-management/hooks/useUnit"; import { useUnitConfiguration } from "@/shared/hooks/useUnitConfiguration"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/shared/common/ui/table"; import { ERecordSenderInformationScope, prefixSuffixService, } from "@/user-management/services/api/prefixSuffixService"; import type { UnitConfigurationItem } from "@/user-management/services/api/prefixSuffixService"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/shared/common/ui/dialog"; import { Button } from "@/shared/common/ui/button"; import { PositionScopeToFetch, positionScopeValues, } from "./PositionConfigurationPage"; import { t } from "i18next"; import { useLocalizedName } from "@/shared/common/localizedName"; import { Switch } from "@/shared/common/ui/switch"; import { toast } from "sonner"; import type { UnitDto } from "@/user-management/dto/unit/unitDto"; const configurationCardShell = "relative overflow-hidden rounded-2xl border border-slate-200/80 bg-gradient-to-br from-white via-slate-50 to-slate-100/60 p-4 shadow-sm sm:p-6 dark:border-slate-700/80 dark:bg-gradient-to-br dark:from-slate-950 dark:via-slate-900 dark:to-slate-900"; const UnitConfigurationPage = () => { const queryClient = useQueryClient(); const localizedName = useLocalizedName(); const { getAccessibleList } = useUnit(); // Org admin: fetch only the orgs they administer const { organizations, isLoading: isLoadingOrgs } = useMyAdminOrganizations(); const [selectedOrgId, setSelectedOrgId] = useState(""); const [selectedUnitId, setSelectedUnitId] = useState(""); // Auto-select the first org on load useEffect(() => { if (organizations.length > 0 && !selectedOrgId) { setSelectedOrgId(organizations[0].id); } }, [organizations, selectedOrgId]); // Organization admins see all units; unit admins see only units they administer. const { data: unitsResponse, isLoading: isLoadingUnits } = getAccessibleList( selectedOrgId, { take: 1000, skip: 0 }, ); const units = (unitsResponse?.data?.items ?? []) as UnitDto[]; // Reset unit selection when org changes useEffect(() => { setSelectedUnitId(""); }, [selectedOrgId]); // Auto-select first unit once units load useEffect(() => { if (units.length > 0 && !selectedUnitId) { setSelectedUnitId(units[0].id); } }, [units, selectedUnitId]); const [open, setOpen] = useState(false); const [newScope, setNewScope] = useState(""); const [recordSenderInformationScope, setRecordSenderInformationScope] = useState(ERecordSenderInformationScope.NAME); const [canAssignCustomReferenceNumber, setCanAssignCustomReferenceNumber] = useState(false); const [canUseNewInternalMemoFormat, setCanUseNewInternalMemoFormat] = useState(false); const [canHaveTagBasedReferenceNumber, setCanHaveTagBasedReferenceNumber] = useState(false); const [referenceNumberCountFirst, setReferenceNumberCountFirst] = useState(false); const [canUserSkipLevel, setCanUserSkipLevel] = useState(false); const [canSendToBranch, setCanSendToBranch] = useState(false); const [ canRecordDateLabelHasLocalization, setCanRecordDateLabelHasLocalization, ] = useState(false); const [canRecordDateHaveTime, setCanRecordDateHaveTime] = useState(false); const [includeSignatureAssign, setIncludeSignatureAssign] = useState(false); const [waitForAllCollaborators, setWaitForAllCollaborators] = useState(false); const [shouldCollaboratorAlwaysSign, setShouldCollaboratorAlwaysSign] = useState(false); const [ shouldIncludeForYourReferenceInCC, setShouldIncludeForYourReferenceInCC, ] = useState(false); const [canCollaborationBeCreatedForAll, setCanCollaborationBeCreatedForAll] = useState(false); const [canCreateDirectRecord, setCanCreateDirectRecord] = useState(false); const [canCreateBankRecord, setCanCreateBankRecord] = useState(false); const [ isApprovalRequiredForPositionChange, setIsApprovalRequiredForPositionChange, ] = useState(false); const [ canPositionBasedRecordsBeCreated, setCanPositionBasedRecordsBeCreated, ] = useState(false); const [ canPositionBasedReferenceBeUsedForAllTypes, setCanPositionBasedReferenceBeUsedForAllTypes, ] = useState(false); const [ canInternalMemoRequirePositionBasedReferenceNumber, setCanInternalMemoRequirePositionBasedReferenceNumber, ] = useState(false); const [ shouldDirectRecordHaveHeaderAndFooter, setShouldDirectRecordHaveHeaderAndFooter, ] = useState(false); const [ canRecordBeEditedByCollaborators, setCanRecordBeEditedByCollaborators, ] = useState(false); const [canRecordHaveCollaboratorsName, setCanRecordHaveCollaboratorsName] = useState(false); const [canRecordBeEditedOnWorkflow, setCanRecordBeEditedOnWorkflow] = useState(false); const [ canIncomingAssignmentsBeSeparated, setcanIncomingAssignmentsBeSeparated, ] = useState(false); const [canROReturn, setCanROReturn] = useState(false); const [internalMemoHasReferenceNumber, setInternalMemoHasReferenceNumber] = useState(false); const [attachSignatureOnAttachment, setAttachSignatureOnAttachment] = useState(false); const { data, isLoading, error } = useUnitConfiguration(selectedUnitId, { enabled: !!selectedUnitId, }); const config: UnitConfigurationItem | undefined = data?.data?.items?.[0]; const [IsLoading, setIsLoading] = useState(false); useEffect(() => { if (config) { setCanAssignCustomReferenceNumber( config.canAssignCustomReferenceNumber || false, ); setRecordSenderInformationScope( (config.recordSenderInformationScope as ERecordSenderInformationScope) || ERecordSenderInformationScope.NAME, ); setCanUseNewInternalMemoFormat( config.canInternalMemosHaveSenderInformation || false, ); setCanRecordDateLabelHasLocalization( config.canRecordDateLabelHasLocalization || false, ); setCanRecordDateHaveTime(config.canRecordDateHaveTime || false); setIncludeSignatureAssign(config.forwardWithTeeterSignature || false); setWaitForAllCollaborators( config.waitAllCollaboratorsBeforeAction || false, ); setShouldCollaboratorAlwaysSign( config.shouldCollaboratorAlwaysSign || false, ); setShouldIncludeForYourReferenceInCC( config.shouldIncludeForYourReferenceInCC || false, ); setCanCollaborationBeCreatedForAll( config.canCollaborationBeCreatedForAll || false, ); setCanCreateDirectRecord(config.canCreateDirectRecord || false); setCanCreateBankRecord(config.canCreateBankRelatedRecords || false); setIsApprovalRequiredForPositionChange( config.isApprovalRequiredForPositionChange || false, ); setCanPositionBasedRecordsBeCreated( config.canPositionBasedRecordsBeCreated || false, ); setCanPositionBasedReferenceBeUsedForAllTypes( config.canPositionBasedReferenceBeUsedForAllTypes || false, ); setShouldDirectRecordHaveHeaderAndFooter( config.shouldDirectRecordHaveHeaderAndFooter || false, ); setCanInternalMemoRequirePositionBasedReferenceNumber( config.canInternalMemoRequirePositionBasedReferenceNumber || false, ); setCanRecordBeEditedByCollaborators( config.canRecordBeEditedByCollaborators || false, ); setCanRecordHaveCollaboratorsName( config.canRecordHaveCollaboratorsName || false, ); setCanRecordBeEditedOnWorkflow( config.canRecordBeEditedOnWorkflow || false, ); setcanIncomingAssignmentsBeSeparated( config.canIncomingAssignmentsBeSeparated || false, ); setCanROReturn(config.canROReturn || false); setInternalMemoHasReferenceNumber( config.internalMemoHasReferenceNumber || false, ); setAttachSignatureOnAttachment( config.attachSignatureOnAttachment || false, ); setCanHaveTagBasedReferenceNumber( config.canHaveTagBasedReferenceNumber || false, ); setReferenceNumberCountFirst(config.referenceNumberCountFirst || false); setCanUserSkipLevel(config.canUserSkipLevel || false); setCanSendToBranch(config.canSendToBranch || false); } }, [config]); const handleCanHaveTagBasedReferenceNumberToggle = (checked: boolean) => { if (!config?.id) return; setCanHaveTagBasedReferenceNumber(checked); updateCanHaveTagBasedReferenceNumber({ id: config.id, value: checked, }); }; const handleReferenceNumberCountFirstToggle = (checked: boolean) => { if (!config?.id) return; setReferenceNumberCountFirst(checked); updateReferenceNumberCountFirst({ id: config.id, value: checked, }); }; const handleCanUserSkipLevelToggle = (checked: boolean) => { if (!config?.id) return; setCanUserSkipLevel(checked); updateCanUserSkipLevel({ id: config.id, value: checked, }); }; const handleCanSendToBranchToggle = (checked: boolean) => { if (!config?.id) return; setCanSendToBranch(checked); updateCanSendToBranch({ id: config.id, value: checked, }); }; const { mutate: updateCanHaveTagBasedReferenceNumber, isPending: isUpdatingCanHaveTagBasedReferenceNumber, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canHaveTagBasedReferenceNumber: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canHaveTagBasedReferenceNumber", "Can Have Tag Based Reference Number")} ${ canHaveTagBasedReferenceNumber ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateReferenceNumberCountFirst, isPending: isUpdatingReferenceNumberCountFirst, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { referenceNumberCountFirst: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t( "setting.referenceNumberCountFirst", "Should The Number Count Come First On The Reference Number", )} ${referenceNumberCountFirst ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanUserSkipLevel, isPending: isUpdatingCanUserSkipLevel, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canUserSkipLevel: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canUserSkipLevel", "User Can Skip Level")} ${ canUserSkipLevel ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanSendToBranch, isPending: isUpdatingCanSendToBranch, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canSendToBranch: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canSendToBranch", "Can Send to Branch")} ${ canSendToBranch ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateRecordSenderInformationScope, isPending: isUpdatingRecordSenderInformationScope, } = useMutation({ mutationFn: ({ id, scope, }: { id: string; scope: ERecordSenderInformationScope; }) => prefixSuffixService.updateInternalPrefixSuffix( { recordSenderInformationScope: scope, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.recordSenderInformationScope", "Record Sender Information Scope")} updated`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanAssignCustomReferenceNumber, isPending: isUpdatingCanAssignCustomReferenceNumber, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canAssignCustomReferenceNumber: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canAssignCustomReferenceNumber")} ${ canAssignCustomReferenceNumber ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanUseNewInternalMemoFormat, isPending: isUpdatingCanUseNewInternalMemoFormat, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canInternalMemosHaveSenderInformation: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canUseNewInternalMemoFormat")} ${ canUseNewInternalMemoFormat ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanRecordDateLabelHasLocalization, isPending: isUpdatingCanRecordDateLabelHasLocalization, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canRecordDateLabelHasLocalization: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canRecordDateLabelHasLocalization")} ${ canRecordDateLabelHasLocalization ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanRecordDateHaveTime, isPending: isUpdatingCanRecordDateHaveTime, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canRecordDateHaveTime: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canRecordDateHaveTime", "Record Date Can Have Time")} ${ canRecordDateHaveTime ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); // mutation for updating scope const { mutate: updateScope, isPending: isUpdating } = useMutation({ mutationFn: ({ id, scope }: { id: string; scope: string }) => prefixSuffixService.updateInternalPrefixSuffix( { positionScopeToFetch: scope, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); setOpen(false); // close modal }, onError: (err) => { console.error("Failed to update scope", err); }, }); // mutation for updating signature const { mutate: updateSignature, isPending: isUpdatingSignature } = useMutation({ mutationFn: ({ id, signature }: { id: string; signature: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { forwardWithTeeterSignature: signature, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `Signature & Teeter ${includeSignatureAssign ? "enabled" : "disabled"}`, ); }, onError: (err) => { console.error("Failed to update signature", err); }, }); const { mutate: updateCollaboratorWait, isPending: isUpdatingCollaboratorWait, } = useMutation({ mutationFn: ({ id, wait }: { id: string; wait: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { waitAllCollaboratorsBeforeAction: wait, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.title6")} ${waitForAllCollaborators ? "enabled" : "disabled"}`, ); }, onError: (err) => { console.error("Failed to update collaborator wait setting", err); }, }); // Open modal and pre-fill value const handleEdit = () => { if (!config?.id) return; setNewScope(config.positionScopeToFetch as PositionScopeToFetch); setOpen(true); }; const handleSave = () => { if (!config?.id) return; if (newScope && newScope !== config.positionScopeToFetch) { updateScope({ id: config.id, scope: newScope }); } }; const handleToggle = (checked: boolean) => { if (!config?.id) return; setIncludeSignatureAssign(checked); updateSignature({ id: config.id, signature: checked }); }; const handleCanAssignCustomReferenceNumberToggle = (checked: boolean) => { if (!config?.id) return; setCanAssignCustomReferenceNumber(checked); updateCanAssignCustomReferenceNumber({ id: config.id, value: checked, }); }; const handleCanUseNewInternalMemoFormatToggle = (checked: boolean) => { if (!config?.id) return; setCanUseNewInternalMemoFormat(checked); updateCanUseNewInternalMemoFormat({ id: config.id, value: checked, }); }; const handleCanRecordDateLabelHasLocalizationToggle = (checked: boolean) => { if (!config?.id) return; setCanRecordDateLabelHasLocalization(checked); updateCanRecordDateLabelHasLocalization({ id: config.id, value: checked, }); }; const handleCanRecordDateHaveTimeToggle = (checked: boolean) => { if (!config?.id) return; setCanRecordDateHaveTime(checked); updateCanRecordDateHaveTime({ id: config.id, value: checked, }); }; const handleCollaboratorWaitToggle = (checked: boolean) => { if (!config?.id) return; setWaitForAllCollaborators(checked); updateCollaboratorWait({ id: config.id, wait: checked }); }; const { mutate: updateCollaboratorAlwaysSign, isPending: isUpdatingCollaboratorAlwaysSign, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { shouldCollaboratorAlwaysSign: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.shouldCollaboratorAlwaysSign")} ${shouldCollaboratorAlwaysSign ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateIncludeForYourReference, isPending: isUpdatingIncludeForYourReference, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { shouldIncludeForYourReferenceInCC: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.shouldIncludeForYourReferenceInCC")} ${shouldIncludeForYourReferenceInCC ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCollaboratorAlwaysSignToggle = (checked: boolean) => { if (!config?.id) return; setShouldCollaboratorAlwaysSign(checked); updateCollaboratorAlwaysSign({ id: config.id, value: checked }); }; const handleRecordSenderInformationScopeToggle = ( scope: ERecordSenderInformationScope, ) => { if (!config?.id) return; setRecordSenderInformationScope(scope); updateRecordSenderInformationScope({ id: config.id, scope }); }; const handleIncludeForYourReferenceToggle = (checked: boolean) => { if (!config?.id) return; setShouldIncludeForYourReferenceInCC(checked); updateIncludeForYourReference({ id: config.id, value: checked }); }; const { mutate: updateCanCollaborationBeCreatedForAll, isPending: isUpdatingCanCollaborationBeCreatedForAll, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canCollaborationBeCreatedForAll: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canCollaborationBeCreatedForAll")} ${ canCollaborationBeCreatedForAll ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanCollaborationBeCreatedForAllToggle = (checked: boolean) => { if (!config?.id) return; setCanCollaborationBeCreatedForAll(checked); updateCanCollaborationBeCreatedForAll({ id: config.id, value: checked }); }; const { mutate: updateCanCreateDirectRecord, isPending: isUpdatingCanCreateDirectRecord, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canCreateDirectRecord: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canCreateDirectRecord")} ${canCreateDirectRecord ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update direct record creation setting", err), }); const handleCanCreateDirectRecordToggle = (checked: boolean) => { if (!config?.id) return; setCanCreateDirectRecord(checked); updateCanCreateDirectRecord({ id: config.id, value: checked }); }; const { mutate: updateCanCreateBankRecord, isPending: isUpdatingCanCreateBankRecord, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canCreateBankRelatedRecords: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canCreateBankRecord")} ${canCreateBankRecord ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update bank record creation setting", err), }); const handleCanCreateBankRecordToggle = (checked: boolean) => { if (!config?.id) return; setCanCreateBankRecord(checked); updateCanCreateBankRecord({ id: config.id, value: checked }); }; const { mutate: updateIsApprovalRequiredForPositionChange, isPending: isUpdatingIsApprovalRequiredForPositionChange, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { isApprovalRequiredForPositionChange: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.isApprovalRequiredForPositionChange")} ${ isApprovalRequiredForPositionChange ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update position change approval setting", err), }); const handleIsApprovalRequiredForPositionChangeToggle = ( checked: boolean, ) => { if (!config?.id) return; setIsApprovalRequiredForPositionChange(checked); updateIsApprovalRequiredForPositionChange({ id: config.id, value: checked, }); }; const { mutate: updateCanPositionBasedRecordsBeCreated, isPending: isUpdatingCanPositionBasedRecordsBeCreated, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canPositionBasedRecordsBeCreated: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canPositionBasedRecordsBeCreated")} ${ canPositionBasedRecordsBeCreated ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error( "Failed to update position-based record creation setting", err, ), }); const handleCanPositionBasedRecordsBeCreatedToggle = (checked: boolean) => { if (!config?.id) return; setCanPositionBasedRecordsBeCreated(checked); updateCanPositionBasedRecordsBeCreated({ id: config.id, value: checked }); }; const { mutate: updateCanPositionBasedReferenceBeUsedForAllTypes, isPending: isUpdatingCanPositionBasedReferenceBeUsedForAllTypes, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canPositionBasedReferenceBeUsedForAllTypes: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canPositionBasedReferenceBeUsedForAllTypes")} ${ canPositionBasedReferenceBeUsedForAllTypes ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error( "Failed to update position-based reference usage setting", err, ), }); const handleCanPositionBasedReferenceBeUsedForAllTypesToggle = ( checked: boolean, ) => { if (!config?.id) return; setCanPositionBasedReferenceBeUsedForAllTypes(checked); updateCanPositionBasedReferenceBeUsedForAllTypes({ id: config.id, value: checked, }); }; const { mutate: updateShouldDirectRecordHaveHeaderAndFooter, isPending: isUpdatingShouldDirectRecordHaveHeaderAndFooter, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { shouldDirectRecordHaveHeaderAndFooter: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.shouldDirectRecordHaveHeaderAndFooter")} ${ shouldDirectRecordHaveHeaderAndFooter ? t("setting.enabled") : t("setting.disabled") }`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleShouldDirectRecordHaveHeaderAndFooterToggle = ( checked: boolean, ) => { if (!config?.id) return; setShouldDirectRecordHaveHeaderAndFooter(checked); updateShouldDirectRecordHaveHeaderAndFooter({ id: config.id, value: checked, }); }; const { mutate: updateCanRecordBeEditedByCollaborators, isPending: isUpdatingCanRecordBeEditedByCollaborators, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canRecordBeEditedByCollaborators: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canRecordBeEditedByCollaborators")} ${canRecordBeEditedByCollaborators ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanRecordBeEditedByCollaboratorsToggle = (checked: boolean) => { if (!config?.id) return; setCanRecordBeEditedByCollaborators(checked); updateCanRecordBeEditedByCollaborators({ id: config.id, value: checked }); }; const { mutate: updateCanRecordHaveCollaboratorsName, isPending: isUpdatingCanRecordHaveCollaboratorsName, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canRecordHaveCollaboratorsName: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canRecordHaveCollaboratorsName")} ${canRecordHaveCollaboratorsName ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanRecordHaveCollaboratorsNameToggle = (checked: boolean) => { if (!config?.id) return; setCanRecordHaveCollaboratorsName(checked); updateCanRecordHaveCollaboratorsName({ id: config.id, value: checked }); }; const { mutate: updateCanRecordBeEditedOnWorkflow, isPending: isUpdatingCanRecordBeEditedOnWorkflow, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canRecordBeEditedOnWorkflow: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canRecordBeEditedOnWorkflow")} ${canRecordBeEditedOnWorkflow ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updatecanIncomingAssignmentsBeSeparated, isPending: isUpdatingcanIncomingAssignmentsBeSeparated, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canIncomingAssignmentsBeSeparated: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canIncomingAssignmentsBeSeparated")} ${canIncomingAssignmentsBeSeparated ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanRecordBeEditedOnWorkflowToggle = (checked: boolean) => { if (!config?.id) return; setCanRecordBeEditedOnWorkflow(checked); updateCanRecordBeEditedOnWorkflow({ id: config.id, value: checked }); }; const handlecanIncomingAssignmentsBeSeparatedToggle = (checked: boolean) => { if (!config?.id) return; setcanIncomingAssignmentsBeSeparated(checked); updatecanIncomingAssignmentsBeSeparated({ id: config.id, value: checked }); }; const { mutate: updateCanROReturn, isPending: isUpdatingCanROReturn } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canROReturn: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.canROReturn")} ${canROReturn ? "enabled" : "disabled"}`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanROReturnToggle = (checked: boolean) => { if (!config?.id) return; setCanROReturn(checked); updateCanROReturn({ id: config.id, value: checked }); }; const { mutate: updateInternalMemoHasReferenceNumber, isPending: isUpdatingInternalMemoHasReferenceNumber, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { internalMemoHasReferenceNumber: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.internalMemoHasReferenceNumber")} ${ internalMemoHasReferenceNumber ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const { mutate: updateCanInternalMemoRequirePositionBasedReferenceNumber, isPending: isUpdatingCanInternalMemoRequirePositionBasedReferenceNumber, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { canInternalMemoRequirePositionBasedReferenceNumber: value, unitId: selectedUnitId, }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t( "setting.canInternalMemoRequirePositionBasedReferenceNumber", "Internal Memo Require Position Based Reference Number", )} ${ canInternalMemoRequirePositionBasedReferenceNumber ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleCanInternalMemoRequirePositionBasedReferenceNumberToggle = ( checked: boolean, ) => { if (!config?.id) return; setCanInternalMemoRequirePositionBasedReferenceNumber(checked); updateCanInternalMemoRequirePositionBasedReferenceNumber({ id: config.id, value: checked, }); }; const handleInternalMemoHasReferenceNumberToggle = (checked: boolean) => { if (!config?.id) return; setInternalMemoHasReferenceNumber(checked); updateInternalMemoHasReferenceNumber({ id: config.id, value: checked }); }; const { mutate: updateAttachSignatureOnAttachment, isPending: isUpdatingAttachSignatureOnAttachment, } = useMutation({ mutationFn: ({ id, value }: { id: string; value: boolean }) => prefixSuffixService.updateInternalPrefixSuffix( { attachSignatureOnAttachment: value, unitId: selectedUnitId }, id, ), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); toast.success( `${t("setting.attachSignatureOnAttachment", "Attach Signature On Attachment")} ${ attachSignatureOnAttachment ? "enabled" : "disabled" }`, ); }, onError: (err) => console.error("Failed to update", err), }); const handleAttachSignatureOnAttachmentToggle = (checked: boolean) => { if (!config?.id) return; setAttachSignatureOnAttachment(checked); updateAttachSignatureOnAttachment({ id: config.id, value: checked }); }; const { mutate: createConfig, isPending: isCreatingConfig } = useMutation({ mutationFn: (unitId: string) => prefixSuffixService.createInternalPrefixSuffix({ unitId }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["unitConfig", selectedUnitId], }); }, onError: (err) => { console.error("Failed to create unit configuration", err); }, }); // Auto-create an empty configuration when a unit has none, so the settings // table renders immediately with all toggles off instead of an empty state. useEffect(() => { if ( !config && !isLoading && !error && selectedUnitId && !isCreatingConfig ) { createConfig(selectedUnitId); } }, [ config, isLoading, error, selectedUnitId, isCreatingConfig, createConfig, ]); return (

{t("setting.title1")}

{t("setting.title2")}

{/* Organization selector */} {/* Unit selector */}
{isLoading && (

Loading configuration...

)} {error && (

Failed to load configuration

)} {!config && !isLoading && !error && (

{isCreatingConfig ? t( "setting.preparingDefaults", "Preparing default configuration...", ) : t("setting.loading", "Loading...")}

)} {config && (
{t("setting.Name")} {t("setting.Value")} {t("setting.Action")} {t("setting.title3")} {config.positionScopeToFetch} {t("setting.title5")} {config.forwardWithTeeterSignature ? "Yes" : "No"} {t("setting.title6")} {config.waitAllCollaboratorsBeforeAction ? "Yes" : "No"} {t( "setting.canAssignCustomReferenceNumber", "Can Assign Custom Reference Number", )} {config.canAssignCustomReferenceNumber ? "Yes" : "No"} {t( "setting.canUseNewInternalMemoFormat", "New Internal Memo Format", )} {config.canInternalMemosHaveSenderInformation ? "Yes" : "No"} {canUseNewInternalMemoFormat && ( {t( "setting.recordSenderInformationScope", "Record Sender Information Scope", )} {config.recordSenderInformationScope || "NAME"} )} {t( "setting.canRecordDateLabelHasLocalization", "Does Record Date Label Have Localization?", )} {config.canRecordDateLabelHasLocalization ? "Yes" : "No"} {t( "setting.canRecordDateHaveTime", "Record Date Can Have Time", )} {config.canRecordDateHaveTime ? "Yes" : "No"} {t("setting.canCreateDirectRecord")} {config.canCreateDirectRecord ? t("common.yes") : t("common.no")} {t("setting.canCreateBankRecord")} {config.canCreateBankRelatedRecords ? t("common.yes") : t("common.no")} {t("setting.isApprovalRequiredForPositionChange")} {config.isApprovalRequiredForPositionChange ? t("common.yes") : t("common.no")} {t("setting.canPositionBasedRecordsBeCreated")} {config.canPositionBasedRecordsBeCreated ? t("common.yes") : t("common.no")} {t("setting.canPositionBasedReferenceBeUsedForAllTypes")} {config.canPositionBasedReferenceBeUsedForAllTypes ? t("common.yes") : t("common.no")} {t( "setting.canInternalMemoRequirePositionBasedReferenceNumber", "Internal Memo Require Position Based Reference Number", )} {config.canInternalMemoRequirePositionBasedReferenceNumber ? "Yes" : "No"} {t("setting.shouldDirectRecordHaveHeaderAndFooter")} {config.shouldDirectRecordHaveHeaderAndFooter ? t("common.yes") : t("common.no")} {t("setting.shouldCollaboratorAlwaysSign")} {config.shouldCollaboratorAlwaysSign ? "Yes" : "No"} {t("setting.shouldIncludeForYourReferenceInCC")} {config.shouldIncludeForYourReferenceInCC ? "Yes" : "No"} {t("setting.canCollaborationBeCreatedForAll")} {config.canCollaborationBeCreatedForAll ? "Yes" : "No"} {t("setting.canRecordBeEditedByCollaborators")} {config.canRecordBeEditedByCollaborators ? "Yes" : "No"} {t("setting.canRecordHaveCollaboratorsName")} {config.canRecordHaveCollaboratorsName ? "Yes" : "No"} {t("setting.canRecordBeEditedOnWorkflow")} {config.canRecordBeEditedOnWorkflow ? "Yes" : "No"} {t("setting.canIncomingAssignmentsBeSeparated")} {config.canIncomingAssignmentsBeSeparated ? "Yes" : "No"} {t("setting.canROReturn")} {config.canROReturn ? "Yes" : "No"} {t("setting.internalMemoHasReferenceNumber")} {config.internalMemoHasReferenceNumber ? "Yes" : "No"} {t( "setting.attachSignatureOnAttachment", "Attach Signature On Attachment", )} {config.attachSignatureOnAttachment ? "Yes" : "No"} {t( "setting.canHaveTagBasedReferenceNumber", "Can Have Tag Based Reference Number", )} {config.canHaveTagBasedReferenceNumber ? "Yes" : "No"} {t( "setting.referenceNumberCountFirst", "Should The Number Count Come First On The Reference Number", )} {config.referenceNumberCountFirst ? "Yes" : "No"} {t("setting.canUserSkipLevel", "User Can Skip Level")} {config.canUserSkipLevel ? "Yes" : "No"} {t( "setting.canSendToBranch", "User Can Send to Branch Departments Directly", )} {config.canUserSkipLevel ? "Yes" : "No"}
)}
{/* Modal for editing */} {t("setting.editTitle")} {t("setting.editMsg")}
); }; export default UnitConfigurationPage;