我正在尝试使用 React
FullCalendar
组件创建自定义日历。日历可以做CRUD
操作,我的问题是显示发送popup
到requests
的server
窗口。一次显示事件编辑窗口和事件删除窗口,即使我在onClick
事件中设置只显示DeleteEvent组件setIsDeleteModalOpen(true);
和EditEvent隐藏setIsEditModalOpen(false);
两个组件同时显示。
我认为这是因为在这个方法中,如果用户点击事件,它会显示编辑窗口
const handleEventClick = (arg) => {
setSelectedEvent(arg.event);
setIsEditModalOpen(true);
};
那我该如何解决呢?
EditEvent组件:
import React, { useState, useEffect } from "react";
import axios from "axios";
const EditEvent = ({ initialValues, handleUpdate, onClose, isOpen, onReload }) => {
const [id, setId] = useState(initialValues?.id || null);
const [description, setDescription] = useState(initialValues?.description || "");
const [date, setDate] = useState(initialValues?.date || "");
const [errorMessage, setErrorMessage] = useState("");
const handleDescriptionChange = (event) => {
setDescription(event.target.value);
};
const handleDateChange = (event) => {
setDate(event.target.value);
};
const onUpdate = (updatedEvent) => {
axios
.put(`/api/calendar/event/put/${updatedEvent.id}`, updatedEvent)
.then((response) => {
// handle successful response
console.log(response.data);
handleUpdate(response.data);
})
.catch((error) => {
// handle error response
console.log(error);
});
};
const handleSubmit = (event) => {
event.preventDefault();
if (!description) {
setErrorMessage("Please provide a description");
return;
}
const updatedEvent = {
id: initialValues ? initialValues.id : null,
description,
date,
};
console.log(id);
onUpdate(updatedEvent);
onClose();
onReload();
};
return (
<>
{isOpen && (
<div className="fixed z-10 inset-0 overflow-y-auto">
<div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div className="fixed inset-0 transition-opacity" aria-hidden="true">
<div className="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<span className="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
<div className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6">
<div>
<div className="mt-3 text-center sm:mt-0 sm:text-left">
<h3 className="text-lg leading-6 font-medium text-gray-900">Edit Event</h3>
<div className="mt-2">
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label htmlFor="description" className="block text-gray-700 font-bold mb-2">
Description
</label>
<input
type="text"
id="description"
name="description"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
value={description}
onChange={handleDescriptionChange}
maxLength={255}
/>
{errorMessage && (
<p className="text-red-500 text-xs italic mt-2">{errorMessage}</p>
)}
</div>
<div className="mb-4">
<label htmlFor="date" className="block text-gray-700 font-bold mb-2">
Date
</label>
<input
type="date"
id="date"
name="date"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
value={date}
onChange={handleDateChange}
/>
</div>
<div className="flex justify-end">
<button
type="submit"
className="inline-flex justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-500 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
onClick={(event) => handleSubmit(event, id)}
>
Update
</button>
<button
type="button"
className="ml-2 inline-flex justify-center px-4 py-2 border border-gray-300 rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
onClick={onClose}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</>
);
};
export default EditEvent;
删除事件组件
import React from "react";
const DeleteEvent = ({ event, onDelete, isOpen }) => {
const handleDelete = () => {
alert("Deleted");
};
return (
<>
{isOpen && (
<div>
<p>Are you sure you want to delete this event?</p>
<p>{event.description}</p>
<p>{event.date}</p>
<button onClick={handleDelete}>Delete</button>
</div>
)}
</>
);
};
export default DeleteEvent;
import React, { useState, useEffect } from 'react';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import CreateEvent from './CreateEvent';
import EditEvent from './EditEvent';
import DeleteEvent from './DeleteEvent';
import axios from 'axios';
function FullComponent() {
const [events, setEvents] = useState([]);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [selectedDate, setSelectedDate] = useState(null);
const [selectedEvent, setSelectedEvent] = useState(null);
const updateEvents = (updatedEvent) => {
setEvents((prevEvents) =>
prevEvents.map((event) => (event.id === updatedEvent.id ? updatedEvent : event))
);
};
const handleDateClick = (arg) => {
setSelectedDate(arg.date);
setIsCreateModalOpen(true);
};
const handleEventClick = (arg) => {
setSelectedEvent(arg.event);
setIsEditModalOpen(true);
};
const handleEventAdded = (event) => {
setEvents([...events, event]);
setIsCreateModalOpen(false);
};
const handleEventEdited = (event) => {
const newEvents = events.map((e) => {
if (e.id === event.id) {
return { ...e, ...event };
}
return e;
});
setEvents(newEvents);
setIsEditModalOpen(false);
};
const handleEventDeleted = (event) => {
const newEvents = events.filter((e) => e.id !== event.id);
setEvents(newEvents);
setIsDeleteModalOpen(false);
};
const handleReload = () => {
axios.get('/api/calendar/events').then((response) => {
const mappedEvents = response.data.map((event) => ({
id: event.id,
title: event.description, // Use description as the event title
start: new Date(event.date),
allDay: true
}));
setEvents(mappedEvents);
})
}
useEffect(() => {
// Fetch events from API endpoint and map them to FullCalendar event objects
axios.get('/api/calendar/events').then((response) => {
const mappedEvents = response.data.map((event) => ({
id: event.id,
title: event.description, // Use description as the event title
start: new Date(event.date),
allDay: true
}));
setEvents(mappedEvents);
});
}, []);
const renderEventContent = (eventInfo) => {
// Render the event title and description
return (
<>
<b>{eventInfo.timeText}</b>
<p>{eventInfo.event.title}</p>
<button onClick={() => {
setSelectedEvent(eventInfo.event);
setIsDeleteModalOpen(true);
setIsEditModalOpen(false);
}}>X</button>
</>
);
};
return (
<>
<FullCalendar
plugins={[dayGridPlugin, interactionPlugin]}
initialView="dayGridMonth"
dateClick={handleDateClick}
eventClick={handleEventClick}
events={events}
eventContent={renderEventContent} // Use custom event renderer
/>
{isCreateModalOpen && (
<CreateEvent
isOpen={isCreateModalOpen}
onClose={() => setIsCreateModalOpen(false)}
date={selectedDate}
onEventAdded={handleEventAdded}
/>
)}
{isEditModalOpen && selectedEvent &&(
<EditEvent
isOpen={isEditModalOpen}
onClose={() => setIsEditModalOpen(false)}
initialValues={selectedEvent}
onEventEdited={handleEventEdited}
handleUpdate={updateEvents}
onReload={handleReload}
/>
)}
{isDeleteModalOpen && (
<DeleteEvent
isOpen={isDeleteModalOpen}
onClose={() => setIsDeleteModalOpen(false)}
event={selectedEvent}
onEventDeleted={handleEventDeleted}
/>
)}
</>
);
}
export default FullComponent;