11'use client' ;
22
3- import { useState , useRef } from 'react' ;
3+ import { useState , useRef , type ReactElement , type ChangeEvent } from 'react' ;
44import { AlertCircle , Upload , X , CheckCircle2 } from 'lucide-react' ;
55import { toast } from 'sonner' ;
6- import { useDisputeForm , DisputeFormData , OpenDisputeResponse } from '@/hooks/useDisputeForm' ;
6+ import {
7+ useDisputeForm ,
8+ DisputeFormData ,
9+ OpenDisputeResponse ,
10+ } from '@/hooks/useDisputeForm' ;
711
812interface DisputeFormProps {
913 deliveryId : string ;
@@ -15,10 +19,26 @@ interface DisputeFormProps {
1519type FormStep = 'dispute_reason' | 'evidence' | 'confirmation' | 'success' ;
1620
1721const DISPUTE_REASONS = [
18- { value : 'damaged_items' , label : 'Items Damaged' , description : 'Items arrived damaged or broken' } ,
19- { value : 'non_delivery' , label : 'Non-Delivery' , description : 'Items were not delivered' } ,
20- { value : 'incorrect_items' , label : 'Incorrect Items' , description : 'Wrong items were delivered' } ,
21- { value : 'other' , label : 'Other Issue' , description : 'Something else went wrong' } ,
22+ {
23+ value : 'damaged_items' ,
24+ label : 'Items Damaged' ,
25+ description : 'Items arrived damaged or broken' ,
26+ } ,
27+ {
28+ value : 'non_delivery' ,
29+ label : 'Non-Delivery' ,
30+ description : 'Items were not delivered' ,
31+ } ,
32+ {
33+ value : 'incorrect_items' ,
34+ label : 'Incorrect Items' ,
35+ description : 'Wrong items were delivered' ,
36+ } ,
37+ {
38+ value : 'other' ,
39+ label : 'Other Issue' ,
40+ description : 'Something else went wrong' ,
41+ } ,
2242] as const ;
2343
2444/**
@@ -36,14 +56,15 @@ function ConfirmationDialog({
3656 onConfirm : ( ) => void ;
3757 onCancel : ( ) => void ;
3858 isSubmitting : boolean ;
39- } ) : JSX . Element {
59+ } ) : ReactElement {
4060 const overlayRef = useRef < HTMLDivElement > ( null ) ;
4161
4262 const handleOverlayClick = ( e : React . MouseEvent < HTMLDivElement > ) => {
4363 if ( e . target === overlayRef . current && ! isSubmitting ) onCancel ( ) ;
4464 } ;
4565
46- const reasonLabel = DISPUTE_REASONS . find ( r => r . value === reason ) ?. label || reason ;
66+ const reasonLabel =
67+ DISPUTE_REASONS . find ( ( r ) => r . value === reason ) ?. label || reason ;
4768
4869 return (
4970 < div
@@ -59,27 +80,41 @@ function ConfirmationDialog({
5980 < AlertCircle className = "h-8 w-8 text-amber-600" />
6081 </ div >
6182
62- < h2 id = "confirmation-modal-title" className = "text-center text-lg font-semibold text-gray-900 mb-2" >
83+ < h2
84+ id = "confirmation-modal-title"
85+ className = "text-center text-lg font-semibold text-gray-900 mb-2"
86+ >
6387 Confirm Dispute
6488 </ h2 >
6589 < p className = "text-center text-sm text-gray-600 mb-6" >
66- Opening a dispute will freeze the escrow funds during arbitration. Confirm your dispute details below.
90+ Opening a dispute will freeze the escrow funds during arbitration.
91+ Confirm your dispute details below.
6792 </ p >
6893
6994 < div className = "rounded-xl border border-amber-100 bg-amber-50 p-4 mb-6 space-y-3" >
7095 < div >
71- < p className = "text-xs font-semibold text-gray-700 uppercase tracking-wide" > Dispute Reason</ p >
72- < p className = "text-sm font-medium text-gray-900 mt-1" > { reasonLabel } </ p >
96+ < p className = "text-xs font-semibold text-gray-700 uppercase tracking-wide" >
97+ Dispute Reason
98+ </ p >
99+ < p className = "text-sm font-medium text-gray-900 mt-1" >
100+ { reasonLabel }
101+ </ p >
73102 </ div >
74103 < div >
75- < p className = "text-xs font-semibold text-gray-700 uppercase tracking-wide" > Description</ p >
76- < p className = "text-sm text-gray-700 mt-1 break-words" > { description } </ p >
104+ < p className = "text-xs font-semibold text-gray-700 uppercase tracking-wide" >
105+ Description
106+ </ p >
107+ < p className = "text-sm text-gray-700 mt-1 break-words" >
108+ { description }
109+ </ p >
77110 </ div >
78111 </ div >
79112
80113 < div className = "rounded-lg border border-red-200 bg-red-50 p-4 mb-6" >
81114 < p className = "text-sm text-red-800" >
82- < strong > ⚠️ Important:</ strong > Your funds will be locked in escrow during arbitration. You will not be able to withdraw them until the dispute is resolved.
115+ < strong > ⚠️ Important:</ strong > Your funds will be locked in escrow
116+ during arbitration. You will not be able to withdraw them until the
117+ dispute is resolved.
83118 </ p >
84119 </ div >
85120
@@ -122,27 +157,32 @@ function SuccessView({
122157} : {
123158 disputeId ?: string ;
124159 transactionHash ?: string ;
125- } ) : JSX . Element {
160+ } ) : ReactElement {
126161 return (
127162 < div className = "text-center py-12" >
128163 < div className = "flex h-16 w-16 items-center justify-center rounded-full bg-green-100 mx-auto mb-4" >
129164 < CheckCircle2 className = "h-8 w-8 text-green-600" />
130165 </ div >
131- < h2 className = "text-2xl font-bold text-gray-900 mb-2" > Dispute Submitted</ h2 >
166+ < h2 className = "text-2xl font-bold text-gray-900 mb-2" >
167+ Dispute Submitted
168+ </ h2 >
132169 < p className = "text-gray-600 mb-6" >
133- Your dispute has been successfully opened. The escrow funds are now frozen.
170+ Your dispute has been successfully opened. The escrow funds are now
171+ frozen.
134172 </ p >
135173 { disputeId && (
136174 < div className = "bg-blue-50 border border-blue-200 rounded-lg p-4 mb-4" >
137175 < p className = "text-sm text-blue-900" >
138- < strong > Dispute ID:</ strong > < code className = "font-mono" > { disputeId } </ code >
176+ < strong > Dispute ID:</ strong > { ' ' }
177+ < code className = "font-mono" > { disputeId } </ code >
139178 </ p >
140179 </ div >
141180 ) }
142181 { transactionHash && (
143182 < div className = "bg-gray-50 border border-gray-200 rounded-lg p-4" >
144183 < p className = "text-sm text-gray-700 break-all" >
145- < strong > Transaction:</ strong > < code className = "font-mono text-xs" > { transactionHash } </ code >
184+ < strong > Transaction:</ strong > { ' ' }
185+ < code className = "font-mono text-xs" > { transactionHash } </ code >
146186 </ p >
147187 </ div >
148188 ) }
@@ -152,7 +192,7 @@ function SuccessView({
152192
153193/**
154194 * DisputeForm Component - Multi-step form for opening a delivery dispute
155- *
195+ *
156196 * Flow:
157197 * 1. Select dispute reason
158198 * 2. Upload evidence files
@@ -164,7 +204,7 @@ export default function DisputeForm({
164204 walletAddress,
165205 onSuccess,
166206 onError,
167- } : DisputeFormProps ) : JSX . Element {
207+ } : DisputeFormProps ) : ReactElement | null {
168208 const {
169209 register,
170210 handleSubmit,
@@ -176,7 +216,9 @@ export default function DisputeForm({
176216
177217 const [ currentStep , setCurrentStep ] = useState < FormStep > ( 'dispute_reason' ) ;
178218 const [ uploadedFiles , setUploadedFiles ] = useState < File [ ] > ( [ ] ) ;
179- const [ successData , setSuccessData ] = useState < OpenDisputeResponse | null > ( null ) ;
219+ const [ successData , setSuccessData ] = useState < OpenDisputeResponse | null > (
220+ null
221+ ) ;
180222 const fileInputRef = useRef < HTMLInputElement > ( null ) ;
181223
182224 const selectedReason = watch ( 'reason' ) ;
@@ -192,9 +234,11 @@ export default function DisputeForm({
192234 return ;
193235 }
194236
195- const validFiles = files . filter ( file => {
237+ const validFiles = files . filter ( ( file ) => {
196238 if ( ! file . type . startsWith ( 'image/' ) && file . type !== 'application/pdf' ) {
197- toast . error ( `${ file . name } is not a supported format. Use images or PDF.` ) ;
239+ toast . error (
240+ `${ file . name } is not a supported format. Use images or PDF.`
241+ ) ;
198242 return false ;
199243 }
200244 if ( file . size > 10 * 1024 * 1024 ) {
@@ -255,14 +299,21 @@ export default function DisputeForm({
255299 return (
256300 < div className = "w-full max-w-2xl mx-auto p-6" >
257301 < div className = "mb-8" >
258- < h1 className = "text-3xl font-bold text-gray-900 mb-2" > Open a Dispute</ h1 >
259- < p className = "text-gray-600" > Step 1 of 3: Select the reason for your dispute</ p >
302+ < h1 className = "text-3xl font-bold text-gray-900 mb-2" >
303+ Open a Dispute
304+ </ h1 >
305+ < p className = "text-gray-600" >
306+ Step 1 of 3: Select the reason for your dispute
307+ </ p >
260308 </ div >
261309
262310 < form onSubmit = { onSubmit } className = "space-y-6" >
263311 { /* Transaction ID */ }
264312 < div >
265- < label htmlFor = "transactionId" className = "block text-sm font-medium text-gray-700 mb-2" >
313+ < label
314+ htmlFor = "transactionId"
315+ className = "block text-sm font-medium text-gray-700 mb-2"
316+ >
266317 Transaction ID < span className = "text-red-500" > *</ span >
267318 </ label >
268319 < input
@@ -278,7 +329,9 @@ export default function DisputeForm({
278329 aria-invalid = { ! ! errors . transactionId }
279330 />
280331 { errors . transactionId && (
281- < p className = "mt-1 text-sm text-red-600" role = "alert" > { errors . transactionId . message } </ p >
332+ < p className = "mt-1 text-sm text-red-600" role = "alert" >
333+ { errors . transactionId . message }
334+ </ p >
282335 ) }
283336 </ div >
284337
@@ -305,19 +358,26 @@ export default function DisputeForm({
305358 />
306359 < div className = "ml-3" >
307360 < p className = "font-medium text-gray-900" > { reason . label } </ p >
308- < p className = "text-sm text-gray-600" > { reason . description } </ p >
361+ < p className = "text-sm text-gray-600" >
362+ { reason . description }
363+ </ p >
309364 </ div >
310365 </ label >
311366 ) ) }
312367 </ div >
313368 { errors . reason && (
314- < p className = "mt-2 text-sm text-red-600" role = "alert" > { errors . reason . message } </ p >
369+ < p className = "mt-2 text-sm text-red-600" role = "alert" >
370+ { errors . reason . message }
371+ </ p >
315372 ) }
316373 </ div >
317374
318375 { /* Description */ }
319376 < div >
320- < label htmlFor = "description" className = "block text-sm font-medium text-gray-700 mb-2" >
377+ < label
378+ htmlFor = "description"
379+ className = "block text-sm font-medium text-gray-700 mb-2"
380+ >
321381 Description < span className = "text-red-500" > *</ span >
322382 </ label >
323383 < textarea
@@ -334,9 +394,13 @@ export default function DisputeForm({
334394 />
335395 < div className = "mt-2 flex justify-between" >
336396 { errors . description && (
337- < p className = "text-sm text-red-600" role = "alert" > { errors . description . message } </ p >
397+ < p className = "text-sm text-red-600" role = "alert" >
398+ { errors . description . message }
399+ </ p >
338400 ) }
339- < p className = "text-xs text-gray-500" > { description ?. length || 0 } /500</ p >
401+ < p className = "text-xs text-gray-500" >
402+ { description ?. length || 0 } /500
403+ </ p >
340404 </ div >
341405 </ div >
342406
@@ -367,15 +431,20 @@ export default function DisputeForm({
367431 return (
368432 < div className = "w-full max-w-2xl mx-auto p-6" >
369433 < div className = "mb-8" >
370- < h1 className = "text-3xl font-bold text-gray-900 mb-2" > Upload Evidence</ h1 >
371- < p className = "text-gray-600" > Step 2 of 3: Attach photo evidence to support your dispute</ p >
434+ < h1 className = "text-3xl font-bold text-gray-900 mb-2" >
435+ Upload Evidence
436+ </ h1 >
437+ < p className = "text-gray-600" >
438+ Step 2 of 3: Attach photo evidence to support your dispute
439+ </ p >
372440 </ div >
373441
374442 < form onSubmit = { onSubmit } className = "space-y-6" >
375443 { /* File Upload */ }
376444 < div >
377445 < label className = "block text-sm font-medium text-gray-700 mb-3" >
378- Evidence Files < span className = "text-gray-500" > (optional, max 5 files)</ span >
446+ Evidence Files{ ' ' }
447+ < span className = "text-gray-500" > (optional, max 5 files)</ span >
379448 </ label >
380449
381450 < div className = "border-2 border-dashed border-gray-300 rounded-lg p-6 text-center hover:border-blue-500 transition" >
@@ -406,14 +475,18 @@ export default function DisputeForm({
406475 { /* Uploaded Files List */ }
407476 { uploadedFiles . length > 0 && (
408477 < div className = "mt-4 space-y-2" >
409- < p className = "text-sm font-medium text-gray-900" > Uploaded Files ({ uploadedFiles . length } )</ p >
478+ < p className = "text-sm font-medium text-gray-900" >
479+ Uploaded Files ({ uploadedFiles . length } )
480+ </ p >
410481 { uploadedFiles . map ( ( file , index ) => (
411482 < div
412483 key = { `${ file . name } -${ index } ` }
413484 className = "flex items-center justify-between p-3 bg-gray-50 rounded-lg border border-gray-200"
414485 >
415486 < div className = "flex-1 min-w-0" >
416- < p className = "text-sm font-medium text-gray-900 truncate" > { file . name } </ p >
487+ < p className = "text-sm font-medium text-gray-900 truncate" >
488+ { file . name }
489+ </ p >
417490 < p className = "text-xs text-gray-500" >
418491 { ( file . size / 1024 / 1024 ) . toFixed ( 2 ) } MB
419492 </ p >
0 commit comments