拖放框显示停止标志

问题描述 投票:0回答:1

我希望能够将可拖动框拖放到任何其他日期,并且它应该删除前一个日期。 例如,如果我将拖动框从 3 月 5 日移动到 3 月 6 日,它应该从 3 月 5 日删除并更新到 3 月 6 日 我的问题是,当我拖放此框时,它显示一个停止标志,我无法移动它。有什么方法可以修复它或任何其他方法,以便我可以将我的框及其数据移动到另一个日期(当您将鼠标悬停在拖动框上时,有一些数据名称和 subrub 吗?

我的 runsheetpreview.js 代码

import React, { useState, useRef } from "react";
import { startOfMonth, endOfMonth, startOfWeek, endOfWeek, format, addDays, addMonths, subMonths, isSameMonth } from "date-fns";
import "../assets/css/RunSheetPDF.css";

const DraggableBox = ({ day, onDrop, name: initialName, suburb: initialSuburb }) => {
  const [editable, setEditable] = useState(false);
  const [name, setName] = useState(initialName);
  const [suburb, setSuburb] = useState(initialSuburb);
  const [showTooltip, setShowTooltip] = useState(false);
  const boxRef = useRef(null);

  const handleDoubleClick = () => {
    setEditable(true);
  };

  const handleChangeName = (e) => {
    setName(e.target.value);
  };

  const handleChangeSuburb = (e) => {
    setSuburb(e.target.value);
  };

  const handleBlur = () => {
    setEditable(false);
  };

  const handleDragStart = () => {
    setShowTooltip(false);
    boxRef.current.classList.add('dragging');
  };

  const handleDragEnd = () => {
    boxRef.current.classList.remove('dragging');
  };

  const handleDragOver = (e) => {
    e.preventDefault();
  };

  const handleDrop = (e) => {
    e.preventDefault();
    const draggedDay = parseInt(e.dataTransfer.getData("text/plain"));
    onDrop(draggedDay, day);
  };

  return (
    <div
      className="drag-box"
      ref={boxRef}
      draggable
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
      onDoubleClick={handleDoubleClick}
      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
      }}
    >
      <p style={{ margin: 0, lineHeight: "80px" }}>{day}</p>
      {showTooltip && (
        <div className="tooltip">
          <p>Name: {name}</p>
          <p>Suburb: {suburb}</p>
        </div>
      )}
    </div>
  );
};

const RunSheetPreview = () => {
  const [selectedDate, setSelectedDate] = useState(new Date());
  const [calendarData, setCalendarData] = useState([
    { day: 5, name: "John", suburb: "Suburb 1" },
    { day: 15, name: "Alice", suburb: "Suburb 2" },
    { day: 25, name: "Bob", suburb: "Suburb 3" },
    { day: 27, name: "Eva", suburb: "Suburb 4" }
  ]);

  const handleDrop = (draggedDay, dropDay) => {
    const newData = [...calendarData];
    const draggedItem = newData.find(item => item.day === draggedDay);
    draggedItem.day = dropDay;
    setCalendarData(newData);
  };

  const generateCalendar = () => {
    const monthStart = startOfMonth(selectedDate);
    const monthEnd = endOfMonth(selectedDate);
    const startDate = startOfWeek(monthStart, { weekStartsOn: 0 });
    const endDate = endOfWeek(monthEnd, { weekStartsOn: 0 });

    const rows = [];
    let days = [];
    let day = startDate;

    while (day <= endDate) {
      for (let i = 0; i < 7; i++) {
        const dayOfMonth = format(day, "d");
        const isCurrentMonth = isSameMonth(day, monthStart);
        const draggableData = calendarData.find(item => item.day === parseInt(dayOfMonth));
        const draggableBoxExists = draggableData !== undefined;

        days.push(
          <td key={day} style={{ width: "70px", height: "80px" }}>
            {isCurrentMonth && (
              <div>
                {draggableBoxExists ? (
                  <DraggableBox
                    day={draggableData.day}
                    name={draggableData.name}
                    suburb={draggableData.suburb}
                    onDrop={handleDrop}
                  />
                ) : (
                  <p>{dayOfMonth}</p>
                )}
              </div>
            )}
          </td>
        );
        day = addDays(day, 1);
      }
      rows.push(<tr key={day}>{days}</tr>);
      days = [];
    }

    return rows;
  };

  const handleNextMonth = () => {
    setSelectedDate(addMonths(selectedDate, 1));
  };

  const handlePreviousMonth = () => {
    setSelectedDate(subMonths(selectedDate, 1));
  };

  return (
    <div style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "center", marginTop: "20px" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "0px" }}>
        <button onClick={handlePreviousMonth} style={{ backgroundColor: "#F5F5F5", color: "#333333", border: "1px solid #CCCCCC", borderRadius: "5px", padding: "5px 10px", marginRight: "10px" }}>Previous Month</button>
        <h2 style={{ color: "#333333", margin: 0 }}>{format(selectedDate, "MMMM yyyy")}</h2>
        <button onClick={handleNextMonth} style={{ backgroundColor: "#F5F5F5", color: "#333333", border: "1px solid #CCCCCC", borderRadius: "5px", padding: "5px 10px", marginLeft: "10px" }}>Next Month</button>
      </div>
      <div className="calendar-container">
        <table className="calendar-table">
          <thead>
            <tr>
              <th>Sun</th>
              <th>Mon</th>
              <th>Tue</th>
              <th>Wed</th>
              <th>Thu</th>
              <th>Fri</th>
              <th>Sat</th>
            </tr>
          </thead>
          <tbody>
            {generateCalendar()}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default RunSheetPreview;

