fix
This commit is contained in:
BIN
app/.DS_Store
vendored
BIN
app/.DS_Store
vendored
Binary file not shown.
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.6616f3cb.css",
|
||||
"main.js": "/static/js/main.02f98813.js",
|
||||
"main.css": "/static/css/main.3cda7e3a.css",
|
||||
"main.js": "/static/js/main.171aba0b.js",
|
||||
"static/js/787.c4e7f8f9.chunk.js": "/static/js/787.c4e7f8f9.chunk.js",
|
||||
"static/media/landing.png": "/static/media/landing.d4c6072db7a67dff6a78.png",
|
||||
"index.html": "/index.html",
|
||||
"main.6616f3cb.css.map": "/static/css/main.6616f3cb.css.map",
|
||||
"main.02f98813.js.map": "/static/js/main.02f98813.js.map",
|
||||
"main.3cda7e3a.css.map": "/static/css/main.3cda7e3a.css.map",
|
||||
"main.171aba0b.js.map": "/static/js/main.171aba0b.js.map",
|
||||
"787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.6616f3cb.css",
|
||||
"static/js/main.02f98813.js"
|
||||
"static/css/main.3cda7e3a.css",
|
||||
"static/js/main.171aba0b.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.02f98813.js"></script><link href="/static/css/main.6616f3cb.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><link rel="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.171aba0b.js"></script><link href="/static/css/main.3cda7e3a.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
1
app/views/static/css/main.3cda7e3a.css.map
Normal file
1
app/views/static/css/main.3cda7e3a.css.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
client/.DS_Store
vendored
BIN
client/.DS_Store
vendored
Binary file not shown.
BIN
client/build/.DS_Store
vendored
BIN
client/build/.DS_Store
vendored
Binary file not shown.
@@ -557,13 +557,22 @@ table .group td {
|
||||
border-color: #ccc!important;
|
||||
}
|
||||
|
||||
.react-time-picker__wrapper input[type=number] {
|
||||
border:none;
|
||||
.react-time-picker__wrapper input[type=number],
|
||||
.react-datetime-picker__wrapper input[type=number] {
|
||||
border: none;
|
||||
padding-left: 2px !important;
|
||||
padding-right: 2px !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.app-main-content-fields-section .field-value {
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
min-height: 1.2em;
|
||||
}
|
||||
|
||||
.app-main-content-fields-section .field-value:empty::before {
|
||||
content: '\00a0';
|
||||
}
|
||||
|
||||
.app-main-content-fields-section .field-body {
|
||||
@@ -748,29 +757,46 @@ input[type="number"] {
|
||||
/* box-sizing: border-box; */
|
||||
}
|
||||
|
||||
/* Exclude react-time-picker inputs from the global input styles above */
|
||||
.react-time-picker .react-time-picker__inputGroup__input {
|
||||
/* Exclude react-time-picker and react-datetime-picker inputs from global input styles */
|
||||
.react-time-picker .react-time-picker__inputGroup__input,
|
||||
.react-datetime-picker .react-datetime-picker__inputGroup__input {
|
||||
height: auto !important;
|
||||
padding-left: 1px !important;
|
||||
padding-right: 1px !important;
|
||||
padding-left: 2px !important;
|
||||
padding-right: 2px !important;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
box-sizing: content-box !important;
|
||||
min-width: 0;
|
||||
min-width: 0.54em !important;
|
||||
width: auto !important;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: normal;
|
||||
text-align: center;
|
||||
appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
/* Hide number input spinners inside pickers */
|
||||
.react-time-picker input[type=number]::-webkit-inner-spin-button,
|
||||
.react-time-picker input[type=number]::-webkit-outer-spin-button,
|
||||
.react-datetime-picker input[type=number]::-webkit-inner-spin-button,
|
||||
.react-datetime-picker input[type=number]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Add spacing between the ":" divider and the minute input */
|
||||
.react-time-picker .react-time-picker__inputGroup__divider {
|
||||
.react-time-picker .react-time-picker__inputGroup__divider,
|
||||
.react-datetime-picker .react-datetime-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 {
|
||||
/* Ensure the leading zero and digit inputs have no extra spacing */
|
||||
.react-time-picker .react-time-picker__inputGroup__leadingZero,
|
||||
.react-datetime-picker .react-datetime-picker__inputGroup__leadingZero {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: inline;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
input[type="email"] {
|
||||
@@ -1712,6 +1738,8 @@ input[type="checkbox"] {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.stage {
|
||||
|
||||
@@ -243,11 +243,12 @@ const EventsCalendar = () => {
|
||||
setToDate(new Date(endDate.getFullYear(), endDate.getMonth() + 1, 0));
|
||||
},
|
||||
onClickDate(date) {
|
||||
if (currentTab === 'medicalCalendar') return;
|
||||
// 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') {
|
||||
// Default to 10:00 AM for Activities tab
|
||||
if (currentTab === 'activitiesCalendar') {
|
||||
localDate.setHours(10, 0, 0, 0);
|
||||
}
|
||||
setNewEventStartDateTime(localDate);
|
||||
@@ -255,6 +256,7 @@ const EventsCalendar = () => {
|
||||
setShowCreationModal(true);
|
||||
},
|
||||
onClickDateTime(dateTime) {
|
||||
if (currentTab === 'medicalCalendar') return;
|
||||
setNewEventStartDateTime(new Date(dateTime.replace(' ', 'T')));
|
||||
setNewEventEndDateTime(new Date(dateTime.replace(' ', 'T')));
|
||||
setShowCreationModal(true);
|
||||
@@ -821,12 +823,12 @@ const EventsCalendar = () => {
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Edit"
|
||||
/>
|
||||
<Archive
|
||||
{currentTab !== 'medicalCalendar' && <Archive
|
||||
size={16}
|
||||
onClick={() => { setDeleteTargetId(calendarEvent?.id); setShowDeleteConfirm(true); }}
|
||||
style={{ cursor: 'pointer' }}
|
||||
title="Delete"
|
||||
/>
|
||||
/>}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
@@ -842,13 +844,6 @@ const EventsCalendar = () => {
|
||||
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' ? (
|
||||
|
||||
@@ -436,7 +436,18 @@ const CreateCustomer = () => {
|
||||
// Additional Information
|
||||
note,
|
||||
edit_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name || '',
|
||||
status: 'active'
|
||||
status: 'active',
|
||||
|
||||
// Form Submission flags
|
||||
hipaa_authorization_form: !!hipaaAuthorizationForm,
|
||||
medication_management_consent_form: !!medicationManagementConsentForm,
|
||||
freedom_of_choice_form: !!freedomOfChoiceForm,
|
||||
meal_benefit_application_form: !!mealBenefitApplicationForm,
|
||||
photo_video_release_form: !!photoVideoReleaseForm,
|
||||
security_deposit_agreement_form: !!securityDepositAgreementForm,
|
||||
recreational_program_contract_form: !!recreationalProgramContractForm,
|
||||
tb_form: !!tbForm,
|
||||
pre_screening_form: !!preScreeningForm,
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
@@ -445,6 +456,24 @@ const CreateCustomer = () => {
|
||||
if (selectedFile) {
|
||||
payload = Object.assign({}, payload, {avatar: formData})
|
||||
}
|
||||
|
||||
// Collect form files for upload after customer creation
|
||||
const formFiles = [
|
||||
{ file: hipaaAuthorizationForm, fileType: 'hipaa_authorization_form' },
|
||||
{ file: medicationManagementConsentForm, fileType: 'medication_management_consent_form' },
|
||||
{ file: freedomOfChoiceForm, fileType: 'freedom_of_choice_form' },
|
||||
{ file: mealBenefitApplicationForm, fileType: 'meal_benefit_application_form' },
|
||||
{ file: photoVideoReleaseForm, fileType: 'photo_video_release_form' },
|
||||
{ file: securityDepositAgreementForm, fileType: 'security_deposit_agreement_form' },
|
||||
{ file: recreationalProgramContractForm, fileType: 'recreational_program_contract_form' },
|
||||
{ file: tbForm, fileType: 'tb_form' },
|
||||
{ file: preScreeningForm, fileType: 'pre_screening_form' },
|
||||
].filter(f => f.file);
|
||||
|
||||
if (formFiles.length > 0) {
|
||||
payload = Object.assign({}, payload, { formFiles });
|
||||
}
|
||||
|
||||
dispatch(createCustomer(payload));
|
||||
redirectTo();
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
YES_NO, YES_NO_TEXT,
|
||||
PREFERRED_TEXT_LANGUAGE, PREFERRED_TEXT_LANGUAGE_TEXT
|
||||
} from "../../shared";
|
||||
import { Upload, BoxArrowRight } from "react-bootstrap-icons";
|
||||
import { Upload, BoxArrowRight, CheckCircleFill } from "react-bootstrap-icons";
|
||||
|
||||
const UpdateCustomer = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -733,7 +733,18 @@ const UpdateCustomer = () => {
|
||||
// Additional Information
|
||||
note,
|
||||
edit_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name || '',
|
||||
status: 'active'
|
||||
status: 'active',
|
||||
|
||||
// Form Submission flags
|
||||
hipaa_authorization_form: hipaaAuthorizationForm ? true : (currentCustomer?.hipaa_authorization_form || false),
|
||||
medication_management_consent_form: medicationManagementConsentForm ? true : (currentCustomer?.medication_management_consent_form || false),
|
||||
freedom_of_choice_form: freedomOfChoiceForm ? true : (currentCustomer?.freedom_of_choice_form || false),
|
||||
meal_benefit_application_form: mealBenefitApplicationForm ? true : (currentCustomer?.meal_benefit_application_form || false),
|
||||
photo_video_release_form: photoVideoReleaseForm ? true : (currentCustomer?.photo_video_release_form || false),
|
||||
security_deposit_agreement_form: securityDepositAgreementForm ? true : (currentCustomer?.security_deposit_agreement_form || false),
|
||||
recreational_program_contract_form: recreationalProgramContractForm ? true : (currentCustomer?.recreational_program_contract_form || false),
|
||||
tb_form: tbForm ? true : (currentCustomer?.tb_form || false),
|
||||
pre_screening_form: preScreeningForm ? true : (currentCustomer?.pre_screening_form || false),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -764,6 +775,13 @@ const UpdateCustomer = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const uploadFormFile = (file, fileType) => {
|
||||
if (!file) return;
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
CustomerService.uploadCustomerFile(fd, urlParams.id, currentCustomer?.name || '', fileType);
|
||||
};
|
||||
|
||||
const saveCustomer = () => {
|
||||
if (!validateCustomer()) {
|
||||
return;
|
||||
@@ -778,6 +796,18 @@ const UpdateCustomer = () => {
|
||||
payload = Object.assign({}, payload, {avatar: formData})
|
||||
}
|
||||
dispatch(updateCustomer(payload));
|
||||
|
||||
// Upload form files
|
||||
uploadFormFile(hipaaAuthorizationForm, 'hipaa_authorization_form');
|
||||
uploadFormFile(medicationManagementConsentForm, 'medication_management_consent_form');
|
||||
uploadFormFile(freedomOfChoiceForm, 'freedom_of_choice_form');
|
||||
uploadFormFile(mealBenefitApplicationForm, 'meal_benefit_application_form');
|
||||
uploadFormFile(photoVideoReleaseForm, 'photo_video_release_form');
|
||||
uploadFormFile(securityDepositAgreementForm, 'security_deposit_agreement_form');
|
||||
uploadFormFile(recreationalProgramContractForm, 'recreational_program_contract_form');
|
||||
uploadFormFile(tbForm, 'tb_form');
|
||||
uploadFormFile(preScreeningForm, 'pre_screening_form');
|
||||
|
||||
setTimeout(() => {
|
||||
redirectToView();
|
||||
}, 3000);
|
||||
@@ -1562,24 +1592,27 @@ const UpdateCustomer = () => {
|
||||
<div className="app-main-content-fields-section base-line">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Maryland HIPAA Authorization</div>
|
||||
{currentCustomer?.hipaa_authorization_form && !hipaaAuthorizationForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.hipaa_authorization_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setHipaaAuthorizationForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{hipaaAuthorizationForm?.name}</div>
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Medication Management Consent Form</div>
|
||||
{currentCustomer?.medication_management_consent_form && !medicationManagementConsentForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.medication_management_consent_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setMedicationManagementConsentForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{medicationManagementConsentForm?.name}</div>
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Freedom Of Choice (Medicaid only)</div>
|
||||
{currentCustomer?.freedom_of_choice_form && !freedomOfChoiceForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.freedom_of_choice_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setFreedomOfChoiceForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{freedomOfChoiceForm?.name}</div>
|
||||
@@ -1588,24 +1621,27 @@ const UpdateCustomer = () => {
|
||||
<div className="app-main-content-fields-section base-line">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Meal Benefit Application</div>
|
||||
{currentCustomer?.meal_benefit_application_form && !mealBenefitApplicationForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.meal_benefit_application_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setMealBenefitApplicationForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{mealBenefitApplicationForm?.name}</div>
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Photo-Video Release Waiver Form</div>
|
||||
{currentCustomer?.photo_video_release_form && !photoVideoReleaseForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.photo_video_release_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setPhotoVideoReleaseForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{photoVideoReleaseForm?.name}</div>
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Security Deposit Payment Agreement (Self Pay only)</div>
|
||||
{currentCustomer?.security_deposit_agreement_form && !securityDepositAgreementForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.security_deposit_agreement_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setSecurityDepositAgreementForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{securityDepositAgreementForm?.name}</div>
|
||||
@@ -1614,8 +1650,9 @@ const UpdateCustomer = () => {
|
||||
<div className="app-main-content-fields-section base-line">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Recreational Program Contract (Senior Plus only)</div>
|
||||
{currentCustomer?.recreational_program_contract_form && !recreationalProgramContractForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.recreational_program_contract_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setRecreationalProgramContractForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{recreationalProgramContractForm?.name}</div>
|
||||
@@ -1627,16 +1664,18 @@ const UpdateCustomer = () => {
|
||||
<div className="app-main-content-fields-section base-line">
|
||||
<div className="me-4">
|
||||
<div className="field-label">TB Form</div>
|
||||
{currentCustomer?.tb_form && !tbForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.tb_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setTbForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{tbForm?.name}</div>
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Pre-Screening Form</div>
|
||||
{currentCustomer?.pre_screening_form && !preScreeningForm && <div style={{color: '#28a745', fontSize: '12px', marginBottom: '4px'}}><CheckCircleFill size={12} className="me-1"/>Uploaded</div>}
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> {currentCustomer?.pre_screening_form ? 'Replace' : 'Upload'}
|
||||
<input type="file" onChange={(e) => setPreScreeningForm(e.target.files[0])}/>
|
||||
</label>
|
||||
<div className="file-name">{preScreeningForm?.name}</div>
|
||||
|
||||
@@ -100,6 +100,7 @@ const Seating = () => {
|
||||
const [deletedItems, setDeletedItems] = useState([]);
|
||||
const [editingLabelId, setEditingLabelId] = useState(null);
|
||||
const [editingLabelName, setEditingLabelName] = useState('');
|
||||
const [editingLabelColorId, setEditingLabelColorId] = useState(null);
|
||||
|
||||
const [selectedCustomer, setSelectedCustomer] = useState(undefined);
|
||||
const [selectedCustomerLabel, setSelectedCustomerLabel] = useState(undefined);
|
||||
@@ -646,12 +647,11 @@ const Seating = () => {
|
||||
setStartAddLabel(false);
|
||||
setEditingLabelId(null);
|
||||
setEditingLabelName('');
|
||||
setEditingLabelColorId(null);
|
||||
}
|
||||
|
||||
const onDeleteLabel = (item) => {
|
||||
setCurrentLabels(prevLabels => ({
|
||||
...prevLabels.filter(lb => lb.id !== item.id)
|
||||
}))
|
||||
setCurrentLabels(prevLabels => prevLabels.filter(lb => lb.id !== item.id))
|
||||
setDeletedItems(prevLabels => ([
|
||||
...prevLabels,
|
||||
item
|
||||
@@ -680,6 +680,16 @@ const Seating = () => {
|
||||
setEditingLabelName('');
|
||||
}
|
||||
|
||||
const saveEditingLabelColor = (labelId, newColor) => {
|
||||
LabelService.updateLabel(labelId, { label_color: newColor }).then(() => {
|
||||
LabelService.getAll('active').then(data => {
|
||||
setCurrentLabels(data?.data);
|
||||
setOriginalLabelsList(data?.data);
|
||||
});
|
||||
});
|
||||
setEditingLabelColorId(null);
|
||||
}
|
||||
|
||||
const handleFullScreen = () => {
|
||||
setIsFullScreen(true);
|
||||
}
|
||||
@@ -1134,7 +1144,11 @@ const Seating = () => {
|
||||
<div className="mb-4">
|
||||
{
|
||||
currentLabels.map((item) => <div className="label-delete-item" key={item.id}>
|
||||
<span style={{width: '16px', height: '16px', borderRadius: '16px', background: item.label_color, flexShrink: 0 }}></span>
|
||||
<span
|
||||
style={{width: '16px', height: '16px', borderRadius: '16px', background: item.label_color, flexShrink: 0, cursor: 'pointer', border: editingLabelColorId === item.id ? '2px solid #333' : 'none' }}
|
||||
onClick={() => setEditingLabelColorId(editingLabelColorId === item.id ? null : item.id)}
|
||||
title="Click to change color"
|
||||
></span>
|
||||
{editingLabelId === item.id ? (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '4px', flex: 1, marginLeft: '8px' }}>
|
||||
<input
|
||||
@@ -1155,6 +1169,21 @@ const Seating = () => {
|
||||
<FileX size={16} style={{ cursor: 'pointer' }} onClick={() => onDeleteLabel(item)} />
|
||||
</>
|
||||
)}
|
||||
{editingLabelColorId === item.id && (
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px', marginTop: '6px', padding: '6px', background: '#f8f8f8', borderRadius: '6px', width: '100%' }}>
|
||||
{colorsList.map(color => (
|
||||
<span
|
||||
key={color}
|
||||
onClick={() => saveEditingLabelColor(item.id, color)}
|
||||
style={{
|
||||
width: '20px', height: '20px', borderRadius: '50%', background: color, cursor: 'pointer',
|
||||
border: item.label_color === color ? '2px solid #333' : '2px solid transparent',
|
||||
display: 'inline-block'
|
||||
}}
|
||||
></span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>)
|
||||
}
|
||||
</div>
|
||||
@@ -1233,7 +1262,7 @@ const Seating = () => {
|
||||
}
|
||||
</div>
|
||||
{
|
||||
currentLabels.map((item) => <div className="mb-4" style={{fontSize: '12px'}} key={item.id}><span style={{width: '16px', height: '16px', borderRadius: '16px', background: item.label_color, display: 'inline-block', marginRight: '8px' }}></span>{item.label_name}</div>)
|
||||
currentLabels.map((item) => <div className="mb-4" style={{fontSize: '12px', display: 'inline-flex', alignItems: 'center', marginRight: '16px'}} key={item.id}><span style={{width: '16px', height: '16px', borderRadius: '16px', background: item.label_color, display: 'inline-block', marginRight: '8px' }}></span>{item.label_name}</div>)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,8 @@ const BreakfastSection = ({transRoutes, breakfastRecords, sectionName, confimHas
|
||||
|
||||
const createBreakfastForAll = async () => {
|
||||
const dateStr = moment(selectedDate || new Date()).format('MM/DD/YYYY');
|
||||
for (const c of customers) {
|
||||
const unconfirmed = customers.filter(c => !c.has_breakfast);
|
||||
for (const c of unconfirmed) {
|
||||
await TransRoutesService.createBreakfastRecords({
|
||||
customer_id: c?.customer_id,
|
||||
customer_name: c?.customer_name,
|
||||
@@ -39,7 +40,7 @@ const BreakfastSection = ({transRoutes, breakfastRecords, sectionName, confimHas
|
||||
return (
|
||||
<>
|
||||
<div className="text-primary mb-4"><h5>{sectionName} {` (${customers?.length})`}</h5></div>
|
||||
{breakfastRecords?.length <= 0 && (<div className="mb-2 mt-2"><button onClick={() => createBreakfastForAll()} className="btn btn-primary btn-sm">Confirm All Breakfast</button></div>)}
|
||||
{customers?.some(c => !c.has_breakfast) && (<div className="mb-2 mt-2"><button onClick={() => createBreakfastForAll()} className="btn btn-primary btn-sm">Confirm All Breakfast</button></div>)}
|
||||
<div className="list row">
|
||||
<div className="col-md-12">
|
||||
<table className="personnel-info-table">
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, {useState, useEffect} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AuthService, DailyRoutesTemplateService } from "../../services";
|
||||
import { Breadcrumb, Modal, Button, Tabs, Tab } from "react-bootstrap";
|
||||
import { PencilSquare, Eye } from "react-bootstrap-icons";
|
||||
import { PencilSquare } from "react-bootstrap-icons";
|
||||
import ReactPaginate from 'react-paginate';
|
||||
|
||||
const DailyTemplatesList = () => {
|
||||
@@ -173,7 +173,6 @@ const DailyTemplatesList = () => {
|
||||
{column.label} <span className="float-right" onClick={() => sortTableWithField(column.key)}><img src={`/images/${getSortingImg(column.key)}.png`} alt="sort"></img></span>
|
||||
</th>)
|
||||
}
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -188,9 +187,6 @@ const DailyTemplatesList = () => {
|
||||
{columns.find(col => col.key === 'routes_count')?.show && <td>{template?.routes_count}</td>}
|
||||
{columns.find(col => col.key === 'create_by')?.show && <td>{template?.create_by}</td>}
|
||||
{columns.find(col => col.key === 'create_date')?.show && <td>{template?.create_date}</td>}
|
||||
<td>
|
||||
<Eye size={16} className="clickable me-2" onClick={() => goToView(template?.id)} title="View" />
|
||||
</td>
|
||||
</tr>)
|
||||
}
|
||||
</tbody>
|
||||
|
||||
@@ -8,7 +8,8 @@ const LunchSection = ({transRoutes, lunchRecords, sectionName, confirmHasLunch,
|
||||
|
||||
const createLunchForAll = async () => {
|
||||
const dateStr = moment(selectedDate || new Date()).format('MM/DD/YYYY');
|
||||
for (const c of customers) {
|
||||
const unconfirmed = customers.filter(c => !c.has_lunch);
|
||||
for (const c of unconfirmed) {
|
||||
await TransRoutesService.createLunchRecords({
|
||||
customer_id: c?.customer_id,
|
||||
customer_name: c?.customer_name,
|
||||
@@ -39,7 +40,7 @@ const LunchSection = ({transRoutes, lunchRecords, sectionName, confirmHasLunch,
|
||||
return (
|
||||
<>
|
||||
<div className="text-primary mb-4"><h5>{sectionName} {` (${customers?.length})`}</h5></div>
|
||||
{lunchRecords?.length <= 0 && (<div className="mb-2 mt-2"><button onClick={() => createLunchForAll()} className="btn btn-primary btn-sm">Confirm All Lunch</button></div>)}
|
||||
{customers?.some(c => !c.has_lunch) && (<div className="mb-2 mt-2"><button onClick={() => createLunchForAll()} className="btn btn-primary btn-sm">Confirm All Lunch</button></div>)}
|
||||
<div className="list row">
|
||||
<div className="col-md-12">
|
||||
<table className="personnel-info-table">
|
||||
|
||||
@@ -593,7 +593,7 @@ const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, view
|
||||
if (item?.customers) {
|
||||
return <Card key={index} index={index} moveCard={reorderItems} content={(<div className="customers-dnd-item-container">
|
||||
<div className="stop-index"><span>{`Stop ${index+1}`}</span><RecordCircleFill size={16} color={"#0d6efd"} className="ms-2"></RecordCircleFill> </div>
|
||||
<GripVertical className="me-4" size={14}></GripVertical>
|
||||
<GripVertical className="me-4" size={20}></GripVertical>
|
||||
<div className="customer-dnd-item" onClick={() => openEditAptGroupModal(index, item)}>
|
||||
<span className="me-2">{item.customer_group} </span> <span>{item.customers[0]?.customer_group_address}</span>
|
||||
<div className="customer-dnd-item-content">{item.customers.map(customer =>
|
||||
@@ -610,7 +610,7 @@ const RouteCustomerEditor = ({currentRoute, setNewCustomerList = (a) => {}, view
|
||||
} else {
|
||||
return <Card key={index} index={index} moveCard={reorderItems} content={<div className="customers-dnd-item-container">
|
||||
<div className="stop-index"><span>{`Stop ${index+1}`}</span><RecordCircleFill size={16} color={"#0d6efd"} className="ms-2"></RecordCircleFill> </div>
|
||||
<GripVertical className="me-4" size={14}></GripVertical>
|
||||
<GripVertical className="me-4" size={20}></GripVertical>
|
||||
<div className="customer-dnd-item">
|
||||
<span>{item.customer_name} </span>
|
||||
<small className="me-2">{item.customer_address}</small>
|
||||
|
||||
@@ -366,7 +366,7 @@ const RouteEdit = () => {
|
||||
|
||||
return (
|
||||
<div ref={drag} style={{ opacity }} className="customers-dnd-item-container-absent">
|
||||
<GripVertical className="me-4" size={14}></GripVertical>
|
||||
<GripVertical className="me-4" size={20}></GripVertical>
|
||||
<div className="customer-dnd-item">
|
||||
<span>{customer.name} </span>
|
||||
<small className="me-2">{customer.address1}</small>
|
||||
@@ -592,7 +592,7 @@ const RouteEdit = () => {
|
||||
// Existing scheduled absences from route data
|
||||
currentRoute?.route_customer_list?.filter(customer => customer?.customer_route_status === PERSONAL_ROUTE_STATUS.SCHEDULED_ABSENT)?.map((abItem) => {
|
||||
return <div key={abItem.customer_id} className="customers-dnd-item-container-absent">
|
||||
<GripVertical className="me-4" size={14}></GripVertical>
|
||||
<GripVertical className="me-4" size={20}></GripVertical>
|
||||
<div className="customer-dnd-item">
|
||||
<span>{abItem.customer_name} </span>
|
||||
<small className="me-2">{abItem.customer_address}</small>
|
||||
@@ -612,7 +612,7 @@ const RouteEdit = () => {
|
||||
.filter(a => !existingIds.has(a.customer_id))
|
||||
.map((abItem) => (
|
||||
<div key={`att-${abItem.customer_id}`} className="customers-dnd-item-container-absent" style={{ opacity: 0.85 }}>
|
||||
<GripVertical className="me-4" size={14}></GripVertical>
|
||||
<GripVertical className="me-4" size={20}></GripVertical>
|
||||
<div className="customer-dnd-item">
|
||||
<span>{abItem.customer_name} </span>
|
||||
<small className="me-2">{abItem.customer_address}</small>
|
||||
|
||||
@@ -8,7 +8,8 @@ const SnackSection = ({transRoutes, snackRecords, sectionName, confirmHasSnack,
|
||||
|
||||
const createSnackForAll = async () => {
|
||||
const dateStr = moment(selectedDate || new Date()).format('MM/DD/YYYY');
|
||||
for (const c of customers) {
|
||||
const unconfirmed = customers.filter(c => !c.has_snack);
|
||||
for (const c of unconfirmed) {
|
||||
await TransRoutesService.createSnackRecords({
|
||||
customer_id: c?.customer_id,
|
||||
customer_name: c?.customer_name,
|
||||
@@ -39,7 +40,7 @@ const SnackSection = ({transRoutes, snackRecords, sectionName, confirmHasSnack,
|
||||
return (
|
||||
<>
|
||||
<div className="text-primary mb-4"><h5>{sectionName} {` (${customers?.length})`}</h5></div>
|
||||
{snackRecords?.length <= 0 && (<div className="mb-2 mt-2"><button onClick={() => createSnackForAll()} className="btn btn-primary btn-sm">Confirm All Snack</button></div>)}
|
||||
{customers?.some(c => !c.has_snack) && (<div className="mb-2 mt-2"><button onClick={() => createSnackForAll()} className="btn btn-primary btn-sm">Confirm All Snack</button></div>)}
|
||||
<div className="list row">
|
||||
<div className="col-md-12">
|
||||
<table className="personnel-info-table">
|
||||
|
||||
@@ -97,20 +97,20 @@ const UpdateVehicle = () => {
|
||||
useEffect(() => {
|
||||
if (currentVehicle) {
|
||||
// Basic Information
|
||||
setVehicleNumber(currentVehicle.vehicle_number || '');
|
||||
setVehicleNumber(String(currentVehicle.vehicle_number ?? ''));
|
||||
setResponsibleDriver(currentVehicle.responsible_driver ? {
|
||||
value: currentVehicle.responsible_driver_id || '',
|
||||
label: currentVehicle.responsible_driver || ''
|
||||
} : null);
|
||||
setCapacity(currentVehicle.capacity?.toString() || '');
|
||||
setMileage(currentVehicle.mileage?.toString() || '');
|
||||
setMake(currentVehicle.make || '');
|
||||
setVehicleModel(currentVehicle.vehicle_model || '');
|
||||
setYear(currentVehicle.year || '');
|
||||
setVin(currentVehicle.vin || '');
|
||||
setTag(currentVehicle.tag || '');
|
||||
setGps(currentVehicle.gps_tag || '');
|
||||
setEzpass(currentVehicle.ezpass || '');
|
||||
setMake(String(currentVehicle.make ?? ''));
|
||||
setVehicleModel(String(currentVehicle.vehicle_model ?? ''));
|
||||
setYear(String(currentVehicle.year ?? ''));
|
||||
setVin(String(currentVehicle.vin ?? ''));
|
||||
setTag(String(currentVehicle.tag ?? ''));
|
||||
setGps(String(currentVehicle.gps_tag ?? ''));
|
||||
setEzpass(String(currentVehicle.ezpass ?? ''));
|
||||
setHasLiftEquip(currentVehicle.has_lift_equip === true ? 'true' : (currentVehicle.has_lift_equip === false ? 'false' : ''));
|
||||
setFuelType(currentVehicle.fuel_type || '');
|
||||
setTitle(currentVehicle.title || '');
|
||||
|
||||
@@ -6,6 +6,21 @@ import moment from 'moment';
|
||||
const { createCustomer, createCustomerFailure, updateCustomer, updateCustomerFailure, deleteCustomer, deleteCustomerFailure } = customerSlice.actions;
|
||||
const { fetchAllRoutesSuccess, fetchAllTomorrowRoutesSuccess, fetchAllHisotryRoutesSuccess } = transRoutesSlice.actions;
|
||||
|
||||
function* uploadFormFiles(customerId, customerName, formFiles) {
|
||||
if (!formFiles || !customerId) return;
|
||||
for (const { file, fileType } of formFiles) {
|
||||
if (file) {
|
||||
try {
|
||||
const fd = new FormData();
|
||||
fd.append('file', file);
|
||||
yield call(CustomerService.uploadCustomerFile, fd, customerId, customerName || '', fileType);
|
||||
} catch (err) {
|
||||
console.error(`Error uploading ${fileType}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* createCustomerSaga(action) {
|
||||
try {
|
||||
const customer = yield call(CustomerService.createNewCustomer, action.payload.data);
|
||||
@@ -15,6 +30,10 @@ function* createCustomerSaga(action) {
|
||||
CustomerService.uploadAvatar(customer.data.id, action.payload.avatar)
|
||||
}
|
||||
}
|
||||
// Upload form files after customer is created
|
||||
if (customer?.data?.id && action.payload.formFiles) {
|
||||
yield* uploadFormFiles(customer.data.id, action.payload.data?.name || '', action.payload.formFiles);
|
||||
}
|
||||
} catch(ex) {
|
||||
yield put(createCustomerFailure(ex));
|
||||
}
|
||||
|
||||
@@ -68,6 +68,14 @@ const getClient = (id) => {
|
||||
return http.get(`clients/${id}`);
|
||||
}
|
||||
|
||||
const uploadCustomerFile = (data, customerId, name, fileType) => {
|
||||
return http.post(`/files/upload-physical?objectId=${customerId}&name=${name}&fileType=${fileType}&model=customer`, data);
|
||||
}
|
||||
|
||||
const getAllCustomerFiles = (customerId, name, fileType) => {
|
||||
return http.get(`/files/list?objectId=${customerId}&name=${name}&fileType=${fileType}&model=customer`);
|
||||
}
|
||||
|
||||
|
||||
export const CustomerService = {
|
||||
getAllActiveCustomers,
|
||||
@@ -85,5 +93,7 @@ export const CustomerService = {
|
||||
updateClient,
|
||||
deleteClient,
|
||||
getClientsByNameOrEmail,
|
||||
getClient
|
||||
getClient,
|
||||
uploadCustomerFile,
|
||||
getAllCustomerFiles
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user