Break down the 1300+ line Exchange page into smaller, focused components: - Create useExchangePrice hook - Handles price fetching and auto-refresh logic - Manages price loading and error states - Centralizes price-related state management - Create useAvailableSlots hook - Manages slot fetching and availability checking - Handles date availability state - Fetches availability when entering booking/confirmation steps - Create PriceDisplay component - Displays market price, agreed price, and premium - Shows price update timestamp and stale warnings - Handles loading and error states - Create ExchangeDetailsStep component - Step 1 of wizard: direction, payment method, amount selection - Contains all form logic for trade details - Validates and displays trade summary - Create BookingStep component - Step 2 of wizard: date and slot selection - Shows trade summary card - Handles date availability and existing trade warnings - Create ConfirmationStep component - Step 3 of wizard: final confirmation - Shows compressed booking summary - Displays all trade details for review - Create StepIndicator component - Visual indicator of current wizard step - Shows completed and active steps - Refactor ExchangePage - Reduced from 1300+ lines to ~350 lines - Uses new hooks and components - Maintains all existing functionality - Improved maintainability and testability All frontend tests pass. Linting passes.
98 lines
2.3 KiB
TypeScript
98 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import { CSSProperties } from "react";
|
|
|
|
type WizardStep = "details" | "booking" | "confirmation";
|
|
|
|
interface StepIndicatorProps {
|
|
currentStep: WizardStep;
|
|
}
|
|
|
|
const styles: Record<string, CSSProperties> = {
|
|
stepIndicator: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
gap: "1rem",
|
|
marginBottom: "2rem",
|
|
},
|
|
step: {
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: "0.5rem",
|
|
opacity: 0.4,
|
|
},
|
|
stepActive: {
|
|
opacity: 1,
|
|
},
|
|
stepCompleted: {
|
|
opacity: 0.7,
|
|
},
|
|
stepNumber: {
|
|
fontFamily: "'DM Mono', monospace",
|
|
width: "28px",
|
|
height: "28px",
|
|
borderRadius: "50%",
|
|
background: "rgba(255, 255, 255, 0.1)",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
fontSize: "0.875rem",
|
|
fontWeight: 600,
|
|
color: "#fff",
|
|
},
|
|
stepLabel: {
|
|
fontFamily: "'DM Sans', system-ui, sans-serif",
|
|
fontSize: "0.875rem",
|
|
color: "#fff",
|
|
},
|
|
stepDivider: {
|
|
width: "40px",
|
|
height: "1px",
|
|
background: "rgba(255, 255, 255, 0.2)",
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Component that displays the wizard step indicator.
|
|
* Shows which step the user is currently on and which steps are completed.
|
|
*/
|
|
export function StepIndicator({ currentStep }: StepIndicatorProps) {
|
|
return (
|
|
<div style={styles.stepIndicator}>
|
|
<div
|
|
style={{
|
|
...styles.step,
|
|
...(currentStep === "details" ? styles.stepActive : styles.stepCompleted),
|
|
}}
|
|
>
|
|
<span style={styles.stepNumber}>1</span>
|
|
<span style={styles.stepLabel}>Exchange Details</span>
|
|
</div>
|
|
<div style={styles.stepDivider} />
|
|
<div
|
|
style={{
|
|
...styles.step,
|
|
...(currentStep === "booking"
|
|
? styles.stepActive
|
|
: currentStep === "confirmation"
|
|
? styles.stepCompleted
|
|
: {}),
|
|
}}
|
|
>
|
|
<span style={styles.stepNumber}>2</span>
|
|
<span style={styles.stepLabel}>Book Appointment</span>
|
|
</div>
|
|
<div style={styles.stepDivider} />
|
|
<div
|
|
style={{
|
|
...styles.step,
|
|
...(currentStep === "confirmation" ? styles.stepActive : {}),
|
|
}}
|
|
>
|
|
<span style={styles.stepNumber}>3</span>
|
|
<span style={styles.stepLabel}>Confirm</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|