More update for Vehicle
This commit is contained in:
parent
e70fb22ac3
commit
f18f213f6b
BIN
app/.DS_Store
vendored
BIN
app/.DS_Store
vendored
Binary file not shown.
@ -167,7 +167,14 @@ exports.updateRouteInProgress = (req, res) => {
|
||||
finalCustomerList.push(cust);
|
||||
}
|
||||
}
|
||||
const finalBody = Object.assign({}, routeBody, {route_customer_list: finalCustomerList})
|
||||
let finalBody = {};
|
||||
if (finalCustomerList?.length > 0) {
|
||||
finalBody = Object.assign({}, routeBody, {route_customer_list: finalCustomerList})
|
||||
} else {
|
||||
const newBody = Object.assign({}, routeBody);
|
||||
delete newBody.route_customer_list;
|
||||
finalBody = Object.assign({}, newBody)
|
||||
}
|
||||
RoutePath.findByIdAndUpdate(currentRoute.id, finalBody, { useFindAndModify: false })
|
||||
.then(data => {
|
||||
// console.log('success', data.id);
|
||||
|
||||
@ -1,10 +1,19 @@
|
||||
const upload = require("../middlewares/upload");
|
||||
// const uploadPhysical = require("../middlewares/upload_physical");
|
||||
const dbConfig = require("../config/db.config");
|
||||
const MongoClient = require("mongodb").MongoClient;
|
||||
const GridFSBucket = require("mongodb").GridFSBucket;
|
||||
const util = require("util");
|
||||
var fs = require('fs');
|
||||
var multer = require('multer');
|
||||
const path = require("path");
|
||||
const url = dbConfig.url;
|
||||
const baseUrl = dbConfig.fileUrl;
|
||||
const mongoClient = new MongoClient(url);
|
||||
|
||||
const readdir = util.promisify(fs.readdir);
|
||||
const stat = util.promisify(fs.stat);
|
||||
|
||||
const uploadFiles = async (req, res) => {
|
||||
try {
|
||||
await upload(req, res);
|
||||
@ -63,8 +72,91 @@ const deleteFile = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
const uploadPhysicalFile = async (req, res) => {
|
||||
try {
|
||||
// Destination and file name would be adjusted to be the same with original file system
|
||||
const {objectId, name, fileType, model} = req.query;
|
||||
const uploadedFile = req.file;
|
||||
if (!uploadedFile) {
|
||||
return res.status(400).send({
|
||||
message: 'No file uploaded.'
|
||||
})
|
||||
}
|
||||
return res.status(200).send({
|
||||
message: `File ${fileType} Uploaded Successfully for ${model} ${objectId}-${name}`
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
return res.status(500).send({
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const getFilesByType = async (req, res) => {
|
||||
try {
|
||||
const {objectId, fileType, name, model} = req.params;
|
||||
|
||||
if (!objectId || !name || !fileType || !model) {
|
||||
return res.status(400).send({message: 'Required fields missed'});
|
||||
}
|
||||
|
||||
const BASE_UPLOAD_DIR = `/www/wwwroot/upload/`;
|
||||
const filesDir = `${BASE_UPLOAD_DIR}${model}/${objectId}/${fileType}/`;
|
||||
|
||||
if (!fs.existsSync(filesDir)) {
|
||||
return res.status(200).send({
|
||||
data: {
|
||||
objectId,
|
||||
model,
|
||||
fileType,
|
||||
name,
|
||||
files: [],
|
||||
count: 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const fileEntries = await readdir(filesDir, { withFileTypes: true});
|
||||
|
||||
const filePromises = fileEntries.filter(entry => entry.isFile()).map(async (entry) => {
|
||||
const filePath = path.join(filesDir, entry.name);
|
||||
const stats = await stat(filePath);
|
||||
|
||||
const fileUrl = `/files/${model}/${objectId}/${fileType}/${entry.name}`;
|
||||
return {
|
||||
name: entry.name,
|
||||
url: fileUrl,
|
||||
size: stats.size,
|
||||
extension: path.extname(entry.name),
|
||||
createdAt: stats.birthtime,
|
||||
modifiedAt: stats.mtime
|
||||
}
|
||||
});
|
||||
const files = await Promise.all(filePromises);
|
||||
return res.status(200).json({
|
||||
data: {
|
||||
objectId,
|
||||
fileType,
|
||||
name,
|
||||
files,
|
||||
count: files.length
|
||||
}
|
||||
})
|
||||
|
||||
} catch(err) {
|
||||
return res.status(500).send({
|
||||
message: err.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
uploadFiles,
|
||||
getFile,
|
||||
deleteFile
|
||||
deleteFile,
|
||||
uploadPhysicalFile,
|
||||
getFilesByType
|
||||
};
|
||||
@ -21,7 +21,15 @@ exports.createVehicle = (req, res) => {
|
||||
year: req.body.year || '',
|
||||
checklist: req.body.checklist || '',
|
||||
status: 'active',
|
||||
site
|
||||
site,
|
||||
has_lift_equip: req.body.has_lift_equip,
|
||||
vin: req.body.vin || '',
|
||||
note: req.body.note || '',
|
||||
insurance_expire_on: req.body.insurance_expire_on,
|
||||
title_registration_on: req.body.title_registration_on,
|
||||
emission_test_on: req.body.emission_test_on,
|
||||
oil_change_mileage: req.body.oil_change_mileage,
|
||||
oil_change_date: req.body.oil_change_date
|
||||
});
|
||||
|
||||
// Save Vehicle in the database
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
const authJwt = require("./authJwt");
|
||||
const splitSite = require("./splitSite");
|
||||
const uploadPhysicalFile = require("./upload_physical");
|
||||
module.exports = {
|
||||
authJwt,
|
||||
splitSite
|
||||
splitSite,
|
||||
uploadPhysicalFile
|
||||
};
|
||||
93
app/middlewares/upload_physical.js
Normal file
93
app/middlewares/upload_physical.js
Normal file
@ -0,0 +1,93 @@
|
||||
var fs = require('fs');
|
||||
var multer = require('multer');
|
||||
const path = require("path");
|
||||
|
||||
const BASE_UPLOAD_DIR = `/www/wwwroot/upload/`;
|
||||
|
||||
// try {
|
||||
// if (!fs.existsSync(BASE_UPLOAD_DIR)) {
|
||||
// fs.mkdirSync(BASE_UPLOAD_DIR, {recursive: true});
|
||||
// console.log (`Created upload directory: ${BASE_UPLOAD_DIR}`);
|
||||
// }
|
||||
// } catch(err) {
|
||||
// console.error(`Error creating directory ${BASE_UPLOAD_DIR}`)
|
||||
// }
|
||||
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
const { objectId, fileType, name, model } = req.query;
|
||||
if (!objectId || !name || !fileType || !model) {
|
||||
return res.status(400).send({message: 'Required fields missed'});
|
||||
}
|
||||
const uploadDir = `${BASE_UPLOAD_DIR}${model}/${objectId}/${fileType}/`;
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, {recursive: true});
|
||||
console.log (`Created upload directory: ${uploadDir}/`);
|
||||
}
|
||||
cb(null, uploadDir);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
const { objectId, fileType, name, date} = req.query;
|
||||
const uniqueSuffix = date || Date.now();
|
||||
const payload = req.body;
|
||||
console.log('is the payload', payload);
|
||||
cb(null, `${name.replaceAll(' ', '_')}_${objectId}_${fileType}_${uniqueSuffix}${path.extname(file.originalname)}`)
|
||||
}
|
||||
})
|
||||
const uploadPhysicalFile = multer({
|
||||
storage: storage,
|
||||
limits: {fileSize: 10 * 1024* 1024},
|
||||
fileFilter: (req, file, cb) => cb(null, true)
|
||||
}).single('file');
|
||||
|
||||
// const memoryStorage = multer.memoryStorage();
|
||||
|
||||
// const upload = multer({
|
||||
// storage: memoryStorage,
|
||||
// limits: { fileSize: 10 * 1024* 1024}
|
||||
// });
|
||||
|
||||
// const uploadPhysicalFile = (req, res, next) => {
|
||||
// upload.single('file')(req, res, async (err) => {
|
||||
// if (err) {
|
||||
// return res.status(400).send({message: `Uplodad Error: ${err}`});
|
||||
// }
|
||||
|
||||
// if (!req.file) {
|
||||
// return res.status(400).send({message: 'No File uploaded'});
|
||||
// }
|
||||
|
||||
// try {
|
||||
// const {objectId, name, fileType} = req.body;
|
||||
// if (!objectId || !name || fileType) {
|
||||
// return res.status(400).send({message: 'Required fields missed'});
|
||||
// }
|
||||
// const uploadDir = `${BASE_UPLOAD_DIR}${objectId}/${fileType}/`;
|
||||
// if (!fs.existsSync(uploadDir)) {
|
||||
// fs.mkdirSync(uploadDir, {recursive: true});
|
||||
// console.log (`Created upload directory: ${uploadDir}`);
|
||||
// }
|
||||
// const uniqueSuffix = Date.now();
|
||||
// const fileExension = path.extname(req.file.originalname);
|
||||
// const fileName = `${name.replaceAll(' ', '_')}_${objectId}_${fileType}_${uniqueSuffix}${fileExension}`;
|
||||
// const filePath = path.join(uploadDir, fileName);
|
||||
|
||||
// fs.writeFileSync(filePath, req.file.buffer);
|
||||
|
||||
// req.fileInfo = {
|
||||
// filename: fileName,
|
||||
// path: filePath,
|
||||
// originalname: req.file.originalname,
|
||||
// size: req.file.size
|
||||
// };
|
||||
// next();
|
||||
|
||||
// } catch (err) {
|
||||
// return res.status(500).send({message: `Upload Parsing error: ${err}`});
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
|
||||
module.exports = uploadPhysicalFile;
|
||||
@ -1,4 +1,3 @@
|
||||
const uniqueValidator = require('mongoose-unique-validator');
|
||||
module.exports = mongoose => {
|
||||
var schema = mongoose.Schema(
|
||||
{
|
||||
|
||||
@ -25,7 +25,15 @@ module.exports = mongoose => {
|
||||
type: String
|
||||
}],
|
||||
status: String,
|
||||
site: Number
|
||||
site: Number,
|
||||
vin: String,
|
||||
has_lift_equip: Boolean,
|
||||
insurance_expire_on: String,
|
||||
title_registration_on: String,
|
||||
emission_test_on: String,
|
||||
oil_change_mileage: Number,
|
||||
oil_change_date: String,
|
||||
note: String
|
||||
},
|
||||
{ collection: 'vehicle', timestamps: true }
|
||||
);
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
const {uploadPhysicalFile} = require("../middlewares");
|
||||
|
||||
module.exports = app => {
|
||||
const upload = require("../controllers/upload.controller.js");
|
||||
var router = require("express").Router();
|
||||
router.get("/:name", upload.getFile);
|
||||
router.post("/upload/:filename", upload.uploadFiles);
|
||||
router.post("/upload-physical", [uploadPhysicalFile], upload.uploadPhysicalFile);
|
||||
router.post("/delete", upload.deleteFile);
|
||||
router.get("/uploadedDocs/:model/:objectId/type/:fileType/name/:name", upload.getFilesByType);
|
||||
app.use('/api/files', router);
|
||||
};
|
||||
@ -1,16 +1,16 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.2fa2d232.css",
|
||||
"main.js": "/static/js/main.da419ea1.js",
|
||||
"main.css": "/static/css/main.e5412702.css",
|
||||
"main.js": "/static/js/main.26b7d753.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.2fa2d232.css.map": "/static/css/main.2fa2d232.css.map",
|
||||
"main.da419ea1.js.map": "/static/js/main.da419ea1.js.map",
|
||||
"main.e5412702.css.map": "/static/css/main.e5412702.css.map",
|
||||
"main.26b7d753.js.map": "/static/js/main.26b7d753.js.map",
|
||||
"787.c4e7f8f9.chunk.js.map": "/static/js/787.c4e7f8f9.chunk.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.2fa2d232.css",
|
||||
"static/js/main.da419ea1.js"
|
||||
"static/css/main.e5412702.css",
|
||||
"static/js/main.26b7d753.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="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.da419ea1.js"></script><link href="/static/css/main.2fa2d232.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="manifest" href="/manifest.json"/><title>Worldshine Transportation</title><script defer="defer" src="/static/js/main.26b7d753.js"></script><link href="/static/css/main.e5412702.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
7
app/views/static/css/main.e5412702.css
Normal file
7
app/views/static/css/main.e5412702.css
Normal file
File diff suppressed because one or more lines are too long
1
app/views/static/css/main.e5412702.css.map
Normal file
1
app/views/static/css/main.e5412702.css.map
Normal file
File diff suppressed because one or more lines are too long
3
app/views/static/js/main.0a956b80.js
Normal file
3
app/views/static/js/main.0a956b80.js
Normal file
File diff suppressed because one or more lines are too long
126
app/views/static/js/main.0a956b80.js.LICENSE.txt
Normal file
126
app/views/static/js/main.0a956b80.js.LICENSE.txt
Normal file
@ -0,0 +1,126 @@
|
||||
/*!
|
||||
Copyright (c) 2018 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
http://jedwatson.github.io/classnames
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Signature Pad v2.3.2
|
||||
* https://github.com/szimek/signature_pad
|
||||
*
|
||||
* Copyright 2017 Szymon Nowak
|
||||
* Released under the MIT license
|
||||
*
|
||||
* The main idea and some parts of the code (e.g. drawing variable width Bézier curve) are taken from:
|
||||
* http://corner.squareup.com/2012/07/smoother-signatures.html
|
||||
*
|
||||
* Implementation of interpolation using cubic Bézier curves is taken from:
|
||||
* http://benknowscode.wordpress.com/2012/09/14/path-interpolation-using-cubic-bezier-and-control-point-estimation-in-javascript
|
||||
*
|
||||
* Algorithm for approximated length of a Bézier curve is taken from:
|
||||
* http://www.lemoda.net/maths/bezier-length/index.html
|
||||
*
|
||||
*/
|
||||
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//! moment.js
|
||||
1
app/views/static/js/main.0a956b80.js.map
Normal file
1
app/views/static/js/main.0a956b80.js.map
Normal file
File diff suppressed because one or more lines are too long
3
app/views/static/js/main.26b7d753.js
Normal file
3
app/views/static/js/main.26b7d753.js
Normal file
File diff suppressed because one or more lines are too long
126
app/views/static/js/main.26b7d753.js.LICENSE.txt
Normal file
126
app/views/static/js/main.26b7d753.js.LICENSE.txt
Normal file
@ -0,0 +1,126 @@
|
||||
/*!
|
||||
Copyright (c) 2018 Jed Watson.
|
||||
Licensed under the MIT License (MIT), see
|
||||
http://jedwatson.github.io/classnames
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Signature Pad v2.3.2
|
||||
* https://github.com/szimek/signature_pad
|
||||
*
|
||||
* Copyright 2017 Szymon Nowak
|
||||
* Released under the MIT license
|
||||
*
|
||||
* The main idea and some parts of the code (e.g. drawing variable width Bézier curve) are taken from:
|
||||
* http://corner.squareup.com/2012/07/smoother-signatures.html
|
||||
*
|
||||
* Implementation of interpolation using cubic Bézier curves is taken from:
|
||||
* http://benknowscode.wordpress.com/2012/09/14/path-interpolation-using-cubic-bezier-and-control-point-estimation-in-javascript
|
||||
*
|
||||
* Algorithm for approximated length of a Bézier curve is taken from:
|
||||
* http://www.lemoda.net/maths/bezier-length/index.html
|
||||
*
|
||||
*/
|
||||
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim/with-selector.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.3.0
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//! moment.js
|
||||
1
app/views/static/js/main.26b7d753.js.map
Normal file
1
app/views/static/js/main.26b7d753.js.map
Normal file
File diff suppressed because one or more lines are too long
737
client/package-lock.json
generated
737
client/package-lock.json
generated
@ -8,11 +8,14 @@
|
||||
"name": "client",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@aldabil/react-scheduler": "^2.9.2",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@reduxjs/toolkit": "^1.8.1",
|
||||
"@schedule-x/event-modal": "^2.30.0",
|
||||
"@schedule-x/events-service": "^2.30.0",
|
||||
"@schedule-x/react": "^2.30.0",
|
||||
"@schedule-x/theme-default": "^2.30.0",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.2.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -53,18 +56,6 @@
|
||||
"tape": "^5.5.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@aldabil/react-scheduler": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@aldabil/react-scheduler/-/react-scheduler-2.9.2.tgz",
|
||||
"integrity": "sha512-WederN8Pmhg7nQdT7685UITFUPk/FDjMC0bSuyeqgHZSn2nhVMqiLVFC4q0kHh+v75lQCPqkFKr8FBnEoZNRig==",
|
||||
"peerDependencies": {
|
||||
"@mui/icons-material": ">=5.0.0",
|
||||
"@mui/material": ">=5.0.0",
|
||||
"@mui/x-date-pickers": ">=6.19.0",
|
||||
"date-fns": ">=3.2.0",
|
||||
"react": ">=17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
@ -2352,44 +2343,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz",
|
||||
"integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
|
||||
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.0.0",
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/react-dom": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.9.tgz",
|
||||
"integrity": "sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
|
||||
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
|
||||
@ -3118,338 +3071,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz",
|
||||
"integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg=="
|
||||
},
|
||||
"node_modules/@mui/base": {
|
||||
"version": "5.0.0-beta.40",
|
||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
|
||||
"integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@floating-ui/react-dom": "^2.0.8",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.1.0",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/core-downloads-tracker": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.16.tgz",
|
||||
"integrity": "sha512-PTIbMJs5C/vYMfyJNW8ArOezh4eyHkg2pTeA7bBxh2kLP1Uzs0Nm+krXWbWGJPwTWjM8EhnDrr4aCF26+2oleg==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/icons-material": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.16.tgz",
|
||||
"integrity": "sha512-s8vYbyACzTNZRKv+20fCfVXJwJqNcVotns2EKnu1wmAga6wv2LAo5kB1d5yqQqZlMFtp34EJvRXf7cy8X0tJVA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mui/material": "^5.0.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.16.tgz",
|
||||
"integrity": "sha512-ery2hFReewko9gpDBqOr2VmXwQG9ifXofPhGzIx09/b9JqCQC/06kZXZDGGrOTpIddK9HlIf4yrS+G70jPAzUQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/base": "5.0.0-beta.40",
|
||||
"@mui/core-downloads-tracker": "^5.15.16",
|
||||
"@mui/system": "^5.15.15",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/react-is": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@mui/private-theming": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz",
|
||||
"integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/styled-engine": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz",
|
||||
"integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/system": {
|
||||
"version": "5.15.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz",
|
||||
"integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/private-theming": "^5.15.14",
|
||||
"@mui/styled-engine": "^5.15.14",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/types": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz",
|
||||
"integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/utils": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz",
|
||||
"integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@types/prop-types": "^15.7.11",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/utils/node_modules/react-is": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@mui/x-date-pickers": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.3.2.tgz",
|
||||
"integrity": "sha512-i7JaDs1eXSZWyJihfszUHVV0t/C2HvtdMv5tHwv3E3enMx5Hup1vkJ64vZAH2fgGrTHQH8mjxvVsmI6jhDXIUg==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.24.0",
|
||||
"@mui/base": "^5.0.0-beta.40",
|
||||
"@mui/system": "^5.15.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"clsx": "^2.1.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.9.0",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@mui/material": "^5.15.14",
|
||||
"date-fns": "^2.25.0 || ^3.2.0",
|
||||
"date-fns-jalali": "^2.13.0-0",
|
||||
"dayjs": "^1.10.7",
|
||||
"luxon": "^3.0.2",
|
||||
"moment": "^2.29.4",
|
||||
"moment-hijri": "^2.1.2",
|
||||
"moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0",
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"date-fns": {
|
||||
"optional": true
|
||||
},
|
||||
"date-fns-jalali": {
|
||||
"optional": true
|
||||
},
|
||||
"dayjs": {
|
||||
"optional": true
|
||||
},
|
||||
"luxon": {
|
||||
"optional": true
|
||||
},
|
||||
"moment": {
|
||||
"optional": true
|
||||
},
|
||||
"moment-hijri": {
|
||||
"optional": true
|
||||
},
|
||||
"moment-jalaali": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@nicolo-ribaudo/chokidar-2": {
|
||||
"version": "2.1.8-no-fsevents.3",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
|
||||
@ -3547,6 +3168,32 @@
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@preact/signals": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals/-/signals-2.0.4.tgz",
|
||||
"integrity": "sha512-9241aGnIv7y0IGzaq2vkBMe8/0jGnnmEEUeFmAoTWsaj8q/BW2PVekL8nHVJcy69bBww6rwEy3A1tc6yPE0sJA==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@preact/signals-core": "^1.7.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"preact": ">= 10.25.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@preact/signals-core": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz",
|
||||
"integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-dnd/asap": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz",
|
||||
@ -3753,6 +3400,45 @@
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz",
|
||||
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw=="
|
||||
},
|
||||
"node_modules/@schedule-x/calendar": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/calendar/-/calendar-2.30.0.tgz",
|
||||
"integrity": "sha512-+yAVnY+4T8+iTrVp03V3usVYKhLuBzWEEtYOKsTnbFapD3LaL02Rv+0Gmv+4Vpk1H5yd3znrSxQvDLNBVNmUhg==",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@preact/signals": "^2.0.2",
|
||||
"preact": "^10.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@schedule-x/event-modal": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/event-modal/-/event-modal-2.30.0.tgz",
|
||||
"integrity": "sha512-RS/p5/rg/wCooKR5y05orJBJjxf7Ls7/VcGsz5MemJCQCXhu5pbU0g+OVVSlh6tJ+OoKF5frm4lIhXu82gd6/Q==",
|
||||
"peerDependencies": {
|
||||
"@preact/signals": "^2.0.2",
|
||||
"preact": "^10.19.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@schedule-x/events-service": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/events-service/-/events-service-2.30.0.tgz",
|
||||
"integrity": "sha512-WztKcKSj9uqvjvVr5bVe5tAzR4FKDBPQ/FFnuDWE2Y76yrxs7Hy4RROG/UCmteGrzJeXv3BV+TU2l63scJUADA=="
|
||||
},
|
||||
"node_modules/@schedule-x/react": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/react/-/react-2.30.0.tgz",
|
||||
"integrity": "sha512-9eVcoE7xYDYHnS+2JwgtRoEZtfzoJdfNHb+VMgvgJ0Ur+ItGifN5DyrFlyQ3l18E848ny0+wp1J8qRvlV5ikMw==",
|
||||
"peerDependencies": {
|
||||
"@schedule-x/calendar": "^2.25.0",
|
||||
"react": "^16.7.0 || ^17 || ^18 || ^19",
|
||||
"react-dom": "^16.7.0 || ^17 || ^18 || ^19"
|
||||
}
|
||||
},
|
||||
"node_modules/@schedule-x/theme-default": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/theme-default/-/theme-default-2.30.0.tgz",
|
||||
"integrity": "sha512-vRUDV3fg7SoETiWQktv3DwYKjFZQMHwuYw+VKW5T3dzEJ8YfatuJbg0sj0JCiu9XQYcjs0hdmzrQvIDFy93r/w=="
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
||||
@ -7026,15 +6712,6 @@
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
@ -7945,23 +7622,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.11",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
|
||||
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
||||
@ -16991,6 +16651,16 @@
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.26.6",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.26.6.tgz",
|
||||
"integrity": "sha512-5SRRBinwpwkaD+OqlBDeITlRgvd8I8QlxHJw9AxSdMNV6O+LodN9nUyYGpSF7sadHjs6RzeFShMexC6DbtWr9g==",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
@ -22218,12 +21888,6 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@aldabil/react-scheduler": {
|
||||
"version": "2.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@aldabil/react-scheduler/-/react-scheduler-2.9.2.tgz",
|
||||
"integrity": "sha512-WederN8Pmhg7nQdT7685UITFUPk/FDjMC0bSuyeqgHZSn2nhVMqiLVFC4q0kHh+v75lQCPqkFKr8FBnEoZNRig==",
|
||||
"requires": {}
|
||||
},
|
||||
"@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
@ -23777,40 +23441,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@floating-ui/core": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz",
|
||||
"integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"@floating-ui/dom": {
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
|
||||
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@floating-ui/core": "^1.0.0",
|
||||
"@floating-ui/utils": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"@floating-ui/react-dom": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.9.tgz",
|
||||
"integrity": "sha512-q0umO0+LQK4+p6aGyvzASqKbKOJcAHJ7ycE9CuUvfx3s9zTHWmGJTPOIlM/hmSBfUfg/XfY5YhLBLR/LHwShQQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@floating-ui/dom": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@floating-ui/utils": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
|
||||
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==",
|
||||
"peer": true
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz",
|
||||
@ -24351,146 +23981,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz",
|
||||
"integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg=="
|
||||
},
|
||||
"@mui/base": {
|
||||
"version": "5.0.0-beta.40",
|
||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
|
||||
"integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@floating-ui/react-dom": "^2.0.8",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"clsx": "^2.1.0",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/core-downloads-tracker": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.16.tgz",
|
||||
"integrity": "sha512-PTIbMJs5C/vYMfyJNW8ArOezh4eyHkg2pTeA7bBxh2kLP1Uzs0Nm+krXWbWGJPwTWjM8EhnDrr4aCF26+2oleg==",
|
||||
"peer": true
|
||||
},
|
||||
"@mui/icons-material": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.16.tgz",
|
||||
"integrity": "sha512-s8vYbyACzTNZRKv+20fCfVXJwJqNcVotns2EKnu1wmAga6wv2LAo5kB1d5yqQqZlMFtp34EJvRXf7cy8X0tJVA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9"
|
||||
}
|
||||
},
|
||||
"@mui/material": {
|
||||
"version": "5.15.16",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.16.tgz",
|
||||
"integrity": "sha512-ery2hFReewko9gpDBqOr2VmXwQG9ifXofPhGzIx09/b9JqCQC/06kZXZDGGrOTpIddK9HlIf4yrS+G70jPAzUQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/base": "5.0.0-beta.40",
|
||||
"@mui/core-downloads-tracker": "^5.15.16",
|
||||
"@mui/system": "^5.15.15",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mui/private-theming": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.14.tgz",
|
||||
"integrity": "sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/styled-engine": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.14.tgz",
|
||||
"integrity": "sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@emotion/cache": "^11.11.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/system": {
|
||||
"version": "5.15.15",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.15.tgz",
|
||||
"integrity": "sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/private-theming": "^5.15.14",
|
||||
"@mui/styled-engine": "^5.15.14",
|
||||
"@mui/types": "^7.2.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"@mui/types": {
|
||||
"version": "7.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.14.tgz",
|
||||
"integrity": "sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==",
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@mui/utils": {
|
||||
"version": "5.15.14",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.14.tgz",
|
||||
"integrity": "sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@types/prop-types": "^15.7.11",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^18.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-is": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
|
||||
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
|
||||
"peer": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mui/x-date-pickers": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-7.3.2.tgz",
|
||||
"integrity": "sha512-i7JaDs1eXSZWyJihfszUHVV0t/C2HvtdMv5tHwv3E3enMx5Hup1vkJ64vZAH2fgGrTHQH8mjxvVsmI6jhDXIUg==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.24.0",
|
||||
"@mui/base": "^5.0.0-beta.40",
|
||||
"@mui/system": "^5.15.14",
|
||||
"@mui/utils": "^5.15.14",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"clsx": "^2.1.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-transition-group": "^4.4.5"
|
||||
}
|
||||
},
|
||||
"@nicolo-ribaudo/chokidar-2": {
|
||||
"version": "2.1.8-no-fsevents.3",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
|
||||
@ -24542,6 +24032,21 @@
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
|
||||
},
|
||||
"@preact/signals": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals/-/signals-2.0.4.tgz",
|
||||
"integrity": "sha512-9241aGnIv7y0IGzaq2vkBMe8/0jGnnmEEUeFmAoTWsaj8q/BW2PVekL8nHVJcy69bBww6rwEy3A1tc6yPE0sJA==",
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"@preact/signals-core": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"@preact/signals-core": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz",
|
||||
"integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==",
|
||||
"peer": true
|
||||
},
|
||||
"@react-dnd/asap": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz",
|
||||
@ -24702,6 +24207,35 @@
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz",
|
||||
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw=="
|
||||
},
|
||||
"@schedule-x/calendar": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/calendar/-/calendar-2.30.0.tgz",
|
||||
"integrity": "sha512-+yAVnY+4T8+iTrVp03V3usVYKhLuBzWEEtYOKsTnbFapD3LaL02Rv+0Gmv+4Vpk1H5yd3znrSxQvDLNBVNmUhg==",
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
},
|
||||
"@schedule-x/event-modal": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/event-modal/-/event-modal-2.30.0.tgz",
|
||||
"integrity": "sha512-RS/p5/rg/wCooKR5y05orJBJjxf7Ls7/VcGsz5MemJCQCXhu5pbU0g+OVVSlh6tJ+OoKF5frm4lIhXu82gd6/Q==",
|
||||
"requires": {}
|
||||
},
|
||||
"@schedule-x/events-service": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/events-service/-/events-service-2.30.0.tgz",
|
||||
"integrity": "sha512-WztKcKSj9uqvjvVr5bVe5tAzR4FKDBPQ/FFnuDWE2Y76yrxs7Hy4RROG/UCmteGrzJeXv3BV+TU2l63scJUADA=="
|
||||
},
|
||||
"@schedule-x/react": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/react/-/react-2.30.0.tgz",
|
||||
"integrity": "sha512-9eVcoE7xYDYHnS+2JwgtRoEZtfzoJdfNHb+VMgvgJ0Ur+ItGifN5DyrFlyQ3l18E848ny0+wp1J8qRvlV5ikMw==",
|
||||
"requires": {}
|
||||
},
|
||||
"@schedule-x/theme-default": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/@schedule-x/theme-default/-/theme-default-2.30.0.tgz",
|
||||
"integrity": "sha512-vRUDV3fg7SoETiWQktv3DwYKjFZQMHwuYw+VKW5T3dzEJ8YfatuJbg0sj0JCiu9XQYcjs0hdmzrQvIDFy93r/w=="
|
||||
},
|
||||
"@sinclair/typebox": {
|
||||
"version": "0.23.5",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz",
|
||||
@ -27274,12 +26808,6 @@
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"peer": true
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
@ -27974,19 +27502,6 @@
|
||||
"whatwg-url": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"peer": true
|
||||
},
|
||||
"dayjs": {
|
||||
"version": "1.11.11",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
|
||||
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"debounce": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
|
||||
@ -34541,6 +34056,12 @@
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||
},
|
||||
"preact": {
|
||||
"version": "10.26.6",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.26.6.tgz",
|
||||
"integrity": "sha512-5SRRBinwpwkaD+OqlBDeITlRgvd8I8QlxHJw9AxSdMNV6O+LodN9nUyYGpSF7sadHjs6RzeFShMexC6DbtWr9g==",
|
||||
"peer": true
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
|
||||
@ -3,11 +3,14 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@aldabil/react-scheduler": "^2.9.2",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@reduxjs/toolkit": "^1.8.1",
|
||||
"@schedule-x/event-modal": "^2.30.0",
|
||||
"@schedule-x/events-service": "^2.30.0",
|
||||
"@schedule-x/react": "^2.30.0",
|
||||
"@schedule-x/theme-default": "^2.30.0",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.2.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
|
||||
@ -660,11 +660,107 @@ input[type="checkbox"] {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.sx__month-grid-day {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.sx__event-modal {
|
||||
box-shadow: 1px -1px 20px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.sx__event-modal__title {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.sx__event-modal__time {
|
||||
padding: 0 8px 8px 8px;
|
||||
}
|
||||
|
||||
.sx__event-modal__time.with-padding {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.event-item-flex {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.event-list-item-container {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.event-red {
|
||||
border-inline-start: 4px solid rgb(249, 28, 69) !important;
|
||||
color: rgb(89, 0, 13) !important;
|
||||
background-color: rgb(255, 210, 220) !important;
|
||||
}
|
||||
|
||||
.event-brown {
|
||||
border-inline-start: 4px solid #d0b316 !important;
|
||||
color: #594800 !important;
|
||||
background-color: #fff5aa !important;
|
||||
}
|
||||
|
||||
.event-green {
|
||||
border-inline-start: 4px solid #004d3d !important;
|
||||
color: #004d3d !important;
|
||||
background-color: #dafff0 !important;
|
||||
}
|
||||
|
||||
.event-blue {
|
||||
border-inline-start: 4px solid rgb(28, 125, 249) !important;
|
||||
color: rgb(0, 40, 89) !important;
|
||||
background-color: rgb(210, 231, 255) !important;
|
||||
}
|
||||
|
||||
.event-black {
|
||||
border-inline-start: 4px solid black !important;
|
||||
color: black !important;
|
||||
background-color: #aaa !important;
|
||||
}
|
||||
|
||||
.event-purple {
|
||||
border-inline-start: 4px solid #6750a4 !important;
|
||||
color: #21005e !important;
|
||||
background-color: #eaddff !important;
|
||||
}
|
||||
|
||||
.event-primary {
|
||||
border-inline-start: 4px solid #6750a4 !important;
|
||||
color: #21005e !important;
|
||||
background-color: #eaddff !important;
|
||||
}
|
||||
|
||||
.event-gray {
|
||||
border-inline-start: 4px solid #777 !important;
|
||||
color: #555 !important;
|
||||
background-color: #eee !important;
|
||||
}
|
||||
|
||||
.event-orange {
|
||||
border-inline-start: 4px solid #F76806 !important;
|
||||
color: #C35214 !important;
|
||||
background-color: #FED8B1 !important;
|
||||
}
|
||||
|
||||
.event-pink {
|
||||
border-inline-start: 4px solid #FF6EC7 !important;
|
||||
color: #A94064 !important;
|
||||
background-color: #FFD1DC !important;
|
||||
}
|
||||
|
||||
.btn-no-deco {
|
||||
text-decoration: none!important;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.small-dropdown-item {
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.personnel-info-table .red {
|
||||
background: #dc3545;
|
||||
color: rgb(25, 23, 23);
|
||||
|
||||
@ -38,6 +38,7 @@ const UpdateEmployee = () => {
|
||||
const [status, setStatus] = useState('');
|
||||
const [tags, setTags] = useState('');
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [selectedFile, setSelectedFile] = useState();
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const redirectTo = () => {
|
||||
const redirect = params.get('redirect');
|
||||
@ -186,6 +187,16 @@ const UpdateEmployee = () => {
|
||||
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("file", selectedFile);
|
||||
// formData.append('employeeId', currentEmployee?.id);
|
||||
// formData.append('name', `${currentEmployee?.lastname}_${currentEmployee?.firstname}`);
|
||||
// formData.append('fileType', 'I9');
|
||||
|
||||
if (selectedFile) {
|
||||
EmployeeService.uploadEmployeeFile(formData, currentEmployee?.id, `${currentEmployee?.lastname}_${currentEmployee?.firstname}`, 'I9');
|
||||
}
|
||||
|
||||
if (params.get('type') === 'driver') {
|
||||
dispatch(updateDriver({id: urlParams.id, data, currentEmployee}));
|
||||
} else {
|
||||
@ -288,6 +299,13 @@ const UpdateEmployee = () => {
|
||||
<div className="col-md-4 mb-4">
|
||||
<div>Tags(Please use ',' between each tags):</div> <input type="text" value={tags || ''} onChange={e => setTags(e.target.value)}/>
|
||||
</div>
|
||||
<div className="col-md-4 mb-4">
|
||||
<div>Upload I9:</div>
|
||||
<input
|
||||
type="file"
|
||||
onChange={(e) => setSelectedFile(e.target.files[0])}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="list row mb-5">
|
||||
<div className="col-md-6 col-sm-6 col-xs-12">
|
||||
|
||||
@ -9,6 +9,7 @@ const ViewEmployee = () => {
|
||||
|
||||
const urlParams = useParams();
|
||||
const [currentEmployee, setCurrentEmployee] = useState(undefined);
|
||||
const [i9Files, setI9Files] = useState([]);
|
||||
|
||||
const redirectTo = () => {
|
||||
navigate(`/employees/list`)
|
||||
@ -26,6 +27,12 @@ const ViewEmployee = () => {
|
||||
})
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentEmployee) {
|
||||
EmployeeService.getAllEmployeeFiles(currentEmployee?.id, currentEmployee?.name, 'I9').then(data => { setI9Files(data?.data?.data?.files)} )
|
||||
}
|
||||
}, [currentEmployee])
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -92,6 +99,14 @@ const ViewEmployee = () => {
|
||||
<div className="col-md-4 mb-4">
|
||||
<div>Tags: {currentEmployee?.tags?.join(', ')}</div>
|
||||
</div>
|
||||
<div className="col-md-4 mb-4">
|
||||
<div>I9: </div>
|
||||
<div>
|
||||
{
|
||||
i9Files?.map(item => <div><a href={`${window.location.origin}${item?.url}`} target="_blank">{item?.name}</a></div> )
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -2,8 +2,23 @@ import React, {useState, useEffect} from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { AuthService, EventsService, CustomerService, ResourceService } from "../../services";
|
||||
import moment from 'moment';
|
||||
import { Button, Modal } from "react-bootstrap";
|
||||
import { Scheduler } from "@aldabil/react-scheduler";
|
||||
import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab, Button, Modal, Dropdown } from "react-bootstrap";
|
||||
import { useCalendarApp, ScheduleXCalendar } from '@schedule-x/react';
|
||||
import {
|
||||
viewWeek,
|
||||
viewDay,
|
||||
viewMonthGrid,
|
||||
viewMonthAgenda,
|
||||
createViewDay,
|
||||
createViewMonthAgenda,
|
||||
createViewWeek,
|
||||
createViewMonthGrid
|
||||
} from '@schedule-x/calendar';
|
||||
import { createEventsServicePlugin } from '@schedule-x/events-service';
|
||||
import { createEventModalPlugin} from '@schedule-x/event-modal';
|
||||
import '@schedule-x/theme-default/dist/calendar.css';
|
||||
import { Archive, PencilSquare, Filter } from "react-bootstrap-icons";
|
||||
// import { Scheduler } from "@aldabil/react-scheduler";
|
||||
|
||||
|
||||
const EventsCalendar = () => {
|
||||
@ -18,6 +33,43 @@ const EventsCalendar = () => {
|
||||
const [currentTotalResource, setCurrentTotalResource] = useState(0);
|
||||
const [showDeletedItems, setShowDeletedItems] = useState(false);
|
||||
const [timeData, setTimeData] = useState([]);
|
||||
const [showFilterDropdown, setShowFilterDropdown] = useState(false);
|
||||
const eventsServicePlugin = createEventsServicePlugin();
|
||||
const eventModalService = createEventModalPlugin();
|
||||
const [groupedEvents, setGroupedEvents] = useState(new Map());
|
||||
|
||||
const calendar = useCalendarApp({
|
||||
views: [createViewMonthGrid(), createViewDay(), createViewMonthAgenda()],
|
||||
monthGridOptions: {
|
||||
/**
|
||||
* Number of events to display in a day cell before the "+ N events" button is shown
|
||||
* */
|
||||
nEventsPerDay: 50,
|
||||
},
|
||||
defaultView: viewMonthGrid.name,
|
||||
skipValidation: true,
|
||||
selectedDate: moment(new Date()).format('YYYY-MM-DD HH:mm'),
|
||||
events: events,
|
||||
plugins: [eventModalService, eventsServicePlugin]
|
||||
})
|
||||
|
||||
const getGroupedEvents = () => {
|
||||
const eventsDateMap = new Map();
|
||||
console.log('events', events);
|
||||
for (const eventItem of events) {
|
||||
const dateString = moment(eventItem.start_time).format('MMM Do, YYYY');
|
||||
if (eventsDateMap.has(dateString)) {
|
||||
eventsDateMap.set(dateString, [...eventsDateMap.get(dateString), eventItem]);
|
||||
} else {
|
||||
const value = [];
|
||||
value.push(eventItem);
|
||||
eventsDateMap.set(dateString, value);
|
||||
}
|
||||
}
|
||||
console.log('eventsMap', eventsDateMap);
|
||||
return eventsDateMap;
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!AuthService.canAccessLegacySystem()) {
|
||||
@ -52,15 +104,17 @@ const EventsCalendar = () => {
|
||||
item.newPatient = item?.data?.new_patient || '';
|
||||
item.needId = item?.data?.need_id || '';
|
||||
item.disability = item?.data?.disability || '';
|
||||
item.startTime = item?.start_time? `${new Date(item?.start_time).toLocaleDateString()} ${moment(new Date(item?.start_time)).format('hh:mm A')}` : '' ;
|
||||
item.startTime = item?.start_time? `${moment(new Date(item?.start_time)).format('hh:mm A')}` : '' ;
|
||||
item.endTime = item?.start_time? `${moment(new Date(item?.end_time)).format('hh:mm A')}` : '' ;
|
||||
item.fasting = item?.data?.fasting || '';
|
||||
item.transportation = item?.link_event_name || '';
|
||||
item.title = `${moment(new Date(item?.start_time)).format('hh:mm A') || ''} ${doctorField} / ${customerField}`;
|
||||
item.start = new Date(item.start_time);
|
||||
item.end = item.stop_time? new Date(item.stop_time): new Date(item.start_time);
|
||||
item.title = `${customerField}, provider: ${doctorField}`;
|
||||
item.start = item?.start_time? `${moment(new Date(item?.start_time)).format('YYYY-MM-DD HH:mm')}` : '';
|
||||
item.end = item.stop_time? `${moment(new Date(item?.stop_time)).format('YYYY-MM-DD HH:mm')}` : '';
|
||||
const transportationInfo = EventsService.getTransportationInfo(data.data, item, timeData);
|
||||
const { isFutureEvent, maxTranslate1, maxTranslate2, maxResource, totalTranslate1, totalTranslate2, totalResource} = transportationInfo;
|
||||
item.color = item?.color;
|
||||
item._options = { additionalClasses: [`event-${item?.color || 'primary'}`]};
|
||||
item.showWarnings = isFutureEvent;
|
||||
item.maxTranslate1 = maxTranslate1;
|
||||
item.maxTranslate2 = maxTranslate2;
|
||||
@ -73,10 +127,17 @@ const EventsCalendar = () => {
|
||||
setCurrentTotalResource(item.totalResource);
|
||||
return item;
|
||||
}).filter(item => item.type === 'medical'));
|
||||
|
||||
})}
|
||||
}, [fromDate, toDate, customers, resources, timeData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (events) {
|
||||
events?.forEach((item) => calendar.eventsService.add(item));
|
||||
setGroupedEvents(getGroupedEvents());
|
||||
}
|
||||
}, [events]);
|
||||
|
||||
|
||||
const redirectToAdmin = () => {
|
||||
navigate(`/medical`)
|
||||
}
|
||||
@ -102,6 +163,8 @@ const EventsCalendar = () => {
|
||||
navigate(`/medical/events/${id}`)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const disableEvent = (id) => {
|
||||
const currentEvent = events.find(item => item.id === id);
|
||||
EventsService.disableEvent(id, { status: 'inactive', edit_by: localStorage.getItem('user') && JSON.parse(localStorage.getItem('user'))?.name,
|
||||
@ -121,12 +184,14 @@ const EventsCalendar = () => {
|
||||
item.newPatient = item?.data?.new_patient || '';
|
||||
item.needId = item?.data?.need_id || '';
|
||||
item.disability = item?.data?.disability || '';
|
||||
item.startTime = item?.start_time? `${new Date(item?.start_time).toLocaleDateString()} ${moment(new Date(item?.start_time)).format('hh:mm A')}` : '' ;
|
||||
item.startTime = item?.start_time? `${moment(new Date(item?.start_time)).format('hh:mm A')}` : '' ;
|
||||
item.endTime = item?.start_time? `${moment(new Date(item?.end_time)).format('hh:mm A')}` : '' ;
|
||||
item.fasting = item?.data?.fasting || '';
|
||||
item.transportation = item?.link_event_name || '';
|
||||
item.title = `${moment(new Date(item?.start_time)).format('hh:mm A') || ''} ${doctorField} / ${customerField}`;
|
||||
item.title = `${customerField}, provider: ${doctorField}`;
|
||||
item.start = new Date(item.start_time);
|
||||
item.end = item.stop_time? new Date(item.stop_time): new Date(item.start_time);
|
||||
item._options = { additionalClasses: [`event-${item?.color || 'primary'}`]};
|
||||
const transportationInfo = EventsService.getTransportationInfo(data.data, item, timeData);
|
||||
const { isFutureEvent, maxTranslate1, maxTranslate2, maxResource, totalTranslate1, totalTranslate2, totalResource} = transportationInfo;
|
||||
item.color = item?.color;
|
||||
@ -145,52 +210,121 @@ const EventsCalendar = () => {
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const FilterAndClose = () => {
|
||||
setShowFilterDropdown(false);
|
||||
}
|
||||
|
||||
const cleanFilterAndClose = () => {
|
||||
setShowFilterDropdown(false);
|
||||
setShowDeletedItems(false);
|
||||
}
|
||||
|
||||
|
||||
const customComponents = {
|
||||
eventModal: ({calendarEvent}) => {
|
||||
return <>
|
||||
<div className="sx__event-modal__title">{calendarEvent?.customer}</div>
|
||||
<div className="sx__event-modal__time">{`${calendarEvent?.doctor}`}</div>
|
||||
<div className="sx__event-modal__time">{`${calendarEvent?.startTime}`}</div>
|
||||
<div className="sx__event-modal__time">
|
||||
<PencilSquare size={16} onClick={() => goToEdit(calendarEvent?.id)} className="me-4"></PencilSquare>
|
||||
<Archive size={16} onClick={() =>{disableEvent(calendarEvent?.id)}}></Archive> </div>
|
||||
</>
|
||||
}
|
||||
};
|
||||
|
||||
const customMenu = React.forwardRef(
|
||||
({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
style={style}
|
||||
className={className}
|
||||
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>
|
||||
<div className="list row">
|
||||
<div className="col-md-12">
|
||||
<button className="btn btn-default btn-sm float-right" onClick={() => cleanFilterAndClose()}> Cancel </button>
|
||||
<button className="btn btn-primary btn-sm float-right" onClick={() => FilterAndClose()}> Filter </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="list row mb-4">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>Medical</Breadcrumb.Item>
|
||||
<Breadcrumb.Item active>
|
||||
Medical Event Calendar
|
||||
</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
<div className="col-md-12 text-primary">
|
||||
<h5>Medical Event Calendar <button className="btn btn-link btn-sm" onClick={() => {redirectToAdmin()}}>Back</button></h5>
|
||||
<h4>
|
||||
Medical Event Calendar
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="list row mb-4">
|
||||
<div className="col-md-12 col-sm-12 mb-4">
|
||||
Show Deleted Events: <input type="checkbox" value={showDeletedItems} checked={showDeletedItems === true} onClick={() => setShowDeletedItems(!showDeletedItems)} />
|
||||
|
||||
|
||||
<div className="app-main-content-list-container" style={{"min-width": "1500px"}}>
|
||||
<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">
|
||||
<h6 className="text-primary me-4">List</h6>
|
||||
{
|
||||
Array.from(groupedEvents?.keys())?.map((key) => {
|
||||
return <>
|
||||
<h6 className="text-primary me-2">{key}</h6>
|
||||
{
|
||||
groupedEvents.get(key).map(eventItem => <div className={`event-${eventItem.color || 'primary'} mb-4 event-list-item-container`}>
|
||||
<div className="event-item-flex">
|
||||
<div className="sx__month-agenda-event__title">{eventItem.customer}</div>
|
||||
<div className="sx__event-modal__time">{`${moment(eventItem?.start_time).format('hh:mm A')} ${eventItem?.end_time ? `- ${moment(eventItem?.end_time).format('hh:mm A')}` : '' }`}</div>
|
||||
</div>
|
||||
<div className="sx__event-modal__time with-padding">{`provider: ${eventItem?.doctor}`}</div>
|
||||
</div>)
|
||||
}
|
||||
</>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div className="list-func-panel">
|
||||
<Dropdown
|
||||
key={'event-calendar-filter'}
|
||||
id="event-calendar-filter"
|
||||
show={showFilterDropdown}
|
||||
onToggle={() => setShowFilterDropdown(!showFilterDropdown)}
|
||||
autoClose={false}
|
||||
>
|
||||
<Dropdown.Toggle variant="primary">
|
||||
<Filter size={16} className="me-2"></Filter>Filter
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu as={customMenu}/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 col-sm-12 mb-4">
|
||||
<Scheduler
|
||||
view="month"
|
||||
events={showDeletedItems ? events : events.filter(event => event.status === 'active')}
|
||||
month = {{
|
||||
weekDays: [0, 1, 2, 3, 4, 5, 6],
|
||||
weekStartOn: 0,
|
||||
startHour: 0,
|
||||
endHour: 24,
|
||||
navigation: true,
|
||||
disableGoToDay: false
|
||||
}}
|
||||
day = {{
|
||||
startHour: 0,
|
||||
endHour: 24,
|
||||
step:1440,
|
||||
navigation: true
|
||||
}}
|
||||
onSelectedDateChange = {(date) => {setFromDate(new Date(new Date(date).getFullYear(), new Date(date).getMonth(), 1)); setToDate(new Date(new Date(date).getFullYear(), new Date(date).getMonth() + 1, 0))}}
|
||||
onEventEdit = {(event) => goToEdit(event.event_id)}
|
||||
onDelete = {(id) => disableEvent(id)}
|
||||
viewerExtraComponent = {(fields, event) => {
|
||||
return (<div>
|
||||
<div>{`Client: ${event.customer}`}</div>
|
||||
<div>{`Doctor: ${event.doctor}`}</div>
|
||||
<div>{`Contact: ${event.contact}`} </div>
|
||||
<div>{`Address: ${event.address}`} </div>
|
||||
<hr />
|
||||
</div>)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
@ -2,11 +2,12 @@ import { Bell, ChevronDown, PersonCircle } from 'react-bootstrap-icons';
|
||||
import { Outlet, useLocation, Navigate } from 'react-router-dom';
|
||||
import { AuthService } from '../../services';
|
||||
import SideMenu from './menu';
|
||||
import { Dropdown } from "react-bootstrap";
|
||||
|
||||
function Layout() {
|
||||
const location = useLocation();
|
||||
const showMenu = location.pathname !== '/login' && location.pathname !== '/landing'; // Example: Hide menu on login page
|
||||
const user = localStorage.getItem('user') || {};
|
||||
const user = localStorage.getItem('user');
|
||||
const getLogoSuffix = () => {
|
||||
return (window.location.hostname.includes('worldshine2.mayo.llc') || window.location.hostname.includes('site2') || window.location.host.includes('ws2') ||window.location.hostname.includes('localhost')) ? "Care LLC" : ((window.location.hostname.includes('worldshine3.mayo.llc') ||window.location.hostname.includes('site3') || window.location.hostname.includes('ws3')) ? "Cloverleaf LLC" : "International LLC");
|
||||
}
|
||||
@ -20,12 +21,21 @@ function Layout() {
|
||||
<div className="app-menu-user-profile-container">
|
||||
<Bell size={16} color="#0066B1"/>
|
||||
<div className="app-menu-user-profile ms-2">
|
||||
<PersonCircle size={24}/>
|
||||
<div className="user-info-container me-2">
|
||||
<div className="user-name">{JSON.parse(user).username}</div>
|
||||
<div className="user-role">{JSON.parse(user).roles[0]}</div>
|
||||
</div>
|
||||
<ChevronDown size={12} color="#555"></ChevronDown>
|
||||
<PersonCircle size={24}/>
|
||||
<div className="user-info-container me-2">
|
||||
<div className="user-name">{user && JSON.parse(user)?.username}</div>
|
||||
<div className="user-role">{user && JSON.parse(user)?.roles[0]}</div>
|
||||
</div>
|
||||
<Dropdown>
|
||||
<Dropdown.Toggle variant="tertiary" id="user-basic">
|
||||
{/* <ChevronDown size={12} color="#555"></ChevronDown> */}
|
||||
</Dropdown.Toggle>
|
||||
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item className="small-dropdown-item" onClick={() => AuthService.logout()}>Logout</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -206,7 +206,6 @@ const SideMenu = () => {
|
||||
}
|
||||
|
||||
const goToLink = (link) => {
|
||||
console.log('this is lik', link);
|
||||
navigate(link);
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,10 @@ import React, {useEffect, useState} from "react";
|
||||
import { useSelector,useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { vehicleSlice, selectVehicleError } from "./../../store";
|
||||
import { AuthService } from "../../services";
|
||||
import { AuthService, VehicleService } from "../../services";
|
||||
import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab } from "react-bootstrap";
|
||||
import DatePicker from "react-datepicker";
|
||||
import moment from 'moment';
|
||||
|
||||
const CreateVehicle = () => {
|
||||
const navigate = useNavigate();
|
||||
@ -26,6 +28,18 @@ const CreateVehicle = () => {
|
||||
const [mileage, setMileage] = useState();
|
||||
const [capacity, setCapacity] = useState();
|
||||
const [checklist, setChecklist] = useState(['']);
|
||||
const [hasLiftEquip, setHasLiftEquip] = useState(undefined);
|
||||
const [insuranceExpireOn, setInsuranceExpireOn] = useState(undefined);
|
||||
const [titleRegistrationOn, setTitleRegistrationOn] = useState(undefined);
|
||||
const [emissionTestOn, setEmissionTestOn] = useState(undefined);
|
||||
const [oilChangeMileage, setOilChangeMileage] = useState(undefined);
|
||||
const [oilChangeDate, setOilChangeDate] = useState(undefined);
|
||||
const [vin, setVin] = useState('');
|
||||
const [note, setNote] = useState('');
|
||||
// const [selectedMothlyFile, setSelectedMonthlyFile] = useState();
|
||||
// const [selectedYearlyFile, setSelectedYearlyFile] = useState();
|
||||
// const [monthlyInspectionDate, setMonthlyInspectionDate] = useState();
|
||||
// const [yearlyInspectionDate, setYearlyInspectionDate] = useState();
|
||||
const error = useSelector(selectVehicleError);
|
||||
|
||||
const redirectTo = () => {
|
||||
@ -60,11 +74,27 @@ const CreateVehicle = () => {
|
||||
make,
|
||||
vehicle_model: vehicleModel,
|
||||
status: 'active',
|
||||
checklist
|
||||
checklist,
|
||||
note,
|
||||
vin,
|
||||
has_lift_equip: hasLiftEquip === 'true',
|
||||
insurance_expire_on: moment(insuranceExpireOn).format('MM/DD/YYYY'),
|
||||
title_registration_on: moment(titleRegistrationOn).format('MM/DD/YYYY'),
|
||||
emission_test_on: moment(emissionTestOn).format('MM/DD/YYYY'),
|
||||
oil_change_date: moment(oilChangeDate).format('MM/DD/YYYY')
|
||||
};
|
||||
dispatch(createVehicle({data, redirectFun: redirectTo}));
|
||||
}
|
||||
|
||||
// const saveDocument = () => {
|
||||
// if (selectedMothlyFile && monthlyInspectionDate) {
|
||||
// VehicleService.uploadVechileFile(formData, currentVechile.id, currentVehchile.vehicle_number, 'monthlyInspection', monthlyInspectionDate);
|
||||
// }
|
||||
// if (selectedYearlyFile && yearlyInspectionDate) {
|
||||
// VehicleService.uploadVechileFile(formData, currentVechile.id, currentVehchile.vehicle_number, 'yearlyInspection', yearlyInspectionDate);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -101,20 +131,57 @@ const CreateVehicle = () => {
|
||||
</div>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4"><div className="field-label">Year</div><input type="text" value={year || ''} placeholder="e.g.,2016" onChange={e => setYear(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">Vin Number</div><input type="text" value={vin || ''} placeholder="e.g, 1FBAX2CM9KA34959" onChange={e => setVin(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">Licence Plate</div><input type="text" value={tag || ''} placeholder="e.g.,91579HT" onChange={e => setTag(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">GPS ID</div><input type="text" value={gps || ''} placeholder="e.g.,609671" onChange={e => setGps(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">EZPass</div><input type="text" value={ezpass || ''} placeholder="e.g.,NY12345" onChange={e => setEzpass(e.target.value)}/></div>
|
||||
{/* Lift Equipped & VIN Number would be added later */}
|
||||
<div className="me-4">
|
||||
<div className="field-label">Lift Equipped</div>
|
||||
<select value={hasLiftEquip} onChange={e => setHasLiftEquip(e.target.value)}>
|
||||
<option value=""></option>
|
||||
<option value="true">Yes</option>
|
||||
<option value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{/* Vehicle Maintenance & Compliance would be added later */}
|
||||
<h6 className="text-primary">Vehicle Maintenance & Compliance</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Last Oil Change Date <span className="field-blurb float-right">1-month due cycle </span></div>
|
||||
<DatePicker selected={oilChangeDate} onChange={(v) => setOilChangeDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Last Emissions Inspection Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={emissionTestOn} onChange={(v) => setEmissionTestOn(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Insurance Expiration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={insuranceExpireOn} onChange={(v) => setInsuranceExpireOn(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Title Registration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={titleRegistrationOn} onChange={(v) => setTitleRegistrationOn(v)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h6 className="text-primary">Check List</h6>
|
||||
<div className="app-main-content-fields-section column">
|
||||
{checklist.map((item, index) => (<div className="mb-4" key={index}><input type="text" value={item} onChange={(e) => setChecklist([...checklist].map((a, index1) => {if (index1 === index) {return e.target.value;} return a;}))}/>
|
||||
<button className="btn btn-link btn-sm" onClick={(e) => setChecklist([...checklist].filter((value, index1) => index1 != index))}>Remove</button>
|
||||
</div>))}
|
||||
<button className="btn btn-link" onClick={() => addItemToArray()}>+Add New Item</button>
|
||||
{/* Note would be added later */}
|
||||
</div>
|
||||
|
||||
<h6 className="text-primary">Additional Information</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Note</div>
|
||||
<textarea placeholder="Any Extra Details" value={note || ''} onChange={e => setNote(e.target.value)}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error && <div className="col-md-12 mb-4 alert alert-danger" role="alert">
|
||||
{error}
|
||||
</div>}
|
||||
@ -124,12 +191,53 @@ const CreateVehicle = () => {
|
||||
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab eventKey="documents" title="Documents">
|
||||
Coming soon...
|
||||
{/* <Tab eventKey="documents" title="Documents">
|
||||
<h6 className="text-primary">Yearly Vehicle Inspection</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Vehicle Inspection Date<span className="required">*</span></div>
|
||||
<DatePicker selected={yearlyInspectionDate} onChange={(v) => setYearlyInspectionDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Yearly Vehicle Inspection Sheet<span className="required">*</span></div>
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload Files
|
||||
<input
|
||||
type="file"
|
||||
onChange={(e) => setSelectedYearlyFile(e.target.files[0])}
|
||||
/>
|
||||
</label>
|
||||
<div className="file-name">{ selectedYearlyFile && selectedYearlyFile?.name }</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 className="text-primary">Monthly Vehicle Inspection</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Vehicle Inspection Date <span className="required">*</span></div>
|
||||
<DatePicker selected={monthlyInspectionDate} onChange={(v) => setMonthlyInspectionDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Monthly Vehicle Inspection Sheet<span className="required">*</span></div>
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload Files
|
||||
<input
|
||||
type="file"
|
||||
onChange={(e) => setSelectedMonthlyFile(e.target.files[0])}
|
||||
/>
|
||||
</label>
|
||||
<div className="file-name">{ selectedMothlyFile && selectedMothlyFile?.name }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 col-sm-12 col-xs-12">
|
||||
<button className="btn btn-default btn-sm float-right" onClick={() => redirectTo()}> Cancel </button>
|
||||
<button className="btn btn-primary btn-sm float-right" onClick={() => saveDocuments()}> Save </button>
|
||||
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab eventKey="Repair Records" title="Repair Records">
|
||||
Coming soon...
|
||||
</Tab>
|
||||
</Tab> */}
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,9 +2,12 @@ import React, {useEffect, useState} from "react";
|
||||
import { useSelector,useDispatch } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { vehicleSlice, selectVehicleError } from "./../../store";
|
||||
import { AuthService } from "../../services";
|
||||
import { Archive } from "react-bootstrap-icons";
|
||||
import { AuthService, VehicleService } from "../../services";
|
||||
import { Archive, Upload } from "react-bootstrap-icons";
|
||||
import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab } from "react-bootstrap";
|
||||
import DatePicker from "react-datepicker";
|
||||
import moment from 'moment';
|
||||
|
||||
|
||||
const UpdateVehicle = () => {
|
||||
const navigate = useNavigate();
|
||||
@ -23,6 +26,18 @@ const UpdateVehicle = () => {
|
||||
const [mileage, setMileage] = useState();
|
||||
const [capacity, setCapacity] = useState();
|
||||
const [checklist, setChecklist] = useState(['']);
|
||||
const [hasLiftEquip, setHasLiftEquip] = useState(undefined);
|
||||
const [insuranceExpireOn, setInsuranceExpireOn] = useState(undefined);
|
||||
const [titleRegistrationOn, setTitleRegistrationOn] = useState(undefined);
|
||||
const [emissionTestOn, setEmissionTestOn] = useState(undefined);
|
||||
const [oilChangeMileage, setOilChangeMileage] = useState(undefined);
|
||||
const [oilChangeDate, setOilChangeDate] = useState(undefined);
|
||||
const [vin, setVin] = useState('');
|
||||
const [note, setNote] = useState('');
|
||||
const [selectedMothlyFile, setSelectedMonthlyFile] = useState();
|
||||
const [selectedYearlyFile, setSelectedYearlyFile] = useState();
|
||||
const [monthlyInspectionDate, setMonthlyInspectionDate] = useState();
|
||||
const [yearlyInspectionDate, setYearlyInspectionDate] = useState();
|
||||
const error = useSelector(selectVehicleError);
|
||||
|
||||
useEffect(() => {
|
||||
@ -48,6 +63,13 @@ const UpdateVehicle = () => {
|
||||
setMileage(currentVehicle.mileage);
|
||||
setCapacity(currentVehicle.capacity);
|
||||
setChecklist(currentVehicle.checklist);
|
||||
setHasLiftEquip(currentVehicle.has_lift_equip === true ? 'true': (currentVehicle?.has_lift_equip === false ? 'false' : undefined) );
|
||||
setNote(currentVehicle?.note);
|
||||
setVin(currentVehicle?.vin);
|
||||
setInsuranceExpireOn(currentVehicle.insurance_expire_on && VehicleService.convertToDate(currentVehicle.insurance_expire_on));
|
||||
setTitleRegistrationOn(currentVehicle?.title_registration_on && VehicleService.convertToDate(currentVehicle?.title_registration_on));
|
||||
setEmissionTestOn(currentVehicle.title_registration_on && VehicleService.convertToDate(currentVehicle.title_registration_on));
|
||||
setOilChangeDate(currentVehicle.oil_change_date && VehicleService.convertToDate(currentVehicle.oil_change_date));
|
||||
}
|
||||
|
||||
}, [currentVehicle])
|
||||
@ -83,7 +105,14 @@ const UpdateVehicle = () => {
|
||||
make,
|
||||
vehicle_model: vehicleModel,
|
||||
status: 'active',
|
||||
checklist
|
||||
checklist,
|
||||
note,
|
||||
vin,
|
||||
has_lift_equip: hasLiftEquip === 'true',
|
||||
insurance_expire_on: moment(insuranceExpireOn).format('MM/DD/YYYY'),
|
||||
title_registration_on: moment(titleRegistrationOn).format('MM/DD/YYYY'),
|
||||
emission_test_on: moment(emissionTestOn).format('MM/DD/YYYY'),
|
||||
oil_change_date: moment(oilChangeDate).format('MM/DD/YYYY')
|
||||
};
|
||||
dispatch(updateVehicle({id: params.id, data, redirectFun: redirectTo}));
|
||||
}
|
||||
@ -106,6 +135,20 @@ const UpdateVehicle = () => {
|
||||
redirectTo();
|
||||
}
|
||||
|
||||
const saveDocuments = () => {
|
||||
if (selectedMothlyFile && monthlyInspectionDate) {
|
||||
const monthlyFormData = new FormData();
|
||||
monthlyFormData.append('file', selectedMothlyFile);
|
||||
VehicleService.uploadVechileFile(monthlyFormData, currentVehicle.id, currentVehicle.vehicle_number, 'monthlyInspection', monthlyInspectionDate);
|
||||
}
|
||||
if (selectedYearlyFile && yearlyInspectionDate) {
|
||||
const yearlyFormData = new FormData();
|
||||
yearlyFormData.append('file', selectedYearlyFile);
|
||||
VehicleService.uploadVechileFile(yearlyFormData, currentVehicle.id, currentVehicle.vehicle_number, 'yearlyInspection', yearlyInspectionDate);
|
||||
}
|
||||
redirectTo();
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -142,19 +185,51 @@ const UpdateVehicle = () => {
|
||||
</div>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4"><div className="field-label">Year</div><input type="text" value={year || ''} placeholder="e.g.,2016" onChange={e => setYear(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">Vin Number</div><input type="text" value={vin || ''} placeholder="e.g, 1FBAX2CM9KA34959" onChange={e => setVin(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">Licence Plate</div><input type="text" value={tag || ''} placeholder="e.g.,91579HT" onChange={e => setTag(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">GPS ID</div><input type="text" value={gps || ''} placeholder="e.g.,609671" onChange={e => setGps(e.target.value)}/></div>
|
||||
<div className="me-4"><div className="field-label">EZPass</div><input type="text" value={ezpass || ''} placeholder="e.g.,NY12345" onChange={e => setEzpass(e.target.value)}/></div>
|
||||
{/* Lift Equipped & VIN Number would be added later */}
|
||||
<div className="me-4">
|
||||
<div className="field-label">Lift Equipped</div>
|
||||
<select value={hasLiftEquip} onChange={e => setHasLiftEquip(e.target.value)}>
|
||||
<option value=""></option>
|
||||
<option value="true">Yes</option>
|
||||
<option value="false">No</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<h6 className="text-primary">Vehicle Maintenance & Compliance</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Last Oil Change Date <span className="field-blurb float-right">1-month due cycle </span></div>
|
||||
<DatePicker selected={oilChangeDate} onChange={(v) => setOilChangeDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Last Emissions Inspection Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={emissionTestOn} onChange={(v) => setEmissionTestOn(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Insurance Expiration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={insuranceExpireOn} onChange={(v) => setInsuranceExpireOn(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Title Registration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<DatePicker selected={titleRegistrationOn} onChange={(v) => setTitleRegistrationOn(v)} />
|
||||
</div>
|
||||
</div>
|
||||
{/* Vehicle Maintenance & Compliance would be added later */}
|
||||
<h6 className="text-primary">Check List</h6>
|
||||
<div className="app-main-content-fields-section column">
|
||||
{checklist.map((item, index) => (<div className="mb-4" key={index}><input type="text" value={item} onChange={(e) => setChecklist([...checklist].map((a, index1) => {if (index1 === index) {return e.target.value;} return a;}))}/>
|
||||
<button className="btn btn-link btn-sm" onClick={(e) => setChecklist([...checklist].filter((value, index1) => index1 != index))}>Remove</button>
|
||||
</div>))}
|
||||
<button className="btn btn-link" onClick={() => addItemToArray()}>+Add New Item</button>
|
||||
{/* Note would be added later */}
|
||||
</div>
|
||||
<h6 className="text-primary">Additional Information</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Note</div>
|
||||
<textarea placeholder="Any Extra Details" value={note || ''} onChange={e => setNote(e.target.value)}/>
|
||||
</div>
|
||||
</div>
|
||||
{error && <div className="col-md-12 mb-4 alert alert-danger" role="alert">
|
||||
{error}
|
||||
@ -166,7 +241,48 @@ const UpdateVehicle = () => {
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab eventKey="documents" title="Documents">
|
||||
Coming soon...
|
||||
<h6 className="text-primary">Yearly Vehicle Inspection</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Vehicle Inspection Date<span className="required">*</span></div>
|
||||
<DatePicker selected={yearlyInspectionDate} onChange={(v) => setYearlyInspectionDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Yearly Vehicle Inspection Sheet<span className="required">*</span></div>
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload Files
|
||||
<input
|
||||
type="file"
|
||||
onChange={(e) => setSelectedYearlyFile(e.target.files[0])}
|
||||
/>
|
||||
</label>
|
||||
<div className="file-name">{ selectedYearlyFile && selectedYearlyFile?.name }</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 className="text-primary">Monthly Vehicle Inspection</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="me-4">
|
||||
<div className="field-label">Vehicle Inspection Date <span className="required">*</span></div>
|
||||
<DatePicker selected={monthlyInspectionDate} onChange={(v) => setMonthlyInspectionDate(v)} />
|
||||
</div>
|
||||
<div className="me-4">
|
||||
<div className="field-label">Monthly Vehicle Inspection Sheet<span className="required">*</span></div>
|
||||
<label className="custom-file-upload">
|
||||
<Upload width={20} color={"#fff"} className="me-2"></Upload> Upload Files
|
||||
<input
|
||||
type="file"
|
||||
onChange={(e) => setSelectedMonthlyFile(e.target.files[0])}
|
||||
/>
|
||||
</label>
|
||||
<div className="file-name">{ selectedMothlyFile && selectedMothlyFile?.name }</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-12 col-sm-12 col-xs-12">
|
||||
<button className="btn btn-default btn-sm float-right" onClick={() => redirectTo()}> Cancel </button>
|
||||
<button className="btn btn-primary btn-sm float-right" onClick={() => saveDocuments()}> Save </button>
|
||||
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab eventKey="Repair Records" title="Repair Records">
|
||||
Coming soon...
|
||||
|
||||
@ -4,14 +4,23 @@ import { useSelector,useDispatch } from "react-redux";
|
||||
import { AuthService, VehicleService } from "../../services";
|
||||
import { vehicleSlice, selectVehicleError } from "./../../store";
|
||||
import { Spinner, Breadcrumb, BreadcrumbItem, Tabs, Tab } from "react-bootstrap";
|
||||
import { Download, Pencil, Archive } from "react-bootstrap-icons";
|
||||
import { Download, PencilSquare, Archive } from "react-bootstrap-icons";
|
||||
import moment from "moment";
|
||||
|
||||
const ViewVehicle = () => {
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const urlParams = useParams();
|
||||
const [currentVehicle, setCurrentVehicle] = useState(undefined);
|
||||
|
||||
const [monthlyDocs, setMonthlyDocs] = useState([]);
|
||||
const [yearlyDocs, setYearlyDocs] = useState([]);
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [sortingMonthly, setSortingMonthly] = useState({key: '', order: ''});
|
||||
const [sortingYearly, setSortingYearly] = useState({key: '', order: ''});
|
||||
const [selectedItemsMonthly, setSelectedItemsMonthly] = useState([]);
|
||||
const [selectedItemsYearly, setSelectedItemsYearly] = useState([]);
|
||||
const [filteredMonthlyDocs, setFilteredMonthlyDocs] = useState(monthlyDocs);
|
||||
const [filteredYearlyDocs, setFilteredYearlyDocs] = useState(yearlyDocs);
|
||||
const { updateVehicle, deleteVehicle, fetchAllVehicles } = vehicleSlice.actions;
|
||||
|
||||
const redirectTo = () => {
|
||||
@ -22,6 +31,18 @@ const ViewVehicle = () => {
|
||||
navigate(`/vehicles/edit/${id}?redirect=list`)
|
||||
}
|
||||
|
||||
const download = () => {
|
||||
const downloadArr = [...selectedItemsMonthly, ...selectedItemsYearly];
|
||||
downloadArr.forEach((url) => {
|
||||
const a = document.createElement('a');
|
||||
a.href= url;
|
||||
a.download = '';
|
||||
document.body.append(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
})
|
||||
}
|
||||
|
||||
const deactivateVehicle = () => {
|
||||
const data = {
|
||||
status: 'inactive'
|
||||
@ -31,6 +52,24 @@ const ViewVehicle = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const getInspectionDate = (name) => {
|
||||
const arr1 = name.split('.');
|
||||
const prefix = arr1[0];
|
||||
if (prefix) {
|
||||
const arr2 = prefix.split('_');
|
||||
const dateNumber = arr2[arr2.length - 1];
|
||||
|
||||
return dateNumber ? new Date(parseInt(dateNumber)).toLocaleDateString('en-US', {month: '2-digit', day: '2-digit', year: 'numeric'}) : moment().format('MM/DD/YYYY');
|
||||
} else {
|
||||
return moment().format('MM/DD/YYYY');
|
||||
}
|
||||
}
|
||||
const getAllDocuments = async (vid, name) => {
|
||||
const monthlyInspectionDocs = (await VehicleService.getAllVechileFiles(vid, name, 'monthlyInspection'))?.data?.data?.files || [];
|
||||
const yearlyInspectionDocs = (await VehicleService.getAllVechileFiles(vid, name, 'yearlyInspection'))?.data?.data?.files || [];
|
||||
setMonthlyDocs(monthlyInspectionDocs?.map(item => ({ ...item, inspectionDate: getInspectionDate(item?.name) })));
|
||||
setYearlyDocs(yearlyInspectionDocs?.map(item => ({ ...item, inspectionDate: getInspectionDate(item?.name) })));
|
||||
};
|
||||
if (!AuthService.canViewVechiles()) {
|
||||
window.alert('You haven\'t login yet OR this user does not have access to this page. Please change an admin account to login.')
|
||||
AuthService.logout();
|
||||
@ -39,9 +78,207 @@ const ViewVehicle = () => {
|
||||
if (!currentVehicle) {
|
||||
VehicleService.getVehicle(urlParams.id).then((data) => {
|
||||
setCurrentVehicle(data.data);
|
||||
getAllDocuments(data.data?.id, data.data?.vehicle_number);
|
||||
})
|
||||
} else {
|
||||
getAllDocuments(currentVehicle?.id, currentVehicle?.vehicle_number);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setFilteredMonthlyDocs(monthlyDocs.filter(item => item?.name?.toLowerCase().includes(keyword.toLowerCase()) || item?.inspectionDate?.includes(keyword.toLowerCase())));
|
||||
setFilteredYearlyDocs(yearlyDocs.filter(item => item?.name?.toLowerCase().includes(keyword.toLowerCase()) || item?.inspectionDate?.includes(keyword.toLowerCase())));
|
||||
}, [keyword, yearlyDocs, monthlyDocs]);
|
||||
|
||||
useEffect(() => {
|
||||
const newYearlyDocs = [...yearlyDocs];
|
||||
const sortedYearlyDocs = sortingYearly.key === '' ? newYearlyDocs : newYearlyDocs.sort((a, b) => {
|
||||
return a[sortingYearly.key]?.localeCompare(b[sortingYearly.key]);
|
||||
});
|
||||
setYearlyDocs(
|
||||
sortingMonthly.order === 'asc' ? sortedYearlyDocs : sortedYearlyDocs.reverse()
|
||||
)
|
||||
}, [sortingYearly]);
|
||||
|
||||
useEffect(() => {
|
||||
const newMonthlyDocs = [...monthlyDocs];
|
||||
const sortedMonthlyDocs = sortingMonthly.key === '' ? newMonthlyDocs : newMonthlyDocs.sort((a, b) => {
|
||||
return a[sortingMonthly.key]?.localeCompare(b[sortingMonthly.key]);
|
||||
});
|
||||
setMonthlyDocs(
|
||||
sortingMonthly.order === 'asc' ? sortedMonthlyDocs : sortedMonthlyDocs.reverse()
|
||||
)
|
||||
}, [sortingMonthly]);
|
||||
|
||||
const columnsMonthly = [
|
||||
{
|
||||
key: 'name',
|
||||
label: 'Monthly Vehicle Inspection Sheet'
|
||||
},
|
||||
{
|
||||
key: 'inspectionDate',
|
||||
label: 'Vehicle Inspection Date'
|
||||
},
|
||||
{
|
||||
key: 'createdAt',
|
||||
label: 'Date Added'
|
||||
}
|
||||
];
|
||||
|
||||
const columnsYearly = [
|
||||
{
|
||||
key: 'name',
|
||||
label: 'Yearly Vehicle Inspection Sheet'
|
||||
},
|
||||
{
|
||||
key: 'inspectionDate',
|
||||
label: 'Vehicle Inspection Date'
|
||||
},
|
||||
{
|
||||
key: 'createdAt',
|
||||
label: 'Date Added'
|
||||
}
|
||||
];
|
||||
|
||||
const sortTableWithFieldMonthly = (key) => {
|
||||
let newSorting = {
|
||||
key,
|
||||
order: 'asc',
|
||||
}
|
||||
|
||||
if (sortingMonthly.key === key && sortingMonthly.order === 'asc') {
|
||||
newSorting = {...newSorting, order: 'desc'};
|
||||
}
|
||||
setSortingMonthly(newSorting);
|
||||
}
|
||||
|
||||
const sortTableWithFieldYearly = (key) => {
|
||||
let newSorting = {
|
||||
key,
|
||||
order: 'asc',
|
||||
}
|
||||
|
||||
if (sortingYearly.key === key && sortingYearly.order === 'asc') {
|
||||
newSorting = {...newSorting, order: 'desc'};
|
||||
}
|
||||
setSortingYearly(newSorting);
|
||||
}
|
||||
|
||||
const toggleSelectedAllItemsMonthly = () => {
|
||||
if (selectedItemsMonthly.length !== filteredMonthlyDocs.length || selectedItemsMonthly.length === 0) {
|
||||
const newSelectedItems = [...filteredMonthlyDocs].map((doc) => doc.url);
|
||||
setSelectedItemsMonthly(newSelectedItems);
|
||||
} else {
|
||||
setSelectedItemsMonthly([]);
|
||||
}
|
||||
}
|
||||
|
||||
const toggleSelectedAllItemsYearly = () => {
|
||||
if (selectedItemsYearly.length !== filteredYearlyDocs.length || selectedItemsYearly.length === 0) {
|
||||
const newSelectedItems = [...filteredYearlyDocs].map((doc) => doc.url);
|
||||
setSelectedItemsYearly(newSelectedItems);
|
||||
} else {
|
||||
setSelectedItemsYearly([]);
|
||||
}
|
||||
}
|
||||
|
||||
const toggleItemYearly = (id) => {
|
||||
if (selectedItemsYearly.includes(id)) {
|
||||
const newSelectedItems = [...selectedItemsYearly].filter((item) => item !== id);
|
||||
setSelectedItemsYearly(newSelectedItems);
|
||||
} else {
|
||||
const newSelectedItems = [...selectedItemsYearly, id];
|
||||
setSelectedItemsYearly(newSelectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
const toggleItemMonthly = (id) => {
|
||||
if (selectedItemsMonthly.includes(id)) {
|
||||
const newSelectedItems = [...selectedItemsMonthly].filter((item) => item !== id);
|
||||
setSelectedItemsMonthly(newSelectedItems);
|
||||
} else {
|
||||
const newSelectedItems = [...selectedItemsMonthly, id];
|
||||
setSelectedItemsMonthly(newSelectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
const getSortingImgMonthly = (key) => {
|
||||
return sortingMonthly.key === key ? (sortingMonthly.order === 'asc' ? 'up_arrow' : 'down_arrow') : 'default';
|
||||
}
|
||||
|
||||
const getSortingImgYearly = (key) => {
|
||||
return sortingYearly.key === key ? (sortingYearly.order === 'asc' ? 'up_arrow' : 'down_arrow') : 'default';
|
||||
}
|
||||
|
||||
const checkSelectAllMonthly = () => {
|
||||
return selectedItemsMonthly.length === filteredMonthlyDocs.length && selectedItemsMonthly.length > 0;
|
||||
}
|
||||
|
||||
const checkSelectAllYearly = () => {
|
||||
return selectedItemsYearly.length === filteredYearlyDocs.length && selectedItemsYearly.length > 0;
|
||||
}
|
||||
|
||||
const tableMonthly = <div className="list row mb-4">
|
||||
<div className="col-md-12">
|
||||
<table className="personnel-info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="th-checkbox"><input type="checkbox" checked={checkSelectAllMonthly()} onClick={() => toggleSelectedAllItemsMonthly()}></input></th>
|
||||
<th className="th-index">No.</th>
|
||||
{
|
||||
columnsMonthly.map((column, index) => <th className="sortable-header" key={index}>
|
||||
{column.label} <span className="float-right" onClick={() => sortTableWithFieldMonthly(column.key)}><img src={`/images/${getSortingImgMonthly(column.key)}.png`}></img></span>
|
||||
</th>)
|
||||
}
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
filteredMonthlyDocs.map((doc, index) => <tr key={doc.url}>
|
||||
<td className="td-checkbox"><input type="checkbox" checked={selectedItemsMonthly.includes(doc?.url)} onClick={()=>toggleItemMonthly(doc?.url)}/></td>
|
||||
<td className="td-index">{index + 1}</td>
|
||||
<td> <PencilSquare size={16} className="clickable me-2" onClick={() => goToEdit(currentVehicle?.id)}></PencilSquare>
|
||||
<a className="btn btn-link btn-sm" href={doc?.url} target="_blank">{doc?.name}</a> </td>
|
||||
<td>{doc?.inspectionDate}</td>
|
||||
<td>{new Date(doc?.createdAt).toLocaleDateString('en-US', {month: '2-digit', day: '2-digit', year: 'numeric'})}</td>
|
||||
</tr>)
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
const tableYearly = <div className="list row mb-4">
|
||||
<div className="col-md-12">
|
||||
<table className="personnel-info-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="th-checkbox"><input type="checkbox" checked={checkSelectAllYearly()} onClick={() => toggleSelectedAllItemsYearly()}></input></th>
|
||||
<th className="th-index">No.</th>
|
||||
{
|
||||
columnsYearly.map((column, index) => <th className="sortable-header" key={index}>
|
||||
{column.label} <span className="float-right" onClick={() => sortTableWithFieldYearly(column.key)}><img src={`/images/${getSortingImgYearly(column.key)}.png`}></img></span>
|
||||
</th>)
|
||||
}
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
filteredYearlyDocs.map((doc, index) => <tr key={doc.url}>
|
||||
<td className="td-checkbox"><input type="checkbox" checked={selectedItemsYearly.includes(doc?.url)} onClick={()=>toggleItemYearly(doc?.url)}/></td>
|
||||
<td className="td-index">{index + 1}</td>
|
||||
<td> <PencilSquare size={16} className="clickable me-2" onClick={() => goToEdit(currentVehicle?.id)}></PencilSquare>
|
||||
<a className="btn btn-link btn-sm" href={doc?.url} target="_blank">{doc?.name}</a> </td>
|
||||
<td>{doc?.inspectionDate}</td>
|
||||
<td>{new Date(doc?.createdAt).toLocaleDateString('en-US', {month: '2-digit', day: '2-digit', year: 'numeric'})}</td>
|
||||
</tr>)
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -91,6 +328,10 @@ const ViewVehicle = () => {
|
||||
<div className="field-label">Year</div>
|
||||
<div className="field-value">{currentVehicle?.year}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Vin Number</div>
|
||||
<div className="field-value">{currentVehicle?.vin}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Licence Plate</div>
|
||||
<div className="field-value">{currentVehicle?.tag}</div>
|
||||
@ -103,25 +344,59 @@ const ViewVehicle = () => {
|
||||
<div className="field-label">EZPass</div>
|
||||
<div className="field-value">{currentVehicle?.ezpass}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Lift Equipped</div>
|
||||
<div className="field-value">{currentVehicle?.has_lift_equip === true ? 'Yes' : (currentVehicle?.has_lift_equip === false? 'No' : '')}</div>
|
||||
</div>
|
||||
</div>
|
||||
<h6 className="text-primary">Vehicle Maintenance & Compliance</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="field-body">
|
||||
<div className="field-label">Last Oil Change Date <span className="field-blurb float-right">1-month due cycle </span></div>
|
||||
<div className="field-value">{currentVehicle?.oil_change_date}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Last Emissions Inspection Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<div className="field-value">{currentVehicle?.emission_test_on}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Insurance Expiration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<div className="field-value">{currentVehicle?.insurance_expire_on}</div>
|
||||
</div>
|
||||
<div className="field-body">
|
||||
<div className="field-label">Title Registration Date <span className="field-blurb float-right">1-year due cycle </span></div>
|
||||
<div className="field-value">{currentVehicle?.title_registration_on}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 className="text-primary">Check List</h6>
|
||||
<div className="app-main-content-fields-section column">
|
||||
<ul>
|
||||
{currentVehicle?.checklist?.map((item) => <li>{item}</li>)}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h6 className="text-primary">Additional Information</h6>
|
||||
<div className="app-main-content-fields-section">
|
||||
<div className="field-body">
|
||||
<div className="field-label">Note</div>
|
||||
<div className="field-value">{currentVehicle?.note}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab eventKey="documents" title="Documents">
|
||||
Coming soon...
|
||||
<h6 className="text-primary">Yearly Vehicle Inspection</h6>
|
||||
{tableYearly}
|
||||
<h6 className="text-primary">Monthly Vehicle Inspection</h6>
|
||||
{tableMonthly}
|
||||
</Tab>
|
||||
<Tab eventKey="Repair Records" title="Repair Records">
|
||||
Coming soon...
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div className="list-func-panel">
|
||||
<button className="btn btn-primary me-2" onClick={() => goToEdit(currentVehicle?.id)}><Pencil size={16} className="me-2"></Pencil>Edit</button>
|
||||
<button className="btn btn-primary me-2" onClick={() => deactivateVehicle()}><Archive size={16} className="me-2"></Archive>Archive</button>
|
||||
<button className="btn btn-primary"><Download size={16} className="me-2"></Download>Export</button>
|
||||
<input className="me-2 with-search-icon" type="text" placeholder="Search" value={keyword} onChange={(e) => setKeyword(e.currentTarget.value)} />
|
||||
<button className="btn btn-primary" onClick={() => download()}><Download size={16} className="me-2"></Download>Download</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -30,6 +30,14 @@ const deleteEmployee = (id, data) => {
|
||||
return http.put(`/employees/${id}`, data);
|
||||
}
|
||||
|
||||
const uploadEmployeeFile = (data, employeeId, name, fileType) => {
|
||||
return http.post(`/files/upload-physical?objectId=${employeeId}&name=${name}&fileType=${fileType}&model=employee`, data)
|
||||
}
|
||||
|
||||
const getAllEmployeeFiles = (employeeId, name, fileType) => {
|
||||
return http.get(`/files/uploadedDocs/employee/${employeeId}/type/${fileType}/name/${name}`)
|
||||
}
|
||||
|
||||
const validatePassword = (password = '') => {
|
||||
const lowercaseRegex = /[a-z]/;
|
||||
const uppercaseRegex = /[A-Z]/;
|
||||
@ -59,5 +67,7 @@ export const EmployeeService = {
|
||||
updateEmployee,
|
||||
deleteEmployee,
|
||||
getEmployee,
|
||||
validatePassword
|
||||
validatePassword,
|
||||
uploadEmployeeFile,
|
||||
getAllEmployeeFiles
|
||||
};
|
||||
|
||||
@ -18,11 +18,27 @@ const getVehicle = (id) => {
|
||||
return http.get(`/vehicles/${id}`);
|
||||
};
|
||||
|
||||
const convertToDate = (dateString) => {
|
||||
const [month, day, year] = dateString.split('/');
|
||||
return new Date(Number(year), Number(month)-1, Number(day))
|
||||
}
|
||||
|
||||
const uploadVechileFile = (data, vehicleId, name, fileType, date) => {
|
||||
return http.post(`/files/upload-physical?objectId=${vehicleId}&name=${name}&fileType=${fileType}&model=vehicle&date=${date.getTime()}`, data)
|
||||
}
|
||||
|
||||
const getAllVechileFiles = (vehicleId, name, fileType) => {
|
||||
return http.get(`/files/uploadedDocs/vehicle/${vehicleId}/type/${fileType}/name/${name}`)
|
||||
}
|
||||
|
||||
export const VehicleService = {
|
||||
getAll,
|
||||
getAllActiveVehicles,
|
||||
updateVehicles,
|
||||
createNewVehicles,
|
||||
deleteVehicles,
|
||||
getVehicle
|
||||
getVehicle,
|
||||
convertToDate,
|
||||
uploadVechileFile,
|
||||
getAllVechileFiles
|
||||
};
|
||||
|
||||
@ -8,6 +8,8 @@ var corsOptions = {
|
||||
|
||||
// const path = __dirname + '/client/build/';
|
||||
const path = __dirname + '/app/views/'
|
||||
const employeeUploadBasePath = '/www/wwwroot/upload/';
|
||||
app.use('/files', express.static(employeeUploadBasePath));
|
||||
app.use(cors(corsOptions));
|
||||
// parse requests of content-type - application/json
|
||||
app.use(bodyParser.json());
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user