feat: add meta title to all route pages (#109)
Every route now exports a meta function so the browser title bar reflects the current page. Static pages use fixed titles; dynamic pages pull names from loader data with a sensible fallback (e.g. league name, sport season name, team name). Titles follow the pattern "Page Name - Brackt" for user-facing routes and "Page Name - Brackt Admin" for admin routes. Fixes #74 Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cf8ac8a765
commit
d784571f29
33 changed files with 158 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin._index";
|
import type { Route } from "./+types/admin._index";
|
||||||
|
|
||||||
import { findAllSports } from "~/models/sport";
|
import { findAllSports } from "~/models/sport";
|
||||||
import { findAllSportsSeasons } from "~/models/sports-season";
|
import { findAllSportsSeasons } from "~/models/sports-season";
|
||||||
import { findAllSeasonTemplates } from "~/models/season-template";
|
import { findAllSeasonTemplates } from "~/models/season-template";
|
||||||
|
|
@ -13,6 +14,10 @@ import {
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Trophy, Calendar, FolderKanban, ArrowRight, Camera } from "lucide-react";
|
import { Trophy, Calendar, FolderKanban, ArrowRight, Camera } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Admin - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const [sports, sportsSeasons, templates] = await Promise.all([
|
const [sports, sportsSeasons, templates] = await Promise.all([
|
||||||
findAllSports(),
|
findAllSports(),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useFetcher } from "react-router";
|
import { useFetcher } from "react-router";
|
||||||
import type { Route } from "./+types/admin.data-sync";
|
import type { Route } from "./+types/admin.data-sync";
|
||||||
|
|
||||||
import { findAllSports } from "~/models/sport";
|
import { findAllSports } from "~/models/sport";
|
||||||
import { findAllSportsSeasons } from "~/models/sports-season";
|
import { findAllSportsSeasons } from "~/models/sports-season";
|
||||||
import { findAllSeasonTemplates } from "~/models/season-template";
|
import { findAllSeasonTemplates } from "~/models/season-template";
|
||||||
|
|
@ -28,6 +29,10 @@ import {
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "~/components/ui/alert-dialog";
|
} from "~/components/ui/alert-dialog";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Data Sync - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const [sports, sportsSeasons, templates, participantCount, evCount] =
|
const [sports, sportsSeasons, templates, participantCount, evCount] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,10 @@ import {
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
import { Users } from "lucide-react";
|
import { Users } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta() {
|
||||||
|
return [{ title: "Participants - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export default function AdminParticipants() {
|
export default function AdminParticipants() {
|
||||||
return (
|
return (
|
||||||
<div className="p-8">
|
<div className="p-8">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Form, Link } from "react-router";
|
import { Form, Link } from "react-router";
|
||||||
import { useState, useEffect, useMemo } from "react";
|
import { useState, useEffect, useMemo } from "react";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.events.$eventId.bracket";
|
import type { Route } from "./+types/admin.sports-seasons.$id.events.$eventId.bracket";
|
||||||
|
|
||||||
import { loader, action } from "./admin.sports-seasons.$id.events.$eventId.bracket.server";
|
import { loader, action } from "./admin.sports-seasons.$id.events.$eventId.bracket.server";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
|
@ -32,6 +33,10 @@ import {
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { ParticipantSelector } from "~/components/ParticipantSelector";
|
import { ParticipantSelector } from "~/components/ParticipantSelector";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Bracket — ${data?.event?.name ?? "Event"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader, action };
|
export { loader, action };
|
||||||
|
|
||||||
export default function EventBracket({
|
export default function EventBracket({
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link } from "react-router";
|
import { Form, Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.events.$eventId";
|
import type { Route } from "./+types/admin.sports-seasons.$id.events.$eventId";
|
||||||
|
|
||||||
import { loader, action } from "./admin.sports-seasons.$id.events.$eventId.server";
|
import { loader, action } from "./admin.sports-seasons.$id.events.$eventId.server";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
|
@ -31,6 +32,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.event?.name ?? "Event"} — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader, action };
|
export { loader, action };
|
||||||
|
|
||||||
function EditEventCard({ event }: { event: { name: string; eventDate?: string | null } }) {
|
function EditEventCard({ event }: { event: { name: string; eventDate?: string | null } }) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link } from "react-router";
|
import { Form, Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.events";
|
import type { Route } from "./+types/admin.sports-seasons.$id.events";
|
||||||
|
|
||||||
import { loader, action } from "./admin.sports-seasons.$id.events.server";
|
import { loader, action } from "./admin.sports-seasons.$id.events.server";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
|
@ -36,6 +37,10 @@ import { format, parseISO } from "date-fns";
|
||||||
import { QualifyingPointsStandings } from "~/components/scoring/QualifyingPointsStandings";
|
import { QualifyingPointsStandings } from "~/components/scoring/QualifyingPointsStandings";
|
||||||
import { getEventTypeLabel } from "~/models/scoring-event";
|
import { getEventTypeLabel } from "~/models/scoring-event";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Events — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader, action };
|
export { loader, action };
|
||||||
|
|
||||||
export default function SportsSeasonEvents({
|
export default function SportsSeasonEvents({
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.expected-values";
|
import type { Route } from "./+types/admin.sports-seasons.$id.expected-values";
|
||||||
|
|
||||||
import { loader } from "./admin.sports-seasons.$id.expected-values.server";
|
import { loader } from "./admin.sports-seasons.$id.expected-values.server";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
|
|
@ -19,6 +20,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { ArrowLeft, Calculator } from "lucide-react";
|
import { ArrowLeft, Calculator } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Expected Values — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader };
|
export { loader };
|
||||||
|
|
||||||
const SCORING = [100, 70, 50, 40, 25, 25, 15, 15] as const;
|
const SCORING = [100, 70, 50, 40, 25, 25, 15, 15] as const;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, redirect, useLoaderData, useActionData, useNavigation } from 'react-router';
|
import { Form, redirect, useLoaderData, useActionData, useNavigation } from 'react-router';
|
||||||
import type { Route } from './+types/admin.sports-seasons.$id.futures-odds';
|
import type { Route } from './+types/admin.sports-seasons.$id.futures-odds';
|
||||||
|
|
||||||
import { findSportsSeasonById, updateSportsSeason } from '~/models/sports-season';
|
import { findSportsSeasonById, updateSportsSeason } from '~/models/sports-season';
|
||||||
import { findParticipantsBySportsSeasonId } from '~/models/participant';
|
import { findParticipantsBySportsSeasonId } from '~/models/participant';
|
||||||
import { getAllParticipantEVsForSeason, batchSaveSourceOdds, batchUpsertParticipantEVs } from '~/models/participant-expected-value';
|
import { getAllParticipantEVsForSeason, batchSaveSourceOdds, batchUpsertParticipantEVs } from '~/models/participant-expected-value';
|
||||||
|
|
@ -20,6 +21,10 @@ import {
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Loader2, Info, CheckCircle2, AlertCircle } from 'lucide-react';
|
import { Loader2, Info, CheckCircle2, AlertCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Futures Odds — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const sportsSeasonId = params.id;
|
const sportsSeasonId = params.id;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link } from "react-router";
|
import { Form, Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.participants";
|
import type { Route } from "./+types/admin.sports-seasons.$id.participants";
|
||||||
|
|
||||||
import { findSportsSeasonById } from "~/models/sports-season";
|
import { findSportsSeasonById } from "~/models/sports-season";
|
||||||
import {
|
import {
|
||||||
findParticipantsBySportsSeasonId,
|
findParticipantsBySportsSeasonId,
|
||||||
|
|
@ -27,6 +28,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { Plus, Trash2, ArrowLeft } from "lucide-react";
|
import { Plus, Trash2, ArrowLeft } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Participants — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const sportsSeason = await findSportsSeasonById(params.id);
|
const sportsSeason = await findSportsSeasonById(params.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link } from "react-router";
|
import { Form, Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id.standings";
|
import type { Route } from "./+types/admin.sports-seasons.$id.standings";
|
||||||
|
|
||||||
import { findSportsSeasonById } from "~/models/sports-season";
|
import { findSportsSeasonById } from "~/models/sports-season";
|
||||||
import { findParticipantsBySportsSeasonId } from "~/models/participant";
|
import { findParticipantsBySportsSeasonId } from "~/models/participant";
|
||||||
import { getSeasonResults, upsertSeasonResultsBulk } from "~/models/participant-season-result";
|
import { getSeasonResults, upsertSeasonResultsBulk } from "~/models/participant-season-result";
|
||||||
|
|
@ -14,6 +15,10 @@ import {
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
import { ArrowLeft, Save, ListOrdered } from "lucide-react";
|
import { ArrowLeft, Save, ListOrdered } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Standings — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const sportsSeason = await findSportsSeasonById(params.id);
|
const sportsSeason = await findSportsSeasonById(params.id);
|
||||||
if (!sportsSeason) {
|
if (!sportsSeason) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link, redirect, useNavigate } from "react-router";
|
import { Form, Link, redirect, useNavigate } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.$id";
|
import type { Route } from "./+types/admin.sports-seasons.$id";
|
||||||
|
|
||||||
import { findSportsSeasonById, updateSportsSeason, deleteSportsSeason } from "~/models/sports-season";
|
import { findSportsSeasonById, updateSportsSeason, deleteSportsSeason } from "~/models/sports-season";
|
||||||
import { findParticipantsBySportsSeasonId } from "~/models/participant";
|
import { findParticipantsBySportsSeasonId } from "~/models/participant";
|
||||||
import { processSeasonStandings } from "~/models/scoring-calculator";
|
import { processSeasonStandings } from "~/models/scoring-calculator";
|
||||||
|
|
@ -39,6 +40,10 @@ import { Badge } from "~/components/ui/badge";
|
||||||
import { Trash2, Users, Trophy, Calculator, CheckCircle2, Zap, AlertTriangle, Loader2 } from "lucide-react";
|
import { Trash2, Users, Trophy, Calculator, CheckCircle2, Zap, AlertTriangle, Loader2 } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const sportsSeason = await findSportsSeasonById(params.id);
|
const sportsSeason = await findSportsSeasonById(params.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link, redirect } from "react-router";
|
import { Form, Link, redirect } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons.new";
|
import type { Route } from "./+types/admin.sports-seasons.new";
|
||||||
|
|
||||||
import { createSportsSeason } from "~/models/sports-season";
|
import { createSportsSeason } from "~/models/sports-season";
|
||||||
import { findAllSports } from "~/models/sport";
|
import { findAllSports } from "~/models/sport";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -21,6 +22,10 @@ import {
|
||||||
} from "~/components/ui/select";
|
} from "~/components/ui/select";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "New Sports Season - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const sports = await findAllSports();
|
const sports = await findAllSports();
|
||||||
return { sports };
|
return { sports };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports-seasons";
|
import type { Route } from "./+types/admin.sports-seasons";
|
||||||
|
|
||||||
import { findAllSportsSeasons } from "~/models/sports-season";
|
import { findAllSportsSeasons } from "~/models/sports-season";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -20,6 +21,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Sports Seasons - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const sportsSeasons = await findAllSportsSeasons();
|
const sportsSeasons = await findAllSportsSeasons();
|
||||||
// Type assertion since we know the sport and participants relations are included from the model
|
// Type assertion since we know the sport and participants relations are included from the model
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link, redirect } from "react-router";
|
import { Form, Link, redirect } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports.$id";
|
import type { Route } from "./+types/admin.sports.$id";
|
||||||
|
|
||||||
import { findSportById, updateSport } from "~/models/sport";
|
import { findSportById, updateSport } from "~/models/sport";
|
||||||
import { writeFile, mkdir } from "node:fs/promises";
|
import { writeFile, mkdir } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
@ -22,6 +23,10 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "~/components/ui/select";
|
} from "~/components/ui/select";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.sport?.name ?? "Sport"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const sport = await findSportById(params.id);
|
const sport = await findSportById(params.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link, redirect } from "react-router";
|
import { Form, Link, redirect } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports.new";
|
import type { Route } from "./+types/admin.sports.new";
|
||||||
|
|
||||||
import { createSport } from "~/models/sport";
|
import { createSport } from "~/models/sport";
|
||||||
import { writeFile, mkdir } from "node:fs/promises";
|
import { writeFile, mkdir } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
@ -22,6 +23,10 @@ import {
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "~/components/ui/select";
|
} from "~/components/ui/select";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "New Sport - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function action({ request }: Route.ActionArgs) {
|
export async function action({ request }: Route.ActionArgs) {
|
||||||
const formData = await request.formData();
|
const formData = await request.formData();
|
||||||
const name = formData.get("name");
|
const name = formData.get("name");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.sports";
|
import type { Route } from "./+types/admin.sports";
|
||||||
|
|
||||||
import { findAllSportsWithActiveSeasons } from "~/models/sport";
|
import { findAllSportsWithActiveSeasons } from "~/models/sport";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -20,6 +21,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Sports - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const sports = await findAllSportsWithActiveSeasons();
|
const sports = await findAllSportsWithActiveSeasons();
|
||||||
return { sports };
|
return { sports };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useLoaderData, useActionData, Form } from "react-router";
|
import { useLoaderData, useActionData, Form } from "react-router";
|
||||||
import { redirect } from "react-router";
|
import { redirect } from "react-router";
|
||||||
import type { Route } from "./+types/admin.standings-snapshots";
|
import type { Route } from "./+types/admin.standings-snapshots";
|
||||||
|
|
||||||
import { database } from "~/database/context";
|
import { database } from "~/database/context";
|
||||||
import { eq, or } from "drizzle-orm";
|
import { eq, or } from "drizzle-orm";
|
||||||
import * as schema from "~/database/schema";
|
import * as schema from "~/database/schema";
|
||||||
|
|
@ -24,6 +25,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { Calendar, RefreshCw, CheckCircle2, AlertCircle } from "lucide-react";
|
import { Calendar, RefreshCw, CheckCircle2, AlertCircle } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Standings Snapshots - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const db = database();
|
const db = database();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Form, Link, redirect } from "react-router";
|
import { Form, Link, redirect } from "react-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type { Route } from "./+types/admin.templates.$id";
|
import type { Route } from "./+types/admin.templates.$id";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
findSeasonTemplateWithSportsSeasons,
|
findSeasonTemplateWithSportsSeasons,
|
||||||
updateSeasonTemplate,
|
updateSeasonTemplate,
|
||||||
|
|
@ -44,6 +45,10 @@ import {
|
||||||
import { Trash2, Plus, X } from "lucide-react";
|
import { Trash2, Plus, X } from "lucide-react";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.template?.name ?? "Template"} - Brackt Admin` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ params }: Route.LoaderArgs) {
|
export async function loader({ params }: Route.LoaderArgs) {
|
||||||
const template = await findSeasonTemplateWithSportsSeasons(params.id);
|
const template = await findSeasonTemplateWithSportsSeasons(params.id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Form, Link, redirect } from "react-router";
|
import { Form, Link, redirect } from "react-router";
|
||||||
import type { Route } from "./+types/admin.templates.new";
|
import type { Route } from "./+types/admin.templates.new";
|
||||||
|
|
||||||
import { createSeasonTemplate } from "~/models/season-template";
|
import { createSeasonTemplate } from "~/models/season-template";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
|
|
@ -13,6 +14,10 @@ import {
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "New Template - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function action({ request }: Route.ActionArgs) {
|
export async function action({ request }: Route.ActionArgs) {
|
||||||
const formData = await request.formData();
|
const formData = await request.formData();
|
||||||
const name = formData.get("name");
|
const name = formData.get("name");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/admin.templates";
|
import type { Route } from "./+types/admin.templates";
|
||||||
|
|
||||||
import { findAllSeasonTemplates } from "~/models/season-template";
|
import { findAllSeasonTemplates } from "~/models/season-template";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -20,6 +21,10 @@ import {
|
||||||
} from "~/components/ui/table";
|
} from "~/components/ui/table";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Templates - Brackt Admin" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const templates = await findAllSeasonTemplates();
|
const templates = await findAllSeasonTemplates();
|
||||||
return { templates };
|
return { templates };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Link, Outlet, redirect } from "react-router";
|
import { Link, Outlet, redirect } from "react-router";
|
||||||
import { getAuth } from "@clerk/react-router/server";
|
import { getAuth } from "@clerk/react-router/server";
|
||||||
import type { Route } from "./+types/admin";
|
import type { Route } from "./+types/admin";
|
||||||
|
|
||||||
import { isUserAdminByClerkId } from "~/models/user";
|
import { isUserAdminByClerkId } from "~/models/user";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
|
|
@ -11,6 +12,10 @@ import {
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Admin - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { userId } = await getAuth(args);
|
const { userId } = await getAuth(args);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { Form, redirect } from "react-router";
|
||||||
import { getAuth } from "@clerk/react-router/server";
|
import { getAuth } from "@clerk/react-router/server";
|
||||||
import { SignInButton } from "@clerk/react-router";
|
import { SignInButton } from "@clerk/react-router";
|
||||||
import type { Route } from "./+types/i.$inviteCode";
|
import type { Route } from "./+types/i.$inviteCode";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
findSeasonByInviteCode,
|
findSeasonByInviteCode,
|
||||||
findLeagueById,
|
findLeagueById,
|
||||||
|
|
@ -19,6 +20,10 @@ import {
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "~/components/ui/card";
|
} from "~/components/ui/card";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Join League - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { params } = args;
|
const { params } = args;
|
||||||
const { inviteCode } = params;
|
const { inviteCode } = params;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@ import { useState, useEffect } from "react";
|
||||||
import { buildOwnerMap } from "~/lib/owner-map";
|
import { buildOwnerMap } from "~/lib/owner-map";
|
||||||
import type { Route } from "./+types/$leagueId.draft-board.$seasonId";
|
import type { Route } from "./+types/$leagueId.draft-board.$seasonId";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Draft Board — ${data?.season?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { params } = args;
|
const { params } = args;
|
||||||
const { leagueId, seasonId } = params;
|
const { leagueId, seasonId } = params;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,10 @@ import { formatClockTime, getTimerColorClass } from "~/lib/draft-timer";
|
||||||
import { Users, LayoutGrid, ListChecks, Settings, ListOrdered } from "lucide-react";
|
import { Users, LayoutGrid, ListChecks, Settings, ListOrdered } from "lucide-react";
|
||||||
import type { Route } from "./+types/$leagueId.draft.$seasonId";
|
import type { Route } from "./+types/$leagueId.draft.$seasonId";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Draft — ${data?.season?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
type QueueItem = typeof schema.draftQueue.$inferSelect;
|
type QueueItem = typeof schema.draftQueue.$inferSelect;
|
||||||
|
|
||||||
type AutodraftStatusEntry = {
|
type AutodraftStatusEntry = {
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,10 @@ import {
|
||||||
import { ScoringRulesEditor } from "~/components/scoring/ScoringRulesEditor";
|
import { ScoringRulesEditor } from "~/components/scoring/ScoringRulesEditor";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Settings — ${data?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { userId } = await getAuth(args);
|
const { userId } = await getAuth(args);
|
||||||
const { params } = args;
|
const { params } = args;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import type { Route } from "./+types/$leagueId.sports-seasons.$sportsSeasonId";
|
import type { Route } from "./+types/$leagueId.sports-seasons.$sportsSeasonId";
|
||||||
|
|
||||||
import { loader } from "./$leagueId.sports-seasons.$sportsSeasonId.server";
|
import { loader } from "./$leagueId.sports-seasons.$sportsSeasonId.server";
|
||||||
import { SportSeasonDisplay } from "~/components/scoring/SportSeasonDisplay";
|
import { SportSeasonDisplay } from "~/components/scoring/SportSeasonDisplay";
|
||||||
import { EventSchedule } from "~/components/sport-season/EventSchedule";
|
import { EventSchedule } from "~/components/sport-season/EventSchedule";
|
||||||
|
|
@ -7,6 +8,10 @@ import { Button } from "~/components/ui/button";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { ArrowLeft, CheckCircle2, Clock, Zap } from "lucide-react";
|
import { ArrowLeft, CheckCircle2, Clock, Zap } from "lucide-react";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.sportsSeason?.name ?? "Sport Season"} — ${data?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader };
|
export { loader };
|
||||||
|
|
||||||
function getStatusBadge(status: string) {
|
function getStatusBadge(status: string) {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
import { useLoaderData } from "react-router";
|
import { useLoaderData } from "react-router";
|
||||||
import type { Route } from "./+types/$leagueId.standings.$seasonId.teams.$teamId";
|
import type { Route } from "./+types/$leagueId.standings.$seasonId.teams.$teamId";
|
||||||
|
|
||||||
import { TeamScoreBreakdown } from "~/components/standings/TeamScoreBreakdown";
|
import { TeamScoreBreakdown } from "~/components/standings/TeamScoreBreakdown";
|
||||||
import { getTeamScoreBreakdown, getTeamStanding } from "~/models/standings";
|
import { getTeamScoreBreakdown, getTeamStanding } from "~/models/standings";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.breakdown?.team?.name ?? "Team"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Team score breakdown page
|
* Team score breakdown page
|
||||||
* Shows all drafted participants with their placements and points
|
* Shows all drafted participants with their placements and points
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ import { isSeasonComplete, getSeasonCompletionPercentage } from "~/lib/season-he
|
||||||
import { PointProgressionChart } from "~/components/standings/PointProgressionChart";
|
import { PointProgressionChart } from "~/components/standings/PointProgressionChart";
|
||||||
import type { Route } from "./+types/$leagueId.standings.$seasonId";
|
import type { Route } from "./+types/$leagueId.standings.$seasonId";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Standings — ${data?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
try {
|
try {
|
||||||
const { userId } = await getAuth(args);
|
const { userId } = await getAuth(args);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Link, useSearchParams } from "react-router";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import type { Route } from "./+types/$leagueId";
|
import type { Route } from "./+types/$leagueId";
|
||||||
|
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
|
|
@ -14,6 +15,10 @@ import {
|
||||||
import { SportSeasonCard } from "~/components/sports/SportSeasonCard";
|
import { SportSeasonCard } from "~/components/sports/SportSeasonCard";
|
||||||
import { getDisplayRank } from "~/lib/standings-display";
|
import { getDisplayRank } from "~/lib/standings-display";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `${data?.league?.name ?? "League"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export { loader } from "./$leagueId.server";
|
export { loader } from "./$leagueId.server";
|
||||||
|
|
||||||
export default function LeagueHome({ loaderData }: Route.ComponentProps) {
|
export default function LeagueHome({ loaderData }: Route.ComponentProps) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useState } from "react";
|
||||||
import { Form, redirect, Link } from "react-router";
|
import { Form, redirect, Link } from "react-router";
|
||||||
import { getAuth } from "@clerk/react-router/server";
|
import { getAuth } from "@clerk/react-router/server";
|
||||||
import type { Route } from "./+types/new";
|
import type { Route } from "./+types/new";
|
||||||
|
|
||||||
import { createLeague, setCurrentSeason } from "~/models/league";
|
import { createLeague, setCurrentSeason } from "~/models/league";
|
||||||
import { createCommissioner } from "~/models/commissioner";
|
import { createCommissioner } from "~/models/commissioner";
|
||||||
import { createSeason } from "~/models/season";
|
import { createSeason } from "~/models/season";
|
||||||
|
|
@ -40,6 +41,10 @@ import {
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { ScoringRulesEditor } from "~/components/scoring/ScoringRulesEditor";
|
import { ScoringRulesEditor } from "~/components/scoring/ScoringRulesEditor";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "New League - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader() {
|
export async function loader() {
|
||||||
const templates = await findActiveSeasonTemplates();
|
const templates = await findActiveSeasonTemplates();
|
||||||
const allSportsSeasons = await findAllSportsSeasons();
|
const allSportsSeasons = await findAllSportsSeasons();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { Form, redirect, useNavigate } from "react-router";
|
import { Form, redirect, useNavigate } from "react-router";
|
||||||
import { getAuth } from "@clerk/react-router/server";
|
import { getAuth } from "@clerk/react-router/server";
|
||||||
import type { Route } from "./+types/$teamId.settings";
|
import type { Route } from "./+types/$teamId.settings";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
findTeamById,
|
findTeamById,
|
||||||
updateTeam,
|
updateTeam,
|
||||||
|
|
@ -29,6 +30,10 @@ import {
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "~/components/ui/alert-dialog";
|
} from "~/components/ui/alert-dialog";
|
||||||
|
|
||||||
|
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
|
||||||
|
return [{ title: `Team Settings — ${data?.team?.name ?? "Team"} - Brackt` }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { params } = args;
|
const { params } = args;
|
||||||
const { teamId } = params;
|
const { teamId } = params;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useDraftSocket } from "~/hooks/useDraftSocket";
|
import { useDraftSocket } from "~/hooks/useDraftSocket";
|
||||||
|
|
||||||
|
export function meta() {
|
||||||
|
return [{ title: "Socket Test - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export default function TestSocket() {
|
export default function TestSocket() {
|
||||||
const [messages, setMessages] = useState<string[]>([]);
|
const [messages, setMessages] = useState<string[]>([]);
|
||||||
const { isConnected, on, off, emit } = useDraftSocket("test-season-123");
|
const { isConnected, on, off, emit } = useDraftSocket("test-season-123");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@ import { getAuth } from "@clerk/react-router/server";
|
||||||
import { redirect } from "react-router";
|
import { redirect } from "react-router";
|
||||||
import type { Route } from "./+types/user-profile";
|
import type { Route } from "./+types/user-profile";
|
||||||
|
|
||||||
|
export function meta(): Route.MetaDescriptors {
|
||||||
|
return [{ title: "Profile - Brackt" }];
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
const { userId } = await getAuth(args);
|
const { userId } = await getAuth(args);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue