After doing a bit of workaround I can drag and drop boxes now however it drops at whatever timeslot is empty first rather dropping to actual timeslot for example, if I drop box to 26th t1 to 27th t2 then it will drop the box to t1 27th instead rather t2 and now lets say I drop to 29th t6 it will drop to 29th t3 as t1 and t2 are full and t3 is empty so does not drop to right timeslot instead drops to whatever timeslot if first empty for that date
also once I load website again all the drag boxes I moved goes back to what it was before
updated code below
import React, { useState, useRef } from "react";
import { startOfWeek, endOfWeek, format, addDays, subDays, set } from "date-fns";
import "../assets/css/RunSheetPDF.css";
const DraggableBox = ({
day,
name: initialName,
suburb: initialSuburb,
calendarData,
setCalendarData,
changeName,
setChangeName,
changeSuburb,
setChangeSuburb,
setChangeDay,
setChangeData,
orderData,
setOrderData,
timeSlotIndex // Add the time slot index as a prop
}) => {
const [showTooltip, setShowTooltip] = useState(false);
const boxRef = useRef(null);
const filteredOrders = orderData.order.filter((order) => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(day);
});
const handleDragStart = (e) => {
setShowTooltip(false);
setChangeData(filteredOrders[timeSlotIndex]);
boxRef.current.classList.add("dragging");
};
const handleDragEnd = () => {
boxRef.current.classList.remove("dragging");
};
const handleDragOver = (e) => {
e.preventDefault();
};
console.log("Filtered Orders:", filteredOrders);
return (
<div
className="drag-box"
ref={boxRef}
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragOver={handleDragOver}
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
style={{
width: "70px",
height: "80px",
textAlign: "center",
backgroundColor: "#F5F5F5",
color: "#333333",
marginTop: "5px",
position: "relative",
cursor: "move", // Set cursor to move when hovering over the box
}}
data-day={day} // Set the day as a dataset attribute
data-name={initialName} // Set the name as a dataset attribute
>
<div style={{ margin: 0, lineHeight: "40px" }}>
{/* Render order details based on time slot index */}
{filteredOrders[timeSlotIndex] && (
<div key={timeSlotIndex}>
{/* Render DelCity */}
<p style={{ margin: 0 }}>{filteredOrders[timeSlotIndex].Id}</p>
{/* Render DelPostalCode */}
<p style={{ margin: 0 }}>{filteredOrders[timeSlotIndex].DelCity}</p>
</div>
)}
</div>
</div>
);
};
const RunSheetPreview = ({
orderData,
setOrderData,
selectedDate,
initialName,
initialSuburb,
setShowTooltip,
}) => {
const boxRef = useRef(null);
const [changeName, setChangeName] = useState("");
const [changeDay, setChangeDay] = useState(null);
const [changeData, setChangeData] = useState(null);
const [changeSuburb, setChangeSuburb] = useState(null);
const [selectedDateState, setSelectedDate] = useState(new Date());
const formatDate = (date) => {
const dateVal = new Date(date);
const year = dateVal.getFullYear();
const month = String(dateVal.getMonth() + 1).padStart(2, "0");
const day = String(dateVal.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
const handleDragOver = (e) => {
e.preventDefault();
};
const handleDrop = (e, timeSlotIndex, dayOfMonth, year, month) => {
e.preventDefault();
e.stopPropagation();
// Parse the date and update the order data
let d = { ...changeData };
d = new Date(d.OrderDate);
const number = e.target.tabIndex.toString();
console.log("Number:", number);
const currentYear = e.target.getAttribute('data-year');
const currentMonth = e.target.getAttribute('data-month');
console.log("Current Year:", currentYear);
console.log("Current Month:", currentMonth);
let day = Number(number);
console.log("Day:", day);
d.setDate(day);
d.setMonth(currentMonth);
d.setFullYear(currentYear);
d = d.toISOString();
let fi = { ...changeData };
fi.OrderDate = d;
fi.RequiredDateAndTime = d;
let newDate = new Date(changeData.OrderDate);
newDate = new Date(currentYear, currentMonth, day, newDate.getHours(), newDate.getMinutes(), newDate.getSeconds());
// Update the order data
let newOrderData = orderData.order.filter(item => item !== changeData);
// Update the order date for the dragged item to its new position
changeData.OrderDate = newDate.toISOString();
changeData.RequiredDateAndTime = newDate.toISOString();
const timeSlot = `t${timeSlotIndex + 1}`;
console.log("Time Slot:", timeSlot);
// Push the updated dragged item to the new position
newOrderData.push({ ...changeData, timeSlot });
// Update the order data state
//orderData.order = newOrderData; // Update the order data
setCalendarData(newOrderData);
// setChangeData(newOrderData[timeSlotIndex]);
console.log("Updated order data:", newOrderData);
};
// Remove the filter based on selectedDate
const dateStrings = orderData.order.map((listItem) => {
const date = new Date(listItem.RequiredDateAndTime);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
});
const initialCalendarData = orderData.order.map((order, index) => {
const name = order.DelCity;
const suburb = order.DelPostalCode;
return {
day: dateStrings[index], // Use dateStrings array here
name,
suburb,
initialName: name, // Assign the value to initialName
initialSuburb: suburb, // Assign the value to initialSuburb
};
});
const [calendarData, setCalendarData] = useState(initialCalendarData);
//console.log("Calendar Data:", calendarData);
//console.log("formatDate Data:", formatDate);
//console.log("filteredOrders Data:", filteredOrders);
//console.log("dateStrings Data:", dateStrings);
//console.log("Order Data:", orderData);
const generateCalendar = (timeSlotIndex ) => {
const startDate = startOfWeek(selectedDate, { weekStartsOn: 0 });
const endDate = endOfWeek(selectedDate, { weekStartsOn: 0 });
const rows = [];
let day = startDate;
while (day <= endDate) {
const formattedDate = formatDate(day);
const dateObject = new Date(formattedDate);
const year = dateObject.getFullYear(); // Extract year (e.g., 2024)
const month = dateObject.getMonth() + 1;
console.log("Month:", month);
console.log("Year:", year);
const dayName = format(day, "EEEE");
const dayOfMonth = format(day, "d");
console.log("dayofmonth", dayOfMonth);
console.log("format date",formattedDate);
const isTargetDate = dateStrings.includes(formattedDate);
const ordersForDay = orderData.order.filter(order => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(dayOfMonth);
});
// Find the first available time slot for the current day
const firstAvailableSlot = ordersForDay.findIndex(order => !order.isAssigned);
const row = (
<tr key={day}>
<td className="calendar-cell">
<div className="day-name">{dayName}</div>
<div className="day-number">{dayOfMonth}</div>
</td>
{[...Array(10)].map((_, index) => (
<td key={index} className={`grid-cell`} data-has-data={ordersForDay[index] ? "true" : "false"} >
{/* Render DraggableBox only if there is an order for this column */}
{ordersForDay[index] && (
<DraggableBox
day={parseInt(dayOfMonth)}
initialName={ordersForDay[index].DelCity}
initialSuburb={ordersForDay[index].DelPostalCode}
calendarData={calendarData}
setCalendarData={setCalendarData}
changeName={changeName}
setOrderData={setOrderData} // Pass the setOrderData function
setChangeName={setChangeName}
changeDay={changeDay}
setChangeDay={setChangeDay}
changeSuburb={changeSuburb}
setChangeSuburb={setChangeSuburb}
setChangeData={setChangeData}
orderData={orderData}
timeSlotIndex={index}
/>
)}
{!ordersForDay[index] && (
<p
style={{
height: "90px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onDragOver={handleDragOver}
onDrop={(e) => handleDrop(e, index, parseInt(dayOfMonth), year, month)}
tabIndex={dayOfMonth}
data-year={year}
data-month={month}
></p>
)}
</td>
))}
</tr>
);
rows.push(row);
day = addDays(day, 1);
}
return rows;
};
const handleNextWeek = () => {
setSelectedDate(addDays(selectedDate, 7));
};
const handlePreviousWeek = () => {
setSelectedDate(subDays(selectedDate, 7));
};
return (
<div style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "center", marginTop: "20px" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "0px" }}>
<h2 style={{ color: "#333333", margin: 0 }}>{format(startOfWeek(selectedDate), "MMMM d")} - {format(endOfWeek(selectedDate), "MMMM d, yyyy")}</h2>
</div>
<div className="calendar-container">
<table className="calendar-table">
<thead>
<tr>
<th>{/* Empty header cell for labels */}</th>
{[...Array(10)].map((_, index) => (
<th key={index}>t{index + 1}</th>
))}
</tr>
</thead>
<tbody>
{generateCalendar()}
</tbody>
</table>
</div>
</div>
);
};
export default RunSheetPreview;
also the data I am using is just order no so it could be any such as 190, 182 etc and suburb name in the dragbox
2
Answers
The code is as explained in the chat room.
In your handleDrop function, you’re currently calculating the new date based on the day retrieved from the tabIndex attribute of the drop target. Instead, you should use the day of the week provided by the calendar grid cell where the drop occurred. You can calculate the correct date by adding the dayOfMonth value (from the calendar grid cell) to the start date of the week.
Replace this line
with this line
You need to implement functionality to save the modified orderData to a backend server or a local storage solution like localStorage. When the page loads, you should retrieve this saved data and initialize your state with it.
You can save orderData to localStorage whenever it changes:
Ensure that changes made to the calendar persist even after a page reload, you should save the modified data to a persistent storage solution such as localStorage or a backend server.