From 2779e85226c6532a0ac63c9ff39b9f9e1a7f27a2 Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 10:52:04 +0900 Subject: [PATCH 01/21] =?UTF-8?q?=E6=96=99=E7=90=86=E5=90=8D=E3=82=92?= =?UTF-8?q?=E7=A9=BA=E6=AC=84=E3=81=AB=E3=81=97=E3=81=9F=E6=99=82=E3=81=AE?= =?UTF-8?q?=E4=B8=8D=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddRecipe.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index 2618fda..e96a779 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -43,6 +43,8 @@ const AddRecipe: React.FC = () => { const navigate = useNavigate(); + // 編集時,既存情報を読み込んだかどうか + const [recipeLoaded, setRecipeLoaded] = useState(false); // 料理名,説明 const [recipeName, setRecipeName] = useState(''); const [recipeSummary, setRecipeSummary] = useState(''); @@ -60,12 +62,13 @@ const AddRecipe: React.FC = () => { const [editingItemIdx, setEditingItemIdx] = useState(0); const loadRecipe = async () => { - if (recipeId && !recipeName) { + if (recipeId && !recipeLoaded) { const recipe = await recipeApi.getById(recipeId); console.log('loaded recipe=', recipe) setRecipeName(recipe.recipeName) setRecipeSummary(recipe.summary) setItems(recipe.stuffAndAmountArray) + setRecipeLoaded(true) } } @@ -122,7 +125,7 @@ const AddRecipe: React.FC = () => { }, []); return ( - (recipeId && !recipeName) + (recipeId && !recipeLoaded) ?

読み込み中...

: From 54b9539c0f3de3cf13500d56e5c0b20b204ced70 Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 11:17:58 +0900 Subject: [PATCH 02/21] =?UTF-8?q?=E3=83=AC=E3=82=B7=E3=83=94=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E6=99=82=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddRecipe.tsx | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index e96a779..72ca041 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -84,23 +84,28 @@ const AddRecipe: React.FC = () => { return false; } - if (!recipeId) { - // 新規追加 - const response = await recipeApi.addRecipe({ + try { + if (!recipeId) { + // 新規追加 + const response = await recipeApi.addRecipe({ + recipeName, + summary: recipeSummary, + stuffAndAmountArray: items, + }) + return response.recipeId; + } + + const response = await recipeApi.updateRecipe({ + recipeId, recipeName, summary: recipeSummary, stuffAndAmountArray: items, }) - return response.recipeId; + } catch { + alert('レシピの送信に失敗しました。既に同じ名前の料理が存在する可能性があります。'); + return false; } - const response = await recipeApi.updateRecipe({ - recipeId, - recipeName, - summary: recipeSummary, - stuffAndAmountArray: items, - }) - return recipeId; } From 34d2487df86c12738be8b1449647e3c90d00720f Mon Sep 17 00:00:00 2001 From: "akito.nishiwaki" Date: Fri, 13 Jun 2025 11:47:24 +0900 Subject: [PATCH 03/21] =?UTF-8?q?=E5=9C=A8=E5=BA=AB=E8=BF=BD=E5=8A=A0?= =?UTF-8?q?=E3=81=AE=E3=82=AB=E3=83=AC=E3=83=B3=E3=83=80=E3=83=BC=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todoapp/service/StocksService.java | 4 ---- .../todoapp/service/ToBuysService.java | 22 +++++++++++++------ frontend/src/pages/StockPage.tsx | 12 ++++++++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/example/todoapp/service/StocksService.java b/backend/src/main/java/com/example/todoapp/service/StocksService.java index bd2dc19..51a142f 100644 --- a/backend/src/main/java/com/example/todoapp/service/StocksService.java +++ b/backend/src/main/java/com/example/todoapp/service/StocksService.java @@ -1,6 +1,5 @@ package com.example.todoapp.service; -import com.example.todoapp.dto.StockDTO; import com.example.todoapp.dto.AddStocksDTO; import com.example.todoapp.dto.UpdateStockRequest; import com.example.todoapp.model.Stocks; @@ -57,9 +56,6 @@ public class StocksService { } else { // 材料情報を取得 Optional existstuffs = stuffsRepository.findById(stock.getStuffId()); - if (existstuffs == null) { - throw new RuntimeException("材料がありません"); - } stuffs = existstuffs.get(); } diff --git a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java index 678aae6..4de730a 100644 --- a/backend/src/main/java/com/example/todoapp/service/ToBuysService.java +++ b/backend/src/main/java/com/example/todoapp/service/ToBuysService.java @@ -91,14 +91,22 @@ public class ToBuysService { stuff = optStuff.get(); } - ToBuys toBuys = new ToBuys(); - toBuys.setUser(user); - toBuys.setStuff(stuff); - toBuys.setAmount(toBuyDTO.getAmount()); - toBuys.setStore(toBuyDTO.getShop()); + Optional existingToBuy = toBuysRepository.findByUserAndStuff(user, stuff); - // データベースに保存 - return toBuysRepository.save(toBuys); + if (existingToBuy.isPresent()) { + // 存在する場合は数量を更新 + ToBuys existing = existingToBuy.get(); + existing.setAmount(existing.getAmount() + toBuyDTO.getAmount()); + return toBuysRepository.save(existing); + } else { + // 新しい材料を作成 + ToBuys toBuys = new ToBuys(); + toBuys.setUser(user); + toBuys.setStuff(stuff); + toBuys.setAmount(toBuyDTO.getAmount()); + toBuys.setStore(toBuyDTO.getShop()); + return toBuysRepository.save(toBuys); + } } diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 3379f18..2aa95ba 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -30,6 +30,14 @@ import { STOCK_ERRORS } from '../constants/errorMessages'; import DatePicker, { registerLocale } from 'react-datepicker'; import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート +// 日付をyyyy-MM-dd形式で返す関数 +const formatDateLocal = (date: Date) => { + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + return `${year}-${month}-${day}`; +}; + // 新規在庫の初期状態 const EMPTY_STOCK: Omit & { stuffId: number | null } & { newAddition: boolean } = { stuffId: null, @@ -494,7 +502,7 @@ const StockPage: React.FC = () => { popperClassName="custom-datepicker-popper" selected={newStock.buyDate ? new Date(newStock.buyDate) : null} onChange={(date) => - setNewStock({ ...newStock, buyDate: date ? date.toISOString().split('T')[0] : '' }) + setNewStock({ ...newStock, buyDate: date ? formatDateLocal(date) : '' }) } dateFormat="yyyy/MM/dd" customInput={ @@ -521,7 +529,7 @@ const StockPage: React.FC = () => { popperClassName="custom-datepicker-popper" selected={newStock.expDate ? new Date(newStock.expDate) : null} onChange={(date) => - setNewStock({ ...newStock, expDate: date ? date.toISOString().split('T')[0] : '' }) + setNewStock({ ...newStock, expDate: date ? formatDateLocal(date) : '' }) } dateFormat="yyyy/MM/dd" customInput={ From 00b6f7f1c74adc4a28d5bc718ada8e226eb3a9dc Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 13:04:58 +0900 Subject: [PATCH 04/21] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/MessageAlert.tsx | 29 ++++++++++++++++++++++ frontend/src/pages/AddRecipe.tsx | 31 ++++++++++++++++++++---- 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 frontend/src/components/MessageAlert.tsx diff --git a/frontend/src/components/MessageAlert.tsx b/frontend/src/components/MessageAlert.tsx new file mode 100644 index 0000000..7368571 --- /dev/null +++ b/frontend/src/components/MessageAlert.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Snackbar, Alert, AlertColor } from '@mui/material'; + +interface MessageAlertProps { + open: boolean; + message: string; + severity: AlertColor; // 'error' | 'warning' | 'info' | 'success' + onClose: (event?: React.SyntheticEvent | Event, reason?: string) => void; + duration?: number; +} + +const MessageAlert: React.FC = ({ + open, + message, + severity, + onClose, + duration = 6000, +}) => { + return ( + + + {message} + + + ); +}; + +export default MessageAlert; diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index 72ca041..2486d70 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -25,7 +25,8 @@ import { Select, FormControl, InputLabel, - ListItemIcon + ListItemIcon, + AlertColor } from '@mui/material'; import { Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, @@ -36,6 +37,7 @@ import { StuffAndCategoryAndAmount } from '../types/types'; import EditAmountDialog from '../components/EditAmountDialog'; import { recipeApi, toBuyApi } from '../services/api'; import { useNavigate, useParams } from 'react-router-dom'; +import MessageAlert from '../components/MessageAlert'; const AddRecipe: React.FC = () => { const { recipeId: recipeIdStr } = useParams(); @@ -43,6 +45,20 @@ const AddRecipe: React.FC = () => { const navigate = useNavigate(); + // メッセージ + const [_openMessage, _setOpenMessage] = useState(false); + const [_messageText, _setMessageText] = useState(''); + const [_messageType, _setMessageType] = useState('info'); + const _showMessage = (message: string, severity: AlertColor) => { + _setOpenMessage(true); + _setMessageText(message); + _setMessageType(severity); + } + const showErrorMessage = (message: string) => _showMessage(message, 'error'); + const showWarningMessage = (message: string) => _showMessage(message, 'warning'); + const showInfoMessage = (message: string) => _showMessage(message, 'info'); + const showSuccessMessage = (message: string) => _showMessage(message, 'success'); + // 編集時,既存情報を読み込んだかどうか const [recipeLoaded, setRecipeLoaded] = useState(false); // 料理名,説明 @@ -75,12 +91,12 @@ const AddRecipe: React.FC = () => { const handleSaveRecipe = async () => { if (!recipeName) { - alert('レシピ名が入力されていません!') + showErrorMessage('レシピ名が入力されていません!') return false; } if (!items.length) { - alert('材料が追加されていません!') + showErrorMessage('材料が追加されていません!') return false; } @@ -102,7 +118,7 @@ const AddRecipe: React.FC = () => { stuffAndAmountArray: items, }) } catch { - alert('レシピの送信に失敗しました。既に同じ名前の料理が存在する可能性があります。'); + showErrorMessage('レシピの送信に失敗しました。同じ料理名が存在する可能性があります。'); return false; } @@ -130,7 +146,10 @@ const AddRecipe: React.FC = () => { }, []); return ( - (recipeId && !recipeLoaded) + <> + _setOpenMessage(false)}> + + {(recipeId && !recipeLoaded) ?

読み込み中...

: @@ -237,6 +256,8 @@ const AddRecipe: React.FC = () => { }} /> + } + ); }; From 3a3296b0d20ad738cb5c75b4614aa260c4f7b31f Mon Sep 17 00:00:00 2001 From: "zhang.pengcheng" Date: Mon, 16 Jun 2025 13:15:22 +0900 Subject: [PATCH 05/21] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E3=81=97=E3=81=BE?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/todoapp/controller/ToBuysController.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java b/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java index 799d3f9..048c69f 100644 --- a/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java +++ b/backend/src/main/java/com/example/todoapp/controller/ToBuysController.java @@ -125,9 +125,6 @@ public class ToBuysController { }) .collect(Collectors.toList()); - // Map responseBody = new HashMap<>(); - // responseBody.put("tobuy_array", responseList); - return ResponseEntity.ok(responseList); } From 777fdc72af7516414f9a5ee4a4889055d7ae93f9 Mon Sep 17 00:00:00 2001 From: "Haru.Kusano" Date: Mon, 16 Jun 2025 13:30:17 +0900 Subject: [PATCH 06/21] =?UTF-8?q?=E3=83=9C=E3=83=88=E3=83=A0=E3=83=8A?= =?UTF-8?q?=E3=83=93=E3=82=B2=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=81=AE?= =?UTF-8?q?=E4=BD=9C=E6=88=90=EF=BC=86=E3=82=B5=E3=82=A4=E3=83=89=E3=83=90?= =?UTF-8?q?=E3=83=BC=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Layout.tsx | 102 ++++++++++------------------ frontend/src/pages/TaskListPage.tsx | 8 +-- 2 files changed, 40 insertions(+), 70 deletions(-) diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index fa90b27..10d255d 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -16,7 +16,10 @@ import { ListItemIcon, ListItemButton, Divider, - IconButton + IconButton, + BottomNavigation, + BottomNavigationAction, + Paper } from '@mui/material'; import { Menu as MenuIcon, @@ -24,6 +27,7 @@ import { Inventory as InventoryIcon, // テストページ用のアイコン Science as ScienceIcon, // 鈴木 SoupKitchen as SoupKitchenIcon, + ShoppingCart as ShoppingCartIcon } from '@mui/icons-material'; import { useNavigate, Outlet, useLocation } from 'react-router-dom'; @@ -31,6 +35,7 @@ const Layout: React.FC = () => { const navigate = useNavigate(); const location = useLocation(); const [drawerOpen, setDrawerOpen] = useState(false); + const [bottomNavi, setBottomNavi] = useState(1); /** * ログアウト処理を行うハンドラー関数 @@ -41,19 +46,9 @@ const Layout: React.FC = () => { navigate('/login'); }; - /** - * 画面遷移処理を行うハンドラー関数 - * 指定されたパスに遷移し、サイドメニューを閉じる - */ - const handleNavigate = (path: string) => { - navigate(path); - setDrawerOpen(false); - }; + - // 現在のパスに基づいてメニュー項目が選択状態かどうかを判定 - const isSelected = (path: string): boolean => { - return location.pathname === path; - }; + // メニューを開閉するハンドラー const toggleDrawer = () => { @@ -65,15 +60,6 @@ const Layout: React.FC = () => { {/* ヘッダー部分 - アプリ名とログアウトボタンを表示 */} - - - shopchop @@ -83,52 +69,36 @@ const Layout: React.FC = () => { - {/* サイドメニュー */} - setDrawerOpen(false)} - > - + { + setBottomNavi(newValue); + switch(newValue) { + case 0: + navigate('stock'); + break; + case 1: + navigate('tasks'); + break; + case 2: + navigate('recipeList'); + break; + } + // ここでルーティング処理などを行う + }} > - - handleNavigate('/tasks')} - selected={isSelected('/tasks')} - > - - - - {/* テストページへのリンクを追加 */} + } /> + } /> + } /> + + - {/* 在庫リストへのリンクを追加 */} - handleNavigate('/addRecipe')} - selected={isSelected('/addRecipe')} - > - - - - handleNavigate('/recipeList')} - selected={isSelected('/recipeList')} - > - - - - handleNavigate('/stock')} - selected={isSelected('/stock')} - > - - - - - - - {/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */} diff --git a/frontend/src/pages/TaskListPage.tsx b/frontend/src/pages/TaskListPage.tsx index 29082a3..7d8b59d 100644 --- a/frontend/src/pages/TaskListPage.tsx +++ b/frontend/src/pages/TaskListPage.tsx @@ -294,28 +294,28 @@ const TaskListPage: React.FC = () => { {/* 新規材料作成ボタン - 画面下部に固定表示 */} - + 材料のみ追加 setOpenAddToBuyDialog(true)} > {/*新規料理追加ボタン - 画面下部に固定表示 */} - + 料理から追加 { // setOpenAddToBuyDialog(true); navigate('/RecipeList'); From 3867bfb30628bf450a43f90fe048dc25a3c060d4 Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 13:34:51 +0900 Subject: [PATCH 07/21] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=82=B3=E3=83=B3=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=A8=E3=81=97=E3=81=A6=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Layout.tsx | 63 +++++++++++++++++++--- frontend/src/components/MessageContext.tsx | 17 ++++++ frontend/src/pages/AddRecipe.tsx | 20 ++----- 3 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 frontend/src/components/MessageContext.tsx diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index fa90b27..fc5a140 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -2,7 +2,7 @@ * アプリケーションの共通レイアウトを提供するコンポーネント * ヘッダー(AppBar)とメインコンテンツ領域を含む基本的なページ構造を定義 */ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { AppBar, Toolbar, @@ -16,7 +16,8 @@ import { ListItemIcon, ListItemButton, Divider, - IconButton + IconButton, + AlertColor } from '@mui/material'; import { Menu as MenuIcon, @@ -26,6 +27,8 @@ import { SoupKitchen as SoupKitchenIcon, } from '@mui/icons-material'; import { useNavigate, Outlet, useLocation } from 'react-router-dom'; +import { MessageContext } from './MessageContext'; +import MessageAlert from './MessageAlert'; const Layout: React.FC = () => { const navigate = useNavigate(); @@ -60,6 +63,40 @@ const Layout: React.FC = () => { setDrawerOpen(!drawerOpen); }; + // メッセージ表示 + + // ページ遷移後もメッセージを維持 + useEffect(() => { + const saved = sessionStorage.getItem('globalMessage'); + if (saved) { + const { message, severity } = JSON.parse(saved); + showMessage(message, severity); + } + }, []); + + const [msgOpen, setMsgOpen] = useState(false); + const [msgText, setMsgText] = useState(''); + const [msgType, setMsgType] = useState('info'); + + const showMessage = (msg: string, sev: AlertColor) => { + setMsgText(msg); + setMsgType(sev); + setMsgOpen(true); + sessionStorage.setItem('globalMessage', JSON.stringify({ message: msg, severity: sev })); + }; + + const showErrorMessage = (message: string) => showMessage(message, 'error'); + const showWarningMessage = (message: string) => showMessage(message, 'warning'); + const showInfoMessage = (message: string) => showMessage(message, 'info'); + const showSuccessMessage = (message: string) => showMessage(message, 'success'); + + const handleMsgClose = () => { + setMsgOpen(false); + setMsgText(''); + sessionStorage.removeItem('globalMessage'); + }; + + return ( {/* ヘッダー部分 - アプリ名とログアウトボタンを表示 */} @@ -103,16 +140,16 @@ const Layout: React.FC = () => { {/* テストページへのリンクを追加 */} - {/* 在庫リストへのリンクを追加 */} - handleNavigate('/addRecipe')} + {/* 在庫リストへのリンクを追加 */} + handleNavigate('/addRecipe')} selected={isSelected('/addRecipe')} > - handleNavigate('/recipeList')} + handleNavigate('/recipeList')} selected={isSelected('/recipeList')} > @@ -133,7 +170,17 @@ const Layout: React.FC = () => { {/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */} - {/* React Router の Outlet - 子ルートのコンポーネントがここにレンダリングされる */} + + + + {/* React Router の Outlet - 子ルートのコンポーネントがここにレンダリングされる */} + + diff --git a/frontend/src/components/MessageContext.tsx b/frontend/src/components/MessageContext.tsx new file mode 100644 index 0000000..599f2a5 --- /dev/null +++ b/frontend/src/components/MessageContext.tsx @@ -0,0 +1,17 @@ + +import React, { createContext, useContext } from 'react'; + +export interface MessageContextType { + showErrorMessage: (message: string) => void; + showWarningMessage: (message: string) => void; + showSuccessMessage: (message: string) => void; + showInfoMessage: (message: string) => void; +} + +export const MessageContext = createContext(undefined); + +export const useMessage = () => { + const context = useContext(MessageContext); + if (!context) throw new Error('useMessage must be used within MessageContext.Provider'); + return context; +}; diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index 2486d70..9a397dd 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -38,6 +38,7 @@ import EditAmountDialog from '../components/EditAmountDialog'; import { recipeApi, toBuyApi } from '../services/api'; import { useNavigate, useParams } from 'react-router-dom'; import MessageAlert from '../components/MessageAlert'; +import { useMessage } from '../components/MessageContext'; const AddRecipe: React.FC = () => { const { recipeId: recipeIdStr } = useParams(); @@ -45,20 +46,6 @@ const AddRecipe: React.FC = () => { const navigate = useNavigate(); - // メッセージ - const [_openMessage, _setOpenMessage] = useState(false); - const [_messageText, _setMessageText] = useState(''); - const [_messageType, _setMessageType] = useState('info'); - const _showMessage = (message: string, severity: AlertColor) => { - _setOpenMessage(true); - _setMessageText(message); - _setMessageType(severity); - } - const showErrorMessage = (message: string) => _showMessage(message, 'error'); - const showWarningMessage = (message: string) => _showMessage(message, 'warning'); - const showInfoMessage = (message: string) => _showMessage(message, 'info'); - const showSuccessMessage = (message: string) => _showMessage(message, 'success'); - // 編集時,既存情報を読み込んだかどうか const [recipeLoaded, setRecipeLoaded] = useState(false); // 料理名,説明 @@ -77,6 +64,9 @@ const AddRecipe: React.FC = () => { const [editingItem, setEditingItem] = useState(emptyItem); const [editingItemIdx, setEditingItemIdx] = useState(0); + // エラーメッセージ表示 + const { showErrorMessage } = useMessage(); + const loadRecipe = async () => { if (recipeId && !recipeLoaded) { const recipe = await recipeApi.getById(recipeId); @@ -147,8 +137,6 @@ const AddRecipe: React.FC = () => { return ( <> - _setOpenMessage(false)}> - {(recipeId && !recipeLoaded) ?

