diff --git a/src/app/(frontend)/intelligence/campaigns/page.tsx b/src/app/(frontend)/intelligence/campaigns/page.tsx index 73800d6..21133e1 100644 --- a/src/app/(frontend)/intelligence/campaigns/page.tsx +++ b/src/app/(frontend)/intelligence/campaigns/page.tsx @@ -2,7 +2,7 @@ import config from "@payload-config"; import { getPayload } from "payload"; import { headers as nextHeaders } from "next/headers"; import { ShieldIcon } from "lucide-react"; -import { CampaignCard } from "@/components/frontend/intelligence/CampaignCard"; +import { CampaignsList } from "@/components/frontend/intelligence/CampaignsList"; import { CreateCampaignDialog } from "@/components/frontend/intelligence/CreateCampaignDialog"; import type { Media } from "@/payload-types"; import { Button } from "@/components/ui/button"; @@ -100,13 +100,6 @@ export default async function CampaignsPage() { }), ); - const officialCampaigns = campaignsWithStats.filter( - (campaign) => campaign.campaignMode === "official", - ); - const communityCampaigns = campaignsWithStats.filter( - (campaign) => campaign.campaignMode !== "official", - ); - return (
@@ -125,51 +118,7 @@ export default async function CampaignsPage() {
- {campaignsWithStats.length > 0 ? ( - <> - {officialCampaigns.length > 0 && ( -
-
-

- Official Campaigns -

-

- Command-sanctioned operations at the heart of the unit's story. -

-
-
- {officialCampaigns.map((campaign) => ( - - ))} -
-
- )} - {officialCampaigns.length > 0 && communityCampaigns.length > 0 && ( -
- )} - {communityCampaigns.length > 0 && ( -
-
-

- Community Campaigns -

-

- Player-made side operations and stories, open to everyone. -

-
-
- {communityCampaigns.map((campaign) => ( - - ))} -
-
- )} - - ) : ( -
-

No campaigns found.

-
- )} + ); } diff --git a/src/components/frontend/intelligence/CampaignsList.tsx b/src/components/frontend/intelligence/CampaignsList.tsx new file mode 100644 index 0000000..bd97a68 --- /dev/null +++ b/src/components/frontend/intelligence/CampaignsList.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { useState } from "react"; +import { CampaignCard } from "@/components/frontend/intelligence/CampaignCard"; +import { Switch } from "@/components/ui/switch"; + +export interface CampaignListEntry { + readonly id: number; + readonly name: string; + readonly summary: string; + readonly status: "concept" | "inProgress" | "completed"; + readonly campaignMode: "official" | "custom"; + readonly startDate?: string | null; + readonly endDate?: string | null; + readonly coverImageUrl: string | null; + readonly missionCount: number; + readonly completedMissions: number; + readonly avgPlayers: number; + readonly avgDurationMinutes: number; + readonly ownerName: string; +} + +interface CampaignsListProps { + readonly campaigns: CampaignListEntry[]; +} + +export function CampaignsList({ campaigns }: CampaignsListProps) { + const [hideCompleted, setHideCompleted] = useState(false); + + const visible = hideCompleted + ? campaigns.filter((campaign) => campaign.status !== "completed") + : campaigns; + const officialCampaigns = visible.filter( + (campaign) => campaign.campaignMode === "official", + ); + const communityCampaigns = visible.filter( + (campaign) => campaign.campaignMode !== "official", + ); + + return ( + <> +
+ + +
+ {visible.length > 0 ? ( + <> + {officialCampaigns.length > 0 && ( +
+
+

+ Official Campaigns +

+

+ Command-sanctioned operations at the heart of the unit's story. +

+
+
+ {officialCampaigns.map((campaign) => ( + + ))} +
+
+ )} + {officialCampaigns.length > 0 && communityCampaigns.length > 0 && ( +
+ )} + {communityCampaigns.length > 0 && ( +
+
+

+ Community Campaigns +

+

+ Player-made side operations and stories, open to everyone. +

+
+
+ {communityCampaigns.map((campaign) => ( + + ))} +
+
+ )} + + ) : campaigns.length > 0 ? ( +
+

No campaigns match the current filter.

+ +
+ ) : ( +
+

No campaigns found.

+
+ )} + + ); +}