import { useState, useEffect, useRef, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { useNavigate, useLocation } from 'react-router-dom';
import moment from 'moment';
import { Form, Tooltip, Collapse, Space, Modal, Table } from 'antd';
import {
ArrowRightOutlined,
PlusCircleOutlined,
DeleteFilled,
EditFilled,
InfoCircleOutlined,
ReloadOutlined,
} from '@ant-design/icons';
import { InputField } from '../../Components/Forms/InputField.jsx';
import Buttons from '../../Components/Forms/Buttons.jsx';
import { Messages } from '../../Components/Notifications/Messages';
import { TimePickers } from '../../Components/Forms/TimePicker.jsx';
import FormHeader from '../PageComponents/FormHeader.jsx';
import { changeBreadCrumb } from '../../Features/AppPage/CenterPage.js';
import { getSession, validateSafeInput } from '../../Services/Others';
import { postshift, putshift } from '../../Features/ShiftMaster/ShiftMaster.js';
import './ShiftMaster.scss';
import { FaPlus } from 'react-icons/fa6';
import '../../Styles/OverAllStyle/OverAllStyle.scss';
const subDirectory = import.meta.env.BASE_URL;
const ShiftForm = ({ formType }) => {
const formRef = useRef(null);
const dispatch = useDispatch();
const navigate = useNavigate();
const location = useLocation();
const state = location?.state;
const editstate = state?.editstate;
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const AppId = getSession('AppId');
const UserId = getSession('UserId');
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [fromTime, setFromTime] = useState();
const [toTime, setToTime] = useState();
const [BrakeFromTime, setBrakeFromTime] = useState();
const [BrakeToTime, setBrakeToTime] = useState();
const [Tabledata, setTabledata] = useState([]);
const [searchedText, setSearchedText] = useState('');
const [sortedInfo, setSortedInfo] = useState({});
const [editDataval, setEditDataval] = useState(false);
const [page, setpage] = useState(1);
const [editIndex, setEditIndex] = useState();
const [BrakeId, setBrakeId] = useState();
const items = [
{
name: 'Home',
link: `${subDirectory}app-page/home`,
},
{
name: 'Shift',
link: `${subDirectory}setting/shift-master`,
},
{
name: editstate ? 'Edit' : 'New',
link: null,
// link: editstate
// ? `${subDirectory}setting/shift-master/update`
// : `${subDirectory}setting/shift-master/new`,
},
];
useEffect(() => {
try {
dispatch(changeBreadCrumb({ items: items }));
if (formType === 'edit') {
if (editstate) {
setFromTime(editstate?.StartTime);
setToTime(editstate?.EndTime);
setBrakeFromTime(editstate?.BreakStartTime);
setBrakeToTime(editstate?.BreakEndTime);
setTabledata(editstate?.BreakDtl);
formRef.current?.setFieldsValue(editstate);
} else {
navigate(`${subDirectory}setting/shift-master/`);
}
}
} catch (err) {
console.log(err, 'err');
}
}, []);
const onFinish = async (values) => {
// Validate all break times are within shift time range
const shiftStart = moment(fromTime, 'HH:mm:ss');
const shiftEnd = moment(toTime, 'HH:mm:ss');
for (const breakItem of Tabledata) {
const breakStart = moment(breakItem.BreakStartTime, 'HH:mm:ss');
const breakEnd = moment(breakItem.BreakEndTime, 'HH:mm:ss');
const isValidBreak = shiftEnd.isBefore(shiftStart)
? (breakStart.isAfter(shiftStart) || breakStart.isBefore(shiftEnd)) &&
(breakEnd.isAfter(shiftStart) || breakEnd.isBefore(shiftEnd))
: breakStart.isBetween(shiftStart, shiftEnd, null, '[]') &&
breakEnd.isBetween(shiftStart, shiftEnd, null, '[]');
if (!isValidBreak) {
setMessageType('error');
setMessageData(
`Break "${breakItem.BreakName}" is not within shift time range`
);
return;
}
}
let postData = {
AppId: getSession('AppId'),
BranchId: getSession('BranchId'),
CompId: getSession('CompId'),
ShiftName: values.ShiftName,
StartTime: fromTime,
EndTime: toTime,
GracePeriod: values.GracePeriod,
BreakDtl: Tabledata.map((item) => ({
BreakName: item.BreakName,
BreakStartTime: item.BreakStartTime,
BreakEndTime: item.BreakEndTime,
BreakId: item.BreakId ? item.BreakId : '',
})),
CreatedBy: getSession('UserId'),
};
console.log(postData, 'postDatapostDatapostDatapostDatapostData');
let response = {};
if (formType === 'add') {
response = await dispatch(postshift(postData)).unwrap();
} else if (formType === 'edit') {
if (editstate) {
postData['UpdatedBy'] = getSession('UserId');
postData['ShiftId'] = editstate?.ShiftId;
}
response = await dispatch(putshift(postData)).unwrap();
}
if (response?.data?.statusCode == 1) {
navigate(`${subDirectory}setting/shift-master/`, {
state: {
Notiffy: {
messageType: 'success',
messageData: response?.data?.response,
},
},
});
} else {
setMessageType('error');
setMessageData(response?.data?.response);
}
};
const validateTime = (rule, value, callback) => {
// if either value is not set yet, bail out (required rule will show message)
if (!fromTime || !toTime) {
return callback();
}
// parse safely (allow formats like "HH:mm" or "HH:mm:ss")
const fromParts = (fromTime || '')
.split(':')
.map((s) => parseInt(s, 10) || 0);
const toParts = (toTime || '').split(':').map((s) => parseInt(s, 10) || 0);
const [fromHour = 0, fromMinute = 0] = fromParts;
const [toHour = 0, toMinute = 0] = toParts;
const fromTotalMinutes = fromHour * 60 + fromMinute;
const toTotalMinutes = toHour * 60 + toMinute;
const minutesInDay = 24 * 60;
let timeDifference = toTotalMinutes - fromTotalMinutes;
if (timeDifference < 0) {
timeDifference = minutesInDay - fromTotalMinutes + toTotalMinutes;
}
const maxAllowedInterval = 12 * 60;
if (timeDifference <= maxAllowedInterval) {
return callback();
} else {
return callback('Shift should not exceed 12 hours');
}
};
const validateBreakTime1 = (rule, value, callback) => {
if (!value) return callback();
const brakeFromTime = moment(BrakeFromTime, 'HH:mm');
const startTime = moment(fromTime, 'HH:mm');
const endTime = moment(toTime, 'HH:mm');
if (endTime.isBefore(startTime)) {
// Handle shifts that span across midnight
if (brakeFromTime.isAfter(startTime) || brakeFromTime.isBefore(endTime)) {
callback(); // Valid time interval
} else {
callback(
'Break Start Time should be between Shift Start Time and Shift End Time'
);
}
} else {
if (
brakeFromTime.isBetween(startTime, endTime, null, '[]') ||
brakeFromTime.isSame(startTime) ||
brakeFromTime.isSame(endTime)
) {
callback(); // Valid time interval
} else {
callback(
'Break Start Time should be between Shift Start Time and Shift End Time'
);
}
}
};
const validateBreakTime2 = (rule, value, callback) => {
if (!value) return callback();
const brakeToTime = moment(BrakeToTime, 'HH:mm');
const brakeFromTime = moment(BrakeFromTime, 'HH:mm');
const startTime = moment(fromTime, 'HH:mm');
const endTime = moment(toTime, 'HH:mm');
if (endTime.isBefore(startTime)) {
// Handle shifts that span across midnight
if (brakeToTime.isAfter(startTime) || brakeToTime.isBefore(endTime)) {
// Check if BrakeToTime is always greater than BrakeFromTime
if (brakeToTime.isAfter(brakeFromTime)) {
callback(); // Valid time interval
} else {
callback('Break End Time should be greater than Break Start Time');
}
} else {
callback(
'Break End Time should be between Shift Start Time and Shift End Time'
);
}
} else {
if (
brakeToTime.isBetween(startTime, endTime, null, '[]') ||
brakeToTime.isSame(startTime) ||
brakeToTime.isSame(endTime)
) {
// Check if BrakeToTime is always greater than BrakeFromTime
if (brakeToTime.isAfter(brakeFromTime)) {
callback(); // Valid time interval
} else {
callback('Break End Time should be greater than Break Start Time');
}
} else {
callback(
'Break End Time should be between Shift Start Time and Shift End Time'
);
}
}
};
const onFromTimeChange = (time, timeString) => {
if (timeString) {
const fromTime = moment(timeString, ['h:mm a']).format('HH:mm:ss');
setToTime(null);
setFromTime(fromTime);
} else {
setFromTime(null);
}
};
const onToTimeChange = (time, timeString) => {
if (timeString) {
const toTime = moment(timeString, ['h:mm a']).format('HH:mm:ss');
setToTime(toTime);
} else {
setToTime(null);
}
};
const onBrakeFromTimeChange = (time, timeString) => {
if (timeString) {
const FromBrakeTime = moment(timeString, ['h:mm a']).format('HH:mm:ss');
setBrakeFromTime(FromBrakeTime);
setBrakeToTime(null);
} else {
setBrakeFromTime(null);
}
};
const onBrakeToTimeChange = (time, timeString) => {
if (timeString) {
const toBrakeTime = moment(timeString, ['h:mm a']).format('HH:mm:ss');
setBrakeToTime(toBrakeTime);
} else {
setBrakeToTime(null);
}
};
const Columns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
render: (text, object, index) => (
{(page - 1) * 10 + index + 1}
),
},
{
title: 'Break Name',
dataIndex: 'BreakName',
key: 'BreakName',
editable: true,
render: (text) => {text},
filteredValue: [searchedText],
onFilter: (value, record) => {
return (
String(record.TableName)
?.toLowerCase()
?.includes(value?.toLowerCase()) ||
String(record.TableName)
?.toLowerCase()
?.includes(value?.toLowerCase()) ||
String(record.ChairCount)
?.toLowerCase()
?.includes(value?.toLowerCase()) ||
String(record.ChairLevelSer)
?.toLowerCase()
?.includes(value?.toLowerCase()) ||
String(record.DineInTypeName)
?.toLowerCase()
?.includes(value?.toLowerCase())
);
},
sorter: (a, b) => a?.BreakName?.length - b?.BreakName?.length,
sortOrder: sortedInfo.columnKey === 'BreakName' ? sortedInfo.order : null,
ellipsis: true,
},
{
title: 'Break Start',
dataIndex: 'BreakStartTime',
key: 'BreakStartTime',
},
{
title: 'Break End',
dataIndex: 'BreakEndTime',
key: 'BreakEndTime',
},
{
title: 'Duration (mins)',
key: 'Duration',
align: 'center',
render: (_, record) => {
const startTime = moment(record.BreakStartTime, 'HH:mm:ss');
const endTime = moment(record.BreakEndTime, 'HH:mm:ss');
const duration = endTime.diff(startTime, 'minutes');
return duration > 0 ? duration : 0;
},
},
{
title: 'Action',
key: 'Action',
dataIndex: 'Action',
align: 'center',
render: (_, record, index) => (
// Tabledata.length >= 1 ? (