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.
 
 
 
 
 
joint_exc/frontend/src/components/AddStuffAmountDialog.tsx

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;