mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 17:08:18 +00:00
feat(freight-api): seal EDR side of contracts with the one global stamp
This commit is contained in:
@@ -12,7 +12,6 @@ import toast from "react-hot-toast";
|
||||
|
||||
import Breadcrumbs from "@/components/ui/Breadcrumbs";
|
||||
import { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
|
||||
import { StampUpload } from "@/components/contracts/StampUpload";
|
||||
import { bookingSurface } from "@/components/bookings/booking-ui.styles";
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
import { invalidateBookingDetail } from "@/utils/queryInvalidation";
|
||||
@@ -41,9 +40,6 @@ export default function BookingContractPage() {
|
||||
const [signOpen, setSignOpen] = useState(false);
|
||||
const [signerName, setSignerName] = useState("");
|
||||
const [signatureData, setSignatureData] = useState<string | null>(null);
|
||||
// Company stamp: prefilled from the profile, or uploaded here when none is
|
||||
// saved yet.
|
||||
const [stampData, setStampData] = useState<string | null>(null);
|
||||
// When the user has a saved signature we offer it for approval first; they
|
||||
// can switch to drawing a fresh one.
|
||||
const [drawNew, setDrawNew] = useState(false);
|
||||
@@ -59,7 +55,6 @@ export default function BookingContractPage() {
|
||||
|
||||
const savedSignature = data?.savedSignature ?? null;
|
||||
const savedSignatureImage = savedSignature?.signatureImageUrl ?? null;
|
||||
const savedStampImage = savedSignature?.stampImageUrl ?? null;
|
||||
// Show the approval view only while a saved signature exists and the user
|
||||
// hasn't opted to draw a new one.
|
||||
const usingSaved = Boolean(savedSignatureImage) && !drawNew;
|
||||
@@ -103,8 +98,6 @@ export default function BookingContractPage() {
|
||||
// approve it; otherwise start with an empty pad.
|
||||
setSignerName(savedSignature?.signerDisplayName ?? "");
|
||||
setSignatureData(null);
|
||||
// Prefill with the reusable stamp saved on the profile; still replaceable.
|
||||
setStampData(savedStampImage);
|
||||
setDrawNew(false);
|
||||
setSignOpen(true);
|
||||
};
|
||||
@@ -113,12 +106,12 @@ export default function BookingContractPage() {
|
||||
if (!canSign || !signerName.trim()) return;
|
||||
// Approve the saved signature, or submit the freshly drawn one.
|
||||
const image = usingSaved ? savedSignatureImage : signatureData;
|
||||
// The API rejects a STAFF signature without a stamp.
|
||||
if (!image || !stampData) return;
|
||||
if (!image) return;
|
||||
// No stamp is sent: EDR's seal is the ONE global company stamp, applied
|
||||
// server-side at render time (see StampSettingsService).
|
||||
signMutation.mutate({
|
||||
role: "STAFF",
|
||||
signatureImageBase64: image,
|
||||
stampImageBase64: stampData,
|
||||
signerDisplayName: signerName.trim(),
|
||||
consentText: "I agree to the terms of this contract.",
|
||||
});
|
||||
@@ -243,15 +236,6 @@ export default function BookingContractPage() {
|
||||
) : (
|
||||
<ContractSignaturePad onChange={setSignatureData} />
|
||||
)}
|
||||
<StampUpload
|
||||
value={stampData}
|
||||
onChange={setStampData}
|
||||
description={
|
||||
savedStampImage
|
||||
? "Your saved company stamp — replace it for this contract if needed."
|
||||
: "Required. Attach your official company stamp or seal."
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setSignOpen(false)}>
|
||||
@@ -261,7 +245,6 @@ export default function BookingContractPage() {
|
||||
disabled={
|
||||
signMutation.isPending ||
|
||||
(!usingSaved && !signatureData) ||
|
||||
!stampData ||
|
||||
!signerName.trim()
|
||||
}
|
||||
onClick={confirmSign}
|
||||
|
||||
@@ -18,7 +18,6 @@ import toast from "react-hot-toast";
|
||||
|
||||
import { ContractSignSuccessModal } from "@/components/contracts/ContractSignSuccessModal";
|
||||
import { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
|
||||
import { StampUpload } from "@/components/contracts/StampUpload";
|
||||
import { contractsService } from "@/services/contracts.service";
|
||||
import { extractApiError } from "@/utils/result";
|
||||
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
|
||||
@@ -40,7 +39,6 @@ export default function ContractViewPage() {
|
||||
const [successOpen, setSuccessOpen] = useState(false);
|
||||
const [signerName, setSignerName] = useState("");
|
||||
const [signatureData, setSignatureData] = useState<string | null>(null);
|
||||
const [stampData, setStampData] = useState<string | null>(null);
|
||||
const [drawNew, setDrawNew] = useState(false);
|
||||
|
||||
const { data, isLoading, isError, refetch } = useQuery({
|
||||
@@ -56,10 +54,11 @@ export default function ContractViewPage() {
|
||||
mutationFn: () =>
|
||||
contractsService.signContract(id!, {
|
||||
role: "STAFF",
|
||||
// No stamp is sent: EDR's seal is the ONE global company stamp, applied
|
||||
// server-side from StampSettingsService when the signature is stored.
|
||||
signatureImageBase64: usingSaved
|
||||
? (savedSignatureImage as string)
|
||||
: (signatureData ?? ""),
|
||||
stampImageBase64: stampData ?? "",
|
||||
signerDisplayName: signerName.trim(),
|
||||
consentText: "I confirm this contract on behalf of EDR.",
|
||||
}),
|
||||
@@ -98,14 +97,12 @@ export default function ContractViewPage() {
|
||||
const openSign = () => {
|
||||
setSignerName(data?.savedSignature?.signerDisplayName ?? "");
|
||||
setSignatureData(null);
|
||||
// Prefill with the reusable stamp saved on the profile; still replaceable.
|
||||
setStampData(data?.savedSignature?.stampImageUrl ?? null);
|
||||
setDrawNew(false);
|
||||
setSignOpen(true);
|
||||
};
|
||||
|
||||
const confirmSign = () => {
|
||||
if (!signerName.trim() || !stampData) return;
|
||||
if (!signerName.trim()) return;
|
||||
const image = usingSaved ? savedSignatureImage : signatureData;
|
||||
if (!image) return;
|
||||
signMutation.mutate();
|
||||
@@ -243,13 +240,6 @@ export default function ContractViewPage() {
|
||||
<ContractSignaturePad onChange={setSignatureData} />
|
||||
)}
|
||||
|
||||
<StampUpload
|
||||
value={stampData}
|
||||
onChange={setStampData}
|
||||
label="EDR company stamp"
|
||||
description="Attach the official EDR stamp or seal — it is applied to the contract next to the signature."
|
||||
/>
|
||||
|
||||
<Group justify="flex-end" gap="sm">
|
||||
<Button variant="default" onClick={() => setSignOpen(false)}>
|
||||
Cancel
|
||||
@@ -260,8 +250,7 @@ export default function ContractViewPage() {
|
||||
disabled={
|
||||
signMutation.isPending ||
|
||||
!signerName.trim() ||
|
||||
(!usingSaved && !signatureData) ||
|
||||
!stampData
|
||||
(!usingSaved && !signatureData)
|
||||
}
|
||||
onClick={confirmSign}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user