My last created Shift Table 16.04.2024

PHOTO EMBED

Mon Apr 15 2024 22:46:59 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";

// Define types for users on and off shift
type UserOnShift = {
  shift_start: string | null;
  user: string; // Email from 'users_view'
};

type OfflineUser = {
  user: string; // Email from 'users_view'
};

const ShiftTable = () => {
  const [usersOnShift, setUsersOnShift] = useState<UserOnShift[]>([]);
  const [usersOffShift, setUsersOffShift] = useState<OfflineUser[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [showModal, setShowModal] = useState(false);
  const [selectedUser, setSelectedUser] = useState<UserOnShift | null>(null);
  const supabaseClient = useSupabaseClient();
  const router = useRouter();
  const excludedUuid = "2b78abeb-133d-4248-8469-21620903cbb3";

  useEffect(() => {
    const fetchUsers = async () => {
      setLoading(true);
      setError("");

      try {
        const { data: usersOnShiftData, error: onShiftError } =
          await supabaseClient
            .from("UserLastWorkedOn")
            .select("shift_start, user, users_view (email)")
            .not("user", "eq", excludedUuid)
            .not("shift_start", "is", null);

        const { data: usersOffShiftData, error: offShiftError } =
          await supabaseClient
            .from("UserLastWorkedOn")
            .select("user, users_view (email)")
            .not("user", "eq", excludedUuid)
            .is("shift_start", null);

        if (onShiftError || offShiftError) {
          setError(
            onShiftError?.message ||
              offShiftError?.message ||
              "Failed to fetch user data."
          );
          return;
        }

        const sortedOnShift = usersOnShiftData
          .map((user) => ({
            shift_start: user.shift_start,
            user: user.users_view?.email ?? user.user,
          }))
          .sort((a, b) => a.user.localeCompare(b.user));

        const sortedOffShift = usersOffShiftData
          .map((user) => ({
            user: user.users_view?.email ?? user.user,
          }))
          .sort((a, b) => a.user.localeCompare(b.user));

        setUsersOnShift(sortedOnShift);
        setUsersOffShift(sortedOffShift);
      } catch (err) {
        setError("Failed to fetch user data: " + err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, [supabaseClient]);

  const handleUserClick = (user: UserOnShift) => {
    setSelectedUser(user);
    setShowModal(true);
  };

  const closeModal = () => {
    setShowModal(false);
    setSelectedUser(null);
  };

  const navigateToUserHistory = () => {
    if (selectedUser) {
      router.push(`/user-history/${selectedUser.user}`); // Adjust the route as needed
      closeModal();
    }
  };

  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="mb-4 text-sm text-gray-400">
        {usersOnShift.length} user(s) currently on shift. Offline users:{" "}
        {usersOffShift.length}.
      </div>
      {loading ? (
        <Spinner />
      ) : error ? (
        <p className="text-red-500">{error}</p>
      ) : (
        <>
          <div className="mt-8 w-full px-4">
            {renderUsersGrid(
              "Users Currently On Shift",
              usersOnShift,
              true,
              handleUserClick
            )}
          </div>
          <div className="mt-8 w-full px-4">
            {renderUsersGrid(
              "Offline Users",
              usersOffShift,
              false,
              handleUserClick
            )}
          </div>
        </>
      )}
      {showModal && selectedUser && (
        <div className="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-black bg-opacity-50">
          <div className="rounded-lg bg-white p-4 shadow-lg">
            <h3 className="text-lg font-bold">User Actions</h3>
            <p>{`Show ${selectedUser.user}'s history?`}</p>
            <button
              className="rounded bg-blue-500 px-4 py-2 font-bold text-white hover:bg-blue-700"
              onClick={navigateToUserHistory}
            >
              View History
            </button>
            <button
              className="ml-2 rounded bg-gray-300 px-4 py-2 text-black hover:bg-gray-400"
              onClick={closeModal}
            >
              Cancel
            </button>
          </div>
        </div>
      )}
    </MinimalPage>
  );

  function renderUsersGrid(
    title: string,
    users: any[],
    showShiftStart: boolean,
    onClick: (user: UserOnShift) => void
  ) {
    return (
      <div className="overflow-hidden overflow-x-auto rounded-3xl border-transparent shadow-lg">
        <h2 className="my-4 px-6 text-lg font-semibold text-white">{title}</h2>
        <div className="grid grid-cols-4 gap-4">
          {users.map((user, index) => (
            <div
              key={index}
              className="cursor-pointer rounded-xl bg-gray-800 p-4 text-center"
              onClick={() => onClick(user)}
            >
              <p className="text-sm text-gray-400">{user.user}</p>
              {showShiftStart && user.shift_start ? (
                <p className="text-sm text-gray-400">
                  {dayjs(user.shift_start).format("DD-MM-YYYY | HH:mm")}
                </p>
              ) : null}
            </div>
          ))}
        </div>
      </div>
    );
  }
};

export default ShiftTable;
content_copyCOPY