読み込み中...

: From be711eccea66002fadab4178960cac1f682333d6 Mon Sep 17 00:00:00 2001 From: "Yuna.Suzuki" Date: Mon, 16 Jun 2025 13:41:18 +0900 Subject: [PATCH 08/21] =?UTF-8?q?=E3=82=B9=E3=83=9E=E3=83=9B=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C=E3=81=97=E3=81=9F=E7=94=BB=E9=9D=A2=E8=A8=AD?= =?UTF-8?q?=E8=A8=88=E3=80=81=E7=B7=A8=E9=9B=86=E7=94=BB=E9=9D=A2=E3=81=A7?= =?UTF-8?q?=E3=81=AE=E8=A9=B3=E7=B4=B0=E8=A1=A8=E7=A4=BA=E3=80=81=E7=B7=A8?= =?UTF-8?q?=E9=9B=86=E3=83=80=E3=82=A4=E3=82=A2=E3=83=AD=E3=82=B0=E3=81=A7?= =?UTF-8?q?=E3=81=AE=E3=82=AB=E3=83=AC=E3=83=B3=E3=83=80=E3=83=BC=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=81=BE=E3=81=97?= =?UTF-8?q?=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/StockPage.tsx | 104 +++++++++++++++++++++++-------- 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 2aa95ba..363230e 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -146,7 +146,7 @@ const StockPage: React.FC = () => { }; /** - * カテゴリー選択?? + * カテゴリー選択 */ const onChangeCategory = async (category: string) => { setNewStock({ ...newStock, category }) @@ -270,8 +270,6 @@ const StockPage: React.FC = () => { 食材名 数量 - 購入価格 - 購入日 消費・賞味期限 @@ -290,8 +288,6 @@ const StockPage: React.FC = () => { > {stock.stuffName} {stock.amount} - {stock.price} - {formatDate(stock.buyDate)} @@ -330,6 +326,54 @@ const StockPage: React.FC = () => { value={editStock.price} onChange={handleChange} /> + {/* 購入日・消費期限を横並びに */} + + {/* 購入日 */} + { + if (editStock) { + setEditStock({ + ...editStock, + buyDate: date ? formatDateLocal(date) : '', + }); + } + }} + dateFormat="yyyy/MM/dd" + customInput={ + + } + isClearable + /> + {/* 消費・賞味期限 */} + { + if (editStock) { + setEditStock({ + ...editStock, + expDate: date ? formatDateLocal(date) : '', + }); + } + }} + dateFormat="yyyy/MM/dd" + customInput={ + + } + isClearable + /> + + {/* 以前の書き方 { name="expDate" value={editStock.expDate} onChange={handleChange} - /> - - - - + /> */} + + + + )} @@ -375,13 +416,26 @@ const StockPage: React.FC = () => { <> 【{selectedRow.stuffName}】を削除します。 ⚠️ 注意: 削除すると復元できません。 - - + + + + + )} @@ -555,7 +609,7 @@ const StockPage: React.FC = () => { {/* 在庫の食材編集ボタン(全テーブル共通) */} {/* 在庫の食材削除ボタン (全テーブル共通) */} From 69a7ede672a5c1cb4786837be0a5eb06bbcbdf8b Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 13:42:29 +0900 Subject: [PATCH 09/21] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E6=B6=88=E5=8E=BB?= =?UTF-8?q?=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index fc5a140..01b985e 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -92,7 +92,7 @@ const Layout: React.FC = () => { const handleMsgClose = () => { setMsgOpen(false); - setMsgText(''); + // setMsgText(''); // ここで空にすると,メッセージが消えるアニメーションが始まる時点で文字が消えてしまう sessionStorage.removeItem('globalMessage'); }; From 81ce6c95306208b976adbd300bb34b4a90d826bc Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 13:42:40 +0900 Subject: [PATCH 10/21] =?UTF-8?q?=E6=88=90=E5=8A=9F=E6=99=82=E3=81=AB?= =?UTF-8?q?=E3=82=82=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddRecipe.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index 9a397dd..a8fccef 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -65,7 +65,7 @@ const AddRecipe: React.FC = () => { const [editingItemIdx, setEditingItemIdx] = useState(0); // エラーメッセージ表示 - const { showErrorMessage } = useMessage(); + const { showErrorMessage, showSuccessMessage } = useMessage(); const loadRecipe = async () => { if (recipeId && !recipeLoaded) { @@ -117,7 +117,7 @@ const AddRecipe: React.FC = () => { const handleSubmit = async () => { const recipeId = await handleSaveRecipe(); - // alert('レシピが保存されました!'); + showSuccessMessage('レシピが保存されました!'); if (!recipeId) return; navigate('/recipeList'); } @@ -126,7 +126,7 @@ const AddRecipe: React.FC = () => { const recipeId = await handleSaveRecipe(); if (!recipeId) return false; await toBuyApi.addByRecipe(recipeId); - // alert('レシピが保存されて買うものリストに追加されました!'); + showSuccessMessage('レシピが保存されて買うものリストに追加されました!'); navigate('/tasks'); } From c615c88d2db5955aa12823482bd43ce520e5642b Mon Sep 17 00:00:00 2001 From: "Yuna.Suzuki" Date: Mon, 16 Jun 2025 13:57:18 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=E5=BE=AE=E8=AA=BF=E6=95=B4=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/StockPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 363230e..07206df 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -608,7 +608,8 @@ const StockPage: React.FC = () => { {/* 在庫の食材編集ボタン(全テーブル共通) */} - From 7da7bb32738ed98907d678f738af884d3340a9c0 Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 14:02:44 +0900 Subject: [PATCH 12/21] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E8=A1=A8=E7=A4=BA=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddRecipe.tsx | 2 +- frontend/src/pages/RecipeList.tsx | 5 ++++- frontend/src/pages/StockPage.tsx | 7 +++++-- frontend/src/pages/TaskListPage.tsx | 9 +++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index a8fccef..798d39b 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -117,8 +117,8 @@ const AddRecipe: React.FC = () => { const handleSubmit = async () => { const recipeId = await handleSaveRecipe(); - showSuccessMessage('レシピが保存されました!'); if (!recipeId) return; + showSuccessMessage('レシピが保存されました!'); navigate('/recipeList'); } diff --git a/frontend/src/pages/RecipeList.tsx b/frontend/src/pages/RecipeList.tsx index 42826db..ac93704 100644 --- a/frontend/src/pages/RecipeList.tsx +++ b/frontend/src/pages/RecipeList.tsx @@ -31,11 +31,14 @@ import { SoupKitchen as SoupKitchenIcon } from '@mui/icons-material'; import { ToBuy, Stuff, RecipeWithId, RecipeDetail } from '../types/types'; +import { useMessage } from '../components/MessageContext'; const RecipeList: React.FC = () => { const navigate = useNavigate(); // 料理リストの料理名を格納する配列 + const { showErrorMessage } = useMessage(); + // すべての料理リスト const [allRecipes, setAllRecipes] = useState(); @@ -48,7 +51,7 @@ const RecipeList: React.FC = () => { const recipes = await recipeApi.getAllRecipes(); setAllRecipes(recipes); } catch (error) { - alert("レシピの取得に失敗しました."); + showErrorMessage("レシピの取得に失敗しました。"); // console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); } }; diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 2aa95ba..7688049 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -29,6 +29,7 @@ import { import { STOCK_ERRORS } from '../constants/errorMessages'; import DatePicker, { registerLocale } from 'react-datepicker'; import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート +import { useMessage } from '../components/MessageContext'; // 日付をyyyy-MM-dd形式で返す関数 const formatDateLocal = (date: Date) => { @@ -72,6 +73,8 @@ const StockPage: React.FC = () => { // 在庫の編集状態 const [editStock, setEditStock] = useState(null); + const { showWarningMessage } = useMessage(); + // コンポーネントマウント時にタスク一覧を取得 useEffect(() => { fetchStocks(); @@ -196,7 +199,7 @@ const StockPage: React.FC = () => { setEditStock({ ...selectedRow }); setIsEditOpen(true); } else { - alert("編集する食材を選択してください。"); + showWarningMessage("編集する食材を選択してください。"); } }; // 変更を適用 @@ -248,7 +251,7 @@ const StockPage: React.FC = () => { if (selectedRow) { setIsDeleteOpen(true); } else { - alert("削除する食材を選択してください。"); + showWarningMessage("削除する食材を選択してください。"); } }; /** 削除ダイアログを閉じる */ diff --git a/frontend/src/pages/TaskListPage.tsx b/frontend/src/pages/TaskListPage.tsx index 74b756d..0a20838 100644 --- a/frontend/src/pages/TaskListPage.tsx +++ b/frontend/src/pages/TaskListPage.tsx @@ -31,6 +31,7 @@ import AddStuffAmountDialog from '../components/AddStuffAmountDialog'; import BuyDialog from '../components/BuyDialog'; import { useNavigate } from 'react-router-dom'; import DatePicker from 'react-datepicker'; +import { useMessage } from '../components/MessageContext'; //import { FaCarrot } from "react-icons/fa6"; //エラー起きる いったん保留 @@ -91,7 +92,7 @@ const TaskListPage: React.FC = () => { shop: undefined, }); - + const { showErrorMessage } = useMessage(); // コンポーネントマウント時にタスク一覧を取得 useEffect(() => { @@ -149,7 +150,7 @@ const TaskListPage: React.FC = () => { const handleAddNewToBuy = async () => { try { if (isNaN(newToBuy.amount)) { - console.log('数量が正しくありません.'); + showErrorMessage('数量が正しくありません.'); return; } @@ -171,7 +172,7 @@ const TaskListPage: React.FC = () => { const handleUpdateNewToBuy = async () => { try { if (isNaN(editingItem.amount)) { - console.log('数量が正しくありません.'); + showErrorMessage('数量が正しくありません.'); return; } @@ -195,7 +196,7 @@ const TaskListPage: React.FC = () => { console.log("newPrice:", newStock.price) console.log("parsedPrice: ", parsedPrice) if (isNaN(parsedPrice)) { - alert('入力が無効です') + showErrorMessage('価格が正しく入力されていません。') return //setNewStock({ ...newStock, price: parsedPrice }); } From 0fb3e0c21ac2ae25d8db1ad8be9eba67672f762e Mon Sep 17 00:00:00 2001 From: "Yuna.Suzuki" Date: Mon, 16 Jun 2025 14:06:04 +0900 Subject: [PATCH 13/21] =?UTF-8?q?=E5=BE=AE=E8=AA=BF=E6=95=B4=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/StockPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 07206df..48fffee 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -452,6 +452,7 @@ const StockPage: React.FC = () => { + {/* */} {/* 在庫の食材追加ボタン */} + + + )} + + + {/* 数量変更ダイアログ */} Date: Mon, 16 Jun 2025 16:17:10 +0900 Subject: [PATCH 17/21] =?UTF-8?q?=E3=83=BB=E3=83=86=E3=83=BC=E3=83=96?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E8=A1=8C=E9=81=B8=E6=8A=9E=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=81=A8=E3=81=8D=E3=81=AB=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=83=9C=E3=83=83=E3=82=AF=E3=82=B9=E3=82=92=E6=8A=BC=E3=81=99?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= =?UTF-8?q?=20=E3=83=BB=E8=BF=BD=E5=8A=A0=E3=83=9C=E3=82=BF=E3=83=B3?= =?UTF-8?q?=E3=81=AA=E3=81=A9=E3=82=92=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=81=97=E3=81=A6=E3=82=82=E4=B8=8A=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E3=81=AB=E3=81=AA=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F=20=E3=83=BB=E7=B7=A8=E9=9B=86?= =?UTF-8?q?=E3=81=A7=E6=95=B0=E9=87=8F=E3=81=A8=E8=B3=BC=E5=85=A5=E9=87=91?= =?UTF-8?q?=E9=A1=8D=E3=81=AB=E8=B2=A0=E3=81=AE=E5=80=A4=E3=81=8C=E5=85=A5?= =?UTF-8?q?=E3=82=89=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=E3=81=97?= =?UTF-8?q?=E3=81=BE=E3=81=97=E3=81=9F=20=E3=83=BB=E7=B7=A8=E9=9B=86?= =?UTF-8?q?=E3=81=A7=E6=95=B0=E9=87=8F=E3=81=AB0=E3=82=92=E5=85=A5?= =?UTF-8?q?=E3=82=8C=E3=81=9F=E3=82=89=E5=89=8A=E9=99=A4=E3=83=80=E3=82=A4?= =?UTF-8?q?=E3=82=A2=E3=83=AD=E3=82=B0=E3=81=AB=E9=A3=9B=E3=81=B6=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/StockPage.tsx | 129 ++++++++++++++++++------------- 1 file changed, 76 insertions(+), 53 deletions(-) diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index 48fffee..ca18564 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -177,18 +177,23 @@ const StockPage: React.FC = () => { const handleOpenAdd = () => { setIsAddOpen(true); }; - /** 削除ダイアログを閉じる */ + /** 追加ダイアログを閉じる */ const handleCloseAdd = () => { setIsAddOpen(false); }; /** - * セルを選択する関数. 再度クリックで選択解除 + * セルを選択する関数. 再度クリックで選択解除 → 行選択ではなくチェックボックスにしたため不要 */ - const handleRowClick = (stock: Stock) => { + // const handleRowClick = (stock: Stock) => { + // setSelectedRow(prev => (prev?.stockId === stock.stockId ? null : stock)); + // }; + // チェックボックス切り替え + const handleCheckboxChange = (stock: Stock) => { setSelectedRow(prev => (prev?.stockId === stock.stockId ? null : stock)); }; + /** 編集ボタンを押したときにダイアログを開く */ // ダイアログを開く際に `selectedRow` の値を `editStock` にセット const handleOpenEdit = () => { @@ -199,26 +204,35 @@ const StockPage: React.FC = () => { alert("編集する食材を選択してください。"); } }; - // 変更を適用 + // 変更を適用. 数量に0を入力したとき、削除ダイアログに飛ぶ機能を追加 const handleApplyChanges = async () => { - if (editStock) { - try { - await handleUpdateStock( - editStock.stockId, - Number(editStock.amount), - Number(editStock.price), - editStock.buyDate, - editStock.expDate - ); - - setSelectedRow(editStock); // `selectedRow` を更新して変更を即時反映 - fetchStocks(); // 最新データを取得してテーブルに反映 - setSelectedRow(null); // セルの選択を解除 - } catch (error) { - console.error(`${STOCK_ERRORS.UPDATE_FAILED}:`, error); + if (!editStock) return; + + try { + if (Number(editStock.amount) === 0) { + // 数量が 0 の場合は削除処理へ誘導 + setIsEditOpen(false); // 編集ダイアログを閉じる + setSelectedRow(editStock); // 削除対象をセット + setIsDeleteOpen(true); // 削除ダイアログを開く + return; } + + await handleUpdateStock( + editStock.stockId, + Number(editStock.amount), + Number(editStock.price), + editStock.buyDate, + editStock.expDate + ); + + setSelectedRow(editStock); // 更新後に選択行を反映 + fetchStocks(); // 最新データを取得 + setSelectedRow(null); // 選択解除 + } catch (error) { + console.error(`${STOCK_ERRORS.UPDATE_FAILED}:`, error); } - setIsEditOpen(false); // ダイアログを閉じる + + setIsEditOpen(false); // 編集ダイアログを閉じる }; // ダイアログを開く際に `selectedRow` の値を `editStock` にコピー @@ -229,15 +243,25 @@ const StockPage: React.FC = () => { }, [selectedRow]); // `selectedRow` が変更されたら `editStock` に反映 // テキストフィールドの変更を検知 + // 負の値を入力できないように書き換え const handleChange = (event: React.ChangeEvent) => { + const { name, value } = event.target; + + // 数値項目に対して負の値をブロック + const numericFields = ['amount', 'price']; + if (numericFields.includes(name) && Number(value) < 0) { + return; // 無視して更新しない + } + if (editStock) { setEditStock({ ...editStock, - [event.target.name]: event.target.value, + [name]: value, }); } }; + /** 編集ダイアログを閉じる */ const handleCloseEdit = () => { setIsEditOpen(false); @@ -268,6 +292,7 @@ const StockPage: React.FC = () => { + 食材名 数量 消費・賞味期限 @@ -275,6 +300,7 @@ const StockPage: React.FC = () => { {filteredStocks.map(stock => { + const isSelected = selectedRow?.stockId === stock.stockId; const today = new Date(); const expDate = new Date(stock.expDate); const timeDiff = expDate.getTime() - today.getTime(); @@ -283,9 +309,17 @@ const StockPage: React.FC = () => { return ( handleRowClick(stock)} - style={{ backgroundColor: selectedRow?.stockId === stock.stockId ? "yellow" : "white", cursor: "pointer" }} + sx={{ + backgroundColor: isSelected ? 'yellow' : 'white', + }} + > + + handleCheckboxChange(stock)} + /> + {stock.stuffName} {stock.amount} { isClearable /> - {/* 以前の書き方 - - */} {/* 新規タスク作成ダイアログ */} - setIsAddOpen(false)} disableScrollLock={true}> + 在庫に食材を追加 @@ -570,15 +601,6 @@ const StockPage: React.FC = () => { isClearable //withPortal // ← 他の文字との重なり対策 /> - {/* - setNewStock({ ...newStock, buyDate: e.target.value })} - /> - */} {/* 消費・賞味期限入力フィールド */} { {/* 在庫の食材編集ボタン(全テーブル共通) */} From ee33a0a82a6f9bf1e592b6567c63dc5e8d032b80 Mon Sep 17 00:00:00 2001 From: "Yuna.Suzuki" Date: Mon, 16 Jun 2025 16:36:41 +0900 Subject: [PATCH 18/21] =?UTF-8?q?=E3=81=9D=E3=82=82=E3=81=9D=E3=82=82"-"?= =?UTF-8?q?=E3=82=92=E5=85=A5=E5=8A=9B=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/StockPage.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frontend/src/pages/StockPage.tsx b/frontend/src/pages/StockPage.tsx index ca18564..76f9352 100644 --- a/frontend/src/pages/StockPage.tsx +++ b/frontend/src/pages/StockPage.tsx @@ -350,6 +350,13 @@ const StockPage: React.FC = () => { type="number" value={editStock.amount} onChange={handleChange} + inputProps={{ min: 0 }} + onKeyDown={(e) => { + if (e.key === '-' || e.key === 'e' || e.key === 'E') { + e.preventDefault(); + } + }} + /> { type="number" value={editStock.price} onChange={handleChange} + inputProps={{ min: 0 }} + onKeyDown={(e) => { + if (e.key === '-' || e.key === 'e' || e.key === 'E') { + e.preventDefault(); + } + }} + /> {/* 購入日・消費期限を横並びに */} From ab815ba94e716fb238d013a575d0f89e63d64045 Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 16:41:11 +0900 Subject: [PATCH 19/21] =?UTF-8?q?=E3=82=B9=E3=83=9E=E3=83=9B=E5=8B=95?= =?UTF-8?q?=E4=BD=9C=E7=A2=BA=E8=AA=8D=E7=94=A8=E3=81=AE=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=82=A8=E3=83=B3=E3=83=89=E8=A8=AD=E5=AE=9A=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/application-localfwd.yml | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 backend/src/main/resources/application-localfwd.yml diff --git a/backend/src/main/resources/application-localfwd.yml b/backend/src/main/resources/application-localfwd.yml new file mode 100644 index 0000000..536f15b --- /dev/null +++ b/backend/src/main/resources/application-localfwd.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: jdbc:postgresql://localhost:5432/${LOCAL_DB_NAME} + driver-class-name: org.postgresql.Driver + username: ${LOCAL_DB_USER} + password: ${LOCAL_DB_PASSWORD} + jpa: + database-platform: org.hibernate.dialect.PostgreSQLDialect + properties: + hibernate: + jdbc: + lob: + non_contextual_creation: true + +server: + address: 0.0.0.0 + port: 8080 + +cors: + allowed-origins: http://${WIN_IP}:3000 \ No newline at end of file From 6ea97add080950ef7b5dc0b3c27f76fc779f254a Mon Sep 17 00:00:00 2001 From: "Masaharu.Kato" Date: Mon, 16 Jun 2025 17:32:01 +0900 Subject: [PATCH 20/21] =?UTF-8?q?=E3=83=9C=E3=83=88=E3=83=A0=E3=83=8A?= =?UTF-8?q?=E3=83=93=E3=82=B2=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=83=90?= =?UTF-8?q?=E3=83=BC=E3=81=AB=E8=A2=AB=E3=82=89=E3=81=AA=E3=81=84=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=AE=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/AddRecipe.tsx | 2 +- frontend/src/pages/DishList.tsx | 7 ++++--- frontend/src/pages/RecipeList.tsx | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index 798d39b..1000a0e 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -215,7 +215,7 @@ const AddRecipe: React.FC = () => { -
+
-
-
-
+