/** * テストページコンポーネント * 白紙の状態で表示されるテスト用のページ */ import React, { useState, useEffect } from 'react'; import { Typography, Tooltip, List, ListItem, ListItemText, ListItemSecondaryAction, IconButton, Fab, Dialog, DialogTitle, DialogContent, DialogActions, TextField, Button, Checkbox, FormControlLabel, Box, } from '@mui/material'; import { Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, SoupKitchen as SoupKitchenIcon, Edit as EditIcon, Save as SaveIcon, ListAlt as ListAltIcon } from '@mui/icons-material'; import AddStuffAmountDialog from '../components/AddStuffAmountDialog'; import { StuffAndCategoryAndAmount } from '../types/types'; import EditAmountDialog from '../components/EditAmountDialog'; 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(); const recipeId = recipeIdStr ? parseInt(recipeIdStr) : null const navigate = useNavigate(); // 編集時,既存情報を読み込んだかどうか const [recipeLoaded, setRecipeLoaded] = useState(false); // 何人分かを格納する const [numOfPeaple, setNumOfPeaple] = useState(1); const [openNumOfPeapleDialog, setOpenNumOfPeapleDialog] = useState(false); // 料理名,説明 const [recipeName, setRecipeName] = useState(''); const [recipeSummary, setRecipeSummary] = useState(''); // 材料リスト const [items, setItems] = useState([]); // 材料追加作成ダイアログの表示状態 const [openAddDialog, setOpenAddDialog] = useState(false); // 材料追加作成ダイアログの表示状態 const [openAmountDialog, setOpenAmountDialog] = useState(false); // 新規アイテムの入力内容 const emptyItem: StuffAndCategoryAndAmount = { stuffId: null, stuffName: '', category: '', amount: 1 } const [newItem, setNewItem] = useState(emptyItem); // 編集しているアイテム const [editingItem, setEditingItem] = useState(emptyItem); const [editingItemIdx, setEditingItemIdx] = useState(0); //削除確認ダイアログの表示状態 const [openDeleteDialog, setOpenDeleteDialog] = useState(false); // チェックボックスが押されたかどうか const [checked, setChecked] = useState(false); // エラーメッセージ表示 const { showErrorMessage, showInfoMessage, showSuccessMessage } = useMessage(); const loadRecipe = async () => { 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) } } const handleSaveRecipe = async () => { if (!recipeName) { showErrorMessage('レシピ名が入力されていません!') // console.log("yes1"); return false; } if (!items.length) { showErrorMessage('材料が追加されていません!') // console.log("yes2"); return false; } try { if (!recipeId) { // console.log("yes3"); // 新規追加 const response = await recipeApi.addRecipe({ recipeName, summary: recipeSummary, stuffAndAmountArray: items, }) return response.recipeId; } const response = await recipeApi.updateRecipe({ recipeId, recipeName, summary: recipeSummary, stuffAndAmountArray: items, }) } catch { showErrorMessage('レシピの送信に失敗しました。同じ料理名が存在する可能性があります。'); return false; } // console.log("yes4"); return recipeId; } const checkRecipeAndItems = async () => { if (!recipeName) { showErrorMessage(RECIPE_ERRORS.INVALID_RECIPE_NAME); // console.log("yes1"); return false; } if (!items.length) { showErrorMessage(RECIPE_ERRORS.NO_STUFFS); // console.log("yes2"); return false; } return true; } const handleSubmit = async () => { const recipeId = await handleSaveRecipe(); if (!recipeId) return; showSuccessMessage(RECIPE_MESSAGES.SAVED); navigate('/recipeList'); } const handleSubmitAndAddToBuy = async () => { // console.log("too"); console.log('recipeName:', recipeName); const recipeId = await handleSaveRecipe(); // console.log("before"); if (!recipeId) return false; // console.log("ds"); if (!numOfPeaple) { showErrorMessage(RECIPE_ERRORS.INVALID_SERVINGS); // console.log("yes2"); return false; } const finalAddResult = await toBuyApi.addByRecipe(recipeId, numOfPeaple, checked); console.log(finalAddResult) // const recipeStuffInfo = (await recipeApi.getById(recipeId)).stuffAndAmountArray; // const recipeStuffId = recipeStuffInfo.map(item => item.stuffId); // console.log(recipeStuffId); // const stockStuff = await stockApi.getStocks(); // const stockedStuffId = stockStuff.filter(stock => recipeStuff.stuffAndAmountArray).map(item => item.id); // const stockedStuffAmountRecipe = recipeStuff.filter(recipe => (stockStuff.some(stuff => recipe.stuffId === stuff.stuffId))); // console.log(stockedStuffAmountRecipe) // const stockedStuffAmountStock = stockStuff.filter(stock => (stockedStuffAmountRecipe.some(stocked => stock.stuffId === stocked.stuffId))); // recipeStuff.map(item => { // await Promise.all(stockStuff.map(async stock => { // if (item.stuffId == stock.stuffId) // await toBuyApi.updateToBuy({stuffName: item.stuffName, // amount: item.amount - stock.amount, // tobuyId: item.tobuyId, // stuffId: item.stuffId}); // })) // }); if (finalAddResult.data.length === 0) { showInfoMessage(RECIPE_MESSAGES.NO_ADDITIONALS); } else { showSuccessMessage(RECIPE_MESSAGES.SAVED_AND_ADDED); } navigate('/tasks'); } const openNumOfPeopleDialog = async () => { const check = await checkRecipeAndItems(); if (!check) return false; setOpenNumOfPeapleDialog(true); } const cancelNumOfPeopleDialog = async () => { const recipeId = await handleSaveRecipe(); if (!recipeId) return false; setOpenNumOfPeapleDialog(false); } // コンポーネントマウント時にタスク一覧を取得 useEffect(() => { loadRecipe(); }, []); return ( <> {(recipeId && !recipeLoaded) ?

