Skip to content

Commit b7b3d8c

Browse files
committed
fsees
1 parent f100632 commit b7b3d8c

8 files changed

Lines changed: 109 additions & 33 deletions

File tree

components/escrow/DisputeForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export default function DisputeForm({
204204
walletAddress,
205205
onSuccess,
206206
onError,
207-
}: DisputeFormProps): ReactElement {
207+
}: DisputeFormProps): ReactElement | null {
208208
const {
209209
register,
210210
handleSubmit,

components/shared/FileUpload.tsx

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
'use client';
22

33
import { useFileUpload } from '@/hooks/useFileUpload';
4-
import { Upload, X, CheckCircle2, AlertCircle, File, Image } from 'lucide-react';
4+
import {
5+
Upload,
6+
X,
7+
CheckCircle2,
8+
AlertCircle,
9+
File,
10+
Image,
11+
} from 'lucide-react';
512
import { useCallback, useState } from 'react';
613

714
interface FileUploadProps {
@@ -35,8 +42,15 @@ export function FileUpload({
3542
title = 'Upload Documents',
3643
description = 'Drag and drop your files here or click to browse',
3744
}: FileUploadProps) {
38-
const { files, isUploading, validationErrors, addFiles, removeFile, uploadAll, clearAll } =
39-
useFileUpload();
45+
const {
46+
files,
47+
isUploading,
48+
validationErrors,
49+
addFiles,
50+
removeFile,
51+
uploadAll,
52+
clearAll,
53+
} = useFileUpload();
4054

4155
const [isDragging, setIsDragging] = useState(false);
4256

@@ -78,7 +92,11 @@ export function FileUpload({
7892
);
7993

8094
const handleUpload = async () => {
81-
const fileIds = await uploadAll(fileType);
95+
await uploadAll(fileType);
96+
const fileIds = files
97+
.filter((file) => file.uploadStatus === 'success' && file.fileId)
98+
.map((file) => file.fileId as string);
99+
82100
if (onUploadComplete && fileIds.length > 0) {
83101
onUploadComplete(fileIds);
84102
}
@@ -97,8 +115,12 @@ export function FileUpload({
97115
<div className="space-y-6 rounded-xl border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-900">
98116
{/* Header */}
99117
<div>
100-
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">{title}</h3>
101-
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">{description}</p>
118+
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
119+
{title}
120+
</h3>
121+
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
122+
{description}
123+
</p>
102124
</div>
103125

104126
{/* Validation Errors */}
@@ -109,7 +131,10 @@ export function FileUpload({
109131
<div className="flex-1">
110132
{validationErrors.map((error, idx) => (
111133
<p key={idx} className="text-sm text-red-700 dark:text-red-300">
112-
<span className="font-semibold">{error.field.toUpperCase()}:</span> {error.message}
134+
<span className="font-semibold">
135+
{error.field.toUpperCase()}:
136+
</span>{' '}
137+
{error.message}
113138
</p>
114139
))}
115140
</div>
@@ -159,7 +184,9 @@ export function FileUpload({
159184
: 'text-gray-900 dark:text-gray-100'
160185
}`}
161186
>
162-
{isDragging ? 'Drop your files here' : 'Click to upload or drag and drop'}
187+
{isDragging
188+
? 'Drop your files here'
189+
: 'Click to upload or drag and drop'}
163190
</p>
164191
<p className="text-xs text-gray-600 dark:text-gray-400">
165192
JPEG, PNG, or PDF up to 5MB
@@ -226,7 +253,8 @@ export function FileUpload({
226253

227254
{file.uploadStatus === 'error' && (
228255
<p className="mt-1 flex items-center gap-1 text-xs font-medium text-red-600 dark:text-red-400">
229-
<AlertCircle className="h-3 w-3" /> {file.error || 'Upload failed'}
256+
<AlertCircle className="h-3 w-3" />{' '}
257+
{file.error || 'Upload failed'}
230258
</p>
231259
)}
232260
</div>
@@ -278,8 +306,8 @@ export function FileUpload({
278306
<CheckCircle2 className="h-5 w-5 flex-shrink-0 text-green-600 dark:text-green-400" />
279307
<div>
280308
<p className="text-sm font-medium text-green-800 dark:text-green-300">
281-
{successFiles.length} file{successFiles.length !== 1 ? 's' : ''} uploaded
282-
successfully!
309+
{successFiles.length} file{successFiles.length !== 1 ? 's' : ''}{' '}
310+
uploaded successfully!
283311
</p>
284312
</div>
285313
</div>
@@ -288,7 +316,9 @@ export function FileUpload({
288316

289317
{/* Constraints */}
290318
<div className="space-y-2 rounded-lg bg-gray-50 p-3 dark:bg-gray-800/50">
291-
<p className="text-xs font-semibold text-gray-700 dark:text-gray-300">Constraints:</p>
319+
<p className="text-xs font-semibold text-gray-700 dark:text-gray-300">
320+
Constraints:
321+
</p>
292322
<ul className="space-y-1 text-xs text-gray-600 dark:text-gray-400">
293323
<li>• Maximum file size: 5MB</li>
294324
<li>• Allowed formats: JPEG, PNG, PDF</li>

features/escrow/components/EscrowLock.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,14 @@ export function EscrowLock({
2626
}: EscrowLockProps) {
2727
const [showConfirmation, setShowConfirmation] = useState(false);
2828
const [state, setState] = useState<LockState>('idle');
29-
const { isLoading, error, escrowId, transactionHash, lockEscrow, reset } = useEscrowLock();
30-
const { toast } = useToast();
29+
const { isLoading, error, escrowId, transactionHash, lockEscrow, reset } =
30+
useEscrowLock();
31+
const {
32+
error: toastError,
33+
success: toastSuccess,
34+
loading: toastLoading,
35+
info: toastInfo,
36+
} = useToast();
3137

3238
const isWalletConnected = !!walletAddress;
3339
const formattedAmount = amount.toFixed(2);
@@ -48,23 +54,24 @@ export function EscrowLock({
4854
const handleConfirm = async () => {
4955
setShowConfirmation(false);
5056
setState('pending');
51-
57+
5258
try {
5359
await lockEscrow({
5460
deliveryId,
5561
amount,
5662
currency,
5763
walletAddress: walletAddress!,
5864
});
59-
65+
6066
setState('success');
6167
toast({
6268
title: 'Success!',
6369
description: `Escrow locked! Transaction: ${transactionHash?.slice(0, 10)}...`,
6470
});
6571
onSuccess?.(escrowId!, transactionHash!);
6672
} catch (err) {
67-
const errorMsg = err instanceof Error ? err.message : 'Failed to lock escrow';
73+
const errorMsg =
74+
err instanceof Error ? err.message : 'Failed to lock escrow';
6875
setState('error');
6976
toast({
7077
title: 'Error',
@@ -99,7 +106,9 @@ export function EscrowLock({
99106
Your escrow payment has been securely locked.
100107
</p>
101108
<div className="bg-gray-50 dark:bg-gray-700 rounded p-3 w-full mb-4">
102-
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Transaction Hash</p>
109+
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">
110+
Transaction Hash
111+
</p>
103112
<p className="text-sm font-mono text-gray-900 dark:text-white break-all">
104113
{transactionHash}
105114
</p>
@@ -146,7 +155,9 @@ export function EscrowLock({
146155
<>
147156
<div className="w-full max-w-md mx-auto p-6 bg-white dark:bg-gray-800 rounded-lg shadow border border-gray-200 dark:border-gray-700">
148157
<div className="text-center mb-6">
149-
<p className="text-sm text-gray-600 dark:text-gray-400 mb-2">Total Cost</p>
158+
<p className="text-sm text-gray-600 dark:text-gray-400 mb-2">
159+
Total Cost
160+
</p>
150161
<p className="text-4xl font-bold text-gray-900 dark:text-white">
151162
{formattedAmount} {currency}
152163
</p>
@@ -179,8 +190,8 @@ export function EscrowLock({
179190
isLoading
180191
? 'bg-blue-500 text-white cursor-wait'
181192
: isWalletConnected
182-
? 'bg-primary text-white hover:bg-primary-dark'
183-
: 'bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400 cursor-not-allowed'
193+
? 'bg-primary text-white hover:bg-primary-dark'
194+
: 'bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400 cursor-not-allowed'
184195
}`}
185196
>
186197
{isLoading ? (
@@ -197,7 +208,9 @@ export function EscrowLock({
197208
</button>
198209

199210
<p className="text-xs text-gray-500 dark:text-gray-400 text-center mt-4">
200-
{isWalletConnected ? 'Wallet connected' : 'Wallet status: disconnected'}
211+
{isWalletConnected
212+
? 'Wallet connected'
213+
: 'Wallet status: disconnected'}
201214
</p>
202215
</div>
203216

features/shipments/components/HandoffQR.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import React, { useEffect, useState } from 'react';
4-
import QRCode from 'qrcode.react';
4+
import { QRCodeCanvas } from 'qrcode.react';
55
import {
66
useHandoffQR,
77
useGenerateHandoffQR,

hooks/useProofUpload.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,15 @@ export function useProofUpload({
5151
const [isCompressing, setIsCompressing] = useState(false);
5252
const [uploadedProofs, setUploadedProofs] = useState<UploadedProof[]>([]);
5353
const [errors, setErrors] = useState<string[]>([]);
54-
const { toast } = useToast();
54+
const { error: toastError, success: toastSuccess, loading: toastLoading, info: toastInfo } = useToast();
5555

5656
const handleFileCapture = useCallback(
5757
async (file: File) => {
5858
// Validate file type
5959
if (!file.type.startsWith('image/')) {
6060
const errorMsg = 'Please select an image file';
6161
setErrors((prev) => [...prev, errorMsg]);
62-
toast({
63-
title: 'Invalid File',
64-
description: errorMsg,
65-
variant: 'destructive',
66-
});
62+
toastError(errorMsg);
6763
return;
6864
}
6965

pnpm-lock.yaml

Lines changed: 15 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/escrowService.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ export interface LockEscrowResponse {
4949
lockedAmount: string;
5050
}
5151

52+
export interface OpenDisputeParams {
53+
deliveryId: string;
54+
transactionId: string;
55+
reason: 'damaged_items' | 'non_delivery' | 'incorrect_items' | 'other';
56+
description: string;
57+
evidenceFiles?: File[];
58+
walletAddress: string;
59+
}
60+
61+
export interface OpenDisputeResponse {
62+
success: boolean;
63+
message: string;
64+
disputeId?: string;
65+
transactionHash?: string;
66+
}
67+
5268
/**
5369
* escrowService — responsible for all escrow-related API communication.
5470
* The hook calls this; components never call this directly.
@@ -84,4 +100,12 @@ export const escrowService = {
84100
);
85101
return data;
86102
},
103+
104+
async openDispute(params: OpenDisputeParams): Promise<OpenDisputeResponse> {
105+
const { data } = await axios.post<OpenDisputeResponse>(
106+
`${API_BASE_URL}/api/escrow/dispute`,
107+
params
108+
);
109+
return data;
110+
},
87111
};

tsconfig.tsbuildinfo

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)