料理追加の画面内での機能まで実装

feature-frontend-dishedit-kato
Masaharu.Kato 4 months ago
parent 1153f69d09
commit 8fd8771ac5
  1. 26
      frontend/src/App.tsx
  2. 45
      frontend/src/components/AddStuffAmountDialog.tsx
  3. 16
      frontend/src/components/EditAmountDialog.tsx
  4. 21
      frontend/src/components/Layout.tsx
  5. 82
      frontend/src/pages/AddDishes1.tsx
  6. 278
      frontend/src/pages/AddDishes2.tsx
  7. 13
      frontend/src/pages/AddDishies1.tsx
  8. 155
      frontend/src/pages/AddRecipe.tsx
  9. 78
      frontend/src/pages/TaskListPage.tsx
  10. 29
      frontend/src/types/types.ts

@ -12,8 +12,7 @@ import TaskListPage from './pages/TaskListPage';
import StockPage from './pages/StockPage';
import './App.css';
// 必要なインポートを追加
import AddDishes1 from './pages/AddDishes1';
import AddDishes2 from './pages/AddDishes2';
import AddRecipe from './pages/AddRecipe';
import DishList from './pages/DishList';
//カレンダーライブラリ
import FullCalendar from '@fullcalendar/react';
@ -120,18 +119,10 @@ const App: React.FC = () => {
/>
{/* テストページへのルートを追加 */}
<Route
path="add1"
path="addRecipe"
element={
<PrivateRoute>
<AddDishes1 />
</PrivateRoute>
}
/>
<Route
path="add2"
element={
<PrivateRoute>
<AddDishes2 />
<AddRecipe />
</PrivateRoute>
}
/>
@ -149,16 +140,7 @@ const App: React.FC = () => {
</PrivateRoute>
}
/>
{/* テストページへのルートを追加 */}
<Route
path="stock"
element={
<PrivateRoute>
<StockPage />
</PrivateRoute>
}
/>
</Route>
</Routes>
</BrowserRouter>

@ -15,7 +15,7 @@ import {
Select,
MenuItem,
} from '@mui/material';
import { NewToBuy, Stuff } from '../types/types';
import { StuffAndCategoryAndAmount, Stuff } from '../types/types';
import { stuffApi } from '../services/api';
@ -23,25 +23,27 @@ import { stuffApi } from '../services/api';
const AddStuffAmountDialog = ({
openDialog,
setOpenDialog,
newToBuy,
setNewToBuy,
newItem,
setNewItem,
onSubmit,
}: {
openDialog: boolean,
setOpenDialog: (open: boolean) => void,
newToBuy: NewToBuy,
setNewToBuy: (tobuy: NewToBuy) => void,
newItem: StuffAndCategoryAndAmount,
setNewItem: (item: StuffAndCategoryAndAmount) => void,
onSubmit: () => void,
}) => {
const onChangeCategory = async (category: string) => {
setNewToBuy({ ...newToBuy, category })
setNewItem({ ...newItem, category })
const result = await stuffApi.getStuffs(category)
setStuffs(result)
}
const [stuffs, setStuffs] = useState<Stuff[]>([]);
const [newAddition, setNewAddition] = useState(false);
return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
@ -51,8 +53,8 @@ const AddStuffAmountDialog = ({
<FormControlLabel
control={<Checkbox />}
label="食材を新規追加"
checked={newToBuy.newAddition}
onChange={(e) => setNewToBuy({ ...newToBuy, newAddition: (e.target as HTMLInputElement).checked })}
checked={newAddition}
onChange={(e) => setNewAddition((e.target as HTMLInputElement).checked)}
/>
</FormGroup>
</Box>
@ -64,7 +66,7 @@ const AddStuffAmountDialog = ({
<InputLabel id="demo-simple-select-label"></InputLabel>
<Select
labelId="demo-simple-select-label"
value={newToBuy.category}
value={newItem.category}
onChange={(e) => onChangeCategory(e.target.value)}
>
<MenuItem value="乳製品"></MenuItem>
@ -75,12 +77,12 @@ const AddStuffAmountDialog = ({
</Select>
</FormControl>
{!newToBuy.newAddition && <FormControl sx={{ width: "100%", marginBottom: 2 }}>
{!newAddition && <FormControl sx={{ width: "100%", marginBottom: 2 }}>
<InputLabel id="demo-simple-select-label"></InputLabel>
<Select
labelId="demo-simple-select-label"
value={newToBuy.stuffId}
onChange={(e) => setNewToBuy({ ...newToBuy, stuffId: Number(e.target.value) })}
value={newItem.stuffId}
onChange={(e) => setNewItem({ ...newItem, stuffId: Number(e.target.value) })}
>
{stuffs.map((stuff) => (
<MenuItem key={stuff.stuffId} value={stuff.stuffId}>
@ -91,13 +93,13 @@ const AddStuffAmountDialog = ({
</FormControl>}
{/* タスクタイトル入力フィールド */}
{newToBuy.newAddition && <TextField
{newAddition && <TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={newToBuy.stuffName}
onChange={(e) => setNewToBuy({ ...newToBuy, stuffName: e.target.value })}
value={newItem.stuffName}
onChange={(e) => setNewItem({ ...newItem, stuffName: e.target.value })}
sx={{ marginBottom: 2 }}
/>}
{/* 数量入力フィールド */}
@ -105,12 +107,12 @@ const AddStuffAmountDialog = ({
margin="dense"
label="数量"
fullWidth
value={newToBuy.amount}
value={newItem.amount}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
setNewToBuy({ ...newToBuy, amount: parsedValue }); // number型で保存
setNewItem({ ...newItem, amount: parsedValue }); // number型で保存
}
}}
sx={{ width: "20%" }}
@ -122,7 +124,14 @@ const AddStuffAmountDialog = ({
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={onSubmit} variant="contained">
<Button onClick={() => {
if (newAddition) {
newItem.stuffId = null;
} else if (newItem.stuffId) {
newItem.stuffName = stuffs.filter(stuff => stuff.stuffId == newItem.stuffId)[0]?.stuffName;
}
onSubmit()
}} variant="contained">
</Button>
</DialogActions>

@ -7,19 +7,19 @@ import {
Button,
Box,
} from '@mui/material';
import { ToBuy } from '../types/types';
import { StuffNameAndAmount } from '../types/types';
const EditAmountDialog = ({
openDialog,
setOpenDialog,
editingTobuy,
setEditingTobuy,
editingItem,
setEditingItem,
onSubmit
}: {
openDialog: boolean,
setOpenDialog: (open: boolean) => void,
editingTobuy: ToBuy,
setEditingTobuy: (tobuy: ToBuy) => void,
editingItem: StuffNameAndAmount,
setEditingItem: (tobuy: StuffNameAndAmount) => void,
onSubmit: () => void,
}) => {
@ -38,7 +38,7 @@ const EditAmountDialog = ({
margin="dense"
label="材料名"
fullWidth
value={editingTobuy.stuffName}
value={editingItem.stuffName}
disabled
sx={{ marginBottom: 2 }}
/>
@ -47,12 +47,12 @@ const EditAmountDialog = ({
margin="dense"
label="数量"
fullWidth
value={editingTobuy.amount}
value={editingItem.amount}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
setEditingTobuy({ ...editingTobuy, amount: parsedValue }); // number型で保存
setEditingItem({ ...editingItem, amount: parsedValue }); // number型で保存
}
}}
sx={{ width: "20%" }}

@ -23,6 +23,7 @@ import {
ListAlt as ListAltIcon,
Inventory as InventoryIcon, // テストページ用のアイコン
Science as ScienceIcon, // 鈴木
SoupKitchen as SoupKitchenIcon,
} from '@mui/icons-material';
import { useNavigate, Outlet, useLocation } from 'react-router-dom';
@ -104,19 +105,12 @@ const Layout: React.FC = () => {
{/* 在庫リストへのリンクを追加 */}
<ListItemButton
onClick={() => handleNavigate('/add1')}
selected={isSelected('/add1')}
onClick={() => handleNavigate('/addRecipe')}
selected={isSelected('/addRecipe')}
>
<ListItemIcon><ScienceIcon /></ListItemIcon>
<ListItemIcon><SoupKitchenIcon /></ListItemIcon>
<ListItemText primary="料理の追加" />
</ListItemButton>
<ListItemButton
onClick={() => handleNavigate('/stock')}
selected={isSelected('/stock')}
>
<ListItemIcon><InventoryIcon /></ListItemIcon>
<ListItemText primary="在庫管理" />
</ListItemButton>
<ListItemButton
onClick={() => handleNavigate('/dishList')}
selected={isSelected('/dishList')}
@ -124,6 +118,13 @@ const Layout: React.FC = () => {
<ListItemIcon><ScienceIcon /></ListItemIcon>
<ListItemText primary="料理リスト" />
</ListItemButton>
<ListItemButton
onClick={() => handleNavigate('/stock')}
selected={isSelected('/stock')}
>
<ListItemIcon><InventoryIcon /></ListItemIcon>
<ListItemText primary="在庫管理" />
</ListItemButton>
<Divider />
</List>
</Box>

@ -1,82 +0,0 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
AppBar,
Toolbar,
Typography,
Container,
Box,
Button,
Drawer,
List,
ListItemText,
ListItemIcon,
ListItemButton,
Divider,
IconButton,
TextField,
Paper,
Alert,
Link,
Grid,
} from '@mui/material';
import { LoginCredentials } from '../types/types';
import { authApi } from '../services/api';
import { GENERAL_ERRORS } from '../constants/errorMessages';
const AddDishes1: React.FC = () => {
const navigate = useNavigate();
const [dish, setDish] = useState("");
// エラーメッセージの状態管理
const [error, setError] = useState(false);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDish(event.target.value);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); // フォームのデフォルト送信動作を防止
if (!dish.trim()) {
alert("エラー");
setError(true);
} else {
alert("送信成功!");
localStorage.setItem("dishName", dish); // ローカルストレージにフォームに入力された料理名を保存
navigate('/add2', { state: dish }); // 料理名から材料名追加ページにリダイレクト
}
};
return (
<div>
<Typography variant="h4" component="h1" gutterBottom>
</Typography>
<Box component="form" onSubmit={handleSubmit}>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '10px', textAlign: 'center'}}>
<TextField
required
// id="username"
label="追加・編集したい料理名を入力"
variant="outlined"
InputLabelProps={{ style: { fontSize: "40px" }}}
style={{width: "80%" }}
InputProps={{ style: { fontSize: "40px"} }}
name="dishName"
// autoComplete="username"
autoFocus
value={dish}
onChange={handleChange}
error={error}
helperText={error ? "入力が必要です" : ""}
/>
</div>
<div style={{position: "fixed", left: "75%", transform: 'translateX(-50%)', bottom: "10px"}}>
<Button type="submit" variant='contained' sx={{ width: "250px", height: "60px", fontSize: "40px" }} color="primary" >
</Button>
</div>
</Box>
</div>
);
};
export default AddDishes1;

@ -1,278 +0,0 @@
/**
*
*
*/
import React, { useState, useEffect } from 'react';
import { toBuyApi } from '../services/api';
import {
Container,
Typography,
Tooltip,
List,
ListItem,
ListItemText,
ListItemSecondaryAction,
IconButton,
Checkbox,
Fab,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
MenuItem,
Select,
FormControl,
InputLabel
} from '@mui/material';
import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon
} from '@mui/icons-material';
import { STUFF_ERRORS } from '../constants/errorMessages';
import { GENERAL_ERRORS } from '../constants/errorMessages';
import CategoryDropDown from "../components/CategoryDropDown";
// 新規タスクの初期状態(画面表示用)
const EMPTY_TASK = { id: 0, title: '', amount: 0, completed: false };
// 新規タスクの初期状態(データベース登録用)
const EMPTY_TASK_DATA_BASE = { id: 0, title: '', amount: 0, completed: false };
interface Stuff {
title: string; // 食材名
amount: number; // 食材の個数
completed: boolean; //
}
const AddDishes2: React.FC = () => {
const receivedData = localStorage.getItem("dishName");
// タスク一覧の状態管理
const [tasks, setTasks] = useState<Stuff[]>([]);
const [addtasks, setAddTasks] = useState<Stuff[]>([]);
// エラーメッセージの状態管理
const [error, setError] = useState(false);
// 新規タスク作成ダイアログの表示状態
const [openDialog, setOpenDialog] = useState(false);
// 新規タスクの入力内容
const [newTask, setNewTask] = useState(EMPTY_TASK);
// // コンポーネントマウント時にタスク一覧を取得
// useEffect(() => {
// fetchTasks();
// }, []);
// /**
// * APIからタスク一覧を取得する関数
// * 取得したタスクをstate(tasks)に設定
// */
// const fetchTasks = async () => {
// try {
// const tasks = await taskApi.getTasks();
// setTasks(tasks);
// } catch (error) {
// console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error);
// }
// };
/**
*
* IDのタスクをAPIを通じて削除
*/
const handleDeleteTask = async (index: number) => {
try {
let newAddTasks = [...addtasks]; // 配列をコピー
newAddTasks.splice(index, 1);
setAddTasks(newAddTasks);
// fetchTasks(); // 削除後のタスク一覧を再取得
} catch (error) {
console.error(`${STUFF_ERRORS.DELETE_FAILED}:`, error);
}
};
/**
*
* APIに送信して新規作成
*
*/
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault(); // フォームのデフォルト送信動作を防止
if (addtasks[0] == null) {
setError(true);
alert("食材を追加してください");
} else {
alert("送信成功!");
handleCreateTask_DataBase();
// localStorage.setItem("dishName", dish); // ローカルストレージにフォームに入力された料理名を保存
// navigate('/add2', { state: dish }); // 料理名から材料名追加ページにリダイレクト
}
};
const handleCreateTask_Temp = async () => {
try {
// await taskApi.createTask(newTask);
let newAddTasks = [...addtasks]; // 配列をコピー
newAddTasks.push(newTask);
setAddTasks(newAddTasks);
setOpenDialog(false); // ダイアログを閉じる
setNewTask(EMPTY_TASK); // 入力内容をリセット
// fetchTasks(); // 作成後のタスク一覧を再取得
} catch (error) {
console.error(`${STUFF_ERRORS.CREATE_FAILED}:`, error);
}
};
const handleCreateTask_DataBase = async () => {
try {
// for (let i = 0; i < addtasks.length; i++) {
// // await taskApi.createTask(addtasks[i]);
// await toBuyApi.addToBuy(addtasks[i]);
// }
setOpenDialog(false); // ダイアログを閉じる
setNewTask(EMPTY_TASK); // 入力内容をリセット
// fetchTasks(); // 作成後のタスク一覧を再取得
} catch (error) {
console.error(`${STUFF_ERRORS.CREATE_FAILED}:`, error);
}
};
return (
<Box>
<div>
<h1></h1>
<p style={{fontSize: "40px"}}>{receivedData}</p>
</div>
<List>
{/* タスク一覧をマップして各タスクをリストアイテムとして表示 */}
{addtasks.map((task, index) => (
<ListItem
key={index}
sx={{
bgcolor: 'background.paper',
mb: 1,
borderRadius: 1,
boxShadow: 1,
}}
>
{/*
<Checkbox
checked={task.completed}
onChange={() => handleToggleComplete(task.id)}
/> */}
{/* タスクのタイトルと説明 - 完了状態に応じて取り消し線を表示 */}
<ListItemText
primary={task.title}
// secondary={task.description}
sx={{
textDecoration: task.completed ? 'line-through' : 'none',
}}
/>
{/* 食材の個数を表示 */}
<ListItemText
primary={<Typography style={{textAlign:"center"}}><br />
{task.amount}
</Typography>
}
// secondary={task.description}
primaryTypographyProps={{ align: "right", marginRight: "20%", fontSize: "20px" }}
/>
{/* 買い物リスト:食材情報記入ボタン */}
<ListItemSecondaryAction>
<Tooltip title="食材情報追加">
<IconButton
edge="end"
aria-label="食材情報追加"
//onClick={() => handleDeleteTask(task.id)}
>
<ShoppingBasketIcon />
</IconButton>
</Tooltip>
{/* 買い物リスト:食材削除ボタン */}
<Tooltip title="項目を削除"
componentsProps={{
tooltip: {
sx: {
backgroundColor: "white",
color: "red",
fontSize: "0.8rem",
padding: "6px",
borderRadius: "6px",
},
},
}}
>
<IconButton
edge="end"
aria-label="delete"
onClick={() => handleDeleteTask(index)}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
<div style={{position: "fixed", left: "75%", transform: 'translateX(-50%)', bottom: "20%"}}>
<Button variant='contained' sx={{ width: "250px", height: "60px", fontSize: "40px" }}
color="primary" onClick={() => setOpenDialog(true)}>
</Button>
</div>
<div style={{position: "fixed", width: "60%", left: "50%", transform: 'translateX(-50%)', bottom: "2%"}}>
<Button variant='contained' sx={{ width: "100%", height: "100px", fontSize: "40px" }}
color="primary" onClick={handleSubmit}>
</Button>
</div>
{/* 新規タスク作成ダイアログ */}
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
<DialogTitle></DialogTitle>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/*材料カテゴリ選択 */}
<CategoryDropDown></CategoryDropDown>
{/* タスクタイトル入力フィールド */}
<TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={newTask.title}
onChange={(e) => setNewTask({ ...newTask, title: e.target.value })}
sx={{ marginBottom: 2 }}
/>
{/* 数量入力フィールド */}
<TextField
margin="dense"
label="数量"
fullWidth
value={newTask.amount}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (!isNaN(parsedValue)) {
setNewTask({ ...newTask, amount: parsedValue }); // number型で保存
}
}}
sx={{ width: "20%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={handleCreateTask_Temp} variant="contained">
</Button>
</DialogActions>
</Dialog>
</Box>
);
};
export default AddDishes2;

@ -1,13 +0,0 @@
import React from 'react';
import { Box } from '@mui/material';
const AddDishies1: React.FC = () => {
return (
<Box>
{/* 白紙のページ - 何も表示しない */}
</Box>
);
};
export default AddDishies1;

@ -0,0 +1,155 @@
/**
*
*
*/
import React, { useState, useEffect } from 'react';
import {
Container,
Typography,
Tooltip,
List,
ListItem,
ListItemText,
ListItemSecondaryAction,
IconButton,
Checkbox,
Fab,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
MenuItem,
Select,
FormControl,
InputLabel,
ListItemIcon
} from '@mui/material';
import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon, Edit as EditIcon, ListAlt as ListAltIcon
} from '@mui/icons-material';
import AddStuffAmountDialog from '../components/AddStuffAmountDialog';
import { StuffAndCategoryAndAmount, StuffNameAndAmount } from '../types/types';
import EditAmountDialog from '../components/EditAmountDialog';
const AddDishes2: React.FC = () => {
// 料理名
const [recipeName, setRecipeName] = useState<string>('');
// 材料リスト
const [items, setItems] = useState<StuffAndCategoryAndAmount[]>([]);
// 材料追加作成ダイアログの表示状態
const [openAddDialog, setOpenAddDialog] = useState(false);
// 材料追加作成ダイアログの表示状態
const [openAmountDialog, setOpenAmountDialog] = useState(false);
// 新規アイテムの入力内容
const emptyItem: StuffAndCategoryAndAmount = { stuffId: null, stuffName: '', category: '', amount: 1 }
const [newItem, setNewItem] = useState<StuffAndCategoryAndAmount>(emptyItem);
// 編集しているアイテム
const [editingItem, setEditingItem] = useState<StuffAndCategoryAndAmount>(emptyItem);
const [editingItemIdx, setEditingItemIdx] = useState(0);
const handleAddRecipeToBuy = () => {
console.log('追加された材料:', items);
}
return (
<Box>
<div>
<h1></h1>
<TextField autoFocus margin="dense" label="料理名" fullWidth
value={recipeName} onChange={(e) => setRecipeName(e.target.value)}
/>
</div>
<h2></h2>
{/* すべての材料情報を表示 */}
{!items.length
? (<p>+</p>)
: (<List>{items.map((item, index) => (
<ListItem
key={index}
sx={{
bgcolor: 'background.paper',
mb: 1,
borderRadius: 1,
boxShadow: 1,
}}
>
<ListItemText primary={item.stuffName} />
{/* 買い物リスト:食材情報記入ボタン */}
<ListItemSecondaryAction>
<Typography variant="body1" component="span" sx={{ marginRight: '1em' }}>
{`× ${item.amount}`}
</Typography>
{/* 買い物リスト:数量変更ボタン */}
<Tooltip title="数量変更">
<IconButton sx={{ marginRight: 0, marginLeft: 0 }} edge="end" aria-label="数量変更"
onClick={() => {
setOpenAmountDialog(true)
setEditingItemIdx(index)
setEditingItem(item)
}}
>
<EditIcon />
</IconButton>
</Tooltip>
{/* 買い物リスト:食材削除ボタン */}
<Tooltip title="項目を削除"
componentsProps={{
tooltip: { sx: { backgroundColor: "white", color: "red", fontSize: "0.8rem", padding: "6px", borderRadius: "6px" } },
}}>
<IconButton edge="end" sx={{ marginRight: 0, marginLeft: 0 }} aria-label="delete"
onClick={() => setItems([...items.slice(0, index), ...items.slice(index + 1)])}>
<DeleteIcon />
</IconButton>
</Tooltip>
</ListItemSecondaryAction>
</ListItem>
))}</List>)}
<div style={{ position: "fixed", left: "80%", transform: 'translateX(-50%)', bottom: "10%" }}>
<Box sx={{ textAlign: 'center' }}>
<Typography variant="caption"></Typography>
</Box>
<Fab color="primary" onClick={() => setOpenAddDialog(true)}>
<AddIcon sx={{ fontSize: "1.5rem" }} />
</Fab>
</div>
<div style={{ position: "fixed", left: "50%", transform: 'translateX(-50%)', bottom: "2%" }}>
<Button variant='contained' sx={{ fontSize: "1.0rem" }}
color="primary" onClick={handleAddRecipeToBuy}>
<ListAltIcon sx={{ fontSize: "1.5rem", marginRight: "0.5rem" }} />
</Button>
</div>
{/* 新規材料追加ダイアログ */}
<AddStuffAmountDialog openDialog={openAddDialog} setOpenDialog={setOpenAddDialog} newItem={newItem} setNewItem={setNewItem}
onSubmit={() => {
console.log('newItem:', newItem);
setItems([...items, newItem]);
setOpenAddDialog(false);
}} />
{/* 数量変更ダイアログ */}
<EditAmountDialog openDialog={openAmountDialog} setOpenDialog={setOpenAmountDialog}
editingItem={editingItem}
setEditingItem={(v) => setEditingItem({ ...editingItem, ...v })}
onSubmit={() => {
setItems([...items.slice(0, editingItemIdx), editingItem, ...items.slice(editingItemIdx + 1)])
setOpenAmountDialog(false);
}} />
</Box>
);
};
export default AddDishes2;

@ -20,7 +20,7 @@ import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon, Edit as EditIcon
} from '@mui/icons-material';
import { ToBuy, Stuff, NewToBuy, NewStock, /*Stock*/ } from '../types/types';
import { ToBuy, Stuff, NewToBuy, NewStock, StuffAndCategoryAndAmount, StuffNameAndAmount, /*Stock*/ } from '../types/types';
import { TOBUY_ERRORS } from '../constants/errorMessages';
import EditAmountDialog from '../components/EditAmountDialog';
import AddStuffAmountDialog from '../components/AddStuffAmountDialog';
@ -36,7 +36,6 @@ const EMPTY_TOBUY: NewToBuy = {
amount: 1,
shop: '',
category: '',
newAddition: false,
}
const TaskListPage: React.FC = () => {
@ -60,7 +59,7 @@ const TaskListPage: React.FC = () => {
expDate: '',
});
const [editingTask, setEditingTask] = useState<ToBuy>({
const [editingItem, setEditingItem] = useState<ToBuy>({
tobuyId: 0,
stuffId: 0,
stuffName: "",
@ -68,7 +67,7 @@ const TaskListPage: React.FC = () => {
shop: undefined,
});
const [newToBuy, setNewToBuy] = useState(EMPTY_TOBUY);
const [newToBuy, setNewToBuy] = useState<StuffAndCategoryAndAmount>(EMPTY_TOBUY);
@ -148,9 +147,6 @@ const TaskListPage: React.FC = () => {
*/
const handleAddNewToBuy = async () => {
try {
if (newToBuy.newAddition) {
newToBuy.stuffId = null;
}
if (isNaN(newToBuy.amount)) {
console.log('数量が正しくありません.');
return;
@ -173,13 +169,13 @@ const TaskListPage: React.FC = () => {
*/
const handleUpdateNewToBuy = async () => {
try {
if (isNaN(editingTask.amount)) {
if (isNaN(editingItem.amount)) {
console.log('数量が正しくありません.');
return;
}
console.log(editingTask)
await toBuyApi.updateToBuy(editingTask);
console.log(editingItem)
await toBuyApi.updateToBuy(editingItem);
setOpenAmountDialog(false); // ダイアログを閉じる
//setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット
fetchTasks(); // 作成後のタスク一覧を再取得
@ -222,17 +218,7 @@ const TaskListPage: React.FC = () => {
boxShadow: 1,
}}
>
{/* タスク完了状態を切り替えるチェックボックス */}
{/*}
<Checkbox
checked={task.completed}
onChange={() => handleToggleComplete(task.id)}
/>
*/}
{/* タスクのタイトルと説明 - 完了状態に応じて取り消し線を表示 */}
<ListItemText
primary={tobuy.stuffName}
/>
<ListItemText primary={tobuy.stuffName} />
{/* 買い物リスト:食材情報記入ボタン */}
<ListItemSecondaryAction>
<Typography variant="body1" component="span" sx={{ marginRight: '1em' }}>
@ -240,13 +226,10 @@ const TaskListPage: React.FC = () => {
</Typography>
{/* 買い物リスト:数量変更ボタン */}
<Tooltip title="数量変更">
<IconButton
sx={{ marginRight: 0, marginLeft: 0 }}
edge="end"
aria-label="数量変更"
onClick={() => {
<IconButton sx={{ marginRight: 0, marginLeft: 0 }} edge="end" aria-label="数量変更"
onClick={() => {
setOpenAmountDialog(true)
setEditingTask(tobuy)
setEditingItem(tobuy)
}}
>
<EditIcon />
@ -254,17 +237,12 @@ const TaskListPage: React.FC = () => {
</Tooltip>
{/* 買い物リスト:食材情報記入ボタン */}
<Tooltip title="購入情報を記入">
<IconButton
color="primary"
sx={{ marginRight: 0, marginLeft: 0 }}
edge="end"
aria-label="購入情報を記入"
<IconButton color="primary" sx={{ marginRight: 0, marginLeft: 0 }} edge="end" aria-label="購入情報を記入"
onClick={() => {
setOpenInfoDialog(true)
setSelectedToBuyId(tobuy.tobuyId)
// handleDeleteTask(tobuy.tobuyId)
}}
>
}}>
<ShoppingBasketIcon />
</IconButton>
</Tooltip>
@ -272,27 +250,14 @@ const TaskListPage: React.FC = () => {
{/* 買い物リスト:食材削除ボタン */}
<Tooltip title="項目を削除"
componentsProps={{
tooltip: {
sx: {
backgroundColor: "white",
color: "red",
fontSize: "0.8rem",
padding: "6px",
borderRadius: "6px",
},
},
}}
>
<IconButton
edge="end"
sx={{ marginRight: 0, marginLeft: 0 }}
aria-label="delete"
onClick={() => handleDeleteToBuy(tobuy.tobuyId)}
>
tooltip: {sx: {backgroundColor: "white", color: "red", fontSize: "0.8rem", padding: "6px", borderRadius: "6px"}},
}}>
<IconButton edge="end" sx={{ marginRight: 0, marginLeft: 0 }} aria-label="delete"
onClick={() => handleDeleteToBuy(tobuy.tobuyId)}>
<DeleteIcon />
</IconButton>
</Tooltip>
</ListItemSecondaryAction>
</ListItem>
@ -332,14 +297,17 @@ const TaskListPage: React.FC = () => {
</Fab>
{/* 新規タスク作成ダイアログ */}
<AddStuffAmountDialog openDialog={openAddToBuyDialog} setOpenDialog={setOpenAddToBuyDialog} newToBuy={newToBuy} setNewToBuy={setNewToBuy} onSubmit={handleAddNewToBuy} />
{/* 買うものリストへの材料追加ダイアログ */}
<AddStuffAmountDialog openDialog={openAddToBuyDialog} setOpenDialog={setOpenAddToBuyDialog} newItem={newToBuy} setNewItem={setNewToBuy} onSubmit={handleAddNewToBuy} />
{/*在庫登録のための数値入力ダイアログ */}
<BuyDialog openDialog={openInfoDialog} setOpenDialog={setOpenInfoDialog} newStock={newStock} setNewStock={setNewStock} onSubmit={handleBuy} />
{/* 数量変更ダイアログ */}
<EditAmountDialog openDialog={openAmountDialog} setOpenDialog={setOpenAmountDialog} editingTobuy={editingTask} setEditingTobuy={setEditingTask} onSubmit={handleUpdateNewToBuy} />
<EditAmountDialog openDialog={openAmountDialog} setOpenDialog={setOpenAmountDialog}
editingItem={editingItem}
setEditingItem={(v) => setEditingItem({...editingItem, ...v})}
onSubmit={handleUpdateNewToBuy} />
</Container>

@ -17,28 +17,39 @@
// //updatedAt: string; // タスク更新日時
// }
/**
*
*
*/
export interface StuffNameAndAmount {
stuffName: string;
amount: number;
}
/**
*
*
*/
export interface ToBuy {
export interface ToBuy extends StuffNameAndAmount {
tobuyId: number,
stuffId: number,
stuffName: string,
amount: number,
shop?: string,
}
/**
*
*
*/
export interface StuffAndCategoryAndAmount extends StuffNameAndAmount {
stuffId: number | null;
category: string,
}
/**
*
*/
export interface NewToBuy {
stuffId: null | number,
stuffName: string,
amount: number,
export interface NewToBuy extends StuffAndCategoryAndAmount {
shop: string,
category: string,
newAddition: boolean,
}
export interface Stuff {

Loading…
Cancel
Save