From 291d5e438c816785e26cfacc4e1506b8393e22a7 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Tue, 1 Sep 2026 17:26:15 +0100 Subject: [PATCH] Add PostFilamentStock Component and Update FilamentStock Model - Introduced the PostFilamentStock component to handle posting filament stock with confirmation dialog and loading state management. - Updated NewFilamentStock component to change the default state from 'unconsumed' to 'draft'. - Enhanced FilamentStock model by adding 'postedAt' field and integrating the PostFilamentStock component into the actions for posting filament stocks. - Improved visibility and disabled state logic for editing and posting actions based on filament stock state. --- .../FilamentStocks/NewFilamentStock.jsx | 5 +- .../FilamentStocks/PostFilamentStock.jsx | 46 ++++++++ src/database/models/FilamentStock.js | 101 +++++++++++++++++- 3 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 src/components/Dashboard/Inventory/FilamentStocks/PostFilamentStock.jsx diff --git a/src/components/Dashboard/Inventory/FilamentStocks/NewFilamentStock.jsx b/src/components/Dashboard/Inventory/FilamentStocks/NewFilamentStock.jsx index 0cb500be..d9a4677f 100644 --- a/src/components/Dashboard/Inventory/FilamentStocks/NewFilamentStock.jsx +++ b/src/components/Dashboard/Inventory/FilamentStocks/NewFilamentStock.jsx @@ -8,7 +8,7 @@ const NewFilamentStock = ({ onOk, reset, defaultValues }) => { {({ handleSubmit, submitLoading, objectData, formValid }) => { const steps = [ @@ -38,7 +38,8 @@ const NewFilamentStock = ({ onOk, reset, defaultValues }) => { _id: false, _reference: false, createdAt: false, - updatedAt: false + updatedAt: false, + postedAt: false }} isEditing={false} objectData={objectData} diff --git a/src/components/Dashboard/Inventory/FilamentStocks/PostFilamentStock.jsx b/src/components/Dashboard/Inventory/FilamentStocks/PostFilamentStock.jsx new file mode 100644 index 00000000..e9cf7ec7 --- /dev/null +++ b/src/components/Dashboard/Inventory/FilamentStocks/PostFilamentStock.jsx @@ -0,0 +1,46 @@ +import { useState, useContext } from 'react' +import PropTypes from 'prop-types' +import { ApiServerContext } from '../../context/ApiServerContext' +import { message } from 'antd' +import MessageDialogView from '../../common/MessageDialogView.jsx' + +const PostFilamentStock = ({ onOk, objectData }) => { + const [postLoading, setPostLoading] = useState(false) + const { sendObjectFunction } = useContext(ApiServerContext) + + const handlePost = async () => { + setPostLoading(true) + try { + const result = await sendObjectFunction( + objectData._id, + 'FilamentStock', + 'post' + ) + if (result) { + message.success('Filament stock posted successfully') + onOk(result) + } + } catch (error) { + console.error('Error posting filament stock:', error) + } finally { + setPostLoading(false) + } + } + + return ( + + ) +} + +PostFilamentStock.propTypes = { + onOk: PropTypes.func.isRequired, + objectData: PropTypes.object +} + +export default PostFilamentStock diff --git a/src/database/models/FilamentStock.js b/src/database/models/FilamentStock.js index bb42bb5f..acb05b06 100644 --- a/src/database/models/FilamentStock.js +++ b/src/database/models/FilamentStock.js @@ -8,9 +8,20 @@ const NewFilamentStock = lazy( () => import('../../components/Dashboard/Inventory/FilamentStocks/NewFilamentStock') ) +const PostFilamentStock = lazy( + () => + import('../../components/Dashboard/Inventory/FilamentStocks/PostFilamentStock.jsx') +) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import FilamentStockIcon from '../../components/Icons/FilamentStockIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' +import EditIcon from '../../components/Icons/EditIcon' +import CheckIcon from '../../components/Icons/CheckIcon' +import XMarkIcon from '../../components/Icons/XMarkIcon' +import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' export const FilamentStock = { @@ -19,7 +30,6 @@ export const FilamentStock = { labelPlural: 'Filament Stocks', url: '/dashboard/inventory/filamentstocks', prefix: 'FLS', - readOnly: true, icon: FilamentStockIcon, actions: [ { @@ -52,6 +62,76 @@ export const FilamentStock = { default: true, row: true, icon: InfoCircleIcon + }, + { + name: 'edit', + type: 'page', + pageName: 'info', + label: 'Edit', + row: true, + icon: EditIcon, + visible: (objectData) => { + return !(objectData?._isEditing && objectData?._isEditing == true) + }, + disabled: (objectData) => { + return objectData?.state?.type != 'draft' + } + }, + { + name: 'cancelEdit', + label: 'Cancel Edits', + type: 'page', + pageName: 'info', + icon: XMarkIcon, + visible: (objectData) => { + return objectData?._isEditing && objectData?._isEditing == true + } + }, + { + name: 'finishEdit', + label: 'Save Edits', + type: 'page', + pageName: 'info', + icon: CheckIcon, + visible: (objectData) => { + return objectData?._isEditing && objectData?._isEditing == true + } + }, + { + name: 'delete', + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + visible: (objectData) => { + return !(objectData?._isEditing && objectData?._isEditing == true) + }, + disabled: (objectData) => { + return objectData?.state?.type != 'draft' + }, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } + }, + { type: 'divider' }, + { + name: 'post', + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Post', + icon: CheckIcon, + disabled: (objectData) => { + return objectData?._isEditing == true + }, + visible: (objectData) => { + return objectData?.state?.type == 'draft' + }, + content: (objectData, { onOk } = {}) => { + return createElement(PostFilamentStock, { objectData, onOk }) + } } ], pages: [ @@ -126,6 +206,13 @@ export const FilamentStock = { readOnly: true, columnWidth: 260 }, + { + name: 'postedAt', + label: 'Posted At', + type: 'dateTime', + readOnly: true, + columnWidth: 175 + }, { name: 'filament', label: 'Filament', @@ -174,7 +261,10 @@ export const FilamentStock = { required: true, columnWidth: 300, value: (objectData) => { - if (objectData?.state?.type === 'unconsumed') { + if ( + objectData?.state?.type === 'unconsumed' || + objectData?.state?.type === 'draft' + ) { return objectData?.startingWeight || { net: 0, gross: 0 } } else { return objectData?.currentWeight || { net: 0, gross: 0 } @@ -186,7 +276,6 @@ export const FilamentStock = { label: 'Starting Weight', type: 'netGross', suffix: 'g', - readOnly: true, initial: true, required: true, columnWidth: 300, @@ -196,6 +285,12 @@ export const FilamentStock = { } ], stats: [ + { + name: 'draft.count', + label: 'Draft', + type: 'number', + color: 'default' + }, { name: 'unconsumed.count', label: 'Unconsumed',