calendar fix started

This commit is contained in:
victorAnumudu
2025-01-17 23:21:38 +01:00
parent 4079d27017
commit 7d7a15e386
6 changed files with 321 additions and 157 deletions
+5 -2
View File
@@ -3,6 +3,11 @@
"version": "0.1.1", "version": "0.1.1",
"private": true, "private": true,
"dependencies": { "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", "@popperjs/core": "^2.11.8",
"@reduxjs/toolkit": "^2.4.0", "@reduxjs/toolkit": "^2.4.0",
"@tanstack/react-query": "^5.62.3", "@tanstack/react-query": "^5.62.3",
@@ -12,11 +17,9 @@
"apexcharts": "^4.1.0", "apexcharts": "^4.1.0",
"axios": "^1.7.9", "axios": "^1.7.9",
"bootstrap": "^5.3.3", "bootstrap": "^5.3.3",
"dayjs": "^1.11.13",
"formik": "^2.4.6", "formik": "^2.4.6",
"react": "^18.3.1", "react": "^18.3.1",
"react-apexcharts": "^1.7.0", "react-apexcharts": "^1.7.0",
"react-big-calendar": "^1.17.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-icons": "^5.4.0", "react-icons": "^5.4.0",
"react-redux": "^9.1.2", "react-redux": "^9.1.2",
+8 -11
View File
@@ -6,19 +6,15 @@ import EventCalendar from "./EventCalendar";
export default function Calendar(){ export default function Calendar(){
const [draggedEvent, setDraggedEvent] = useState('undroppable') 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 = [ const dummyEvents = [
{id: '1', title: 'Family Vacation', color: 'fc-event-primary', isAllDay: false}, {id: '1111', title: 'Family Vacation', color: 'fc-event-primary', start: new Date('2025-01-18')},
{id: '2', title: 'Meeting In Office', color: 'fc-event-warning', isAllDay: false}, {id: '2222', title: 'Meeting In Office', color: 'fc-event-warning', start: new Date('2025-01-19')},
{id: '3', title: 'Client Call', color: 'fc-event-danger', isAllDay: false}, {id: '3333', title: 'Client Call', color: 'fc-event-danger', start: new Date('2025-01-22')},
{id: '4', title: 'Interview', color: 'fc-event-success', isAllDay: false} {id: '4444', title: 'Interview', color: 'fc-event-success', start: new Date('2025-01-1')}
] ]
return( return(
@@ -63,6 +59,7 @@ export default function Calendar(){
</div> </div>
<div className="col-xl-9"> <div className="col-xl-9">
<div className="event-calendar"> <div className="event-calendar">
{/* <EventCalendar draggedEvent={draggedEvent} setDraggedEvent={setDraggedEvent} /> */}
<EventCalendar draggedEvent={draggedEvent} setDraggedEvent={setDraggedEvent} /> <EventCalendar draggedEvent={draggedEvent} setDraggedEvent={setDraggedEvent} />
</div> </div>
</div> </div>
+121 -120
View File
@@ -1,130 +1,131 @@
import React, { useCallback, useState } from 'react' import React, { useCallback, useState } from 'react';
import { Calendar, dayjsLocalizer } from 'react-big-calendar' import { formatDate } from '@fullcalendar/core';
import dayjs from 'dayjs' import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop' import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
import { INITIAL_EVENTS, createEventId } from './event-utils';
const localizer = dayjsLocalizer(dayjs)
const DnDCalendar = withDragAndDrop(Calendar)
export default function EventCalendar({draggedEvent, setDraggedEvent}) { export default function EventCalendar({draggedEvent, setDraggedEvent}) {
const myEventsList = [] const [weekendsVisible, setWeekendsVisible] = useState(true);
const [myEvents, setMyEvents] = useState(myEventsList) const [currentEvents, setCurrentEvents] = useState(INITIAL_EVENTS);
const moveEvent = useCallback( function handleWeekendsToggle() {
({ event, start, end, isAllDay: droppedOnAllDaySlot = false }) => { setWeekendsVisible(!weekendsVisible);
// 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 handleDateSelect(selectInfo) {
let title = prompt('Please enter a new title for your event');
// let calendarApi = selectInfo.view.calendar;
const eventPropGetter = useCallback( // calendarApi.unselect(); // clear date selection
(event) => ({
...(event.isDraggable if (title) {
? { className: 'isDraggable' } // calendarApi.addEvent({
: { className: 'nonDraggable' }), // id: createEventId(),
}), // title,
[] // start: selectInfo.startStr,
) // end: selectInfo.endStr,
// allDay: selectInfo.allDay,
const newEvent = useCallback( // });
(event) => { let newEvent = {
setMyEvents((prev) => { id: createEventId(),
const idList = prev.map((item) => item.id) title,
const newId = Math.max(...idList) + 1 start: selectInfo.startStr,
// return [...prev, { ...event, id: newId }] end: selectInfo.endStr,
return [...prev, { ...event}] allDay: selectInfo.allDay,
}) }
}, setCurrentEvents(prev => ([...prev, newEvent]))
[setMyEvents] }
) }
const onDropFromOutside = useCallback( // const onDrop = useCallback(
({ start, end, allDay: isAllDay }) => { // (event) => {
if (draggedEvent === 'undroppable') { // // if (draggedEvent === 'undroppable') {
setDraggedEvent(null) // // setDraggedEvent(null)
return // // return
} // // }
const { title, id } = draggedEvent // // let calendarApi;
const event = {
title: title, // // calendarApi.unselect(); // clear date selection
start,
end, // // calendarApi.addEvent({
isAllDay, // // id: createEventId(),
id // // allDay: selectInfo.allDay,
} // // end: selectInfo.endStr,
setDraggedEvent(null) // // start: selectInfo.startStr,
newEvent(event) // // title,
}, // // ...draggedEvent
[draggedEvent, setDraggedEvent, newEvent] // // });
)
// // setDraggedEvent(null)
const resizeEvent = useCallback( // console.log('EVENT', event)
({ event, start, end }) => { // },
setMyEvents((prev) => { // [draggedEvent]
const existing = prev.find((ev) => ev.id === event.id) ?? {} // )
const filtered = prev.filter((ev) => ev.id !== event.id)
return [...filtered, { ...existing, start, end }] const onDrop =
}) (dropInfo) => {
}, console.log('dropInfo', dropInfo)
[setMyEvents] }
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 ( return (
<div className='w-100'> <div className="demo-app">
<DnDCalendar <div className="demo-app-main">
dragFromOutsideItem={ <FullCalendar
displayDragItemInCell ? dragFromOutsideItem : null plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
} headerToolbar={{
eventPropGetter={eventPropGetter} left: 'prev next today',
// draggableAccessor="isDraggable" center: 'title',
localizer={localizer} right: 'dayGridMonth,timeGridWeek,timeGridDay',
events={myEvents} }}
startAccessor="start" initialView="dayGridMonth"
endAccessor="end" editable={true}
style={{ height: 500 }} selectable={true}
// onEventResize={resizeEvent} selectMirror={true}
resizable dayMaxEvents={true}
onEventDrop={moveEvent} weekends={weekendsVisible}
onDropFromOutside={onDropFromOutside} // initialEvents={INITIAL_EVENTS} // alternatively, use the `events` setting to fetch from a feed
// onDragOverFromOutside={customOnDragOverFromOutside} events={currentEvents}
select={handleDateSelect}
eventContent={renderEventContent} // custom render function
eventClick={handleEventClick}
eventsSet={handleEvents} // called after events are initialized/added/changed/removed
/* you can update a remote database when these fire:
eventAdd={function(){}}
eventChange={function(){}}
eventRemove={function(){}}
*/
dropAccept= '.fc-event'
droppable= {true} // this allows things to be dropped onto the calendar
drop= {onDrop}
/> />
</div>
</div> </div>
) );
} }
function renderEventContent(eventInfo) {
return (
<>
{/* <b>{eventInfo.timeText}</b> */}
<i>{eventInfo.event.title}</i>
</>
);
}
+138
View File
@@ -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 (
// <div className='w-100'>
// <DnDCalendar
// dragFromOutsideItem={
// displayDragItemInCell ? dragFromOutsideItem : null
// }
// eventPropGetter={eventPropGetter}
// // draggableAccessor="isDraggable"
// localizer={localizer}
// events={myEvents}
// startAccessor="start"
// endAccessor="end"
// style={{ height: 500 }}
// // onEventResize={resizeEvent}
// resizable
// onEventDrop={moveEvent}
// onDropFromOutside={onDropFromOutside}
// // onDragOverFromOutside={customOnDragOverFromOutside}
// />
// </div>
// )
// }
import React from 'react'
export default function EventCalendar() {
return (
<div>EventCalendar</div>
)
}
+29
View File
@@ -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++);
}
+20 -24
View File
@@ -91,9 +91,6 @@ $btn-bg: #8e54e9;
$btn-border: #8e54e9; $btn-border: #8e54e9;
$event-padding: 10px; $event-padding: 10px;
@import 'react-big-calendar/lib/sass/styles';
@import 'react-big-calendar/lib/addons/dragAndDrop/styles'; // if using DnD
.extraProductCard{ .extraProductCard{
background-color: aliceblue; background-color: aliceblue;
border-radius: 5px; border-radius: 5px;
@@ -125,30 +122,29 @@ $event-padding: 10px;
/* CALENDER STYLE HERE */ /* CALENDER STYLE HERE */
// .rbc-today{ .fc-next-button.fc-button, .fc-prev-button.fc-button,
// background-color: '#fcf8e3' !important; .fc-timeGridWeek-button.fc-button, .fc-timeGridDay-button.fc-button, .fc-dayGridMonth-button.fc-button {
// } background: #eceef3!important;
.rbc-toolbar button {
background: #eceef3;
border: none; border: none;
color: #a6a9b7 !important; color: #a6a9b7 !important;
text-transform: capitalize; text-transform: capitalize !important;
box-shadow: none!important; // box-shadow: none!important;
text-shadow: none!important; // text-shadow: none!important;
border-radius: 3px!important; // border-radius: 3px!important;
margin: 0 3px!important; // margin: 0 3px!important;
padding: 6px 12px!important; // padding: 6px 12px!important;
height: auto!important; // height: auto!important;
} }
.rbc-toolbar-label{
color: black !important; .fc-today-button.fc-button,
font-size: 1.5rem; .fc-timeGridWeek-button.fc-button-active, .fc-timeGridDay-button.fc-button-active, .fc-dayGridMonth-button.fc-button-active{
font-weight: 700;
}
// .rbc-month-view{
// border: .5px solid #e8edf1!important;
// }
.rbc-toolbar button.rbc-active, .rbc-toolbar button:active, .rbc-toolbar button:hover{
color: #fff!important; 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 */ /* END OF CALENDER STYLE */