code quality
Some checks failed
CI / lint-typecheck (pull_request) Failing after 13s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
Some checks failed
CI / lint-typecheck (pull_request) Failing after 13s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
This commit is contained in:
@@ -7,16 +7,17 @@ import React from 'react';
|
||||
interface AuthFormProps {
|
||||
children: React.ReactNode;
|
||||
onSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
|
||||
'data-testid'?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* AuthForm
|
||||
*
|
||||
*
|
||||
* Semantic form wrapper for auth flows.
|
||||
*/
|
||||
export function AuthForm({ children, onSubmit }: AuthFormProps) {
|
||||
export function AuthForm({ children, onSubmit, 'data-testid': testId }: AuthFormProps) {
|
||||
return (
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Form onSubmit={onSubmit} data-testid={testId}>
|
||||
<Group direction="column" gap={6}>
|
||||
{children}
|
||||
</Group>
|
||||
|
||||
@@ -8,25 +8,28 @@ interface KpiItem {
|
||||
|
||||
interface DashboardKpiRowProps {
|
||||
items: KpiItem[];
|
||||
'data-testid'?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* DashboardKpiRow
|
||||
*
|
||||
*
|
||||
* A horizontal row of key performance indicators with telemetry styling.
|
||||
*/
|
||||
export function DashboardKpiRow({ items }: DashboardKpiRowProps) {
|
||||
export function DashboardKpiRow({ items, 'data-testid': testId }: DashboardKpiRowProps) {
|
||||
return (
|
||||
<StatGrid
|
||||
variant="card"
|
||||
cardVariant="dark"
|
||||
font="mono"
|
||||
columns={{ base: 2, md: 3, lg: 6 }}
|
||||
stats={items.map(item => ({
|
||||
stats={items.map((item, index) => ({
|
||||
label: item.label,
|
||||
value: item.value,
|
||||
intent: item.intent as any
|
||||
intent: item.intent as any,
|
||||
'data-testid': `stat-${item.label.toLowerCase()}`
|
||||
}))}
|
||||
data-testid={testId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ export function RecentActivityTable({ items }: RecentActivityTableProps) {
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{items.map((item) => (
|
||||
<TableRow key={item.id}>
|
||||
<TableCell>
|
||||
<TableRow key={item.id} data-testid={`activity-item-${item.id}`}>
|
||||
<TableCell data-testid="activity-race-result-link">
|
||||
<Text font="mono" variant="telemetry" size="xs">{item.type}</Text>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
||||
@@ -5,16 +5,17 @@ import React from 'react';
|
||||
interface TelemetryPanelProps {
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
'data-testid'?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* TelemetryPanel
|
||||
*
|
||||
*
|
||||
* A dense, instrument-grade panel for displaying data and controls.
|
||||
*/
|
||||
export function TelemetryPanel({ title, children }: TelemetryPanelProps) {
|
||||
export function TelemetryPanel({ title, children, 'data-testid': testId }: TelemetryPanelProps) {
|
||||
return (
|
||||
<Panel title={title} variant="dark" padding={4}>
|
||||
<Panel title={title} variant="dark" padding={4} data-testid={testId}>
|
||||
<Text size="sm" variant="med">
|
||||
{children}
|
||||
</Text>
|
||||
|
||||
@@ -91,7 +91,7 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack gap={8}>
|
||||
<Stack gap={8} data-testid="avatar-creation-form">
|
||||
{/* Photo Upload */}
|
||||
<Stack>
|
||||
<Text as="label" size="sm" weight="medium" color="text-gray-300" block mb={3}>
|
||||
@@ -100,6 +100,7 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
<Stack direction="row" gap={6}>
|
||||
{/* Upload Area */}
|
||||
<Stack
|
||||
data-testid="photo-upload-area"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
flex={1}
|
||||
display="flex"
|
||||
@@ -126,6 +127,7 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
accept="image/*"
|
||||
onChange={handleFileSelect}
|
||||
display="none"
|
||||
data-testid="photo-upload-input"
|
||||
/>
|
||||
|
||||
{avatarInfo.isValidating ? (
|
||||
@@ -144,6 +146,7 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
objectFit="cover"
|
||||
fullWidth
|
||||
fullHeight
|
||||
data-testid="photo-preview"
|
||||
/>
|
||||
</Stack>
|
||||
<Text size="sm" color="text-performance-green" block>
|
||||
@@ -199,11 +202,12 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
Racing Suit Color
|
||||
</Stack>
|
||||
</Text>
|
||||
<Stack flexDirection="row" flexWrap="wrap" gap={2}>
|
||||
<Stack flexDirection="row" flexWrap="wrap" gap={2} data-testid="suit-color-options">
|
||||
{SUIT_COLORS.map((color) => (
|
||||
<Button
|
||||
key={color.value}
|
||||
type="button"
|
||||
data-testid={`suit-color-${color.value}`}
|
||||
onClick={() => setAvatarInfo({ ...avatarInfo, suitColor: color.value })}
|
||||
rounded="lg"
|
||||
transition
|
||||
@@ -235,6 +239,7 @@ export function AvatarStep({ avatarInfo, setAvatarInfo, errors, setErrors, onGen
|
||||
<Stack>
|
||||
<Button
|
||||
type="button"
|
||||
data-testid="generate-avatars-btn"
|
||||
variant="primary"
|
||||
onClick={onGenerateAvatars}
|
||||
disabled={avatarInfo.isGenerating || avatarInfo.isValidating}
|
||||
|
||||
@@ -49,6 +49,7 @@ export function OnboardingPrimaryActions({
|
||||
onClick={onNext}
|
||||
disabled={isLoading || !canNext}
|
||||
w="40"
|
||||
data-testid={isLastStep ? 'complete-onboarding-btn' : 'next-btn'}
|
||||
>
|
||||
<Stack direction="row" align="center" gap={2}>
|
||||
{isLoading ? 'Processing...' : isLastStep ? 'Complete Setup' : nextLabel}
|
||||
|
||||
@@ -17,7 +17,7 @@ interface OnboardingShellProps {
|
||||
*/
|
||||
export function OnboardingShell({ children, header, footer, sidebar }: OnboardingShellProps) {
|
||||
return (
|
||||
<Box minHeight="100vh" bg="rgba(10,10,10,1)" color="white">
|
||||
<Box minHeight="100vh" bg="rgba(10,10,10,1)" color="white" data-testid="onboarding-wizard">
|
||||
{header && (
|
||||
<Box borderBottom borderColor="rgba(255,255,255,0.1)" py={4} bg="rgba(20,22,25,1)">
|
||||
<Container size="md">
|
||||
|
||||
@@ -15,8 +15,9 @@ interface OnboardingStepPanelProps {
|
||||
* Provides a consistent header and surface.
|
||||
*/
|
||||
export function OnboardingStepPanel({ title, description, children }: OnboardingStepPanelProps) {
|
||||
const testId = title.toLowerCase().includes('personal') ? 'step-1-personal-info' : 'step-2-avatar';
|
||||
return (
|
||||
<Stack gap={6}>
|
||||
<Stack gap={6} data-testid={testId}>
|
||||
<Stack gap={1}>
|
||||
<Text as="h2" size="2xl" weight="bold" color="text-white" letterSpacing="tight">
|
||||
{title}
|
||||
|
||||
@@ -49,6 +49,7 @@ export function PersonalInfoStep({ personalInfo, setPersonalInfo, errors, loadin
|
||||
</Text>
|
||||
<Input
|
||||
id="firstName"
|
||||
data-testid="first-name-input"
|
||||
type="text"
|
||||
value={personalInfo.firstName}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
@@ -67,6 +68,7 @@ export function PersonalInfoStep({ personalInfo, setPersonalInfo, errors, loadin
|
||||
</Text>
|
||||
<Input
|
||||
id="lastName"
|
||||
data-testid="last-name-input"
|
||||
type="text"
|
||||
value={personalInfo.lastName}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
@@ -86,6 +88,7 @@ export function PersonalInfoStep({ personalInfo, setPersonalInfo, errors, loadin
|
||||
</Text>
|
||||
<Input
|
||||
id="displayName"
|
||||
data-testid="display-name-input"
|
||||
type="text"
|
||||
value={personalInfo.displayName}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
@@ -104,6 +107,7 @@ export function PersonalInfoStep({ personalInfo, setPersonalInfo, errors, loadin
|
||||
Country *
|
||||
</Text>
|
||||
<CountrySelect
|
||||
data-testid="country-select"
|
||||
value={personalInfo.country}
|
||||
onChange={(value: string) =>
|
||||
setPersonalInfo({ ...personalInfo, country: value })
|
||||
|
||||
Reference in New Issue
Block a user