website refactor
This commit is contained in:
@@ -2,6 +2,7 @@ import { notFound } from 'next/navigation';
|
||||
import { LeagueDetailPageQuery } from '@/lib/page-queries/LeagueDetailPageQuery';
|
||||
import { LeagueDetailTemplate } from '@/templates/LeagueDetailTemplate';
|
||||
import { LeagueDetailViewDataBuilder } from '@/lib/builders/view-data/LeagueDetailViewDataBuilder';
|
||||
import { DriverService } from '@/lib/services/drivers/DriverService';
|
||||
import { Text } from '@/ui/Text';
|
||||
|
||||
export default async function LeagueLayout({
|
||||
@@ -14,7 +15,10 @@ export default async function LeagueLayout({
|
||||
const { id: leagueId } = await params;
|
||||
|
||||
// Execute PageQuery to get league data
|
||||
const result = await LeagueDetailPageQuery.execute(leagueId);
|
||||
const [result, currentDriver] = await Promise.all([
|
||||
LeagueDetailPageQuery.execute(leagueId),
|
||||
new DriverService().getCurrentDriver(),
|
||||
]);
|
||||
|
||||
if (result.isErr()) {
|
||||
const error = result.getError();
|
||||
@@ -34,6 +38,7 @@ export default async function LeagueLayout({
|
||||
ownerSummary: null,
|
||||
adminSummaries: [],
|
||||
stewardSummaries: [],
|
||||
memberSummaries: [],
|
||||
sponsorInsights: null
|
||||
}}
|
||||
tabs={[]}
|
||||
@@ -47,11 +52,11 @@ export default async function LeagueLayout({
|
||||
|
||||
const viewData = LeagueDetailViewDataBuilder.build({
|
||||
league: data.league,
|
||||
owner: null,
|
||||
scoringConfig: null,
|
||||
memberships: { members: [] },
|
||||
races: [],
|
||||
sponsors: [],
|
||||
owner: data.owner,
|
||||
scoringConfig: data.scoringConfig,
|
||||
memberships: data.memberships,
|
||||
races: data.races,
|
||||
sponsors: data.sponsors,
|
||||
});
|
||||
|
||||
// Define tab configuration
|
||||
@@ -59,19 +64,23 @@ export default async function LeagueLayout({
|
||||
{ label: 'Overview', href: `/leagues/${leagueId}`, exact: true },
|
||||
{ label: 'Schedule', href: `/leagues/${leagueId}/schedule`, exact: false },
|
||||
{ label: 'Standings', href: `/leagues/${leagueId}/standings`, exact: false },
|
||||
{ label: 'Roster', href: `/leagues/${leagueId}/roster`, exact: false },
|
||||
{ label: 'Rulebook', href: `/leagues/${leagueId}/rulebook`, exact: false },
|
||||
];
|
||||
|
||||
const adminTabs = [
|
||||
// Check if user is admin or owner
|
||||
const isOwner = currentDriver && data.league.ownerId === currentDriver.id;
|
||||
const isAdmin = currentDriver && data.memberships.members?.some(m => m.driverId === currentDriver.id && m.role === 'admin');
|
||||
const hasAdminAccess = isOwner || isAdmin;
|
||||
|
||||
const adminTabs = hasAdminAccess ? [
|
||||
{ label: 'Schedule Admin', href: `/leagues/${leagueId}/schedule/admin`, exact: false },
|
||||
{ label: 'Sponsorships', href: `/leagues/${leagueId}/sponsorships`, exact: false },
|
||||
{ label: 'Stewarding', href: `/leagues/${leagueId}/stewarding`, exact: false },
|
||||
{ label: 'Wallet', href: `/leagues/${leagueId}/wallet`, exact: false },
|
||||
{ label: 'Settings', href: `/leagues/${leagueId}/settings`, exact: false },
|
||||
];
|
||||
] : [];
|
||||
|
||||
// TODO: Admin check needs to be implemented properly
|
||||
// For now, show admin tabs if user is logged in
|
||||
const tabs = [...baseTabs, ...adminTabs];
|
||||
|
||||
return (
|
||||
|
||||
@@ -64,14 +64,13 @@ export default async function Page({ params }: Props) {
|
||||
const league = data.league;
|
||||
|
||||
// Build ViewData using the builder
|
||||
// Note: This would need additional data (owner, scoring config, etc.) in real implementation
|
||||
const viewData = LeagueDetailViewDataBuilder.build({
|
||||
league: data.league,
|
||||
owner: null,
|
||||
scoringConfig: null,
|
||||
memberships: { members: [] },
|
||||
races: [],
|
||||
sponsors: [],
|
||||
owner: data.owner,
|
||||
scoringConfig: data.scoringConfig,
|
||||
memberships: data.memberships,
|
||||
races: data.races,
|
||||
sponsors: data.sponsors,
|
||||
});
|
||||
|
||||
const jsonLd = {
|
||||
|
||||
67
apps/website/app/leagues/[id]/roster/page.tsx
Normal file
67
apps/website/app/leagues/[id]/roster/page.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { LeagueDetailPageQuery } from '@/lib/page-queries/LeagueDetailPageQuery';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
|
||||
interface Props {
|
||||
params: Promise<{ id: string }>;
|
||||
}
|
||||
|
||||
export default async function LeagueRosterPage({ params }: Props) {
|
||||
const { id: leagueId } = await params;
|
||||
const result = await LeagueDetailPageQuery.execute(leagueId);
|
||||
|
||||
if (result.isErr()) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const data = result.unwrap();
|
||||
const members = data.memberships.members || [];
|
||||
|
||||
return (
|
||||
<Stack gap={8}>
|
||||
<Box as="header" display="flex" flexDirection="col" gap={2}>
|
||||
<Text as="h2" size="xl" weight="bold" color="text-white" uppercase letterSpacing="tight">League Roster</Text>
|
||||
<Text size="sm" color="text-zinc-500">All drivers currently registered in this league.</Text>
|
||||
</Box>
|
||||
|
||||
<Box border borderColor="zinc-800" bg="zinc-900/30" overflow="hidden">
|
||||
<table className="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr className="border-b border-zinc-800 bg-zinc-900/50">
|
||||
<th className="px-6 py-4 text-xs font-bold uppercase tracking-widest text-zinc-500">Driver</th>
|
||||
<th className="px-6 py-4 text-xs font-bold uppercase tracking-widest text-zinc-500">Role</th>
|
||||
<th className="px-6 py-4 text-xs font-bold uppercase tracking-widest text-zinc-500">Joined</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{members.map((member) => (
|
||||
<tr key={member.driverId} className="border-b border-zinc-800/50 hover:bg-zinc-800/30 transition-colors">
|
||||
<td className="px-6 py-4">
|
||||
<Box display="flex" alignItems="center" gap={3}>
|
||||
<Box w="8" h="8" bg="zinc-800" rounded="full" />
|
||||
<Text weight="bold" color="text-white">{member.driver.name}</Text>
|
||||
</Box>
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
<Text size="xs" color="text-zinc-400" uppercase weight="bold">{member.role}</Text>
|
||||
</td>
|
||||
<td className="px-6 py-4">
|
||||
<Text size="sm" color="text-zinc-500">{new Date(member.joinedAt).toLocaleDateString()}</Text>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
{members.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={3} className="px-6 py-12 text-center">
|
||||
<Text color="text-zinc-600" italic>No members found in this league.</Text>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user