fix
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
**/.DS_Store
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.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; */
|
/* box-sizing: border-box; */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exclude react-time-picker inputs from the padding rules above */
|
/* Exclude react-time-picker inputs from the global input styles above */
|
||||||
.react-time-picker__inputGroup__input {
|
.react-time-picker .react-time-picker__inputGroup__input {
|
||||||
padding-left: initial;
|
height: auto !important;
|
||||||
padding-right: initial;
|
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"] {
|
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 { useNavigate } from "react-router-dom";
|
||||||
import { AuthService, EventsService, CustomerService, ResourceService } from "../../services";
|
import { AuthService, EventsService, CustomerService, ResourceService } from "../../services";
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
@@ -24,6 +24,8 @@ import { Archive, PencilSquare, Filter } from "react-bootstrap-icons";
|
|||||||
const EventsCalendar = () => {
|
const EventsCalendar = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [events, setEvents] = useState([]);
|
const [events, setEvents] = useState([]);
|
||||||
|
const calendarColumnRef = useRef(null);
|
||||||
|
const [listHeight, setListHeight] = useState(null);
|
||||||
const [customers, setCustomers] = useState([]);
|
const [customers, setCustomers] = useState([]);
|
||||||
const [resources, setResources] = useState([]);
|
const [resources, setResources] = useState([]);
|
||||||
const [fromDate, setFromDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth(), 1));
|
const [fromDate, setFromDate] = useState(new Date(new Date().getFullYear(), new Date().getMonth(), 1));
|
||||||
@@ -212,6 +214,27 @@ const EventsCalendar = () => {
|
|||||||
}
|
}
|
||||||
}, [events, currentRangeStart, currentRangeEnd]);
|
}, [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 = () => {
|
const redirectToAdmin = () => {
|
||||||
@@ -357,13 +380,43 @@ const EventsCalendar = () => {
|
|||||||
<div className="app-main-content-list-func-container">
|
<div className="app-main-content-list-func-container">
|
||||||
<Tabs defaultActiveKey="eventsCalendar" id="events-calendar-tab">
|
<Tabs defaultActiveKey="eventsCalendar" id="events-calendar-tab">
|
||||||
<Tab eventKey="eventsCalendar" title="Medical Appointments">
|
<Tab eventKey="eventsCalendar" title="Medical Appointments">
|
||||||
<div className="multi-columns-container">
|
|
||||||
<div className="column-container" style={{'minWidth': '1000px'}}>
|
</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} />}
|
{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 className="column-container">
|
))}
|
||||||
<div className="column-card" style={{ maxHeight: '800px', overflowY: 'auto', overflowX: 'hidden' }}>
|
</div>
|
||||||
<h6 className="text-primary me-4">List</h6>
|
</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) => {
|
Array.from(groupedEvents?.keys())?.map((key) => {
|
||||||
return <div key={key}>
|
return <div key={key}>
|
||||||
@@ -371,14 +424,15 @@ const EventsCalendar = () => {
|
|||||||
{
|
{
|
||||||
groupedEvents.get(key).map(eventItem => <div
|
groupedEvents.get(key).map(eventItem => <div
|
||||||
key={eventItem.id}
|
key={eventItem.id}
|
||||||
className={`event-${eventItem.color || 'primary'} mb-4 event-list-item-container`}
|
className={`event-${eventItem.color || 'primary'} mb-3 event-list-item-container`}
|
||||||
onClick={() => goToView(eventItem.id)}
|
onClick={() => goToView(eventItem.id)}
|
||||||
style={{ cursor: 'pointer' }}
|
style={{ cursor: 'pointer', padding: '8px 12px', borderRadius: '4px' }}
|
||||||
>
|
>
|
||||||
<div className="event-item-flex">
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<div className="sx__month-agenda-event__title">{`${moment(eventItem?.start_time).format('hh:mm A')}: ${formatFullName(eventItem.customer)}`}</div>
|
<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>
|
||||||
<div className="sx__event-modal__time with-padding">{`provider: ${eventItem?.doctor}`}</div>
|
<div className="sx__event-modal__time" style={{ fontSize: '12px', marginTop: '4px' }}>Provider: {eventItem?.doctor || '-'}</div>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -387,8 +441,7 @@ const EventsCalendar = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</div>
|
||||||
</Tabs>
|
|
||||||
<div className="list-func-panel">
|
<div className="list-func-panel">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
key={'event-calendar-filter'}
|
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 { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab, Button, Modal } from "react-bootstrap";
|
||||||
import { Columns, Download, Filter, PencilSquare, PersonSquare, Plus } from "react-bootstrap-icons";
|
import { Columns, Download, Filter, PencilSquare, PersonSquare, Plus } from "react-bootstrap-icons";
|
||||||
import TimePicker from 'react-time-picker';
|
import TimePicker from 'react-time-picker';
|
||||||
|
import 'react-time-picker/dist/TimePicker.css';
|
||||||
import { ManageTable, Export } from "../../shared/components";
|
import { ManageTable, Export } from "../../shared/components";
|
||||||
|
|
||||||
const EventsList = () => {
|
const EventsList = () => {
|
||||||
|
|||||||
@@ -521,10 +521,8 @@ const InfoScreen = () => {
|
|||||||
(customers.find(c => c.id === item?.data?.customer)?.name || item?.data?.client_name || '') :
|
(customers.find(c => c.id === item?.data?.customer)?.name || item?.data?.client_name || '') :
|
||||||
(item?.data?.client_name || '');
|
(item?.data?.client_name || '');
|
||||||
|
|
||||||
// Add location/address
|
// Add driver info (from linked transportation event)
|
||||||
item.location = item?.data?.resource ?
|
item.driverInfo = item?.link_event_name || '';
|
||||||
(resources.find(r => r.id === item?.data?.resource)?.address || item?.data?.resource_address || '') :
|
|
||||||
(item?.data?.resource_address || '');
|
|
||||||
|
|
||||||
// Format start time
|
// Format start time
|
||||||
item.startTime = item?.start_time ?
|
item.startTime = item?.start_time ?
|
||||||
@@ -647,7 +645,7 @@ const InfoScreen = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Time</th>
|
<th>Time</th>
|
||||||
<th>Customer</th>
|
<th>Customer</th>
|
||||||
<th>Location</th>
|
<th>Driver</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -656,7 +654,7 @@ const InfoScreen = () => {
|
|||||||
<tr key={medicalEvent.id}>
|
<tr key={medicalEvent.id}>
|
||||||
<td>{medicalEvent.startTime}</td>
|
<td>{medicalEvent.startTime}</td>
|
||||||
<td>{medicalEvent.customer}</td>
|
<td>{medicalEvent.customer}</td>
|
||||||
<td>{medicalEvent.location}</td>
|
<td>{medicalEvent.driverInfo}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@@ -934,7 +932,7 @@ const InfoScreen = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Time</th>
|
<th>Time</th>
|
||||||
<th>Customer</th>
|
<th>Customer</th>
|
||||||
<th>Location</th>
|
<th>Driver</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -943,7 +941,7 @@ const InfoScreen = () => {
|
|||||||
<tr key={medicalEvent.id}>
|
<tr key={medicalEvent.id}>
|
||||||
<td>{medicalEvent.startTime}</td>
|
<td>{medicalEvent.startTime}</td>
|
||||||
<td>{medicalEvent.customer}</td>
|
<td>{medicalEvent.customer}</td>
|
||||||
<td>{medicalEvent.location}</td>
|
<td>{medicalEvent.driverInfo}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user