diff --git a/src/components/LeftNav.js b/src/components/LeftNav.js index 8a4c8b5..ee6e4c7 100644 --- a/src/components/LeftNav.js +++ b/src/components/LeftNav.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import { styled, useTheme } from '@mui/material/styles'; import Box from '@mui/material/Box'; import Drawer from '@mui/material/Drawer'; @@ -18,7 +18,7 @@ import PersonIcon from '@mui/icons-material/Person'; import TextSnippetIcon from '@mui/icons-material/TextSnippet'; import { makeStyles } from "@mui/styles"; import { Link } from "react-router-dom"; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; const drawerWidth = 240; @@ -44,14 +44,12 @@ const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })(({ ], })); - - const NavStyles = makeStyles((theme) => ({ header: { borderBottom: "2px solid rgba(0,0,0,0.1)", display: "flex", }, - title:{ + title: { fontWeight: "600!important", fontSize: "1.25rem!important", } @@ -62,93 +60,101 @@ const DrawerHeader = styled('div')(({ theme }) => ({ alignItems: 'center', padding: theme.spacing(0, 1), background: 'rgb(246 248 249)', - // necessary for content to be below app bar ...theme.mixins.toolbar, justifyContent: 'flex-end', })); -export default function PersistentDrawerLeft({ handleDrawerClose, open}) { +export default function PersistentDrawerLeft({ handleDrawerClose, open }) { const location = useLocation(); const theme = useTheme(); - + const drawerRef = useRef(null); // Create a ref for the drawer + useEffect(() => { - document.addEventListener('mousedown', handleDrawerClose); + const handleClickOutside = (event) => { + // Check if the click was outside the drawer + if (drawerRef.current && !drawerRef.current.contains(event.target)) { + handleDrawerClose(); + } + }; + + document.addEventListener('mousedown', handleClickOutside); return () => { - document.removeEventListener('mousedown', handleDrawerClose); + document.removeEventListener('mousedown', handleClickOutside); }; - }, []); + }, [handleDrawerClose]); return ( - - - - {theme.direction === 'ltr' ? : } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + boxSizing: 'border-box', + }, + }} + variant="persistent" + anchor="left" + open={open} + > + + + {theme.direction === 'ltr' ? : } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); } \ No newline at end of file diff --git a/src/components/ListHeader.js b/src/components/ListHeader.js index d059cec..5ca4646 100644 --- a/src/components/ListHeader.js +++ b/src/components/ListHeader.js @@ -6,7 +6,6 @@ import ListHeaderStyles from "./ListHeader.Styles"; const ListHeader = ({ handleClickFormModalOpen, isEmpty, text }) => { const classes = ListHeaderStyles(); return ( - !isEmpty && ( {text} @@ -20,7 +19,6 @@ const ListHeader = ({ handleClickFormModalOpen, isEmpty, text }) => { Add - ) ); }; export default ListHeader; diff --git a/src/pages/address/components/Form.js b/src/pages/address/components/Form.js index afcbca2..e264e64 100644 --- a/src/pages/address/components/Form.js +++ b/src/pages/address/components/Form.js @@ -76,28 +76,11 @@ const ItemForm = ({ - {PRIMARY_TEXT} + {PRIMARY_TEXT.replace("Item", "Address")} - - { - const { value } = event.target; - handleChangeKV("name", value); - }} - error={!!errors.FirstName} - helperText={errors.FirstName} - /> + /> + { + const { value } = event.target; + handleChangeKV("name", value); + }} + error={!!errors.FirstName} + helperText={errors.FirstName} + /> diff --git a/src/pages/address/components/Table.js b/src/pages/address/components/Table.js index 4ad878c..7e42a41 100644 --- a/src/pages/address/components/Table.js +++ b/src/pages/address/components/Table.js @@ -62,7 +62,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick }) => { } }, { - name: "name", + name: "title", label: "Name", options: { display: true, @@ -71,8 +71,8 @@ const TableItems = ({ items, onEditClick, onDeleteClick }) => { } }, { - name: "title", - label: "Title", + name: "name", + label: "Address", options: { display: true, filter: true, diff --git a/src/pages/workorder/_utility.js b/src/pages/workorder/_utility.js index 6b02e1c..c4b4104 100644 --- a/src/pages/workorder/_utility.js +++ b/src/pages/workorder/_utility.js @@ -1,7 +1,7 @@ export const initialValues = { "workerOrderNumber": "", - "workerOrderTitle": "", + "workerOrderTitle": "PLUMBING JANITORIAL SCRUBBER PIT CLEANOUT 13W", "description": "", "po": "", "tt": "", diff --git a/src/pages/workorder/attachments/ImageDrawer.js b/src/pages/workorder/attachments/ImageDrawer.js index 1d37518..58006ad 100644 --- a/src/pages/workorder/attachments/ImageDrawer.js +++ b/src/pages/workorder/attachments/ImageDrawer.js @@ -86,7 +86,7 @@ const ImageDrawer = ({ item, open, setOpen }) => { Upload Images { const [isFormLoading, setIsFormLoading] = useState(false); const [workOrders, setWorkOrders] = useState([]); @@ -58,7 +59,8 @@ const ItemForm = ({ const [isFormSubmit, setIsFormSubmit] = useState(false); const classes = FormStyles(); const { PRIMARY_TEXT, SECONDARY_TEXT, BUTTON_TEXT } = form_text_builder(mode); - const { values, errors, handleChangeKV, handleSubmit, setValues } = useForm({ + + const { values, errors, handleChangeKV, handleSubmit } = useForm({ initialValues: item, onSubmit(values) { setIsFormLoading(true); @@ -81,11 +83,11 @@ const ItemForm = ({ }); }, validate: (formValues) => { - if (isFormSubmit) setIsFormSubmit(false); - + if (isFormSubmit) setIsFormSubmit(false); return formValidation(formValues); }, }); + const handleClose = () => { setOpen({ open: false }); }; @@ -95,7 +97,6 @@ const ItemForm = ({ getContacts().then((response) => { handleSuccess(response, setContacts) }); getLocations().then((response) => { handleSuccess(response, setLocations) }); getCategories().then((response) => { handleSuccess(response, setCategories) }); - }, []); function handleSuccess(response, cb) { @@ -113,269 +114,230 @@ const ItemForm = ({ - + {PRIMARY_TEXT} -
- WO ID: - { - const { value } = event.target; - handleChangeKV("workerOrderNumber", value); - }} - error={!!errors.workerOrderNumber} - helperText={errors.workerOrderNumber} - /> +
{/* Changed alignItems to flex-start */} + {/* Left Section */} +
+ {/* Full-width Work Order Title */} + Work Order Title: + handleChangeKV("workerOrderTitle", event.target.value)} + error={!!errors.workerOrderTitle} + helperText={errors.workerOrderTitle} + disabled={viewOnly} // Disable if in read-only mode + /> + + {/* Inputs Layout for WO number, PO#, TT# */} +
+
+ WO Number: + handleChangeKV("workerOrderNumber", event.target.value)} + error={!!errors.workerOrderNumber} + helperText={errors.workerOrderNumber} + disabled={viewOnly} // Disable if in read-only mode + /> +
+ +
+ PO #: + handleChangeKV("po", event.target.value)} + error={!!errors.po} + helperText={errors.po} + disabled={viewOnly} // Disable if in read-only mode + /> +
+ +
+ TT #: + handleChangeKV("tt", event.target.value)} + error={!!errors.tt} + helperText={errors.tt} + disabled={viewOnly} // Disable if in read-only mode + /> +
+
+ + {/* Inputs Layout for Priority, Schedule Date, Due Date */} +
+
+ Priority: + +
+ +
+ Schedule Date: + handleChangeKV("scheduleDate", event.target.value)} + disabled={viewOnly} // Disable if in read-only mode + /> +
+ +
+ Due Date: + handleChangeKV("dueDate", event.target.value)} + disabled={viewOnly} // Disable if in read-only mode + /> +
+
+ + {/* Inputs Layout for Categories and Work Order Type */} +
+
+ Categories: + +
+ +
+ Work Order Type: + +
+
+ + {/* Contact and Dispatcher */} +
+
+ Site Contact: + +
+ +
+ Dispatcher: + +
+
+ + {/* Location */} +
+ Location: + +
-
- - Work Order Title: - { - const { value } = event.target; - handleChangeKV("workerOrderTitle", value); - }} - error={!!errors.workerOrderTitle} - helperText={errors.workerOrderTitle} - /> -
-
- Description - { - const { value } = event.target; - handleChangeKV("description", value); - }} - error={!!errors.description} - helperText={errors.description} - /> -
-
- PO # : - { - const { value } = event.target; - handleChangeKV("po", value); - }} - error={!!errors.po} - helperText={errors.po} - /> -
-
- TT # - { - const { value } = event.target; - handleChangeKV("tt", value); - }} - error={!!errors.tt} - helperText={errors.tt} - /> -
-
- Due Date* - { - const { value } = event.target; - handleChangeKV("dueDate", value); - }} - error={!!errors.dueDate} - helperText={errors.dueDate} - /> -
-
- POC* - -
-
- Assigned To:* - -
-
- Priority:* - -
-
- Work Order Type:* - -
-
- Location:* - -
-
- Categories:* - + {/* Right Section for Notes, starts at the same level as Work Order Title */} +
{/* Added margin-top to align with the title */} + Notes: + handleChangeKV("notes", event.target.value)} + disabled={viewOnly} // Disable if in read-only mode + /> +
- - - + + {!viewOnly && ( + + )} @@ -384,4 +346,4 @@ const ItemForm = ({ ); }; -export default ItemForm; +export default ItemForm; \ No newline at end of file diff --git a/src/pages/workorder/components/Table.js b/src/pages/workorder/components/Table.js index a1309fe..b5afe61 100644 --- a/src/pages/workorder/components/Table.js +++ b/src/pages/workorder/components/Table.js @@ -4,12 +4,35 @@ import IconButton from "@mui/material/IconButton"; import EditOutlined from "@mui/icons-material/EditOutlined"; import DeleteIcon from "@mui/icons-material/Delete"; import SpeakerNotes from '@mui/icons-material/SpeakerNotes'; +import PermMediaIcon from '@mui/icons-material/PermMedia'; +import Select from "@mui/material/Select"; +import MenuItem from "@mui/material/MenuItem"; import TableStyles from './TableStyles'; import { createTheme, ThemeProvider } from '@mui/material/styles'; -import PermMediaIcon from '@mui/icons-material/PermMedia'; +import { post } from '../../../apiUtil'; +import { API_URL } from '../../../constants'; -const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpenAttachmentsClick }) => { +export const EditStatus = (item) => post(`${API_URL}/WorkOrder/EditStatus`, item); +export const EditAvettaTask = (item) => post(`${API_URL}/WorkOrder/EditAvettaTask`, item); + +const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpenAttachmentsClick, onRowClickViewOnly }) => { const classes = TableStyles(); + + const statusOptions = [ + "Open", + "Pending", + "Assigned", + "In Progress", + "On Hold", + "Cancelled", + "Completed" + ]; + + const completionOptions = [ + "Yes, Complete", + "Yes, Incomplete", + "No" // Default option + ]; const getMuiTheme = () => { return createTheme({ @@ -19,49 +42,61 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen root: { backgroundColor: '#98acbf', color: '#fff', - } - }, - }, - MUIDataTableSelectCell: { - styleOverrides: { - headerCell: { - backgroundColor: '#98acbf', - color: '#fff', - } - } - }, - MUIDataTableBodyRow: { - styleOverrides: { - root: { - '&:nth-of-type(odd)': { - backgroundColor: 'rgba(0, 0, 0, 0.02)' - } - } + cursor: 'col-resize', // Indicate column can be resized + }, }, }, MUIDataTableBodyCell: { styleOverrides: { root: { padding: 6, - wordBreak: 'break-all' - } + wordBreak: 'break-all', + }, + }, + }, + MUIDataTableBodyRow: { + styleOverrides: { + root: { + cursor: 'pointer', // Change cursor to pointer for clickable rows + }, }, }, }, - }) - } + }); + }; + const updateStatusOnServer = async (id, status) => { + try { + await EditStatus({ id, status }); + } catch (error) { + console.error('Error updating status:', error); + } + }; + + const updateTaskOnServer = async (id, avettaTask) => { + try { + await EditAvettaTask({ id, avettaTask }); + } catch (error) { + console.error('Error updating Avetta Task:', error); + } + }; + + const handleRowClick = (rowData, rowMeta) => { + const index = rowMeta.dataIndex; + const selectedItem = items[index]; // Access the original items array + onRowClickViewOnly({ open: true, selectedItem, viewOnly:true }); // Pass the selected item + }; const columns = [ { name: "id", - label: "id", + label: "ID", options: { display: false, filter: false, sort: false, - viewColumns:false, - } + viewColumns: false, + }, }, { name: "workerOrderNumber", @@ -70,7 +105,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: false, sort: true, - } + }, }, { name: "workerOrderTitle", @@ -79,7 +114,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: false, sort: true, - } + }, }, { name: "assignToUserName", @@ -88,7 +123,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: true, sort: false, - } + }, }, { name: "priority", @@ -97,7 +132,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: true, sort: false, - } + }, }, { name: "status", @@ -106,7 +141,58 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: true, sort: false, - } + customBodyRender: (value, tableMeta, updateValue) => { + return ( + + ); + }, + }, + }, + { + name: "avettaTask", + label: "Avetta Task", // New column + options: { + display: true, + filter: true, + sort: false, + customBodyRender: (value, tableMeta, updateValue) => { + return ( + + ); + }, + }, }, { name: "formattedDueDate", @@ -115,7 +201,16 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen display: true, filter: true, sort: false, - } + }, + }, + { + name: "formattedAssignDate", + label: "AssignDate", + options: { + display: true, + filter: true, + sort: false, + }, }, { name: "", @@ -124,7 +219,7 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen filter: false, sort: false, empty: true, - customBodyRender: (value, tableMeta, updateValue) => { + customBodyRender: (value, tableMeta) => { return ( <> { e.stopPropagation(); - const id = tableMeta.rowData[0]; - const _selectedItem = tableMeta.tableData - .find(obj => obj.id == id); - onEditClick({ open: true, selectedItem: _selectedItem }); + const rowIndex = tableMeta.rowIndex; // Get the index of the row + const selectedItem = items[rowIndex]; // Access the original items array + onEditClick({ open: true, selectedItem }); // Pass the selected item }} > - { - e.stopPropagation(); - const id = tableMeta.rowData[0]; - const _selectedItem = tableMeta.tableData - .find(obj => obj.id == id); - onDeleteClick({ open: true, selectedItem: _selectedItem }); - }} - > - - { e.stopPropagation(); - const id = tableMeta.rowData[0]; - const _selectedItem = tableMeta.tableData - .find(obj => obj.id == id); - onOpenNoteClick({ open: true, selectedItem: _selectedItem }); + const rowIndex = tableMeta.rowIndex; // Get the index of the row + const selectedItem = items[rowIndex]; // Access the original items array + onOpenNoteClick({ open: true, selectedItem }); // Pass the selected item }} > - + { e.stopPropagation(); - const id = tableMeta.rowData[0]; - const _selectedItem = tableMeta.tableData - .find(obj => obj.id == id); - onOpenAttachmentsClick({ open: true, selectedItem: _selectedItem }); + const rowIndex = tableMeta.rowIndex; // Get the index of the row + const selectedItem = items[rowIndex]; // Access the original items array + onOpenAttachmentsClick({ open: true, selectedItem }); // Pass the selected item }} > - + + + { + e.stopPropagation(); + const rowIndex = tableMeta.rowIndex; // Get the index of the row + const selectedItem = items[rowIndex]; // Access the original items array + onDeleteClick({ open: true, selectedItem }); // Pass the selected item + }} + > + ); @@ -190,16 +281,13 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen } ]; - const handleRowClick = (rowData, rowMeta) => { - console.log(rowData, rowMeta); - }; - const options = { filterType: "checkbox", rowsPerPage: 50, - rowsPerPageOptions: [50, 100, 200], + rowsPerPageOptions: [50, 100, 200], jumpToPage: true, onRowClick: handleRowClick, + resizableColumns: true, // Enables column resizing }; return ( @@ -212,6 +300,6 @@ const TableItems = ({ items, onEditClick, onDeleteClick, onOpenNoteClick, onOpen /> ); -} +}; -export default React.memo(TableItems); +export default React.memo(TableItems); \ No newline at end of file diff --git a/src/pages/workorder/edit/index.js b/src/pages/workorder/edit/index.js index 368947e..9b62b9f 100644 --- a/src/pages/workorder/edit/index.js +++ b/src/pages/workorder/edit/index.js @@ -3,7 +3,7 @@ import Form from "../components/Form"; import { EDIT } from "../../../constants"; import { editItems } from "./api"; -const EditItemModal = ({ item, open, setOpen, isEdit, setApiStatus }) => { +const EditItemModal = ({ item, open, setOpen, isEdit, setApiStatus, viewOnly = false }) => { return ( isEdit && open && (
{ mode={EDIT} apiCall={editItems} setApiStatus={setApiStatus} + viewOnly = {viewOnly} /> ) ); diff --git a/src/pages/workorder/list/index.js b/src/pages/workorder/list/index.js index 8284001..9dccb74 100644 --- a/src/pages/workorder/list/index.js +++ b/src/pages/workorder/list/index.js @@ -23,6 +23,11 @@ const List = () => { selectedItem: {}, open: false, }); + const [viewOnlyopen, setViewOnlyopen] = React.useState({ + selectedItem: {}, + open: false, + viewOnly:false, + }); const [noteHistoryModalopen, setNoteHistoryModalopen] = React.useState({ selectedItem: {}, open: false, @@ -80,6 +85,7 @@ const List = () => { onOpenNoteClick = {setNoteHistoryModalopen} onOpenAttachmentsClick = {setAttachmentsModalopen} isEmpty={isEmptyList} + onRowClickViewOnly = {setViewOnlyopen} /> { setApiStatus={setApiStatus} /> + setViewOnlyopen({viewOnly:false})} + isEdit={viewOnlyopen.viewOnly} + setApiStatus={setApiStatus} + viewOnly={viewOnlyopen.viewOnly} + /> { const [note, setNote] = useState(''); const [noteHistory, setNoteHistory] = useState([]); const [comments, setComments] = useState([]); + const [loaded, setLoaded] = useState(false); const handleSubmit = async () => { if (note.trim()) { await addComments({id: item.id , Comments: [...noteHistory, note]}); - setNoteHistory([]); - setNote(''); - setOpen(false); + setLoaded(true); } }; @@ -42,7 +41,7 @@ const NoteHistoryDrawer = ({ item, open, setOpen, setApiStatus }) => { setComments(_comments); } } - }, [item]) + }, [item,loaded]) return (