Skip to content

Commit

Permalink
feat: query by academic year
Browse files Browse the repository at this point in the history
  • Loading branch information
Gum-Joe committed Aug 14, 2024
1 parent 0ad967e commit 534c267
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 34 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
"editor.tabSize": 4,
"editor.insertSpaces": true,
"editor.detectIndentation": false,
"editor.formatOnSave": true
"editor.formatOnSave": true,
"sqltools.formatLanguages": []
}
83 changes: 54 additions & 29 deletions collection/app/(app)/UserSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,6 @@ export const UserSearch: React.FC<UserSearchProps> = ({
const router = useRouter();
const shortcodeURLParam = useMemo(() => searchParams.get("shortcode") || "", [searchParams]);

const fetchPurchases = useCallback(async (shortcode: string) => {
const res = await fetch(`/api/purchases/${shortcode}`, {
next: { tags: [`purchases:${shortcode}`] },
});
if (!res.ok) {
setError("An error occurred");
return;
}

const purchases = await res.json();
if (purchases.status === "error") {
setError(purchases.message);
setPurchases([]);
} else {
setPurchases(purchases.orders);
}
}, []);

// Form
// 2 fields: shortcode & academic year purcahses.
// Default value of shortcode is from the URL if possible
Expand All @@ -60,26 +42,67 @@ export const UserSearch: React.FC<UserSearchProps> = ({
},
},
});

const fetchPurchases = useCallback(
async (shortcode: string) => {
const res = await fetch(
`/api/purchases/${shortcode}?` +
new URLSearchParams({
academicYears: form.getValues().academicYears.join(","),
}),
{
next: { tags: [`purchases:${shortcode}`] },
},
);
if (!res.ok) {
setError("An error occurred");
return;
}

const purchases = await res.json();
if (purchases.status === "error") {
setError(purchases.message);
setPurchases([]);
} else {
setPurchases(purchases.orders);
}
},
[form],
);

// This looks a bit weird, but effectively prevent an infinite loop of fetching purchases
const [prevURLParam, setPrevURLParam] = useState(shortcodeURLParam);
useEffect(() => {
if (shortcodeURLParam) {
fetchPurchases(shortcodeURLParam);
} else {
setPurchases([]);
form.setFieldValue("shortcode", "");
if (!shortcodeURLParam) {
// only allow one rerender when the shortcode is clear
// by tracking the previous value
if (prevURLParam) {
setPurchases([]);
form.setFieldValue("shortcode", "");
setPrevURLParam("");
}
}
}, [shortcodeURLParam, prevURLParam, form]);

// Fetch purchases if academic year changes
form.watch("academicYears", (academicYears) => {
if (form.getValues().shortcode) {
startTransition(async () => {
setError(null);
await fetchPurchases(form.getValues().shortcode);
});
}
// can't add form as would cause infinite loop
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shortcodeURLParam, fetchPurchases]);
});

const submitAction = useCallback(
({ shortcode }: { shortcode: string }) => {
startTransition(() => {
startTransition(async () => {
setError(null);

await fetchPurchases(shortcode);
router.push("/?shortcode=" + shortcode);
});
},
[router],
[router, fetchPurchases],
);

return (
Expand All @@ -96,6 +119,7 @@ export const UserSearch: React.FC<UserSearchProps> = ({
alignItems: "center",
}}
onSubmit={form.onSubmit(submitAction)}
// eslint-disable-next-line @typescript-eslint/no-empty-function
action={() => {}}
>
<Group w="100%">
Expand All @@ -115,6 +139,7 @@ export const UserSearch: React.FC<UserSearchProps> = ({
<Button
color="pink"
onClick={() => {
setPurchases([]);
router.push("/");
}}
>
Expand Down
10 changes: 7 additions & 3 deletions collection/app/api/purchases/[shortcode]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { getAcademicYear } from "@/lib/config";
import { getPurchasesByShortcode } from "@/lib/crud/purchase";
import { NextResponse } from "next/server";
import { NextRequest, NextResponse } from "next/server";

export async function GET(request: Request, { params }: { params: { shortcode: string } }) {
return NextResponse.json(await getPurchasesByShortcode(params.shortcode));
export async function GET(request: NextRequest, { params }: { params: { shortcode: string } }) {
const searchParams = request.nextUrl.searchParams;
const academicYears =
searchParams.get("academicYears")?.split(",") ?? (await getAcademicYear());
return NextResponse.json(await getPurchasesByShortcode(params.shortcode, academicYears));
}
10 changes: 9 additions & 1 deletion collection/lib/crud/purchase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export type GetPurchasesReturn =
orders: OrderResponse[];
}
| { status: "error"; message: string };
export const getPurchasesByShortcode = async (shortcode: string): Promise<GetPurchasesReturn> => {
export const getPurchasesByShortcode = async (
shortcode: string,
academicYears: string[],
): Promise<GetPurchasesReturn> => {
const student = await prisma.imperialStudent.findFirst({
where: {
shortcode: shortcode,
Expand All @@ -42,6 +45,11 @@ export const getPurchasesByShortcode = async (shortcode: string): Promise<GetPur
},
},
},
where: {
academicYear: {
in: academicYears,
},
},
},
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Warnings:
- Added the required column `academicYear` to the `Order` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "Order" ADD COLUMN "academicYear" TEXT;

-- AddForeignKey
ALTER TABLE "Order" ADD CONSTRAINT "Order_academicYear_fkey" FOREIGN KEY ("academicYear") REFERENCES "AcademicYear"("year") ON DELETE RESTRICT ON UPDATE CASCADE;

-- Set default value to 23-24
-- create 23-24 if it doesn't exist
INSERT INTO "AcademicYear" ("year") VALUES ('23-24') ON CONFLICT DO NOTHING;
UPDATE "Order" SET "academicYear" = '23-24';

-- Make it non-NULL
ALTER TABLE "Order" ALTER COLUMN "academicYear" SET NOT NULL;

6 changes: 6 additions & 0 deletions collection/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ model AcademicYear {
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
Order Order[]
}

// ==================
Expand Down Expand Up @@ -78,6 +80,10 @@ model Order {
orderNo Int @unique
ImperialStudent ImperialStudent @relation(fields: [studentId], references: [id])
OrderItem OrderItem[]
// An order is placed in some academic year
academicYear String
academicYearReference AcademicYear @relation(fields: [academicYear], references: [year])
}

// OrderItems are the items that make up an order
Expand Down

0 comments on commit 534c267

Please sign in to comment.