shiftTable.tsx
Fri May 24 2024 09:21:12 GMT+0000 (Coordinated Universal Time)
Saved by @rafal_rydz
import React from "react"; import { BodyText, Conditional, H2, HeadingLink, IntroText, Loading, MinimalPage, PageHeading, PrimaryButton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "ui"; import Link from "next/link"; import { CommandInterface } from "@/components"; import { useShiftTable } from "@/hooks"; import { timeSince } from "@/functions"; import dayjs from "dayjs"; type User = { shift_start: string | null; break_start: string | null; user: any; image: string; fullName: string; group: string | null; users_view?: { email?: string; raw_user_meta_data?: { avatar_url?: string; full_name?: string; }; }; email: string; }; const ShiftTable = () => { const { data, isLoading, error, isError } = useShiftTable(); const countUsersInGroups = (users: User[]): Record<string, number> => { return users.reduce<Record<string, number>>((acc, user) => { const groupName = user.group || "No Group"; acc[groupName] = (acc[groupName] || 0) + 1; return acc; }, {}); }; const usersOnShiftCounts = countUsersInGroups(data?.onShift ?? []); const usersOffShiftCounts = countUsersInGroups(data?.offShift ?? []); const sortUsers = (users: User[]) => { return users .slice() .sort((a, b) => a.fullName.localeCompare(b.fullName)) .sort((a, b) => { const shiftA = a.shift_start ? new Date(a.shift_start).getTime() : 0; const shiftB = b.shift_start ? new Date(b.shift_start).getTime() : 0; return shiftA - shiftB; }); }; return ( <MinimalPage pageTitle="Shift Table | Email Interface" pageDescription="Spot Ship Email Interface | Shift Table" commandPrompt > <CommandInterface /> <div className="hidden"> <PageHeading text="Homepage" /> </div> <div className="w-full pl-1 pt-1"> <HeadingLink icon="back" text="Home" href="/secure/home" /> <PageHeading text="Spot Ship Shift Table" /> <Conditional condition={!isLoading} elseChildren={ <Loading style="grid" size="large" colour="#AAAAAA50" /> } > <Conditional condition={!isError} elseChildren={<p className="text-red-500">{`${error?.message}`}</p>} > <div className="mb-4 text-center text-sm text-gray-400"> Users currently on shift:{" "} {Object.entries(usersOnShiftCounts) .map(([group, count]) => `${group}: ${count}`) .join(", ")} </div> <RenderUsersGrid title="Data Analysts" users={sortUsers( data?.onShift?.filter( (user) => user.group === "Data Analyst", ) ?? [], )} /> <RenderUsersGrid title="Senior Data Analysts" users={sortUsers( data?.onShift?.filter( (user) => user.group === "Senior Data Analyst", ) ?? [], )} /> <RenderUsersGrid title="Data Team Managers" users={sortUsers( data?.onShift?.filter( (user) => user.group === "Data Team Manager", ) ?? [], )} /> <RenderUsersGrid title="Europe Team" users={sortUsers( data?.onShift?.filter((user) => user.group === "Europe Team") ?? [], )} /> <div className="mb-4 text-center text-sm text-gray-400"> Offline users:{" "} {Object.entries(usersOffShiftCounts) .map(([group, count]) => `${group}: ${count}`) .join(", ")} </div> <RenderUsersGrid title="Offline Data Analysts" users={sortUsers( data?.offShift?.filter( (user) => user.group === "Data Analyst", ) ?? [], )} showShiftStart={false} dim={true} /> <RenderUsersGrid title="Offline Senior Data Analysts" users={sortUsers( data?.offShift?.filter( (user) => user.group === "Senior Data Analyst", ) ?? [], )} showShiftStart={false} dim={true} /> <RenderUsersGrid title="Offline Data Team Managers" users={sortUsers( data?.offShift?.filter( (user) => user.group === "Data Team Manager", ) ?? [], )} showShiftStart={false} dim={true} /> <RenderUsersGrid title="Offline Europe Team" users={sortUsers( data?.offShift?.filter( (user) => user.group === "Europe Team", ) ?? [], )} showShiftStart={false} dim={true} /> </Conditional> </Conditional> </div> </MinimalPage> ); }; const RenderUsersGrid = ({ title, users = [], showShiftStart = true, dim = false, }: { title: string; users?: User[]; showShiftStart?: boolean; dim?: boolean; }) => { return ( <div className={`overflow-hidden overflow-x-auto rounded-lg shadow ${ dim ? "opacity-50" : "" }`} > <H2 className="text-center ">{title}</H2> <div className="grid grid-cols-4 gap-4 p-4"> {users.map((user, index) => ( <div key={index} className={`relative flex flex-col items-center justify-center rounded-lg bg-gray-200 p-4 dark:bg-gray-800 ${ dim ? "bg-opacity-50" : "" }`} > <div className="relative h-12 w-12"> <img src={user.image || "/avatar_url.png"} alt={user.fullName} className="h-full w-full rounded-full object-cover" /> <span className={`absolute bottom-0 right-0 block h-5 w-5 rounded-full border border-white/20 dark:border-black ${ user.shift_start === null ? "bg-gray-400" : user.break_start === null ? "bg-green-400" : "bg-yellow-400" }`} /> </div> <Conditional condition={user.email !== ""}> <div className="mt-2"> <Link href={`/secure/review/email?filename=${user.email}`} passHref rel="noopener noreferrer" target="_blank" > <PrimaryButton size="small">Working on Email</PrimaryButton> </Link> </div> </Conditional> <IntroText className="mt-2">{user.fullName}</IntroText> <Conditional condition={showShiftStart && !!user.shift_start}> <TooltipProvider> <Tooltip> <TooltipTrigger> <BodyText> {user.shift_start ? `On shift for: ${timeSince(new Date(user.shift_start))}` : ""} </BodyText> </TooltipTrigger> <TooltipContent> <p> {dayjs(user.shift_start).format("DD-MM-YYYY | HH:mm")} </p> </TooltipContent> </Tooltip> </TooltipProvider> </Conditional> <Conditional condition={showShiftStart && !!user.break_start}> <TooltipProvider> <Tooltip> <TooltipTrigger> <BodyText> {user.break_start ? `On break for: ${timeSince( new Date(user.break_start), )}` : ""} </BodyText> </TooltipTrigger> <TooltipContent> <p> {dayjs(user.break_start).format("DD-MM-YYYY | HH:mm")} </p> </TooltipContent> </Tooltip> </TooltipProvider> </Conditional> </div> ))} </div> </div> ); }; export default ShiftTable;
Comments