我的 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;
  text-align: center;
}

.calendar-table p {
  margin: 0;
}
.drag-box {
  cursor: pointer;
  border: 1px solid #ccc;
  border-radius: 5px;
  padding: 5px;
  margin: 2px;
  position: relative; /* Add relative positioning */
}

.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 */
}

.drag-box:hover .tooltip {
  visibility: visible; /* Show tooltip on hover */
}
javascript node.js calendar drag-and-drop draggable
1个回答
0
投票

所以,我对您的代码做了一些更改。所以我想要理解的是,首先,如果我将一个可拖动框拖到其他框上(比如说第 5 个框超过第 15 个框,那么第 15 个框中的任何数据都将被第 5 个框数据替换,之后第 5 个框数据也将被删除),所以对于我已将一些附加状态作为道具传递给可拖动框组件(calenddarData、changeName、changeDay、changeSuburb states)。 然后在 Draggablebox 组件中声明的handleDragStart 和handleDrop 函数也都被更新。在handleDragStart中,每当开始拖动时,我都会将拖动的元素数据保存在changeName、changeDay、changeSuburb状态中。 然后在handleDrop中,我首先检查拖动的元素是否在同一日期被删除,如果不是,那么我只是更新calendarData。解决了第一个问题。 现在,对于第二个问题,即在没有自己的可拖动框的日期上放置可拖动框(例如在第 6 个日期拖动第 5 个框),使用相同的逻辑,只是我已将handleDragStart、handDrop、handleDragOver 传递给 p 标记。您应该在 RunSheetPreview 组件中定义这些函数。由于这些组件被重用,您可以将它们作为 props 传递给 Draggable box 组件。

import { useState, useRef } from "react";
import { startOfMonth, endOfMonth, startOfWeek, endOfWeek, format, addDays, addMonths, subMonths, isSameMonth } from "date-fns";
import "./RunSheetPDF.css";

const DraggableBox = ({ day, name: initialName, suburb: initialSuburb, calendarData, setCalendarData, 
  changeName, setChangeName, changeSuburb, setChangeSuburb, setChangeDay, changeDay }) => {

  //eslint-disable-next-line
  const [editable, setEditable] = useState(false);
  const [name, setName] = useState(initialName);
  const [suburb, setSuburb] = useState(initialSuburb);
  const [showTooltip, setShowTooltip] = useState(false);
  const boxRef = useRef(null);

  const handleDoubleClick = () => {
    setEditable(true);
  };
//eslint-disable-next-line
  const handleChangeName = (e) => {
    setName(e.target.value);
  };
//eslint-disable-next-line
  const handleChangeSuburb = (e) => {
    setSuburb(e.target.value);
  };
//eslint-disable-next-line
  const handleBlur = () => {
    setEditable(false);
  };

  const handleDragStart = () => {
    setShowTooltip(false);
    setChangeName(initialName);
    setChangeSuburb(initialSuburb)
    setChangeDay(day)
    boxRef.current.classList.add('dragging');
  };

  const handleDragEnd = () => {
    boxRef.current.classList.remove('dragging');
  };

  const handleDragOver = (e) => {
    e.preventDefault();
  };

  const handleDrop = (e) => {
    e.preventDefault();
    e.stopPropagation();
    if(Number(changeDay) !== Number(e.target.innerText)){
      const newData = {
        day: Number(e.target.innerText),
        name: changeName,
        suburb: changeSuburb,
      }
      const newCalData = [...calendarData];
      const calData = newCalData.filter((f) => Number(f.day) !== Number(e.target.innerText) && Number(f.day) !== Number(changeDay) );
      calData.push(newData);
      calData.sort((a,b) => Number(a.day) - Number(b.day))
      setCalendarData(calData)
      setChangeDay(null);
      setChangeName(null);
      setChangeSuburb(null);
    }
  };

  return (
    <div
      className="drag-box"
      ref={boxRef}
      draggable
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
      onDoubleClick={handleDoubleClick}
      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
      }}
    >
      <p style={{ margin: 0, lineHeight: "80px" }}>{day}</p>
      {showTooltip && (
        <div className="tooltip">
          <p>Name: {initialName}</p>
          <p>Suburb: {initialSuburb}</p>
        </div>
      )}
    </div>   
  );
};

