import { useEffect, useState } from "react";
import { useSupabaseClient } from "@supabase/auth-helpers-react";
import { HeadingLink, MinimalPage, PageHeading, Spinner } from "ui";
import type { Database } from "../../../types";
import dayjs from "dayjs";
const ShiftTable = () => {
const [usersOnShift, setUsersOnShift] = useState<
Array<{
user: string;
shift_start: string | undefined;
image: string | undefined;
fullName: string;
}>
>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const supabaseClient = useSupabaseClient<Database>();
useEffect(() => {
const fetchUsersOnShift = async () => {
setLoading(true);
try {
const { data: usersData, error: usersError } = await supabaseClient
.from("UserLastWorkedOn")
.select("shift_start, user, users_view (email, raw_user_meta_data)")
.not("shift_start", "is", null);
if (usersError) {
setError(usersError.message ?? "Failed to fetch user shift data");
console.error(usersError);
}
const mappedUsers = usersData?.map((user) => {
const userMetaData = Array.isArray(user.users_view)
? user.users_view[0].raw_user_meta_data
: user.users_view?.raw_user_meta_data;
const fullName = userMetaData
? userMetaData["full_name"] ?? "No Name Provided"
: "No Name Provided";
const image = userMetaData ? userMetaData["avatar_url"] : undefined;
return {
shift_start: user.shift_start
? dayjs(user.shift_start).format("DD-MM-YYYY | HH:mm")
: undefined,
user: fullName,
image: image,
fullName: fullName,
};
});
setUsersOnShift(mappedUsers ?? []);
} catch (err) {
setError("Failed to fetch user shift data");
console.error(err);
} finally {
setLoading(false);
}
};
fetchUsersOnShift();
}, [supabaseClient]);
const defaultAvatar = "/path_to_default_avatar.jpg"; // Replace with actual path to your default avatar image
return (
<MinimalPage
pageTitle="Shift Table | Email Interface"
pageDescription="Spot Ship Email Interface | Shift Table"
commandPrompt
>
<div className="w-full">
<HeadingLink icon="back" text="Home" href="/secure/home" />
</div>
<PageHeading text="Spot Ship Shift Table" />
<div className="flex w-full flex-col">
{loading ? (
<Spinner />
) : error ? (
<p className="text-red-500">Error: {error}</p>
) : usersOnShift.length ? (
<table className="mt-4 min-w-full">
<thead>
<tr>
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
User Name
</th>
<th className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500">
Shift Started
</th>
</tr>
</thead>
<tbody className="divide-white-200 divide-x ">
{usersOnShift.map((user, index) => (
<tr key={index}>
<td className="text-white-500 flex items-center px-6 py-4 text-sm">
<img
src={user.image || defaultAvatar}
onError={(e) => (e.currentTarget.src = defaultAvatar)}
alt={user.fullName}
style={{
height: 30,
width: 30,
borderRadius: "50%",
marginRight: "0.5rem",
}}
/>
{user.user}
</td>
<td className="text-white-500 px-6 py-4 text-sm">
{user.shift_start ?? "No Data"}
</td>
</tr>
))}
</tbody>
</table>
) : (
<p>No users are currently on shift</p>
)}
</div>
</MinimalPage>
);
};
export default ShiftTable;
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter