diff --git a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.test.tsx b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.test.tsx index f1f43688..d805d7f0 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.test.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.test.tsx @@ -38,12 +38,14 @@ describe("buildNonIntegratedDetailChrome", () => { productContext: {}, productFactoryActions: {}, productLimitWorkbook: {}, + productPricingWorkbook: {}, productPhotoUploadActions: {}, productWorkflowActions: {}, qualityInspectionActions: {}, reviewDerived: {}, reviewSheetAssets: {}, reviewSheetFields: {}, + sampleMeasurementWorkbook: {}, sampleWorkflowActions: {}, secondaryRenderers: { workspaceImageDialog: {} }, seriesDerived: {}, diff --git a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.tsx b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.tsx index 2ed8e3ea..b9836bac 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailChrome.tsx @@ -64,12 +64,14 @@ type DetailChromeProps = Required< productContext: ProductSetupState["productContext"]; productFactoryActions: FormActionState["productFactoryActions"]; productLimitWorkbook: SkuReviewActionState["productLimitWorkbook"]; + productPricingWorkbook: SkuReviewActionState["productPricingWorkbook"]; productPhotoUploadActions: FileActionState["productPhotoUploadActions"]; productWorkflowActions: FormActionState["productWorkflowActions"]; qualityInspectionActions: SkuReviewActionState["qualityInspectionActions"]; reviewDerived: WorkflowDerivedState["reviewDerived"]; reviewSheetAssets: SkuReviewActionState["reviewSheetAssets"]; reviewSheetFields: SkuReviewActionState["reviewSheetFields"]; + sampleMeasurementWorkbook: SkuReviewActionState["sampleMeasurementWorkbook"]; sampleWorkflowActions: DocumentActionState["sampleWorkflowActions"]; secondaryRenderers: SecondaryRendererState; seriesDerived: ProductSetupState["seriesDerived"]; @@ -109,12 +111,14 @@ export function buildNonIntegratedDetailChrome({ productContext, productFactoryActions, productLimitWorkbook, + productPricingWorkbook, productPhotoUploadActions, productWorkflowActions, qualityInspectionActions, reviewDerived, reviewSheetAssets, reviewSheetFields, + sampleMeasurementWorkbook, sampleWorkflowActions, secondaryRenderers, seriesDerived, @@ -148,6 +152,10 @@ export function buildNonIntegratedDetailChrome({ documentDownloads.handleDownloadWorkspaceFiles, onExportProductLimitWorkbook: productLimitWorkbook.handleExportProductLimitWorkbook, + onExportProductPricingWorkbook: + productPricingWorkbook.handleExportProductPricingWorkbook, + onExportSampleMeasurementWorkbook: + sampleMeasurementWorkbook.handleExportSampleMeasurementWorkbook, onExportQualityInspection: qualityInspectionActions.handleExportQualityInspection, onExportReviewSheet: reviewSheetAssets.handleExportReviewSheet, @@ -155,6 +163,10 @@ export function buildNonIntegratedDetailChrome({ sampleWorkflowActions.handleFinishedSampleShipmentStatusClick, onImportProductLimitWorkbookChange: productLimitWorkbook.handleImportProductLimitWorkbookChange, + onImportProductPricingWorkbookChange: + productPricingWorkbook.handleImportProductPricingWorkbookChange, + onImportSampleMeasurementWorkbookChange: + sampleMeasurementWorkbook.handleImportSampleMeasurementWorkbookChange, onOpenProductPhotoCurrentUpload: documentSelectionActions.openProductPhotoCurrentUpload, onOpenProductPhotoPanelUpload: @@ -232,11 +244,19 @@ export function buildNonIntegratedDetailChrome({ permissionState.isCurrentUserPlainReadOnlyViewer, isExportingProductLimit: productLimitWorkbook.isExportingProductLimit, + isExportingProductPricing: + productPricingWorkbook.isExportingProductPricing, isExportingQualityInspection: qualityInspectionActions.isExportingQualityInspection, isExportingReviewSheet: reviewSheetAssets.isExportingReviewSheet, + isExportingSampleMeasurement: + sampleMeasurementWorkbook.isExportingSampleMeasurement, isImportingProductLimit: productLimitWorkbook.isImportingProductLimit, + isImportingProductPricing: + productPricingWorkbook.isImportingProductPricing, + isImportingSampleMeasurement: + sampleMeasurementWorkbook.isImportingSampleMeasurement, isProductFactoryReopenPickerOpen: workflowState.isProductFactoryReopenPickerOpen, isProductLimitNodeLocked: @@ -248,6 +268,10 @@ export function buildNonIntegratedDetailChrome({ workflowState.productFactoryReopenField, productLimitWorkbookInputRef: inputRefs.productLimitWorkbookInputRef, + productPricingWorkbookInputRef: + inputRefs.productPricingWorkbookInputRef, + sampleMeasurementWorkbookInputRef: + inputRefs.sampleMeasurementWorkbookInputRef, productPhotoCurrentUploadInputRef: inputRefs.productPhotoCurrentUploadInputRef, productPhotoDetailUploadInputRef: diff --git a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailRenderers.tsx b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailRenderers.tsx index 7455872a..4bdd7ad4 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailRenderers.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDetailRenderers.tsx @@ -164,6 +164,8 @@ export function buildNonIntegratedDetailRenderers({ productContext: setup.productContext, productFactoryActions: formActions.productFactoryActions, productLimitWorkbook: skuActions.productLimitWorkbook, + productPricingWorkbook: skuActions.productPricingWorkbook, + sampleMeasurementWorkbook: skuActions.sampleMeasurementWorkbook, productPhotoUploadActions: fileActions.productPhotoUploadActions, productWorkflowActions: formActions.productWorkflowActions, qualityInspectionActions: skuActions.qualityInspectionActions, diff --git a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDocumentWorkspaceHeaderActions.ts b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDocumentWorkspaceHeaderActions.ts index 4430a45f..a8648ba4 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDocumentWorkspaceHeaderActions.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/buildNonIntegratedDocumentWorkspaceHeaderActions.ts @@ -1,6 +1,8 @@ import type { ComponentProps } from "react"; import { NON_INTEGRATED_PRODUCT_LIMIT_WORKBOOK_ACCEPT } from "@/lib/non-integrated-product-limit-workbook"; +import { NON_INTEGRATED_PRODUCT_PRICING_WORKBOOK_ACCEPT } from "@/lib/non-integrated-product-pricing-workbook"; +import { NON_INTEGRATED_SAMPLE_MEASUREMENT_WORKBOOK_ACCEPT } from "@/lib/non-integrated-sample-measurement-workbook"; import { DOCUMENT_WORKSPACE_ACTION_GROUP_CLASS, DOCUMENT_WORKSPACE_CONFIRMED_CLASS, @@ -49,15 +51,21 @@ type DirectStateName = | "isCurrentUserAdmin" | "isCurrentUserPlainReadOnlyViewer" | "isExportingProductLimit" + | "isExportingProductPricing" | "isExportingQualityInspection" | "isExportingReviewSheet" + | "isExportingSampleMeasurement" | "isImportingProductLimit" + | "isImportingProductPricing" + | "isImportingSampleMeasurement" | "isProductFactoryReopenPickerOpen" | "isProductLimitNodeLocked" | "isProductPricingNodeLocked" | "isReadOnly" | "productFactoryReopenField" | "productLimitWorkbookInputRef" + | "productPricingWorkbookInputRef" + | "sampleMeasurementWorkbookInputRef" | "productPhotoCurrentUploadInputRef" | "productPhotoDetailUploadInputRef" | "selectedProductPhotoTarget"; @@ -150,6 +158,10 @@ export function buildNonIntegratedDocumentWorkspaceHeaderActions({ isSampleMeasurementWorkspace: presentation.isSampleMeasurementWorkspace, productLimitWorkbookAccept: NON_INTEGRATED_PRODUCT_LIMIT_WORKBOOK_ACCEPT, + productPricingWorkbookAccept: + NON_INTEGRATED_PRODUCT_PRICING_WORKBOOK_ACCEPT, + sampleMeasurementWorkbookAccept: + NON_INTEGRATED_SAMPLE_MEASUREMENT_WORKBOOK_ACCEPT, qualityStandardFileAccept: QUALITY_STANDARD_FILE_ACCEPT, reviewRoundCount: rows.reviewRounds.length, }; diff --git a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailDomainControllers.ts b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailDomainControllers.ts index 818c1242..fad875d7 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailDomainControllers.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailDomainControllers.ts @@ -239,6 +239,7 @@ export function useNonIntegratedDetailDomainControllers( }); const skuActions = useNonIntegratedSkuReviewActionControllers({ artifactState, + workflowCompletion: workflow.workflowCompletion, basicInfoController: formActions.basicInfoController, basicInfoDerived: setup.basicInfoDerived, bomLibrary, diff --git a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailInputRefs.ts b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailInputRefs.ts index e38e1cd5..bba521fc 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailInputRefs.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedDetailInputRefs.ts @@ -10,6 +10,10 @@ export function useNonIntegratedDetailInputRefs() { const batchSkuImageInputRef = useRef(null); const skuWorkbookInputRef = useRef(null); const productLimitWorkbookInputRef = useRef(null); + const productPricingWorkbookInputRef = useRef(null); + const sampleMeasurementWorkbookInputRef = useRef( + null, + ); const fileUploadInputRef = useRef(null); const documentWorkspaceUploadInputRef = useRef(null); const installationWorkspaceUploadInputRef = useRef( @@ -46,6 +50,8 @@ export function useNonIntegratedDetailInputRefs() { productLimitWorkbookInputRef, productPhotoCurrentUploadInputRef, productPhotoDetailUploadInputRef, + productPricingWorkbookInputRef, + sampleMeasurementWorkbookInputRef, skuWorkbookInputRef, }; } diff --git a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.test.ts b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.test.ts index 8117ff93..8fe31696 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.test.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.test.ts @@ -9,6 +9,8 @@ import { useSkuCreationController } from "./workspaces/basic-info/useSkuCreation import { useSkuDisplayState } from "./workspaces/basic-info/useSkuDisplayState"; import { useSkuWorkbookController } from "./workspaces/basic-info/useSkuWorkbookController"; import { useProductLimitWorkbookController } from "./workspaces/product-workflow/useProductLimitWorkbookController"; +import { useProductPricingWorkbookController } from "./workspaces/product-workflow/useProductPricingWorkbookController"; +import { useSampleMeasurementWorkbookController } from "./workspaces/sample-workflow/useSampleMeasurementWorkbookController"; import { useQualityInspectionController } from "./workspaces/quality-inspection/useQualityInspectionController"; import { useReviewSheetAssetController } from "./workspaces/review-sheet/useReviewSheetAssetController"; import { useReviewSheetFieldController } from "./workspaces/review-sheet/useReviewSheetFieldController"; @@ -22,6 +24,12 @@ jest.mock("./workspaces/basic-info/useSkuCreationController"); jest.mock("./workspaces/basic-info/useSkuDisplayState"); jest.mock("./workspaces/basic-info/useSkuWorkbookController"); jest.mock("./workspaces/product-workflow/useProductLimitWorkbookController"); +jest.mock( + "./workspaces/product-workflow/useProductPricingWorkbookController", +); +jest.mock( + "./workspaces/sample-workflow/useSampleMeasurementWorkbookController", +); jest.mock("./workspaces/quality-inspection/useQualityInspectionController"); jest.mock("./workspaces/review-sheet/useReviewSheetAssetController"); jest.mock("./workspaces/review-sheet/useReviewSheetFieldController"); @@ -35,6 +43,12 @@ describe("useNonIntegratedSkuReviewActionControllers", () => { skuBatchLifecycle: { handleAddSkuBatch: jest.fn() }, skuWorkbook: { handleExportSkuWorkbook: jest.fn() }, productLimitWorkbook: { handleExportProductLimitWorkbook: jest.fn() }, + productPricingWorkbook: { + handleExportProductPricingWorkbook: jest.fn(), + }, + sampleMeasurementWorkbook: { + handleExportSampleMeasurementWorkbook: jest.fn(), + }, bomWorkbook: { handleExportBomWorkbook: jest.fn() }, workspaceNavigation: { navigateToIntakeList: jest.fn() }, qualityInspectionActions: { handleExportQualityInspection: jest.fn() }, @@ -54,6 +68,12 @@ describe("useNonIntegratedSkuReviewActionControllers", () => { jest .mocked(useProductLimitWorkbookController) .mockReturnValue(returns.productLimitWorkbook as never); + jest + .mocked(useProductPricingWorkbookController) + .mockReturnValue(returns.productPricingWorkbook as never); + jest + .mocked(useSampleMeasurementWorkbookController) + .mockReturnValue(returns.sampleMeasurementWorkbook as never); jest.mocked(useBomWorkbookController).mockReturnValue(returns.bomWorkbook as never); jest .mocked(useNonIntegratedWorkspaceNavigationController) @@ -115,6 +135,7 @@ describe("useNonIntegratedSkuReviewActionControllers", () => { spuEstimate: {}, supplementSelection: {}, transferProgress: {}, + workflowCompletion: {}, workflowConfirmation: {}, workflowRows: {}, workflowState: {}, @@ -130,6 +151,8 @@ describe("useNonIntegratedSkuReviewActionControllers", () => { aiWhiteBackground: returns.aiWhiteBackground, bomWorkbook: returns.bomWorkbook, productLimitWorkbook: returns.productLimitWorkbook, + productPricingWorkbook: returns.productPricingWorkbook, + sampleMeasurementWorkbook: returns.sampleMeasurementWorkbook, qualityInspectionActions: returns.qualityInspectionActions, reviewSheetAssets: returns.reviewSheetAssets, reviewSheetFields: returns.reviewSheetFields, diff --git a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.ts b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.ts index e5662497..9d450f8f 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.ts +++ b/furniture-3d-system/src/app/intake/non-integrated/useNonIntegratedSkuReviewActionControllers.ts @@ -9,6 +9,8 @@ import { useSkuCreationController } from "./workspaces/basic-info/useSkuCreation import { useSkuDisplayState } from "./workspaces/basic-info/useSkuDisplayState"; import { useSkuWorkbookController } from "./workspaces/basic-info/useSkuWorkbookController"; import { useProductLimitWorkbookController } from "./workspaces/product-workflow/useProductLimitWorkbookController"; +import { useProductPricingWorkbookController } from "./workspaces/product-workflow/useProductPricingWorkbookController"; +import { useSampleMeasurementWorkbookController } from "./workspaces/sample-workflow/useSampleMeasurementWorkbookController"; import { useQualityInspectionController } from "./workspaces/quality-inspection/useQualityInspectionController"; import { useReviewSheetAssetController } from "./workspaces/review-sheet/useReviewSheetAssetController"; import { useReviewSheetFieldController } from "./workspaces/review-sheet/useReviewSheetFieldController"; @@ -25,6 +27,7 @@ import type { useNonIntegratedPersistenceCoordinator } from "./useNonIntegratedP import type { useNonIntegratedProductSetupController } from "./useNonIntegratedProductSetupController"; import type { useNonIntegratedProjectState } from "./useNonIntegratedProjectState"; import type { useNonIntegratedSkuState } from "./useNonIntegratedSkuState"; +import type { useNonIntegratedWorkflowCompletion } from "./useNonIntegratedWorkflowCompletion"; import type { useNonIntegratedWorkflowDerivedController } from "./useNonIntegratedWorkflowDerivedController"; import type { useNonIntegratedWorkflowState } from "./useNonIntegratedWorkflowState"; import type { useSpuEstimateRefreshToken } from "./useSpuEstimateRefreshToken"; @@ -93,6 +96,7 @@ type SkuReviewActionControllerProps = Pick< spuEstimate: ReturnType; supplementSelection: WorkflowDerivedState["supplementSelection"]; transferProgress: ReturnType; + workflowCompletion: ReturnType; workflowConfirmation: WorkflowDerivedState["workflowConfirmation"]; workflowRows: WorkflowDerivedState["workflowRows"]; workflowState: ReturnType; @@ -140,6 +144,7 @@ export function useNonIntegratedSkuReviewActionControllers({ spuEstimate, supplementSelection, transferProgress, + workflowCompletion, workflowConfirmation, workflowRows, workflowState, @@ -291,6 +296,56 @@ export function useNonIntegratedSkuReviewActionControllers({ updateImportProgress: transferProgress.updateImportProgress, workflowSkuItems: seriesDerived.workflowSkuItems, }); + const productPricingWorkbook = useProductPricingWorkbookController({ + allProductPricingRows: workflowRows.productPricingRows, + canDownloadWorkspaceFiles: permissionState.canDownloadWorkspaceFiles, + denyWorkspaceDownloadForCurrentUser: + documentDownloads.denyWorkspaceDownloadForCurrentUser, + finishDownloadProgress: transferProgress.finishDownloadProgress, + finishImportProgress: transferProgress.finishImportProgress, + isProductPricingNodeLocked: workflowConfirmation.isProductPricingNodeLocked, + isReadOnly: editability.isReadOnly, + pricingRows: workflowState.pricingRows, + setDownloadProgress: transferProgress.setDownloadProgress, + setPricingRows: workflowState.setPricingRows, + setSaveMessage: overlayState.setSaveMessage, + setSaveMessageType: overlayState.setSaveMessageType, + setUploadProgress: transferProgress.setUploadProgress, + spu: formState.formValues.spu || formState.formValues.productCode, + startGeneratedDownloadProgress: + transferProgress.startGeneratedDownloadProgress, + startImportProgress: transferProgress.startImportProgress, + updateGeneratedDownloadProgress: + transferProgress.updateGeneratedDownloadProgress, + updateImportProgress: transferProgress.updateImportProgress, + workflowSkuItems: seriesDerived.workflowSkuItems, + }); + const sampleMeasurementWorkbook = useSampleMeasurementWorkbookController({ + allSampleMeasurementRows: workflowRows.productSampleMeasurementRows, + canDownloadWorkspaceFiles: permissionState.canDownloadWorkspaceFiles, + denyWorkspaceDownloadForCurrentUser: + documentDownloads.denyWorkspaceDownloadForCurrentUser, + finishDownloadProgress: transferProgress.finishDownloadProgress, + finishImportProgress: transferProgress.finishImportProgress, + isReadOnly: editability.isReadOnly, + isSampleMeasurementRowEditable: (skuId: string) => + workflowRows.isSkuItemFactoryConfirmed(skuId) && + !workflowCompletion.isSampleMeasurementSkuLocked(skuId), + sampleMeasurementRows: workflowState.sampleMeasurementRows, + setDownloadProgress: transferProgress.setDownloadProgress, + setSampleMeasurementRows: workflowState.setSampleMeasurementRows, + setSaveMessage: overlayState.setSaveMessage, + setSaveMessageType: overlayState.setSaveMessageType, + setUploadProgress: transferProgress.setUploadProgress, + spu: formState.formValues.spu || formState.formValues.productCode, + startGeneratedDownloadProgress: + transferProgress.startGeneratedDownloadProgress, + startImportProgress: transferProgress.startImportProgress, + updateGeneratedDownloadProgress: + transferProgress.updateGeneratedDownloadProgress, + updateImportProgress: transferProgress.updateImportProgress, + workflowSkuItems: seriesDerived.workflowSkuItems, + }); const bomWorkbook = useBomWorkbookController({ canDownloadWorkspaceFiles: permissionState.canDownloadWorkspaceFiles, denyWorkspaceDownloadForCurrentUser: @@ -439,9 +494,11 @@ export function useNonIntegratedSkuReviewActionControllers({ aiWhiteBackground, bomWorkbook, productLimitWorkbook, + productPricingWorkbook, qualityInspectionActions, reviewSheetAssets, reviewSheetFields, + sampleMeasurementWorkbook, skuBatchLifecycle, skuCreation, skuDisplay, diff --git a/furniture-3d-system/src/app/intake/non-integrated/workspaces/product-pricing/ProductPricingHeaderActions.tsx b/furniture-3d-system/src/app/intake/non-integrated/workspaces/product-pricing/ProductPricingHeaderActions.tsx index 1c60eebd..697caa64 100644 --- a/furniture-3d-system/src/app/intake/non-integrated/workspaces/product-pricing/ProductPricingHeaderActions.tsx +++ b/furniture-3d-system/src/app/intake/non-integrated/workspaces/product-pricing/ProductPricingHeaderActions.tsx @@ -1,8 +1,12 @@ +import type { ChangeEvent, RefObject } from "react"; import Button from "@/components/ui/Button"; type ProductPricingHeaderActionsProps = { actionGroupClassName: string; + canDownloadWorkspaceFiles: boolean; canUsePushControls: boolean; + isExporting: boolean; + isImporting: boolean; isReadOnly: boolean; isNodeLocked: boolean; rowCount: number; @@ -10,12 +14,19 @@ type ProductPricingHeaderActionsProps = { rowsComplete: boolean; rowsReadyForPush: boolean; isJstPushEnabled: boolean; + workbookInputRef: RefObject; + workbookAccept: string; + onExportWorkbook: () => void; + onImportWorkbookChange: (event: ChangeEvent) => void; onBatchConfirmPush: () => void; }; export function ProductPricingHeaderActions({ actionGroupClassName, + canDownloadWorkspaceFiles, canUsePushControls, + isExporting, + isImporting, isReadOnly, isNodeLocked, rowCount, @@ -23,6 +34,10 @@ export function ProductPricingHeaderActions({ rowsComplete, rowsReadyForPush, isJstPushEnabled, + workbookInputRef, + workbookAccept, + onExportWorkbook, + onImportWorkbookChange, onBatchConfirmPush, }: ProductPricingHeaderActionsProps) { const disabled = @@ -44,6 +59,37 @@ export function ProductPricingHeaderActions({ return (
+ {canDownloadWorkspaceFiles ? ( + + ) : null} + {isReadOnly ? null : ( + <> + + + + )} {canUsePushControls ? ( + ) : null} + {isReadOnly ? null : ( + <> + + + + )}