const RunSheetPreview = () => {
  const [selectedDate, setSelectedDate] = useState(new Date());
  const [calendarData, setCalendarData] = useState([
    { day: 5, name: "John", suburb: "Suburb 1" },
    { day: 15, name: "Alice", suburb: "Suburb 2" },
    { day: 25, name: "Bob", suburb: "Suburb 3" },
    { day: 27, name: "Eva", suburb: "Suburb 4" }
  ]);
  const boxRef = useRef(null);
  const [changeName, setChangeName] = useState("");
  const [changeDay, setChangeDay] = useState(null);
  const [changeSuburb, setChangeSuburb] = useState(null);

  const handleDragStart = () => {
    setShowTooltip(false);
    setChangeName(initialName);
    setChangeSuburb(initialSuburb)
    setChangeDay(day)
    boxRef.current.classList.add('dragging');
  };

  const handleDragOver = (e) => {
    e.preventDefault();
  };

  const handleDrop = (e) => {
    e.preventDefault();
    e.stopPropagation();
    if(Number(changeDay) !== Number(e.target.innerText)){
      const newData = {
        day: Number(e.target.innerText),
        name: changeName,
        suburb: changeSuburb,
      }
      const newCalData = [...calendarData];
      const calData = newCalData.filter((f) => Number(f.day) !== Number(e.target.innerText) && Number(f.day) !== Number(changeDay) );
      calData.push(newData);
      calData.sort((a,b) => Number(a.day) - Number(b.day))
      setCalendarData(calData)
      setChangeDay(null);
      setChangeName(null);
      setChangeSuburb(null);
    }
  };

  const generateCalendar = () => {
    const monthStart = startOfMonth(selectedDate);
    const monthEnd = endOfMonth(selectedDate);
    const startDate = startOfWeek(monthStart, { weekStartsOn: 0 });
    const endDate = endOfWeek(monthEnd, { weekStartsOn: 0 });

    const rows = [];
    let days = [];
    let day = startDate;

    while (day <= endDate) {
      for (let i = 0; i < 7; i++) {
        const dayOfMonth = format(day, "d");
        const isCurrentMonth = isSameMonth(day, monthStart);
        const draggableData = calendarData.find(item => item.day === parseInt(dayOfMonth));
        const draggableBoxExists = draggableData;

        days.push(
          <td key={day} style={{ width: "70px", height: "80px" }}>
            {isCurrentMonth && (
              <div
              >
                {draggableBoxExists ? (
                  <DraggableBox
                    day={draggableData.day}
                    name={draggableData.name}
                    suburb={draggableData.suburb}
                    setCalendarData={setCalendarData}
                    calendarData={calendarData}
                    changeName={changeName}
                    setChangeName={setChangeName}
                    changeDay={changeDay}
                    setChangeDay={setChangeDay}
                    changeSuburb={changeSuburb}
                    setChangeSuburb={setChangeSuburb}
                  />
                ) : (
                  <p
                    style={{
                      height: "100px",
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                    }}
                    ref={boxRef}
                    onDragStart={handleDragStart}
                    onDragOver={handleDragOver}
                    onDrop={handleDrop}
                  >
                    {dayOfMonth}
                  </p>
                )}
              </div>
            )}
          </td>
        );
        day = addDays(day, 1);
      }
      rows.push(<tr key={day}>{days}</tr>);
      days = [];
    }

    return rows;
  };

  const handleNextMonth = () => {
    setSelectedDate(addMonths(selectedDate, 1));
  };

  const handlePreviousMonth = () => {
    setSelectedDate(subMonths(selectedDate, 1));
  };

  return (
    <div style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "center", marginTop: "20px" }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "center", marginBottom: "0px" }}>
        <button onClick={handlePreviousMonth} style={{ backgroundColor: "#F5F5F5", color: "#333333", border: "1px solid #CCCCCC", borderRadius: "5px", padding: "5px 10px", marginRight: "10px" }}>Previous Month</button>
        <h2 style={{ color: "#333333", margin: 0 }}>{format(selectedDate, "MMMM yyyy")}</h2>
        <button onClick={handleNextMonth} style={{ backgroundColor: "#F5F5F5", color: "#333333", border: "1px solid #CCCCCC", borderRadius: "5px", padding: "5px 10px", marginLeft: "10px" }}>Next Month</button>
      </div>
      <div className="calendar-container">
        <table className="calendar-table">
          <thead>
            <tr>
              <th>Sun</th>
              <th>Mon</th>
              <th>Tue</th>
              <th>Wed</th>
              <th>Thu</th>
              <th>Fri</th>
              <th>Sat</th>
            </tr>
          </thead>
          <tbody>
            {generateCalendar()}
          </tbody>
        </table>
      </div>
    </div>
  );
};

export default RunSheetPreview;
© www.soinside.com 2019 - 2024. All rights reserved.