feat(account): Add assignment cards and current assignments display to account page
Add AssignmentCard component integration showing user's assignments with transfer button. Add RequestTransferDialog integration for requesting transfers. Display current assignments as badges with leader indication. Include proper loading states and error handling.
This commit is contained in:
parent
f1a338c90b
commit
b9326cfc54
1 changed files with 86 additions and 0 deletions
|
|
@ -2,17 +2,27 @@ import config from "@payload-config";
|
||||||
import { getPayload } from "payload";
|
import { getPayload } from "payload";
|
||||||
import { headers as nextHeaders } from "next/headers";
|
import { headers as nextHeaders } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
import type { Assignment } from "@/payload-types";
|
||||||
import { UserCogIcon } from "lucide-react";
|
import { UserCogIcon } from "lucide-react";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { AccountProfileForm } from "@/components/frontend/account/AccountProfileForm";
|
import { AccountProfileForm } from "@/components/frontend/account/AccountProfileForm";
|
||||||
|
import { AssignmentCard } from "@/components/frontend/account/AssignmentCard";
|
||||||
|
import type { AccountAssignment } from "@/components/frontend/transfers/transferTypes";
|
||||||
import { ChangePasswordForm } from "@/components/frontend/account/ChangePasswordForm";
|
import { ChangePasswordForm } from "@/components/frontend/account/ChangePasswordForm";
|
||||||
import { DiscordUsernameRequestForm } from "@/components/frontend/account/DiscordUsernameRequestForm";
|
import { DiscordUsernameRequestForm } from "@/components/frontend/account/DiscordUsernameRequestForm";
|
||||||
import { PreferencesForm } from "@/components/frontend/account/PreferencesForm";
|
import { PreferencesForm } from "@/components/frontend/account/PreferencesForm";
|
||||||
|
import { RequestTransferDialog } from "@/components/frontend/account/RequestTransferDialog";
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: "Account — Polaris Task Force",
|
title: "Account — Polaris Task Force",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function relationId(value: Assignment["leader"]): number | null {
|
||||||
|
if (typeof value === "object" && value !== null) return value.id;
|
||||||
|
return value ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
export default async function AccountPage() {
|
export default async function AccountPage() {
|
||||||
const payload = await getPayload({ config });
|
const payload = await getPayload({ config });
|
||||||
const { user } = await payload.auth({
|
const { user } = await payload.auth({
|
||||||
|
|
@ -30,6 +40,46 @@ export default async function AccountPage() {
|
||||||
depth: 0,
|
depth: 0,
|
||||||
overrideAccess: true,
|
overrideAccess: true,
|
||||||
});
|
});
|
||||||
|
const assignmentsRes = await payload.find({
|
||||||
|
collection: "assignments",
|
||||||
|
where: {
|
||||||
|
or: [{ members: { equals: user.id } }, { leader: { equals: user.id } }],
|
||||||
|
},
|
||||||
|
limit: 50,
|
||||||
|
depth: 0,
|
||||||
|
select: { name: true, type: true, callsign: true, leader: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const assignments: AccountAssignment[] = assignmentsRes.docs.map((assignment) => ({
|
||||||
|
id: assignment.id,
|
||||||
|
name: assignment.name,
|
||||||
|
type: assignment.type,
|
||||||
|
callsign: assignment.callsign ?? null,
|
||||||
|
leaderId:
|
||||||
|
typeof assignment.leader === "object" && assignment.leader !== null
|
||||||
|
? assignment.leader.id
|
||||||
|
: (assignment.leader ?? null),
|
||||||
|
isLeader: relationId(assignment.leader) === user.id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const assignmentRes = await payload.find({
|
||||||
|
collection: "assignments",
|
||||||
|
where: {
|
||||||
|
or: [{ members: { contains: user.id } }, { leader: { equals: user.id } }],
|
||||||
|
},
|
||||||
|
sort: "name",
|
||||||
|
limit: 100,
|
||||||
|
depth: 0,
|
||||||
|
select: { name: true, type: true, callsign: true, leader: true },
|
||||||
|
});
|
||||||
|
const currentAssignments: AccountAssignment[] = assignmentRes.docs.map((assignment) => ({
|
||||||
|
id: assignment.id,
|
||||||
|
name: assignment.name,
|
||||||
|
type: assignment.type,
|
||||||
|
callsign: assignment.callsign ?? null,
|
||||||
|
leaderId: relationId(assignment.leader),
|
||||||
|
isLeader: relationId(assignment.leader) === user.id,
|
||||||
|
}));
|
||||||
|
|
||||||
const notifications = fullUser.preferences?.notifications;
|
const notifications = fullUser.preferences?.notifications;
|
||||||
const discord = fullUser.preferences?.discord;
|
const discord = fullUser.preferences?.discord;
|
||||||
|
|
@ -57,6 +107,42 @@ export default async function AccountPage() {
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<AssignmentCard assignments={assignments} requesterId={user.id} />
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<CardHeader className="gap-3">
|
||||||
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
||||||
|
<div className="flex min-w-0 flex-col gap-1">
|
||||||
|
<CardTitle>Assignment</CardTitle>
|
||||||
|
<CardDescription>Review your current assignment and request a move.</CardDescription>
|
||||||
|
</div>
|
||||||
|
<RequestTransferDialog
|
||||||
|
currentAssignments={currentAssignments}
|
||||||
|
currentUserId={fullUser.id}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{currentAssignments.length > 0 ? (
|
||||||
|
<div className="flex flex-wrap gap-2" aria-label="Current assignments">
|
||||||
|
{currentAssignments.map((assignment) => (
|
||||||
|
<Badge key={assignment.id} variant="outline">
|
||||||
|
{assignment.callsign
|
||||||
|
? `${assignment.name} · ${assignment.callsign}`
|
||||||
|
: assignment.name}
|
||||||
|
{assignment.isLeader ? " · Leader" : ""}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
You are not currently assigned to a unit. Ask leadership to add you before
|
||||||
|
requesting a transfer.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle>Password</CardTitle>
|
<CardTitle>Password</CardTitle>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue