CZQM-Ops-Demo/components/controller-profile.tsx
2024-11-24 17:27:55 -06:00

139 lines
4.7 KiB
TypeScript

import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Skeleton } from "@/components/ui/skeleton";
import { Card } from "@/components/ui/card";
import { formatDistanceToNow, format } from "date-fns";
import { Clock, Calendar, Radio } from "lucide-react";
interface ControllerProfileProps {
sessions: any[];
loading: boolean;
}
export function ControllerProfile({ sessions, loading }: ControllerProfileProps) {
if (loading) {
return <LoadingSkeleton />;
}
const totalTime = sessions.reduce((acc, session) => {
const duration = new Date(session.last_seen).getTime() - new Date(session.logon_time).getTime();
return acc + duration;
}, 0);
const totalHours = Math.floor(totalTime / (1000 * 60 * 60));
const totalMinutes = Math.floor((totalTime % (1000 * 60 * 60)) / (1000 * 60));
// Get unique positions
const positions = [...new Set(sessions.map(s => s.facility_type))];
return (
<div className="space-y-6 p-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card className="p-6">
<div className="flex items-center gap-3 mb-4">
<Clock className="h-5 w-5 text-blue-500" />
<h3 className="text-lg font-semibold">Total Time</h3>
</div>
<p className="text-3xl font-bold">
{totalHours}h {totalMinutes}m
</p>
</Card>
<Card className="p-6">
<div className="flex items-center gap-3 mb-4">
<Calendar className="h-5 w-5 text-blue-500" />
<h3 className="text-lg font-semibold">Total Sessions</h3>
</div>
<p className="text-3xl font-bold">{sessions.length}</p>
</Card>
<Card className="p-6">
<div className="flex items-center gap-3 mb-4">
<Radio className="h-5 w-5 text-blue-500" />
<h3 className="text-lg font-semibold">Positions</h3>
</div>
<div className="flex flex-wrap gap-2">
{positions.map(position => (
<span
key={position}
className="inline-flex items-center rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-200"
>
{position}
</span>
))}
</div>
</Card>
</div>
<div className="mt-8">
<h3 className="text-lg font-semibold mb-4">Session History</h3>
<Table>
<TableHeader>
<TableRow>
<TableHead>Date</TableHead>
<TableHead>Callsign</TableHead>
<TableHead>Position</TableHead>
<TableHead>Airport</TableHead>
<TableHead>Frequency</TableHead>
<TableHead>Duration</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sessions.map((session) => (
<TableRow key={`${session.callsign}-${session.last_seen}`}>
<TableCell>
{format(new Date(session.logon_time), "MMM d, yyyy")}
</TableCell>
<TableCell>{session.callsign}</TableCell>
<TableCell>{session.facility_type}</TableCell>
<TableCell>{session.airport}</TableCell>
<TableCell>{session.frequency}</TableCell>
<TableCell>
{formatSessionDuration(session.logon_time, session.last_seen)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
}
function formatSessionDuration(start: string, end: string) {
const duration = new Date(end).getTime() - new Date(start).getTime();
const hours = Math.floor(duration / (1000 * 60 * 60));
const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60));
return `${hours}h ${minutes}m`;
}
function LoadingSkeleton() {
return (
<div className="space-y-6 p-6">
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Skeleton className="h-[140px] rounded-lg" />
<Skeleton className="h-[140px] rounded-lg" />
<Skeleton className="h-[140px] rounded-lg" />
</div>
<div className="space-y-3 mt-8">
<Skeleton className="h-8 w-[200px]" />
{Array.from({ length: 5 }).map((_, i) => (
<div key={i} className="flex gap-4">
<Skeleton className="h-4 w-[120px]" />
<Skeleton className="h-4 w-[120px]" />
<Skeleton className="h-4 w-[100px]" />
<Skeleton className="h-4 w-[80px]" />
<Skeleton className="h-4 w-[100px]" />
<Skeleton className="h-4 w-[100px]" />
</div>
))}
</div>
</div>
);
}