読み込み中...

:

{!recipeId ? '料理の追加' : '料理の編集'}

setRecipeName(e.target.value)} /> setRecipeSummary(e.target.value)} />

材料リスト

{/* すべての材料情報を表示 */} {(!items || !items.length) ? (

+ボタンで材料を追加してください

) : ({items.map((item, index) => ( {/* 買い物リスト:食材情報記入ボタン */} {`× ${item.amount}`} {/* 買い物リスト:数量変更ボタン */} { setOpenAmountDialog(true) setEditingItemIdx(index) setEditingItem(item) }} > {/* 買い物リスト:食材削除ボタン */} { setOpenDeleteDialog(true) setEditingItem(item) setEditingItemIdx(index) }}> ))})}
材料を追加 setOpenAddDialog(true)}>
{/* 新規材料追加ダイアログ */} { console.log('newItem:', newItem); setItems([...items, newItem]); setOpenAddDialog(false); }} /> {/* 削除ダイアログ */} setOpenDeleteDialog(false)} disableScrollLock={true} fullWidth maxWidth="sm" sx={{ overflow: "hidden" }} > 食材の削除 {editingItem && ( <> {editingItem.stuffName}を削除します。 ⚠️ 注意: 削除すると復元できません。 )} {/* 数量変更ダイアログ */} setEditingItem({ ...editingItem, ...v })} onSubmit={() => { setItems([...items.slice(0, editingItemIdx), editingItem, ...items.slice(editingItemIdx + 1)]) setOpenAmountDialog(false); }} /> {/* 人数入力ダイアログ */} setOpenNumOfPeapleDialog(false)} disableScrollLock={true} style={{ width : '100%', position : 'fixed', left: '50%', transform: 'translateX(-50%)' }} > 買うものリストへ追加
{/* 人数入力フィールド */} { const value = e.target.value; const parsedValue = parseInt(value, 10); // 数値に変換 if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外 setNumOfPeaple(parsedValue); // number型で保存 } }} sx={{ minWidth: "8px", width: "100%" }} type="number" inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可 />
setChecked(e.target.checked)} />} label={足りない食材のみ登録} />
} ); }; export default AddRecipe;