買うものリストの各種ダイアログをコンポーネント化

feature-frontend-dishedit-kato
Masaharu.Kato 4 months ago
parent a20c77b682
commit 1153f69d09
  1. 134
      frontend/src/components/AddStuffAmountDialog.tsx
  2. 83
      frontend/src/components/BuyDialog.tsx
  3. 76
      frontend/src/components/EditAmountDialog.tsx
  4. 302
      frontend/src/pages/TaskListPage.tsx
  5. 29
      frontend/src/types/types.ts

@ -0,0 +1,134 @@
import { useState } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
InputLabel,
FormGroup,
FormControl,
FormControlLabel,
Checkbox,
Select,
MenuItem,
} from '@mui/material';
import { NewToBuy, Stuff } from '../types/types';
import { stuffApi } from '../services/api';
const AddStuffAmountDialog = ({
openDialog,
setOpenDialog,
newToBuy,
setNewToBuy,
onSubmit,
}: {
openDialog: boolean,
setOpenDialog: (open: boolean) => void,
newToBuy: NewToBuy,
setNewToBuy: (tobuy: NewToBuy) => void,
onSubmit: () => void,
}) => {
const onChangeCategory = async (category: string) => {
setNewToBuy({ ...newToBuy, category })
const result = await stuffApi.getStuffs(category)
setStuffs(result)
}
const [stuffs, setStuffs] = useState<Stuff[]>([]);
return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
<Box display="flex" alignItems="center">
<DialogTitle sx={{ flexGrow: 1 }}></DialogTitle>
<FormGroup row>
<FormControlLabel
control={<Checkbox />}
label="食材を新規追加"
checked={newToBuy.newAddition}
onChange={(e) => setNewToBuy({ ...newToBuy, newAddition: (e.target as HTMLInputElement).checked })}
/>
</FormGroup>
</Box>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/*材料カテゴリ選択 */}
<FormControl sx={{ width: "50%", marginBottom: 2 }}>
<InputLabel id="demo-simple-select-label"></InputLabel>
<Select
labelId="demo-simple-select-label"
value={newToBuy.category}
onChange={(e) => onChangeCategory(e.target.value)}
>
<MenuItem value="乳製品"></MenuItem>
<MenuItem value="魚・肉"></MenuItem>
<MenuItem value="野菜"></MenuItem>
<MenuItem value="調味料">調</MenuItem>
<MenuItem value="その他"></MenuItem>
</Select>
</FormControl>
{!newToBuy.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) })}
>
{stuffs.map((stuff) => (
<MenuItem key={stuff.stuffId} value={stuff.stuffId}>
{stuff.stuffName}
</MenuItem>
))}
</Select>
</FormControl>}
{/* タスクタイトル入力フィールド */}
{newToBuy.newAddition && <TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={newToBuy.stuffName}
onChange={(e) => setNewToBuy({ ...newToBuy, stuffName: e.target.value })}
sx={{ marginBottom: 2 }}
/>}
{/* 数量入力フィールド */}
<TextField
margin="dense"
label="数量"
fullWidth
value={newToBuy.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型で保存
}
}}
sx={{ width: "20%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={onSubmit} variant="contained">
</Button>
</DialogActions>
</Dialog>
)
}
export default AddStuffAmountDialog;

