diff --git a/src/components/BMDashboard/ConsumableList/ConsumableListView.jsx b/src/components/BMDashboard/ConsumableList/ConsumableListView.jsx index 230a12ccb4..438b256240 100644 --- a/src/components/BMDashboard/ConsumableList/ConsumableListView.jsx +++ b/src/components/BMDashboard/ConsumableList/ConsumableListView.jsx @@ -3,6 +3,8 @@ import { useDispatch, useSelector } from 'react-redux'; import { fetchAllConsumables } from '../../../actions/bmdashboard/consumableActions'; import ItemListView from '../ItemList/ItemListView'; import UpdateConsumableModal from '../UpdateConsumables/UpdateConsumableModal'; +import { Link } from 'react-router-dom'; +import styles from '../InventoryTypesList/TypesList.module.css'; function ConsumableListView() { const dispatch = useDispatch(); @@ -50,13 +52,19 @@ function ConsumableListView() { ]; return ( - + <> + + All Inventory Types + + + + ); } diff --git a/src/components/BMDashboard/Equipment/List/EquipmentList.jsx b/src/components/BMDashboard/Equipment/List/EquipmentList.jsx index fd4f7fbd32..a591890eea 100644 --- a/src/components/BMDashboard/Equipment/List/EquipmentList.jsx +++ b/src/components/BMDashboard/Equipment/List/EquipmentList.jsx @@ -3,6 +3,8 @@ import useTheme from '../../../../hooks/useTheme'; import EquipmentsTable from './EquipmentsTable'; import EquipmentsInputs from './EquipmentsInputs'; import styles from './Equipments.module.css'; +import { Link } from 'react-router-dom'; +import stylesList from '../../InventoryTypesList/TypesList.module.css'; function EquipmentList() { const [equipment, setEquipment] = useState({ label: 'All Equipments', value: '0' }); @@ -12,25 +14,30 @@ function EquipmentList() { useTheme(); return ( -
-
-
-
EQUIPMENTS
- - + <> + + All Inventory Types + +
+
+
+
EQUIPMENTS
+ + +
-
+ ); } diff --git a/src/components/BMDashboard/InventoryTypesList/InventoryTypesList.jsx b/src/components/BMDashboard/InventoryTypesList/InventoryTypesList.jsx index bc1bc415e2..56ab32c39b 100644 --- a/src/components/BMDashboard/InventoryTypesList/InventoryTypesList.jsx +++ b/src/components/BMDashboard/InventoryTypesList/InventoryTypesList.jsx @@ -1,31 +1,25 @@ import { useState, useEffect } from 'react'; import { connect } from 'react-redux'; -import { useHistory } from 'react-router-dom'; - +import { Link } from 'react-router-dom'; import { fetchInvTypeByType } from '~/actions/bmdashboard/invTypeActions'; import { fetchInvUnits } from '~/actions/bmdashboard/invUnitActions'; -import { Accordion, Card, Button } from 'react-bootstrap'; -import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; - +import { Accordion, Card } from 'react-bootstrap'; import BMError from '../shared/BMError'; -import TypesTable from './TypesTable'; import UnitsTable from './invUnitsTable'; import AccordionToggle from './AccordionToggle'; import styles from './TypesList.module.css'; +const categories = [ + { label: 'Materials', route: '/bmdashboard/materials' }, + { label: 'Consumables', route: '/bmdashboard/consumables' }, + { label: 'Equipments', route: '/bmdashboard/equipment' }, + { label: 'Reusables', route: '/bmdashboard/reusables' }, + { label: 'Tools', route: '/bmdashboard/tools' }, +]; + export function InventoryTypesList(props) { const { invUnits, errors, dispatch } = props; - const history = useHistory(); - - const categories = ['Materials', 'Consumables', 'Equipments', 'Reusables', 'Tools']; - const [isError, setIsError] = useState(false); - const [currentTime, setCurrentTime] = useState(new Date()); - - const handleBack = () => { - history.goBack(); - }; useEffect(() => { dispatch(fetchInvTypeByType('Materials')); @@ -50,52 +44,38 @@ export function InventoryTypesList(props) { } return ( -
-

All Inventory Types

- -
- Time: - setCurrentTime(date)} - dateFormat="MM-dd-yyyy hh:mm:ss" - id="timestamp" - showTimeInput - /> +
+ {/* Page Header */} +
+

All Inventory Types

+

Select a category to view and manage inventory

- - {categories?.map((category, index) => { - return ( - - - {category} - - - - - - - - ); - })} - - - - Unit of Measurement - - - - - - - - + {/* Category Cards Grid */} +
+ {categories.map(({ label, route }) => ( + + {label} +
+ + ))} +
-
- + {/* Unit of Measurement */} +
+

Unit of Measurement

+ + + + View all units + + + + + + + +
); diff --git a/src/components/BMDashboard/InventoryTypesList/TypesList.module.css b/src/components/BMDashboard/InventoryTypesList/TypesList.module.css index 476ebde5c4..5f5449aeef 100644 --- a/src/components/BMDashboard/InventoryTypesList/TypesList.module.css +++ b/src/components/BMDashboard/InventoryTypesList/TypesList.module.css @@ -1,15 +1,17 @@ +:root { + --color-h50: #e8f4f9; + --color-h100: #78bdda; + --color-h500: #0d5675; + --color-n0: #fff; + --color-text: #1c8bcc; + --font-clickable: roboto; +} + .typesListContainer { width: 100%; max-width: 1080px; margin: 1rem auto; padding: 0 1rem; - - --color-h50: #e8f4f9; - --color-h100: #78bdda; - --color-h500: #0d5675; - --color-n0: #ffffff; - --color-text: #1c8bcc; - --font-clickable: Roboto; } /* Dark mode support */ @@ -96,7 +98,7 @@ } .tableHeader { - border-bottom: 1px solid rgba(0, 0, 0, 0.125); + border-bottom: 1px solid rgb(0 0 0 / 12.5%); } :global(.dark-mode) .tableHeader, @@ -258,16 +260,86 @@ font-size: 10px; } -/* Dark mode table styling */ -:global(.dark-mode) .typesListContainer table, -:global(.bm-dashboard-dark) .typesListContainer table { - color: #ffffff; +/* ---- Page Header ---- */ +.pageHeader { + margin-bottom: 28px; + padding-bottom: 16px; + border-bottom: 2px solid var(--color-h50); } -:global(.dark-mode) .typesListContainer table tbody tr, -:global(.bm-dashboard-dark) .typesListContainer table tbody tr { - background-color: #2a2a2a; - color: #ffffff; +.pageTitle { + font-size: 2rem; + font-weight: 700; + color: var(--color-h500); + margin: 0 0 6px; +} + +.pageSubtitle { + font-size: 14px; + color: #6c757d; + margin: 0; +} + +/* ---- Category Cards Grid ---- */ +.categoryGrid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 16px; + margin-bottom: 36px; +} + +.categoryCard { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px 24px; + background-color: var(--color-n0); + border: 1.5px solid var(--color-h50); + border-radius: 12px; + text-decoration: none !important; + color: inherit !important; + transition: all 0.2s ease; + box-shadow: 0 1px 4px rgb(0 0 0 / 6%); +} + +.categoryCardLabel { + font-size: 16px; + font-weight: 700; + color: var(--color-h500); +} + +.categoryCardArrow { + font-size: 22px; + color: var(--color-h100); + font-weight: 300; + flex-shrink: 0; +} + +/* ---- Unit Section ---- */ +.unitSection { + margin-top: 8px; +} + +.unitSectionTitle { + font-size: 1.1rem; + font-weight: 600; + color: var(--color-h500); + margin-bottom: 12px; +} + +.unitCard { + border: 1.5px solid var(--color-h50) !important; + border-radius: 10px !important; + overflow: hidden; +} + +/* Main container dark mode */ +:global(.bm-dashboard-dark) .typesListContainer { + color: #fff; +} + +:global(.bm-dashboard-dark) .typesListContainer h1 { + color: #fff !important; } :global(.dark-mode) .typesListContainer table tbody tr:hover, @@ -319,19 +391,17 @@ :global(.dark-mode) .timestampContainer, :global(.bm-dashboard-dark) .timestampContainer { - color: #ffffff; + color: #fff; } :global(.bm-dashboard-dark) .timestampContainer span { - color: #ffffff !important; + color: #fff !important; } -/* Dark mode react-datepicker styling */ -:global(.dark-mode) .timestampContainer :global(.react-datepicker-wrapper) input, -:global(.bm-dashboard-dark) .timestampContainer :global(.react-datepicker-wrapper) input { - background-color: #3a3a3a !important; - color: #ffffff !important; - border-color: rgba(255, 255, 255, 0.2) !important; +:global(.bm-dashboard-dark) #timestamp { + background-color: #2e5061 !important; + color: #fff !important; + border-color: #3a506b !important; } :global(.dark-mode) :global(.react-datepicker), @@ -414,7 +484,7 @@ /* Dark mode card header - Bootstrap override */ :global(.bm-dashboard-dark) .cardHeader { background-color: #2e5061 !important; - color: #ffffff !important; + color: #fff !important; border-color: #3a506b !important; } @@ -425,7 +495,7 @@ /* Accordion collapse body dark mode */ :global(.bm-dashboard-dark) .accordionCollapse { background-color: #1c2541 !important; - color: #ffffff !important; + color: #fff !important; scrollbar-width: thin; scrollbar-color: #3a506b #1c2541; } @@ -457,13 +527,13 @@ } :global(.bm-dashboard-dark) .tableHeader th { - color: #ffffff !important; + color: #fff !important; background-color: #1c2541 !important; } /* Table dark mode (bm-dashboard specific) */ :global(.bm-dashboard-dark) .typesListContainer :global(table) { - color: #ffffff !important; + color: #fff !important; background-color: #1c2541 !important; } @@ -472,7 +542,7 @@ } :global(.bm-dashboard-dark) .typesListContainer :global(table) :global(thead) th { - color: #ffffff !important; + color: #fff !important; background-color: #1c2541 !important; border-color: #3a506b !important; } @@ -482,7 +552,7 @@ } :global(.bm-dashboard-dark) .typesListContainer :global(table) td { - color: #ffffff !important; + color: #fff !important; background-color: transparent !important; } @@ -497,20 +567,20 @@ /* Card header - Bootstrap override (bm-dashboard specific) */ :global(.bm-dashboard-dark) .typesListContainer :global(.card-header) { background-color: #2e5061 !important; - color: #ffffff !important; + color: #fff !important; border-color: #3a506b !important; } /* Card body - Bootstrap override (bm-dashboard specific) */ :global(.bm-dashboard-dark) .typesListContainer :global(.card-body) { background-color: #1c2541 !important; - color: #ffffff !important; + color: #fff !important; } /* Buttons dark mode (bm-dashboard specific) */ :global(.bm-dashboard-dark) .btnTypes { background-color: #3a506b !important; - color: #ffffff !important; + color: #fff !important; border-color: #5a7a9b !important; } @@ -522,7 +592,7 @@ /* Back button dark mode */ :global(.bm-dashboard-dark) .buttonContainer a { background-color: #2e5061 !important; - color: #ffffff !important; + color: #fff !important; } :global(.bm-dashboard-dark) .buttonContainer a:hover { @@ -532,7 +602,7 @@ /* Input measurement dark mode */ :global(.bm-dashboard-dark) #input-measurement { background-color: #2e5061 !important; - color: #ffffff !important; + color: #fff !important; border-color: #3a506b !important; } @@ -543,7 +613,7 @@ /* All inputs in the container */ :global(.bm-dashboard-dark) .typesListContainer input { background-color: #2e5061 !important; - color: #ffffff !important; + color: #fff !important; border-color: #3a506b !important; } @@ -554,15 +624,21 @@ :global(.bm-dashboard-dark) .typesListContainer input:focus { background-color: #3a506b !important; border-color: #5a7a9b !important; - box-shadow: 0 0 0 0.2rem rgba(106, 241, 234, 0.25) !important; + box-shadow: 0 0 0 0.2rem rgb(106 241 234 / 25%) !important; +} + +:global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker-time__input) input { + background-color: #1c2541 !important; + color: #fff !important; + border-color: #3a506b !important; } /* Autocomplete styling */ :global(.bm-dashboard-dark) .typesListContainer input:-webkit-autofill, :global(.bm-dashboard-dark) .typesListContainer input:-webkit-autofill:hover, :global(.bm-dashboard-dark) .typesListContainer input:-webkit-autofill:focus { - -webkit-box-shadow: 0 0 0 30px #2e5061 inset !important; - -webkit-text-fill-color: #ffffff !important; + box-shadow: 0 0 0 30px #2e5061 inset !important; + -webkit-text-fill-color: #fff !important; } /* Bootstrap Card dark mode */ @@ -585,7 +661,7 @@ :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__current-month), :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__day-name), :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__day) { - color: #ffffff !important; + color: #fff !important; } :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__day:hover) { @@ -606,7 +682,7 @@ } :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__time-list-item) { - color: #ffffff !important; + color: #fff !important; } :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__time-list-item:hover) { @@ -614,11 +690,114 @@ } :global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker__input-time-container) { - color: #ffffff !important; + color: #fff !important; } -:global(.bm-dashboard-dark) .typesListContainer :global(.react-datepicker-time__input) input { +/* ---- New page element dark mode (before hover rules) ---- */ +:global(.bm-dashboard-dark) .pageTitle { + color: #fff !important; +} + +:global(.bm-dashboard-dark) .pageSubtitle { + color: #b5bac5 !important; +} + +:global(.bm-dashboard-dark) .pageHeader { + border-color: #3a506b !important; +} + +:global(.bm-dashboard-dark) .categoryCard { background-color: #1c2541 !important; - color: #ffffff !important; border-color: #3a506b !important; + color: #fff !important; +} + +:global(.bm-dashboard-dark) .categoryCardLabel { + color: #fff !important; +} + +:global(.bm-dashboard-dark) .categoryCardArrow { + color: #6af1ea !important; +} + +:global(.bm-dashboard-dark) .unitSectionTitle { + color: #fff !important; +} + +:global(.bm-dashboard-dark) .unitCard { + border-color: #3a506b !important; +} + +/* ---- Hover rules AFTER dark mode overrides ---- */ +.categoryCard:hover { + border-color: var(--color-h100); + box-shadow: 0 4px 12px rgb(13 86 117 / 12%); + transform: translateY(-2px); + text-decoration: none !important; +} + +:global(.bm-dashboard-dark) .categoryCard:hover { + border-color: #5a7a9b !important; + box-shadow: 0 4px 12px rgb(0 0 0 / 30%) !important; +} + +/* ---- Back link ---- */ +.backLink { + display: inline-flex; + align-items: center; + gap: 6px; + margin-bottom: 20px; + padding: 8px 16px; + background-color: #e8f4f9; + color: #0d5675 !important; + text-decoration: none !important; + font-size: 14px; + font-weight: 600; + border-radius: 25px; + border: 1.5px solid #78bdda; + transition: all 0.2s ease; +} + +.backLink::before { + content: ''; + display: inline-block; + width: 8px; + height: 8px; + border-left: 2px solid #0d5675; + border-bottom: 2px solid #0d5675; + transform: rotate(45deg); + transition: border-color 0.2s ease; + margin-right: 2px; +} + +.backLink:hover { + background-color: #0d5675; + color: #fff !important; + border-color: #0d5675; + text-decoration: none !important; + transform: translateX(-2px); +} + +.backLink:hover::before { + border-color: #fff; +} + +:global(.bm-dashboard-dark) .backLink { + background-color: #1c2541 !important; + color: #6af1ea !important; + border-color: #3a506b !important; +} + +:global(.bm-dashboard-dark) .backLink::before { + border-color: #6af1ea !important; +} + +:global(.bm-dashboard-dark) .backLink:hover { + background-color: #2e5061 !important; + color: #fff !important; + border-color: #5a7a9b !important; +} + +:global(.bm-dashboard-dark) .backLink:hover::before { + border-color: #fff !important; } diff --git a/src/components/BMDashboard/MaterialList/MaterialListView.jsx b/src/components/BMDashboard/MaterialList/MaterialListView.jsx index 4b6baa5edb..c005ab663d 100644 --- a/src/components/BMDashboard/MaterialList/MaterialListView.jsx +++ b/src/components/BMDashboard/MaterialList/MaterialListView.jsx @@ -12,6 +12,8 @@ import { import { fetchAllMaterials, resetMaterialUpdate } from '~/actions/bmdashboard/materialsActions'; import ItemListView from '../ItemList/ItemListView'; import UpdateMaterialModal from '../UpdateMaterials/UpdateMaterialModal'; +import { Link } from 'react-router-dom'; +import styles from '../InventoryTypesList/TypesList.module.css'; function MaterialListView() { const dispatch = useDispatch(); @@ -82,42 +84,47 @@ function MaterialListView() { ]; return ( - - - - - - - setSearchTerm(e.target.value)} - /> - {searchTerm && ( - - - - )} - - - + type="text" + placeholder="Search Material, PID, Unit..." + value={searchTerm} + onChange={e => setSearchTerm(e.target.value)} + /> + {searchTerm && ( + + + + )} + + + + ); } diff --git a/src/components/BMDashboard/ReusableList/ReusableListView.jsx b/src/components/BMDashboard/ReusableList/ReusableListView.jsx index 01ee88ff08..37fea5b56e 100644 --- a/src/components/BMDashboard/ReusableList/ReusableListView.jsx +++ b/src/components/BMDashboard/ReusableList/ReusableListView.jsx @@ -3,6 +3,8 @@ import { useDispatch, useSelector } from 'react-redux'; import { fetchAllReusables } from '~/actions/bmdashboard/reusableActions'; import ItemListView from '../ItemList/ItemListView'; import UpdateReusableModal from '../UpdateReusables/UpdateReusableModal'; +import { Link } from 'react-router-dom'; +import styles from '../InventoryTypesList/TypesList.module.css'; function ReusableListView() { const dispatch = useDispatch(); @@ -44,13 +46,18 @@ function ReusableListView() { ]; return ( - + <> + + All Inventory Types + + + ); } diff --git a/src/components/BMDashboard/Tools/ToolsList.jsx b/src/components/BMDashboard/Tools/ToolsList.jsx index 66d1889946..bda4e26e5a 100644 --- a/src/components/BMDashboard/Tools/ToolsList.jsx +++ b/src/components/BMDashboard/Tools/ToolsList.jsx @@ -3,6 +3,8 @@ import { useDispatch, useSelector } from 'react-redux'; import { fetchTools } from '../../../actions/bmdashboard/toolActions'; import ToolItemListView from '../ToolItemList/ToolItemListView'; import UpdateToolModal from '../UpdateTools/UpdateToolModal'; +import { Link } from 'react-router-dom'; +import styles from '../InventoryTypesList/TypesList.module.css'; function ToolsList() { const dispatch = useDispatch(); @@ -47,13 +49,18 @@ function ToolsList() { ]; return ( - + <> + + All Inventory Types + + + ); } diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx index 9a171d540e..98af8396f2 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.jsx @@ -53,6 +53,7 @@ import { ACTUAL_COST_BREAKDOWN, BLUE_SQUARE_EMAIL_MANAGEMENT, JOB_ANALYTICS_REPORT, + BM_DASHBOARD } from '../../languages/en/ui'; import Logout from '../Logout/Logout'; import '../../App.module.css'; @@ -403,6 +404,9 @@ export function Header(props) { if (location.pathname === '/login') return null; const viewingUser = JSON.parse(window.sessionStorage.getItem('viewingUser')); + + const showBMDashboard = location.pathname.startsWith('/bmdashboard'); + return (
@@ -488,6 +492,13 @@ export function Header(props) { {DASHBOARD} + + {showBMDashboard && ( + + {BM_DASHBOARD} + + + )} @@ -506,6 +517,9 @@ export function Header(props) { }`} disabled={headerDisabled} > + + All Inventory Types + Add Material