Skip to content
Merged
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,7 +1,8 @@
import { Box, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';
import { Box, Link, Table, TableBody, TableCell, TableHead, TableRow, Typography } from '@mui/material';
import { getUniqueWbsElementsWithProductsFromReimbursementRequest } from '../../../utils/reimbursement-request.utils';
import { ReimbursementRequest } from 'shared';
import { centsToDollar } from '../../../utils/pipes';
import { routes } from '../../../utils/routes';

interface ReimbursementRequestProductsViewProps {
reimbursementRequest: ReimbursementRequest;
Expand All @@ -21,7 +22,6 @@ const ReimbursementProductsView: React.FC<ReimbursementRequestProductsViewProps>
(product) => product.refundSources.length > 1
);

// put all the refund source names in a set to avoid duplicate names
const refundSourceNames: string[] = Array.from(
new Set(
reimbursementRequest.reimbursementProducts.flatMap((product) => product.refundSources.map((rs) => rs.indexCode.name))
Expand Down Expand Up @@ -58,16 +58,26 @@ const ReimbursementProductsView: React.FC<ReimbursementRequestProductsViewProps>
return (
<TableRow key={key}>
<TableCell>
<Box
sx={{
maxWidth: '64ch',
overflowWrap: 'anywhere',
whiteSpace: 'normal'
}}
>
{uniqueWbsElementsWithProducts.get(key)?.map((product, index) => (
<div key={index}>{product.name}</div>
))}
<Box sx={{ maxWidth: '64ch', overflowWrap: 'anywhere', whiteSpace: 'normal' }}>
{uniqueWbsElementsWithProducts.get(key)?.map((product, index) => {
const bomUrl = (() => {
if (!product.materialId) return undefined;
const reason = product.reimbursementProductReason;
if (!('wbsNum' in reason)) return undefined;
return `${routes.PROJECTS}/${reason.wbsNum.carNumber}.${reason.wbsNum.projectNumber}.${reason.wbsNum.workPackageNumber}/bom`;
})();
return (
<div key={index}>
{bomUrl ? (
<Link href={bomUrl} underline="hover">
{product.name}
</Link>
) : (
product.name
)}
</div>
);
})}
</Box>
</TableCell>
{!allKeysAreSame && <TableCell>{key}</TableCell>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { ReimbursementRequestFormInput } from './ReimbursementRequestForm';
import { useTheme } from '@mui/system';
import { useEffect, useState, useRef, useMemo } from 'react';
import { useGetAllOtherProductReason } from '../../../hooks/finance.hooks';
import { useGetMaterialsForWbsElement, useGetAssembliesForWbsElement } from '../../../hooks/bom.hooks';
import { useGetMaterialsForWbsElement } from '../../../hooks/bom.hooks';
import LoadingIndicator from '../../../components/LoadingIndicator';
import ErrorPage from '../../ErrorPage';
import { formatReasonName } from '../../../utils/reimbursement-request.utils';
Expand Down Expand Up @@ -174,13 +174,6 @@ const ReimbursementProductTable: React.FC<ReimbursementProductTableProps> = ({
const [currentProject, setCurrentProject] = useState<ProjectPreview | null>(null);
const [pendingMaterialIndices, setPendingMaterialIndices] = useState<Set<number>>(new Set());

const {
data: assemblies,
isLoading: assembliesLoading,
isError: assembliesIsError,
error: assembliesError
} = useGetAssembliesForWbsElement(currentProject?.wbsNum || { carNumber: 0, projectNumber: 0, workPackageNumber: 0 });

const onCostBlurHandler = (value: number, index: number) => {
setValue(`reimbursementProducts.${index}.cost`, parseFloat(value.toFixed(2)));

Expand Down Expand Up @@ -337,9 +330,6 @@ const ReimbursementProductTable: React.FC<ReimbursementProductTableProps> = ({
if (otherReasonIsError) {
return <ErrorPage message={otherReasonError.message} />;
}
if (assembliesIsError) {
return <ErrorPage message={assembliesError?.message || 'Failed to load assemblies'} />;
}

return (
<>
Expand Down Expand Up @@ -864,13 +854,13 @@ const ReimbursementProductTable: React.FC<ReimbursementProductTableProps> = ({
</Table>
</TableContainer>

{currentProject && !assembliesLoading && assemblies && (
{currentProject && (
<CreateMaterialModal
open={showCreateMaterialModal}
onHide={handleCloseCreateMaterial}
wbsElement={currentProject}
assemblies={assemblies}
onSuccess={handleMaterialCreated}
fromRRForm
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
import { Assembly, WbsElementPreview } from 'shared';
import { WbsElementPreview } from 'shared';
import MaterialForm, { MaterialDataSubmission } from './MaterialForm';
import LoadingIndicator from '../../../../../components/LoadingIndicator';
import { useToast } from '../../../../../hooks/toasts.hooks';
import { useCreateMaterial } from '../../../../../hooks/bom.hooks';
import { useCreateMaterial, useGetAssembliesForWbsElement } from '../../../../../hooks/bom.hooks';
import ErrorPage from '../../../../ErrorPage';

export interface CreateMaterialModalProps {
open: boolean;
onHide: () => void;
wbsElement: WbsElementPreview;
assemblies: Assembly[];
onSuccess?: (materialName: string) => void;
fromRRForm?: boolean;
}

const CreateMaterialModal: React.FC<CreateMaterialModalProps> = ({ open, onHide, assemblies, wbsElement, onSuccess }) => {
const { mutateAsync: createMaterial, isLoading, isError, error } = useCreateMaterial(wbsElement.wbsNum);
const CreateMaterialModal: React.FC<CreateMaterialModalProps> = ({
open,
onHide,
wbsElement,
onSuccess,
fromRRForm = false
}) => {
const { mutateAsync: createMaterial } = useCreateMaterial(wbsElement.wbsNum);
const {
data: assemblies,
isError: assembliesIsError,
error: assembliesError
} = useGetAssembliesForWbsElement(wbsElement.wbsNum);
const toast = useToast();

if (isLoading) return <LoadingIndicator />;
if (isError) return <ErrorPage message={error?.message} />;
if (assembliesIsError) return <ErrorPage message={assembliesError?.message} />;

const onSubmit = async (data: MaterialDataSubmission): Promise<void> => {
try {
Expand All @@ -37,7 +46,16 @@ const CreateMaterialModal: React.FC<CreateMaterialModalProps> = ({ open, onHide,
}
};

return <MaterialForm submitText="Add" onSubmit={onSubmit} assemblies={assemblies} onHide={onHide} open={open} />;
return (
<MaterialForm
submitText="Add"
onSubmit={onSubmit}
assemblies={assemblies}
onHide={onHide}
open={open}
fromRRForm={fromRRForm}
/>
);
};

export default CreateMaterialModal;

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { yupResolver } from '@hookform/resolvers/yup';
import { useForm } from 'react-hook-form';
import { Assembly, MaterialStatus, RoleEnum } from 'shared';
import { Assembly, MaterialStatus } from 'shared';
import * as yup from 'yup';
import LoadingIndicator from '../../../../../components/LoadingIndicator';
import {
useCreateManufacturer,
useGetAllManufacturers,
Expand All @@ -12,10 +11,8 @@ import {
} from '../../../../../hooks/bom.hooks';
import ErrorPage from '../../../../ErrorPage';
import { Decimal } from 'decimal.js';
import { useCurrentUser } from '../../../../../hooks/users.hooks';
import MaterialAdminWrapper from './MaterialAdminWrapper';
import MaterialHeadWrapper from './MaterialHeadWrapper';
import MaterialMemberWrapper from './MaterialMemberWrapper';
import MaterialFormView from './MaterialFormView';
import LoadingIndicator from '../../../../../components/LoadingIndicator';

const schema = yup.object().shape({
name: yup.string().required('Enter a name!'),
Expand Down Expand Up @@ -72,10 +69,19 @@ export interface MaterialFormProps {
defaultValues?: MaterialFormInput;
onHide: () => void;
open: boolean;
assemblies: Assembly[];
assemblies?: Assembly[];
fromRRForm?: boolean;
}

const MaterialForm: React.FC<MaterialFormProps> = ({ submitText, assemblies, onSubmit, defaultValues, onHide, open }) => {
const MaterialForm: React.FC<MaterialFormProps> = ({
submitText,
assemblies,
onSubmit,
defaultValues,
onHide,
open,
fromRRForm = false
}) => {
const {
handleSubmit,
control,
Expand All @@ -85,10 +91,10 @@ const MaterialForm: React.FC<MaterialFormProps> = ({ submitText, assemblies, onS
} = useForm<MaterialFormInput>({
defaultValues: {
name: defaultValues?.name ?? '',
status: defaultValues?.status ?? MaterialStatus.NotReadyToOrder,
status: defaultValues?.status ?? (fromRRForm ? MaterialStatus.ReadyToOrder : MaterialStatus.NotReadyToOrder),
materialTypeName: defaultValues?.materialTypeName ?? '',
manufacturerPartNumber: defaultValues?.manufacturerPartNumber ?? '',
quantity: defaultValues?.quantity ?? 0,
quantity: defaultValues?.quantity ?? 1,
manufacturerName: defaultValues?.manufacturerName ?? '',
pdmFileName: defaultValues?.pdmFileName,
price: defaultValues?.price ?? 0,
Expand All @@ -101,39 +107,19 @@ const MaterialForm: React.FC<MaterialFormProps> = ({ submitText, assemblies, onS
resolver: yupResolver(schema)
});

const user = useCurrentUser();

const { mutateAsync: createManufacturer, isLoading: isLoadingCreateManufacturer } = useCreateManufacturer();

const {
data: materialTypes,
isLoading: isLoadingMaterialTypes,
isError: materialTypesIsError,
error: materialTypesError
} = useGetAllMaterialTypes();
const { data: materialTypes, isError: materialTypesIsError, error: materialTypesError } = useGetAllMaterialTypes();

const { data: units, isLoading: isLoadingUnits, isError: unitsIsError, error: unitsError } = useGetAllUnits();
const { data: units, isError: unitsIsError, error: unitsError } = useGetAllUnits();

const {
data: manufactuers,
isLoading: isLoadingManufactuers,
isError: manufacturersIsError,
error: manufacturersError
} = useGetAllManufacturers();
const { data: manufactuers, isError: manufacturersIsError, error: manufacturersError } = useGetAllManufacturers();

if (materialTypesIsError) return <ErrorPage message={materialTypesError.message} />;
if (unitsIsError) return <ErrorPage message={unitsError.message} />;
if (manufacturersIsError) return <ErrorPage message={manufacturersError.message} />;

if (
isLoadingManufactuers ||
isLoadingMaterialTypes ||
isLoadingUnits ||
!materialTypes ||
!units ||
!manufactuers ||
isLoadingCreateManufacturer
) {
if (isLoadingCreateManufacturer) {
return <LoadingIndicator />;
}

Expand All @@ -158,30 +144,25 @@ const MaterialForm: React.FC<MaterialFormProps> = ({ submitText, assemblies, onS
}
};

const sharedProps = {
assemblies,
allManufacturers: manufactuers,
allMaterialTypes: materialTypes,
allUnits: units,
onSubmit: onSubmitWrapper,
handleSubmit,
submitText,
onHide,
control,
errors,
open,
watch,
createManufacturer: createManufacturerWrapper,
setValue
};

if (user.role === RoleEnum.APP_ADMIN || user.role === RoleEnum.ADMIN) {
return <MaterialAdminWrapper {...sharedProps} />;
}
if (user.role === RoleEnum.HEAD || user.role === RoleEnum.LEADERSHIP) {
return <MaterialHeadWrapper {...sharedProps} />;
}
return <MaterialMemberWrapper {...sharedProps} />;
return (
<MaterialFormView
assemblies={assemblies}
allManufacturers={manufactuers}
allMaterialTypes={materialTypes}
allUnits={units}
onSubmit={onSubmitWrapper}
handleSubmit={handleSubmit}
submitText={submitText}
onHide={onHide}
control={control}
errors={errors}
open={open}
watch={watch}
createManufacturer={createManufacturerWrapper}
setValue={setValue}
fromRRForm={fromRRForm}
/>
);
};

export default MaterialForm;
Loading