userShiftStateButton.tsx

PHOTO EMBED

Fri May 24 2024 09:19:33 GMT+0000 (Coordinated Universal Time)

Saved by @rafal_rydz

import React, { useState } from "react";
import { useSupabaseClient } from "@supabase/auth-helpers-react";
import {
  ButtonContent,
  CaptionText,
  Conditional,
  dateToTimeString,
  PrimaryButton,
  SecondaryButton,
} from "ui";
import { useUserShiftStart } from "../../hooks";
import { useQueryClient } from "react-query";
import { CirclePlay, CircleStop } from "lucide-react";

interface ShiftStatus {
  isOnShift: boolean;
  onShiftSince: string | null | undefined;
  isOnBreak: boolean;
  onBreakSince: string | null | undefined;
}

export const UserShiftStateButton = () => {
  const {
    data: shiftStatus,
    isError,
    error: loadShiftStatusError,
  } = useUserShiftStart();
  const [error, setError] = useState<string>();
  const supabaseClient = useSupabaseClient();
  const queryClient = useQueryClient();

  const logUserAction = async (
    action: string,
    details: object | null,
    userId: string,
  ) => {
    const { error: insertError } = await supabaseClient
      .from("UserHistory")
      .insert([{ user: userId, action, detail: details }]);
    if (insertError) {
      setError("Failed to log user action");
    }
  };

  const toggleShiftStatus = async () => {
    const { data: sessionData } = await supabaseClient.auth.getSession();
    if (sessionData?.session) {
      const userId = sessionData.session.user.id;
      const now = new Date().toISOString();
      let newStatus: string;
      let details: { duration?: string; start?: string; end?: string } | null =
        null;

      if (shiftStatus?.isOnShift && shiftStatus.onShiftSince) {
        const shiftStart = new Date(shiftStatus.onShiftSince);
        const shiftEnd = new Date();
        const shiftDuration = shiftEnd.getTime() - shiftStart.getTime();
        details = {
          duration: dateToTimeString(shiftDuration),
          start: shiftStart.toISOString(),
          end: shiftEnd.toISOString(),
        };
        newStatus = "SHIFT END";

        if (shiftStatus.isOnBreak && shiftStatus.onBreakSince) {
          const breakStart = new Date(shiftStatus.onBreakSince);
          const breakEnd = new Date();
          const breakDuration = breakEnd.getTime() - breakStart.getTime();
          const breakDetails = {
            duration: dateToTimeString(breakDuration),
            start: breakStart.toISOString(),
            end: breakEnd.toISOString(),
          };
          await logUserAction("BREAK END", breakDetails, userId);
        }
      } else {
        newStatus = "SHIFT START";
      }

      const { error: updateError } = await supabaseClient
        .from("UserLastWorkedOn")
        .update({
          shift_start: shiftStatus?.isOnShift ? null : now,
          break_start: null,
        })
        .eq("user", userId);

      if (updateError) {
        setError("Failed to toggle shift status");
        return;
      }

      await logUserAction(newStatus, details, userId);
      queryClient.invalidateQueries({ queryKey: ["userShiftStatus"] });
    }
  };

  const toggleBreakStatus = async () => {
    const { data: sessionData } = await supabaseClient.auth.getSession();
    if (sessionData?.session) {
      const userId = sessionData.session.user.id;
      const now = new Date().toISOString();
      let newStatus: string;
      let details: { duration?: string; start?: string; end?: string } | null =
        null;

      if (shiftStatus?.isOnBreak && shiftStatus.onBreakSince) {
        const breakStart = new Date(shiftStatus.onBreakSince);
        const breakEnd = new Date();
        const breakDuration = breakEnd.getTime() - breakStart.getTime();
        details = {
          duration: dateToTimeString(breakDuration),
          start: breakStart.toISOString(),
          end: breakEnd.toISOString(),
        };
        newStatus = "BREAK END";
      } else {
        newStatus = "BREAK START";
      }

      const { error: updateError } = await supabaseClient
        .from("UserLastWorkedOn")
        .update({
          break_start: shiftStatus?.isOnBreak ? null : now,
        })
        .eq("user", userId);

      if (updateError) {
        setError("Failed to toggle break status");
        return;
      }

      await logUserAction(newStatus, details, userId);
      queryClient.invalidateQueries({ queryKey: ["userShiftStatus"] });
    }
  };

  return (
    <Conditional
      condition={!isError}
      elseChildren={
        <CaptionText>
          Error: {isError ? `${loadShiftStatusError}` : ""}
          {error}
        </CaptionText>
      }
    >
      <CaptionText className="mt-1">
        You are {shiftStatus?.isOnShift ? "On" : "Off"} shift
      </CaptionText>
      <PrimaryButton
        onClick={toggleShiftStatus}
        className="min-w-32 rounded-none rounded-bl-md rounded-tl-md"
      >
        <ButtonContent className="gap-2">
          <div>{shiftStatus?.isOnShift ? "End" : "Start"} Shift</div>
          <Conditional
            condition={!shiftStatus?.isOnShift}
            elseChildren={<CircleStop size={16} />}
          >
            <CirclePlay size={16} />
          </Conditional>
        </ButtonContent>
      </PrimaryButton>
      <SecondaryButton
        onClick={toggleBreakStatus}
        disabled={!shiftStatus?.isOnShift}
        className="min-w-32 rounded-none rounded-br-md rounded-tr-md"
      >
        <ButtonContent className="gap-2">
          <div>{shiftStatus?.isOnBreak ? "End" : "Start"} Break</div>
          <Conditional
            condition={!shiftStatus?.isOnBreak}
            elseChildren={<CircleStop size={16} />}
          >
            <CirclePlay size={16} />
          </Conditional>
        </ButtonContent>
      </SecondaryButton>
    </Conditional>
  );
};
content_copyCOPY