86 lines
3 KiB
TypeScript
86 lines
3 KiB
TypeScript
import config from "@payload-config";
|
|
import { getPayload } from "payload";
|
|
import type { Award, Media } from "@/payload-types";
|
|
import { AwardWithGrantButton } from "@/components/frontend/account/AwardWithGrantButton";
|
|
import { Item, ItemContent, ItemHeader, ItemTitle } from "@/components/ui/item";
|
|
import { MedalIcon } from "lucide-react";
|
|
|
|
export const metadata = {
|
|
title: "Awards",
|
|
description:
|
|
"Browse every medal and ribbon that can be granted to a member of Polaris Task Force.",
|
|
};
|
|
|
|
const TYPE_LABEL: Record<"ribbon" | "medal", string> = {
|
|
ribbon: "Ribbons",
|
|
medal: "Medals",
|
|
};
|
|
|
|
export default async function AwardsPage() {
|
|
const payload = await getPayload({ config });
|
|
|
|
const res = await payload.find({
|
|
collection: "awards",
|
|
where: {
|
|
type: { in: ["ribbon", "medal"] },
|
|
},
|
|
sort: "name",
|
|
limit: 100,
|
|
depth: 1,
|
|
overrideAccess: true,
|
|
});
|
|
|
|
const awards: Award[] = res.docs;
|
|
const ribbons = awards.filter((a) => a.type === "ribbon");
|
|
const medals = awards.filter((a) => a.type === "medal");
|
|
|
|
const sections: { title: string; items: Award[] }[] = [];
|
|
if (medals.length > 0) sections.push({ title: TYPE_LABEL.medal, items: medals });
|
|
if (ribbons.length > 0) sections.push({ title: TYPE_LABEL.ribbon, items: ribbons });
|
|
|
|
return (
|
|
<div className="p-5 flex flex-col gap-6 max-w-7xl">
|
|
<div className="flex flex-col gap-1.5">
|
|
<div className="flex items-center gap-2">
|
|
<MedalIcon className="size-4 text-muted-foreground" />
|
|
<h1 className="text-2xl font-bold tracking-tight uppercase">Awards</h1>
|
|
</div>
|
|
<p className="text-sm text-muted-foreground max-w-2xl">
|
|
A reference of every medal and ribbon that can be earned by a member of Polaris Task
|
|
Force. Review the requirements for each award and its artwork. Commendations are granted
|
|
on the fly and are not catalogued here.
|
|
</p>
|
|
</div>
|
|
|
|
{awards.length === 0 ? (
|
|
<Item variant="muted">
|
|
<ItemHeader>
|
|
<ItemTitle>No awards defined</ItemTitle>
|
|
</ItemHeader>
|
|
<ItemContent>
|
|
<p className="text-sm text-muted-foreground italic">
|
|
No medals or ribbons have been catalogued yet. Check back soon.
|
|
</p>
|
|
</ItemContent>
|
|
</Item>
|
|
) : (
|
|
sections.map((section) => (
|
|
<section key={section.title} className="flex flex-col gap-3">
|
|
<h2 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground">
|
|
{section.title}
|
|
</h2>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{section.items.map((award) => {
|
|
const awardImage =
|
|
typeof award.image === "object" && award.image ? (award.image as Media) : null;
|
|
return (
|
|
<AwardWithGrantButton key={award.id} award={award} awardImage={awardImage} />
|
|
);
|
|
})}
|
|
</div>
|
|
</section>
|
|
))
|
|
)}
|
|
</div>
|
|
);
|
|
}
|