- Created StatusBadge component: Standardizes status badge display - Supports tradeStatus prop for trade-specific styling - Supports variant prop for simple badges (success/error/ready) - Eliminates repetitive badge style combinations - Created EmptyState component: Standardizes empty state display - Handles loading and empty states consistently - Supports message, hint, and action props - Used across trades, invites, admin pages - Created ConfirmationButton component: Standardizes confirmation flows - Two-step confirmation pattern (action -> confirm/cancel) - Supports different variants (danger/success/primary) - Handles loading states automatically - Used for cancel, complete, no-show actions - Migrated pages to use new components: - trades/page.tsx: StatusBadge, EmptyState, ConfirmationButton - trades/[id]/page.tsx: StatusBadge - invites/page.tsx: StatusBadge, EmptyState - admin/trades/page.tsx: StatusBadge, EmptyState, ConfirmationButton - admin/invites/page.tsx: StatusBadge Benefits: - Eliminated ~50+ lines of repetitive badge styling code - Consistent UI patterns across all pages - Easier to maintain and update styling - Better type safety All tests passing (32 frontend, 33 e2e)
97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import { buttonStyles } from "../styles/shared";
|
|
|
|
interface ConfirmationButtonProps {
|
|
/** Whether confirmation mode is active */
|
|
isConfirming: boolean;
|
|
/** Callback when user confirms the action */
|
|
onConfirm: () => void;
|
|
/** Callback when user cancels the confirmation */
|
|
onCancel: () => void;
|
|
/** Callback when user clicks the initial action button (to enter confirmation mode) */
|
|
onActionClick: () => void;
|
|
/** Label for the initial action button */
|
|
actionLabel: string;
|
|
/** Label for the confirm button (default: "Confirm") */
|
|
confirmLabel?: string;
|
|
/** Label for the cancel button (default: "No") */
|
|
cancelLabel?: string;
|
|
/** Whether the action is in progress (shows "..." on confirm button) */
|
|
isLoading?: boolean;
|
|
/** Style variant for the confirm button */
|
|
confirmVariant?: "danger" | "success" | "primary";
|
|
/** Custom style for the action button */
|
|
actionButtonStyle?: React.CSSProperties;
|
|
/** Custom style for the confirm button */
|
|
confirmButtonStyle?: React.CSSProperties;
|
|
}
|
|
|
|
/**
|
|
* Confirmation button component that shows a two-step confirmation flow.
|
|
* Initially shows an action button. When clicked, shows Confirm/Cancel buttons.
|
|
*/
|
|
export function ConfirmationButton({
|
|
isConfirming,
|
|
onConfirm,
|
|
onCancel,
|
|
onActionClick,
|
|
actionLabel,
|
|
confirmLabel = "Confirm",
|
|
cancelLabel = "No",
|
|
isLoading = false,
|
|
confirmVariant = "primary",
|
|
actionButtonStyle,
|
|
confirmButtonStyle,
|
|
}: ConfirmationButtonProps) {
|
|
if (isConfirming) {
|
|
let confirmStyle: React.CSSProperties = buttonStyles.primaryButton;
|
|
if (confirmVariant === "danger") {
|
|
confirmStyle = {
|
|
...buttonStyles.primaryButton,
|
|
background: "rgba(239, 68, 68, 0.9)",
|
|
borderColor: "rgba(239, 68, 68, 1)",
|
|
};
|
|
} else if (confirmVariant === "success") {
|
|
confirmStyle = {
|
|
...buttonStyles.primaryButton,
|
|
background: "rgba(34, 197, 94, 0.9)",
|
|
borderColor: "rgba(34, 197, 94, 1)",
|
|
};
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onConfirm();
|
|
}}
|
|
disabled={isLoading}
|
|
style={{ ...confirmStyle, ...confirmButtonStyle }}
|
|
>
|
|
{isLoading ? "..." : confirmLabel}
|
|
</button>
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onCancel();
|
|
}}
|
|
style={buttonStyles.secondaryButton}
|
|
>
|
|
{cancelLabel}
|
|
</button>
|
|
</>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
onActionClick();
|
|
}}
|
|
style={actionButtonStyle || buttonStyles.secondaryButton}
|
|
>
|
|
{actionLabel}
|
|
</button>
|
|
);
|
|
}
|