Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux';
import { Button, ButtonGroup, Table } from 'reactstrap';
import { Button, Table, UncontrolledTooltip } from 'reactstrap';
import Select from 'react-select';

import { fetchBMProjects } from '~/actions/bmdashboard/projectActions';
Expand All @@ -11,6 +11,8 @@
import { getHeaderData } from '~/actions/authActions';
import { getUserProfile } from '~/actions/userProfile';

import styles from './EDailyActivityLog.module.css';

const TODAY = new Date().toISOString().split('T')[0];

const buildToolNumbers = (name = 'EQ', qty = 0) => {
Expand Down Expand Up @@ -54,34 +56,93 @@
};
});

const getSelectStyles = (darkMode, isTableSelect = false) => ({
container: base => ({
...base,
width: isTableSelect ? 300 : '100%',
minWidth: isTableSelect ? 300 : 'auto',
maxWidth: isTableSelect ? 300 : 'none',
}),
control: base => ({
...base,

backgroundColor: darkMode ? '#2a3f5f' : '#fff',
borderColor: darkMode ? '#3a506b' : '#ced4da',
color: darkMode ? '#e0e0e0' : '#000',
}),
singleValue: base => ({
...base,
color: darkMode ? '#e0e0e0' : '#000',
}),
input: base => ({
...base,
color: darkMode ? '#e0e0e0' : '#000',
}),
menu: base => ({
...base,
backgroundColor: darkMode ? '#2a3f5f' : '#fff',
zIndex: 9999,
}),
option: (base, state) => ({
...base,

backgroundColor: state.isFocused
? darkMode
? '#3a506b'
: '#e9ecef'

Check warning on line 92 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUl&open=AZryor2Q3DlPyLSGeLUl&pullRequest=4515
: darkMode
? '#2a3f5f'
: '#fff',

Check warning on line 95 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUm&open=AZryor2Q3DlPyLSGeLUm&pullRequest=4515
color: darkMode ? '#e0e0e0' : '#000',
cursor: 'pointer',
}),
placeholder: base => ({
...base,
color: darkMode ? '#e0e0e0' : '#6c757d',
opacity: 0.7,
}),
multiValue: base => ({
...base,
backgroundColor: darkMode ? '#3a506b' : '#e9ecef',
}),
multiValueLabel: base => ({
...base,
color: darkMode ? '#e0e0e0' : '#000',
}),
multiValueRemove: base => ({
...base,
color: darkMode ? '#e0e0e0' : '#000',
':hover': {
backgroundColor: 'red',
color: 'white',
},
}),
});

function EDailyActivityLog(props) {
const dispatch = useDispatch();

/* redux slices */
const bmProjects = useSelector(s => s.bmProjects || []);
const equipments = useSelector(s => s.bmEquipments?.equipmentslist || []);
const darkMode = useSelector(state => state.theme.darkMode);

const { user } = props.auth;

/* local state */
const [selectedProject, setSelectedProject] = useState(null);
const [date, setDate] = useState(TODAY);
const [logType, setLogType] = useState('check-in'); // 'check-in' | 'check-out'
const [logType, setLogType] = useState('check-in');
const [rows, setRows] = useState([]);

useEffect(() => {
dispatch(fetchBMProjects());
}, [dispatch]);

/* fetch equipments whenever project changes */
useEffect(() => {
if (selectedProject?.value) {
dispatch(fetchAllEquipments(selectedProject.value));
}
}, [selectedProject, dispatch]);

/* build rows whenever equipments slice updates */
const derived = useMemo(() => buildRows(equipments), [equipments]);
useEffect(() => setRows(derived), [derived]);

Expand Down Expand Up @@ -137,16 +198,16 @@
dispatch(updateMultipleEquipmentLogs(selectedProject.value, payload));
};

const projectSelectStyles = getSelectStyles(darkMode, false);
const tableSelectStyles = getSelectStyles(darkMode, true);

