Files
gridpilot.gg/apps/website/components/leagues/LeagueBasicsSection.tsx
2025-12-05 12:24:38 +01:00

130 lines
4.0 KiB
TypeScript

'use client';
import Input from '@/components/ui/Input';
import type {
LeagueConfigFormModel,
} from '@gridpilot/racing/application';
interface LeagueBasicsSectionProps {
form: LeagueConfigFormModel;
onChange?: (form: LeagueConfigFormModel) => void;
errors?: {
name?: string;
visibility?: string;
};
readOnly?: boolean;
}
export function LeagueBasicsSection({
form,
onChange,
errors,
readOnly,
}: LeagueBasicsSectionProps) {
const basics = form.basics;
const disabled = readOnly || !onChange;
const updateBasics = (patch: Partial<typeof basics>) => {
if (!onChange) return;
onChange({
...form,
basics: {
...form.basics,
...patch,
},
});
};
return (
<div className="space-y-6">
<h2 className="text-lg font-semibold text-white">Step 1 Basics</h2>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
League name *
</label>
<Input
value={basics.name}
onChange={(e) => updateBasics({ name: e.target.value })}
placeholder="GridPilot Sprint Series"
error={!!errors?.name}
errorMessage={errors?.name}
disabled={disabled}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Description
</label>
<textarea
value={basics.description ?? ''}
onChange={(e) =>
updateBasics({
description: e.target.value,
})
}
rows={3}
disabled={disabled}
className="block w-full rounded-md border-0 px-4 py-3 bg-iron-gray text-white shadow-sm ring-1 ring-inset ring-charcoal-outline placeholder:text-gray-500 focus:ring-2 focus:ring-inset focus:ring-primary-blue text-sm disabled:opacity-60 disabled:cursor-not-allowed"
placeholder="Weekly league with structured championships and live standings."
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<span className="block text-sm font-medium text-gray-300 mb-2">
Visibility *
</span>
<div className="flex gap-3">
<button
type="button"
disabled={disabled}
onClick={() =>
updateBasics({
visibility: 'public',
})
}
className={`flex-1 px-3 py-2 text-xs rounded-md border ${
basics.visibility === 'public'
? 'border-primary-blue bg-primary-blue/10 text-primary-blue'
: 'border-charcoal-outline bg-iron-gray text-gray-300'
} ${disabled ? 'opacity-60 cursor-not-allowed' : ''}`}
>
Public
</button>
<button
type="button"
disabled={disabled}
onClick={() =>
updateBasics({
visibility: 'private',
})
}
className={`flex-1 px-3 py-2 text-xs rounded-md border ${
basics.visibility === 'private'
? 'border-primary-blue bg-primary-blue/10 text-primary-blue'
: 'border-charcoal-outline bg-iron-gray text-gray-300'
} ${disabled ? 'opacity-60 cursor-not-allowed' : ''}`}
>
Private
</button>
</div>
{errors?.visibility && (
<p className="mt-1 text-xs text-warning-amber">
{errors.visibility}
</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Game
</label>
<Input value="iRacing" disabled />
</div>
</div>
</div>
</div>
);
}