Skip to content

Commit 5cbc622

Browse files
committed
feat: add submissions overview to admin
1 parent de0257d commit 5cbc622

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export default function SheetStats({ submissions }) {
2+
return (
3+
<>
4+
<p>Total Submissions: {submissions.length}</p>
5+
<div className="overflow-x-auto">
6+
<table className="table">
7+
<thead>
8+
<tr>
9+
<th>username</th>
10+
<th>name</th>
11+
<th>paid</th>
12+
<th>submitted at</th>
13+
</tr>
14+
</thead>
15+
<tbody>
16+
{submissions.map((submission) => (
17+
<tr key={submission.id}>
18+
<th>{submission?.sailor?.username}</th>
19+
<th>{`${submission?.sailor?.firstName} ${submission?.sailor?.lastName}`}</th>
20+
<th>{submission.isPaid ? "✅" : "❌"}</th>
21+
<th>{submission.createdAt}</th>
22+
</tr>
23+
))}
24+
</tbody>
25+
</table>
26+
</div>
27+
</>
28+
);
29+
}

app/routes/sheets.$sheetId.admin/route.tsx

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,35 @@
1-
import { json, LoaderFunctionArgs } from "@remix-run/node";
1+
import { json, LoaderFunctionArgs, redirect } from "@remix-run/node";
22
import { useLoaderData } from "@remix-run/react";
33
import invariant from "tiny-invariant";
44
import { readSheet } from "~/models/sheet.server";
55
import { authenticator } from "~/services/auth.server";
66
import StatusSelector from "./components/StatusSelector";
77
import EditSheet from "./components/EditSheet";
88
import MarkSheet from "./components/MarkSheet";
9+
import { readSailor } from "~/models/sailor.server";
10+
import SheetStats from "./components/SheetStats";
11+
import { readSheetSubmissions } from "~/models/submission.server";
912

1013
export const loader = async ({ params, request }: LoaderFunctionArgs) => {
11-
await authenticator.isAuthenticated(request, {
14+
const sailorId = await authenticator.isAuthenticated(request, {
1215
failureRedirect: "/login",
1316
});
1417
invariant(params.sheetId, `params.sheetId is required`);
15-
// todo: redirect if not an admin
18+
const sailor = await readSailor(sailorId);
19+
if (!sailor || !sailor.admin) return redirect("/");
1620
const sheet = await readSheet(params.sheetId);
21+
const submissions = await readSheetSubmissions(params.sheetId);
1722
invariant(!!sheet, "No such sheet");
18-
return json({ sheet });
23+
return json({ sheet, submissions });
1924
};
2025

2126
export default function SheetEdit() {
22-
const { sheet } = useLoaderData<typeof loader>();
27+
const { sheet, submissions } = useLoaderData<typeof loader>();
2328
return (
2429
<>
2530
<StatusSelector sheet={sheet} />
2631
{sheet.status === "DRAFT" && <EditSheet sheet={sheet} />}
27-
{sheet.status === "OPEN" && <span>Currently accepting submissions</span>}
32+
{sheet.status === "OPEN" && <SheetStats submissions={submissions} />}
2833
{sheet.status === "CLOSED" && <MarkSheet sheet={sheet} />}
2934
</>
3035
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- AlterTable
2+
ALTER TABLE "Submission" ADD COLUMN "isPaid" BOOLEAN NOT NULL DEFAULT false;

prisma/schema.prisma

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ model Submission {
9696
selections PropositionSelection[]
9797
9898
tieBreaker Int
99+
isPaid Boolean @default(false)
99100
}
100101

101102
model PropositionSelection {

0 commit comments

Comments
 (0)