diff --git a/package.json b/package.json index 64c8218..06fc1ed 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,11 @@ "version": "0.1.1", "private": true, "dependencies": { + "@fullcalendar/core": "^6.1.15", + "@fullcalendar/daygrid": "^6.1.15", + "@fullcalendar/interaction": "^6.1.15", + "@fullcalendar/react": "^6.1.15", + "@fullcalendar/timegrid": "^6.1.15", "@popperjs/core": "^2.11.8", "@reduxjs/toolkit": "^2.4.0", "@tanstack/react-query": "^5.62.3", @@ -12,11 +17,9 @@ "apexcharts": "^4.1.0", "axios": "^1.7.9", "bootstrap": "^5.3.3", - "dayjs": "^1.11.13", "formik": "^2.4.6", "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 9aa4175..1ec5470 100644 --- a/src/component/calendar/Calendar.jsx +++ b/src/component/calendar/Calendar.jsx @@ -6,19 +6,15 @@ import EventCalendar from "./EventCalendar"; export default function Calendar(){ const [draggedEvent, setDraggedEvent] = useState('undroppable') - const handleDragStart = useCallback((event) => setDraggedEvent(event), []) + const handleDragStart = (event) => { + setDraggedEvent(event) + } - // const dummyEvents = [ - // {id: '1', title: 'Family Vacation', color: 'fc-event-primary', start: new Date('2024-12-18'), end: new Date('2024-12-18'), isAllDay: false, resource: ''}, - // {id: '2', title: 'Meeting In Office', color: 'fc-event-warning', start: new Date('2024-12-19'), end: new Date('2024-12-19'), isAllDay: false, resource: ''}, - // {id: '3', title: 'Client Call', color: 'fc-event-danger', start: new Date('2024-12-20'), end: new Date('2024-12-20'), isAllDay: false, resource: ''}, - // {id: '4', title: 'Interview', color: 'fc-event-success', start: new Date('2024-12-21'), end: new Date('2024-12-21'), isAllDay: false, resource: ''} - // ] const dummyEvents = [ - {id: '1', title: 'Family Vacation', color: 'fc-event-primary', isAllDay: false}, - {id: '2', title: 'Meeting In Office', color: 'fc-event-warning', isAllDay: false}, - {id: '3', title: 'Client Call', color: 'fc-event-danger', isAllDay: false}, - {id: '4', title: 'Interview', color: 'fc-event-success', isAllDay: false} + {id: '1111', title: 'Family Vacation', color: 'fc-event-primary', start: new Date('2025-01-18')}, + {id: '2222', title: 'Meeting In Office', color: 'fc-event-warning', start: new Date('2025-01-19')}, + {id: '3333', title: 'Client Call', color: 'fc-event-danger', start: new Date('2025-01-22')}, + {id: '4444', title: 'Interview', color: 'fc-event-success', start: new Date('2025-01-1')} ] return( @@ -63,6 +59,7 @@ export default function Calendar(){
+ {/* */}
diff --git a/src/component/calendar/EventCalendar.jsx b/src/component/calendar/EventCalendar.jsx index 5d03708..e6a56a6 100644 --- a/src/component/calendar/EventCalendar.jsx +++ b/src/component/calendar/EventCalendar.jsx @@ -1,130 +1,131 @@ -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) +import React, { useCallback, useState } from 'react'; +import { formatDate } from '@fullcalendar/core'; +import FullCalendar from '@fullcalendar/react'; +import dayGridPlugin from '@fullcalendar/daygrid'; +import timeGridPlugin from '@fullcalendar/timegrid'; +import interactionPlugin from '@fullcalendar/interaction'; +import { INITIAL_EVENTS, createEventId } from './event-utils'; export default function EventCalendar({draggedEvent, setDraggedEvent}) { - const myEventsList = [] - const [myEvents, setMyEvents] = useState(myEventsList) + const [weekendsVisible, setWeekendsVisible] = useState(true); + const [currentEvents, setCurrentEvents] = useState(INITIAL_EVENTS); - const moveEvent = useCallback( - ({ event, start, end, isAllDay: droppedOnAllDaySlot = false }) => { - // const { isAllDay } = 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 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] - ) + function handleWeekendsToggle() { + setWeekendsVisible(!weekendsVisible); + } + function handleDateSelect(selectInfo) { + let title = prompt('Please enter a new title for your event'); + // let calendarApi = selectInfo.view.calendar; - const eventPropGetter = useCallback( - (event) => ({ - ...(event.isDraggable - ? { className: 'isDraggable' } - : { className: 'nonDraggable' }), - }), - [] - ) - - const newEvent = useCallback( - (event) => { - setMyEvents((prev) => { - const idList = prev.map((item) => item.id) - const newId = Math.max(...idList) + 1 - // return [...prev, { ...event, id: newId }] - return [...prev, { ...event}] - }) - }, - [setMyEvents] - ) - - const onDropFromOutside = useCallback( - ({ start, end, allDay: isAllDay }) => { - if (draggedEvent === 'undroppable') { - setDraggedEvent(null) - return - } - - const { title, id } = draggedEvent - const event = { - title: title, - start, - end, - isAllDay, - id - } - setDraggedEvent(null) - newEvent(event) - }, - [draggedEvent, setDraggedEvent, 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] + // calendarApi.unselect(); // clear date selection + + if (title) { + // calendarApi.addEvent({ + // id: createEventId(), + // title, + // start: selectInfo.startStr, + // end: selectInfo.endStr, + // allDay: selectInfo.allDay, + // }); + let newEvent = { + id: createEventId(), + title, + start: selectInfo.startStr, + end: selectInfo.endStr, + allDay: selectInfo.allDay, + } + setCurrentEvents(prev => ([...prev, newEvent])) + } + } + +// const onDrop = useCallback( +// (event) => { +// // if (draggedEvent === 'undroppable') { +// // setDraggedEvent(null) +// // return +// // } + +// // let calendarApi; + +// // calendarApi.unselect(); // clear date selection + +// // calendarApi.addEvent({ +// // id: createEventId(), +// // allDay: selectInfo.allDay, +// // end: selectInfo.endStr, +// // start: selectInfo.startStr, +// // title, +// // ...draggedEvent +// // }); + +// // setDraggedEvent(null) +// console.log('EVENT', event) +// }, +// [draggedEvent] +// ) + + const onDrop = + (dropInfo) => { + console.log('dropInfo', dropInfo) + } + + function handleEventClick(clickInfo) { + if ( + confirm( + `Are you sure you want to delete the event '${clickInfo.event.title}'` ) + ) { + clickInfo.event.remove(); + } + } + + function handleEvents(events) { + // setCurrentEvents(events); + } return ( -
- +
+ +
- ) -} \ No newline at end of file + ); +} + +function renderEventContent(eventInfo) { + return ( + <> + {/* {eventInfo.timeText} */} + {eventInfo.event.title} + + ); +} diff --git a/src/component/calendar/EventCalendarOld.jsx b/src/component/calendar/EventCalendarOld.jsx new file mode 100644 index 0000000..5634a54 --- /dev/null +++ b/src/component/calendar/EventCalendarOld.jsx @@ -0,0 +1,138 @@ +// 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}) { +// const myEventsList = [] +// const [myEvents, setMyEvents] = useState(myEventsList) + +// const moveEvent = useCallback( +// ({ event, start, end, isAllDay: droppedOnAllDaySlot = false }) => { +// // const { isAllDay } = 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 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 eventPropGetter = useCallback( +// (event) => ({ +// ...(event.isDraggable +// ? { className: 'isDraggable' } +// : { className: 'nonDraggable' }), +// }), +// [] +// ) + +// const newEvent = useCallback( +// (event) => { +// setMyEvents((prev) => { +// const idList = prev.map((item) => item.id) +// const newId = Math.max(...idList) + 1 +// // return [...prev, { ...event, id: newId }] +// return [...prev, { ...event}] +// }) +// }, +// [setMyEvents] +// ) + +// const onDropFromOutside = useCallback( +// ({ start, end, allDay: isAllDay }) => { +// if (draggedEvent === 'undroppable') { +// setDraggedEvent(null) +// return +// } + +// const { title, id } = draggedEvent +// const event = { +// title: title, +// start, +// end, +// isAllDay, +// id +// } +// setDraggedEvent(null) +// newEvent(event) +// }, +// [draggedEvent, setDraggedEvent, 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 ( +//
+// +//
+// ) +// } + +import React from 'react' + +export default function EventCalendar() { + return ( +
EventCalendar
+ ) +} diff --git a/src/component/calendar/event-utils.js b/src/component/calendar/event-utils.js new file mode 100644 index 0000000..566934c --- /dev/null +++ b/src/component/calendar/event-utils.js @@ -0,0 +1,29 @@ +let eventGuid = 0; +let todayStr = new Date().toISOString().replace(/T.*$/, ''); // YYYY-MM-DD of today + +export const INITIAL_EVENTS = [ + { + id: createEventId(), + title: 'All-day event', + start: new Date('2025-01-19'), + end: new Date('2025-01-20'), + // color: 'blue' + }, + { + id: createEventId(), + title: 'Timed event', + start: todayStr + 'T12:00:00', + // color: 'red' + }, + { + id: createEventId(), + title: 'Timed event 2', + start: new Date('2025-01-25'), + start: new Date('2025-01-26'), + // color: 'blue' + }, +]; + +export function createEventId() { + return String(eventGuid++); +} diff --git a/src/css/style.scss b/src/css/style.scss index 13c9f28..ba10949 100644 --- a/src/css/style.scss +++ b/src/css/style.scss @@ -91,9 +91,6 @@ $btn-bg: #8e54e9; $btn-border: #8e54e9; $event-padding: 10px; -@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; @@ -125,30 +122,29 @@ $event-padding: 10px; /* CALENDER STYLE HERE */ -// .rbc-today{ -// background-color: '#fcf8e3' !important; -// } -.rbc-toolbar button { - background: #eceef3; +.fc-next-button.fc-button, .fc-prev-button.fc-button, +.fc-timeGridWeek-button.fc-button, .fc-timeGridDay-button.fc-button, .fc-dayGridMonth-button.fc-button { + background: #eceef3!important; border: none; color: #a6a9b7 !important; - text-transform: capitalize; - box-shadow: none!important; - text-shadow: none!important; - border-radius: 3px!important; - margin: 0 3px!important; - padding: 6px 12px!important; - height: auto!important; + text-transform: capitalize !important; + // box-shadow: none!important; + // text-shadow: none!important; + // border-radius: 3px!important; + // margin: 0 3px!important; + // padding: 6px 12px!important; + // height: auto!important; } -.rbc-toolbar-label{ - color: black !important; - font-size: 1.5rem; - font-weight: 700; -} -// .rbc-month-view{ -// border: .5px solid #e8edf1!important; -// } -.rbc-toolbar button.rbc-active, .rbc-toolbar button:active, .rbc-toolbar button:hover{ + +.fc-today-button.fc-button, +.fc-timeGridWeek-button.fc-button-active, .fc-timeGridDay-button.fc-button-active, .fc-dayGridMonth-button.fc-button-active{ color: #fff!important; + border: none; + background-color: #8E54E9!important; +} + +.fc-event.fc-event-draggable.fc-event-start.fc-event-end.fc-daygrid-event, +.fc-event.fc-event-draggable.fc-event-start.fc-event-end.fc-daygrid-event{ + padding: 10px 2px !important; } /* END OF CALENDER STYLE */ \ No newline at end of file