Files
mwitnessing/components/calendar/ShiftComponent.tsx
Dobromir Popov acd776e988 renames
2024-03-26 01:08:57 +02:00

238 lines
11 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 [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) => {
// console.log("onShiftSelect prop:", onShiftSelect);
// console.log("Shift clicked:", shift);
//shift.selectedPublisher = selectedPublisher;
if (onShiftSelect) {
onShiftSelect(shift);
}
};
const handlePublisherClick = (publisher) => {
//toggle selected
// if (selectedPublisher != null) {
// setSelectedPublisher(null);
// }
// else {
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 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) { }
}
return (
<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="text-lg font-semibold">
{`${common.getTimeRange(new Date(shift.startTime), new Date(shift.endTime))}`}
{/* {shift.requiresTransport && (<LocalShippingIcon />)} */}
</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;
}
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 space-x-2 rounded-md px-2 py-1 my-1 ${ass.isConfirmed ? '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 ? () => toggleTransport(ass) : undefined}
className={`material-icons ${ass.isWithTransport ? 'text-green-500 font-bold' : (transportProvided ? 'text-gray-400 ' : 'text-orange-400 font-bold')} ${ass.canTransport ? ' cursor-pointer' : 'cursor-not-allowed'} px-3 py-1 ml-2 rounded-md`}
>
{ass.isWithTransport ? "транспорт" : ass.canTransport ? "може транспорт" : "без транспорт"} <LocalShippingIcon />
</span>
)}
<button onClick={() => removeAssignment(ass.id)} className="text-white bg-red-500 hover:bg-red-600 px-3 py-1 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>
</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;