10-10
This commit is contained in:
parent
a7b7be491e
commit
f2b17edb13
|
|
@ -90,6 +90,7 @@ export enum SaveTypeEnum {
|
|||
DRAW = "DRAW",
|
||||
TYPE = "TEXT",
|
||||
UPLOAD = "IMAGE",
|
||||
SELECT = "SELECT",
|
||||
}
|
||||
export interface SaveType {
|
||||
signatureId: string | null
|
||||
|
|
@ -98,6 +99,7 @@ export interface SaveType {
|
|||
signature: string | null;
|
||||
initial: string | null;
|
||||
isDefaultAndClicked?: boolean;
|
||||
font?: string;
|
||||
}
|
||||
interface TagsSubmitDataObj {
|
||||
tags: TagSubmitData[];
|
||||
|
|
|
|||
|
|
@ -629,8 +629,8 @@ const TagsCon: React.FC<TagsConProps> = ({
|
|||
)
|
||||
)) ? (
|
||||
<FaSignature className="text-lg text-slate-600" />
|
||||
) : saved.saveType === "SELECT" ? (
|
||||
<>{saved.fullName}</>
|
||||
) : saved && saved.saveType !== null && saved.saveType === "SELECT" ? (
|
||||
<><span style={{ fontFamily: saved?.font, fontSize: "18px" }}>{saved.signature}</span></>
|
||||
) : (
|
||||
<img
|
||||
style={{
|
||||
|
|
@ -669,16 +669,18 @@ const TagsCon: React.FC<TagsConProps> = ({
|
|||
)
|
||||
)) ?
|
||||
<TbSignature className="text-lg text-slate-600" />
|
||||
:
|
||||
<img
|
||||
style={{
|
||||
width: `${item.dimensions.width}px`,
|
||||
height: `${item.dimensions.height}px`,
|
||||
}}
|
||||
className="w-[100%] h-full"
|
||||
// src={saved.initial as string}
|
||||
src={`data:image/png;base64,${saved.initial}`}
|
||||
/>
|
||||
: saved && saved.saveType !== null && saved.saveType === "SELECT" ? (
|
||||
<><span style={{ fontFamily: saved?.font }}>{saved.initial}</span></>
|
||||
) :
|
||||
(<img
|
||||
style={{
|
||||
width: `${item.dimensions.width}px`,
|
||||
height: `${item.dimensions.height}px`,
|
||||
}}
|
||||
className="w-[100%] h-full"
|
||||
// src={saved.initial as string}
|
||||
src={`data:image/png;base64,${saved.initial}`}
|
||||
/>)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,21 +65,29 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
|||
initials: string | null;
|
||||
}>({ fullSignature: null, initials: null });
|
||||
|
||||
const signatureOptions = [
|
||||
{ id: 1, name: 'print', initials: 'LA', style: 'print' },
|
||||
{ id: 2, name: 'cursive', initials: 'LA', style: 'cursive' },
|
||||
{ id: 3, name: 'script', initials: 'LA', style: 'script' },
|
||||
{ id: 4, name: 'elegant', initials: 'LA', style: 'elegant' },
|
||||
{ id: 5, name: 'modern', initials: 'LA', style: 'modern' },
|
||||
{ id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
||||
];
|
||||
// const signatureOptions = [
|
||||
// { id: 1, name: 'print', initials: 'LA', style: 'print' },
|
||||
// { id: 2, name: 'cursive', initials: 'LA', style: 'cursive' },
|
||||
// { id: 3, name: 'script', initials: 'LA', style: 'script' },
|
||||
// { id: 4, name: 'elegant', initials: 'LA', style: 'elegant' },
|
||||
// { id: 5, name: 'modern', initials: 'LA', style: 'modern' },
|
||||
// { id: 6, name: 'classic', initials: 'LA', style: 'classic' },
|
||||
// ];
|
||||
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
const toggleCheckbox = () => setChecked(!checked);
|
||||
|
||||
|
||||
const fontsMap = [
|
||||
{ style: "'Great Vibes', cursive", label: "Elegant Script", acronym: "f1" },
|
||||
{ style: "'Pacifico', cursive", label: "Casual Handwritten", acronym: "f2" },
|
||||
{ style: "'Dancing Script', cursive", label: "Smooth Flow", acronym: "f3" },
|
||||
{ style: "'Playfair Display', serif", label: "Classic Serif", acronym: "f4" },
|
||||
]
|
||||
|
||||
const [selectedSignature, setSelectedSignature] = useState<SelectStyle>(
|
||||
signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" }
|
||||
fontsMap.length > 0 ? { id: fontsMap[0].acronym, style: fontsMap[0].style } : { id: "f1", style: "" }
|
||||
);
|
||||
|
||||
// Store the actual file
|
||||
|
|
@ -216,9 +224,10 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
|||
// Base payload
|
||||
const payload = {
|
||||
signatureType: activeTab,
|
||||
firstName: fullName.split(' ')[0] || user.firstName,
|
||||
lastName: fullName.split(' ')[1] || user.lastName,
|
||||
font: selectedSignature.style,
|
||||
initials: activeTab === "SELECT" ? initials : "",
|
||||
firstName: fullName.split(' ').length > 1 ? fullName.split(' ')[0] : "",
|
||||
lastName: fullName.split(' ').length > 1 ? fullName.split(' ')[1] : fullName.split(' ')[0],
|
||||
font: activeTab === "SELECT" ? selectedSignature.id : "",
|
||||
default: checked
|
||||
};
|
||||
|
||||
|
|
@ -292,41 +301,68 @@ const AddSignatureModal: React.FC<AddSignatureModalProps> = ({
|
|||
switch (activeTab) {
|
||||
case 'SELECT':
|
||||
return (
|
||||
<>
|
||||
{/* Form Inputs - Fixed */}
|
||||
<div className="px-4 lg:px-6 py-4 flex-shrink-0">
|
||||
<h2 className='mt-4 mb-5 text-sm'>Confirm your name and choose signature style. *Are required fields.</h2>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className='w-full'>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Full Name
|
||||
<span className='text-red-600'> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={fullName}
|
||||
onChange={(e) => setFullName(e.target.value)}
|
||||
placeholder="Enter full name"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div className='w-full'>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Initials
|
||||
<span className='text-red-600'> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={initials}
|
||||
onChange={(e) => setInitials(e.target.value)}
|
||||
placeholder="Enter initials"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-4 lg:px-6 py-4 flex-shrink-0">
|
||||
<h2 className='mt-4 mb-5 text-sm'>
|
||||
Confirm your name and choose signature style. *Are required fields.
|
||||
</h2>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3 mb-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Full Name
|
||||
<span className='text-red-600'> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={fullName}
|
||||
onChange={(e) => {
|
||||
setFullName(e.target.value)
|
||||
setInitials(e.target.value.trim().split(' ').length > 1 ? e.target.value.split(' ')[0][0] + "" + e.target.value.split(' ')[1][0] : e.target.value.split(' ')[0][0])
|
||||
}}
|
||||
placeholder="Enter full name"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Initials
|
||||
<span className='text-red-600'> *</span>
|
||||
</label>
|
||||
<input
|
||||
disabled
|
||||
type="text"
|
||||
value={initials}
|
||||
// onChange={(e) => setInitials(e.target.value)}
|
||||
placeholder="Enter initials"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
{/* Signature Style Options */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{fontsMap.map((opt) => (
|
||||
<div
|
||||
key={opt.acronym}
|
||||
onClick={() => setSelectedSignature({ id: opt.acronym, style: opt.style })}
|
||||
className={`cursor-pointer border border-slate-200 rounded-xl p-4 text-center bg-white transition
|
||||
${selectedSignature.id === opt.acronym
|
||||
? "ring-2 ring-[var(--mainPrimaryBtn)]"
|
||||
: "hover:shadow-md"}`}
|
||||
>
|
||||
<div style={{ fontFamily: opt.style, fontSize: "1.75rem" }}>
|
||||
{fullName || "Full Name"}
|
||||
</div>
|
||||
<div
|
||||
style={{ fontFamily: opt.style, fontSize: "1.25rem", opacity: 0.7 }}
|
||||
>
|
||||
{initials || "AB"}
|
||||
</div>
|
||||
<p className="text-xs mt-2 text-gray-500">{opt.label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
case 'DRAW':
|
||||
|
|
|
|||
|
|
@ -75,10 +75,18 @@ interface UserData {
|
|||
}
|
||||
|
||||
interface SelectStyle {
|
||||
id: number,
|
||||
id: number | string,
|
||||
style: string
|
||||
}
|
||||
|
||||
const fontsMap = [
|
||||
{ style: "'Great Vibes', cursive", label: "Elegant Script", acronym: "f1" },
|
||||
{ style: "'Pacifico', cursive", label: "Casual Handwritten", acronym: "f2" },
|
||||
{ style: "'Dancing Script', cursive", label: "Smooth Flow", acronym: "f3" },
|
||||
{ style: "'Playfair Display', serif", label: "Classic Serif", acronym: "f4" },
|
||||
]
|
||||
|
||||
|
||||
const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||
recipient,
|
||||
setOpenSign,
|
||||
|
|
@ -228,26 +236,9 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
|
||||
const handleSubmit = async () => {
|
||||
setIsSubmitting(true);
|
||||
// if (!signatures.fullSignature || !signatures.initials) {
|
||||
// alert('Please provide both signature and initials');
|
||||
// setIsSubmitting(false);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if ((activeTab === 'DRAW' || activeTab === 'UPLOAD') &&
|
||||
(!signatures.fullSignature || !signatures.initials)) {
|
||||
// alert('Please provide both signature and initials');
|
||||
// toast.error('Please provide both signature and initials in draw and upload case', {
|
||||
// position: "top-center",
|
||||
// autoClose: 2000,
|
||||
// hideProgressBar: false,
|
||||
// closeOnClick: false,
|
||||
// pauseOnHover: true,
|
||||
// draggable: true,
|
||||
// progress: undefined,
|
||||
// theme: "light",
|
||||
// transition: Bounce,
|
||||
// });
|
||||
setIsSubmitting(false);
|
||||
return;
|
||||
}
|
||||
|
|
@ -257,12 +248,12 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
tagId: signTagId,
|
||||
// signatureId: signatureId,
|
||||
type: activeTab,
|
||||
firstName: fullName.split(' ')[0] || user.firstName,
|
||||
lastName: fullName.split(' ')[1] || user.lastName,
|
||||
initials: "",
|
||||
firstName: fullName.split(' ').length > 1 ? fullName.split(' ')[0] : "",
|
||||
lastName: fullName.split(' ').length > 1 ? fullName.split(' ')[1] : fullName.split(' ')[0],
|
||||
initials: initials,
|
||||
initialsBase64: signatures.initials,
|
||||
signatureBase64: signatures.fullSignature,
|
||||
font: selectedSignature.style
|
||||
font: activeTab === "SELECT" ? selectedSignature.id : ""
|
||||
};
|
||||
|
||||
if (activeTab !== 'SELECT') {
|
||||
|
|
@ -270,48 +261,30 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
payload.initialsBase64 = signatures.initials;
|
||||
}
|
||||
|
||||
// if (isEditMode && editingSignature) {
|
||||
// // Update existing signature
|
||||
// const updatePayload = {
|
||||
// ...payload,
|
||||
// signatureId: editingSignature.id
|
||||
// };
|
||||
// res = await axios.put(`${import.meta.env.VITE_BASE_URI}/api/v1/user/signatures`, updatePayload);
|
||||
// console.log("handleUpdate", res);
|
||||
let res = null
|
||||
if (activeTab === 'SAVED') {
|
||||
res = await axios.get(`${import.meta.env.VITE_BASE_URI}/api/v1/sign/${recipientId}/signatures/${selectedSignature.id}`)
|
||||
} else if (activeTab === 'SELECT') {
|
||||
|
||||
// toast.success("Signature Updated Successfully", {
|
||||
// position: "top-center",
|
||||
// autoClose: 500,
|
||||
// hideProgressBar: false,
|
||||
// closeOnClick: false,
|
||||
// pauseOnHover: true,
|
||||
// draggable: true,
|
||||
// progress: undefined,
|
||||
// theme: "light",
|
||||
// transition: Bounce,
|
||||
// });
|
||||
// } else {
|
||||
// Create new signature
|
||||
let res = await axios.post(`${import.meta.env.VITE_BASE_URI}/api/v1/sign/${recipientId}/signatures`,
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
"ngrok-skip-browser-warning": "69420"
|
||||
}
|
||||
});
|
||||
payload.signatureBase64 = ""
|
||||
payload.initialsBase64 = ""
|
||||
|
||||
// toast.success("Signature Created Successfully", {
|
||||
// position: "top-center",
|
||||
// autoClose: 500,
|
||||
// hideProgressBar: false,
|
||||
// closeOnClick: false,
|
||||
// pauseOnHover: true,
|
||||
// draggable: true,
|
||||
// progress: undefined,
|
||||
// theme: "light",
|
||||
// transition: Bounce,
|
||||
// });
|
||||
// }
|
||||
res = await axios.post(`${import.meta.env.VITE_BASE_URI}/api/v1/sign/${recipientId}/signatures`,
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
"ngrok-skip-browser-warning": "69420"
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res = await axios.post(`${import.meta.env.VITE_BASE_URI}/api/v1/sign/${recipientId}/signatures`,
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
"ngrok-skip-browser-warning": "69420"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (res?.data) {
|
||||
setSignatures({
|
||||
|
|
@ -322,231 +295,20 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
signatureId: res.data.id ?? null,
|
||||
saveType: res.data.signatureType ?? null,
|
||||
save: true,
|
||||
signature: res.data.signatureBlob ?? null,
|
||||
initial: res.data.initialsBlob ?? null,
|
||||
signature: res.data.signatureType === "SELECT" ? payload.firstName : (res.data.signatureBlob ?? null),
|
||||
initial: res.data.signatureType === "SELECT" ? payload.initials : (res.data.initialsBlob ?? null),
|
||||
font: res.data.signatureType === "SELECT" ? selectedSignature.style : ""
|
||||
});
|
||||
setOpenSign(false);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error submitting signature:", error);
|
||||
// toast.error(isEditMode ? "Failed to update signature" : "Failed to create signature", {
|
||||
// position: "top-center",
|
||||
// autoClose: 2000,
|
||||
// hideProgressBar: false,
|
||||
// closeOnClick: false,
|
||||
// pauseOnHover: true,
|
||||
// draggable: true,
|
||||
// progress: undefined,
|
||||
// theme: "light",
|
||||
// transition: Bounce,
|
||||
// });
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
// const renderContent = () => {
|
||||
// switch (activeTab) {
|
||||
// case 'SELECT':
|
||||
// return (
|
||||
// <div className="h-full flex flex-col ">
|
||||
// <div className="mb-6">
|
||||
// <h2 className="text-xl font-semibold text-gray-900 mb-2">Choose Signature Style</h2>
|
||||
// <p className="text-sm text-gray-600">Select from pre-designed signature styles</p>
|
||||
// </div>
|
||||
|
||||
// <div className="flex-1 overflow-y-auto">
|
||||
// <div className="space-y-4">
|
||||
// {signatureOptions.map((option) => (
|
||||
// <div key={option.id} className="flex items-center space-x-4 px-2 py-1 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
|
||||
// <input
|
||||
// type="radio"
|
||||
// id={`signature-${option.id}`}
|
||||
// name="signature"
|
||||
// checked={selectedSignature.id === option.id}
|
||||
// onChange={() => setSelectedSignature({ id: option.id, style: option.style })}
|
||||
// className="w-4 h-4 text-blue-600 focus:ring-blue-500"
|
||||
// />
|
||||
// <div className="flex-1 grid grid-cols-2 gap-2">
|
||||
// <div className=" border-gray-300 rounded-lg px-2 py-1 bg-white ">
|
||||
// <div className="text-xs text-gray-500 mb-2">Signed by:</div>
|
||||
// <div className={`text-lg ${option.style === 'cursive' ? 'font-serif italic' :
|
||||
// option.style === 'script' ? 'font-mono' :
|
||||
// option.style === 'elegant' ? 'font-serif' :
|
||||
// option.style === 'modern' ? 'font-sans tracking-wide' :
|
||||
// 'font-sans'
|
||||
// }`}>
|
||||
// {fullName || option.name}
|
||||
// </div>
|
||||
// <div className="text-xs text-gray-400 mt-2">
|
||||
// dca3e646-62cd-4cc...
|
||||
// </div>
|
||||
// </div>
|
||||
// <div className=" rounded-lg px-2 py-2 bg-white ">
|
||||
// <div className="text-xs text-gray-500 mb-2">DS</div>
|
||||
// <div className={`text-2xl ${option.style === 'cursive' ? 'font-serif italic' :
|
||||
// option.style === 'script' ? 'font-mono' :
|
||||
// option.style === 'elegant' ? 'font-serif' :
|
||||
// option.style === 'modern' ? 'font-sans tracking-wide' :
|
||||
// 'font-sans'
|
||||
// }`}>
|
||||
// {initials || option.initials}
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// ))}
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
|
||||
// case 'DRAW':
|
||||
// return (
|
||||
// <DrawSignatureCanvas
|
||||
// onSignatureChange={handleSignatureChange}
|
||||
// // initialSignatures={isEditMode ? signatures : undefined}
|
||||
// />
|
||||
// );
|
||||
|
||||
// case 'UPLOAD':
|
||||
// return (
|
||||
// <div className="h-full flex flex-col">
|
||||
// <div className="mb-6">
|
||||
// <h2 className="text-xl font-semibold text-gray-900 mb-2">Upload Signature</h2>
|
||||
// </div>
|
||||
// <div className="flex-1 overflow-y-auto">
|
||||
// <div>
|
||||
// <div className="grid grid-cols-12 gap-6">
|
||||
// {/* Upload 1 */}
|
||||
// <div className="col-span-8">
|
||||
// <label className="block text-sm font-medium text-gray-700 mb-2">Full Signature</label>
|
||||
// <label htmlFor="upload1" className=" border-2 border-dashed border-gray-300 rounded-lg h-62 flex items-center justify-center bg-gray-50 hover:bg-gray-100 cursor-pointer transition-colors">
|
||||
// {preview1 ? (
|
||||
// <img src={preview1} alt="Signature Preview" className="max-h-44 object-contain" />
|
||||
// ) : (
|
||||
// <div className="text-center">
|
||||
// <MdCloudUpload className="mx-auto h-12 w-12 text-gray-400 mb-3" />
|
||||
// <p className="text-sm text-gray-500 mb-1">Click to upload or drag and drop</p>
|
||||
// <p className="text-xs text-gray-400">PNG, JPG, GIF up to 10MB</p>
|
||||
// </div>
|
||||
// )}
|
||||
// </label>
|
||||
// <input
|
||||
// id="upload1"
|
||||
// type="file"
|
||||
// accept="image/*"
|
||||
// className="hidden"
|
||||
// onChange={(e) => handleImageChange(e, setFile1, setPreview1, "fullSignature")}
|
||||
// />
|
||||
// </div>
|
||||
|
||||
// {/* Upload 2 */}
|
||||
// <div className="col-span-4">
|
||||
// <label className="block text-sm font-medium text-gray-700 mb-2">Initials</label>
|
||||
// <label htmlFor="upload2" className=" border-2 border-dashed border-gray-300 rounded-lg h-62 flex items-center justify-center bg-gray-50 hover:bg-gray-100 cursor-pointer transition-colors">
|
||||
// {preview2 ? (
|
||||
// <img src={preview2} alt="Initials Preview" className="max-h-44 object-contain" />
|
||||
// ) : (
|
||||
// <div className="text-center">
|
||||
// <MdCloudUpload className="mx-auto h-8 w-8 text-gray-400 mb-2" />
|
||||
// <p className="text-xs text-gray-500">Upload initials</p>
|
||||
// </div>
|
||||
// )}
|
||||
// </label>
|
||||
// <input
|
||||
// id="upload2"
|
||||
// type="file"
|
||||
// accept="image/*"
|
||||
// className="hidden"
|
||||
// onChange={(e) => handleImageChange(e, setFile2, setPreview2, "initials")}
|
||||
// />
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
// case 'SAVED':
|
||||
// return (
|
||||
// <div className="h-full flex flex-col ">
|
||||
// <div className="mb-6">
|
||||
// <h2 className="text-xl font-semibold text-gray-900 mb-2">Saved Signature's</h2>
|
||||
// {/* <p className="text-sm text-gray-600">Select from pre-designed signature styles</p> */}
|
||||
// </div>
|
||||
|
||||
// <div className="flex-1 overflow-y-auto">
|
||||
// <div className="space-y-4">
|
||||
// {preSaveSignatures.map((signature) => (
|
||||
// <div key={signature?.id} className="grid grid-cols-12 gap-4 px-6 py-9 hover:bg-gray-50 transition-colors duration-150">
|
||||
// {/* Signature Column */}
|
||||
// <div className="col-span-5">
|
||||
// <div className="flex flex-col space-y-2 relative ps-6 border-l-3 border-blue-600 rounded-bl-2xl rounded-tl-2xl">
|
||||
// <div className="text-sm text-gray-600 font-medium mb-1">
|
||||
// Signed by:
|
||||
// </div>
|
||||
|
||||
// {/* Signature Image or Fallback Text */}
|
||||
// <div className="bg-white rounded-lg p-1 flex items-center justify-center">
|
||||
// {signature?.signatureBlob ? (
|
||||
// <img
|
||||
// src={`data:${signature?.signatureMimeType || "image/png"};base64,${signature?.signatureBlob}`}
|
||||
// className="h-[50px] w-[250px] object-contain"
|
||||
// alt="Signature"
|
||||
// />
|
||||
// ) : (
|
||||
// <div className="text-gray-400 italic text-sm">No Signature</div>
|
||||
// )}
|
||||
// </div>
|
||||
|
||||
// {/* Name */}
|
||||
// <div className="text-xs text-gray-500 truncate">
|
||||
// {signature?.signatureHash ?? ' '}
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
|
||||
// {/* Initial Column */}
|
||||
// <div className="col-span-5">
|
||||
// <div className="flex flex-col space-y-2 relative ps-6 border-l-3 border-green-600 rounded-bl-2xl rounded-tl-2xl">
|
||||
// <div className="text-sm text-gray-600 font-medium mb-1">
|
||||
// Initials
|
||||
// </div>
|
||||
|
||||
// {/* Initials Image */}
|
||||
// <div className="bg-white rounded-lg p-1 flex items-center justify-center">
|
||||
// {signature?.initialsBlob ? (
|
||||
// <img
|
||||
// src={`data:image/png;base64,${signature?.initialsBlob}`}
|
||||
// className="h-[50px] object-contain"
|
||||
// alt="Initials"
|
||||
// />
|
||||
// ) : (
|
||||
// <div className="text-gray-400 italic text-sm">No Initials</div>
|
||||
// )}
|
||||
// </div>
|
||||
|
||||
// {/* Optional initials hash or font */}
|
||||
// <div className="text-xs text-gray-500 truncate">
|
||||
// {signature?.initialsHash || " "}
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// ))}
|
||||
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
|
||||
// default:
|
||||
// return null;
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
const renderSignatureText = (type, font, firstName, lastName, mode = 'name') => {
|
||||
if (type !== 'SELECT') return null;
|
||||
|
||||
|
|
@ -579,10 +341,12 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
case 'SELECT':
|
||||
return (
|
||||
<div className="px-4 lg:px-6 py-4 flex-shrink-0">
|
||||
<h2 className='mt-4 mb-5 text-sm'>Confirm your name and choose signature style. *Are required fields.</h2>
|
||||
<h2 className='mt-4 mb-5 text-sm'>
|
||||
Confirm your name and choose signature style. *Are required fields.
|
||||
</h2>
|
||||
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div className=''>
|
||||
<div className="grid grid-cols-2 gap-3 mb-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Full Name
|
||||
<span className='text-red-600'> *</span>
|
||||
|
|
@ -590,29 +354,57 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
<input
|
||||
type="text"
|
||||
value={fullName}
|
||||
onChange={(e) => setFullName(e.target.value)}
|
||||
onChange={(e) => {
|
||||
setFullName(e.target.value)
|
||||
setInitials(e.target.value.trim().split(' ').length > 1 ? e.target.value.split(' ')[0][0]+""+e.target.value.split(' ')[1][0] : e.target.value.split(' ')[0][0])
|
||||
}}
|
||||
placeholder="Enter full name"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
<div className=''>
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">
|
||||
Initials
|
||||
<span className='text-red-600'> *</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
disabled
|
||||
value={initials}
|
||||
onChange={(e) => setInitials(e.target.value)}
|
||||
// onChange={(e) => setInitials(e.target.value)}
|
||||
placeholder="Enter initials"
|
||||
className="w-full px-3 py-2 text-sm border border-gray-200 rounded-md outline-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Signature Style Options */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{fontsMap.map((opt) => (
|
||||
<div
|
||||
key={opt.acronym}
|
||||
onClick={() => setSelectedSignature({ id: opt.acronym, style: opt.style })}
|
||||
className={`cursor-pointer border border-slate-200 rounded-xl p-4 text-center bg-white transition
|
||||
${selectedSignature.id === opt.acronym
|
||||
? "ring-2 ring-[var(--mainPrimaryBtn)]"
|
||||
: "hover:shadow-md"}`}
|
||||
>
|
||||
<div style={{ fontFamily: opt.style, fontSize: "1.75rem" }}>
|
||||
{fullName || "Full Name"}
|
||||
</div>
|
||||
<div
|
||||
style={{ fontFamily: opt.style, fontSize: "1.25rem", opacity: 0.7 }}
|
||||
>
|
||||
{initials || "AB"}
|
||||
</div>
|
||||
<p className="text-xs mt-2 text-gray-500">{opt.label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
case 'DRAW':
|
||||
return (
|
||||
<div className="h-full">
|
||||
|
|
@ -716,12 +508,12 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
|||
{/* Horizontal Scrollable List */}
|
||||
<div className="flex-1 overflow-x-auto px-2 sm:px-6">
|
||||
<div className="flex flex-col space-x-4 max-h-[40vh] gap-2">
|
||||
{preSaveSignatures.map((signature) => (
|
||||
{preSaveSignatures.map((signature: Signature) => (
|
||||
<div
|
||||
key={signature?.id}
|
||||
onClick={() => setSelectedSignature(signature?.id)}
|
||||
onClick={() => setSelectedSignature({ id: Number(signature?.id), style: "" })}
|
||||
className={`cursor-pointer bg-white rounded-xl border p-4 w-full flex justify-between items-start transition-shadow duration-200 gap-3
|
||||
${selectedSignature === signature?.id ? 'border-blue-500 shadow-lg' : 'border-gray-200'}
|
||||
${selectedSignature.id === Number(signature?.id) ? 'border-blue-500 shadow-lg' : 'border-gray-200'}
|
||||
`}
|
||||
style={{ minWidth: '220px' }} // each card width
|
||||
>
|
||||
|
|
|
|||
|
|
@ -50,11 +50,6 @@ api.interceptors.response.use(
|
|||
window.location.href = "/";
|
||||
}
|
||||
|
||||
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||
// Likely a full HTML page, handle accordinglys
|
||||
window.location.href = response.request.responseURL;
|
||||
}
|
||||
|
||||
if (response && (response.status === 301 || response.status === 302)) {
|
||||
const redirectUrl = response.headers["location"];
|
||||
if (redirectUrl) {
|
||||
|
|
@ -62,6 +57,13 @@ api.interceptors.response.use(
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||
// Likely a full HTML page, handle accordinglys
|
||||
if("responseURL" in response.request && response.request.responseURL !== null && response.request.responseURL !== "" && response.request.responseURL !== undefined) {
|
||||
window.location.href = response.request.responseURL;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
},
|
||||
async error => {
|
||||
|
|
@ -81,7 +83,7 @@ api.interceptors.response.use(
|
|||
|
||||
// Prevent multiple refresh attempts
|
||||
// if (error.response?.status === 401 || error.response?.status === 500) {
|
||||
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||
if (error.response?.status === 401 && error.response?.status === 502 && !originalRequest._retry) {
|
||||
originalRequest._retry = true;
|
||||
try {
|
||||
if (!isRefreshing) {
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ const axiosInstance: AxiosInstance = axios.create({
|
|||
axiosInstance.interceptors.response.use(
|
||||
(response) => {
|
||||
|
||||
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||
// Likely a full HTML page, handle accordingly
|
||||
window.location.href = response.request.responseURL;
|
||||
}
|
||||
|
||||
if (response && (response.status === 301 || response.status === 302)) {
|
||||
const redirectUrl = response.headers["location"];
|
||||
|
|
@ -29,6 +25,13 @@ axiosInstance.interceptors.response.use(
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||
// Likely a full HTML page, handle accordingly
|
||||
if ("responseURL" in response.request && response.request.responseURL !== null && response.request.responseURL !== "" && response.request.responseURL !== undefined) {
|
||||
window.location.href = response.request.responseURL;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise just continue as normal
|
||||
return response;
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue