fix
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
**/.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
|
||||
BIN
app/.DS_Store
vendored
BIN
app/.DS_Store
vendored
Binary file not shown.
@@ -692,10 +692,29 @@ input[type="number"] {
|
||||
/* box-sizing: border-box; */
|
||||
}
|
||||
|
||||
/* Exclude react-time-picker inputs from the padding rules above */
|
||||
.react-time-picker__inputGroup__input {
|
||||
padding-left: initial;
|
||||
padding-right: initial;
|
||||
/* Exclude react-time-picker inputs from the global input styles above */
|
||||
.react-time-picker .react-time-picker__inputGroup__input {
|
||||
height: auto !important;
|
||||
padding-left: 1px !important;
|
||||
padding-right: 1px !important;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
box-sizing: content-box !important;
|
||||
min-width: 0;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: normal;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Add spacing between the ":" divider and the minute input */
|
||||
.react-time-picker .react-time-picker__inputGroup__divider {
|
||||
padding: 0 3px;
|
||||
}
|
||||
|
||||
/* Ensure the leading zero and minute digit inputs have no extra spacing */
|
||||
.react-time-picker .react-time-picker__inputGroup__leadingZero {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="email"] {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useState, useEffect} from "react";
|
||||
import React, {useState, useEffect, useRef} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AuthService, EventsService, CustomerService, ResourceService } from "../../services";
|
||||
import moment from 'moment';
|
||||
@@ -24,6 +24,8 @@ import { Archive, PencilSquare, Filter } from "react-bootstrap-icons";
|
||||
const EventsCalendar = () => {
|
||||
const navigate = useNavigate();
|
||||
const [events, setEvents] = useState([]);
|
||||
const calendarColumnRef = useRef(null);
|
||||
const [listHeight, setListHeight] = useState(null);
|
||||
const [customers, setCustomers] = useState([]);
|
||||
const [resources, setResources] = useState([]);
|
||||
const [fromDate, setFromDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth(), 1));
|
||||
@@ -212,6 +214,27 @@ const EventsCalendar = () => {
|
||||
}
|
||||
}, [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]);
|
||||
|
||||
|
||||
|
||||
const redirectToAdmin = () => {
|
||||
@@ -357,38 +380,68 @@ const EventsCalendar = () => {
|
||||
<div className="app-main-content-list-func-container">
|
||||
<Tabs defaultActiveKey="eventsCalendar" id="events-calendar-tab">
|
||||
<Tab eventKey="eventsCalendar" title="Medical Appointments">
|
||||
<div className="multi-columns-container">
|
||||
<div className="column-container" style={{'minWidth': '1000px'}}>
|
||||
{calendar && <ScheduleXCalendar customComponents={customComponents} calendarApp={calendar} />}
|
||||
</div>
|
||||
<div className="column-container">
|
||||
<div className="column-card" style={{ maxHeight: '800px', overflowY: 'auto', overflowX: 'hidden' }}>
|
||||
<h6 className="text-primary me-4">List</h6>
|
||||
{
|
||||
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-4 event-list-item-container`}
|
||||
onClick={() => goToView(eventItem.id)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div className="event-item-flex">
|
||||
<div className="sx__month-agenda-event__title">{`${moment(eventItem?.start_time).format('hh:mm A')}: ${formatFullName(eventItem.customer)}`}</div>
|
||||
</div>
|
||||
<div className="sx__event-modal__time with-padding">{`provider: ${eventItem?.doctor}`}</div>
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<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} />}
|
||||
{/* 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">
|
||||
{EventsService.labelOptions?.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={() => goToView(eventItem.id)}
|
||||
style={{ cursor: 'pointer', padding: '8px 12px', borderRadius: '4px' }}
|
||||
>
|
||||
<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>
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="list-func-panel">
|
||||
<Dropdown
|
||||
key={'event-calendar-filter'}
|
||||
|
||||
@@ -5,6 +5,7 @@ import DatePicker from "react-datepicker";
|
||||
import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab, Button, Modal } from "react-bootstrap";
|
||||
import { Columns, Download, Filter, PencilSquare, PersonSquare, Plus } from "react-bootstrap-icons";
|
||||
import TimePicker from 'react-time-picker';
|
||||
import 'react-time-picker/dist/TimePicker.css';
|
||||
import { ManageTable, Export } from "../../shared/components";
|
||||
|
||||
const EventsList = () => {
|
||||
|
||||
@@ -521,10 +521,8 @@ const InfoScreen = () => {
|
||||
(customers.find(c => c.id === item?.data?.customer)?.name || item?.data?.client_name || '') :
|
||||
(item?.data?.client_name || '');
|
||||
|
||||
// Add location/address
|
||||
item.location = item?.data?.resource ?
|
||||
(resources.find(r => r.id === item?.data?.resource)?.address || item?.data?.resource_address || '') :
|
||||
(item?.data?.resource_address || '');
|
||||
// Add driver info (from linked transportation event)
|
||||
item.driverInfo = item?.link_event_name || '';
|
||||
|
||||
// Format start time
|
||||
item.startTime = item?.start_time ?
|
||||
@@ -647,7 +645,7 @@ const InfoScreen = () => {
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Customer</th>
|
||||
<th>Location</th>
|
||||
<th>Driver</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -656,7 +654,7 @@ const InfoScreen = () => {
|
||||
<tr key={medicalEvent.id}>
|
||||
<td>{medicalEvent.startTime}</td>
|
||||
<td>{medicalEvent.customer}</td>
|
||||
<td>{medicalEvent.location}</td>
|
||||
<td>{medicalEvent.driverInfo}</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
@@ -934,7 +932,7 @@ const InfoScreen = () => {
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Customer</th>
|
||||
<th>Location</th>
|
||||
<th>Driver</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -943,7 +941,7 @@ const InfoScreen = () => {
|
||||
<tr key={medicalEvent.id}>
|
||||
<td>{medicalEvent.startTime}</td>
|
||||
<td>{medicalEvent.customer}</td>
|
||||
<td>{medicalEvent.location}</td>
|
||||
<td>{medicalEvent.driverInfo}</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user