From 2b4179cf49eda8e343bcabfa949249c4b9d620dd Mon Sep 17 00:00:00 2001
From: shamoo53
Date: Fri, 30 Jan 2026 16:50:53 +0100
Subject: [PATCH 1/2] implemented the Escrow detail page
---
apps/frontend/app/escrow/[id]/page.tsx | 110 ++++++++++++++
.../components/escrow/detail/EscrowHeader.tsx | 110 ++++++++++++++
.../escrow/detail/PartiesSection.tsx | 94 ++++++++++++
.../components/escrow/detail/TermsSection.tsx | 102 +++++++++++++
.../escrow/detail/TimelineSection.tsx | 142 ++++++++++++++++++
.../escrow/detail/TransactionHistory.tsx | 94 ++++++++++++
apps/frontend/hooks/useEscrow.ts | 41 +++++
apps/frontend/hooks/useWallet.ts | 19 +++
apps/frontend/package-lock.json | 10 --
apps/frontend/types/escrow.d.ts | 58 +++++++
10 files changed, 770 insertions(+), 10 deletions(-)
create mode 100644 apps/frontend/app/escrow/[id]/page.tsx
create mode 100644 apps/frontend/components/escrow/detail/EscrowHeader.tsx
create mode 100644 apps/frontend/components/escrow/detail/PartiesSection.tsx
create mode 100644 apps/frontend/components/escrow/detail/TermsSection.tsx
create mode 100644 apps/frontend/components/escrow/detail/TimelineSection.tsx
create mode 100644 apps/frontend/components/escrow/detail/TransactionHistory.tsx
create mode 100644 apps/frontend/hooks/useEscrow.ts
create mode 100644 apps/frontend/hooks/useWallet.ts
create mode 100644 apps/frontend/types/escrow.d.ts
diff --git a/apps/frontend/app/escrow/[id]/page.tsx b/apps/frontend/app/escrow/[id]/page.tsx
new file mode 100644
index 0000000..4a3ba08
--- /dev/null
+++ b/apps/frontend/app/escrow/[id]/page.tsx
@@ -0,0 +1,110 @@
+'use client';
+
+import { useState, useEffect } from 'react';
+import { useParams } from 'next/navigation';
+import Link from 'next/link';
+import { useEscrow } from '@/hooks/useEscrow';
+import { useWallet } from '@/hooks/useWallet';
+import EscrowHeader from '@/components/escrow/detail/EscrowHeader';
+import PartiesSection from '@/components/escrow/detail/PartiesSection';
+import TermsSection from '@/components/escrow/detail/TermsSection';
+import TimelineSection from '@/components/escrow/detail/TimelineSection';
+import TransactionHistory from '@/components/escrow/detail/TransactionHistory';
+import { Escrow } from '@/types/escrow';
+
+const EscrowDetailPage = () => {
+ const { id } = useParams();
+ const { escrow, loading, error } = useEscrow(id as string);
+ const { connected, publicKey, connect } = useWallet(); // Assuming wallet hook exists
+ const [userRole, setUserRole] = useState<'creator' | 'counterparty' | null>(null);
+
+ useEffect(() => {
+ if (escrow && publicKey) {
+ if (escrow.creatorId === publicKey) {
+ setUserRole('creator');
+ } else if (escrow.parties?.some((party: any) => party.userId === publicKey)) {
+ setUserRole('counterparty');
+ }
+ }
+ }, [escrow, publicKey]);
+
+ if (loading) {
+ return (
+
+
+
+
Loading escrow details...
+
+
+ );
+ }
+
+ if (error) {
+ return (
+
+
+
Error Loading Escrow
+
{error}
+
+
+
+ );
+ }
+
+ if (!escrow) {
+ return (
+
+
+
Escrow Not Found
+
The requested escrow agreement could not be found.
+
+ Back to Escrows
+
+
+
+ );
+ }
+
+ return (
+
+
+ {/* Header Section */}
+
+
+
+
+ {/* Parties Section */}
+
+
+ {/* Timeline Section */}
+
+
+ {/* Transaction History */}
+
+
+
+
+ {/* Terms Section */}
+
+
+
+
+
+ );
+};
+
+export default EscrowDetailPage;
\ No newline at end of file
diff --git a/apps/frontend/components/escrow/detail/EscrowHeader.tsx b/apps/frontend/components/escrow/detail/EscrowHeader.tsx
new file mode 100644
index 0000000..366cce4
--- /dev/null
+++ b/apps/frontend/components/escrow/detail/EscrowHeader.tsx
@@ -0,0 +1,110 @@
+import React from 'react';
+import { Share, Copy, Wallet, Clock, CheckCircle, AlertTriangle, XCircle, ShareIcon } from 'lucide-react';
+import { Escrow } from '@/types/escrow';
+
+interface EscrowHeaderProps {
+ escrow: Escrow;
+ userRole: 'creator' | 'counterparty' | null;
+ connected: boolean;
+ connect: () => void;
+ publicKey: string | null;
+}
+
+const getStatusColor = (status: string) => {
+ switch (status.toLowerCase()) {
+ case 'pending':
+ return 'bg-yellow-100 text-yellow-800';
+ case 'active':
+ return 'bg-blue-100 text-blue-800';
+ case 'completed':
+ return 'bg-green-100 text-green-800';
+ case 'cancelled':
+ return 'bg-gray-100 text-gray-800';
+ case 'disputed':
+ return 'bg-red-100 text-red-800';
+ default:
+ return 'bg-gray-100 text-gray-800';
+ }
+};
+
+const getStatusIcon = (status: string) => {
+ switch (status.toLowerCase()) {
+ case 'pending':
+ return ;
+ case 'active':
+ return ;
+ case 'completed':
+ return ;
+ case 'cancelled':
+ return ;
+ case 'disputed':
+ return ;
+ default:
+ return ;
+ }
+};
+
+const EscrowHeader: React.FC = ({
+ escrow,
+ userRole,
+ connected,
+ connect,
+ publicKey
+}: EscrowHeaderProps) => {
+ const handleCopyLink = () => {
+ navigator.clipboard.writeText(window.location.href);
+ alert('Link copied to clipboard!');
+ };
+
+ return (
+
+
+
+
+
{escrow.title}
+
+ {getStatusIcon(escrow.status)}
+ {escrow.status}
+
+
+
{escrow.description}
+
+
+
+ ID:
+ {escrow.id.substring(0, 8)}...
+
+
+ Amount:
+ {Number(escrow.amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 7 })} {escrow.asset}
+
+
+ Created:
+ {new Date(escrow.createdAt).toLocaleDateString()}
+
+
+
+
+
+
+ {!connected && (
+
+ )}
+
+
+
+ );
+};
+
+export default EscrowHeader;
\ No newline at end of file
diff --git a/apps/frontend/components/escrow/detail/PartiesSection.tsx b/apps/frontend/components/escrow/detail/PartiesSection.tsx
new file mode 100644
index 0000000..2d45e8e
--- /dev/null
+++ b/apps/frontend/components/escrow/detail/PartiesSection.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { Escrow } from '@/types/escrow';
+
+interface PartiesSectionProps {
+ escrow: Escrow;
+ userRole: 'creator' | 'counterparty' | null;
+}
+
+const getRoleColor = (role: string) => {
+ switch (role.toUpperCase()) {
+ case 'BUYER':
+ return 'bg-blue-100 text-blue-800';
+ case 'SELLER':
+ return 'bg-green-100 text-green-800';
+ case 'ARBITRATOR':
+ return 'bg-purple-100 text-purple-800';
+ default:
+ return 'bg-gray-100 text-gray-800';
+ }
+};
+
+const getStatusColor = (status: string) => {
+ switch (status.toUpperCase()) {
+ case 'ACCEPTED':
+ return 'bg-green-100 text-green-800';
+ case 'REJECTED':
+ return 'bg-red-100 text-red-800';
+ case 'PENDING':
+ return 'bg-yellow-100 text-yellow-800';
+ default:
+ return 'bg-gray-100 text-gray-800';
+ }
+};
+
+const PartiesSection: React.FC = ({ escrow, userRole }: PartiesSectionProps) => {
+ return (
+
+
Parties
+
+
+ {escrow.parties.map((party) => (
+
+
+
+
+
+ {party.role}
+
+
+ {party.status}
+
+
+
+ User ID: {party.userId}
+
+
+
+ {userRole === 'creator' && party.status === 'PENDING' && (
+
+
+
+
+ )}
+
+
+ ))}
+
+
+ {escrow.conditions && escrow.conditions.length > 0 && (
+
+
Conditions
+
+ {escrow.conditions.map((condition) => (
+ -
+
+
{condition.description}
+
+ ))}
+
+
+ )}
+
+ );
+};
+
+export default PartiesSection;
\ No newline at end of file
diff --git a/apps/frontend/components/escrow/detail/TermsSection.tsx b/apps/frontend/components/escrow/detail/TermsSection.tsx
new file mode 100644
index 0000000..8975d75
--- /dev/null
+++ b/apps/frontend/components/escrow/detail/TermsSection.tsx
@@ -0,0 +1,102 @@
+import React, { useState, useEffect } from 'react';
+import { Escrow } from '@/types/escrow';
+
+interface TermsSectionProps {
+ escrow: Escrow;
+ userRole: 'creator' | 'counterparty' | null;
+}
+
+const TermsSection: React.FC = ({ escrow, userRole }: TermsSectionProps) => {
+ const [timeLeft, setTimeLeft] = useState('');
+
+ useEffect(() => {
+ if (escrow.expiresAt) {
+ const calculateTimeLeft = () => {
+ const expiryDate = new Date(escrow.expiresAt!);
+ const now = new Date();
+ const difference = expiryDate.getTime() - now.getTime();
+
+ if (difference <= 0) {
+ return 'Expired';
+ }
+
+ const days = Math.floor(difference / (1000 * 60 * 60 * 24));
+ const hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
+ const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
+
+ return `${days}d ${hours}h ${minutes}m`;
+ };
+
+ setTimeLeft(calculateTimeLeft());
+ const timer = setInterval(() => {
+ setTimeLeft(calculateTimeLeft());
+ }, 60000); // Update every minute
+
+ return () => clearInterval(timer);
+ }
+ }, [escrow.expiresAt]);
+
+ return (
+
+
Terms & Actions
+
+
+
+
Agreement Details
+
+
+
- Amount
+ - {Number(escrow.amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 7 })} {escrow.asset}
+
+
+
- Type
+ - {escrow.type}
+
+
+
- Status
+ - {escrow.status}
+
+ {escrow.expiresAt && (
+
+
- Expires
+ -
+ {new Date(escrow.expiresAt).toLocaleDateString()}
+
+ {timeLeft}
+
+
+ )}
+
+
+
+ {/* Action buttons based on user role and escrow status */}
+
+ {userRole === 'creator' && escrow.status === 'PENDING' && (
+
+ )}
+
+ {userRole === 'counterparty' && escrow.status === 'ACTIVE' && (
+ <>
+
+
+ >
+ )}
+
+ {(userRole === 'creator' || userRole === 'counterparty') && escrow.status === 'ACTIVE' && (
+
+ )}
+
+
+
+ );
+};
+
+export default TermsSection;
\ No newline at end of file
diff --git a/apps/frontend/components/escrow/detail/TimelineSection.tsx b/apps/frontend/components/escrow/detail/TimelineSection.tsx
new file mode 100644
index 0000000..8d24608
--- /dev/null
+++ b/apps/frontend/components/escrow/detail/TimelineSection.tsx
@@ -0,0 +1,142 @@
+import React from 'react';
+import { Escrow } from '@/types/escrow';
+
+interface TimelineSectionProps {
+ escrow: Escrow;
+}
+
+const getEventIcon = (eventType: string) => {
+ switch (eventType.toUpperCase()) {
+ case 'CREATED':
+ return (
+
+
+
+ );
+ case 'FUNDED':
+ return (
+
+
+
+ );
+ case 'CONDITION_MET':
+ return (
+
+
+
+ );
+ case 'COMPLETED':
+ return (
+
+
+
+ );
+ case 'CANCELLED':
+ return (
+
+
+
+ );
+ default:
+ return (
+
+
+
+ );
+ }
+};
+
+const getEventColor = (eventType: string) => {
+ switch (eventType.toUpperCase()) {
+ case 'CREATED':
+ return 'bg-blue-50 text-blue-700';
+ case 'FUNDED':
+ return 'bg-green-50 text-green-700';
+ case 'CONDITION_MET':
+ return 'bg-yellow-50 text-yellow-700';
+ case 'COMPLETED':
+ return 'bg-purple-50 text-purple-700';
+ case 'CANCELLED':
+ return 'bg-red-50 text-red-700';
+ default:
+ return 'bg-gray-50 text-gray-700';
+ }
+};
+
+const TimelineSection: React.FC = ({ escrow }: TimelineSectionProps) => {
+ // Sort events by date, with the newest first
+ const sortedEvents = [...escrow.events].sort((a, b) =>
+ new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
+ );
+
+ return (
+
+
Timeline
+
+ {sortedEvents.length === 0 ? (
+
No events recorded yet.
+ ) : (
+
+
+ {sortedEvents.map((event, index) => (
+ -
+
+ {index !== sortedEvents.length - 1 ? (
+
+ ) : null}
+
+
{getEventIcon(event.eventType)}
+
+
+
+
+ {event.eventType.replace(/_/g, ' ').toLowerCase()}
+
+
+ {event.eventType === 'CREATED' && 'Escrow agreement created'}
+ {event.eventType === 'FUNDED' && 'Escrow funded'}
+ {event.eventType === 'CONDITION_MET' && 'Condition met'}
+ {event.eventType === 'COMPLETED' && 'Escrow completed'}
+ {event.eventType === 'CANCELLED' && 'Escrow cancelled'}
+ {event.eventType === 'PARTY_ACCEPTED' && 'Party accepted the agreement'}
+ {event.eventType === 'PARTY_REJECTED' && 'Party rejected the agreement'}
+ {event.eventType === 'PARTY_ADDED' && 'Party added to the agreement'}
+ {event.eventType === 'DISPUTED' && 'Dispute raised'}
+ {event.eventType === 'STATUS_CHANGED' && 'Status changed'}
+ {event.eventType === 'UPDATED' && 'Agreement updated'}
+
+
+ {event.data && Object.keys(event.data).length > 0 && (
+
+
{JSON.stringify(event.data, null, 2)}
+
+ )}
+
+
+ {new Date(event.createdAt).toLocaleString()}
+
+
+
+
+
+ ))}
+
+
+ )}
+
+ );
+};
+
+export default TimelineSection;
\ No newline at end of file
diff --git a/apps/frontend/components/escrow/detail/TransactionHistory.tsx b/apps/frontend/components/escrow/detail/TransactionHistory.tsx
new file mode 100644
index 0000000..f1b1d67
--- /dev/null
+++ b/apps/frontend/components/escrow/detail/TransactionHistory.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import { Escrow } from '@/types/escrow';
+
+interface TransactionHistoryProps {
+ escrow: Escrow;
+}
+
+const TransactionHistory: React.FC = ({ escrow }: TransactionHistoryProps) => {
+ // Filter events that represent transactions
+ const transactionEvents = escrow.events.filter(event =>
+ event.eventType === 'FUNDED' ||
+ event.eventType === 'CONDITION_MET' ||
+ event.eventType === 'COMPLETED' ||
+ event.eventType === 'CANCELLED'
+ );
+
+ return (
+
+
Transaction History
+
+ {transactionEvents.length === 0 ? (
+
No transaction history available.
+ ) : (
+
+
+
+
+ |
+ Type
+ |
+
+ Amount
+ |
+
+ Status
+ |
+
+ Date
+ |
+
+ Transaction
+ |
+
+
+
+ {transactionEvents.map((event) => (
+
+ |
+
+ {event.eventType.replace(/_/g, ' ').toLowerCase()}
+
+ |
+
+
+ {event.eventType === 'FUNDED' && `${Number(escrow.amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 7 })} ${escrow.asset}`}
+ {event.eventType === 'COMPLETED' && `${Number(escrow.amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 7 })} ${escrow.asset}`}
+ {event.eventType === 'CANCELLED' && '0 XLM'}
+ {event.eventType === 'CONDITION_MET' && 'Variable'}
+
+ |
+
+
+ {event.eventType === 'COMPLETED' ? 'Completed' :
+ event.eventType === 'CANCELLED' ? 'Cancelled' : 'Processed'}
+
+ |
+
+ {new Date(event.createdAt).toLocaleDateString()}
+ |
+
+ {event.data?.transactionHash ? (
+
+ View Transaction
+
+ ) : (
+ N/A
+ )}
+ |
+
+ ))}
+
+
+
+ )}
+
+ );
+};
+
+export default TransactionHistory;
\ No newline at end of file
diff --git a/apps/frontend/hooks/useEscrow.ts b/apps/frontend/hooks/useEscrow.ts
new file mode 100644
index 0000000..54d1565
--- /dev/null
+++ b/apps/frontend/hooks/useEscrow.ts
@@ -0,0 +1,41 @@
+import { useState, useEffect } from 'react';
+import { Escrow, UseEscrowReturn } from '@/types/escrow';
+
+export const useEscrow = (id: string): UseEscrowReturn => {
+ const [escrow, setEscrow] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchEscrow = async () => {
+ try {
+ setLoading(true);
+ const response = await fetch(`/api/escrows/${id}`);
+
+ if (!response.ok) {
+ if (response.status === 404) {
+ setError('Escrow not found');
+ } else {
+ setError('Failed to load escrow details');
+ }
+ return;
+ }
+
+ const data = await response.json();
+ setEscrow(data);
+ setError(null);
+ } catch (err) {
+ setError('An error occurred while fetching escrow details');
+ console.error('Error fetching escrow:', err);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (id) {
+ fetchEscrow();
+ }
+ }, [id]);
+
+ return { escrow, loading, error };
+};
\ No newline at end of file
diff --git a/apps/frontend/hooks/useWallet.ts b/apps/frontend/hooks/useWallet.ts
new file mode 100644
index 0000000..b1f849b
--- /dev/null
+++ b/apps/frontend/hooks/useWallet.ts
@@ -0,0 +1,19 @@
+import { useState } from 'react';
+import { WalletHookReturn } from '@/types/escrow';
+
+export const useWallet = (): WalletHookReturn => {
+ const [connected, setConnected] = useState(false);
+ const [publicKey, setPublicKey] = useState(null);
+
+ const connect = () => {
+ // Mock implementation - in real app this would connect to a wallet provider
+ setConnected(true);
+ setPublicKey('GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H'); // Mock public key
+ };
+
+ return {
+ connected,
+ publicKey,
+ connect
+ };
+};
\ No newline at end of file
diff --git a/apps/frontend/package-lock.json b/apps/frontend/package-lock.json
index 02fc5af..4c2e3ba 100644
--- a/apps/frontend/package-lock.json
+++ b/apps/frontend/package-lock.json
@@ -1294,7 +1294,6 @@
"integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -1354,7 +1353,6 @@
"integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.53.1",
"@typescript-eslint/types": "8.53.1",
@@ -1861,7 +1859,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2856,7 +2853,6 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -3026,7 +3022,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -5388,7 +5383,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -5398,7 +5392,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
@@ -5411,7 +5404,6 @@
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz",
"integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18.0.0"
},
@@ -6223,7 +6215,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -6424,7 +6415,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/apps/frontend/types/escrow.d.ts b/apps/frontend/types/escrow.d.ts
new file mode 100644
index 0000000..50cfa42
--- /dev/null
+++ b/apps/frontend/types/escrow.d.ts
@@ -0,0 +1,58 @@
+// Define types based on backend entities
+export interface Party {
+ id: string;
+ userId: string;
+ role: 'BUYER' | 'SELLER' | 'ARBITRATOR';
+ status: 'PENDING' | 'ACCEPTED' | 'REJECTED';
+ createdAt: string;
+}
+
+export interface Condition {
+ id: string;
+ description: string;
+ type: string;
+ metadata?: Record;
+}
+
+export interface EscrowEvent {
+ id: string;
+ eventType: 'CREATED' | 'PARTY_ADDED' | 'PARTY_ACCEPTED' | 'PARTY_REJECTED' | 'FUNDED' | 'CONDITION_MET' | 'STATUS_CHANGED' | 'UPDATED' | 'CANCELLED' | 'COMPLETED' | 'DISPUTED';
+ actorId?: string;
+ data?: Record;
+ ipAddress?: string;
+ createdAt: string;
+}
+
+export interface Escrow {
+ id: string;
+ title: string;
+ description?: string;
+ amount: number;
+ asset: string;
+ status: 'PENDING' | 'ACTIVE' | 'COMPLETED' | 'CANCELLED' | 'DISPUTED';
+ type: 'STANDARD' | 'MILESTONE' | 'TIMED';
+ creatorId: string;
+ expiresAt?: string;
+ isActive: boolean;
+ creator: {
+ id: string;
+ walletAddress?: string;
+ };
+ parties: Party[];
+ conditions: Condition[];
+ events: EscrowEvent[];
+ createdAt: string;
+ updatedAt: string;
+}
+
+export interface UseEscrowReturn {
+ escrow: Escrow | null;
+ loading: boolean;
+ error: string | null;
+}
+
+export interface WalletHookReturn {
+ connected: boolean;
+ publicKey: string | null;
+ connect: () => void;
+}
\ No newline at end of file
From c3eb7bd2ae6466b50b8eec9fd8d4360284d7ed5a Mon Sep 17 00:00:00 2001
From: shamoo53
Date: Fri, 30 Jan 2026 20:44:50 +0100
Subject: [PATCH 2/2] fixes
---
apps/frontend/app/escrow/[id]/page.tsx | 2 +-
apps/frontend/app/page.tsx | 23 ++++----
.../components/escrow/detail/EscrowHeader.tsx | 4 +-
.../escrow/detail/PartiesSection.tsx | 8 +--
.../components/escrow/detail/TermsSection.tsx | 4 +-
.../escrow/detail/TimelineSection.tsx | 4 +-
.../escrow/detail/TransactionHistory.tsx | 8 +--
apps/frontend/hooks/useEscrow.ts | 6 +-
apps/frontend/hooks/useWallet.ts | 4 +-
apps/frontend/types/escrow.d.ts | 58 -------------------
apps/frontend/types/escrow.ts | 53 ++++++++++++++++-
11 files changed, 84 insertions(+), 90 deletions(-)
delete mode 100644 apps/frontend/types/escrow.d.ts
diff --git a/apps/frontend/app/escrow/[id]/page.tsx b/apps/frontend/app/escrow/[id]/page.tsx
index 4a3ba08..ad72f70 100644
--- a/apps/frontend/app/escrow/[id]/page.tsx
+++ b/apps/frontend/app/escrow/[id]/page.tsx
@@ -10,7 +10,7 @@ import PartiesSection from '@/components/escrow/detail/PartiesSection';
import TermsSection from '@/components/escrow/detail/TermsSection';
import TimelineSection from '@/components/escrow/detail/TimelineSection';
import TransactionHistory from '@/components/escrow/detail/TransactionHistory';
-import { Escrow } from '@/types/escrow';
+import { IEscrowExtended } from '@/types/escrow';
const EscrowDetailPage = () => {
const { id } = useParams();
diff --git a/apps/frontend/app/page.tsx b/apps/frontend/app/page.tsx
index 432c880..da685af 100644
--- a/apps/frontend/app/page.tsx
+++ b/apps/frontend/app/page.tsx
@@ -1,4 +1,5 @@
-import Image from "next/image";
+ import Image from "next/image";
+ import Link from "next/link";
export default function Home() {
return (
@@ -27,18 +28,18 @@ export default function Home() {
@@ -64,26 +65,26 @@ export default function Home() {
);
diff --git a/apps/frontend/components/escrow/detail/EscrowHeader.tsx b/apps/frontend/components/escrow/detail/EscrowHeader.tsx
index 366cce4..b320136 100644
--- a/apps/frontend/components/escrow/detail/EscrowHeader.tsx
+++ b/apps/frontend/components/escrow/detail/EscrowHeader.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import { Share, Copy, Wallet, Clock, CheckCircle, AlertTriangle, XCircle, ShareIcon } from 'lucide-react';
-import { Escrow } from '@/types/escrow';
+import { IEscrowExtended } from '@/types/escrow';
interface EscrowHeaderProps {
- escrow: Escrow;
+ escrow: IEscrowExtended;
userRole: 'creator' | 'counterparty' | null;
connected: boolean;
connect: () => void;
diff --git a/apps/frontend/components/escrow/detail/PartiesSection.tsx b/apps/frontend/components/escrow/detail/PartiesSection.tsx
index 2d45e8e..730682d 100644
--- a/apps/frontend/components/escrow/detail/PartiesSection.tsx
+++ b/apps/frontend/components/escrow/detail/PartiesSection.tsx
@@ -1,8 +1,8 @@
import React from 'react';
-import { Escrow } from '@/types/escrow';
+import { IEscrowExtended } from '@/types/escrow';
interface PartiesSectionProps {
- escrow: Escrow;
+ escrow: IEscrowExtended;
userRole: 'creator' | 'counterparty' | null;
}
@@ -38,7 +38,7 @@ const PartiesSection: React.FC = ({ escrow, userRole }: Par
Parties
- {escrow.parties.map((party) => (
+ {escrow.parties.map((party: any) => (
@@ -74,7 +74,7 @@ const PartiesSection: React.FC
= ({ escrow, userRole }: Par
Conditions
- {escrow.conditions.map((condition) => (
+ {escrow.conditions.map((condition: any) => (
-