144 lines
4.4 KiB
TypeScript
144 lines
4.4 KiB
TypeScript
import { useEffect } from "react";
|
|
import { Link, useSearchParams } from "react-router";
|
|
import { toast } from "sonner";
|
|
import { getAuth } from "@clerk/react-router/server";
|
|
|
|
import type { Route } from "./+types/home";
|
|
import { findLeaguesWithActiveSeasonsByUserId } from "~/models/league";
|
|
import { findSeasonById } from "~/models/season";
|
|
import { Button } from "~/components/ui/button";
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardDescription,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "~/components/ui/card";
|
|
|
|
export function meta() {
|
|
return [
|
|
{ title: "Brackt - Fantasy All of the Sports!" },
|
|
{
|
|
name: "description",
|
|
content: "Play multi-sport fantasy leagues with your friends!",
|
|
},
|
|
];
|
|
}
|
|
|
|
export async function loader(args: Route.LoaderArgs) {
|
|
const { userId } = await getAuth(args);
|
|
|
|
if (!userId) {
|
|
return { leagues: [], isLoggedIn: false };
|
|
}
|
|
|
|
// Fetch leagues where user has a team in the current season
|
|
const leagues = await findLeaguesWithActiveSeasonsByUserId(userId);
|
|
|
|
// Fetch season details for each league's current season
|
|
const leaguesWithSeasons = await Promise.all(
|
|
leagues.map(async (league) => {
|
|
const season = league.currentSeasonId
|
|
? await findSeasonById(league.currentSeasonId)
|
|
: null;
|
|
return {
|
|
...league,
|
|
currentSeason: season,
|
|
};
|
|
})
|
|
);
|
|
|
|
return {
|
|
leagues: leaguesWithSeasons,
|
|
isLoggedIn: true,
|
|
};
|
|
}
|
|
|
|
export default function Home({ loaderData }: Route.ComponentProps) {
|
|
const { leagues, isLoggedIn } = loaderData;
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
|
|
useEffect(() => {
|
|
if (searchParams.get("deleted") === "true") {
|
|
toast.success("League deleted successfully");
|
|
setSearchParams({});
|
|
}
|
|
}, [searchParams, setSearchParams]);
|
|
|
|
if (!isLoggedIn) {
|
|
return (
|
|
<div className="container mx-auto py-16 px-4 text-center">
|
|
<h1 className="text-4xl font-bold mb-4">Welcome to Brackt</h1>
|
|
<p className="text-xl text-muted-foreground mb-8">
|
|
Please sign in to view your leagues
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="container mx-auto py-8 px-4">
|
|
<div className="flex items-center justify-between mb-8">
|
|
<h1 className="text-4xl font-bold">My Leagues</h1>
|
|
<Button asChild>
|
|
<Link to="/leagues/new">Create New League</Link>
|
|
</Button>
|
|
</div>
|
|
|
|
{leagues.length === 0 ? (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>No Active Leagues</CardTitle>
|
|
<CardDescription>
|
|
You don't have any teams in leagues with active seasons yet
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Button asChild>
|
|
<Link to="/leagues/new">Create a New League</Link>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
) : (
|
|
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
{leagues.map((league) => (
|
|
<Link key={league.id} to={`/leagues/${league.id}`}>
|
|
<Card className="hover:border-primary transition-colors cursor-pointer h-full">
|
|
<CardHeader>
|
|
<CardTitle>{league.name}</CardTitle>
|
|
<CardDescription>
|
|
Created {new Date(league.createdAt).toLocaleDateString()}
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{league.currentSeason ? (
|
|
<div className="space-y-2">
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">
|
|
Current Season
|
|
</p>
|
|
<p className="font-medium">
|
|
{league.currentSeason.year}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm text-muted-foreground">Status</p>
|
|
<p className="font-medium capitalize">
|
|
{league.currentSeason.status.replace("_", " ")}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<p className="text-sm text-muted-foreground">
|
|
No active season
|
|
</p>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|