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