1
0
Fork 0
polaris-task-force/src/app/(frontend)/logistics/game-vehicles/page.tsx

126 lines
5 KiB
TypeScript

import config from "@payload-config";
import { getPayload } from "payload";
import type { GameVehicle, Vehicle } from "@/payload-types";
import { TruckIcon } from "lucide-react";
import Link from "next/link";
import {
Item,
ItemContent,
ItemDescription,
ItemHeader,
ItemMedia,
ItemTitle,
} from "@/components/ui/item";
export const metadata = {
title: "Vehicles: Polaris Task Force",
};
export default async function GameVehiclesPage() {
const payload = await getPayload({ config });
const vehiclesRes = await payload.find({
collection: "game-vehicles",
limit: 500,
depth: 2,
});
const vehicles = vehiclesRes.docs as unknown as (GameVehicle & {
type: Vehicle;
})[];
const statusColors: Record<string, string> = {
idle: "bg-emerald-500/20 text-emerald-400",
assigned: "bg-blue-500/20 text-blue-400",
in_transit: "bg-amber-500/20 text-amber-400",
damaged: "bg-red-500/20 text-red-400",
destroyed: "bg-red-500/20 text-red-400",
};
return (
<div className="p-5 flex flex-col gap-6">
<div className="flex flex-col gap-1">
<div className="flex items-center gap-2">
<TruckIcon className="size-5 text-muted-foreground" />
<h1 className="text-lg font-semibold">Vehicles</h1>
</div>
<p className="text-sm text-muted-foreground">
{vehicles.length} vehicle{vehicles.length !== 1 ? "s" : ""} deployed.
</p>
</div>
{vehicles.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
{vehicles.map((vehicle) => {
const vehicleType = typeof vehicle.type === "object" ? vehicle.type : null;
const fuelPercent = vehicleType?.fuel?.fuelCapacity
? (vehicle.currentFuel / vehicleType.fuel.fuelCapacity) * 100
: 0;
return (
<Link key={vehicle.id} href={`/logistics/game-vehicles/${vehicle.id}`}>
<Item
variant="outline"
className="cursor-pointer group transition-all duration-200 hover:scale-[1.01] hover:[box-shadow:inset_0_2px_8px_rgba(255,255,255,0.33)]"
>
<ItemHeader>
<div className="flex items-center gap-2">
<ItemMedia variant="icon">
<TruckIcon />
</ItemMedia>
<ItemTitle className="flex flex-col">
<span>{vehicle.name}</span>
<span className="text-xs font-normal text-muted-foreground">
{vehicleType?.name ?? "Unknown type"}
</span>
</ItemTitle>
</div>
<span
className={`text-[10px] font-semibold uppercase tracking-wider px-1.5 py-0.5 rounded ${statusColors[vehicle.status] ?? "bg-muted text-muted-foreground"}`}
>
{vehicle.status === "in_transit"
? "In Transit"
: vehicle.status.charAt(0).toUpperCase() + vehicle.status.slice(1)}
</span>
</ItemHeader>
<ItemContent>
<div className="flex flex-col gap-2 w-full">
<div className="flex items-center gap-2">
<div className="flex-1 h-1.5 bg-border rounded-full overflow-hidden">
<div
className={`h-full rounded-full transition-all ${
fuelPercent > 20 ? "bg-green-500" : "bg-red-500"
}`}
style={{
width: `${Math.min(100, fuelPercent)}%`,
}}
/>
</div>
<span className="text-[10px] font-mono text-muted-foreground">
{vehicle.currentFuel?.toFixed(0)} /{" "}
{vehicleType?.fuel?.fuelCapacity ?? "?"} fuel
</span>
</div>
<div className="flex items-center justify-between text-xs text-muted-foreground">
<span>HP: {vehicle.currentHealth}</span>
{vehicleType?.fuel?.fuelType &&
typeof vehicleType.fuel.fuelType === "object" && (
<span>{vehicleType.fuel.fuelType.name}</span>
)}
</div>
</div>
</ItemContent>
<ItemDescription>{vehicleType?.name ?? "Unknown type"}</ItemDescription>
</Item>
</Link>
);
})}
</div>
) : (
<div className="flex flex-col items-center justify-center py-12 text-muted-foreground">
<p className="text-sm">No vehicles deployed.</p>
</div>
)}
</div>
);
}