This commit is contained in:
@@ -607,7 +607,11 @@ const EventsCalendar = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const disableEvent = (id) => {
|
const disableEvent = (id) => {
|
||||||
if (!AuthService.canEditCalendarTab(currentTab)) return;
|
if (currentTab === 'medicalCalendar') {
|
||||||
|
if (!AuthService.canEditMedicalEvents()) return;
|
||||||
|
} else {
|
||||||
|
if (!AuthService.canEditCalendarTab(currentTab)) return;
|
||||||
|
}
|
||||||
// Handle recurring event instances
|
// Handle recurring event instances
|
||||||
const isRecurInstance = typeof id === 'string' && id.startsWith('recur-');
|
const isRecurInstance = typeof id === 'string' && id.startsWith('recur-');
|
||||||
if (isRecurInstance) {
|
if (isRecurInstance) {
|
||||||
@@ -921,7 +925,7 @@ const EventsCalendar = () => {
|
|||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
title="Edit"
|
title="Edit"
|
||||||
/>}
|
/>}
|
||||||
{currentTab !== 'medicalCalendar' && AuthService.canEditCalendarTab(currentTab) && <Archive
|
{((currentTab === 'medicalCalendar' && AuthService.canEditMedicalEvents()) || (currentTab !== 'medicalCalendar' && AuthService.canEditCalendarTab(currentTab))) && <Archive
|
||||||
size={16}
|
size={16}
|
||||||
onClick={() => { setDeleteTargetId(calendarEvent?.id); setShowDeleteConfirm(true); }}
|
onClick={() => { setDeleteTargetId(calendarEvent?.id); setShowDeleteConfirm(true); }}
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer' }}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import { createEventsServicePlugin } from '@schedule-x/events-service';
|
import { createEventsServicePlugin } from '@schedule-x/events-service';
|
||||||
import { createEventModalPlugin} from '@schedule-x/event-modal';
|
import { createEventModalPlugin} from '@schedule-x/event-modal';
|
||||||
import '@schedule-x/theme-default/dist/calendar.css';
|
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";
|
import DatePicker from "react-datepicker";
|
||||||
|
|
||||||
|
|
||||||
@@ -40,6 +40,8 @@ const EventsCalendar = () => {
|
|||||||
const [currentRangeStart, setCurrentRangeStart] = useState(null);
|
const [currentRangeStart, setCurrentRangeStart] = useState(null);
|
||||||
const [currentRangeEnd, setCurrentRangeEnd] = useState(null);
|
const [currentRangeEnd, setCurrentRangeEnd] = useState(null);
|
||||||
const [showCreationModal, setShowCreationModal] = useState(false);
|
const [showCreationModal, setShowCreationModal] = useState(false);
|
||||||
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||||
|
const [deleteTargetId, setDeleteTargetId] = useState(null);
|
||||||
const [newEventStartDateTime, setNewEventStartDateTime] = useState(new Date());
|
const [newEventStartDateTime, setNewEventStartDateTime] = useState(new Date());
|
||||||
const [newEventEndDateTime, setNewEventEndDateTime] = useState(new Date());
|
const [newEventEndDateTime, setNewEventEndDateTime] = useState(new Date());
|
||||||
const [newEventColor, setNewEventColor] = useState('');
|
const [newEventColor, setNewEventColor] = useState('');
|
||||||
@@ -270,6 +272,28 @@ const EventsCalendar = () => {
|
|||||||
navigate(`/medical/events/${id}`)
|
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) => {
|
const toggleColorFilter = (colorValue) => {
|
||||||
setSelectedColorFilters(prev =>
|
setSelectedColorFilters(prev =>
|
||||||
prev.includes(colorValue)
|
prev.includes(colorValue)
|
||||||
@@ -294,6 +318,20 @@ const EventsCalendar = () => {
|
|||||||
<div className="sx__event-modal__title">{calendarEvent?.customer}</div>
|
<div className="sx__event-modal__title">{calendarEvent?.customer}</div>
|
||||||
{calendarEvent?.doctor && <div className="sx__event-modal__time">{`${calendarEvent?.doctor}`}</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">{`${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>
|
<span style={{ fontSize: '12px' }}>{moment(eventItem?.start_time).format('HH:mm')} - {moment(eventItem?.stop_time || eventItem?.start_time).format('HH:mm')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Provider: {eventItem?.doctor || '-'}</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>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -592,6 +644,22 @@ const handleSave = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Modal.Footer>
|
</Modal.Footer>
|
||||||
</Modal>
|
</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>
|
||||||
</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);
|
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;
|
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)
|
// Default sort: 1) driver name ascending, 2) start time early to late, 3) address ascending, 4) language (empty first)
|
||||||
const applyDefaultSort = (eventsArray) => {
|
const applyDefaultSort = (eventsArray) => {
|
||||||
@@ -141,8 +146,11 @@ const EventsList = () => {
|
|||||||
setCustomers(data.data);
|
setCustomers(data.data);
|
||||||
})
|
})
|
||||||
DriverService.getAllActiveDrivers().then((data) => {
|
DriverService.getAllActiveDrivers().then((data) => {
|
||||||
console.log('drivers', data.data);
|
const filteredDrivers = (data?.data || [])
|
||||||
setDriverOptions(data.data);
|
.filter((employee) => employee?.status === 'active')
|
||||||
|
.filter(isEligibleDriverOption)
|
||||||
|
.sort((a, b) => `${a?.name || ''}`.localeCompare(`${b?.name || ''}`));
|
||||||
|
setDriverOptions(filteredDrivers);
|
||||||
})
|
})
|
||||||
ResourceService.getAll().then(data => {
|
ResourceService.getAll().then(data => {
|
||||||
setResources(data.data);
|
setResources(data.data);
|
||||||
|
|||||||
@@ -179,9 +179,10 @@ const RouteEdit = () => {
|
|||||||
if (!validateRoute()) {
|
if (!validateRoute()) {
|
||||||
return;
|
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(
|
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 existingRouteCustomers = currentRoute?.route_customer_list || [];
|
||||||
const existingByCustomerId = new Map(existingRouteCustomers.map((c) => [c?.customer_id, c]));
|
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)));
|
const mergedAbsentIds = Array.from(new Set([].concat(existingScheduledAbsentIds, attendanceBasedAbsentIds)));
|
||||||
return (
|
return (
|
||||||
<RouteCustomerEditor
|
<RouteCustomerEditor
|
||||||
currentRoute={currentRoute ? {
|
currentRoute={currentRoute}
|
||||||
...currentRoute,
|
|
||||||
route_customer_list: currentRoute.route_customer_list?.filter(
|
|
||||||
customer => customer?.customer_route_status !== PERSONAL_ROUTE_STATUS.SCHEDULED_ABSENT
|
|
||||||
) || []
|
|
||||||
} : undefined}
|
|
||||||
setNewCustomerList={setNewCustomerList}
|
setNewCustomerList={setNewCustomerList}
|
||||||
onAddCustomer={(addFn) => setAddCustomerToRoute(() => addFn)}
|
onAddCustomer={(addFn) => setAddCustomerToRoute(() => addFn)}
|
||||||
scheduledAbsentCustomerIds={mergedAbsentIds}
|
scheduledAbsentCustomerIds={mergedAbsentIds}
|
||||||
|
|||||||
Reference in New Issue
Block a user