Skip to content

Commit

Permalink
feat:商品検索
Browse files Browse the repository at this point in the history
Add product category selection modal to ProductItem

Introduced a modal for selecting product categories in the `ProductItem` component. This includes new hooks, handlers, and UI elements to fetch, display, and manage product categories. Created `ProductCategorySelectView` and `ProductCategoryCollectionSelectView` components to support the feature.
  • Loading branch information
k2works committed Dec 27, 2024
1 parent d838736 commit 720a3c4
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 29 deletions.
143 changes: 114 additions & 29 deletions app/frontend/src/components/master/ProductItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ import {
CustomerSpecificSellingPriceCollectionView
} from "../../views/master/product/CustomerSpecificSellingPriceCollection.tsx";
import {ProductSearchSingleView} from "../../views/master/product/ProductSearch.tsx";
import {ProductCriteriaType, ProductType} from "../../models";
import {useFetchBoms, useFetchProducts, useFetchSubstitutes, useProduct} from "./hooks";
import {ProductCategoryCriteriaType, ProductCriteriaType, ProductType} from "../../models";
import {
useFetchBoms,
useFetchProductCategories,
useFetchProducts,
useFetchSubstitutes,
useProduct,
useProductCategory
} from "./hooks";
import {
ProductCategoryCollectionSelectView,
ProductCategorySelectView
} from "../../views/master/product/ProductCategorySelect.tsx";

