diff --git a/package.json b/package.json index 2084336..0f1052d 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "apexcharts": "^4.1.0", "axios": "^1.7.9", "bootstrap": "^5.3.3", + "dayjs": "^1.11.13", "react": "^18.3.1", "react-apexcharts": "^1.7.0", + "react-big-calendar": "^1.17.0", "react-dom": "^18.3.1", "react-icons": "^5.4.0", "react-redux": "^9.1.2", diff --git a/src/component/calendar/Calendar.jsx b/src/component/calendar/Calendar.jsx index 034c38e..619edb6 100644 --- a/src/component/calendar/Calendar.jsx +++ b/src/component/calendar/Calendar.jsx @@ -1,9 +1,22 @@ -import React from "react"; +import React, { useCallback, useState } from "react"; import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS"; +import EventCalendar from "./EventCalendar"; export default function Calendar(){ + const [draggedEvent, setDraggedEvent] = useState() + const handleDragStart = useCallback((event) => setDraggedEvent(event), []) + + const formatName = (name) => `${name}` + + const dummyEvents = [ + {id: '1', name: 'Family Vacation', color: 'fc-event-primary'}, + {id: '2', name: 'Meeting In Office', color: 'fc-event-warning'}, + {id: '3', name: 'Client Call', color: 'fc-event-danger'}, + {id: '4', name: 'Interview', color: 'fc-event-success'} + ] + return( <> @@ -26,20 +39,16 @@ export default function Calendar(){

Drag and drop your event or click in the calendar.

-
- Family - Vacation -
-
- Meeting In - Office -
-
- Client Call -
-
- Interview -
+ {dummyEvents.map(item => ( +
+ handleDragStart({ title: formatName(item.name)}) + } + > + {item.name} +
+ ))}
@@ -51,7 +60,7 @@ export default function Calendar(){
-
+
diff --git a/src/component/calendar/EventCalendar.jsx b/src/component/calendar/EventCalendar.jsx new file mode 100644 index 0000000..950432a --- /dev/null +++ b/src/component/calendar/EventCalendar.jsx @@ -0,0 +1,133 @@ +import React, { useCallback, useState } from 'react' +import { Calendar, dayjsLocalizer } from 'react-big-calendar' +import dayjs from 'dayjs' + +import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop' + + + +const localizer = dayjsLocalizer(dayjs) + +const DnDCalendar = withDragAndDrop(Calendar) + +export default function EventCalendar({draggedEvent, setDraggedEvent, formatName}) { + const myEventsList = [] + const [myEvents, setMyEvents] = useState(myEventsList) + + const moveEvent = useCallback( + ({ event, start, end, isAllDay: droppedOnAllDaySlot = false }) => { + const { allDay } = event + if (!allDay && droppedOnAllDaySlot) { + event.allDay = true + } + if (allDay && !droppedOnAllDaySlot) { + event.allDay = false; + } + + setMyEvents((prev) => { + const existing = prev.find((ev) => ev.id === event.id) ?? {} + const filtered = prev.filter((ev) => ev.id !== event.id) + return [...filtered, { ...existing, start, end, allDay: event.allDay }] + }) + }, + [setMyEvents] + ) + + const [displayDragItemInCell, setDisplayDragItemInCell] = useState(true) + const [counters, setCounters] = useState({ item1: 0, item2: 0 }) + + const eventPropGetter = useCallback( + (event) => ({ + ...(event.isDraggable + ? { className: 'isDraggable' } + : { className: 'nonDraggable' }), + }), + [] + ) + + const dragFromOutsideItem = useCallback(() => draggedEvent === 'undroppable' ? null : draggedEvent, [draggedEvent]) + + const customOnDragOverFromOutside = useCallback( + (dragEvent) => { + // check for undroppable is specific to this example + // and not part of API. This just demonstrates that + // onDragOver can optionally be passed to conditionally + // allow draggable items to be dropped on cal, based on + // whether event.preventDefault is called + if (draggedEvent !== 'undroppable') { + console.log('preventDefault') + dragEvent.preventDefault() + } + }, + [draggedEvent] + ) + + const newEvent = useCallback( + (event) => { + setMyEvents((prev) => { + const idList = prev.map((item) => item.id) + const newId = Math.max(...idList) + 1 + return [...prev, { ...event, id: newId }] + }) + }, + [setMyEvents] + ) + + const onDropFromOutside = useCallback( + ({ start, end, allDay: isAllDay }) => { + if (draggedEvent === 'undroppable') { + setDraggedEvent(null) + return + } + + const { name } = draggedEvent + const event = { + title: formatName(name, counters[name]), + start, + end, + isAllDay, + } + setDraggedEvent(null) + setCounters((prev) => { + const { [name]: count } = prev + return { + ...prev, + [name]: count + 1, + } + }) + newEvent(event) + }, + [draggedEvent, counters, setDraggedEvent, setCounters, newEvent] + ) + + const resizeEvent = useCallback( + ({ event, start, end }) => { + setMyEvents((prev) => { + const existing = prev.find((ev) => ev.id === event.id) ?? {} + const filtered = prev.filter((ev) => ev.id !== event.id) + return [...filtered, { ...existing, start, end }] + }) + }, + [setMyEvents] + ) + + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/src/css/style.scss b/src/css/style.scss index 9cdabc6..ff59fe4 100644 --- a/src/css/style.scss +++ b/src/css/style.scss @@ -83,6 +83,10 @@ @import "pages/employees"; @import "pages/coming-soon"; +// THIS IMPORTS ARE FOR THE CALENDAR PACKAGE - PLEASE DO NOT REMOVE +@import 'react-big-calendar/lib/sass/styles'; +@import 'react-big-calendar/lib/addons/dragAndDrop/styles'; // if using DnD + .extraProductCard{ background-color: aliceblue; border-radius: 5px;