"use client"; import { CSSProperties } from "react"; import { useParams, useRouter } from "next/navigation"; import { Permission } from "../../auth-context"; import { tradesApi } from "../../api"; import { Header } from "../../components/Header"; import { SatsDisplay } from "../../components/SatsDisplay"; import { useRequireAuth } from "../../hooks/useRequireAuth"; import { useAsyncData } from "../../hooks/useAsyncData"; import { formatDateTime } from "../../utils/date"; import { formatEur, getTradeStatusDisplay } from "../../utils/exchange"; import { layoutStyles, typographyStyles, bannerStyles, badgeStyles, buttonStyles, tradeCardStyles, } from "../../styles/shared"; export default function TradeDetailPage() { const router = useRouter(); const params = useParams(); const publicId = params?.id as string | undefined; const { user, isLoading, isAuthorized } = useRequireAuth({ requiredPermission: Permission.VIEW_OWN_EXCHANGES, fallbackRedirect: "/", }); const { data: trade, isLoading: isLoadingTrade, error, } = useAsyncData( () => { if (!publicId) throw new Error("Trade ID is required"); return tradesApi.getTrade(publicId); }, { enabled: !!user && isAuthorized && !!publicId, onError: () => { // Error message is set by useAsyncData }, } ); if (isLoading || isLoadingTrade) { return (
Loading...
); } if (!isAuthorized) { return null; } if (error || (!isLoadingTrade && !trade)) { return (

Trade Details

{error && (
{error || "Failed to load trade. It may not exist or you may not have permission to view it."}
)}
); } const status = getTradeStatusDisplay(trade.status); const isBuy = trade.direction === "buy"; return (

Trade Details

Trade Information

Status: {status.text}
Time: {formatDateTime(trade.slot_start)}
Direction: {isBuy ? "BUY BTC" : "SELL BTC"}
Payment Method: {isBuy ? `Receive via ${trade.bitcoin_transfer_method === "onchain" ? "Onchain" : "Lightning"}` : `Send via ${trade.bitcoin_transfer_method === "onchain" ? "Onchain" : "Lightning"}`}

Amounts

EUR Amount: {formatEur(trade.eur_amount)}
Bitcoin Amount:

Pricing

Market Price: € {trade.market_price_eur.toLocaleString("de-DE", { maximumFractionDigits: 0, })} /BTC
Agreed Price: € {trade.agreed_price_eur.toLocaleString("de-DE", { maximumFractionDigits: 0, })} /BTC
Premium: {trade.premium_percentage}%

Timestamps

Created: {formatDateTime(trade.created_at)}
{trade.cancelled_at && (
Cancelled: {formatDateTime(trade.cancelled_at)}
)} {trade.completed_at && (
Completed: {formatDateTime(trade.completed_at)}
)}
{trade.status === "booked" && (
)}
); } const styles: Record = { content: { flex: 1, padding: "2rem", maxWidth: "800px", margin: "0 auto", width: "100%", }, header: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "2rem", }, tradeDetailCard: { background: "rgba(255, 255, 255, 0.03)", border: "1px solid rgba(255, 255, 255, 0.08)", borderRadius: "12px", padding: "2rem", }, detailSection: { marginBottom: "2rem", }, sectionTitle: { fontFamily: "'DM Sans', system-ui, sans-serif", fontSize: "1.1rem", fontWeight: 600, color: "#fff", marginBottom: "1rem", }, detailGrid: { display: "flex", flexDirection: "column", gap: "1rem", }, detailRow: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0.75rem 0", borderBottom: "1px solid rgba(255, 255, 255, 0.05)", }, detailLabel: { fontFamily: "'DM Sans', system-ui, sans-serif", fontSize: "0.9rem", color: "rgba(255, 255, 255, 0.6)", }, detailValue: { fontFamily: "'DM Sans', system-ui, sans-serif", fontSize: "0.9rem", color: "#fff", fontWeight: 500, }, actionSection: { marginTop: "2rem", paddingTop: "2rem", borderTop: "1px solid rgba(255, 255, 255, 0.1)", }, };