@ -0,0 +1,83 @@
import { useState } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
} from '@mui/material';
import { NewStock } from '../types/types';
const BuyDialog = ({
openDialog,
setOpenDialog,
newStock,
setNewStock,
onSubmit,
}: {
openDialog: boolean,
setOpenDialog: (open: boolean) => void,
newStock: NewStock,
setNewStock: (tobuy: NewStock) => void,
onSubmit: () => void,
}) => {
return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
<DialogTitle></DialogTitle>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/* 価格入力フィールド */}
<TextField
autoFocus
margin="dense"
label="価格"
fullWidth
value={newStock.price}
onChange={(e) => {
const value = e.target.value;
if (/^\d*$/.test(value)) {
setNewStock({ ...newStock, price: value })
};
}}
/>
{/* 購入日入力フィールド */}
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
value={newStock.buyDate}
onChange={(e) => setNewStock({ ...newStock, buyDate: e.target.value })}
/>
{/* 消費・賞味期限入力フィールド */}
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
value={newStock.expDate}
onChange={(e) => setNewStock({ ...newStock, expDate: e.target.value })}
/>
{/* 購入店舗入力フィールド */}
{/* TODO: 実装 */}
<TextField
margin="dense"
label="店舗"
fullWidth
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={() => { onSubmit() }} variant="contained"></Button>
</DialogActions>
</Dialog>
)
}
export default BuyDialog;

@ -0,0 +1,76 @@
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box,
} from '@mui/material';
import { ToBuy } from '../types/types';
const EditAmountDialog = ({
openDialog,
setOpenDialog,
editingTobuy,
setEditingTobuy,
onSubmit
}: {
openDialog: boolean,
setOpenDialog: (open: boolean) => void,
editingTobuy: ToBuy,
setEditingTobuy: (tobuy: ToBuy) => void,
onSubmit: () => void,
}) => {
return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
<Box display="flex" alignItems="center">
<DialogTitle sx={{ flexGrow: 1 }}></DialogTitle>
</Box>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/* 材料名表示 */}
<TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={editingTobuy.stuffName}
disabled
sx={{ marginBottom: 2 }}
/>
{/* 数量入力フィールド */}
<TextField
margin="dense"
label="数量"
fullWidth
value={editingTobuy.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型で保存
}
}}
sx={{ width: "20%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={onSubmit} variant="contained">
</Button>
</DialogActions>
</Dialog>
)
}
export default EditAmountDialog;

