This commit is contained in:
@@ -607,7 +607,11 @@ const EventsCalendar = () => {
|
||||
}
|
||||
|
||||
const disableEvent = (id) => {
|
||||
if (currentTab === 'medicalCalendar') {
|
||||
if (!AuthService.canEditMedicalEvents()) return;
|
||||
} else {
|
||||
if (!AuthService.canEditCalendarTab(currentTab)) return;
|
||||
}
|
||||
// Handle recurring event instances
|
||||
const isRecurInstance = typeof id === 'string' && id.startsWith('recur-');
|
||||
if (isRecurInstance) {
|
||||
@@ -921,7 +925,7 @@ const EventsCalendar = () => {
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Edit"
|
||||
/>}
|
||||
{currentTab !== 'medicalCalendar' && AuthService.canEditCalendarTab(currentTab) && <Archive
|
||||
{((currentTab === 'medicalCalendar' && AuthService.canEditMedicalEvents()) || (currentTab !== 'medicalCalendar' && AuthService.canEditCalendarTab(currentTab))) && <Archive
|
||||
size={16}
|
||||
onClick={() => { setDeleteTargetId(calendarEvent?.id); setShowDeleteConfirm(true); }}
|
||||
style={{ cursor: 'pointer' }}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
import { createEventsServicePlugin } from '@schedule-x/events-service';
|
||||
import { createEventModalPlugin} from '@schedule-x/event-modal';
|
||||
import '@schedule-x/theme-default/dist/calendar.css';
|
||||
import { Filter } from "react-bootstrap-icons";
|
||||
import { Archive, Filter, PencilSquare } from "react-bootstrap-icons";
|
||||
import DatePicker from "react-datepicker";
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ const EventsCalendar = () => {
|
||||
const [currentRangeStart, setCurrentRangeStart] = useState(null);
|
||||
const [currentRangeEnd, setCurrentRangeEnd] = useState(null);
|
||||
const [showCreationModal, setShowCreationModal] = useState(false);
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
||||
const [newEventStartDateTime, setNewEventStartDateTime] = useState(new Date());
|
||||
const [newEventEndDateTime, setNewEventEndDateTime] = useState(new Date());
|
||||
const [newEventColor, setNewEventColor] = useState('');
|
||||
@@ -270,6 +272,28 @@ const EventsCalendar = () => {
|
||||
navigate(`/medical/events/${id}`)
|
||||
}
|
||||
|
||||
const goToEdit = (id) => {
|
||||
if (!AuthService.canEditMedicalEvents()) return;
|
||||
navigate(`/medical/events/edit/${id}?from=calendar`)
|
||||
}
|
||||
|
||||
const disableEvent = (id) => {
|
||||
if (!AuthService.canEditMedicalEvents()) return;
|
||||
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);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const toggleColorFilter = (colorValue) => {
|
||||
setSelectedColorFilters(prev =>
|
||||
prev.includes(colorValue)
|
||||
@@ -294,6 +318,20 @@ const EventsCalendar = () => {
|
||||
<div className="sx__event-modal__title">{calendarEvent?.customer}</div>
|
||||
{calendarEvent?.doctor && <div className="sx__event-modal__time">{`${calendarEvent?.doctor}`}</div>}
|
||||
<div className="sx__event-modal__time">{`${calendarEvent?.start}`}</div>
|
||||
{AuthService.canEditMedicalEvents() && <div className="sx__event-modal__time" style={{ display: 'flex', gap: '12px', marginTop: '8px' }}>
|
||||
<PencilSquare
|
||||
size={16}
|
||||
onClick={() => goToEdit(calendarEvent?.id)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Edit"
|
||||
/>
|
||||
<Archive
|
||||
size={16}
|
||||
onClick={() => { setDeleteTargetId(calendarEvent?.id); setShowDeleteConfirm(true); }}
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Delete"
|
||||
/>
|
||||
</div>}
|
||||
</>
|
||||
}
|
||||
};
|
||||
@@ -412,6 +450,20 @@ const EventsCalendar = () => {
|
||||
<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>
|
||||
{AuthService.canEditMedicalEvents() && <div style={{ display: 'flex', gap: '10px', marginTop: '6px' }} onClick={(e) => e.stopPropagation()}>
|
||||
<PencilSquare
|
||||
size={14}
|
||||
onClick={() => goToEdit(eventItem?.id)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Edit"
|
||||
/>
|
||||
<Archive
|
||||
size={14}
|
||||
onClick={() => { setDeleteTargetId(eventItem?.id); setShowDeleteConfirm(true); }}
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Delete"
|
||||
/>
|
||||
</div>}
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
@@ -592,6 +644,22 @@ const handleSave = () => {
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
<Modal show={showDeleteConfirm} onHide={() => { setShowDeleteConfirm(false); setDeleteTargetId(null); }} size="sm" centered>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Confirm Delete</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
Are you sure you want to delete this event?
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button variant="secondary" size="sm" onClick={() => { setShowDeleteConfirm(false); setDeleteTargetId(null); }}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="danger" size="sm" onClick={() => { disableEvent(deleteTargetId); setShowDeleteConfirm(false); setDeleteTargetId(null); }}>
|
||||
Delete
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -97,6 +97,11 @@ const EventsList = () => {
|
||||
const currentCustomer = customers?.find(c => c?.id === event?.data?.customer || c?.name === event?.data?.client_name || c?.name === event?.target_name);
|
||||
return currentCustomer?.disability || event?.data?.disability?.toLowerCase() === 'yes' || false;
|
||||
};
|
||||
const isEligibleDriverOption = (employee) => {
|
||||
const roles = Array.isArray(employee?.roles) ? employee.roles.map((role) => `${role || ''}`.toLowerCase()) : [];
|
||||
const permissions = Array.isArray(employee?.permissions) ? employee.permissions.map((permission) => `${permission || ''}`.toLowerCase()) : [];
|
||||
return roles.includes('driver') || permissions.includes('isdriver');
|
||||
};
|
||||
|
||||
// Default sort: 1) driver name ascending, 2) start time early to late, 3) address ascending, 4) language (empty first)
|
||||
const applyDefaultSort = (eventsArray) => {
|
||||
@@ -141,8 +146,11 @@ const EventsList = () => {
|
||||
setCustomers(data.data);
|
||||
})
|
||||
DriverService.getAllActiveDrivers().then((data) => {
|
||||
console.log('drivers', data.data);
|
||||
setDriverOptions(data.data);
|
||||
const filteredDrivers = (data?.data || [])
|
||||
.filter((employee) => employee?.status === 'active')
|
||||
.filter(isEligibleDriverOption)
|
||||
.sort((a, b) => `${a?.name || ''}`.localeCompare(`${b?.name || ''}`));
|
||||
setDriverOptions(filteredDrivers);
|
||||
})
|
||||
ResourceService.getAll().then(data => {
|
||||
setResources(data.data);
|
||||
|
||||
@@ -179,9 +179,10 @@ const RouteEdit = () => {
|
||||
if (!validateRoute()) {
|
||||
return;
|
||||
}
|
||||
// Do not persist scheduled-absence entries into route_customer_list.
|
||||
// Keep scheduled-absence customers in route assignment payload; only skip transient
|
||||
// attendance-derived placeholder rows if any are ever injected into this list.
|
||||
const filteredCustomerList = (newCustomerList || []).filter(
|
||||
(customer) => customer?.customer_route_status !== PERSONAL_ROUTE_STATUS.SCHEDULED_ABSENT
|
||||
(customer) => customer?._attendance_based !== true
|
||||
);
|
||||
const existingRouteCustomers = currentRoute?.route_customer_list || [];
|
||||
const existingByCustomerId = new Map(existingRouteCustomers.map((c) => [c?.customer_id, c]));
|
||||
@@ -677,12 +678,7 @@ const RouteEdit = () => {
|
||||
const mergedAbsentIds = Array.from(new Set([].concat(existingScheduledAbsentIds, attendanceBasedAbsentIds)));
|
||||
return (
|
||||
<RouteCustomerEditor
|
||||
currentRoute={currentRoute ? {
|
||||
...currentRoute,
|
||||
route_customer_list: currentRoute.route_customer_list?.filter(
|
||||
customer => customer?.customer_route_status !== PERSONAL_ROUTE_STATUS.SCHEDULED_ABSENT
|
||||
) || []
|
||||
} : undefined}
|
||||
currentRoute={currentRoute}
|
||||
setNewCustomerList={setNewCustomerList}
|
||||
onAddCustomer={(addFn) => setAddCustomerToRoute(() => addFn)}
|
||||
scheduledAbsentCustomerIds={mergedAbsentIds}
|
||||
|
||||
Reference in New Issue
Block a user