export const ProductItem: React.FC = () => {
const Content: React.FC = () => {
Expand All @@ -24,6 +35,8 @@ export const ProductItem: React.FC = () => {
const {pageNation, setPageNation, criteria, setCriteria} = usePageNation<ProductCriteriaType>();
const {pageNation: substitutePageNation, setPageNation: setSubstitutePageNation} = usePageNation();
const {pageNation: bomPageNation, setPageNation: setBomPageNation} = usePageNation();
const {pageNation: productCategoryPageNation, setPageNation: setProductCategoryPageNation} = usePageNation<ProductCategoryCriteriaType>();

const {modalIsOpen: searchModalIsOpen, setModalIsOpen: setSearchModalIsOpen,} = useModal();

const {
Expand All @@ -49,6 +62,11 @@ export const ProductItem: React.FC = () => {
setEditId: setBomEditId
} = useModal();

const {
modalIsOpen: productCategoryModalIsOpen,
setModalIsOpen: setProductCategoryModalIsOpen
} = useModal();

const {
initialProduct,
products,
Expand Down Expand Up @@ -99,13 +117,29 @@ export const ProductItem: React.FC = () => {
bomService
);

const {
productCategories,
setProductCategories,
productCategoryService
} = useProductCategory();

const fetchProductCategories = useFetchProductCategories(
setLoading,
setProductCategories,
setProductCategoryPageNation,
setError,
showErrorMessage,
productCategoryService
);

useEffect(() => {
(async () => {
try {
await Promise.all([
fetchProducts.load(),
fetchSubstitutes.load(),
fetchBoms.load()
fetchBoms.load(),
fetchProductCategories.load()
]);
} catch (error: any) {
showErrorMessage(`商品情報の取得に失敗しました: ${error?.message}`, setError);
Expand Down Expand Up @@ -339,6 +373,50 @@ export const ProductItem: React.FC = () => {
}
}

const productCategoryModal = () => {
const handleCloseProductModal = () => {
setError("");
setProductModalIsOpen(false);
setProductEditId(null);
}

const productCategorySearchModalView = () => {
return (
<Modal
isOpen={productCategoryModalIsOpen}
onRequestClose={handleCloseProductModal}
contentLabel="商品情報を入力"
className="modal"
overlayClassName="modal-overlay"
bodyOpenClassName="modal-open"
>
{
<ProductCategoryCollectionSelectView
productCategories={productCategories}
handleSelect={(productCategory) => {
setSearchProductCriteria(
{
...searchProductCriteria,
productCategoryCode: productCategory.productCategoryCode.value
}
)
setProductCategoryModalIsOpen(false);
}}
handleClose={() => setProductCategoryModalIsOpen(false)}
pageNation={productCategoryPageNation}
fetchProductCategories={fetchProductCategories.load}
/>
}
</Modal>

)
}

return {
productCategorySearchModalView
}
}

const searchModal = () => {
const handleOpenSearchModal = () => {
setSearchModalIsOpen(true);
Expand All @@ -359,33 +437,40 @@ export const ProductItem: React.FC = () => {
bodyOpenClassName="modal-open"
>
{
<ProductSearchSingleView
criteria={searchProductCriteria}
setCondition={setSearchProductCriteria}
handleSelect={async () => {
if (!searchProductCriteria) {
return;
}
setLoading(true);
try {
const result = await productService.search(searchProductCriteria);
setProducts(result ? result.list : []);
if (result.list.length === 0) {
showErrorMessage(`検索結果は0件です`, setError);
} else {
setCriteria(searchProductCriteria);
setPageNation(result);
setMessage("");
setError("");
<>
<ProductSearchSingleView
criteria={searchProductCriteria}
setCondition={setSearchProductCriteria}
handleSelect={async () => {
if (!searchProductCriteria) {
return;
}
} catch (error: any) {
showErrorMessage(`実行履歴情報の検索に失敗しました: ${error?.message}`, setError);
} finally {
setLoading(false);
}
}}
handleClose={handleCloseSearchModal}
/>
setLoading(true);
try {
const result = await productService.search(searchProductCriteria);
setProducts(result ? result.list : []);
if (result.list.length === 0) {
showErrorMessage(`検索結果は0件です`, setError);
} else {
setCriteria(searchProductCriteria);
setPageNation(result);
setMessage("");
setError("");
}
} catch (error: any) {
showErrorMessage(`実行履歴情報の検索に失敗しました: ${error?.message}`, setError);
} finally {
setLoading(false);
}
}}
handleClose={handleCloseSearchModal}
/>

{productCategoryModal().productCategorySearchModalView()}
<ProductCategorySelectView
handleSelect={() => setProductCategoryModalIsOpen(true)}
/>
</>
}
</Modal>
)
Expand Down
83 changes: 83 additions & 0 deletions app/frontend/src/views/master/product/ProductCategorySelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from "react";
import {ProductCategoryType} from "../../../models";
import {FaTimes} from "react-icons/fa";
import {PageNation} from "../../application/PageNation.tsx";

interface ProductCategorySelectProps {
handleSelect: () => void;
}

export const ProductCategorySelectView: React.FC<ProductCategorySelectProps> = ({handleSelect}) => {
return (
<div className="collection-view-object-container">
<div className="collection-view-container">
<div className="collection-view-header">
<div className="single-view-header-item">
<h2 className="single-view-title">商品分類</h2>
</div>
</div>
<div className="collection-view-content">
<div className="button-container">
<button className="action-button" onClick={handleSelect} id="select-product-category">選択
</button>
</div>
</div>
</div>
</div>
)
}

interface ProductCategoryCollectionSelectProps {
productCategories: ProductCategoryType[];
handleSelect: (product: ProductCategoryType) => void;
handleClose: () => void;
pageNation: any; // 適切な型を使用してください
fetchProductCategories: () => void;
}

export const ProductCategoryCollectionSelectView: React.FC<ProductCategoryCollectionSelectProps> = ({
productCategories,
handleSelect,
handleClose,
pageNation,
fetchProductCategories
}) => {
return (
<div className="collection-view-object-container">
<div className="collection-view-container">
<button className="close-modal-button" onClick={handleClose}>
<FaTimes aria-hidden="true"/>
</button>
<div className="collection-view-header">
<div className="single-view-header-item">
<h2 className="single-view-title">商分類品</h2>
</div>
</div>
<div className="collection-view-content">
<div className="collection-object-container-modal">
<ul className="collection-object-list">
{productCategories.map(productCategory => (
<li className="collection-object-item" key={productCategory.productCategoryCode.value}>
<div className="collection-object-item-content" data-id={productCategory.productCategoryCode.value}>
<div className="collection-object-item-content-details">商品分類コード</div>
<div
className="collection-object-item-content-name">{productCategory.productCategoryCode.value}</div>
</div>
<div className="collection-object-item-content" data-id={productCategory.productCategoryCode.value}>
<div className="collection-object-item-content-details">商品分類名</div>
<div
className="collection-object-item-content-name">{productCategory.productCategoryName}</div>
</div>
<div className="collection-object-item-actions" data-id={productCategory.productCategoryCode.value}>
<button className="action-button" onClick={() => handleSelect(productCategory)} id="select-product">選択</button>
</div>
</li>
))}
</ul>
</div>
</div>
<PageNation pageNation={pageNation} callBack={fetchProductCategories}/>
</div>
</div>
);
};

0 comments on commit 720a3c4

Please sign in to comment.