diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d4d6caf..82bce23 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -93,6 +93,7 @@ const App: React.FC = () => { } /> + }> {/* ルートパスへのアクセスはタスク一覧にリダイレクト */} diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index eb3612f..4ac785b 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -22,6 +22,7 @@ import { Menu as MenuIcon, ListAlt as ListAltIcon, Inventory as InventoryIcon, // テストページ用のアイコン + Science as ScienceIcon, // 鈴木 } from '@mui/icons-material'; import { useNavigate, Outlet, useLocation } from 'react-router-dom'; @@ -100,6 +101,8 @@ const Layout: React.FC = () => { {/* テストページへのリンクを追加 */} + + {/* 在庫リストへのリンクを追加 */} handleNavigate('/stock')} selected={isSelected('/stock')} diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 8de8bd9..e305d3b 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -2,15 +2,273 @@ * テストページコンポーネント * 白紙の状態で表示されるテスト用のページ */ -import React from 'react'; -import { Box } from '@mui/material'; +import React, { useState, useEffect } from 'react'; +import { stockApi } from '../services/api'; +import { Stock } from '../types/types'; +import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper } from "@mui/material"; +import { + Container, + Typography, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + TextField, + Button, + Box, + +} from '@mui/material'; +import { TASK_ERRORS } from '../constants/errorMessages'; +import CategoryDropDown from "../components/CategoryDropDown"; const StockPage: React.FC = () => { - return ( - - {/* 白紙のページ - 何も表示しない */} - - ); + + const [stocks, setStocks] = useState([]); + // 在庫編集ダイアログの表示状態 + const [openDialog, setOpenDialog] = useState(false); + + // コンポーネントマウント時にタスク一覧を取得 + useEffect(() => { + fetchStocks(); + }, []); + + /** + * APIからタスク一覧を取得する関数 + * 取得したタスクをstate(tasks)に設定 + */ + const fetchStocks = async () => { + try { + const stocks = await stockApi.getStocks(); + setStocks(stocks.stock_array); + } catch (error) { + console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); + } + }; + + /** + * 文字列(ISO 8601形式)をyyyy/MM/ddに変換する関数 + */ + const formatDate = (isoString: string): string => { + const date = new Date(isoString); + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); // 月は0始まりなので+1 + const day = date.getDate().toString().padStart(2, "0"); + return `${year}/${month}/${day}`; + }; + /* Date型をyyyy/MM/ddに変換する関数 + const formatDate = (date: Date): string => { + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); // 月は0始まりなので+1 + const day = date.getDate().toString().padStart(2, "0"); + return `${year}/${month}/${day}`; + }; + */ + + return ( + + + 在庫一覧 + + + {/* タスク編集ボタン */} + + + {/* タスク削除ボタン */} + + + + 乳製品 + + {/* 乳製品一覧表示エリア - 青い背景のコンテナ */} +
+ + {/* 要素が無かったら表示しない */} + {stocks.filter(stock => stock.category === "乳製品").length === 0 ? null : ( + + + + + 食材名 + 数量 + 購入価格 + 賞味・消費期限 + 購入日 + + + + {stocks + .filter(stock => stock.category == "乳製品") // 乳製品だけ抽出 + .map(stock => ( + + {stock.stuff_name} + {stock.amount} + {stock.price} + {formatDate(stock.exp_date)} + {formatDate(stock.buy_date)} + + ))} + +
+
+ )} +
+ + + 肉・魚 + + {/* 肉・魚一覧表示エリア - 青い背景のコンテナ */} +
+ + {stocks.filter(stock => stock.category == "肉" || stock.category == "魚").length === 0 ? null : ( + + + + + 食材名 + 数量 + 購入価格 + 賞味・消費期限 + 購入日 + + + + {stocks + .filter(stock => stock.category == "肉" || stock.category == "魚") // 肉と魚だけ抽出 + .map(stock => ( + + {stock.stuff_name} + {stock.amount} + {stock.price} + {formatDate(stock.exp_date)} + {formatDate(stock.buy_date)} + + ))} + +
+
+ )} + +
+ + + 野菜 + + {/* 野菜一覧表示エリア - 青い背景のコンテナ */} +
+ {stocks.filter(stock => stock.category === "野菜").length === 0 ? null : ( + + + + + 食材名 + 数量 + 購入価格 + 賞味・消費期限 + 購入日 + + + + {stocks + .filter(stock => stock.category == "野菜") // 野菜だけ抽出 + .map(stock => ( + + {stock.stuff_name} + {stock.amount} + {stock.price} + {formatDate(stock.exp_date)} + {formatDate(stock.buy_date)} + + ))} + +
+
+ )} +
+ + + 調味料 + + {/* 調味料一覧表示エリア - 青い背景のコンテナ */} +
+ {stocks.filter(stock => stock.category === "調味料").length === 0 ? null : ( + + + + + 食材名 + 数量 + 購入価格 + 賞味・消費期限 + 購入日 + + + + {stocks + .filter(stock => stock.category == "調味料") // 調味料だけ抽出 + .map(stock => ( + + {stock.stuff_name} + {stock.amount} + {stock.price} + {formatDate(stock.exp_date)} + {formatDate(stock.buy_date)} + + ))} + +
+
+ )} +
+ + + その他 + + {/* その他一覧表示エリア - 青い背景のコンテナ */} +
+ {stocks.filter(stock => stock.category === "その他").length === 0 ? null : ( + + + + + 食材名 + 数量 + 購入価格 + 賞味・消費期限 + 購入日 + + + + {stocks + .filter(stock => stock.category == "その他") // その他だけ抽出 + .map(stock => ( + + {stock.stuff_name} + {stock.amount} + {stock.price} + {formatDate(stock.exp_date)} + {formatDate(stock.buy_date)} + + ))} + +
+
+ )} +
+
+ ); }; export default StockPage; \ No newline at end of file diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index a77a601..5853f7c 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -3,7 +3,7 @@ * バックエンドAPIとの通信を担当するモジュール * 認証、タスク管理などの機能を提供 */ -import { LoginCredentials, RegisterCredentials, AuthResponse, Task, ToBuy, Stuff } from '../types/types'; +import { LoginCredentials, RegisterCredentials, AuthResponse, Task, ToBuy, Stuff, Stock } from '../types/types'; import { AUTH_ERRORS, TASK_ERRORS } from '../constants/errorMessages'; // APIのベースURL - 環境変数から取得するか、デフォルト値を使用 @@ -89,8 +89,8 @@ export const authApi = { */ export const toBuyApi = { /** - * 全タスクを取得 - * @returns タスク一覧 + * 全買うものリストを取得 + * @returns 買うものリスト一覧 */ getToBuys: async (): Promise<{ "tobuy_array": ToBuy[] }> => { // const response = await fetch(`${API_BASE_URL}/api/tobuy/get`, { @@ -214,6 +214,54 @@ export const stuffApi = { } +export const stockApi = { + /** + * 全在庫リストを取得 + * @returns 買在庫リスト一覧 + */ + getStocks: async (): Promise<{ "stock_array": Stock[] }> => { + // const response = await fetch(`${API_BASE_URL}/api/tobuy/get`, { + // headers: getHeaders(), // 認証トークンを含むヘッダー + // }); + + // if (!response.ok) { + // throw new Error(TASK_ERRORS.FETCH_FAILED); + // } + + // return response.json(); + + return { + "stock_array": [ + { + "stock_id": 1, + "stuff_id": 10, + "stuff_name": "豚肉", + "amount": 100, + "price": 200, + "buy_date": "2025-05-18T09:00:00.000Z", + "last_update": "2025-05-18T09:00:00.000Z", + "exp_date": "2025-05-19T10:15:00.000Z", + "category": "肉" + }, + { + "stock_id": 2, + "stuff_id": 1, + "stuff_name": "トマト", + "amount": 10, + "price": 200, + "buy_date": "2025-05-18T09:00:00.000Z", + "last_update": "2025-05-18T09:00:00.000Z", + "exp_date": "2025-05-19T10:15:00.000Z", + "category": "野菜" + } + ] + } + + + }, +} + + /** * (サンプル,実際には不要) * タスク管理関連のAPI機能を提供するオブジェクト diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts index 8d6a10c..76c645d 100644 --- a/frontend/src/types/types.ts +++ b/frontend/src/types/types.ts @@ -35,6 +35,22 @@ export interface Stuff { category: string, } +/** + * タスク情報を表す型定義 + * タスクの基本情報と状態を管理 + */ +export interface Stock { + stock_id: number, + stuff_id: number, + stuff_name: string, + amount: number, + price: number, + buy_date: string, + last_update: string, + exp_date: string, + category: string, +} + /** * ユーザー情報を表す型定義 * ユーザーの基本情報を管理