Files
mwitnessing/components/calendar/ShiftComponent.tsx
2024-05-23 02:52:03 +03:00

267 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import axiosInstance from '../../src/axiosSecure';
import PublisherSearchBox from '../publisher/PublisherSearchBox'; // Update the path
import Modal from '../Modal';
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
const common = require('src/helpers/common');
function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, allPublishersInfo }) {
const [isDeleted, setIsDeleted] = useState(false);
const [assignments, setAssignments] = useState(shift.assignments);
const [isModalOpen, setIsModalOpen] = useState(false);
const [useFilterDate, setUseFilterDate] = useState(true);
const [selectedPublisher, setSelectedPublisher] = useState(null);
const [showCopyHint, setShowCopyHint] = useState(false);
const [transportProvided, setTransportProvided] = useState(false);
// Update assignments when shift changes
useEffect(() => {
setAssignments(shift.assignments);
setTransportProvided(!shift.requiresTransport || shift.assignments.some(ass => ass.isWithTransport));
}, [shift.assignments]);
const handleShiftClick = (shiftId) => {
if (onShiftSelect) {
onShiftSelect(shift);
}
};
const handlePublisherClick = (publisher) => {
setSelectedPublisher(publisher);
console.log("Publisher clicked:", publisher, "selected publisher:", selectedPublisher);
shift.selectedPublisher = publisher;
if (onShiftSelect) {
onShiftSelect(shift);
}
// if (onPublisherSelect) {
// onPublisherSelect(publisher);
// }
common.copyToClipboard(null, publisher.firstName + ' ' + publisher.lastName);
}
const deleteShift = async (id) => {
try {
console.log("Removing shift with id:", id);
await axiosInstance.delete("/api/data/shifts/" + id);
setIsDeleted(true);
} catch (error) {
console.error("Error removing shift:", error);
}
}
const removeAssignment = async (id) => {
try {
console.log("Removing assignment with id:", id);
await axiosInstance.delete("/api/data/assignments/" + id);
setAssignments(prevAssignments => prevAssignments.filter(ass => ass.id !== id));
} catch (error) {
console.error("Error removing assignment:", error);
}
};
const addAssignment = async (publisher, shiftId) => {
try {
console.log(`new assignment for publisher ${publisher.id} - ${publisher.firstName} ${publisher.lastName}`);
const newAssignment = {
publisher: { connect: { id: publisher.id } },
shift: { connect: { id: shiftId } },
//isActive: true,
isConfirmed: true,
};
const { data } = await axiosInstance.post("/api/data/assignments", newAssignment);
// Update the 'publisher' property of the returned data with the full publisher object
data.publisher = publisher;
setAssignments(prevAssignments => [...prevAssignments, data]);
} catch (error) {
console.error("Error adding assignment:", error);
}
};
const copyAllPublisherNames = () => {
const names = assignments.map(ass => `${ass.publisher.firstName} ${ass.publisher.lastName}`).join(', ');
common.copyToClipboard(null, names);
// Show hint and set a timer to hide it
setShowCopyHint(true);
setTimeout(() => setShowCopyHint(false), 1500);
};
async function toggleTransport(assignment): Promise<void> {
try {
assignment.isWithTransport = !assignment.isWithTransport;
const { data } = await axiosInstance.put("/api/data/assignments/" + assignment.id,
{ isWithTransport: assignment.isWithTransport })
.then(() => {
setTransportProvided(assignments.some(ass => ass.isWithTransport))
});
} catch (error) { }
}
async function toggleRequiresTransport(shiftId): Promise<void> {
try {
shift.requiresTransport = !shift.requiresTransport;
const { data } = await axiosInstance.put("/api/data/shifts/" + shiftId,
{ requiresTransport: shift.requiresTransport })
.then(() => {
console.log("shift '" + shiftId + "' transport required:" + shift.requiresTransport);
// setTransportProvided(assignments.some(ass => ass.isWithTransport))
});
} catch (error) { }
}
return (
<>{!isDeleted && (
<div className={`flow w-full p-4 py-2 border-2 border-gray-300 rounded-md my-1 ${isSelected ? 'bg-gray-200' : ''}`}
onClick={handleShiftClick} onDoubleClick={copyAllPublisherNames}>
{/* Time Window Header */}
<div className="flex justify-between items-center mb-2 border-b pb-1">
<span className="flex text-lg font-semibold">
{`${common.getTimeRange(new Date(shift.startTime), new Date(shift.endTime))}`}
{/* {shift.requiresTransport && (<LocalShippingIcon />)} */}
{/* Toggle for Transport Requirement */}
<label className="ml-4 flex items-center">
<input type="checkbox" checked={shift.requiresTransport}
onChange={() => toggleRequiresTransport(shift.id)}
className="form-checkbox h-5 w-5 text-green-600" />
<span className="ml-2 text-sm text-gray-700">транспорт</span>
</label>
</span>
{/* Copy All Names Button */}
<button onClick={copyAllPublisherNames} className="bg-green-500 text-white py-1 px-2 text-sm rounded-md">
копирай имената {/* Placeholder for Copy icon */}
</button>
{/* Hint Message */}
{showCopyHint && (
<div className="absolute top-0 right-0 p-2 bg-green-200 text-green-800 rounded">
Имената са копирани
</div>
)}
</div>
{/* Assignments */}
{assignments.map((ass, index) => {
const publisherInfo = allPublishersInfo.find(info => info?.id === ass.publisher.id) || ass.publisher;
// Determine border styles
let borderStyles = '';
let canTransport = false;
if (selectedPublisher && selectedPublisher.id === ass.publisher.id) {
borderStyles += 'border-2 border-blue-300'; // Bottom border for selected publishers
}
else {
if (publisherInfo.availabilityCount == 0) //user has never the form
{
borderStyles = 'border-2 border-orange-300 ';
}
else
//if there is no publisherInfo - draw red border - publisher is no longer available for the day!
if (!publisherInfo.availabilities || publisherInfo.availabilities.length == 0) {
borderStyles = 'border-2 border-red-500 ';
}
else {
// checkig if the publisher is available for this assignment
const av = publisherInfo.availabilities?.find(av =>
av.startTime <= shift.startTime && av.endTime >= shift.endTime
);
if (av) {
borderStyles += 'border-l-2 border-blue-500 '; // Left border for specific availability conditions
ass.canTransport = av.isWithTransportIn || av.isWithTransportOut;
}
else {
borderStyles += 'border-l-4 border-red-500 ';
}
if (publisherInfo.hasUpToDateAvailabilities) {
//add green right border
borderStyles += 'border-r-2 border-green-300';
}
//the pub is the same time as last month
// if (publisherInfo.availabilities?.some(av =>
// (!av.dayOfMonth || av.isFromPreviousMonth) &&
// av.startTime <= ass.startTime &&
// av.endTime >= ass.endTime)) {
// borderStyles += 'border-t-2 border-yellow-500 '; // Left border for specific availability conditions
// }
}
}
return (
<div key={index}
className={`flow rounded-md px-2 py-1 sm:py-0.5 my-1 ${(ass.isConfirmed && !ass.isBySystem) ? 'bg-green-100' : 'bg-gray-100'} ${borderStyles}`}
>
<div className="flex justify-between items-center" onClick={() => handlePublisherClick(ass.publisher)}>
<span className="text-gray-700">{publisherInfo.firstName} {publisherInfo.lastName}</span>
<div className="flex items-left" >
{/* //if shift.isWithTransport, add trnsport button toggle, which sets ass.isWithTransportIn */}
{shift.requiresTransport && (
<span
onClick={ass.canTransport || true ? () => toggleTransport(ass) : undefined}
className={`material-icons ${ass.isWithTransport ? 'text-green-500 font-bold' : (transportProvided ? 'text-gray-400 ' : 'text-orange-400 font-bold')} ${ass.canTransport || ass.isWithTransport || true ? ' cursor-pointer' : 'cursor-not-allowed'} px-3 py-0 ml-2 rounded-md`}
>
{ass.isWithTransport ? "транспорт" : ass.canTransport ? "може транспорт" : "без транспорт"} <LocalShippingIcon />
</span>
)}
<button onClick={() => removeAssignment(ass.id)} className="items-center leading-snug text-white text-center bg-red-500 hover:bg-red-600 px-3 py-1 md:py-0.5 ml-2 rounded-md" >
махни
</button>
</div>
</div>
</div>
);
})}
{/* This is a placeholder for the dropdown to add a publisher. You'll need to implement or integrate a dropdown component */}
<div className="flex space-x-2 items-center">
{/* Add Button */}
<button onClick={() => setIsModalOpen(true)} className="bg-blue-500 text-white p-2 py-1 rounded-md">
добави участник{/* Placeholder for Add icon */}
</button>
{assignments.length == 0 && (
<button onClick={() => deleteShift(shift.id)} className="bg-red-500 text-white p-2 py-1 rounded-md"
>изтрий смяната</button>
)}
</div>
{/* Modal for Publisher Search
forDate={new Date(shift.startTime)}
*/}
<Modal isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
forDate={new Date(shift.startTime)}
useFilterDate={useFilterDate}
onUseFilterDateChange={(value) => setUseFilterDate(value)}>
<PublisherSearchBox
selectedId={null}
isFocused={isModalOpen}
filterDate={useFilterDate ? new Date(shift.startTime) : null}
onChange={(publisher) => {
// Add publisher as assignment logic
setIsModalOpen(false);
addAssignment(publisher, shift.id);
}}
showAllAuto={true}
showSearch={true}
showList={false}
/>
</Modal>
</div >
)}</>
);
}
export default ShiftComponent;