Compare commits

...

3 Commits

  1. 4
      frontend/src/App.css
  2. 22
      frontend/src/components/AddByRecipeDialog.tsx
  3. 5
      frontend/src/components/AddStuffAmountDialog.tsx
  4. 12
      frontend/src/components/DeleteStuffDialog.tsx
  5. 43
      frontend/src/components/Layout.tsx
  6. 33
      frontend/src/components/StuffHistoryDialog.tsx
  7. 2
      frontend/src/index.css
  8. 14
      frontend/src/pages/RecipeList.tsx
  9. 24
      frontend/src/pages/StockPage.tsx
  10. 4
      frontend/src/pages/TaskListPage.tsx

@ -23,8 +23,8 @@ body {
/* Material UIのコンテナコンポーネントのカスタマイズ */
.MuiContainer-root {
padding-top: 24px;
padding-bottom: 24px;
/* padding-top: 24px;
padding-bottom: 24px; */
}
/* Material UIのペーパーコンポーネントのカスタマイズ */

@ -76,10 +76,10 @@ const AddByRecipeDialog = ({
/>
</DialogTitle>
<DialogContent dividers sx={{ padding: 2 }}>
<Typography variant="h3">
<Typography sx={{fontSize: '1.6rem'}}>
{recipe.recipeName}
</Typography>
<Typography>
<Typography sx={{mt: 2, mb: 2}}>
({recipe.maxServings})
</Typography>
<div>
@ -112,11 +112,17 @@ const AddByRecipeDialog = ({
defaultValue={1}
value={numOfPeople}
onChange={(e) => {
// const num = parseInt(e.target.value, 10);
// setNumOfPeaple(!isNaN(num) ? num : '');
setNumOfPeaple(e.target.value);
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
setNumOfPeaple(value);
}
}}
onKeyDown={(e) => {
if (e.key === '-' || e.key === 'e' || e.key === 'E') {
e.preventDefault();
}
}}
sx={{ minWidth: "8px", width: "100%" }}
inputProps={{ inputMode: "numeric", min: 1, pattern: "[0-9]*" }} // ここで整数のみ許可
/>
@ -133,14 +139,14 @@ const AddByRecipeDialog = ({
color="primary"
onClick={async () => {
const num = parseInt(numOfPeople, 10);
if (!num || isNaN(num)) {
if (!num || isNaN(num) || num <= 0) {
showErrorMessage('人数が正しく入力されていません。');
return;
}
const finalAddResult = await toBuyApi.addByRecipe(recipe.recipeId, num, checked);
setOpenDialog(false);
if (finalAddResult.data.length === 0) {
showInfoMessage('必要な食材が在庫にあったのでリストには追加されませんでした');
showInfoMessage('必要な食材が在庫にあったのでリストには追加されませんでした');
} else {
showSuccessMessage('レシピが保存されて買うものリストに追加されました!');
}

@ -136,6 +136,11 @@ const AddStuffAmountDialog = ({
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]*" }} // ここで整数のみ許可

@ -4,6 +4,7 @@ import {
DialogContent,
Button,
Typography,
DialogActions,
} from '@mui/material';
const DeleteStuffDialog = ({
@ -26,15 +27,16 @@ const DeleteStuffDialog = ({
>
<DialogTitle></DialogTitle>
<DialogContent>
<Typography variant="h4">{stuffName}</Typography>
<Typography sx={{fontSize: '1.6rem'}}>{stuffName} </Typography>
<Typography variant="body1" color="error"> 注意: 削除すると復元できません</Typography>
<Button onClick={() => setOpenDialog(false)} sx={{ mt: 3, mb: 2, left: '70%' }}></Button>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenDialog(false)} ></Button>
<Button variant="contained" color="error" onClick={() => {
onSubmit();
setOpenDialog(false); // 削除処理後にダイアログを閉じる
}}
style={{ marginTop: "10px" }} sx={{ mt: 3, mb: 2, left: '72%' }}></Button>
</DialogContent>
}}></Button>
</DialogActions>
</Dialog>
}

@ -76,10 +76,6 @@ const Layout: React.FC = () => {
navigate('/login');
};
// メニューを開閉するハンドラー
const toggleDrawer = () => {
setDrawerOpen(!drawerOpen);
@ -119,7 +115,21 @@ const Layout: React.FC = () => {
sessionStorage.removeItem('globalMessage');
};
const onBottomNaviChange = (event: React.SyntheticEvent, value: any) => {
setBottomNavi(value);
switch (value) {
case 0:
navigate('stock');
break;
case 1:
navigate('tasks');
break;
case 2:
navigate('recipeList');
break;
}
// ここでルーティング処理などを行う
}
return (
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
@ -135,29 +145,11 @@ const Layout: React.FC = () => {
</Toolbar>
</AppBar>
<Paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0, zIndex: (theme) => theme.zIndex.drawer + 1 }} elevation={3}>
<BottomNavigation
showLabels
value={bottomNavi}
onChange={(event, newValue) => {
setBottomNavi(newValue);
switch (newValue) {
case 0:
navigate('stock');
break;
case 1:
navigate('tasks');
break;
case 2:
navigate('recipeList');
break;
}
// ここでルーティング処理などを行う
}}
onChange={onBottomNaviChange}
>
<BottomNavigationAction label="在庫" icon={<InventoryIcon />} />
<BottomNavigationAction label="買うもの" icon={<ShoppingCartIcon />} />
@ -165,10 +157,9 @@ const Layout: React.FC = () => {
</BottomNavigation>
</Paper>
{/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */}
<Box component="main" sx={{ flexGrow: 1, bgcolor: 'background.default', py: 3 }}>
<Container sx={{ padding: 0, margin: 0 }}>
<Container sx={{ padding: 0, mt: 0, mb: 0, mr: 'auto', ml: 'auto' }}>
<MessageContext.Provider value={{ showErrorMessage, showWarningMessage, showSuccessMessage, showInfoMessage }}>
<MessageAlert
open={msgOpen}

@ -14,7 +14,8 @@ import {
TableHead, // 追加
TableRow, // 追加
Paper,
Typography, // 追加: TableContainerの背景用
Typography,
styled, // 追加: TableContainerの背景用
} from '@mui/material';
import CloseIcon from '@mui/icons-material/Close'; // 追加: 閉じるアイコンをインポート
import { StockHistory } from '../types/types';
@ -31,6 +32,14 @@ const StuffHistoryDialog = ({
stockHistories: StockHistory[],
}) => {
const StyledTableCell = styled(TableCell)({
paddingTop: '8px',
paddingBottom: '8px',
paddingLeft: '8px',
paddingRight: '8px',
whiteSpace: 'nowrap',
})
return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true} PaperProps={{ sx: { minWidth: '90vw', maxHeight: '80vh' } }}>
<DialogTitle sx={{ m: 0, p: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
@ -62,15 +71,15 @@ const StuffHistoryDialog = ({
overflowX: 'auto',
}}
>
<Table sx={{ minWidth: 400 }} aria-label="purchase history table">
<TableHead sx={{ backgroundColor: "#dcdcdc", color: "#333" }}>
<Table aria-label="purchase history table">
<TableHead sx={{ backgroundColor: "#ebcba2", color: "#333" }}>
<TableRow>
{/* 各ヘッダーセルに white-space: nowrap; を適用 */}
<TableCell sx={{ whiteSpace: 'nowrap' }}></TableCell>
<StyledTableCell></StyledTableCell>
{/* 「購入店舗」ヘッダーも nowrap にし、minWidth でスクロールを考慮 */}
<TableCell sx={{ whiteSpace: 'nowrap', minWidth: '120px' }}></TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell>
<StyledTableCell></StyledTableCell>
<StyledTableCell align="right"></StyledTableCell>
<StyledTableCell align="right"></StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
@ -80,13 +89,13 @@ const StuffHistoryDialog = ({
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
{/* 各ボディセルに white-space: nowrap; を適用 */}
<TableCell component="th" scope="row" sx={{ whiteSpace: 'nowrap' }}>
<StyledTableCell component="th" scope="row" sx={{ whiteSpace: 'nowrap' }}>
{history.buyDate}
</TableCell>
</StyledTableCell>
{/* 「購入店舗」セルに nowrap と minWidth を適用 */}
<TableCell sx={{ whiteSpace: 'nowrap', minWidth: '150px' }}>{history.shop || ''}</TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}>{history.buyAmount}</TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}>{history.price}</TableCell>
<StyledTableCell sx={{whiteSpace: 'wrap'}}>{history.shop || ''}</StyledTableCell>
<StyledTableCell align="right" sx={{pr: '16px'}}>{history.buyAmount}</StyledTableCell>
<StyledTableCell align="right" sx={{pr: '16px'}}>{history.price}</StyledTableCell>
</TableRow>
))}
</TableBody>

@ -18,7 +18,7 @@ html, body {
-moz-osx-font-smoothing: grayscale;
/* スクロールバーのレイアウトシフトを防止 */
scrollbar-gutter: stable both-edges;
overflow: auto
overflow: auto;
}
/* ルート要素のスタイル - Reactアプリケーションのマウントポイント */

@ -114,26 +114,26 @@ const RecipeList: React.FC = () => {
<ListItemSecondaryAction>
{recipe.maxServings ?
<Typography variant="body1" component="span" sx={{ marginRight: '1em', color: "mediumaquamarine" }}>
<Typography variant="body1" component="span" sx={{ mr: 0, color: "mediumaquamarine" }}>
{recipe.maxServings}
</Typography>
: <></>}
{recipe.maxServings === 0 ?
<Tooltip title="" sx={{ color: "tomato" }}>
<IconButton edge="end" aria-label="">
<Tooltip title="">
<IconButton sx={{ mr: 0, ml: 0, color: "tomato" }} edge="end" aria-label="">
<CloseIcon />
</IconButton>
</Tooltip> :
<Tooltip title="" sx={{ color: "mediumaquamarine" }}>
<IconButton edge="end" aria-label="">
<Tooltip title="">
<IconButton sx={{ mr: 0, ml: 0, color: "mediumaquamarine" }} edge="end" aria-label="">
<TaskAltIcon />
</IconButton>
</Tooltip>
}
<Tooltip title="編集">
<IconButton edge="end" aria-label="編集"
<Tooltip title="編集" sx={{}}>
<IconButton sx={{ mr: 0, ml: 0 }} edge="end" aria-label="編集"
onClick={() => {
navigate('/addRecipe/' + recipe.recipeId);
}}

@ -453,6 +453,7 @@ const StockPage: React.FC = () => {
margin="normal"
name="amount"
type="number"
fullWidth
className="numberField"
value={editStock.amount}
onChange={handleChange}
@ -470,7 +471,7 @@ const StockPage: React.FC = () => {
margin="normal"
name="buyAmount"
type="number"
className="numberField"
fullWidth
value={editStock.buyAmount}
onChange={handleChange}
inputProps={{ min: 0 }}
@ -484,10 +485,10 @@ const StockPage: React.FC = () => {
{/* 購入価格フィールド */}
<TextField
label="購入価格"
fullWidth
margin="normal"
name="price"
type="number"
fullWidth
value={editStock.price}
onChange={handleChange}
inputProps={{ min: 0 }}
@ -511,19 +512,18 @@ const StockPage: React.FC = () => {
{/* 購入日・賞味期限入力 */}
<BuyExpDateSelect newStock={editStock} setNewStock={({ buyDate, expDate }) => setEditStock({ ...editStock, buyDate, expDate })} />
<Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, mt: 3, mb: 2 }}>
</>
)}
</DialogContent>
<DialogActions>
<Button onClick={() => { setOpenEditDialog(false); setSelectedRow(null); }}>
</Button>
<Button variant="contained" color="success" onClick={handleApplyChanges} sx={{ mt: 3, mb: 2 }}>
<Button variant="contained" color="success" onClick={handleApplyChanges}>
</Button>
<Button variant="contained" color="error" onClick={() => setOpenDeleteDialog(true)} sx={{ mt: 3, mb: 2 }}></Button>
</Box>
</>
)}
</DialogContent>
<Button variant="contained" color="error" onClick={() => setOpenDeleteDialog(true)}></Button>
</DialogActions>
</Dialog>
{/* 削除ダイアログ */}
@ -613,10 +613,10 @@ const StockPage: React.FC = () => {
{!openCategory[category] ? <ArrowDownIcon color="primary" /> : <ArrowUpIcon color="primary" />}
{category}
</Typography>
{!stocks
{openCategory[category] && (!stocks
? <Typography>...</Typography>
: StockTable(stocks, [category])
}
)}
</Box>
)
})}

@ -290,7 +290,7 @@ const TaskListPage: React.FC = () => {
</Typography>
{/* 買い物リスト:数量変更ボタン */}
<Tooltip title="数量変更">
<IconButton sx={{ marginRight: 0, marginLeft: 0 }} edge="end" aria-label="数量変更"
<IconButton sx={{ mr: 0, ml: 0 }} edge="end" aria-label="数量変更"
onClick={() => {
setOpenAmountDialog(true)
setEditingItem(tobuy)
@ -301,7 +301,7 @@ const TaskListPage: React.FC = () => {
</Tooltip>
{/* 買い物リスト:食材情報記入ボタン */}
<Tooltip title="購入情報を記入">
<IconButton color="primary" sx={{ marginRight: 0, marginLeft: 0 }} edge="end" aria-label="購入情報を記入"
<IconButton color="primary" sx={{ mr: 0, ml: 0 }} edge="end" aria-label="購入情報を記入"
onClick={() => {
setOpenInfoDialog(true)
setEditingItem(tobuy)

Loading…
Cancel
Save