mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 02:30:55 +00:00
1938 lines
70 KiB
TypeScript
1938 lines
70 KiB
TypeScript
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>(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 (
|
|
<div className={configurationCardShell}>
|
|
<div className="mb-5 flex flex-col gap-4 border-b border-slate-200 pb-4 dark:border-slate-700 sm:flex-row sm:items-start sm:justify-between">
|
|
<div className="space-y-1">
|
|
<h1 className="flex items-center gap-2 text-2xl font-bold text-slate-900 sm:text-3xl dark:text-slate-100">
|
|
<Settings className="h-8 w-8 text-primary" />
|
|
{t("setting.title1")}
|
|
</h1>
|
|
<p className="text-sm text-slate-600 dark:text-slate-400">
|
|
{t("setting.title2")}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-2 sm:ml-auto sm:flex-row sm:items-center">
|
|
{/* Organization selector */}
|
|
<Select
|
|
value={selectedOrgId}
|
|
onValueChange={(value) => setSelectedOrgId(value)}
|
|
>
|
|
<SelectTrigger className="h-10 w-full bg-white/90 dark:border-slate-700 dark:bg-slate-900 sm:w-36 [&>span]:truncate">
|
|
<SelectValue
|
|
placeholder={
|
|
t("organization.selectOrganization") || "Select organization"
|
|
}
|
|
/>
|
|
</SelectTrigger>
|
|
<SelectContent
|
|
position="popper"
|
|
align="end"
|
|
className="dark:border-slate-700 dark:bg-slate-900"
|
|
>
|
|
{isLoadingOrgs ? (
|
|
<SelectItem value="loading" disabled>
|
|
{t("setting.loading")}
|
|
</SelectItem>
|
|
) : organizations.length > 0 ? (
|
|
organizations.map((org) => (
|
|
<SelectItem key={org.id} value={org.id}>
|
|
<span className="block truncate max-w-70">
|
|
{localizedName(org.name as { am: string; en: string })}
|
|
</span>
|
|
</SelectItem>
|
|
))
|
|
) : (
|
|
<SelectItem value="no-orgs" disabled>
|
|
{t("organization.noOrganizationsFound") ||
|
|
"No organizations found"}
|
|
</SelectItem>
|
|
)}
|
|
</SelectContent>
|
|
</Select>
|
|
|
|
{/* Unit selector */}
|
|
<Select
|
|
value={selectedUnitId}
|
|
onValueChange={(value) => setSelectedUnitId(value)}
|
|
disabled={!selectedOrgId}
|
|
>
|
|
<SelectTrigger className="h-10 w-full bg-white/90 dark:border-slate-700 dark:bg-slate-900 sm:w-36 [&>span]:truncate">
|
|
<SelectValue
|
|
placeholder={t("organization.selectUnit") || "Select a unit"}
|
|
/>
|
|
</SelectTrigger>
|
|
<SelectContent
|
|
position="popper"
|
|
align="end"
|
|
className="dark:border-slate-700 dark:bg-slate-900"
|
|
>
|
|
{isLoadingUnits ? (
|
|
<SelectItem value="loading" disabled>
|
|
{t("setting.loading")}
|
|
</SelectItem>
|
|
) : units.length > 0 ? (
|
|
units.map((unit) => (
|
|
<SelectItem key={unit.id} value={unit.id}>
|
|
<span className="block truncate max-w-70">
|
|
{localizedName(unit.name as { am: string; en: string })}
|
|
</span>
|
|
</SelectItem>
|
|
))
|
|
) : (
|
|
<SelectItem value="no-units" disabled>
|
|
{t("setting.noUnit")}
|
|
</SelectItem>
|
|
)}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-3">
|
|
{isLoading && (
|
|
<p className="text-sm text-slate-600 dark:text-slate-300">
|
|
Loading configuration...
|
|
</p>
|
|
)}
|
|
{error && (
|
|
<p className="text-sm text-red-600 dark:text-red-400">
|
|
Failed to load configuration
|
|
</p>
|
|
)}
|
|
{!config && !isLoading && !error && (
|
|
<p className="text-sm text-slate-600 dark:text-slate-300">
|
|
{isCreatingConfig
|
|
? t(
|
|
"setting.preparingDefaults",
|
|
"Preparing default configuration...",
|
|
)
|
|
: t("setting.loading", "Loading...")}
|
|
</p>
|
|
)}
|
|
|
|
{config && (
|
|
<div className="max-h-128 overflow-x-auto overflow-y-auto rounded-xl border border-slate-200 bg-white/90 dark:border-slate-700 dark:bg-slate-900/70">
|
|
<Table>
|
|
<TableHeader className="sticky top-0 z-10 bg-white/95 backdrop-blur dark:bg-slate-900/95">
|
|
<TableRow className="dark:border-slate-700">
|
|
<TableHead className="text-slate-600 dark:text-slate-300">
|
|
{t("setting.Name")}
|
|
</TableHead>
|
|
<TableHead className="text-slate-600 dark:text-slate-300">
|
|
{t("setting.Value")}
|
|
</TableHead>
|
|
<TableHead className="text-right text-slate-600 dark:text-slate-300">
|
|
{t("setting.Action")}
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
<TableRow className="dark:border-slate-700">
|
|
<TableCell className="font-medium text-slate-900 dark:text-slate-100">
|
|
{t("setting.title3")}
|
|
</TableCell>
|
|
<TableCell className="text-slate-700 dark:text-slate-300">
|
|
{config.positionScopeToFetch}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Button
|
|
onClick={handleEdit}
|
|
variant="outline"
|
|
size="sm"
|
|
className="dark:border-slate-700 dark:bg-slate-900 dark:hover:bg-slate-800"
|
|
>
|
|
<Edit2Icon className="h-4 w-4" />
|
|
</Button>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow className="dark:border-slate-700">
|
|
<TableCell className="font-medium text-slate-900 dark:text-slate-100">
|
|
{t("setting.title5")}
|
|
</TableCell>
|
|
<TableCell className="text-slate-700 dark:text-slate-300">
|
|
{config.forwardWithTeeterSignature ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="add-teeter-assign"
|
|
checked={includeSignatureAssign}
|
|
onCheckedChange={handleToggle}
|
|
disabled={isUpdatingSignature}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow className="dark:border-slate-700">
|
|
<TableCell className="font-medium text-slate-900 dark:text-slate-100">
|
|
{t("setting.title6")}
|
|
</TableCell>
|
|
<TableCell className="text-slate-700 dark:text-slate-300">
|
|
{config.waitAllCollaboratorsBeforeAction ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="wait-for-all-collaborators-before-action"
|
|
checked={waitForAllCollaborators}
|
|
onCheckedChange={handleCollaboratorWaitToggle}
|
|
disabled={isUpdatingCollaboratorWait}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canAssignCustomReferenceNumber",
|
|
"Can Assign Custom Reference Number",
|
|
)}
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
{config.canAssignCustomReferenceNumber ? "Yes" : "No"}
|
|
</TableCell>
|
|
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-assign-custom-reference-number"
|
|
checked={canAssignCustomReferenceNumber}
|
|
onCheckedChange={
|
|
handleCanAssignCustomReferenceNumberToggle
|
|
}
|
|
disabled={isUpdatingCanAssignCustomReferenceNumber}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canUseNewInternalMemoFormat",
|
|
"New Internal Memo Format",
|
|
)}
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
{config.canInternalMemosHaveSenderInformation
|
|
? "Yes"
|
|
: "No"}
|
|
</TableCell>
|
|
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-use-new-internal-memo-format"
|
|
checked={canUseNewInternalMemoFormat}
|
|
onCheckedChange={handleCanUseNewInternalMemoFormatToggle}
|
|
disabled={isUpdatingCanUseNewInternalMemoFormat}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
{canUseNewInternalMemoFormat && (
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.recordSenderInformationScope",
|
|
"Record Sender Information Scope",
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.recordSenderInformationScope || "NAME"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Select
|
|
value={recordSenderInformationScope}
|
|
onValueChange={(value) =>
|
|
handleRecordSenderInformationScopeToggle(
|
|
value as ERecordSenderInformationScope,
|
|
)
|
|
}
|
|
disabled={isUpdatingRecordSenderInformationScope}
|
|
>
|
|
<SelectTrigger className="w-40 dark:border-slate-700 dark:bg-slate-900">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent className="dark:border-slate-700 dark:bg-slate-900">
|
|
<SelectItem
|
|
value={ERecordSenderInformationScope.NAME}
|
|
>
|
|
Name
|
|
</SelectItem>
|
|
<SelectItem
|
|
value={ERecordSenderInformationScope.SIGNATURE}
|
|
>
|
|
Signature
|
|
</SelectItem>
|
|
<SelectItem
|
|
value={ERecordSenderInformationScope.STAMP}
|
|
>
|
|
Stamp
|
|
</SelectItem>
|
|
<SelectItem
|
|
value={
|
|
ERecordSenderInformationScope.NAME_AND_SIGNATURE
|
|
}
|
|
>
|
|
Name & Signature
|
|
</SelectItem>
|
|
<SelectItem
|
|
value={ERecordSenderInformationScope.NAME_AND_STAMP}
|
|
>
|
|
Name & Stamp
|
|
</SelectItem>
|
|
<SelectItem
|
|
value={
|
|
ERecordSenderInformationScope.SIGNATURE_AND_STAMP
|
|
}
|
|
>
|
|
SIGNATURE & Stamp
|
|
</SelectItem>
|
|
<SelectItem value={ERecordSenderInformationScope.ALL}>
|
|
All
|
|
</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canRecordDateLabelHasLocalization",
|
|
"Does Record Date Label Have Localization?",
|
|
)}
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
{config.canRecordDateLabelHasLocalization ? "Yes" : "No"}
|
|
</TableCell>
|
|
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-record-date-label-has-localization"
|
|
checked={canRecordDateLabelHasLocalization}
|
|
onCheckedChange={
|
|
handleCanRecordDateLabelHasLocalizationToggle
|
|
}
|
|
disabled={isUpdatingCanRecordDateLabelHasLocalization}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canRecordDateHaveTime",
|
|
"Record Date Can Have Time",
|
|
)}
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
{config.canRecordDateHaveTime ? "Yes" : "No"}
|
|
</TableCell>
|
|
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-record-date-have-time"
|
|
checked={canRecordDateHaveTime}
|
|
onCheckedChange={handleCanRecordDateHaveTimeToggle}
|
|
disabled={isUpdatingCanRecordDateHaveTime}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canCreateDirectRecord")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canCreateDirectRecord
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-create-direct-record"
|
|
checked={canCreateDirectRecord}
|
|
onCheckedChange={handleCanCreateDirectRecordToggle}
|
|
disabled={isUpdatingCanCreateDirectRecord}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canCreateBankRecord")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canCreateBankRelatedRecords
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-create-bank-record"
|
|
checked={canCreateBankRecord}
|
|
onCheckedChange={handleCanCreateBankRecordToggle}
|
|
disabled={isUpdatingCanCreateBankRecord}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.isApprovalRequiredForPositionChange")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.isApprovalRequiredForPositionChange
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="is-approval-required-for-position-change"
|
|
checked={isApprovalRequiredForPositionChange}
|
|
onCheckedChange={
|
|
handleIsApprovalRequiredForPositionChangeToggle
|
|
}
|
|
disabled={isUpdatingIsApprovalRequiredForPositionChange}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canPositionBasedRecordsBeCreated")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canPositionBasedRecordsBeCreated
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-position-based-records-be-created"
|
|
checked={canPositionBasedRecordsBeCreated}
|
|
onCheckedChange={
|
|
handleCanPositionBasedRecordsBeCreatedToggle
|
|
}
|
|
disabled={isUpdatingCanPositionBasedRecordsBeCreated}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canPositionBasedReferenceBeUsedForAllTypes")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canPositionBasedReferenceBeUsedForAllTypes
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-position-based-reference-be-used-for-all-types"
|
|
checked={canPositionBasedReferenceBeUsedForAllTypes}
|
|
onCheckedChange={
|
|
handleCanPositionBasedReferenceBeUsedForAllTypesToggle
|
|
}
|
|
disabled={
|
|
isUpdatingCanPositionBasedReferenceBeUsedForAllTypes
|
|
}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canInternalMemoRequirePositionBasedReferenceNumber",
|
|
"Internal Memo Require Position Based Reference Number",
|
|
)}
|
|
</TableCell>
|
|
|
|
<TableCell>
|
|
{config.canInternalMemoRequirePositionBasedReferenceNumber
|
|
? "Yes"
|
|
: "No"}
|
|
</TableCell>
|
|
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-internal-memo-require-position-based-reference-number"
|
|
checked={
|
|
canInternalMemoRequirePositionBasedReferenceNumber
|
|
}
|
|
onCheckedChange={
|
|
handleCanInternalMemoRequirePositionBasedReferenceNumberToggle
|
|
}
|
|
disabled={
|
|
isUpdatingCanInternalMemoRequirePositionBasedReferenceNumber
|
|
}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.shouldDirectRecordHaveHeaderAndFooter")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.shouldDirectRecordHaveHeaderAndFooter
|
|
? t("common.yes")
|
|
: t("common.no")}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="should-direct-record-have-header-and-footer"
|
|
checked={shouldDirectRecordHaveHeaderAndFooter}
|
|
onCheckedChange={
|
|
handleShouldDirectRecordHaveHeaderAndFooterToggle
|
|
}
|
|
disabled={isUpdatingShouldDirectRecordHaveHeaderAndFooter}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.shouldCollaboratorAlwaysSign")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.shouldCollaboratorAlwaysSign ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="should-collaborator-always-sign"
|
|
checked={shouldCollaboratorAlwaysSign}
|
|
onCheckedChange={handleCollaboratorAlwaysSignToggle}
|
|
disabled={isUpdatingCollaboratorAlwaysSign}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.shouldIncludeForYourReferenceInCC")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.shouldIncludeForYourReferenceInCC ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="should-include-for-your-reference"
|
|
checked={shouldIncludeForYourReferenceInCC}
|
|
onCheckedChange={handleIncludeForYourReferenceToggle}
|
|
disabled={isUpdatingIncludeForYourReference}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canCollaborationBeCreatedForAll")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canCollaborationBeCreatedForAll ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-collaboration-be-created-for-all"
|
|
checked={canCollaborationBeCreatedForAll}
|
|
onCheckedChange={
|
|
handleCanCollaborationBeCreatedForAllToggle
|
|
}
|
|
disabled={isUpdatingCanCollaborationBeCreatedForAll}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canRecordBeEditedByCollaborators")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canRecordBeEditedByCollaborators ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-record-be-edited-by-collaborators"
|
|
checked={canRecordBeEditedByCollaborators}
|
|
onCheckedChange={
|
|
handleCanRecordBeEditedByCollaboratorsToggle
|
|
}
|
|
disabled={isUpdatingCanRecordBeEditedByCollaborators}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canRecordHaveCollaboratorsName")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canRecordHaveCollaboratorsName ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-record-have-collaborators-name"
|
|
checked={canRecordHaveCollaboratorsName}
|
|
onCheckedChange={
|
|
handleCanRecordHaveCollaboratorsNameToggle
|
|
}
|
|
disabled={isUpdatingCanRecordHaveCollaboratorsName}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canRecordBeEditedOnWorkflow")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canRecordBeEditedOnWorkflow ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-record-be-edited-on-workflow"
|
|
checked={canRecordBeEditedOnWorkflow}
|
|
onCheckedChange={handleCanRecordBeEditedOnWorkflowToggle}
|
|
disabled={isUpdatingCanRecordBeEditedOnWorkflow}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canIncomingAssignmentsBeSeparated")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canIncomingAssignmentsBeSeparated ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-incoming-assignements-be-separated"
|
|
checked={canIncomingAssignmentsBeSeparated}
|
|
onCheckedChange={
|
|
handlecanIncomingAssignmentsBeSeparatedToggle
|
|
}
|
|
disabled={isUpdatingcanIncomingAssignmentsBeSeparated}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canROReturn")}
|
|
</TableCell>
|
|
<TableCell>{config.canROReturn ? "Yes" : "No"}</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-ro-return"
|
|
checked={canROReturn}
|
|
onCheckedChange={handleCanROReturnToggle}
|
|
disabled={isUpdatingCanROReturn}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.internalMemoHasReferenceNumber")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.internalMemoHasReferenceNumber ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="internal-memo-has-reference-number"
|
|
checked={internalMemoHasReferenceNumber}
|
|
onCheckedChange={
|
|
handleInternalMemoHasReferenceNumberToggle
|
|
}
|
|
disabled={isUpdatingInternalMemoHasReferenceNumber}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.attachSignatureOnAttachment",
|
|
"Attach Signature On Attachment",
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.attachSignatureOnAttachment ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="attach-signature-on-attachment"
|
|
checked={attachSignatureOnAttachment}
|
|
onCheckedChange={handleAttachSignatureOnAttachmentToggle}
|
|
disabled={isUpdatingAttachSignatureOnAttachment}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canHaveTagBasedReferenceNumber",
|
|
"Can Have Tag Based Reference Number",
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canHaveTagBasedReferenceNumber ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-have-tag-based-reference-number"
|
|
checked={canHaveTagBasedReferenceNumber}
|
|
onCheckedChange={
|
|
handleCanHaveTagBasedReferenceNumberToggle
|
|
}
|
|
disabled={isUpdatingCanHaveTagBasedReferenceNumber}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.referenceNumberCountFirst",
|
|
"Should The Number Count Come First On The Reference Number",
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.referenceNumberCountFirst ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="reference-number-count-first"
|
|
checked={referenceNumberCountFirst}
|
|
onCheckedChange={handleReferenceNumberCountFirstToggle}
|
|
disabled={isUpdatingReferenceNumberCountFirst}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t("setting.canUserSkipLevel", "User Can Skip Level")}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canUserSkipLevel ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-user-skip-level"
|
|
checked={canUserSkipLevel}
|
|
onCheckedChange={handleCanUserSkipLevelToggle}
|
|
disabled={isUpdatingCanUserSkipLevel}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
<TableRow>
|
|
<TableCell className="font-medium">
|
|
{t(
|
|
"setting.canSendToBranch",
|
|
"User Can Send to Branch Departments Directly",
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
{config.canUserSkipLevel ? "Yes" : "No"}
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<Switch
|
|
id="can-send-to-branch"
|
|
checked={canSendToBranch}
|
|
onCheckedChange={handleCanSendToBranchToggle}
|
|
disabled={isUpdatingCanSendToBranch}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Modal for editing */}
|
|
<Dialog open={open} onOpenChange={setOpen}>
|
|
<DialogContent className="dark:border-slate-700 dark:bg-slate-900">
|
|
<DialogHeader>
|
|
<DialogTitle className="dark:text-slate-100">
|
|
{t("setting.editTitle")}
|
|
</DialogTitle>
|
|
<DialogDescription className="dark:text-slate-400">
|
|
{t("setting.editMsg")}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
<div className="my-4">
|
|
<Select
|
|
value={newScope}
|
|
onValueChange={(value) =>
|
|
setNewScope(value as PositionScopeToFetch)
|
|
}
|
|
>
|
|
<SelectTrigger className="w-full dark:border-slate-700 dark:bg-slate-900">
|
|
<SelectValue placeholder="Select scope" />
|
|
</SelectTrigger>
|
|
<SelectContent className="dark:border-slate-700 dark:bg-slate-900">
|
|
{positionScopeValues.map((scope) => (
|
|
<SelectItem key={scope} value={scope}>
|
|
{scope.replace(/_/g, " ").toUpperCase()}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<DialogFooter className="flex justify-end gap-2">
|
|
<Button
|
|
variant="secondary"
|
|
onClick={() => setOpen(false)}
|
|
className="dark:bg-slate-800 dark:text-slate-100 dark:hover:bg-slate-700"
|
|
>
|
|
{t("common.Cancel")}
|
|
</Button>
|
|
<Button
|
|
onClick={handleSave}
|
|
disabled={isUpdating}
|
|
className="bg-primary hover:bg-primary/90 text-primary-foreground"
|
|
>
|
|
{isUpdating
|
|
? t("contentManagement.saving")
|
|
: t("delegation.save")}
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default UnitConfigurationPage;
|