Merge branch 'WorkflowChange' of https://github.com/Tria-plc/emaui into estif-branch-1

This commit is contained in:
nati14575
2026-08-19 16:49:12 +03:00
19 changed files with 818 additions and 189 deletions

View File

@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import { useNavigate, useParams } from "react-router-dom";
import {
ActionIcon,
Alert,
@@ -41,6 +41,8 @@ import {
useAssignApplicationMutation,
useCompleteReviewMutation,
useConfirmPaymentMutation,
useScheduleIssuanceMutation,
useIssueCertificateMutation,
useScheduleExamMutation,
useEscalateApplicationMutation,
useFinalApproveMutation,
@@ -147,6 +149,7 @@ function buildChecklist(
* position instead of scrolling back to a column of buttons.
*/
export function LicenseReviewPage() {
const navigate = useNavigate();
const { t, i18n } = useTranslation();
const showDate = useDateDisplayer();
const localized = useLocalized();
@@ -202,6 +205,8 @@ export function LicenseReviewPage() {
const [scheduleInspection] = useScheduleInspectionMutation();
const [recordResult] = useRecordInspectionResultMutation();
const [confirmPayment] = useConfirmPaymentMutation();
const [scheduleIssuance] = useScheduleIssuanceMutation();
const [issueCertificate] = useIssueCertificateMutation();
const [scheduleExam, { isLoading: schedulingExam }] =
useScheduleExamMutation();
const [holdApplication] = useHoldApplicationMutation();
@@ -225,6 +230,8 @@ export function LicenseReviewPage() {
const [railOpen, setRailOpen] = useState(true);
const [inspectionOpen, setInspectionOpen] = useState(false);
const [inspectionDate, setInspectionDate] = useState("");
const [issuanceOpen, setIssuanceOpen] = useState(false);
const [issuanceDate, setIssuanceDate] = useState("");
const [resultOpen, setResultOpen] = useState(false);
const [scheduleExamOpen, setScheduleExamOpen] = useState(false);
const [findings, setFindings] = useState("");
@@ -472,6 +479,9 @@ export function LicenseReviewPage() {
case "schedule-inspection":
setInspectionOpen(true);
return;
case "schedule-issuance":
setIssuanceOpen(true);
return;
case "record-inspection":
setResultOpen(true);
return;
@@ -615,6 +625,12 @@ export function LicenseReviewPage() {
t("review.done.confirmPayment", "Payment confirmed"),
);
break;
case "issue-certificate":
await run(
() => issueCertificate(id).unwrap(),
t("review.done.issueCertificate", "Certificate issued"),
);
break;
case "hold":
await run(
() => holdApplication({ id, reason: submission.reason }).unwrap(),
@@ -688,6 +704,12 @@ export function LicenseReviewPage() {
applicantFullName ||
applicantOrCompanyName(app) ||
app.applicationNumber;
const linkedBookServices = (data.relatedApplications ?? []).filter(
(related) =>
["SEAMAN_BOOK", "BTC_BASIC_TRAINING"].includes(
related.licenseType?.key ?? "",
),
);
return (
<Container size="xl" py="md">
@@ -710,6 +732,25 @@ export function LicenseReviewPage() {
</Badge>
)}
</Group>
{linkedBookServices.length > 1 && (
<Group gap="xs" mt="xs">
{linkedBookServices.map((related) => (
<Badge
key={related.id}
variant={related.id === app.id ? "filled" : "outline"}
color={STATUS_COLORS[related.status]}
style={{ cursor: "pointer" }}
onClick={() => navigate(`/licence-review/${related.id}`)}
>
{related.licenseType?.key === "SEAMAN_BOOK"
? "Seaman Book"
: "BTC"}{" "}
· {related.applicationNumber} ·{" "}
{STATUS_LABELS[related.status]}
</Badge>
))}
</Group>
)}
</div>
<Group gap="xs">
<Tooltip
@@ -1177,6 +1218,50 @@ export function LicenseReviewPage() {
</Stack>
</Modal>
<Modal
opened={issuanceOpen}
onClose={() => setIssuanceOpen(false)}
title={t("review.actions.scheduleIssuance", "Schedule pickup")}
>
<Stack>
<AmharicDatePicker
label={t("review.pickupDate", "Pickup date")}
value={issuanceDate}
onChange={setIssuanceDate}
/>
<ModalFooter>
<Tooltip
label={t("review.pickDate", "Pick a date and time first")}
disabled={Boolean(issuanceDate)}
>
<span>
<button type="button" hidden aria-hidden />
</span>
</Tooltip>
<ActionIcon
variant="filled"
size="lg"
disabled={!issuanceDate}
aria-label={t("review.schedule", "Schedule")}
onClick={() =>
run(
async () => {
await scheduleIssuance({
id,
scheduledDate: issuanceDate,
}).unwrap();
setIssuanceOpen(false);
},
t("review.done.scheduleIssuance", "Pickup scheduled"),
)
}
>
<IconCheck size={18} />
</ActionIcon>
</ModalFooter>
</Stack>
</Modal>
<Modal
opened={resultOpen}
onClose={() => setResultOpen(false)}