Skip to content

Commit 59b8f79

Browse files
committed
#4107 simplified price/quanity + proper loading
1 parent 02c269c commit 59b8f79

3 files changed

Lines changed: 40 additions & 27 deletions

File tree

src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTable.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ const BOMTable: React.FC<BOMTableProps> = ({
7070
assembly.materials.reduce(addMaterialCosts, 0)
7171
)} ${arrowSymbol(assembly.assemblyId)}`,
7272
pdmFileName: '',
73-
quantity: '',
74-
price: '',
73+
quantity: undefined,
74+
price: undefined,
75+
unitName: undefined,
7576
subtotal: '',
7677
link: '',
7778
notes: '',

src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTableWrapper.tsx

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
useGetAllManufacturers,
1818
useGetAllMaterialTypes
1919
} from '../../../../hooks/bom.hooks';
20+
import ErrorPage from '../../../ErrorPage';
2021
import LoadingIndicator from '../../../../components/LoadingIndicator';
2122
import EditMaterialModal from './MaterialForm/EditMaterialModal';
2223
import { BomRow, bomBaseColDef } from '../../../../utils/bom.utils';
@@ -54,8 +55,18 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
5455
const { mutateAsync: deleteAssemblyMutateAsync, isLoading: deleteAssemblyIsLoading } = useDeleteAssembly(project.wbsNum);
5556
const { mutateAsync: assignMaterialToAssembly } = useAssignMaterialToAssembly();
5657
const { mutateAsync: editMaterial } = useEditMaterialById(project.wbsNum);
57-
const { data: materialTypes } = useGetAllMaterialTypes();
58-
const { data: manufacturers } = useGetAllManufacturers();
58+
const {
59+
data: materialTypes,
60+
isLoading: materialTypesIsLoading,
61+
isError: materialTypesIsError,
62+
error: materialTypesError
63+
} = useGetAllMaterialTypes();
64+
const {
65+
data: manufacturers,
66+
isLoading: manufacturersIsLoading,
67+
isError: manufacturersIsError,
68+
error: manufacturersError
69+
} = useGetAllManufacturers();
5970

6071
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
6172

@@ -85,7 +96,10 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
8596
}
8697
}, [setHideColumn]);
8798

88-
if (deleteMaterialIsLoading || deleteAssemblyIsLoading) return <LoadingIndicator />;
99+
if (deleteMaterialIsLoading || deleteAssemblyIsLoading || manufacturersIsLoading || materialTypesIsLoading)
100+
return <LoadingIndicator />;
101+
if (manufacturersIsError) return <ErrorPage message={manufacturersError?.message} />;
102+
if (materialTypesIsError) return <ErrorPage message={materialTypesError?.message} />;
89103

90104
const assignMaterial = (materialId: string, assemblyId?: string) => async () => {
91105
try {
@@ -134,8 +148,8 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
134148
const material = materials.find((m) => m.materialId === newRow.materialId);
135149
if (!material) return newRow;
136150

137-
const quantityChanged = newRow.quantityRaw !== oldRow.quantityRaw;
138-
const priceChanged = newRow.priceRaw !== oldRow.priceRaw;
151+
const quantityChanged = newRow.quantity !== oldRow.quantity;
152+
const priceChanged = newRow.price !== oldRow.price;
139153

140154
if (
141155
newRow.name === oldRow.name &&
@@ -152,11 +166,11 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
152166
toast.error('Name cannot be empty');
153167
return oldRow;
154168
}
155-
if (quantityChanged && newRow.quantityRaw !== undefined && (isNaN(newRow.quantityRaw) || newRow.quantityRaw <= 0)) {
169+
if (quantityChanged && newRow.quantity !== undefined && newRow.quantity <= 0) {
156170
toast.error('Quantity must be a positive number');
157171
return oldRow;
158172
}
159-
if (priceChanged && newRow.priceRaw !== undefined && (isNaN(newRow.priceRaw) || newRow.priceRaw < 0)) {
173+
if (priceChanged && newRow.price !== undefined && newRow.price < 0) {
160174
toast.error('Price must be a non-negative number');
161175
return oldRow;
162176
}
@@ -170,9 +184,8 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
170184
if (quantityChanged) changedFields.push('Quantity');
171185
if (priceChanged) changedFields.push('Price');
172186

173-
const priceInCents = priceChanged && newRow.priceRaw !== undefined ? Math.round(newRow.priceRaw * 100) : material.price;
174-
const quantityValue =
175-
quantityChanged && newRow.quantityRaw != null ? new Decimal(newRow.quantityRaw) : material.quantity;
187+
const priceInCents = priceChanged && newRow.price !== undefined ? Math.round(newRow.price * 100) : material.price;
188+
const quantityValue = quantityChanged && newRow.quantity != null ? new Decimal(newRow.quantity) : material.quantity;
176189

177190
try {
178191
await editMaterial({
@@ -195,9 +208,8 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
195208
toast.success(`Material ${changedFields.join(', ')} updated successfully`);
196209
return {
197210
...newRow,
198-
quantity: material.unitName ? `${quantityValue} ${material.unitName}` : `${quantityValue}`,
199-
price: priceInCents !== undefined ? `$${centsToDollar(priceInCents)}` : newRow.price,
200-
priceRaw: priceInCents !== undefined ? priceInCents / 100 : newRow.priceRaw
211+
quantity: Number(quantityValue),
212+
price: priceInCents !== undefined ? priceInCents / 100 : newRow.price
201213
};
202214
} catch (e: unknown) {
203215
if (e instanceof Error) toast.error(e.message, 6000);
@@ -483,22 +495,24 @@ const BOMTableWrapper: React.FC<BOMTableWrapperProps> = ({
483495
},
484496
{
485497
...bomBaseColDef,
486-
field: 'quantityRaw',
498+
field: 'quantity',
487499
headerName: 'Quantity',
488500
type: 'number',
489501
editable: editPerms,
490-
renderCell: (params) => params.row.quantity,
502+
renderCell: ({ value, row }) => (value != null ? (row.unitName ? `${value} ${row.unitName}` : `${value}`) : ''), // show unit (e.g. 5 kg) if available
503+
valueParser: (value) => (value == null || value === '' ? undefined : Number(value)), // convert back to number for editing
491504
sortable: false,
492505
filterable: false,
493506
hide: hideColumn[7]
494507
},
495508
{
496509
...bomBaseColDef,
497-
field: 'priceRaw',
510+
field: 'price',
498511
headerName: 'Price per Unit',
499512
type: 'number',
500513
editable: editPerms,
501-
renderCell: (params) => params.row.price,
514+
renderCell: ({ value }) => (value != null ? `$${centsToDollar(Math.round(value * 100))}` : ''), // $ formatting with cents to dollar conversion
515+
valueParser: (value) => (value == null || value === '' ? undefined : Number(value)), // convert back to number for editing
502516
sortable: false,
503517
filterable: false,
504518
hide: hideColumn[8]

src/frontend/src/utils/bom.utils.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@ export interface BomRow extends GridValidRowModel {
1414
manufacturer: string;
1515
manufacturerPN: string;
1616
pdmFileName: string;
17-
quantity: string;
18-
quantityRaw?: number;
19-
price: string;
20-
priceRaw?: number;
17+
quantity: number | undefined;
18+
unitName: string | undefined;
19+
price: number | undefined;
2120
subtotal: string;
2221
link: string;
2322
notes: string | undefined;
@@ -36,10 +35,9 @@ export const materialToRow = (material: Material, idx: number): BomRow => {
3635
manufacturer: material.manufacturerName ?? '',
3736
manufacturerPN: material.manufacturerPartNumber ?? '',
3837
pdmFileName: material.pdmFileName ?? '',
39-
quantity: material.quantity + (material.unitName ? ' ' + material.unitName : ''),
40-
quantityRaw: material.quantity !== undefined ? Number(material.quantity) : undefined,
41-
price: material.price !== undefined ? `$${centsToDollar(material.price)}` : '',
42-
priceRaw: material.price !== undefined ? material.price / 100 : undefined,
38+
quantity: material.quantity !== undefined ? Number(material.quantity) : undefined,
39+
unitName: material.unitName,
40+
price: material.price !== undefined ? material.price / 100 : undefined,
4341
subtotal: material.subtotal !== undefined ? `$${centsToDollar(material.subtotal)}` : '',
4442
link: material.linkUrl,
4543
notes: material.notes,

0 commit comments

Comments
 (0)