You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
6.0 KiB
191 lines
6.0 KiB
import { useState } from 'react';
|
|
import {
|
|
Dialog,
|
|
DialogTitle,
|
|
DialogContent,
|
|
DialogActions,
|
|
TextField,
|
|
Button,
|
|
Box,
|
|
InputLabel,
|
|
FormGroup,
|
|
FormControl,
|
|
FormControlLabel,
|
|
Checkbox,
|
|
Select,
|
|
MenuItem,
|
|
} from '@mui/material';
|
|
import { StuffAndCategoryAndAmount, Stuff } from '../types/types';
|
|
import { stuffApi } from '../services/api';
|
|
import { GENERAL_ERRORS } from '../constants/errorMessages';
|
|
import { useMessage } from './MessageContext';
|
|
import '../App.css'
|
|
|
|
|
|
|
|
const AddStuffAmountDialog = ({
|
|
openDialog,
|
|
setOpenDialog,
|
|
newItem,
|
|
setNewItem,
|
|
onSubmit,
|
|
title = "材料の追加",
|
|
children,
|
|
}: {
|
|
openDialog: boolean,
|
|
setOpenDialog: (open: boolean) => void,
|
|
newItem: StuffAndCategoryAndAmount,
|
|
setNewItem: (item: StuffAndCategoryAndAmount) => void,
|
|
onSubmit: () => void,
|
|
title?: string,
|
|
children?: React.ReactNode,
|
|
}) => {
|
|
|
|
const onChangeCategory = async (category: string) => {
|
|
setNewItem({ ...newItem, stuffId: null, category })
|
|
const result = category ? await stuffApi.getStuffs(category) : undefined
|
|
setStuffs(result)
|
|
}
|
|
|
|
const [stuffs, setStuffs] = useState<Stuff[]>();
|
|
|
|
const [newAddition, setNewAddition] = useState(false);
|
|
|
|
// エラーメッセージ表示
|
|
const { showErrorMessage } = useMessage();
|
|
|
|
return (
|
|
|
|
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true}>
|
|
<Box display="flex" alignItems="center">
|
|
<DialogTitle sx={{ flexGrow: 1 }}>{title}</DialogTitle>
|
|
<FormGroup row>
|
|
<FormControlLabel
|
|
control={<Checkbox />}
|
|
label="食材を新規追加"
|
|
checked={newAddition}
|
|
onChange={(e) => setNewAddition((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={newItem.category}
|
|
onChange={(e) => onChangeCategory(e.target.value)}
|
|
>
|
|
<MenuItem value="乳製品">乳製品</MenuItem>
|
|
<MenuItem value="魚・肉">魚・肉</MenuItem>
|
|
<MenuItem value="野菜">野菜</MenuItem>
|
|
<MenuItem value="調味料">調味料</MenuItem>
|
|
<MenuItem value="その他">その他</MenuItem>
|
|
</Select>
|
|
</FormControl>
|
|
|
|
{!newAddition && <FormControl sx={{ width: "100%", marginBottom: 2 }}>
|
|
{stuffs ?
|
|
<>
|
|
<InputLabel id="demo-simple-select-label">材料名(選択)</InputLabel>
|
|
<Select
|
|
labelId="demo-simple-select-label"
|
|
value={newItem.stuffId}
|
|
onChange={(e) => setNewItem({ ...newItem, stuffId: Number(e.target.value) })}
|
|
>
|
|
{stuffs.map((stuff) => (
|
|
<MenuItem key={stuff.stuffId} value={stuff.stuffId}>
|
|
{stuff.stuffName}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</>
|
|
:
|
|
<>
|
|
<InputLabel id="demo-simple-select-label">
|
|
{newItem.category ? '読み込み中...' : 'カテゴリを選択してください...'}
|
|
</InputLabel>
|
|
<Select labelId="demo-simple-select-label" value="" disabled>
|
|
</Select>
|
|
</>
|
|
}
|
|
</FormControl>}
|
|
|
|
{/* タスクタイトル入力フィールド */}
|
|
{newAddition && <TextField
|
|
autoFocus
|
|
margin="dense"
|
|
label="材料名"
|
|
fullWidth
|
|
value={newItem.stuffName}
|
|
onChange={(e) => setNewItem({ ...newItem, stuffName: e.target.value })}
|
|
sx={{ marginBottom: 2 }}
|
|
/>}
|
|
{/* 数量入力フィールド */}
|
|
<TextField
|
|
margin="dense"
|
|
label="数量"
|
|
value={newItem.amount}
|
|
onChange={(e) => {
|
|
const value = e.target.value;
|
|
const parsedValue = parseInt(value, 10); // 数値に変換
|
|
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
|
|
setNewItem({ ...newItem, amount: parsedValue }); // number型で保存
|
|
}
|
|
}}
|
|
onKeyDown={(e) => {
|
|
if (e.key === '-' || e.key === 'e' || e.key === 'E') {
|
|
e.preventDefault();
|
|
}
|
|
}}
|
|
className="numberField"
|
|
type="number"
|
|
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
|
|
|
|
/>
|
|
</Box>
|
|
|
|
{children} {/* ここに追加要素がレンダリングされる */}
|
|
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={() => setOpenDialog(false)}>キャンセル</Button>
|
|
<Button onClick={() => {
|
|
|
|
if (!newItem.category || !stuffs) {
|
|
showErrorMessage(GENERAL_ERRORS.INVALID_CATEGORY);
|
|
return;
|
|
}
|
|
|
|
if (newAddition) {
|
|
newItem.stuffId = null;
|
|
} else if (newItem.stuffId) {
|
|
newItem.stuffName = stuffs.filter(stuff => stuff.stuffId == newItem.stuffId)[0]?.stuffName;
|
|
}
|
|
|
|
if (isNaN(newItem.amount)) {
|
|
showErrorMessage(GENERAL_ERRORS.INVALID_AMOUNT);
|
|
return;
|
|
}
|
|
|
|
newItem.stuffName = newItem.stuffName.trim(); // 材料名の前後の空白を削除
|
|
|
|
if (!newItem.stuffName) {
|
|
showErrorMessage(GENERAL_ERRORS.INVALID_STUFF_NAME);
|
|
return;
|
|
}
|
|
|
|
onSubmit()
|
|
}} variant="contained">
|
|
追加
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
|
|
)
|
|
}
|
|
|
|
export default AddStuffAmountDialog; |