return (
<div
className={`container-fluid ${darkMode ? 'bg-oxford-blue text-light' : ''}`}
style={{ height: '100%' }}
>
<div className={`container-fluid ${styles.mainContainer} ${darkMode ? styles.darkMode : ''}`}>
<div className="container">
<h4 className="mb-4">Daily Equipment Log</h4>
<h4 className="mb-4 pt-3">Daily Equipment Log</h4>

{/* header */}
<div className="row mb-3">
{/* Header Row */}
<div className="row mb-3 align-items-end">
<div className="col-md-3">
<label className="form-label fw-bold" htmlFor="date">
Date
Expand All @@ -165,62 +226,86 @@
Project
</label>
<Select
inputId="project-select" // associate label via inputId for react-select
inputId="project-select"
value={selectedProject}
onChange={setSelectedProject}
options={bmProjects.map(p => ({ label: p.name, value: p._id }))}
placeholder="Select project…"
isClearable
styles={{ maxWidth: '150px' }}
styles={projectSelectStyles}
/>
</div>

<div className="col-md-4">
<p className="form-label fw-bold" id="log-type-label">
<div className="col-md-3">
<div className="form-label font-weight-bold mb-2" id="log-type-label">
Log Type
</p>
<ButtonGroup className="d-block" aria-labelledby="log-type-label">
</div>

<div className="d-flex" role="group" aria-labelledby="log-type-label">

Check warning on line 244 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use <details>, <fieldset>, <optgroup>, or <address> instead of the "group" role to ensure accessibility across all devices.

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUn&open=AZryor2Q3DlPyLSGeLUn&pullRequest=4515
<Button
color={logType === 'check-in' ? 'primary' : 'secondary'}
onClick={() => flipLogType('check-in')}
className={styles.checkInBtn}
>
Check In
</Button>
<Button
color={logType === 'check-out' ? 'primary' : 'secondary'}
onClick={() => flipLogType('check-out')}
className={styles.checkOutBtn}
>
Check Out
</Button>
</ButtonGroup>
</div>
</div>
</div>

{/* table */}
{/* Table */}
<Table bordered responsive>
<thead className={`${darkMode ? 'table-dark' : 'table-light'} align-middle`}>
<tr className={`${darkMode ? 'text-light' : 'text-dark'} `}>
<thead className={`${darkMode ? styles.tableDark : 'table-light'} align-middle`}>
<tr>
<th>Name</th>
<th>Working</th>
<th>Available</th>
<th>Using</th>
<th>Tool / Equipment&nbsp;#</th>
<th>
Working
<i className={`fa fa-info-circle ${styles.infoIcon}`} id="tooltip-working"></i>

Check warning on line 270 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Ambiguous spacing before next element i

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUo&open=AZryor2Q3DlPyLSGeLUo&pullRequest=4515
<UncontrolledTooltip placement="top" target="tooltip-working">
Total number of units operational today
</UncontrolledTooltip>
</th>
<th>
Available
<i className={`fa fa-info-circle ${styles.infoIcon}`} id="tooltip-available"></i>

Check warning on line 277 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Ambiguous spacing before next element i

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUp&open=AZryor2Q3DlPyLSGeLUp&pullRequest=4515
<UncontrolledTooltip placement="top" target="tooltip-available">
Number of units currently not in use
</UncontrolledTooltip>
</th>
<th>
Using
<i className={`fa fa-info-circle ${styles.infoIcon}`} id="tooltip-using"></i>

Check warning on line 284 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Ambiguous spacing before next element i

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUq&open=AZryor2Q3DlPyLSGeLUq&pullRequest=4515
<UncontrolledTooltip placement="top" target="tooltip-using">
Quantity being checked in/out
</UncontrolledTooltip>
</th>
<th>
Tool / Equipment #
<i className={`fa fa-info-circle ${styles.infoIcon}`} id="tooltip-toolnum"></i>

Check warning on line 291 in src/components/BMDashboard/Equipment/DailyActivityLog/EDailyActivityLog.jsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Ambiguous spacing before next element i

See more on https://sonarcloud.io/project/issues?id=OneCommunityGlobal_HighestGoodNetworkApp&issues=AZryor2Q3DlPyLSGeLUr&open=AZryor2Q3DlPyLSGeLUr&pullRequest=4515
<UncontrolledTooltip placement="top" target="tooltip-toolnum">
Select the specific tool identifier
</UncontrolledTooltip>
</th>
</tr>
</thead>
<tbody>
{!selectedProject && (
<tr>
<td
colSpan={5}
className={`text-center py-3 ${darkMode ? 'text-light' : 'text-dark'} `}
>
<td colSpan={5} className={`text-center py-3 ${darkMode ? styles.darkMode : ''}`}>
Select a project to load equipments.
</td>
</tr>
)}

{selectedProject && rows.length === 0 && (
<tr className={`${darkMode ? 'text-light' : 'text-dark'} `}>
<tr className={`${darkMode ? styles.darkMode : ''}`}>
<td colSpan={5} className="text-center py-3">
No equipments found for this project.
</td>
Expand All @@ -234,7 +319,7 @@
const limit = logType === 'check-in' ? r.availableQty : r.usingQty;

return (
<tr key={r.id} className={`${darkMode ? 'text-light' : 'text-dark'} `}>
<tr key={r.id} className={`${darkMode ? styles.darkMode : ''}`}>
<td>{r.name}</td>
<td>{r.workingQty}</td>
<td>{r.availableQty}</td>
Expand All @@ -248,61 +333,7 @@
onChange={sel => onToolSelect(idx, sel)}
placeholder={`Pick up to ${limit}…`}
menuPortalTarget={document.body}
styles={{
container: base => ({
...base,
width: 300, // lock it to 300px
minWidth: 300,
maxWidth: 300,
}),
control: base => ({
...base,
width: '100%', // fill the container
overflow: 'hidden',
whiteSpace: 'nowrap',
}),
placeholder: base => ({
...base,
color: '#000',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}),
singleValue: base => ({
...base,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}),
multiValue: base => ({
...base,
maxWidth: '60%',
overflow: 'hidden',
}),
multiValueLabel: base => ({
...base,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}),
indicatorsContainer: base => ({
...base,
flexWrap: 'nowrap',
}),
menu: base => ({
...base,
width: 300,
minWidth: 300,
maxWidth: 300,
zIndex: 9999,
}),
option: (base, state) => ({
...base,
color: '#000',
backgroundColor: state.isFocused ? '#f0f0f0' : '#fff',
}),
menuPortal: base => ({ ...base, zIndex: 9999 }),
}}
styles={tableSelectStyles}
/>
</td>
</tr>
Expand All @@ -311,8 +342,7 @@
</tbody>
</Table>

{/* actions */}
<div className="d-flex justify-content-end gap-2">
<div className={styles.actionContainer}>
<Button color="secondary" onClick={handleCancel}>
Cancel
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.mainContainer {
height: 100%;
min-height: 100vh;
padding-bottom: 2rem;
}

.darkMode {
background-color: #1e293b;
color: #f8f9fa;
}

.tableDark th {
background-color: #0f172a;
color: #fff;
border-color: #334155;
}

.tableDark td {
background-color: #1e293b;
color: #e2e8f0;
border-color: #334155;
}

.infoIcon {
cursor: pointer;
opacity: 0.7;
margin-left: 0.5rem;
}

.actionContainer {
display: flex;
justify-content: flex-end;
gap: 1rem;
margin-top: 1.5rem;
}

.checkInBtn {
margin-right: 15px !important;
width: 50%;
}

.checkOutBtn {
width: 50%;
}
Loading