在下面的代码中,我显示了一个每周日历,如下所示:
当我将这些可拖动框从一个日期拖放到另一个日期时,例如,如果我将第 8 列中的 Morooka 从星期二 9 日拖动到星期日 7 日,它会将其放入第一列。其他可拖动框也会发生同样的情况;如果我将它们从第 1 列的第 9 个放到第 6 列的第 10 个,它们仍然会出现在第 1 列中。
我希望拖拽框被拖放到我释放它的列中。因此,如果我将其放入第 5 列,它应该保留在第 5 列。但是,目前,所有内容都被放入第 1 列。有什么方法可以解决这个问题吗?
当拖动框被放下时,我尝试在 console.log 中进行打印,它似乎可以识别正确的列并正确打印日期和时间段。然而,它仍然没有落入正确的列
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;
问题似乎是您使用ordersForDay索引来标识时间段,而不是使用您自己的timeSlot属性。
当您在 JavaScript 中过滤数组时,它不会维护其原始索引。这就是为什么所有订单最终都在起始列中“分组在一起”,而不是像您期望的那样留下空白。
而不是像您在代码中那样按天过滤:
const ordersForDay = orderData.order.filter((order) => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(dayOfMonth);
});
您可以在行创建中按时间段过滤:
{[...Array(15)].map((_, index) => {
const ordersForTimeSlot = orderData.order.filter((order) => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(dayOfMonth) && order.timeSlot == index;
});
return (<td ...
然后你可以检查该时间段是否有订单,将其显示为 DraggableBox:
{ordersForTimeSlot[0] && (
<DraggableBox ...
此代码未经测试,但我希望这可以帮助您指出正确的方向!