diff --git a/frontend/src/constants/errorMessages.ts b/frontend/src/constants/errorMessages.ts index 7dab57b..a0a667e 100644 --- a/frontend/src/constants/errorMessages.ts +++ b/frontend/src/constants/errorMessages.ts @@ -6,6 +6,7 @@ // 一般的なエラーメッセージ export const GENERAL_ERRORS = { UNEXPECTED_ERROR: '予期せぬエラーが発生しました', + INVALID_STUFF_NAME: '材料名が正しく入力されていません。', INVALID_AMOUNT: '数量が正しく入力されていません。', INVALID_PRICE: '価格が正しく入力されていません。', }; @@ -23,6 +24,7 @@ export const TOBUY_ERRORS = { UPDATE_FAILED: '買うものリストの更新に失敗しました', DELETE_FAILED: '買うものリストの削除に失敗しました', BUY_FAILED: '買うものリストの購入処理に失敗しました', + INVALID_BUYAMOUNT: '購入数量が正しく入力されていません。', }; // 材料リスト関連のエラーメッセージ(料理の追加編集で用いる) @@ -40,7 +42,6 @@ export const STOCK_ERRORS = { CREATE_FAILED: '在庫リストの作成に失敗しました', UPDATE_FAILED: '在庫リストの更新に失敗しました', DELETE_FAILED: '在庫リストの削除に失敗しました', - BUY_FAILED: '在庫リストの購入処理に失敗しました', }; // 料理リスト関連のエラーメッセージ @@ -50,8 +51,15 @@ export const RECIPE_ERRORS = { CREATE_FAILED: '料理リストの作成に失敗しました', UPDATE_FAILED: '料理リストの更新に失敗しました', DELETE_FAILED: '料理リストの削除に失敗しました', + INVALID_RECIPE_NAME: 'レシピ名が入力されていません!', + NO_STUFFS: '材料が追加されていません!', + INVALID_SERVINGS: '人数が入力されていません。', }; +// 購入履歴関連のエラーメッセージ +export const STUFF_HISTORY_ERRORS = { + FETCH_FAILED: '履歴の取得に失敗しました。', +}; // // タスク関連のエラーメッセージ // export const TASK_ERRORS = { diff --git a/frontend/src/constants/normalMessages.ts b/frontend/src/constants/normalMessages.ts new file mode 100644 index 0000000..32bd867 --- /dev/null +++ b/frontend/src/constants/normalMessages.ts @@ -0,0 +1,16 @@ +/** + * 通常メッセージ(エラーでないメッセージ)の定数定義 + * アプリケーション全体で使用されるメッセージを一元管理 + */ + +// 買うものリスト +export const TOBUY_MESSAGES = { + CREATE_OK: '買うものリストに追加されました!', +}; + +// 料理リスト +export const RECIPE_MESSAGES = { + SAVED: 'レシピが保存されました!', + SAVED_AND_ADDED: 'レシピが保存されて買うものリストに追加されました!', + NO_ADDITIONALS: '必要な食材が在庫にあったのでリストには追加されませんでした。', +} diff --git a/frontend/src/pages/AddRecipe.tsx b/frontend/src/pages/AddRecipe.tsx index ecff456..ffc71ee 100644 --- a/frontend/src/pages/AddRecipe.tsx +++ b/frontend/src/pages/AddRecipe.tsx @@ -33,6 +33,8 @@ import { recipeApi, toBuyApi, stockApi } from '../services/api'; import { useNavigate, useParams } from 'react-router-dom'; import MessageAlert from '../components/MessageAlert'; import { useMessage } from '../components/MessageContext'; +import { RECIPE_MESSAGES } from '../constants/normalMessages'; +import { RECIPE_ERRORS } from '../constants/errorMessages'; const AddRecipe: React.FC = () => { const { recipeId: recipeIdStr } = useParams(); @@ -66,7 +68,7 @@ const AddRecipe: React.FC = () => { const [checked, setChecked] = useState(false); // エラーメッセージ表示 - const { showErrorMessage, showSuccessMessage } = useMessage(); + const { showErrorMessage, showInfoMessage, showSuccessMessage } = useMessage(); const loadRecipe = async () => { if (recipeId && !recipeLoaded) { @@ -83,19 +85,19 @@ const AddRecipe: React.FC = () => { if (!recipeName) { showErrorMessage('レシピ名が入力されていません!') - console.log("yes1"); + // console.log("yes1"); return false; } if (!items.length) { showErrorMessage('材料が追加されていません!') - console.log("yes2"); + // console.log("yes2"); return false; } try { if (!recipeId) { - console.log("yes3"); + // console.log("yes3"); // 新規追加 const response = await recipeApi.addRecipe({ recipeName, @@ -115,21 +117,21 @@ const AddRecipe: React.FC = () => { showErrorMessage('レシピの送信に失敗しました。同じ料理名が存在する可能性があります。'); return false; } - console.log("yes4"); + // console.log("yes4"); return recipeId; } const checkRecipeAndItems = async () => { if (!recipeName) { - showErrorMessage('レシピ名が入力されていません!') - console.log("yes1"); + showErrorMessage(RECIPE_ERRORS.INVALID_RECIPE_NAME); + // console.log("yes1"); return false; } if (!items.length) { - showErrorMessage('材料が追加されていません!') - console.log("yes2"); + showErrorMessage(RECIPE_ERRORS.NO_STUFFS); + // console.log("yes2"); return false; } return true; @@ -138,20 +140,20 @@ const AddRecipe: React.FC = () => { const handleSubmit = async () => { const recipeId = await handleSaveRecipe(); if (!recipeId) return; - showSuccessMessage('レシピが保存されました!'); + showSuccessMessage(RECIPE_MESSAGES.SAVED); navigate('/recipeList'); } const handleSubmitAndAddToBuy = async () => { - console.log("too"); - console.log(recipeName); + // console.log("too"); + console.log('recipeName:', recipeName); const recipeId = await handleSaveRecipe(); - console.log("before"); + // console.log("before"); if (!recipeId) return false; - console.log("ds"); + // console.log("ds"); if (!numOfPeaple) { - showErrorMessage('人数が入力されていません!') - console.log("yes2"); + showErrorMessage(RECIPE_ERRORS.INVALID_SERVINGS); + // console.log("yes2"); return false; } const finalAddResult = await toBuyApi.addByRecipe(recipeId, numOfPeaple, checked); @@ -175,10 +177,10 @@ const AddRecipe: React.FC = () => { // })) // }); if (finalAddResult.data.length === 0) { - showSuccessMessage('必要な食材が在庫にあったのでリストには追加されませんでした!'); + showInfoMessage(RECIPE_MESSAGES.NO_ADDITIONALS); } else { - showSuccessMessage('レシピが保存されて買うものリストに追加されました!'); + showSuccessMessage(RECIPE_MESSAGES.SAVED_AND_ADDED); } navigate('/tasks'); } diff --git a/frontend/src/pages/RecipeList.tsx b/frontend/src/pages/RecipeList.tsx index bcdce5a..66d91e8 100644 --- a/frontend/src/pages/RecipeList.tsx +++ b/frontend/src/pages/RecipeList.tsx @@ -32,6 +32,7 @@ import { } from '@mui/icons-material'; import { ToBuy, Stuff, RecipeWithId, RecipeDetail } from '../types/types'; import { useMessage } from '../components/MessageContext'; +import { RECIPE_ERRORS } from '../constants/errorMessages'; const RecipeList: React.FC = () => { const navigate = useNavigate(); @@ -51,7 +52,7 @@ const RecipeList: React.FC = () => { const recipes = await recipeApi.getAllRecipes(); setAllRecipes(recipes); } catch (error) { - showErrorMessage("レシピの取得に失敗しました。"); + showErrorMessage(RECIPE_ERRORS.FETCH_FAILED); // console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error); } }; diff --git a/frontend/src/pages/TaskListPage.tsx b/frontend/src/pages/TaskListPage.tsx index bc5b43a..8c9ad5d 100644 --- a/frontend/src/pages/TaskListPage.tsx +++ b/frontend/src/pages/TaskListPage.tsx @@ -25,7 +25,8 @@ import { SoupKitchen as SoupKitchenIcon, Edit as EditIcon } from '@mui/icons-material'; import { ToBuy, Stuff, NewToBuy, NewStock, StuffAndCategoryAndAmount, StuffNameAndAmount, StockHistory, /*Stock*/ } from '../types/types'; -import { GENERAL_ERRORS, TOBUY_ERRORS } from '../constants/errorMessages'; +import { GENERAL_ERRORS, TOBUY_ERRORS, STUFF_HISTORY_ERRORS } from '../constants/errorMessages'; +import { TOBUY_MESSAGES } from '../constants/normalMessages'; import EditAmountDialog from '../components/EditAmountDialog'; import AddStuffAmountDialog from '../components/AddStuffAmountDialog'; import BuyDialog from '../components/BuyDialog'; @@ -96,7 +97,7 @@ const TaskListPage: React.FC = () => { shop: undefined, }); - const { showErrorMessage } = useMessage(); + const { showErrorMessage, showSuccessMessage } = useMessage(); // コンポーネントマウント時にタスク一覧を取得 useEffect(() => { @@ -158,11 +159,20 @@ const TaskListPage: React.FC = () => { return; } + newToBuy.stuffName = newToBuy.stuffName.trim(); // 材料名の前後の空白を削除 + + if (!newToBuy.stuffName) { + showErrorMessage(GENERAL_ERRORS.INVALID_STUFF_NAME); + return; + } + console.log(newToBuy) await toBuyApi.addToBuy(newToBuy); setOpenAddToBuyDialog(false); // ダイアログを閉じる + showSuccessMessage(TOBUY_MESSAGES.CREATE_OK); setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット fetchTasks(); // 作成後のタスク一覧を再取得 + } catch (error) { console.error(`${TOBUY_ERRORS.CREATE_FAILED}:`, error); } @@ -197,17 +207,17 @@ const TaskListPage: React.FC = () => { try { const today = new Date().toISOString().substring(0, 10); const parsedPrice = parseInt(newStock.price, 10); - console.log("newPrice:", newStock.price) - console.log("parsedPrice: ", parsedPrice) + console.log("newPrice:", newStock.price); + console.log("parsedPrice: ", parsedPrice); if (isNaN(parsedPrice)) { - showErrorMessage(GENERAL_ERRORS.INVALID_PRICE) - return + showErrorMessage(GENERAL_ERRORS.INVALID_PRICE); + return; //setNewStock({ ...newStock, price: parsedPrice }); } const amount = parseInt(newStock.amount, 10); if (isNaN(amount)) { - showErrorMessage('購入数量が正しく入力されていません。') - return + showErrorMessage(TOBUY_ERRORS.INVALID_BUYAMOUNT); + return; } await toBuyApi.buy({ tobuyId: selectedToBuyId, @@ -236,7 +246,7 @@ const TaskListPage: React.FC = () => { setStockHistories(await stockApi.getHistories(tobuy.stuffId)); setOpenHistoryDialog(true); } catch { - showErrorMessage("履歴の読み込みに失敗しました。"); + showErrorMessage(STUFF_HISTORY_ERRORS.FETCH_FAILED); } }