Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/app/quote/Client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ export default function QuoteClient() {
executeQuoteRequest();
};

// Retry wrapper for the quote request – re‑uses the existing submission logic.
const retryQuote = useCallback(() => {
// Create a synthetic submit event to trigger the same validation & request flow.
// The event type is cast to any to satisfy the FormEvent generic.
onSubmit(new Event('submit') as any);
}, [onSubmit]);

return (
<main
id="main-content"
Expand Down Expand Up @@ -325,7 +332,7 @@ export default function QuoteClient() {
quote ? `${((quote.estimated_rate - 1) * 100).toFixed(2)}%` : undefined
}
errorMessage={formError ?? undefined}
onRetry={formError ? executeQuoteRequest : undefined}
onRetry={formError ? retryQuote : undefined}
/>
{formError && (
<div role="alert" className="text-sm text-rose-700 dark:text-rose-400">
Expand Down
15 changes: 9 additions & 6 deletions src/app/quote/QuoteHistory.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ describe('QuoteHistory Component', () => {
let renderCount = 0;

// Component wrapper that tracks render count of memoized QuoteHistory
const TrackedHistoryInner = (props: React.ComponentProps<typeof QuoteHistory>) => {
renderCount++;
return <QuoteHistory {...props} />;
};
TrackedHistoryInner.displayName = 'TrackedHistory';
const TrackedHistory = React.memo(TrackedHistoryInner);
const TrackedHistory = React.memo(
function TrackedHistoryComponent(
props: React.ComponentProps<typeof QuoteHistory>
) {
renderCount++;
return <QuoteHistory {...props} />;
}
);
TrackedHistory.displayName = 'TrackedHistory';

const ParentComponent = () => {
const [dummyState, setDummyState] = useState(0);
Expand Down
18 changes: 12 additions & 6 deletions src/app/quote/Slippage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,26 @@ type Props = {
};

function SlippageBase({ status, slippage, errorMessage, onRetry }: Props) {
const content = (
<span data-testid="slippage-status">
// Accessible live region – always present, content changes with status.
const liveRegion = (
<span role="status" aria-live="polite" data-testid="slippage-status">
{status === 'empty' && 'No slippage data'}
{status === 'loading' && 'Calculating slippage…'}
{status === 'error' && `Error: ${errorMessage ?? 'Unable to calculate'}`}
{status === 'success' && `Slippage: ${slippage}`}
</span>
);

// Render a tooltip‑styled badge for visual consistency.
const tooltip = (
<Tooltip status={status} message={status === 'error' ? errorMessage : undefined}>
{liveRegion}
</Tooltip>
);

return (
<section className="flex items-center gap-2" data-testid="slippage-view">
<Tooltip status={status} message={status === 'error' ? errorMessage : undefined}>
{content}
</Tooltip>
<section className="flex items-center gap-2">
{tooltip}
{status === 'error' && onRetry && (
<button
type="button"
Expand Down
Loading