-
Notifications
You must be signed in to change notification settings - Fork 93
LF-4966 implement delete product functionality #3896
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
SayakaOno
merged 16 commits into
integration
from
LF-4966-implement-delete-product-functionality
Oct 15, 2025
Merged
Changes from 9 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
a032fbf
LF-4966 Add new strings
kathyavini 3931611
LF-4966 Add new modals
kathyavini 6bb4fec
LF-4966 Add delete mutation and remove unused tag
kathyavini 7128204
LF-4966 Add selector for product deletability check
kathyavini c12f64e
LF-4966 Add useRemoveProduct.ts hook
kathyavini 5ccd82c
LF-4966 Refactor hook props
kathyavini 70dc8a0
LF-4966 Move inventory menu item outside of isAdmin block
kathyavini 62d341d
LF-4966 Render delete button conditionally on admin status
kathyavini ed1c940
LF-4966 Merge integration and fix conflict in ProductForm imports
kathyavini 08547fa
LF-4966 Fix setter capitalization
kathyavini 62e4d93
LF-4966 Call onProductsFetched() logic directly after removal
kathyavini 4f68976
LF-4966 Combine modal state
kathyavini b5725fc
LF-4966 Remove extra state setting line
kathyavini 7d5e11b
LF-4966 Restore FormMode.READ_ONLY in the case of API error
kathyavini 934f678
LF-4966 Fix PropType console error
kathyavini b1f3725
LF-4966 Re-write selector without using a factory
kathyavini File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
packages/webapp/src/components/Modals/RemoveProductConfirmationModal/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| * Copyright 2025 LiteFarm.org | ||
| * This file is part of LiteFarm. | ||
| * | ||
| * LiteFarm is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * LiteFarm is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details, see <https://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| import ModalComponent from '../ModalComponent/v2'; | ||
| import { useTranslation, Trans } from 'react-i18next'; | ||
| import Button from '../../Form/Button'; | ||
|
|
||
| interface RemoveProductConfirmationModalProps { | ||
| dismissModal: () => void; | ||
| handleRemove: () => void; | ||
| productName?: string; | ||
| } | ||
|
|
||
| export default function RemoveProductConfirmationModal({ | ||
| dismissModal, | ||
| handleRemove, | ||
| productName, | ||
| }: RemoveProductConfirmationModalProps) { | ||
| const { t } = useTranslation(); | ||
|
|
||
| return ( | ||
| <ModalComponent | ||
| title={t('INVENTORY.REMOVE_CONFIRMATION.TITLE')} | ||
| contents={[ | ||
| <Trans | ||
| i18nKey="INVENTORY.REMOVE_CONFIRMATION.BODY" | ||
| values={{ name: productName }} | ||
| components={{ strong: <strong /> }} | ||
| />, | ||
| ]} | ||
| dismissModal={dismissModal} | ||
| buttonGroup={ | ||
| <> | ||
| <Button onClick={dismissModal} color={'secondary'} type={'button'} sm> | ||
| {t('common:CANCEL')} | ||
| </Button> | ||
| <Button onClick={handleRemove} type={'submit'} sm> | ||
| {t('common:REMOVE')} | ||
| </Button> | ||
| </> | ||
| } | ||
| /> | ||
| ); | ||
| } |
35 changes: 35 additions & 0 deletions
35
packages/webapp/src/components/Modals/UnableToRemoveProductModal/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| /* | ||
| * Copyright 2025 LiteFarm.org | ||
| * This file is part of LiteFarm. | ||
| * | ||
| * LiteFarm is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * LiteFarm is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details, see <https://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| import { useTranslation } from 'react-i18next'; | ||
| import ModalComponent from '../ModalComponent/v2'; | ||
|
|
||
| export default function UnableToRemoveProductModal({ | ||
| dismissModal, | ||
| productName, | ||
| }: { | ||
| dismissModal: () => void; | ||
| productName: string; | ||
| }) { | ||
| const { t } = useTranslation(); | ||
| return ( | ||
| <ModalComponent | ||
| title={t('INVENTORY.UNABLE_TO_REMOVE.TITLE')} | ||
| contents={[t('INVENTORY.UNABLE_TO_REMOVE.BODY', { name: productName })]} | ||
| dismissModal={dismissModal} | ||
| error | ||
| /> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
packages/webapp/src/containers/ProductInventory/ProductForm/useRemoveProduct.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| /* | ||
| * Copyright 2025 LiteFarm.org | ||
| * This file is part of LiteFarm. | ||
| * | ||
| * LiteFarm is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * LiteFarm is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details, see <https://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| import { useState, useEffect } from 'react'; | ||
| import { useTranslation } from 'react-i18next'; | ||
| import { useDispatch, useSelector } from 'react-redux'; | ||
| import { getProducts } from '../../Task/saga'; | ||
| import { isProductUsedInPlannedTasksSelector, productSelector } from '../../productSlice'; | ||
| import { enqueueErrorSnackbar, enqueueSuccessSnackbar } from '../../Snackbar/snackbarSlice'; | ||
| import { useDeleteSoilAmendmentProductMutation } from '../../../store/api/apiSlice'; | ||
| import { TASK_TYPES } from '../../Task/constants'; | ||
| import type { Product } from '../../../store/api/types'; | ||
| import { FormMode } from '..'; | ||
|
|
||
| interface useRemoveProductProps { | ||
| productFormType: Product['type'] | null; | ||
| formMode: FormMode | null; | ||
| productId?: Product['product_id']; | ||
| onRemovalSuccess: () => void; | ||
| onRemovalCancel: () => void; | ||
| } | ||
|
|
||
| const useRemoveProduct = ({ | ||
| productFormType, | ||
| formMode, | ||
| productId, | ||
| onRemovalSuccess, | ||
| onRemovalCancel, | ||
| }: useRemoveProductProps) => { | ||
| const { t } = useTranslation(); | ||
| const dispatch = useDispatch(); | ||
| const [isRemoveModalOpen, setisRemoveModalOpen] = useState(false); | ||
| const [isCannotRemoveModalOpen, setisCannotRemoveModalOpen] = useState(false); | ||
SayakaOno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| const product = useSelector(productSelector(productId)); | ||
| const productName = product?.name; | ||
|
|
||
| const isProductInUse = useSelector(isProductUsedInPlannedTasksSelector(productId)); | ||
|
|
||
| const [deleteSoilAmendmentProduct] = useDeleteSoilAmendmentProductMutation(); | ||
|
|
||
| useEffect(() => { | ||
| if (formMode === FormMode.DELETE && productId) { | ||
| if (isProductInUse) { | ||
| setisCannotRemoveModalOpen(true); | ||
| } else { | ||
| setisRemoveModalOpen(true); | ||
| } | ||
| } | ||
| }, [formMode, productId, isProductInUse]); | ||
|
|
||
| const onRemove = async () => { | ||
| if (!formMode || !productFormType || !productId) { | ||
| return; | ||
| } | ||
|
|
||
| let apiCall = null; | ||
|
|
||
| if (productFormType === TASK_TYPES.SOIL_AMENDMENT) { | ||
| apiCall = deleteSoilAmendmentProduct; | ||
| } else { | ||
| throw new Error(`Unsupported product type: ${productFormType}`); | ||
| } | ||
|
|
||
| try { | ||
| await apiCall(productId).unwrap(); | ||
| } catch (e) { | ||
| console.error(e); | ||
| dispatch(enqueueErrorSnackbar(t('message:PRODUCT.ERROR.REMOVE'))); | ||
| setisRemoveModalOpen(false); | ||
| return; | ||
| } | ||
|
|
||
| const onProductsFetched = () => { | ||
| dispatch(enqueueSuccessSnackbar(t('message:PRODUCT.SUCCESS.REMOVE'))); | ||
| setisRemoveModalOpen(false); | ||
| onRemovalSuccess(); | ||
| }; | ||
|
|
||
| dispatch(getProducts({ callback: onProductsFetched })); | ||
SayakaOno marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }; | ||
|
|
||
| return { | ||
| isRemoveModalOpen, | ||
| isCannotRemoveModalOpen, | ||
| onRemove, | ||
| cancelRemoval: () => { | ||
| setisRemoveModalOpen(false); | ||
| setisCannotRemoveModalOpen(false); | ||
| onRemovalCancel(); | ||
| }, | ||
| productName, | ||
| }; | ||
| }; | ||
|
|
||
| export default useRemoveProduct; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As always wrapping the return in a parent fragment has annoyingly made the whole return into a diff, but the actual changes within
<Drawer />are the two extra conditionals intoisOpen, and theisAdminargument intorenderDrawerTitle