mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-09-07 18:55:43 +00:00
feat: add certificate regeneration functionality to LicenseReviewPage
This commit is contained in:
@@ -34,6 +34,7 @@ import {
|
||||
IconPaperclip,
|
||||
IconPencil,
|
||||
IconQuestionMark,
|
||||
IconRefresh,
|
||||
IconX,
|
||||
} from "@tabler/icons-react";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
@@ -71,6 +72,7 @@ import {
|
||||
useScheduleInspectionMutation,
|
||||
useRescheduleInspectionMutation,
|
||||
useGetCertificateUrlForOfficerMutation,
|
||||
useRegenerateCertificateMutation,
|
||||
uploadDocument,
|
||||
type ApplicationRemark,
|
||||
type RemarkTargetType,
|
||||
@@ -236,6 +238,8 @@ export function LicenseReviewPage() {
|
||||
const [scheduleIssuance] = useScheduleIssuanceMutation();
|
||||
const [issueCertificate] = useIssueCertificateMutation();
|
||||
const [getCertificateUrlForOfficer] = useGetCertificateUrlForOfficerMutation();
|
||||
const [regenerateCertificate, { isLoading: regeneratingCertificate }] =
|
||||
useRegenerateCertificateMutation();
|
||||
const [certificateBusy, setCertificateBusy] = useState<"view" | "download" | null>(
|
||||
null,
|
||||
);
|
||||
@@ -720,6 +724,37 @@ export function LicenseReviewPage() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-renders the stored certificate from whatever design is published now.
|
||||
* Unlike View/Download above, this overwrites the stored PDF even though
|
||||
* one already exists — the fix for a certificate printed from a design
|
||||
* that turned out to be wrong (e.g. a placeholder published for a rank),
|
||||
* where View/Download would otherwise keep handing back the same bad file.
|
||||
*/
|
||||
async function handleRegenerateCertificate() {
|
||||
if (!app.issuedLicenseId) return;
|
||||
try {
|
||||
await regenerateCertificate(app.issuedLicenseId).unwrap();
|
||||
notifications.show({
|
||||
color: "teal",
|
||||
title: t("review.certificateRegenerated", "Certificate regenerated"),
|
||||
message: t(
|
||||
"review.certificateRegeneratedBody",
|
||||
"Re-rendered from the currently published design.",
|
||||
),
|
||||
});
|
||||
} catch (err) {
|
||||
notifications.show({
|
||||
color: "red",
|
||||
title: t(
|
||||
"review.certificateRegenerateError",
|
||||
"Could not regenerate the certificate",
|
||||
),
|
||||
message: extractErrorMessage(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Opens the booking modal seeded with the visit already on the books. */
|
||||
function openReschedule() {
|
||||
if (!pendingInspection) return;
|
||||
@@ -1156,6 +1191,29 @@ export function LicenseReviewPage() {
|
||||
>
|
||||
{t("review.download", "Download")}
|
||||
</Button>
|
||||
{/* Same authority as issuing in the first place — reprints
|
||||
the stored PDF from whatever design is published now,
|
||||
for when the one on file turns out to be wrong. */}
|
||||
{can(["can:issue:license-certificate"]) && (
|
||||
<Tooltip
|
||||
label={t(
|
||||
"review.regenerateCertificateHint",
|
||||
"Re-render from the currently published design",
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
size="xs"
|
||||
variant="subtle"
|
||||
color="gray"
|
||||
leftSection={<IconRefresh size={14} />}
|
||||
loading={regeneratingCertificate}
|
||||
disabled={Boolean(certificateBusy) || regeneratingCertificate}
|
||||
onClick={handleRegenerateCertificate}
|
||||
>
|
||||
{t("review.regenerateCertificate", "Regenerate")}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
@@ -763,6 +763,17 @@ export const licensingApi = baseApi
|
||||
query: (id) => ({ url: `/licenses/${id}/certificate-backoffice` }),
|
||||
}),
|
||||
|
||||
/**
|
||||
* Force re-renders a certificate that already has a stored PDF, from
|
||||
* whatever design is published now — the two routes above only fill in
|
||||
* a *missing* PDF, so a licence printed from a design that turns out to
|
||||
* be wrong (a placeholder someone published, a broken background image)
|
||||
* has no other way to pick up a fix once the design is corrected.
|
||||
*/
|
||||
regenerateCertificate: builder.mutation<{ url: string }, string>({
|
||||
query: (id) => ({ url: `/licenses/${id}/regenerate-certificate`, method: 'POST' }),
|
||||
}),
|
||||
|
||||
// ------------------------------------------------------------- review
|
||||
getQueue: builder.query<Paginated<LicenseApplication>, QueueFilter | void>({
|
||||
query: (params) => ({
|
||||
@@ -1479,6 +1490,7 @@ export const {
|
||||
useGetLicensesQuery,
|
||||
useGetCertificateUrlMutation,
|
||||
useGetCertificateUrlForOfficerMutation,
|
||||
useRegenerateCertificateMutation,
|
||||
useGetApplicationPaymentQuery,
|
||||
usePatchSectionMutation,
|
||||
useAddStaffMutation,
|
||||
|
||||
Reference in New Issue
Block a user