"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."} )} router.push("/trades")} style={buttonStyles.primaryButton}> Back to Trades ); } const status = getTradeStatusDisplay(trade.status); const isBuy = trade.direction === "buy"; return ( Trade Details router.push("/trades")} style={buttonStyles.secondaryButton}> ← Back to Trades 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" && ( { if ( !confirm( "Are you sure you want to cancel this trade? This action cannot be undone." ) ) { return; } try { await tradesApi.cancelTrade(trade.public_id); router.push("/trades"); } catch (err) { setError(err instanceof Error ? err.message : "Failed to cancel trade"); } }} style={buttonStyles.secondaryButton} > Cancel Trade )} ); } 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)", }, };