Shift Table 30.04.2024 working perfecly, needs to change components to <Conditional> and <Loading>
Thu Apr 18 2024 08:08:00 GMT+0000 (Coordinated Universal Time)
Saved by @rafal_rydz
import React, { useEffect, useState } from "react"; import { useSupabaseClient } from "@supabase/auth-helpers-react"; import { HeadingLink, MinimalPage, PageHeading, Spinner } from "ui"; import dayjs from "dayjs"; import { useRouter } from "next/router"; import { getFilename } from "@/functions"; import Link from "next/link"; import { CommandInterface } from "@/components"; 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 [usersOnShift, setUsersOnShift] = useState<User[]>([]); const [usersOffShift, setUsersOffShift] = useState<User[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); const supabaseClient = useSupabaseClient(); const router = useRouter(); const nonUser = ["2b78abeb-133d-4248-8469-21620903cbb3"]; useEffect(() => { const fetchUsers = async () => { setLoading(true); setError(""); try { const { data: usersData, error: fetchError } = await supabaseClient .from("UserLastWorkedOn") .select( "shift_start, break_start, user, users_view ( raw_user_meta_data), email, group" ) .not("user", "eq", nonUser); if (fetchError) { setError(fetchError.message || "Failed to fetch user data."); return; } const mappedUsers = await Promise.all( usersData.map(async (user) => { const meta_data = user.users_view as any; const metaData = meta_data?.raw_user_meta_data; const image = metaData.avatar_url || "/avatar_url.png"; const fullName = metaData.full_name || "No Name Provided"; const filename = await getFilename(supabaseClient, user.email); return { shift_start: user.shift_start ? dayjs(user.shift_start).format("DD-MM-YYYY | HH:mm") : null, break_start: user.break_start ? dayjs(user.break_start).format("DD-MM-YYYY | HH:mm") : null, user: user.user, image: image, fullName: fullName, group: user.group || "No Group", email: filename ?? "", }; }) ); setUsersOnShift( mappedUsers.filter((user) => user.shift_start !== null) ); setUsersOffShift( mappedUsers.filter((user) => user.shift_start === null) ); } catch (err: unknown) { if (err instanceof Error) { setError("Failed to fetch user data: " + err.message); } else { setError("Failed to fetch user data: An unknown error occurred."); } } finally { setLoading(false); } }; fetchUsers(); }, [supabaseClient]); 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(usersOnShift); const usersOffShiftCounts = countUsersInGroups(usersOffShift); 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"></div> <div className="w-full"> <HeadingLink icon="back" text="Home" href="/secure/home" /> <PageHeading text="Spot Ship Shift Table" /> <div className="mb-4 text-sm text-gray-400"> {usersOnShift.length} user(s) currently on shift ( {Object.entries(usersOnShiftCounts) .map(([group, count]) => `${group}: ${count}`) .join(", ")} ). Offline users: {usersOffShift.length} ( {Object.entries(usersOffShiftCounts) .map(([group, count]) => `${group}: ${count}`) .join(", ")} ). </div> {loading ? ( <Spinner /> ) : error ? ( <p className="text-red-500">{error}</p> ) : ( <> {renderUsersGrid( "Data Analysts", usersOnShift.filter((user) => user.group === "Data Analyst"), true, false )} {renderUsersGrid( "Senior Data Analysts", usersOnShift.filter( (user) => user.group === "Senior Data Analyst" ), true, false )} {renderUsersGrid( "Data Team Managers", usersOnShift.filter((user) => user.group === "Data Team Manager"), true, false )} {renderUsersGrid( "Europe Team", usersOnShift.filter((user) => user.group === "Europe Team"), true, false )} {renderUsersGrid("Offline Users", usersOffShift, false, true)} </> )} </div> </MinimalPage> ); function renderUsersGrid( 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 text-lg font-semibold">{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-800 p-4 ${ dim ? "bg-opacity-50" : "" }`} > <div className="relative h-12 w-12"> <img src={user.image || "email-interface/public/avatar_url.png"} alt={user.fullName} className="h-full w-full rounded-full object-cover" /> {user.shift_start && !user.break_start && ( <span className="absolute bottom-0 right-0 block h-5 w-5 rounded-full border-2 border-black bg-green-400" /> )} {user.break_start && ( <span className="absolute bottom-0 right-0 block h-5 w-5 rounded-full border-2 border-black bg-yellow-400" /> )} {!user.shift_start && ( <span className="absolute bottom-0 right-0 block h-5 w-5 rounded-full border-2 border-black bg-gray-400" /> )} </div> {user.email && ( <Link href={`/secure/review/email?filename=${user.email}`} passHref rel="noopener noreferrer" target="_blank" > <button className="mt-2 rounded bg-blue-500 px-2 py-1 text-xs font-bold text-white hover:bg-blue-700"> Working on Email </button> </Link> )} <p className="mt-2 text-sm text-white">{user.fullName}</p> {showShiftStart && user.shift_start && ( <p className="text-xs text-gray-400">{user.shift_start}</p> )} </div> ))} </div> </div> ); } }; export default ShiftTable;
Comments