diff --git a/apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx b/apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx new file mode 100644 index 0000000..52dac08 --- /dev/null +++ b/apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx @@ -0,0 +1,297 @@ +// TODO: replace stub views with real components once merged in frontend-SafeTrust +// Sources: +// frontend-SafeTrust/src/components/escrow/views/EscrowPaidView.tsx +// frontend-SafeTrust/src/components/escrow/views/EscrowBlockedView.tsx +// frontend-SafeTrust/src/components/escrow/views/EscrowReleasedView.tsx +// frontend-SafeTrust/src/components/escrow/RealTimeEscrowStatus.tsx +// +// Status-to-view mapping (when wired): +// funded -> EscrowPaidView (Payment batch) +// active -> EscrowBlockedView (Deposit blocked) +// completed -> EscrowReleasedView (Deposit released) +// default -> redirect to /hotel/[id]/escrow/create +// +// Real-time: RealTimeEscrowStatus (Hasura subscription) drives automatic transitions + +import { InvoiceHeader } from '@/components/escrow/InvoiceHeader'; +import { ProcessStepper } from '@/components/escrow/ProcessStepper'; +import type { CSSProperties } from 'react'; + +type StubStatus = 'paid' | 'blocked' | 'released'; + +type ViewConfig = { + label: StubStatus; + step: 2 | 3 | 4; + title: string; +}; + +const styles = { + page: { + maxWidth: '72rem', + margin: '0 auto', + padding: '2rem 1.5rem 3rem', + color: '#111827', + } satisfies CSSProperties, + grid: { + display: 'grid', + gap: '1.5rem', + marginTop: '1.5rem', + alignItems: 'start', + } satisfies CSSProperties, + panel: { + border: '1px solid #fed7aa', + borderRadius: '1rem', + backgroundColor: '#ffffff', + padding: '1.5rem', + } satisfies CSSProperties, + splitGrid: { + display: 'grid', + gap: '1rem', + gridTemplateColumns: 'repeat(auto-fit, minmax(13rem, 1fr))', + } satisfies CSSProperties, + table: { + width: '100%', + borderCollapse: 'collapse', + fontSize: '0.95rem', + } satisfies CSSProperties, + input: { + width: '100%', + border: '1px solid #d1d5db', + borderRadius: '0.75rem', + padding: '0.75rem', + font: 'inherit', + resize: 'vertical', + minHeight: '6rem', + } satisfies CSSProperties, + buttonRow: { + display: 'flex', + gap: '0.75rem', + marginTop: '0.75rem', + flexWrap: 'wrap', + } satisfies CSSProperties, + secondaryButton: { + border: '1px solid #d1d5db', + backgroundColor: '#ffffff', + color: '#111827', + borderRadius: '0.75rem', + padding: '0.6rem 1rem', + fontWeight: 600, + } satisfies CSSProperties, + primaryButton: { + border: '1px solid #f97316', + backgroundColor: '#f97316', + color: '#ffffff', + borderRadius: '0.75rem', + padding: '0.6rem 1rem', + fontWeight: 700, + } satisfies CSSProperties, +} as const; + +function getStubView(status: string | undefined): ViewConfig { + switch (status) { + case 'blocked': + return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' }; + case 'released': + return { label: 'released', step: 4, title: 'Deposit / Escrow Released' }; + case 'paid': + default: + return { label: 'paid', step: 2, title: 'Payment batch January 2025' }; + } +} + +function InfoPair({ label, value }: { label: string; value: string }) { + return ( +
+

{label}

+

{value}

+
+ ); +} + +function PaidStubView() { + return ( +
+
+ + + + +
+ +
+ + + + + + + + + + + + + + + +
PRODUCTPRICE / MONTHDEPOSIT
La sabana apartment + $4,000 + + $4,000 +
+
+ +
+ Total: $8,000 +
+
+ ); +} + +function BlockedStubView() { + return ( +
+
+ + +
+ +
+
+

Tenant Information

+
+ + + +
+
+
+

Owner Information

+
+ + + +
+
+
+
+ ); +} + +function ReleasedStubView() { + return ( +
+
+
+

Escrow Justification

+ +
+