Files
worldshine-redesign/client/src/components/center-calendar/CenterCalendar.js
2026-02-09 15:53:03 -05:00

1254 lines
54 KiB
JavaScript

import React, {useState, useEffect, useRef, useCallback} from "react";
import { useNavigate } from "react-router-dom";
import { AuthService, EventsService, CustomerService, ResourceService, VehicleService, EmployeeService } from "../../services";
import moment from 'moment';
import { Breadcrumb, Tabs, Tab, Button, Modal, Dropdown } from "react-bootstrap";
import { useCalendarApp, ScheduleXCalendar } from '@schedule-x/react';
import {
viewMonthGrid,
createViewDay,
createViewWeek,
createViewMonthGrid
} from '@schedule-x/calendar';
import { createEventsServicePlugin } from '@schedule-x/events-service';
import { createEventModalPlugin} from '@schedule-x/event-modal';
import { createEventRecurrencePlugin } from "@schedule-x/event-recurrence";
import '@schedule-x/theme-default/dist/calendar.css';
import { Archive, PencilSquare, Filter } from "react-bootstrap-icons";
import DatePicker from "react-datepicker";
import { vehicleSlice } from "../../store";
import Select from 'react-select';
// import { Scheduler } from "@aldabil/react-scheduler";
const EventsCalendar = () => {
const navigate = useNavigate();
const [events, setEvents] = useState([]);
const calendarColumnRef = useRef(null);
const [listHeight, setListHeight] = useState(null);
const [allEvents, setAllEvents] = useState([]);
const [targetedEventType, setTargetedEventType] = useState('medical');
const [currentTab, setCurrentTab] = useState('medicalCalendar');
const [customers, setCustomers] = useState([]);
const [resources, setResources] = useState([]);
const [fromDate, setFromDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth(), 1));
const [toDate, setToDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0));
const [currentTotalTranslate1, setCurrentTotalTranslate1] = useState(0);
const [currentTotalTranslate2, setCurrentTotalTranslate2] = useState(0);
const [currentTotalResource, setCurrentTotalResource] = useState(0);
const [showDeletedItems, setShowDeletedItems] = useState(false);
const [selectedColorFilters, setSelectedColorFilters] = useState([]);
const [timeData, setTimeData] = useState([]);
const [showFilterDropdown, setShowFilterDropdown] = useState(false);
const eventsServicePlugin = createEventsServicePlugin();
const eventModalService = createEventModalPlugin();
const eventRecurrence = createEventRecurrencePlugin();
const [groupedEvents, setGroupedEvents] = useState(new Map());
const [currentRangeStart, setCurrentRangeStart] = useState(null);
const [currentRangeEnd, setCurrentRangeEnd] = useState(null);
const [showCreationModal, setShowCreationModal] = useState(false);
const [newEventStartDateTime, setNewEventStartDateTime] = useState(new Date());
const [newEventEndDateTime, setNewEventEndDateTime] = useState(new Date())
const [newEventType, setNewEventType] = useState('');
const [newEventTitle, setNewEventTitle] = useState('');
const [newEventDescription, setNewEventDescription] = useState('');
const [newEventLocation, setNewEventLocation] = useState('');
const [newEventTarget, setNewEventTarget] = useState(undefined);
const [newEventSource, setNewEventSource] = useState(undefined);
const [newEventDepartment, setNewEventDepartment] = useState('');
const [newEventColor, setNewEventColor] = useState('');
const [newEventSourceType, setNewEventSourceType] = useState('');
const [newEventTargetType, setNewEventTargetType] = useState('');
const [newEventFutureDate, setNewEventFutureDate] = useState(undefined);
const [newEventReminderType, setNewEventReminderType] = useState('');
const [newEventRecurring, setNewEventRecurring] = useState(undefined);
const [vehicles, setVehicles] = useState([]);
const [employees, setEmployees] = useState([]);
// Medical appointment specific fields
const [newEventCustomer, setNewEventCustomer] = useState('');
const [newEventResource, setNewEventResource] = useState('');
const [newEventInterpreter, setNewEventInterpreter] = useState('');
const [newEventFasting, setNewEventFasting] = useState('');
const [newEventNeedId, setNewEventNeedId] = useState('');
const [newEventNewPatient, setNewEventNewPatient] = useState('');
const [newEventDisability, setNewEventDisability] = useState('');
const [newEventTransMethod, setNewEventTransMethod] = useState('');
// Activity specific fields
const [newActivityCategory, setNewActivityCategory] = useState('');
// Attendance Note specific fields
const [newAttendanceCustomer, setNewAttendanceCustomer] = useState(null);
const [newAttendanceReason, setNewAttendanceReason] = useState('');
// Meal Plan specific fields
const [newMealType, setNewMealType] = useState('');
const [newMealIngredients, setNewMealIngredients] = useState('');
// Important Dates specific fields
const [newReminderTitleCategory, setNewReminderTitleCategory] = useState('');
const [newReminderAssociatedEntity, setNewReminderAssociatedEntity] = useState(null);
// Helper function to format name from "lastname, firstname" to "firstname lastname"
const formatFullName = (name) => {
if (!name) return '';
if (name.includes(',')) {
const parts = name.split(',').map(part => part.trim());
return `${parts[1]} ${parts[0]}`; // firstname lastname
}
return name;
};
// Helper function to get shortened name
const getShortenedName = (name) => {
if (!name) return '';
const fullName = formatFullName(name);
const parts = fullName.split(' ');
if (parts.length >= 2) {
return `${parts[0]} ${parts[parts.length - 1].charAt(0)}`; // FirstName L
}
return fullName;
};
// Helper function to format event title - now uses full name, CSS handles overflow
const formatEventTitle = (customerName, startTime) => {
const fullName = formatFullName(customerName);
// Return full name - CSS will handle truncation with text-overflow: ellipsis
return fullName;
};
// Get full name for description/tooltip
const getEventDescription = (customerName, doctorName) => {
const fullName = formatFullName(customerName);
return doctorName ? `${fullName} - ${doctorName}` : fullName;
};
const eventTypeMap = {
medicalCalendar: 'medical',
activitiesCalendar: 'activity',
incidentsCalendar: 'incident',
mealPlanCalendar: 'meal_plan',
reminderDatesCalendar: 'reminder'
}
const calendar = useCalendarApp({
views: [createViewMonthGrid(), createViewDay(), createViewWeek()],
monthGridOptions: {
/**
* Number of events to display in a day cell before the "+ N events" button is shown
* */
nEventsPerDay: 50,
},
defaultView: viewMonthGrid.name,
skipValidation: true,
selectedDate: moment(new Date()).format('YYYY-MM-DD HH:mm'),
events: events,
plugins: [eventModalService, eventsServicePlugin, eventRecurrence],
callbacks: {
onRangeUpdate(range) {
console.log('new calendar range start date', range.start);
console.log('new calendar range end date', range.end);
setCurrentRangeStart(range.start);
setCurrentRangeEnd(range.end);
// Update fromDate/toDate for API fetching based on the range
const startDate = new Date(range.start);
const endDate = new Date(range.end);
setFromDate(new Date(startDate.getFullYear(), startDate.getMonth(), 1));
setToDate(new Date(endDate.getFullYear(), endDate.getMonth() + 1, 0));
},
onClickDate(date) {
// Parse as local date to avoid UTC timezone offset shifting the day
const [y, m, d] = date.split('-').map(Number);
const localDate = new Date(y, m - 1, d);
// Default to 10:00 AM for Medical Appointments and Activities tabs
if (currentTab === 'medicalCalendar' || currentTab === 'activitiesCalendar') {
localDate.setHours(10, 0, 0, 0);
}
setNewEventStartDateTime(localDate);
setNewEventEndDateTime(localDate);
setShowCreationModal(true);
},
onClickDateTime(dateTime) {
setNewEventStartDateTime(new Date(dateTime.replace(' ', 'T')));
setNewEventEndDateTime(new Date(dateTime.replace(' ', 'T')));
setShowCreationModal(true);
}
}
});
// Filter events based on current calendar range
const getFilteredEvents = () => {
console.log("CenterCalendar - range:", currentRangeStart, "to", currentRangeEnd, "events:", events.length);
if (!currentRangeStart || !currentRangeEnd) {
// If no range set yet, show all events for current month
const now = moment();
return events.filter(event => {
const eventDate = moment(event.start_time);
return eventDate.isSame(now, 'month');
});
}
// Filter events within the calendar's visible range
const rangeStart = moment(currentRangeStart);
const rangeEnd = moment(currentRangeEnd);
return events.filter(event => {
const eventDate = moment(event.start_time);
return eventDate.isBetween(rangeStart, rangeEnd, 'day', '[]');
});
};
const getGroupedEvents = () => {
const eventsDateMap = new Map();
const filteredEvents = getFilteredEvents();
for (const eventItem of filteredEvents) {
const dateString = moment(eventItem.start_time).format('MMM Do, YYYY');
if (eventsDateMap.has(dateString)) {
eventsDateMap.set(dateString, [...eventsDateMap.get(dateString), eventItem]);
} else {
const value = [];
value.push(eventItem);
eventsDateMap.set(dateString, value);
}
}
return eventsDateMap;
};
useEffect(() => {
if (!AuthService.canAccessLegacySystem()) {
window.alert('You haven\'t login yet OR this user does not have access to this page. Please change an admin account to login.')
AuthService.logout();
navigate(`/login`);
}
VehicleService.getAllActiveVehicles().then((data) => {
setVehicles(data.data)
});
EmployeeService.getAllEmployees().then((data) => {
setEmployees(data.data);
});
CustomerService.getAllActiveCustomers().then((data) => {
setCustomers(data.data);
});
ResourceService.getAll().then((data) => {
setResources(data.data);
});
EventsService.getTimeData().then(data => {
setTimeData(data.data);
});
}, []);
useEffect(() => {
EventsService.getAllEvents({ from: EventsService.formatDate(fromDate), to: EventsService.formatDate(toDate) }).then(data => setAllEvents(data?.data));
}, [fromDate, toDate]);
useEffect(() => {
setNewEventType(eventTypeMap[currentTab]);
if (currentTab === 'medicalCalendar') {
if (customers?.length > 0 && resources.length > 0) {
const orignialEvents = [...allEvents];
setEvents(orignialEvents?.filter(item => item.type === 'medical')?.map((item) => {
const customerField = item?.data?.customer ? (customers?.find(c => c.id === item?.data?.customer)?.name || item?.data?.client_name || '') : (item?.data?.client_name || '');
const doctorField = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.name || item?.data?.resource_name || '') : (item?.data?.resource_name || '');
item.event_id = item.id;
item.customer = customerField;
item.doctor = doctorField;
item.phone = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.phone || item?.data?.resource_phone || '') : (item?.data?.resource_phone || '');
item.contact = item?.data?.resource? ((resources?.find(r => r.id === item?.data?.resource))?.contact || item?.data?.resource_contact || '') : (item?.data?.resource_contact || '')
item.address = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.address || item?.data?.resource_address || '') : (item?.data?.resource_address || '');
item.translation = item?.data?.interpreter || '';
item.newPatient = item?.data?.new_patient || '';
item.needId = item?.data?.need_id || '';
item.disability = item?.data?.disability || '';
item.startTime = item?.start_time? `${moment(new Date(item?.start_time)).format('YYYY-MM-DD HH:mm')}` : '' ;
item.endTime = item?.start_time? `${moment(new Date(item?.end_time)).format('YYYY-MM-DD HH:mm')}` : '' ;
item.fasting = item?.data?.fasting || '';
item.transportation = item?.link_event_name || '';
item.title = currentTab==='medicalCalendar' ? formatEventTitle(customerField, item?.start_time) : item.title;
item.description = currentTab==='medicalCalendar' ? getEventDescription(customerField, doctorField) : item.description; // Full info for tooltip
item.start = item?.start_time? `${moment(new Date(item?.start_time)).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}`;
item.end = item?.stop_time? `${moment(new Date(item?.stop_time)).format('YYYY-MM-DD HH:mm')}` : (item?.start_time? `${moment(item?.start_time).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}`);
const transportationInfo = EventsService.getTransportationInfo(allEvents, item, timeData);
const { isFutureEvent, maxTranslate1, maxTranslate2, maxResource, totalTranslate1, totalTranslate2, totalResource} = transportationInfo;
item.color = item?.color;
item._options = { additionalClasses: [`event-${item?.color || 'primary'}`]};
item.showWarnings = isFutureEvent;
item.maxTranslate1 = maxTranslate1;
item.maxTranslate2 = maxTranslate2;
item.maxResource = maxResource;
item.totalTranslate1 = totalTranslate1;
setCurrentTotalTranslate1(item.totalTranslate1);
item.totalTranslate2 = totalTranslate2;
setCurrentTotalTranslate2(item.totalTranslate2);
item.totalResource = totalResource;
setCurrentTotalResource(item.totalResource);
return item;
})?.filter(item => (!showDeletedItems && item.status === 'active') || showDeletedItems)
?.filter(item => {
if (selectedColorFilters.length === 0) return true;
if (selectedColorFilters.includes(item.color)) return true;
// When "Drop-Off Only" (purple) is selected, also show events with no label
if (selectedColorFilters.includes('purple') && !item.color) return true;
return false;
}));
}
} else {
const originalEvents = [...allEvents];
let filteredEvents = originalEvents?.filter(item => item.type === eventTypeMap[currentTab])?.map(item => {
// For Important Dates, remap old blue/orange colors to new member_related/vehicle_maintenance
let eventColor = item?.color;
if (currentTab === 'reminderDatesCalendar') {
const isMember = ['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(item?.event_reminder_type) || item?.target_type === 'customer';
eventColor = isMember ? 'member_related' : 'vehicle_maintenance';
}
const additionalClasses = [`event-${eventColor || 'primary'}`];
// Disable clicking for birthday events on Important Dates tab
if (currentTab === 'reminderDatesCalendar' && item?.event_reminder_type === 'birthday') {
additionalClasses.push('event-no-click');
}
// For Important Dates, use date-only format so tiles don't show hour:minute
const dateFormat = (currentTab === 'reminderDatesCalendar' || currentTab === 'incidentsCalendar') ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm';
return {
...item,
color: eventColor,
title: item?.title,
start: item?.start_time? `${moment(new Date(item?.start_time)).format(dateFormat)}` : `${moment().format(dateFormat)}`,
end: item?.stop_time? `${moment(new Date(item?.stop_time)).format(dateFormat)}` : (item?.start_time? `${moment(item?.start_time).format(dateFormat)}` : `${moment().format(dateFormat)}`),
_options: { additionalClasses }
};
})?.filter(item => (!showDeletedItems && item.status === 'active') || showDeletedItems)
?.filter(item => {
if (selectedColorFilters.length === 0) return true;
// For Important Dates, filter by event_reminder_type
if (currentTab === 'reminderDatesCalendar') {
return selectedColorFilters.includes(item.event_reminder_type);
}
if (selectedColorFilters.includes(item.color)) return true;
// When "Drop-Off Only" (purple) is selected, also show events with no label
if (selectedColorFilters.includes('purple') && !item.color) return true;
return false;
});
// For Important Dates tab, filter to only show events for active customers
if (currentTab === 'reminderDatesCalendar' && customers?.length > 0) {
filteredEvents = filteredEvents?.filter(item => {
// If it's a customer-related event, check if the customer is active
if (item.target_type === 'customer' && item.target_uuid) {
const customer = customers.find(c => c.id === item.target_uuid);
// Only show if customer exists and is active (not discharged/transferred/deceased)
return customer && customer.status === 'active' &&
customer.type !== 'discharged' &&
customer.type !== 'transferred' &&
customer.type !== 'deceased';
}
// Vehicle-related events are always shown
return true;
});
}
setEvents(filteredEvents);
}
}, [customers, resources, timeData, currentTab, allEvents, showDeletedItems, selectedColorFilters])
useEffect(() => {
if (events && calendar) {
console.log("CenterCalendar useEffect - events:", events.length, "range:", currentRangeStart, "to", currentRangeEnd);
calendar?.eventsService?.set(events);
setGroupedEvents(getGroupedEvents());
}
}, [events, currentRangeStart, currentRangeEnd]);
// Sync list column height with calendar column height
useEffect(() => {
const updateListHeight = () => {
if (calendarColumnRef.current) {
const calendarHeight = calendarColumnRef.current.offsetHeight;
setListHeight(calendarHeight);
}
};
// Initial measurement after render
const timer = setTimeout(updateListHeight, 100);
// Update on window resize
window.addEventListener('resize', updateListHeight);
return () => {
clearTimeout(timer);
window.removeEventListener('resize', updateListHeight);
};
}, [events, currentTab]);
const redirectToAdmin = () => {
navigate(`/medical`)
}
const goToEdit = (id) => {
navigate(`/medical/events/edit/${id}?from=calendar`)
}
const goToCreateNew = () => {
navigate(`/medical/events`)
}
const goToList = () => {
navigate(`/medical/events/list`)
}
const goToMultipleList = () => {
navigate(`/medical/events/multiple-list`)
}
const goToView = (id) => {
navigate(`/medical/events/${id}`)
}
const disableEvent = (id) => {
const currentEvent = events.find(item => item.id === id);
EventsService.disableEvent(id, { status: 'inactive', edit_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
edit_date: new Date(),
edit_history: currentEvent?.edit_history? [...currentEvent.edit_history, { employee: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name, date: new Date() }] : [{ employee: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name, date: new Date() }]}).then(() => {
EventsService.getAllEvents({ from: EventsService.formatDate(fromDate), to: EventsService.formatDate(toDate) }).then((data) => {
setAllEvents(data?.data);
// if (currentTab === 'medicalCalendar') {
// setEvents(data.data.filter((item) => {
// const customerField = item?.data?.customer ? (customers?.find(c => c.id === item?.data?.customer)?.name || item?.data?.client_name || '') : (item?.data?.client_name || '');
// const doctorField = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.name || item?.data?.resource_name || '') : (item?.data?.resource_name || '');
// item.event_id = item.id;
// item.customer = customerField;
// item.doctor = doctorField;
// item.phone = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.phone || item?.data?.resource_phone || '') : (item?.data?.resource_phone || '');
// item.contact = item?.data?.resource? ((resources?.find(r => r.id === item?.data?.resource))?.contact || item?.data?.resource_contact || '') : (item?.data?.resource_contact || '')
// item.address = item?.data?.resource ? ((resources?.find(r => r.id === item?.data?.resource))?.address || item?.data?.resource_address || '') : (item?.data?.resource_address || '');
// item.translation = item?.data?.interpreter || '';
// item.newPatient = item?.data?.new_patient || '';
// item.needId = item?.data?.need_id || '';
// item.disability = item?.data?.disability || '';
// item.startTime = item?.start_time? `${moment(new Date(item?.start_time)).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}` ;
// item.endTime = item.stop_time? `${moment(new Date(item?.stop_time)).format('YYYY-MM-DD HH:mm')}` : (item?.start_time? `${moment(item?.start_time).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}`);
// item.fasting = item?.data?.fasting || '';
// item.transportation = item?.link_event_name || '';
// item.title = `${customerField}, provider: ${doctorField}`;
// item.start = item?.start_time? `${moment(new Date(item?.start_time)).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}`;
// item.end = item.stop_time? `${moment(new Date(item?.stop_time)).format('YYYY-MM-DD HH:mm')}` : (item?.start_time? `${moment(item?.start_time).format('YYYY-MM-DD HH:mm')}` : `${moment().format('YYYY-MM-DD HH:mm')}`);
// item._options = { additionalClasses: [`event-${item?.color || 'primary'}`]};
// const transportationInfo = EventsService.getTransportationInfo(data.data, item, timeData);
// const { isFutureEvent, maxTranslate1, maxTranslate2, maxResource, totalTranslate1, totalTranslate2, totalResource} = transportationInfo;
// item.color = item?.color;
// item.showWarnings = isFutureEvent;
// item.maxTranslate1 = maxTranslate1;
// item.maxTranslate2 = maxTranslate2;
// item.maxResource = maxResource;
// item.totalTranslate1 = totalTranslate1;
// setCurrentTotalTranslate1(item.totalTranslate1);
// item.totalTranslate2 = totalTranslate2;
// setCurrentTotalTranslate2(item.totalTranslate2);
// item.totalResource = totalResource;
// setCurrentTotalResource(item.totalResource);
// return item;
// }).filter(item => item.type === 'medical'));
// }
})
});
}
const toggleColorFilter = (colorValue) => {
setSelectedColorFilters(prev =>
prev.includes(colorValue)
? prev.filter(c => c !== colorValue)
: [...prev, colorValue]
);
};
const FilterAndClose = () => {
setShowFilterDropdown(false);
}
const cleanFilterAndClose = () => {
setShowFilterDropdown(false);
setShowDeletedItems(false);
setSelectedColorFilters([]);
}
const goToTab = (value) => {
setTargetedEventType(eventTypeMap[value]);
setCurrentTab(value);
setSelectedColorFilters([]);
}
const customComponents = {
eventModal: ({calendarEvent}) => {
return <>
<div className="sx__event-modal__title">{currentTab === 'medicalCalendar' ? calendarEvent?.customer : calendarEvent?.title}</div>
{calendarEvent?.doctor && <div className="sx__event-modal__time">{`${calendarEvent?.doctor}`}</div>}
<div className="sx__event-modal__time">{`${calendarEvent?.start}`}</div>
<div className="sx__event-modal__time" style={{ display: 'flex', gap: '12px', marginTop: '8px' }}>
<PencilSquare
size={16}
onClick={() => currentTab === 'medicalCalendar' ? goToEdit(calendarEvent?.id) : goToEdit(calendarEvent?.id)}
style={{ cursor: 'pointer' }}
title="Edit"
/>
<Archive
size={16}
onClick={() => disableEvent(calendarEvent?.id)}
style={{ cursor: 'pointer' }}
title="Delete"
/>
</div>
</>
}
};
const customMenu = React.forwardRef(
({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
return (
<div
ref={ref}
style={style}
className={className}
aria-labelledby={labeledBy}
>
<h6>Filter By</h6>
<div className="app-main-content-fields-section margin-sm dropdown-container">
<div className="me-4">
<div className="field-label">Show Deleted Events</div>
<input type="checkbox" value={showDeletedItems} checked={showDeletedItems === true} onClick={() => setShowDeletedItems(!showDeletedItems)} />
</div>
</div>
<hr style={{ margin: '8px 0' }} />
<div style={{ display: 'flex', flexDirection: 'column' }}>
<div className="field-label" style={{ marginBottom: '8px' }}>Filter by Type</div>
{currentTab === 'reminderDatesCalendar' ? (
<>
<div style={{ fontSize: '11px', fontWeight: '600', color: '#0066B1', marginBottom: '4px', marginTop: '4px' }}>Member-Related</div>
{EventsService.importantDatesFilterOptions.filter(o => o.group === 'member_related').map((item) => (
<div key={item.value} className="d-flex align-items-center mb-1" style={{ cursor: 'pointer', paddingLeft: '4px' }} onClick={() => toggleColorFilter(item.value)}>
<input
type="checkbox"
checked={selectedColorFilters.includes(item.value)}
onChange={() => toggleColorFilter(item.value)}
style={{ marginRight: '8px', marginLeft: '0' }}
onClick={(e) => e.stopPropagation()}
/>
<span
className="event-member_related"
style={{
width: '14px',
height: '14px',
borderRadius: '3px',
display: 'inline-block',
marginRight: '6px',
flexShrink: 0
}}
></span>
<span style={{ fontSize: '12px' }}>{item.label}</span>
</div>
))}
<div style={{ fontSize: '11px', fontWeight: '600', color: '#9C2A10', marginBottom: '4px', marginTop: '8px' }}>Vehicle Maintenance</div>
{EventsService.importantDatesFilterOptions.filter(o => o.group === 'vehicle_maintenance').map((item) => (
<div key={item.value} className="d-flex align-items-center mb-1" style={{ cursor: 'pointer', paddingLeft: '4px' }} onClick={() => toggleColorFilter(item.value)}>
<input
type="checkbox"
checked={selectedColorFilters.includes(item.value)}
onChange={() => toggleColorFilter(item.value)}
style={{ marginRight: '8px', marginLeft: '0' }}
onClick={(e) => e.stopPropagation()}
/>
<span
className="event-vehicle_maintenance"
style={{
width: '14px',
height: '14px',
borderRadius: '3px',
display: 'inline-block',
marginRight: '6px',
flexShrink: 0
}}
></span>
<span style={{ fontSize: '12px' }}>{item.label}</span>
</div>
))}
</>
) : (
getLegendOptions().map((item) => (
<div key={item.value} className="d-flex align-items-center mb-1" style={{ cursor: 'pointer' }} onClick={() => toggleColorFilter(item.value)}>
<input
type="checkbox"
checked={selectedColorFilters.includes(item.value)}
onChange={() => toggleColorFilter(item.value)}
style={{ marginRight: '8px', marginLeft: '0' }}
onClick={(e) => e.stopPropagation()}
/>
<span
className={`event-${item.value}`}
style={{
width: '14px',
height: '14px',
borderRadius: '3px',
display: 'inline-block',
marginRight: '6px',
flexShrink: 0
}}
></span>
<span style={{ fontSize: '12px' }}>{item.label}</span>
</div>
))
)}
{selectedColorFilters.length > 0 && (
<div style={{ marginTop: '4px' }}>
<span
style={{ fontSize: '11px', color: '#0066B1', cursor: 'pointer', textDecoration: 'underline' }}
onClick={() => setSelectedColorFilters([])}
>
Clear all
</span>
</div>
)}
</div>
<div className="list row" style={{ marginTop: '8px' }}>
<div className="col-md-12">
<button className="btn btn-default btn-sm float-right" onClick={() => cleanFilterAndClose()}> Cancel </button>
<button className="btn btn-primary btn-sm float-right" onClick={() => FilterAndClose()}> Filter </button>
</div>
</div>
</div>
);
},
);
// Get legend options based on current tab
const getLegendOptions = () => {
switch (currentTab) {
case 'medicalCalendar':
return EventsService.labelOptions;
case 'activitiesCalendar':
return EventsService.activityColorOptions;
case 'incidentsCalendar':
return EventsService.incidentColorOptions;
case 'mealPlanCalendar':
return EventsService.mealPlanColorOptions;
case 'reminderDatesCalendar':
return EventsService.importantDatesLegendOptions;
default:
return [];
}
};
const calendarView = <div className="multi-columns-container" style={{ display: 'flex', alignItems: 'flex-start', width: '100%' }}>
<div className="column-container" ref={calendarColumnRef} style={{ minWidth: '1000px', flexShrink: 0, display: 'flex', flexDirection: 'column' }}>
{calendar && <ScheduleXCalendar customComponents={customComponents} calendarApp={calendar} />}
{/* Dynamic Legend */}
<div className="calendar-legend mt-3">
<h6 className="text-muted mb-2" style={{ fontSize: '12px' }}>Legend:</h6>
<div className="d-flex flex-wrap gap-3">
{getLegendOptions().map((item) => (
<div key={item.value} className="d-flex align-items-center">
<span
className={`event-${item.value}`}
style={{
width: '16px',
height: '16px',
borderRadius: '4px',
display: 'inline-block',
marginRight: '6px'
}}
></span>
<span style={{ fontSize: '12px' }}>{item.label}</span>
</div>
))}
</div>
</div>
</div>
<div className="column-container calendar-list-column" style={{ display: 'flex', flexDirection: 'column', flex: 1, minWidth: 0 }}>
<div className="column-card" style={{ height: listHeight ? `${listHeight}px` : 'auto', overflowY: 'auto', overflowX: 'hidden', padding: '16px', display: 'flex', flexDirection: 'column', width: '100%', boxSizing: 'border-box' }}>
<h6 className="text-primary mb-3">List</h6>
<div style={{ flex: 1, overflowY: 'auto', width: '100%' }}>
{(!groupedEvents || groupedEvents.size === 0) && (
<div style={{ padding: '24px', textAlign: 'center', color: '#999' }}>
No events for this period
</div>
)}
{
Array.from(groupedEvents?.keys())?.map((key) => {
return <div key={key}>
<h6 className="text-primary me-2">{key}</h6>
{
groupedEvents.get(key).map(eventItem => <div
key={eventItem.id}
className={`event-${eventItem.color || 'primary'} mb-3 event-list-item-container`}
onClick={() => currentTab === 'medicalCalendar' && goToView(eventItem.id)}
style={{ cursor: currentTab === 'medicalCalendar' ? 'pointer' : 'default', padding: '8px 12px', borderRadius: '4px' }}
>
{/* Medical Events */}
{currentTab === 'medicalCalendar' && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span className="sx__month-agenda-event__title">{formatFullName(eventItem.customer)}</span>
<span style={{ fontSize: '12px' }}>{moment(eventItem?.start_time).format('HH:mm')} - {moment(eventItem?.stop_time || eventItem?.start_time).format('HH:mm')}</span>
</div>
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Provider: {eventItem?.doctor || '-'}</div>
</>
)}
{/* Activities */}
{currentTab === 'activitiesCalendar' && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span className="sx__month-agenda-event__title">{eventItem.title}</span>
<span style={{ fontSize: '12px' }}>{moment(eventItem?.start_time).format('HH:mm')}</span>
</div>
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Location: {eventItem?.event_location || '-'}</div>
</>
)}
{/* Attendance Notes */}
{currentTab === 'incidentsCalendar' && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span className="sx__month-agenda-event__title">{eventItem?.target_name || eventItem.title}</span>
<span style={{ fontSize: '12px' }}>{moment(eventItem?.start_time).format('MM/DD')}</span>
</div>
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Reason: {eventItem?.description || '-'}</div>
</>
)}
{/* Meal Plan */}
{currentTab === 'mealPlanCalendar' && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span className="sx__month-agenda-event__title">{eventItem.title}</span>
<span style={{ fontSize: '12px', textTransform: 'capitalize' }}>{eventItem?.meal_type || '-'}</span>
</div>
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Ingredients: {eventItem?.ingredients || '-'}</div>
</>
)}
{/* Important Dates / Reminders */}
{currentTab === 'reminderDatesCalendar' && (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span className="sx__month-agenda-event__title">{eventItem.title}</span>
<span style={{ fontSize: '12px' }}>{moment(eventItem?.start_time).format('MM/DD')}</span>
</div>
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>{eventItem?.target_type === 'vehicle' ? 'Vehicle' : 'Person'}: {eventItem?.target_name || '-'}</div>
{eventItem?.event_prediction_date && <div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '2px' }}>Deadline: {moment(eventItem?.event_prediction_date).format('MM/DD/YYYY')}</div>}
</>
)}
</div>)
}
</div>
})
}
</div>
</div>
</div>
</div>
const handleClose = () => {
setNewEventDescription('');
setNewEventTitle('');
setNewEventLocation('');
setNewEventSource(undefined);
setNewEventTarget(undefined);
setNewEventStartDateTime(undefined);
setNewEventType('');
setNewEventFutureDate(undefined);
setNewEventSourceType('');
setNewEventTargetType('');
setShowCreationModal(false);
setNewEventEndDateTime(undefined);
setNewEventColor('');
setNewEventRecurring(undefined);
setNewEventReminderType('');
// Reset medical fields
setNewEventCustomer('');
setNewEventResource('');
setNewEventInterpreter('');
setNewEventFasting('');
setNewEventNeedId('');
setNewEventNewPatient('');
setNewEventDisability('');
setNewEventTransMethod('');
// Reset activity fields
setNewActivityCategory('');
// Reset attendance note fields
setNewAttendanceCustomer(null);
setNewAttendanceReason('');
// Reset meal plan fields
setNewMealType('');
setNewMealIngredients('');
// Reset important dates fields
setNewReminderTitleCategory('');
setNewReminderAssociatedEntity(null);
}
const handleSave = () => {
const userName = localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name;
let data = {
type: newEventType,
status: 'active',
create_by: userName,
edit_by: userName,
edit_date: new Date(),
create_date: new Date(),
edit_history: [{ employee: userName, date: new Date() }]
};
// Handle Medical Appointments
if (currentTab === 'medicalCalendar') {
const selectedCustomer = customers.find(c => c.id === newEventCustomer);
const selectedResource = resources.find(r => r.id === newEventResource);
data = {
...data,
title: selectedCustomer ? `${selectedCustomer.name} - Medical Appointment` : 'Medical Appointment',
start_time: newEventStartDateTime,
stop_time: newEventStartDateTime,
color: newEventColor,
confirmed: true,
data: {
customer: newEventCustomer,
client_name: selectedCustomer?.name || '',
resource: newEventResource,
resource_name: selectedResource?.name || '',
resource_phone: selectedResource?.phone || '',
resource_address: selectedResource?.address || '',
interpreter: newEventInterpreter,
fasting: newEventFasting,
need_id: newEventNeedId,
new_patient: newEventNewPatient,
disability: newEventDisability,
trans_method: newEventTransMethod,
}
};
}
// Handle Activities
if (currentTab === 'activitiesCalendar') {
data = {
...data,
title: newEventTitle,
start_time: newEventStartDateTime,
stop_time: newEventStartDateTime,
activity_category: newActivityCategory,
color: newActivityCategory, // category maps to color for display
event_location: newEventLocation,
rrule: newEventRecurring,
};
}
// Handle Attendance Notes (Incidents)
if (currentTab === 'incidentsCalendar') {
data = {
...data,
title: newAttendanceCustomer?.label ? `Attendance Note - ${newAttendanceCustomer.label}` : 'Attendance Note',
start_time: newEventStartDateTime,
stop_time: newEventStartDateTime,
target_type: 'customer',
target_uuid: newAttendanceCustomer?.value,
target_name: newAttendanceCustomer?.label,
description: newAttendanceReason,
color: 'blue', // Default color for attendance notes
};
}
// Handle Meal Plan
if (currentTab === 'mealPlanCalendar') {
data = {
...data,
title: newEventTitle,
start_time: newEventStartDateTime,
stop_time: newEventStartDateTime,
meal_type: newMealType,
color: newMealType === 'breakfast' ? 'brown' : (newMealType === 'lunch' ? 'green' : 'red'),
ingredients: newMealIngredients,
rrule: newEventRecurring,
};
}
// Handle Important Dates (Reminders)
if (currentTab === 'reminderDatesCalendar') {
const isMemberCategory = ['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(newReminderTitleCategory);
data = {
...data,
title: getReminderTitleLabel(newReminderTitleCategory),
start_time: newEventStartDateTime,
stop_time: newEventStartDateTime,
event_reminder_type: newReminderTitleCategory,
target_type: isMemberCategory ? 'customer' : 'vehicle',
target_uuid: newReminderAssociatedEntity?.value,
target_name: newReminderAssociatedEntity?.label,
rrule: newEventRecurring,
color: isMemberCategory ? 'member_related' : 'vehicle_maintenance',
};
}
EventsService.createNewEvent(data).then(() => {
EventsService.getAllEvents({ from: EventsService.formatDate(fromDate), to: EventsService.formatDate(toDate) }).then((data) => {
setAllEvents(data.data);
handleClose();
})
});
}
// Helper function to get reminder title label
const getReminderTitleLabel = (value) => {
const memberOptions = {
'birthday': 'Birthday',
'adcaps_completion': 'ADCAPS Completion',
'center_qualification_expiration': 'Center Qualification Expiration'
};
const vehicleOptions = {
'oil_change': 'Oil Change',
'monthly_vehicle_inspection': 'Monthly Vehicle Inspection',
'emissions_inspection': 'Emissions Inspection',
'insurance_expiration': 'Insurance Expiration',
'license_plate_expiration': 'License Plate Expiration'
};
return memberOptions[value] || vehicleOptions[value] || value;
};
return (
<>
<div className="list row mb-4">
<Breadcrumb>
<Breadcrumb.Item href="/">General</Breadcrumb.Item>
<Breadcrumb.Item active>
Calendar
</Breadcrumb.Item>
</Breadcrumb>
<div className="col-md-12 text-primary">
<h4>
Calendar
</h4>
</div>
</div>
<div className="app-main-content-list-container" style={{"min-width": "1500px"}}>
<div className="app-main-content-list-func-container">
<Tabs defaultActiveKey="medicalCalendar" id="medical-calendar-tab" onSelect={(k) => goToTab(k)}>
<Tab eventKey="medicalCalendar" title="Medical Appointments">
</Tab>
<Tab eventKey="activitiesCalendar" title="Activities">
</Tab>
<Tab eventKey="incidentsCalendar" title="Attendance">
</Tab>
<Tab eventKey="mealPlanCalendar" title="Meal Plan">
</Tab>
<Tab eventKey="reminderDatesCalendar" title="Important Dates">
</Tab>
</Tabs>
{ calendarView}
<div className="list-func-panel">
<Dropdown
key={'event-calendar-filter'}
id="event-calendar-filter"
show={showFilterDropdown}
onToggle={() => setShowFilterDropdown(!showFilterDropdown)}
autoClose={false}
>
<Dropdown.Toggle variant="primary">
<Filter size={16} className="me-2"></Filter>Filter
</Dropdown.Toggle>
<Dropdown.Menu as={customMenu}/>
</Dropdown>
</div>
<Modal show={showCreationModal} onHide={handleClose} size="sm" dialogClassName="calendar-event-modal">
<Modal.Header closeButton>
<Modal.Title>
{currentTab === 'medicalCalendar' && 'New Medical Appointment'}
{currentTab === 'activitiesCalendar' && 'New Activity'}
{currentTab === 'incidentsCalendar' && 'New Attendance Note'}
{currentTab === 'mealPlanCalendar' && 'New Meal Item'}
{currentTab === 'reminderDatesCalendar' && 'New Important Date'}
</Modal.Title>
</Modal.Header>
<Modal.Body>
{/* Medical Appointment Fields */}
{currentTab === 'medicalCalendar' && (
<>
<div className="mb-3">
<div className="field-label">Customer<span className="required">*</span></div>
<select className="form-control" value={newEventCustomer} onChange={(e) => setNewEventCustomer(e.target.value)}>
<option value="">Select Customer</option>
{customers.filter(item => item?.status === 'active' && item?.type !== 'discharged').map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
</select>
</div>
<div className="mb-3">
<div className="field-label">Provider<span className="required">*</span></div>
<select className="form-control" value={newEventResource} onChange={(e) => setNewEventResource(e.target.value)}>
<option value="">Select Provider</option>
{resources.filter(item => item?.status === 'active').map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
</select>
</div>
<div className="mb-3">
<div className="field-label">Appointment Time<span className="required">*</span></div>
<DatePicker
className="form-control"
selected={newEventStartDateTime}
onChange={setNewEventStartDateTime}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
dateFormat="MM/dd/yyyy, HH:mm"
/>
</div>
<div className="mb-3">
<div className="field-label">Language Support</div>
<select className="form-control" value={newEventInterpreter} onChange={(e) => setNewEventInterpreter(e.target.value)}>
<option value="">Select</option>
<option value="Checkin">Checkin</option>
<option value="Center">Center</option>
<option value="Family">Family</option>
<option value="Office in person">Office in person</option>
<option value="Office by phone">Office by phone</option>
<option value="Nurse">Nurse</option>
</select>
</div>
<div className="mb-3">
<div className="field-label">Transportation Support</div>
<select className="form-control" value={newEventTransMethod} onChange={(e) => setNewEventTransMethod(e.target.value)}>
<option value="">Select</option>
<option value="ByOwn">Self-Transport</option>
<option value="By Center Transportation">By Center Transportation</option>
<option value="DropOff Only">Drop-Off Only</option>
<option value="Pickup Only">Pick-Up Only</option>
<option value="Client Does Not need to Go">Medication Pickup Only</option>
</select>
</div>
<div className="mb-3">
<div className="field-label">Label</div>
<select className="form-control" value={newEventColor} onChange={(e) => setNewEventColor(e.target.value)}>
<option value="">Select</option>
{EventsService.labelOptions?.map((item) => <option key={item.value} value={item.value}>{item.label}</option>)}
</select>
</div>
</>
)}
{/* Activity Fields */}
{currentTab === 'activitiesCalendar' && (
<>
<div className="mb-3">
<div className="field-label">Activity Name<span className="required">*</span></div>
<input type="text" className="form-control" placeholder="Enter activity name" value={newEventTitle || ''} onChange={e => setNewEventTitle(e.target.value)}/>
</div>
<div className="mb-3">
<div className="field-label">Date & Time</div>
<DatePicker
className="form-control"
selected={newEventStartDateTime}
onChange={setNewEventStartDateTime}
showTimeSelect
timeFormat="HH:mm"
timeIntervals={15}
dateFormat="MM/dd/yyyy, HH:mm"
/>
</div>
<div className="mb-3">
<div className="field-label">Category<span className="required">*</span></div>
<select className="form-control" value={newActivityCategory} onChange={(e) => setNewActivityCategory(e.target.value)}>
<option value="">Select Category</option>
<option value="red">Classes</option>
<option value="pink">Games</option>
<option value="green">Events</option>
<option value="blue">Outings</option>
<option value="purple">Personal Care</option>
<option value="brown">Care Activities</option>
</select>
</div>
<div className="mb-3">
<div className="field-label">Location</div>
<input type="text" className="form-control" placeholder="Enter location" value={newEventLocation || ''} onChange={e => setNewEventLocation(e.target.value)}/>
</div>
<div className="mb-3">
<div className="field-label">Repeat</div>
<select className="form-control" value={newEventRecurring} onChange={(e) => setNewEventRecurring(e.target.value)}>
<option value="">No (One-time)</option>
<option value="FREQ=DAILY">Daily</option>
<option value="FREQ=WEEKLY">Weekly</option>
<option value="FREQ=MONTHLY">Monthly</option>
<option value="FREQ=YEARLY">Yearly</option>
</select>
</div>
</>
)}
{/* Attendance Note Fields */}
{currentTab === 'incidentsCalendar' && (
<>
<div className="mb-3">
<div className="field-label">Customer Name<span className="required">*</span></div>
<Select
value={newAttendanceCustomer}
onChange={setNewAttendanceCustomer}
options={customers.filter(item => item?.status === 'active' && item?.type !== 'discharged').map(c => ({ value: c.id, label: c.name }))}
placeholder="Select Customer"
isClearable
/>
</div>
<div className="mb-3">
<div className="field-label">Date<span className="required">*</span></div>
<DatePicker
className="form-control"
selected={newEventStartDateTime}
onChange={setNewEventStartDateTime}
dateFormat="MM/dd/yyyy"
/>
</div>
<div className="mb-3">
<div className="field-label">Reason</div>
<input type="text" className="form-control" placeholder="Enter reason" value={newAttendanceReason || ''} onChange={e => setNewAttendanceReason(e.target.value)}/>
</div>
</>
)}
{/* Meal Item Fields */}
{currentTab === 'mealPlanCalendar' && (
<>
<div className="mb-3">
<div className="field-label">Dish Name<span className="required">*</span></div>
<input type="text" className="form-control" placeholder="Enter dish name" value={newEventTitle || ''} onChange={e => setNewEventTitle(e.target.value)}/>
</div>
<div className="mb-3">
<div className="field-label">Meal Type<span className="required">*</span></div>
<select className="form-control" value={newMealType} onChange={(e) => setNewMealType(e.target.value)}>
<option value="">Select Meal Type</option>
<option value="breakfast">Breakfast</option>
<option value="lunch">Lunch</option>
<option value="snack">Snack</option>
</select>
</div>
<div className="mb-3">
<div className="field-label">Date</div>
<DatePicker
className="form-control"
selected={newEventStartDateTime}
onChange={setNewEventStartDateTime}
dateFormat="MM/dd/yyyy"
/>
</div>
<div className="mb-3">
<div className="field-label">Repeat</div>
<select className="form-control" value={newEventRecurring} onChange={(e) => setNewEventRecurring(e.target.value)}>
<option value="">No (One-time)</option>
<option value="FREQ=DAILY">Daily</option>
<option value="FREQ=WEEKLY">Weekly</option>
<option value="FREQ=MONTHLY">Monthly</option>
</select>
</div>
<div className="mb-3">
<div className="field-label">Ingredients</div>
<input type="text" className="form-control" placeholder="Enter ingredients" value={newMealIngredients || ''} onChange={e => setNewMealIngredients(e.target.value)}/>
</div>
</>
)}
{/* Important Dates Fields */}
{currentTab === 'reminderDatesCalendar' && (
<>
<div className="mb-3">
<div className="field-label">Title<span className="required">*</span></div>
<select className="form-control" value={newReminderTitleCategory} onChange={(e) => {
setNewReminderTitleCategory(e.target.value);
setNewReminderAssociatedEntity(null); // Reset when category changes
}}>
<option value="">Select Title</option>
<optgroup label="Member">
<option value="adcaps_completion">ADCAPS Completion</option>
<option value="center_qualification_expiration">Center Qualification Expiration</option>
</optgroup>
<optgroup label="Vehicle">
<option value="oil_change">Oil Change</option>
<option value="monthly_vehicle_inspection">Monthly Vehicle Inspection</option>
<option value="emissions_inspection">Emissions Inspection</option>
<option value="insurance_expiration">Insurance Expiration</option>
<option value="license_plate_expiration">License Plate Expiration</option>
</optgroup>
</select>
</div>
{newReminderTitleCategory && (
<div className="mb-3">
<div className="field-label">
{['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(newReminderTitleCategory)
? 'Associated Person'
: 'Associated Vehicle'}<span className="required">*</span>
</div>
<Select
value={newReminderAssociatedEntity}
onChange={setNewReminderAssociatedEntity}
options={
['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(newReminderTitleCategory)
? customers.filter(item => item?.status === 'active' && item?.type !== 'discharged').map(c => ({ value: c.id, label: c.name }))
: vehicles.map(v => ({ value: v.id, label: v.vehicle_number }))
}
placeholder={['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(newReminderTitleCategory) ? 'Select Person' : 'Select Vehicle'}
isClearable
/>
</div>
)}
<div className="mb-3">
<div className="field-label">Date</div>
<DatePicker
className="form-control"
selected={newEventStartDateTime}
onChange={setNewEventStartDateTime}
dateFormat="MM/dd/yyyy"
/>
</div>
<div className="mb-3">
<div className="field-label">Category</div>
<div className="field-value" style={{ padding: '8px 0', color: '#666' }}>
{newReminderTitleCategory
? (['birthday', 'adcaps_completion', 'center_qualification_expiration'].includes(newReminderTitleCategory) ? 'Member Related' : 'Vehicle Related')
: '-'}
</div>
</div>
<div className="mb-3">
<div className="field-label">Repeat Cycle</div>
<select className="form-control" value={newEventRecurring} onChange={(e) => setNewEventRecurring(e.target.value)}>
<option value="">No (One-time)</option>
<option value="FREQ=DAILY">Daily</option>
<option value="FREQ=WEEKLY">Weekly</option>
<option value="FREQ=MONTHLY">Monthly</option>
<option value="FREQ=YEARLY">Yearly</option>
</select>
</div>
</>
)}
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" size="sm" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary" size="sm" onClick={handleSave} disabled={
(currentTab === 'medicalCalendar' && (!newEventCustomer || !newEventResource || !newEventStartDateTime)) ||
(currentTab === 'activitiesCalendar' && (!newEventTitle || !newActivityCategory)) ||
(currentTab === 'incidentsCalendar' && (!newAttendanceCustomer || !newEventStartDateTime)) ||
(currentTab === 'mealPlanCalendar' && (!newEventTitle || !newMealType)) ||
(currentTab === 'reminderDatesCalendar' && (!newReminderTitleCategory || !newReminderAssociatedEntity))
}>
Save
</Button>
</Modal.Footer>
</Modal>
</div>
</div>
</>
)
};
export default EventsCalendar;