@ -3,8 +3,7 @@
* *
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { toBuyApi, stuffApi } from '../services/api'; import { toBuyApi } from '../services/api';
import { useNavigate, Outlet, useLocation } from 'react-router-dom';
import { import {
Container, Container,
Typography, Typography,
@ -14,34 +13,24 @@ import {
ListItemText, ListItemText,
ListItemSecondaryAction, ListItemSecondaryAction,
IconButton, IconButton,
Checkbox,
Fab, Fab,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Box, Box,
FormControlLabel,
FormGroup,
FormControl,
InputLabel,
Select,
MenuItem
} from '@mui/material'; } from '@mui/material';
import { import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon, Edit as EditIcon SoupKitchen as SoupKitchenIcon, Edit as EditIcon
} from '@mui/icons-material'; } from '@mui/icons-material';
import { ToBuy, Stuff, /*Stock*/ } from '../types/types'; import { ToBuy, Stuff, NewToBuy, NewStock, /*Stock*/ } from '../types/types';
import { TOBUY_ERRORS } from '../constants/errorMessages'; import { TOBUY_ERRORS } from '../constants/errorMessages';
import EditAmountDialog from '../components/EditAmountDialog';
import AddStuffAmountDialog from '../components/AddStuffAmountDialog';
import BuyDialog from '../components/BuyDialog';
//import { FaCarrot } from "react-icons/fa6"; //エラー起きる いったん保留 //import { FaCarrot } from "react-icons/fa6"; //エラー起きる いったん保留
// 新規タスクの初期状態 // 新規タスクの初期状態
const EMPTY_TOBUY: Omit<ToBuy, 'tobuyId' | 'stuffId'> & { stuffId: number | null, category: string } & { newAddition: boolean } = { const EMPTY_TOBUY: NewToBuy = {
stuffId: null, stuffId: null,
stuffName: '', stuffName: '',
amount: 1, amount: 1,
@ -50,41 +39,37 @@ const EMPTY_TOBUY: Omit<ToBuy, 'tobuyId' | 'stuffId'> & { stuffId: number | null
newAddition: false, newAddition: false,
} }
const EMPTY_STOCK = {
price: 0,
buyDate: '',
expDate: '',
}
const TaskListPage: React.FC = () => { const TaskListPage: React.FC = () => {
// タスク一覧の状態管理 // タスク一覧の状態管理
const [tobuys, setToBuys] = useState<ToBuy[]>([]); const [tobuys, setToBuys] = useState<ToBuy[]>([]);
// 新規タスク作成ダイアログの表示状態
const [openDialog, setOpenDialog] = useState(false); // 買うものリストへの食材追加ダイアログの表示状態
const [openAddToBuyDialog, setOpenAddToBuyDialog] = useState(false);
//在庫登録ダイアログの表示状態 //在庫登録ダイアログの表示状態
const [openInfoDialog, setOpenInfoDialog] = useState(false); const [openInfoDialog, setOpenInfoDialog] = useState(false);
//数量変更ダイアログの表示状態 //数量変更ダイアログの表示状態
const [openAmountDialog, setOpenAmountDialog] = useState(false); const [openAmountDialog, setOpenAmountDialog] = useState(false);
const [selectedTask, setSelectedTask] = useState<ToBuy["tobuyId"]>(0); const [selectedToBuyId, setSelectedToBuyId] = useState<ToBuy["tobuyId"]>(0);
const [selectedEditingTask, setSelectedEditingTask] = useState<ToBuy>({ const [newStock, setNewStock] = useState<NewStock>({
tobuyId: 0, price: '', // ここではstring
stuffId: 0, buyDate: '',
stuffName: "", expDate: '',
amount: 0, });
shop: undefined,
}); const [editingTask, setEditingTask] = useState<ToBuy>({
tobuyId: 0,
stuffId: 0,
stuffName: "",
amount: 0,
shop: undefined,
});
const [newToBuy, setNewToBuy] = useState(EMPTY_TOBUY); const [newToBuy, setNewToBuy] = useState(EMPTY_TOBUY);
const [stuffs, setStuffs] = useState<Stuff[]>([]);
const [newStock, setNewStock] = useState(EMPTY_STOCK);
const [newPrice, setNewPrice] = useState("");//入力用の価格(文字列)
// コンポーネントマウント時にタスク一覧を取得 // コンポーネントマウント時にタスク一覧を取得
@ -106,12 +91,6 @@ const TaskListPage: React.FC = () => {
} }
}; };
const onChangeCategory = async (category: string) => {
setNewToBuy({ ...newToBuy, category })
const result = await stuffApi.getStuffs(category)
setStuffs(result)
}
// /** // /**
// * タスクの完了状態を切り替えるハンドラー // * タスクの完了状態を切り替えるハンドラー
// * 対象タスクの完了状態を反転させてAPIに更新を要求 // * 対象タスクの完了状態を反転させてAPIに更新を要求
@ -129,10 +108,10 @@ const TaskListPage: React.FC = () => {
// }; // };
/** /**
* *
* IDのタスクをAPIを通じて削除 * IDのタスクをAPIを通じて削除
*/ */
const handleDeleteTask = async (toBuyId: number) => { const handleDeleteToBuy = async (toBuyId: number) => {
try { try {
await toBuyApi.deleteToBuy(toBuyId); await toBuyApi.deleteToBuy(toBuyId);
fetchTasks(); // 削除後の買うもの一覧を再取得 fetchTasks(); // 削除後の買うもの一覧を再取得
@ -144,20 +123,18 @@ const TaskListPage: React.FC = () => {
/** /**
* *
*/ */
const handleBuy = async (tobuyId: number) => { const handleBuy = async () => {
try { try {
const today = new Date().toISOString().substring(0, 10); const today = new Date().toISOString().substring(0, 10);
const parsedPrice = parseInt(newPrice, 10); const parsedPrice = parseInt(newStock.price, 10);
console.log("newPrice") console.log("newPrice:", newStock.price)
console.log(newPrice) console.log("parsedPrice: ", parsedPrice)
console.log("parsedPrice")
console.log(parsedPrice)
if (isNaN(parsedPrice)) { if (isNaN(parsedPrice)) {
alert('入力が無効です') alert('入力が無効です')
return return
//setNewStock({ ...newStock, price: parsedPrice }); //setNewStock({ ...newStock, price: parsedPrice });
} }
await toBuyApi.buy({ tobuyId, ...newStock, price: parsedPrice, lastUpdate: today }); //データベースに送信 await toBuyApi.buy({ tobuyId: selectedToBuyId, ...newStock, price: parsedPrice, lastUpdate: today }); //データベースに送信
fetchTasks(); // 削除後の買うもの一覧を再取得 fetchTasks(); // 削除後の買うもの一覧を再取得
} catch (error) { } catch (error) {
console.error(`${TOBUY_ERRORS.BUY_FAILED}:`, error); console.error(`${TOBUY_ERRORS.BUY_FAILED}:`, error);
@ -165,11 +142,11 @@ const TaskListPage: React.FC = () => {
}; };
/** /**
* *
* APIに送信して新規作成 * APIに送信して新規作成
* *
*/ */
const handleCreateTask = async () => { const handleAddNewToBuy = async () => {
try { try {
if (newToBuy.newAddition) { if (newToBuy.newAddition) {
newToBuy.stuffId = null; newToBuy.stuffId = null;
@ -181,7 +158,7 @@ const TaskListPage: React.FC = () => {
console.log(newToBuy) console.log(newToBuy)
await toBuyApi.addToBuy(newToBuy); await toBuyApi.addToBuy(newToBuy);
setOpenDialog(false); // ダイアログを閉じる setOpenAddToBuyDialog(false); // ダイアログを閉じる
setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット
fetchTasks(); // 作成後のタスク一覧を再取得 fetchTasks(); // 作成後のタスク一覧を再取得
} catch (error) { } catch (error) {
@ -194,15 +171,15 @@ const TaskListPage: React.FC = () => {
* APIに送信して変更 * APIに送信して変更
* *
*/ */
const handleUpdateTask = async () => { const handleUpdateNewToBuy = async () => {
try { try {
if (isNaN(selectedEditingTask.amount)) { if (isNaN(editingTask.amount)) {
console.log('数量が正しくありません.'); console.log('数量が正しくありません.');
return; return;
} }
console.log(selectedEditingTask) console.log(editingTask)
await toBuyApi.updateToBuy(selectedEditingTask); await toBuyApi.updateToBuy(editingTask);
setOpenAmountDialog(false); // ダイアログを閉じる setOpenAmountDialog(false); // ダイアログを閉じる
//setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット //setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット
fetchTasks(); // 作成後のタスク一覧を再取得 fetchTasks(); // 作成後のタスク一覧を再取得
@ -269,7 +246,7 @@ const TaskListPage: React.FC = () => {
aria-label="数量変更" aria-label="数量変更"
onClick={() => { onClick={() => {
setOpenAmountDialog(true) setOpenAmountDialog(true)
setSelectedEditingTask(tobuy) setEditingTask(tobuy)
}} }}
> >
<EditIcon /> <EditIcon />
@ -284,7 +261,7 @@ const TaskListPage: React.FC = () => {
aria-label="購入情報を記入" aria-label="購入情報を記入"
onClick={() => { onClick={() => {
setOpenInfoDialog(true) setOpenInfoDialog(true)
setSelectedTask(tobuy.tobuyId) setSelectedToBuyId(tobuy.tobuyId)
// handleDeleteTask(tobuy.tobuyId) // handleDeleteTask(tobuy.tobuyId)
}} }}
> >
@ -311,7 +288,7 @@ const TaskListPage: React.FC = () => {
edge="end" edge="end"
sx={{ marginRight: 0, marginLeft: 0 }} sx={{ marginRight: 0, marginLeft: 0 }}
aria-label="delete" aria-label="delete"
onClick={() => handleDeleteTask(tobuy.tobuyId)} onClick={() => handleDeleteToBuy(tobuy.tobuyId)}
> >
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
@ -331,7 +308,7 @@ const TaskListPage: React.FC = () => {
<Fab <Fab
color="primary" color="primary"
sx={{ position: 'fixed', bottom: 16, left: '40%', transform: 'translateX(-50%)' }} sx={{ position: 'fixed', bottom: 16, left: '40%', transform: 'translateX(-50%)' }}
onClick={() => setOpenDialog(true)} onClick={() => setOpenAddToBuyDialog(true)}
> >
<AddIcon /> <AddIcon />
</Fab> </Fab>
@ -346,7 +323,7 @@ const TaskListPage: React.FC = () => {
color="primary" color="primary"
sx={{ position: 'fixed', bottom: 16, left: '60%', transform: 'translateX(-50%)' }} sx={{ position: 'fixed', bottom: 16, left: '60%', transform: 'translateX(-50%)' }}
onClick={() => { onClick={() => {
setOpenDialog(true); setOpenAddToBuyDialog(true);
//handleNavigate('/AddDishies1'); //handleNavigate('/AddDishies1');
}} }}
//selected={isSelected('/test')} //selected={isSelected('/test')}
@ -356,195 +333,14 @@ const TaskListPage: React.FC = () => {
{/* 新規タスク作成ダイアログ */} {/* 新規タスク作成ダイアログ */}
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}> <AddStuffAmountDialog openDialog={openAddToBuyDialog} setOpenDialog={setOpenAddToBuyDialog} newToBuy={newToBuy} setNewToBuy={setNewToBuy} onSubmit={handleAddNewToBuy} />
<Box display="flex" alignItems="center">
<DialogTitle sx={{ flexGrow: 1 }}></DialogTitle>
<FormGroup row>
<FormControlLabel
control={<Checkbox />}
label="食材を新規追加"
checked={newToBuy.newAddition}
onChange={(e) => setNewToBuy({ ...newToBuy, newAddition: (e.target as HTMLInputElement).checked })}
/>
</FormGroup>
</Box>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/*材料カテゴリ選択 */}
<FormControl sx={{ width: "50%", marginBottom: 2 }}>
<InputLabel id="demo-simple-select-label"></InputLabel>
<Select
labelId="demo-simple-select-label"
value={newToBuy.category}
onChange={(e) => onChangeCategory(e.target.value)}
>
<MenuItem value="乳製品"></MenuItem>
<MenuItem value="魚・肉"></MenuItem>
<MenuItem value="野菜"></MenuItem>
<MenuItem value="調味料">調</MenuItem>
<MenuItem value="その他"></MenuItem>
</Select>
</FormControl>
{!newToBuy.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) })}
>
{stuffs.map((stuff) => (
<MenuItem key={stuff.stuffId} value={stuff.stuffId}>
{stuff.stuffName}
</MenuItem>
))}
</Select>
</FormControl>}
{/* タスクタイトル入力フィールド */}
{newToBuy.newAddition && <TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={newToBuy.stuffName}
onChange={(e) => setNewToBuy({ ...newToBuy, stuffName: e.target.value })}
sx={{ marginBottom: 2 }}
/>}
{/* 数量入力フィールド */}
<TextField
margin="dense"
label="数量"
fullWidth
value={newToBuy.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型で保存
}
}}
sx={{ width: "20%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)}></Button>
<Button onClick={handleCreateTask} variant="contained">
</Button>
</DialogActions>
</Dialog>
{/*在庫登録のための数値入力ダイアログ */} {/*在庫登録のための数値入力ダイアログ */}
<Dialog open={openInfoDialog} onClose={() => setOpenInfoDialog(false)} disableScrollLock={true}> <BuyDialog openDialog={openInfoDialog} setOpenDialog={setOpenInfoDialog} newStock={newStock} setNewStock={setNewStock} onSubmit={handleBuy} />
<DialogTitle></DialogTitle>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/* 価格入力フィールド */}
<TextField
autoFocus
margin="dense"
label="価格"
fullWidth
value={newPrice}
onChange={(e) => {
const value = e.target.value;
if (/^\d*$/.test(value)) {
setNewPrice(value)
};
}}
/>
{/* 購入日入力フィールド */}
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
value={newStock.buyDate}
onChange={(e) => setNewStock({ ...newStock, buyDate: e.target.value })}
/>
{/* 消費・賞味期限入力フィールド */}
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
value={newStock.expDate}
onChange={(e) => setNewStock({ ...newStock, expDate: e.target.value })}
/>
{/* 購入店舗入力フィールド */}
<TextField
margin="dense"
label="店舗"
fullWidth
value={newToBuy.shop}
onChange={(e) => setNewToBuy({ ...newToBuy, shop: e.target.value })}
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenInfoDialog(false)}></Button>
<Button onClick={() => {
if (selectedTask) {
handleBuy(selectedTask)
setOpenInfoDialog(false)
setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット
}
}}
variant="contained">
</Button>
</DialogActions>
</Dialog>
{/* 数量変更ダイアログ */} {/* 数量変更ダイアログ */}
<Dialog open={openAmountDialog} onClose={() => setOpenAmountDialog(false)} disableScrollLock={true}> <EditAmountDialog openDialog={openAmountDialog} setOpenDialog={setOpenAmountDialog} editingTobuy={editingTask} setEditingTobuy={setEditingTask} onSubmit={handleUpdateNewToBuy} />
<Box display="flex" alignItems="center">
<DialogTitle sx={{ flexGrow: 1 }}></DialogTitle>
</Box>
<DialogContent>
<Box sx={{ pt: 1 }}>
{/* 材料名表示 */}
<TextField
autoFocus
margin="dense"
label="材料名"
fullWidth
value={selectedEditingTask.stuffName}
disabled
sx={{ marginBottom: 2 }}
/>
{/* 数量入力フィールド */}
<TextField
margin="dense"
label="数量"
fullWidth
value={selectedEditingTask.amount}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
setSelectedEditingTask({ ...selectedEditingTask, amount: parsedValue }); // number型で保存
}
}}
sx={{ width: "20%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenAmountDialog(false)}></Button>
<Button onClick={handleUpdateTask} variant="contained">
</Button>
</DialogActions>
</Dialog>
</Container> </Container>
); );

@ -18,8 +18,8 @@
// } // }
/** /**
* *
* *
*/ */
export interface ToBuy { export interface ToBuy {
tobuyId: number, tobuyId: number,
@ -29,6 +29,18 @@ export interface ToBuy {
shop?: string, shop?: string,
} }
/**
*
*/
export interface NewToBuy {
stuffId: null | number,
stuffName: string,
amount: number,
shop: string,
category: string,
newAddition: boolean,
}
export interface Stuff { export interface Stuff {
stuffId: number, stuffId: number,
stuffName: string, stuffName: string,
@ -51,6 +63,15 @@ export interface Stock {
category: string, category: string,
} }
/**
*
*/
export interface NewStock {
price: string,
buyDate: string,
expDate: string,
}
/** /**
* *
* *
@ -94,9 +115,9 @@ export interface RegisterCredentials {
export interface Recipes { export interface Recipes {
recipeName: string;// レシピ名 recipeName: string;// レシピ名
summary: string;// レシピ概要 summary: string;// レシピ概要
// 材料リスト(直接配列として内包) // 材料リスト(直接配列として内包)
stuffAndAmountArray : Array<{ stuffAndAmountArray: Array<{
// 既存材料IDまたは新規作成情報のどちらか一方のみ必要 // 既存材料IDまたは新規作成情報のどちらか一方のみ必要
stuffId?: number; // 既存材料ID(オプション) stuffId?: number; // 既存材料ID(オプション)
stuffName?: string;// 新規材料名(オプション) stuffName?: string;// 新規材料名(オプション)

Loading…
Cancel
Save