refactor: remove guest book feature and update league settings success flow
This commit is contained in:
parent
9749fc8b77
commit
48bca99f37
8 changed files with 375 additions and 127 deletions
|
|
@ -1,7 +1,5 @@
|
|||
import { useEffect } from "react";
|
||||
import { useSearchParams } from "react-router";
|
||||
import { database } from "~/database/context";
|
||||
import * as schema from "~/database/schema";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import type { Route } from "./+types/home";
|
||||
|
|
@ -9,50 +7,18 @@ import { Welcome } from "../welcome/welcome";
|
|||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: "New React Router App" },
|
||||
{ name: "description", content: "Welcome to React Router!" },
|
||||
{ title: "Brackt - Fantasy Sports Brackets" },
|
||||
{ name: "description", content: "Create and manage your fantasy sports leagues" },
|
||||
];
|
||||
}
|
||||
|
||||
export async function action({ request }: Route.ActionArgs) {
|
||||
const formData = await request.formData();
|
||||
let name = formData.get("name");
|
||||
let email = formData.get("email");
|
||||
if (typeof name !== "string" || typeof email !== "string") {
|
||||
return { guestBookError: "Name and email are required" };
|
||||
}
|
||||
|
||||
name = name.trim();
|
||||
email = email.trim();
|
||||
if (!name || !email) {
|
||||
return { guestBookError: "Name and email are required" };
|
||||
}
|
||||
|
||||
const db = database();
|
||||
try {
|
||||
await db.insert(schema.guestBook).values({ name, email });
|
||||
} catch (error) {
|
||||
return { guestBookError: "Error adding to guest book" };
|
||||
}
|
||||
}
|
||||
|
||||
export async function loader({ context }: Route.LoaderArgs) {
|
||||
const db = database();
|
||||
|
||||
const guestBook = await db.query.guestBook.findMany({
|
||||
columns: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
guestBook,
|
||||
message: context.VALUE_FROM_EXPRESS,
|
||||
};
|
||||
}
|
||||
|
||||
export default function Home({ actionData, loaderData }: Route.ComponentProps) {
|
||||
export default function Home({ loaderData }: Route.ComponentProps) {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -63,11 +29,5 @@ export default function Home({ actionData, loaderData }: Route.ComponentProps) {
|
|||
}
|
||||
}, [searchParams, setSearchParams]);
|
||||
|
||||
return (
|
||||
<Welcome
|
||||
guestBook={loaderData.guestBook}
|
||||
guestBookError={actionData?.guestBookError}
|
||||
message={loaderData.message}
|
||||
/>
|
||||
);
|
||||
return <Welcome message={loaderData.message} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ export async function action(args: Route.ActionArgs) {
|
|||
name: name.trim(),
|
||||
});
|
||||
|
||||
return { success: "League updated successfully" };
|
||||
return redirect(`/leagues/${leagueId}?updated=true`);
|
||||
} catch (error) {
|
||||
console.error("Error updating league:", error);
|
||||
return { error: "Failed to update league. Please try again." };
|
||||
|
|
@ -198,12 +198,6 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
|
|||
</p>
|
||||
</div>
|
||||
|
||||
{actionData?.success && (
|
||||
<div className="bg-green-50 dark:bg-green-950 text-green-700 dark:text-green-300 px-4 py-3 rounded-md text-sm">
|
||||
{actionData.success}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{actionData?.error && (
|
||||
<div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
|
||||
{actionData.error}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
import { Link } from "react-router";
|
||||
import { useEffect } from "react";
|
||||
import { Link, useSearchParams } from "react-router";
|
||||
import { getAuth } from "@clerk/react-router/server";
|
||||
import { findLeagueById } from "~/models/league";
|
||||
import { findCurrentSeason } from "~/models/season";
|
||||
import { findTeamsBySeasonId } from "~/models/team";
|
||||
import { findCommissionersByLeagueId } from "~/models/commissioner";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
findLeagueById,
|
||||
findCurrentSeason,
|
||||
findTeamsBySeasonId,
|
||||
findCommissionersByLeagueId,
|
||||
} from "~/models";
|
||||
import type { Route } from "./+types/$leagueId";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
|
|
@ -12,7 +17,6 @@ import {
|
|||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card";
|
||||
import { Button } from "~/components/ui/button";
|
||||
|
||||
export async function loader(args: Route.LoaderArgs) {
|
||||
const { userId } = await getAuth(args);
|
||||
|
|
@ -50,6 +54,15 @@ export async function loader(args: Route.LoaderArgs) {
|
|||
|
||||
export default function LeagueHome({ loaderData }: Route.ComponentProps) {
|
||||
const { league, season, teams, commissioners, currentUserId, isUserCommissioner } = loaderData;
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
|
||||
useEffect(() => {
|
||||
if (searchParams.get("updated") === "true") {
|
||||
toast.success("League updated successfully");
|
||||
// Remove the query parameter
|
||||
setSearchParams({});
|
||||
}
|
||||
}, [searchParams, setSearchParams]);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-8 px-4">
|
||||
|
|
|
|||
|
|
@ -1,23 +1,10 @@
|
|||
import { Form, Link, useNavigation } from "react-router";
|
||||
import { Link } from "react-router";
|
||||
import { Button } from "~/components/ui/button";
|
||||
|
||||
import logoDark from "./logo-dark.svg";
|
||||
import logoLight from "./logo-light.svg";
|
||||
|
||||
export function Welcome({
|
||||
guestBook,
|
||||
guestBookError,
|
||||
message,
|
||||
}: {
|
||||
guestBook: {
|
||||
name: string;
|
||||
id: number;
|
||||
}[];
|
||||
guestBookError?: string;
|
||||
message: string;
|
||||
}) {
|
||||
const navigation = useNavigation();
|
||||
|
||||
export function Welcome({ message }: { message: string }) {
|
||||
return (
|
||||
<main className="flex items-center justify-center pt-16 pb-4">
|
||||
<div className="flex-1 flex flex-col items-center gap-16 min-h-0">
|
||||
|
|
@ -62,55 +49,6 @@ export function Welcome({
|
|||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
<section className="rounded-3xl border border-gray-200 p-6 dark:border-gray-700 space-y-4">
|
||||
<Form
|
||||
method="post"
|
||||
className="space-y-4 w-full max-w-lg"
|
||||
onSubmit={(event) => {
|
||||
if (navigation.state === "submitting") {
|
||||
event.preventDefault();
|
||||
}
|
||||
const form = event.currentTarget;
|
||||
requestAnimationFrame(() => {
|
||||
form.reset();
|
||||
});
|
||||
}}
|
||||
>
|
||||
<input
|
||||
name="name"
|
||||
placeholder="Name"
|
||||
required
|
||||
className="w-full dark:bg-gray-800 dark:text-gray-200 dark:border-gray-700 dark:focus:ring-blue-500 h-10 px-3 rounded-lg border border-gray-200 focus:ring-1 focus:ring-blue-500"
|
||||
/>
|
||||
<input
|
||||
name="email"
|
||||
type="email"
|
||||
placeholder="your@email.com"
|
||||
required
|
||||
className="w-full dark:bg-gray-800 dark:text-gray-200 dark:border-gray-700 dark:focus:ring-blue-500 h-10 px-3 rounded-lg border border-gray-200 focus:ring-1 focus:ring-blue-500"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={navigation.state === "submitting"}
|
||||
className="w-full h-10 px-3 text-white bg-blue-500 rounded-lg hover:bg-blue-600"
|
||||
>
|
||||
Sign Guest Book
|
||||
</button>
|
||||
{guestBookError && (
|
||||
<p className="text-red-500 dark:text-red-400">
|
||||
{guestBookError}
|
||||
</p>
|
||||
)}
|
||||
</Form>
|
||||
<ul className="text-center">
|
||||
{<li className="p-3">{message}</li>}
|
||||
{guestBook.map(({ id, name }) => (
|
||||
<li key={id} className="p-3">
|
||||
{name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,5 @@
|
|||
import { integer, pgTable, varchar, uuid, timestamp, pgEnum } from "drizzle-orm/pg-core";
|
||||
|
||||
export const guestBook = pgTable("guestBook", {
|
||||
id: integer().primaryKey().generatedAlwaysAsIdentity(),
|
||||
name: varchar({ length: 255 }).notNull(),
|
||||
email: varchar({ length: 255 }).notNull().unique(),
|
||||
});
|
||||
|
||||
// Users table - synced from Clerk
|
||||
export const users = pgTable("users", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
|
|
|
|||
1
drizzle/0005_abnormal_thunderbird.sql
Normal file
1
drizzle/0005_abnormal_thunderbird.sql
Normal file
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE "guestBook" CASCADE;
|
||||
341
drizzle/meta/0005_snapshot.json
Normal file
341
drizzle/meta/0005_snapshot.json
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
{
|
||||
"id": "6839ce43-d04c-4246-9b00-7820935e1166",
|
||||
"prevId": "5e858241-1709-4099-90d2-58c7e3bf0d23",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.commissioners": {
|
||||
"name": "commissioners",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"league_id": {
|
||||
"name": "league_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"commissioners_league_id_leagues_id_fk": {
|
||||
"name": "commissioners_league_id_leagues_id_fk",
|
||||
"tableFrom": "commissioners",
|
||||
"tableTo": "leagues",
|
||||
"columnsFrom": [
|
||||
"league_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.leagues": {
|
||||
"name": "leagues",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_by": {
|
||||
"name": "created_by",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.seasons": {
|
||||
"name": "seasons",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"league_id": {
|
||||
"name": "league_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"year": {
|
||||
"name": "year",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"status": {
|
||||
"name": "status",
|
||||
"type": "season_status",
|
||||
"typeSchema": "public",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'pre_draft'"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"seasons_league_id_leagues_id_fk": {
|
||||
"name": "seasons_league_id_leagues_id_fk",
|
||||
"tableFrom": "seasons",
|
||||
"tableTo": "leagues",
|
||||
"columnsFrom": [
|
||||
"league_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.teams": {
|
||||
"name": "teams",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"season_id": {
|
||||
"name": "season_id",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"owner_id": {
|
||||
"name": "owner_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"teams_season_id_seasons_id_fk": {
|
||||
"name": "teams_season_id_seasons_id_fk",
|
||||
"tableFrom": "teams",
|
||||
"tableTo": "seasons",
|
||||
"columnsFrom": [
|
||||
"season_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.users": {
|
||||
"name": "users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"clerk_id": {
|
||||
"name": "clerk_id",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": true
|
||||
},
|
||||
"display_name": {
|
||||
"name": "display_name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"first_name": {
|
||||
"name": "first_name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"last_name": {
|
||||
"name": "last_name",
|
||||
"type": "varchar(255)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"image_url": {
|
||||
"name": "image_url",
|
||||
"type": "varchar(512)",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
},
|
||||
"updated_at": {
|
||||
"name": "updated_at",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "now()"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"users_clerk_id_unique": {
|
||||
"name": "users_clerk_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"clerk_id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {
|
||||
"public.season_status": {
|
||||
"name": "season_status",
|
||||
"schema": "public",
|
||||
"values": [
|
||||
"pre_draft",
|
||||
"draft",
|
||||
"active",
|
||||
"completed"
|
||||
]
|
||||
}
|
||||
},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,13 @@
|
|||
"when": 1760168383812,
|
||||
"tag": "0004_spicy_zarda",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"version": "7",
|
||||
"when": 1760169537260,
|
||||
"tag": "0005_abnormal_thunderbird",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue