@@ -28,7 +28,6 @@ export default function SignOffModal({
2828} : SignOffModalProps ) {
2929 const { user } = useUser ( ) ;
3030 const { apiClient } = useApiClient ( ) ;
31- const signatureCanvasRef = useRef < SignatureCanvas > ( null ) ;
3231 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
3332
3433 const { data : userData } = useFetch < {
@@ -37,37 +36,56 @@ export default function SignOffModal({
3736
3837 const staffName = userData ?. user ?. name || userData ?. user ?. email || "" ;
3938 const currentDate = new Date ( ) ;
39+ const staffSignatureCanvasRef = useRef < SignatureCanvas > ( null ) ;
40+ const partnerSignatureCanvasRef = useRef < SignatureCanvas > ( null ) ;
41+ const [ partnerSignerName , setPartnerSignerName ] = useState ( "" ) ;
4042
4143 useEffect ( ( ) => {
42- if ( isOpen && signatureCanvasRef . current ) {
43- signatureCanvasRef . current . clear ( ) ;
44- }
44+ if ( ! isOpen ) return ;
45+
46+ staffSignatureCanvasRef . current ?. clear ( ) ;
47+ partnerSignatureCanvasRef . current ?. clear ( ) ;
48+ setPartnerSignerName ( "" ) ;
4549 } , [ isOpen ] ) ;
4650
4751 const handleSubmit = async ( ) => {
48- if ( ! signatureCanvasRef . current ) {
49- toast . error ( "Please provide a signature " ) ;
52+ if ( ! partnerSignerName . trim ( ) ) {
53+ toast . error ( "Please enter the partner name " ) ;
5054 return ;
5155 }
5256
53- if ( signatureCanvasRef . current . isEmpty ( ) ) {
54- toast . error ( "Please provide a signature" ) ;
57+ if ( ! staffSignatureCanvasRef . current || ! partnerSignatureCanvasRef . current ) {
58+ toast . error ( "Please provide both signatures" ) ;
59+ return ;
60+ }
61+
62+ if (
63+ staffSignatureCanvasRef . current . isEmpty ( ) ||
64+ partnerSignatureCanvasRef . current . isEmpty ( )
65+ ) {
66+ toast . error ( "Please provide both signatures" ) ;
5567 return ;
5668 }
5769
5870 setIsSubmitting ( true ) ;
5971
6072 try {
61- const base64Data = signatureCanvasRef . current
73+ const signatureUrl = staffSignatureCanvasRef . current
74+ . getCanvas ( )
75+ . toDataURL ( "image/png" ) ;
76+ const partnerSignatureUrl = partnerSignatureCanvasRef . current
6277 . getCanvas ( )
6378 . toDataURL ( "image/png" ) ;
6479
6580 const formData = new FormData ( ) ;
6681 formData . append ( "partnerId" , partnerId . toString ( ) ) ;
67- formData . append ( "staffName" , staffName ) ;
6882 formData . append ( "partnerName" , partnerName ) ;
83+ formData . append ( "partnerSignerName" , partnerSignerName ) ;
84+ formData . append ( "staffName" , staffName ) ;
6985 formData . append ( "date" , currentDate . toISOString ( ) ) ;
70- formData . append ( "signatureUrl" , base64Data ) ;
86+ formData . append ( "signatureUrl" , signatureUrl ) ;
87+ formData . append ( "partnerSignatureUrl" , partnerSignatureUrl ) ;
88+
7189 selectedAllocationIds . forEach ( ( id ) => {
7290 formData . append ( "allocation" , id . toString ( ) ) ;
7391 } ) ;
@@ -87,88 +105,137 @@ export default function SignOffModal({
87105 }
88106 } ;
89107
90- const handleClear = ( ) => {
91- if ( signatureCanvasRef . current ) {
92- signatureCanvasRef . current . clear ( ) ;
93- }
94- } ;
108+ const clearStaffSignature = ( ) => staffSignatureCanvasRef . current ?. clear ( ) ;
109+ const clearPartnerSignature = ( ) => partnerSignatureCanvasRef . current ?. clear ( ) ;
95110
96111 if ( ! isOpen ) return null ;
97112
98113 return (
99- < div className = "fixed inset-0 flex items-center justify-center bg-black/50 z-50 " >
100- < div className = "relative bg-white rounded-2xl p-6 w-full max-w-lg shadow-lg text-[#22070B] " >
114+ < div className = "fixed inset-0 z-50 overflow-y-auto bg-black/50 px-4 py-6 " >
115+ < div className = "relative mx-auto flex max-h-[calc(100dvh-3rem)] w-full max-w-lg flex-col overflow-hidden rounded-2xl bg-white text-gray-primary shadow-lg " >
101116 < button
102117 onClick = { onClose }
103118 aria-label = "Close"
104119 className = "absolute top-4 right-4 text-2xl text-gray-500 hover:text-gray-700"
105120 >
106121 < X className = "size-6" />
107122 </ button >
108- < h2 className = "text-[20px] font-semibold leading-[28px] mb-4" >
109- Sign Off Items
110- </ h2 >
111-
112- < div className = "space-y-4" >
113- < div >
114- < label className = "block text-sm font-medium text-gray-700 mb-1" >
115- Staff Name
116- </ label >
117- < input
118- type = "text"
119- value = { staffName }
120- readOnly
121- className = "w-full rounded-[4px] border border-[rgba(34,7,11,0.05)] bg-[rgba(34,7,11,0.05)] text-[16px] p-3 cursor-not-allowed"
122- />
123- </ div >
123+ < div className = "shrink-0 border-b border-gray-200 px-6 py-5 pr-14" >
124+ < h2 className = "text-xl font-semibold leading-7" >
125+ Sign Off Items
126+ </ h2 >
127+ </ div >
128+
129+ < div className = "flex-1 space-y-6 overflow-y-auto px-6 py-5" >
130+ < div className = "space-y-4" >
131+ < div >
132+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
133+ Staff Name
134+ </ label >
135+ < input
136+ type = "text"
137+ value = { staffName }
138+ readOnly
139+ className = "w-full rounded-sm border border-gray-primary/10 bg-sunken p-3 text-base text-gray-primary cursor-not-allowed"
140+ />
141+ </ div >
142+
143+ < div >
144+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
145+ Date and Time
146+ </ label >
147+ < input
148+ type = "text"
149+ value = { format ( currentDate , "MMM d, yyyy 'at' h:mm a" ) }
150+ readOnly
151+ className = "w-full rounded-sm border border-gray-primary/10 bg-sunken p-3 text-base text-gray-primary cursor-not-allowed"
152+ />
153+ </ div >
124154
125- < div >
126- < label className = "block text-sm font-medium text-gray-700 mb-1" >
127- Date and Time
128- </ label >
129- < input
130- type = "text"
131- value = { format ( currentDate , "MMM d, yyyy 'at' h:mm a" ) }
132- readOnly
133- className = "w-full rounded-[4px] border border-[rgba(34,7,11,0.05)] bg-[rgba(34,7,11,0.05)] text-[16px] p-3 cursor-not-allowed"
134- />
155+ < div >
156+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
157+ Signature
158+ </ label >
159+ < div className = "rounded-sm border-2 border-gray-primary/20 bg-white" >
160+ < SignatureCanvas
161+ ref = { staffSignatureCanvasRef }
162+ canvasProps = { {
163+ className : "h-40 w-full sm:h-48" ,
164+ } }
165+ backgroundColor = "white"
166+ />
167+ </ div >
168+ < button
169+ type = "button"
170+ onClick = { clearStaffSignature }
171+ className = "mt-2 text-sm text-blue-primary hover:text-blue-primary/80"
172+ >
173+ Clear Signature
174+ </ button >
175+ </ div >
135176 </ div >
136177
137- < div >
138- < label className = "block text-sm font-medium text-gray-700 mb-1" >
139- Signature
140- </ label >
141- < div className = "border-2 border-gray-300 rounded-[4px] bg-white" >
142- < SignatureCanvas
143- ref = { signatureCanvasRef }
144- canvasProps = { {
145- className : "w-full h-48" ,
146- } }
147- backgroundColor = "white"
178+ < div className = "space-y-4 border-t border-gray-200 pt-6" >
179+ < div >
180+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
181+ Partner Name
182+ </ label >
183+ < input
184+ type = "text"
185+ value = { partnerSignerName }
186+ onChange = { ( e ) => setPartnerSignerName ( e . target . value ) }
187+ className = "w-full rounded-sm border border-gray-primary/10 bg-sunken p-3 text-base text-gray-primary"
188+ />
189+ </ div >
190+
191+ < div >
192+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
193+ Date and Time
194+ </ label >
195+ < input
196+ type = "text"
197+ value = { format ( currentDate , "MMM d, yyyy 'at' h:mm a" ) }
198+ readOnly
199+ className = "w-full rounded-sm border border-gray-primary/10 bg-sunken p-3 text-base text-gray-primary cursor-not-allowed"
148200 />
149201 </ div >
150- < button
151- type = "button"
152- onClick = { handleClear }
153- className = "mt-2 text-sm text-blue-primary hover:text-blue-primary/80"
154- >
155- Clear Signature
156- </ button >
202+
203+ < div >
204+ < label className = "mb-1 block text-sm font-medium text-gray-700" >
205+ Signature
206+ </ label >
207+ < div className = "rounded-sm border-2 border-gray-primary/20 bg-white" >
208+ < SignatureCanvas
209+ ref = { partnerSignatureCanvasRef }
210+ canvasProps = { {
211+ className : "h-40 w-full sm:h-48" ,
212+ } }
213+ backgroundColor = "white"
214+ />
215+ </ div >
216+ < button
217+ type = "button"
218+ onClick = { clearPartnerSignature }
219+ className = "mt-2 text-sm text-blue-primary hover:text-blue-primary/80"
220+ >
221+ Clear Signature
222+ </ button >
223+ </ div >
157224 </ div >
158225 </ div >
159226
160- < div className = "mt-6 flex justify-end gap-4" >
227+ < div className = "mt-auto flex shrink-0 justify-end gap-4 border-t border-gray-200 bg-white px-6 py -4" >
161228 < button
162229 onClick = { onClose }
163230 disabled = { isSubmitting }
164- className = "bg-white hover:bg-gray-100 text-[#EF3340] border-2 border-[#EF3340] font-semibold py-2 px-4 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
231+ className = "rounded-md border-2 border-red-primary bg-white px-4 py-2 font-semibold text-red-primary hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50 "
165232 >
166233 Cancel
167234 </ button >
168235 < button
169236 onClick = { handleSubmit }
170237 disabled = { isSubmitting }
171- className = "bg-[#EF3340] hover: bg-[#a32027] text-white font-semibold py-2 px-4 rounded-md disabled:opacity-50 disabled:cursor-not-allowed"
238+ className = "rounded-md bg-red-primary px-4 py-2 font-semibold text-white hover:bg-red-primary/80 disabled:cursor-not-allowed disabled:opacity-50 "
172239 >
173240 { isSubmitting ? "Submitting..." : "Submit" }
174241 </ button >
0 commit comments