In the code below, I have a weekly calendar displayed as shown below:
When I drag and drop these draggable boxes from one date to another, for example, if I drag the Morooka from Tuesday 9th to Sunday 7th in column 8th, it will drop it into column 1st. The same happens with other draggable boxes; if I drop them from the 9th in the 1st column to the 10th in the 6th column, they still end up in column 1.
I expect the dragbox to be dropped into the column where I release it. So if I drop it into column 5, it should stay in column 5. However, currently, everything is being dropped into column 1. Is there any way to fix this?
I tried printing in my console.log when the drag box is dropped, and it seems to identify the correct column and print the date and timeslot correctly. However, it still doesn't drop into the correct column
import React, { useState, useRef } from "react";
import { startOfWeek, endOfWeek, format, addDays, subDays, set } from "date-fns";
import axios from 'axios';
import { fetchCustomers } from '../../api/customer';
const DraggableBox = ({
day,
name: initialName,
suburb: initialSuburb,
calendarData,
setCalendarData,
changeName,
setChangeName,
changeSuburb,
setChangeSuburb,
setChangeDay,
setChangeData,
orderData,
setOrderData,
timeSlotIndex,
}) => {
const [showTooltip, setShowTooltip] = useState(false);
const boxRef = useRef(null);
const filteredOrders = orderData.order.filter(
(order) => new Date(order.RequiredDateAndTime).getDate() === 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();
};
return (
<div
className="drag-box"
ref={boxRef}
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragOver={handleDragOver}
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
style={{
width: "70px",
height: "70px",
textAlign: "center",
backgroundColor: "#F5F5F5",
color: "#333333",
marginTop: "0px",
position: "relative",
cursor: "move",
fontSize: "10px",
}}
data-day={day}
data-name={initialName}
>
<div>
{filteredOrders[timeSlotIndex] && (
<div key={timeSlotIndex}>
<p>{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 handleNextWeek = () => {
setSelectedDate(addDays(selectedDateState, 7));
};
const handlePreviousWeek = () => {
setSelectedDate(subDays(selectedDateState, 7));
};
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();
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');
let currentMonth = e.target.getAttribute('data-month');
// Log the day, month, and year
console.log("Day:", dayOfMonth);
// Format the month with leading zero if it's a single digit
currentMonth = currentMonth.padStart(2, "0");
console.log("Month:", currentMonth);
console.log("Year:", currentYear);
// Format the day with leading zero
const formattedDay = dayOfMonth.toString().padStart(2, "0");
const formattedDate = `${currentYear}-${currentMonth}-${formattedDay}`;
console.log("Formatted Date:", formattedDate);
d.setDate(dayOfMonth);
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, dayOfMonth, 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 = `${timeSlotIndex + 1}`;
console.log("Updated changeData:", changeData); // Log the updated changeData
console.log("Time Slot:", timeSlot);
// Push the updated dragged item to the new position
newOrderData.push({ ...changeData, timeSlot });
console.log("Updated newOrderData:", newOrderData);
setCalendarData(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);
const generateCalendar = () => {
const startDate = startOfWeek(selectedDateState, { weekStartsOn: 0 });
const endDate = endOfWeek(selectedDateState, { 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;
const dayName = format(day, "EEEE");
const dayOfMonth = format(day, "d");
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(15)].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: "40px",
width: "60px",
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;
};
return (
<div>
<div className="delivery-schedule-heading">
<h2 style={{ color: "", margin: "0 0px 0 0px", textAlign: "left" }}></h2>
<div style={{ textAlign: "left", margin: "0 0px 0 0px" }}>
<h2 style={{ margin: 0, color: "#08315b", fontWeight: "bold" }}>
Delivery Schedule : {format(startOfWeek(selectedDateState), "MMMM d")} -{" "}
{format(endOfWeek(selectedDateState), "MMMM d, yyyy")}
</h2>
</div>
<div style={{ textAlign: "right" }}>
{/* Button for moving to the previous week */}
<button onClick={handlePreviousWeek}>< Previous Week</button>
{/* Button for moving to the next week */}
<button onClick={handleNextWeek}>Next Week ></button>
</div>
</div>
<div className="calendar-container">
<table className="calendar-table">
<thead>
<tr>
<th>{/* Empty header cell for labels */}</th>
{[...Array(15)].map((_, index) => (
<th key={index}>{index + 1}</th>
))}
</tr>
</thead>
<tbody>
{generateCalendar()}
</tbody>
</table>
</div>
</div>
);
};
export default RunSheetPreview;
e.dataTransfer.setData("text", e.currentTarget.id)
in thehandleDrop
function. This probably won't make a difference with you current code, but in general, it's best to usee.currentTarget
, instead ofe.target
. ThecurrentTarget
always refers to the element that has the event listener.target
refers to the child of thecurrentTarget
that the cursor is on.<table>
related elements are very outdated and can be very challenging to work with. You might want to look into using<div>
elements with table relatedrole
attributes. Do research first to know whether changing this will benefit you, but usually when I've worked with<table>
elements, I end up needing to switch to<div>
elements to accomplish my goals, as it related toCSS
andJavaScript
.