UPDATED CODE BELOW:
我的问题是,当我尝试将框从一个日历日期拖放到另一个日历日期时,假设我在 3 月 12 日星期二 t1 有数据,我想将其拖动到 t3,它显示停止标志,但我无法拖动它。 我觉得我的handleDragStart、handleDragOver和handleDrop()有问题,因为我使用的是数据数组,也许数据首先分配得很好,正如我在我的保管箱中看到的那样,但稍后当我拖放数据时,它没有正确分配因此,在我的 console.log 中,这行
console.log("Drag start - Name:", initialName, "Suburb:", initialSuburb, "Day:", dataset.day);
表示未定义
console.log output
runsheetpreview.js
import React, { useState, useRef } from "react";
import { startOfWeek, endOfWeek, format, addDays, subDays } from "date-fns";
import "../assets/css/RunSheetPDF.css";
const DraggableBox = ({
day,
name: initialName,
suburb: initialSuburb,
calendarData,
setCalendarData,
changeName,
setChangeName,
changeSuburb,
setChangeSuburb,
setChangeDay,
orderData,
timeSlotIndex // Add the time slot index as a prop
}) => {
const [showTooltip, setShowTooltip] = useState(false);
const boxRef = useRef(null);
const handleDragStart = (e) => {
setShowTooltip(false);
const { dataset } = e.target;
setChangeName(initialName);
setChangeSuburb(initialSuburb);
setChangeDay(dataset.day);
boxRef.current.classList.add("dragging");
console.log("Drag start - Name:", initialName, "Suburb:", initialSuburb, "Day:", dataset.day);
};
const handleDragEnd = () => {
boxRef.current.classList.remove("dragging");
};
const handleDragOver = (e) => {
e.preventDefault();
};
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
const newDay = e.target.dataset.day; // Get the day from the dataset attribute
const newData = {
day: newDay,
name: initialName, // Use initialName instead of changeName
suburb: initialSuburb, // Use initialSuburb instead of changeSuburb
};
const newCalData = [...calendarData];
const calData = newCalData.filter((f) => f.day !== newData.day); // Remove existing data for the dropped day
calData.push(newData);
calData.sort((a, b) => Number(a.day) - Number(b.day));
setCalendarData(calData);
setChangeDay(null);
setChangeName(null);
setChangeSuburb(null);
console.log("Drop - New Data:", newData, "Calendar Data:", calData);
};
// Filter orderData.order based on the day
const filteredOrders = orderData.order.filter((order) => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(day);
});
console.log("Filtered Orders:", filteredOrders);
return (
<div
className="drag-box"
ref={boxRef}
draggable
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onDragOver={handleDragOver}
onDrop={handleDrop}
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].DelCity}</p>
{/* Render DelPostalCode */}
<p style={{ margin: 0 }}>{filteredOrders[timeSlotIndex].DelPostalCode}</p>
</div>
)}
</div>
</div>
);
};
const RunSheetPreview = ({
orderData,
selectedDate,
initialName,
initialSuburb,
setShowTooltip,
}) => {
const boxRef = useRef(null);
const [changeName, setChangeName] = useState("");
const [changeDay, setChangeDay] = 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) => {
e.preventDefault();
e.stopPropagation();
const newDay = e.target.dataset.day; // Get the day from the dataset attribute
const newData = {
day: newDay,
name: initialName, // Use initialName instead of changeName
suburb: initialSuburb, // Use initialSuburb instead of changeSuburb
};
const newCalData = [...calendarData];
const calData = newCalData.filter((f) => f.day !== newData.day); // Remove existing data for the dropped day
calData.push(newData);
calData.sort((a, b) => Number(a.day) - Number(b.day));
setCalendarData(calData);
setChangeDay(null);
setChangeName(null);
setChangeSuburb(null);
console.log("Drop - New Data:", newData, "Calendar Data:", calData);
};
const [calendarData, setCalendarData] = useState(initialCalendarData);
let filteredOrders = [];
if (selectedDate) {
filteredOrders = orderData.order.filter(
(order) =>
order.RequiredDateAndTime.substring(0, 10) ===
formatDate(selectedDate)
);
}
// 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 dayStrings = filteredOrders.map((listItem, index) => {
const date = new Date(listItem.RequiredDateAndTime);
const day = String(date.getDate()).padStart(2, "0");
return day;
});
console.log("Calendar Data:", calendarData);
console.log("formatDate Data:", formatDate);
console.log("filteredOrders Data:", filteredOrders);
console.log("dayStrings Data:", dayStrings);
console.log("dateStrings Data:", dateStrings);
console.log("Order Data:", orderData);
const generateCalendar = () => {
const startDate = startOfWeek(selectedDate, { weekStartsOn: 0 });
const endDate = endOfWeek(selectedDate, { weekStartsOn: 0 });
const rows = [];
let day = startDate;
while (day <= endDate) {
const dayName = format(day, "EEEE");
const dayOfMonth = format(day, "d");
const formattedDate = formatDate(day);
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}
setChangeName={setChangeName}
changeDay={changeDay}
setChangeDay={setChangeDay}
changeSuburb={changeSuburb}
setChangeSuburb={setChangeSuburb}
orderData={orderData}
timeSlotIndex={index}
handleDrop={handleDrop}
handleDragOver={handleDragOver}
/>
)}
{!ordersForDay[index] && (
<p
style={{
height: "90px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
tabIndex={dayOfMonth}
></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;
而且我的CSS看起来很糟糕,我无法正确地看到数据,如果有什么方法可以让它变得更好,并使我的日历看起来也不错,因为它看起来很糟糕,也感谢任何帮助。 我的CSS代码 RunSheetPDF.css
.centered-text {
text-align: center;
font-weight: 700;
}
.title {
text-align: left;
font-weight: bold;
font-size: 30px;
text-transform: uppercase;
font-style: bold;
}
.table-container {
width: 1000px;
background: white;
font-family: "Times New Roman";
}
.table {
width: 90%;
border-collapse: collapse;
}
.top-header th {
text-align: left;
border: none;
}
.table-body td {
text-align: left;
border: none;
}
.paper {
padding: 20px;
display: flex;
justify-content: space-between;
}
.left-content {
flex: 1;
text-align: left;
}
.right-content {
flex: 1;
text-align: left;
}
.flex-content {
display: flex;
justify-content: space-between;
}
.empty-box {
text-align: left;
}
.border-box {
width: 100px;
height: 20px;
border: 1px solid #000;
}
.bold-text {
font-weight: bold;
}
.normal-text {
font-weight: normal;
}
.text-left {
text-align: left;
font-family: "Times New Roman", Times, serif;
}
.no-border {
border: none;
}
.page-content {
height: 38rem;
overflow: auto;
border: solid 1px black;
margin: 0 80mm 30mm 45mm;
width: 35rem;
page-break-after: always;
}
/* Use media query to apply styles only when printing */
@media print {
.page-content {
page-break-before: always; /* This will force a page break before each .page-content element */
}
}
/* Add this to your CSS file or CSS module */
.print-button-wrapper {
position: fixed;
bottom: 130px; /* Adjust this value to change the vertical position */
right: 150px; /* Adjust this value to change the horizontal position */
}
.calendar-container {
margin: 20px auto;
max-width: 800px;
background-color: #f2f2f2;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.calendar-table {
width: 100%;
border-collapse: collapse;
}
.calendar-table th, .calendar-table td {
padding: 10px;
text-align: center;
border: 2px solid #fff; /* White border to separate cells */
}
.calendar-table th {
background-color: #3f51b5; /* Dark blue background for days */
color: #fff;
font-weight: bold;
font-size: 18px;
}
.calendar-table td {
background-color: #ffffff; /* White background for date cells */
}
.calendar-table td:first-child {
background-color: #f5f5f5; /* Light gray background for first column */
}
.drag-box {
padding: 10px;
border: 1px solid #ccc;
background-color: #fff;
cursor: pointer;
}
.drag-box p {
margin: 5px 0;
}
.drag-box input {
width: 100%;
padding: 5px;
margin-bottom: 5px;
}
.drag-box.draggable {
background-color: #ffd700; /* Gold background for draggable box */
border-color: #ffd700;
color: #000;
}
.drag-box.draggable p {
color: #000;
}
.drag-box {
background-color: #ffffff;
border: 1px solid #cccccc;
border-radius: 5px;
padding: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
width: 100px; /* Adjust the width as needed */
height: 60px; /* Adjust the height as needed */
transition: opacity 0.3s ease; /* Add transition for smooth hide/show effect */
}
.drag-box.hidden {
opacity: 0; /* Hide the box during drag */
}
.calendar-table {
border-collapse: collapse;
width: 100%; /* Make the table fill its container */
background-color: #f0e8ff; /* Light purple background color */
}
.calendar-table th,
.calendar-table td {
border: 1px solid #cccccc;
padding: 8px;
text-align: center;
width: 100px; /* Adjust the width of table cells */
}
.drag-box {
cursor: pointer;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
margin: 2px;
}
.calendar-table {
width: 100%;
}
.calendar-table td {
border: 1px solid #ccc;
padding: 5px;
margin: 2px;
}
.calendar-table {
width: 100%;
}
.calendar-table td {
border: 1px solid #ccc;
padding: 5px;
text-align: center;
}
.calendar-table p {
margin: 0;
}
.tooltip {
position: absolute;
top: 100%; /* Position below the draggable box */
left: 50%; /* Center horizontally */
transform: translateX(-50%); /* Center horizontally */
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
z-index: 1; /* Ensure tooltip appears above other elements */
white-space: nowrap; /* Prevent line breaks */
visibility: hidden; /* Initially hidden */
}
#mydiv {
position: absolute;
z-index: 9;
background-color: #f1f1f1;
text-align: center;
border: 1px solid #d3d3d3;
}
#mydivheader {
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
.calendar-cell {
width: 70px;
height: 80px;
padding: 5px;
text-align: center;
}
.day-name {
font-weight: bold;
}
.day-number {
margin-top: 5px;
}
.grid-cell {
width: 70px;
height: 80px;
border: 1px solid #ccc; /* Add border for grid cells */
}
.tooltip {
position: absolute;
top: calc(100% + 5px); /* Position tooltip below the box */
left: 50%;
transform: translateX(-50%);
background-color: #333333;
color: #FFFFFF;
padding: 5px;
border-radius: 5px;
display: none;
}
.calendar-table {
width: 100%;
border-collapse: collapse;
}
.calendar-cell {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
.grid-cell {
border: 1px solid #ccc;
padding: 10px;
text-align: center;
}
/* Adjust width of grid cells with data */
.grid-cell[data-has-data="true"] {
width: 150px; /* Adjust width as needed */
}
.drag-box {
width: 70px;
height: 80px;
text-align: center;
background-color: #F5F5F5;
color: #333333;
margin-top: 5px;
position: relative;
cursor: move;
overflow: hidden; /* Ensure text does not overflow outside the box */
}
.drag-box p {
margin: 5px 0; /* Adjust margin for better spacing */
overflow: hidden; /* Ensure text does not overflow outside the box */
text-overflow: ellipsis; /* Show ellipsis for overflowed text */
white-space: nowrap; /* Prevent text from wrapping */
}
.calendar-table {
width: 100%; /* Ensure the table takes full width */
border-collapse: collapse; /* Collapse table borders */
}
.calendar-cell {
width: 120px; /* Increase the width of the calendar cell */
height: 120px; /* Increase the height of the calendar cell */
border: 1px solid #ccc; /* Add border to the calendar cell */
}
.grid-cell {
height: 100%; /* Make the grid cells take full height of the calendar cell */
}
代码如聊天室中所述。
import React, { useState, useRef } from "react";
import { startOfWeek, endOfWeek, format, addDays, subDays } from "date-fns";
import "./RunSheetPDF.css";
const DraggableBox = ({
day,
initialName,
initialSuburb,
setChangeData,
orderData,
timeSlotIndex, // Add the time slot index as a prop
}) => {
const [showTooltip, setShowTooltip] = useState(false);
const boxRef = useRef(null);
const handleDragStart = (e) => {
setShowTooltip(false);
setChangeData(filteredOrders[timeSlotIndex]);
boxRef.current.classList.add("dragging");
};
const handleDragEnd = () => {
boxRef.current.classList.remove("dragging");
};
const filteredOrders = orderData.order.filter((order) => {
const orderDate = new Date(order.RequiredDateAndTime).getDate();
return orderDate === parseInt(day);
});
return (
<div
className="drag-box"
ref={boxRef}
draggable
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
onMouseEnter={() => setShowTooltip(true)}
onMouseLeave={() => setShowTooltip(false)}
style={{
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" }}>
{filteredOrders[timeSlotIndex] && (
<div key={timeSlotIndex}>
<p style={{ margin: 0 }} className="el">
{filteredOrders[timeSlotIndex].DelCity}
</p>
<p style={{ margin: 0 }}>
{filteredOrders[timeSlotIndex].DelPostalCode}
</p>
</div>
)}
</div>
{showTooltip && (
<div className="tooltip">
<p style={{ margin: 0 }}>{initialName}</p>
<p style={{ margin: 0 }}>{initialSuburb}</p>
</div>
)}
</div>
);
};
const RunSheetPreview = ({ selectedDate = "2023-08-27", orderData }) => {
const boxRef = useRef(null);
const [changeData, setChangeData] = useState(null);
const [selectedDateState, setSelectedDateState] = 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 formatDate1 = (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 initialCalendarData = orderData.order.map((order) => ({
day: 31, // Assuming day 31 is default for all orders, you can change this if needed
date: order.RequiredDateAndTime,
name: order.DelCity,
suburb: order.DelPostalCode,
}));
// console.log(initialCalendarData);
const [calendarData, setCalendarData] = useState(initialCalendarData);
let filteredOrders = [];
let startDate = startOfWeek(selectedDate, { weekStartsOn: 0 });
const endDate = endOfWeek(selectedDate, { weekStartsOn: 0 });
while (startDate <= endDate) {
let fO = [];
fO = orderData.order.filter(myF);
startDate = addDays(startDate, 1);
}
function myF(order) {
if (order.RequiredDateAndTime.substring(0, 10) === formatDate(startDate)) {
filteredOrders.push(order);
}
}
const dateStrings = filteredOrders.map((listItem, index) => {
const date = new Date(listItem.RequiredDateAndTime);
const day = String(date.getDate()).padStart(2, "0");
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
return `${year}-${month}-${day}`;
});
const dayStrings = filteredOrders.map((listItem, index) => {
const date = new Date(listItem.RequiredDateAndTime);
const day = String(date.getDate()).padStart(2, "0");
return day;
});
// dayStrings.map((day) => {
// const parsedDay = parseInt(day);
// console.log("Parsed Day:", parsedDay); //returns 31
// });
// console.log("Calendar Data:", calendarData);
// console.log("formatDate Data:", formatDate);
// console.log("filteredOrders Data:", filteredOrders);
// console.log("dayStrings Data:", dayStrings);
// console.log("dateStrings Data:", dateStrings);
// console.log("Order Data:", orderData);
const generateCalendar = () => {
const startDate = startOfWeek(selectedDate, { weekStartsOn: 0 });
const endDate = endOfWeek(selectedDate, { weekStartsOn: 0 });
const rows = [];
let day = startDate;
while (day <= endDate) {
const cellDate = formatDate1(day);
const dayName = format(day, "EEEE");
const dayOfMonth = format(day, "d");
const formattedDate = formatDate(day);
const isTargetDate = dateStrings.includes(formattedDate);
const ordersForDay = filteredOrders.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 handleDragOver = (e) => {
e.preventDefault();
};
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
let d = { ...changeData };
d = new Date(d.OrderDate);
const number = e.target.tabIndex.toString();
let year = Number(number.substring(0, 4));
let month = number.substring(4).substring(0, 2);
month =
Number(month.substring(0, 1)) === 0
? Number(month.substring(1)) - 1
: Number(month) - 1;
let day = number.substring(6);
day =
Number(day.substring(0, 1)) === 0
? Number(day.substring(1))
: Number(day);
d.setDate(day);
d.setMonth(month);
d.setFullYear(year);
d = d.toISOString();
let fi = { ...changeData };
fi.OrderDate = d;
fi.RequiredDateAndTime = d;
let newOrderData = orderData.order.filter(myFilter);
function myFilter(item) {
if (item === changeData) {
return;
}
return item;
}
newOrderData.push(fi);
// console.log(orderData.order);
orderData.order = newOrderData;
// console.log(orderData.order);
};
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}
setChangeData={setChangeData}
orderData={orderData}
timeSlotIndex={index} // Pass the index of the time slot
/>
) : (
<p
style={{
height: "90px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
onDragOver={handleDragOver}
onDrop={handleDrop}
tabIndex={cellDate}
></p>
)}
</td>
))}
</tr>
);
rows.push(row);
day = addDays(day, 1);
}
return rows;
};
const handleNextWeek = () => {
setSelectedDateState(addDays(selectedDate, 7));
};
const handlePreviousWeek = () => {
setSelectedDateState(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></th> {/* Empty header cell for labels */}
{[...Array(10)].map((_, index) => (
<th key={index}>t{index + 1}</th>
))}
</tr>
</thead>
<tbody>{generateCalendar()}</tbody>
</table>
</div>
</div>
);
};
export default RunSheetPreview;