はじめに
今回はリサイズイベントを学んでいこうと思います!
前回までの記事の続きになります
成果物
ソースコード
src/App.tsx
import { useState } from "react";
import { Calendar, dateFnsLocalizer } from "react-big-calendar";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import withDragAndDrop from "react-big-calendar/lib/addons/dragAndDrop";
import { format, parse, startOfWeek, getDay } from "date-fns";
import { ja } from "date-fns/locale";
import "react-big-calendar/lib/css/react-big-calendar.css";
import "react-big-calendar/lib/addons/dragAndDrop/styles.css";
// DnD対応カレンダーに拡張
const DragAndDropCalendar = withDragAndDrop(Calendar);
// date-fns ローカライザー設定
const locales = {
ja: ja,
};
const localizer = dateFnsLocalizer({
format,
parse,
startOfWeek,
getDay,
locales,
locale: "ja",
});
type EventType = {
id: number;
title: string;
start: Date;
end: Date;
};
const initialEvents: EventType[] = [
{
id: 0,
title: "会議A",
start: new Date(),
end: new Date(new Date().getTime() + 60 * 60 * 1000), // +1時間
},
];
type EventDropArgs = {
event: EventType;
start: Date;
end: Date;
};
export default function App() {
const [events, setEvents] = useState<EventType[]>(initialEvents);
const [showDialog, setShowDialog] = useState(false);
const [resizedEvent, setResizedEvent] = useState<EventType | null>(null);
const onEventDrop = ({ event, start, end }: EventDropArgs) => {
const updated = events.map((e) =>
e.id === event.id ? { ...e, start, end } : e,
);
setEvents(updated);
};
const handleResizeWithDialog = ({ event, start, end }: EventDropArgs) => {
const updated = events.map((e) =>
e.id === event.id ? { ...e, start, end } : e,
);
setEvents(updated);
setResizedEvent({ ...event, start, end });
setShowDialog(true);
};
return (
<DndProvider backend={HTML5Backend}>
<div style={{ height: "100vh", padding: 20 }}>
<DragAndDropCalendar
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
onEventDrop={onEventDrop}
resizable
onEventResize={handleResizeWithDialog}
style={{ height: "100%" }}
/>
{showDialog && resizedEvent && (
<div
style={{
position: "absolute",
top: "30%",
left: "30%",
padding: 20,
background: "white",
border: "1px solid #ccc",
boxShadow: "0 2px 10px rgba(0,0,0,0.3)",
zIndex: 1000,
}}
>
<p>「{resizedEvent.title}」の時間を変更しました。</p>
<button type="button" onClick={() => setShowDialog(false)}>
閉じる
</button>
</div>
)}
</div>
</DndProvider>
);
}