全体的なレイアウトを統一

feature-dishuiandcolor^2
Masaharu.Kato 4 months ago
parent 2f910ce675
commit 51886f3730
  1. 40
      frontend/src/App.css
  2. 2
      frontend/src/App.tsx
  3. 2
      frontend/src/components/Layout.tsx
  4. 19
      frontend/src/pages/AddRecipe.tsx
  5. 62
      frontend/src/pages/RecipeList.tsx
  6. 455
      frontend/src/pages/StockPage.tsx
  7. 41
      frontend/src/pages/TaskListPage.tsx

@ -31,3 +31,43 @@ body {
.MuiPaper-root { .MuiPaper-root {
background-color: white; /* 白背景を確保 */ background-color: white; /* 白背景を確保 */
} }
.mainContainer {
padding-top: 0;
padding-left: 0;
padding-right: 0;
padding-bottom: 80px; /* ボトムナビゲーションバーで隠れる分 */
}
.mainTitle {
padding-left: 1rem;
font-size: 2rem;
margin-bottom: 0.25rem;
}
.listWrapper {
background: #ebcba2;
margin: 0;
padding: 1rem;
}
.plusButtonWrapper {
position: fixed !important;
text-align: center;
bottom: 80px;
left: 80%;
transform: translateX(-50%);
}
.plusButtonLabel {
font-size: 0.9rem;
color: #000;
background: rgba(255, 255, 255, 0.8);
padding: 0.5rem;
border-radius: 4px;
white-space: nowrap;
}
.plusButton {
/* box-shadow: 0px 4px 15px 5px #ebcba2 !important; */
}

@ -29,7 +29,7 @@ const theme = createTheme({
palette: { palette: {
mode: 'light', mode: 'light',
primary: { primary: {
main: '#1976d2', main: '#d27619',
}, },
secondary: { secondary: {
main: '#dc004e', main: '#dc004e',

@ -167,7 +167,7 @@ const Layout: React.FC = () => {
{/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */} {/* メインコンテンツ領域 - 子ルートのコンポーネントがここに表示される */}
<Box component="main" sx={{ flexGrow: 1, bgcolor: 'background.default', py: 3 }}> <Box component="main" sx={{ flexGrow: 1, bgcolor: 'background.default', py: 3 }}>
<Container> <Container sx={{ padding: 0, margin: 0 }}>
<MessageContext.Provider value={{ showErrorMessage, showWarningMessage, showSuccessMessage, showInfoMessage }}> <MessageContext.Provider value={{ showErrorMessage, showWarningMessage, showSuccessMessage, showInfoMessage }}>
<MessageAlert <MessageAlert
open={msgOpen} open={msgOpen}

@ -21,6 +21,7 @@ import {
Checkbox, Checkbox,
FormControlLabel, FormControlLabel,
Box, Box,
Container,
} 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,
@ -203,16 +204,17 @@ const AddRecipe: React.FC = () => {
}, []); }, []);
return ( return (
<> <div className="mainContainer">
{(recipeId && !recipeLoaded) {(recipeId && !recipeLoaded)
? <p>...</p> ? <p>...</p>
: :
<Box> <>
<div className="mainTitle">
<SoupKitchenIcon sx={{ marginRight: "0.5em" }} />
{!recipeId ? '料理の追加' : '料理の編集'}
</div>
<div style={{padding: '1rem'}}>
<div> <div>
<h1>
<SoupKitchenIcon sx={{ marginRight: "0.5em" }} />
{!recipeId ? '料理の追加' : '料理の編集'}
</h1>
<TextField autoFocus margin="dense" label="料理名" fullWidth <TextField autoFocus margin="dense" label="料理名" fullWidth
value={recipeName} onChange={(e) => setRecipeName(e.target.value)} value={recipeName} onChange={(e) => setRecipeName(e.target.value)}
/> />
@ -381,9 +383,10 @@ const AddRecipe: React.FC = () => {
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
</Box> </div>
</>
} }
</> </div>
); );
}; };

@ -26,6 +26,7 @@ import {
FormControl, FormControl,
InputLabel InputLabel
} from '@mui/material'; } from '@mui/material';
import '../App.css';
import { import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon, Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon SoupKitchen as SoupKitchenIcon
@ -46,7 +47,7 @@ const RecipeList: React.FC = () => {
const openRecipeById = (recipeId: number) => { const openRecipeById = (recipeId: number) => {
navigate('/addRecipe/' + recipeId); navigate('/addRecipe/' + recipeId);
} }
const fetchAllRecipes = async () => { const fetchAllRecipes = async () => {
try { try {
const recipes = await recipeApi.getAllRecipes(); const recipes = await recipeApi.getAllRecipes();
@ -63,54 +64,45 @@ const RecipeList: React.FC = () => {
}, []); }, []);
return ( return (
<Container> <div className="mainContainer">
<Box> <div className="mainTitle">
<div> <SoupKitchenIcon sx={{ mr: "0.5em" }} />
<h1 style={{ fontSize: "40px", textAlign: "center" }}></h1>
</div> </div>
<div style={{ <div className="listWrapper">
border: '3px solid black', borderRadius: '8px', height: '500px', <List>
overflowY: 'auto', padding: '20px'
}}>
{/* <List> */}
{/* 料理一覧をマップして各タスクをリストアイテムとして表示 */} {/* 料理一覧をマップして各タスクをリストアイテムとして表示 */}
{!allRecipes {!allRecipes
? <p>...</p> ? <p>...</p>
: allRecipes.map((recipe, index) => ( : allRecipes.map((recipe, index) => (
<FormGroup> <ListItem
<Button
// <ListItem
key={recipe.recipeId} key={recipe.recipeId}
sx={{ sx={{
color: 'primary',
bgcolor: 'background.paper', bgcolor: 'background.paper',
mb: 1, mb: 1,
borderRadius: 1, borderRadius: 1,
boxShadow: 1, boxShadow: 1,
fontSize: '40px' fontSize: '1.5rem'
}} }}
onClick={() => openRecipeById(recipe.recipeId)} onClick={() => openRecipeById(recipe.recipeId)}
> >
{recipe.recipeName} {recipe.recipeName}
</Button> </ListItem>
</FormGroup> ))}
// </ListItem> </List>
))} </div>
{/* </List> */}
</div> <Box className="plusButtonWrapper">
<div style={{ width: "100%", position: "fixed", left: "50%", transform: 'translateX(-50%)', bottom: "64px" }}> <Fab color="primary" onClick={() => navigate('/addRecipe')} className="plusButton">
<Button variant='contained' sx={{ <AddIcon />
width: "60%", height: "60px", </Fab>
fontSize: "32px", left: "50%", transform: 'translateX(-50%)' {/* <Typography className="plusButtonLabel">
}}
color="primary" </Typography> */}
onClick={() => navigate('/addRecipe')}
>
</Button>
</div>
</Box> </Box>
</Container> </div>
); );
}; };

@ -26,8 +26,9 @@ import {
Select, Select,
MenuItem, MenuItem,
} from '@mui/material'; } from '@mui/material';
import '../App.css';
import { GENERAL_ERRORS, STOCK_ERRORS } from '../constants/errorMessages'; import { GENERAL_ERRORS, STOCK_ERRORS } from '../constants/errorMessages';
import { Add as AddIcon } from '@mui/icons-material'; import { Add as AddIcon, KeyboardArrowDown as ArrowDownIcon, KeyboardArrowUp as ArrowUpIcon, Inventory as InventoryIcon } from '@mui/icons-material';
import DatePicker, { registerLocale } from 'react-datepicker'; import DatePicker, { registerLocale } from 'react-datepicker';
import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールをインポート
import { useMessage } from '../components/MessageContext'; import { useMessage } from '../components/MessageContext';
@ -79,6 +80,19 @@ const StockPage: React.FC = () => {
const { showErrorMessage, showWarningMessage } = useMessage(); const { showErrorMessage, showWarningMessage } = useMessage();
// カテゴリ名一覧
const CATEGORY_NAMES = [
"乳製品",
"魚・肉",
"野菜",
"調味料",
"その他",
];
const [openCategory, setOpenCategory] = useState(Object.fromEntries(
CATEGORY_NAMES.map(category => [category, true])
));
// コンポーネントマウント時にタスク一覧を取得 // コンポーネントマウント時にタスク一覧を取得
useEffect(() => { useEffect(() => {
fetchStocks(); fetchStocks();
@ -209,15 +223,6 @@ const StockPage: React.FC = () => {
}; };
*/ */
/** 追加ボタンを押したときにダイアログを開く */
const handleOpenAdd = () => {
setIsAddOpen(true);
};
/** 追加ダイアログを閉じる */
const handleCloseAdd = () => {
setIsAddOpen(false);
};
/** /**
* *
*/ */
@ -358,8 +363,8 @@ const StockPage: React.FC = () => {
return ( return (
<> <>
<TableContainer component={Paper}> <TableContainer component={Paper}>
<Table> <Table size="small">
<TableHead sx={{ backgroundColor: "#dcdcdc", color: "#333" }}> <TableHead sx={{ backgroundColor: "#ebcba2", color: "#333" }}>
<TableRow> <TableRow>
<TableCell align="center" sx={{ width: '40%', fontSize: '16px' }}></TableCell> <TableCell align="center" sx={{ width: '40%', fontSize: '16px' }}></TableCell>
<TableCell align="center" sx={{ width: '20%', fontSize: '16px' }}></TableCell> <TableCell align="center" sx={{ width: '20%', fontSize: '16px' }}></TableCell>
@ -588,244 +593,208 @@ const StockPage: React.FC = () => {
}; };
return ( return (
<Container> <div className="mainContainer">
<Typography variant="h3" component="h1" sx={{ mb: 4 }} > <div className="mainTitle">
<InventoryIcon sx={{ mr: "0.5em" }} />
</Typography> </div>
<Box {/* 新規タスク作成ダイアログ */}
sx={{ <Dialog open={isAddOpen} onClose={() => setIsAddOpen(false)} disableScrollLock={true}>
position: 'fixed', // ← sticky から fixed に変更 <Box display="flex" alignItems="center" >
bottom: 55, // ← 下に固定 <DialogTitle sx={{ flexGrow: 1 }}>
left: 0, <Typography variant="h5" >
right: 0,
zIndex: 1300, // ダイアログよりは低く </Typography>
backgroundColor: '#f5f5f5', </DialogTitle>
// backgroundColor: 'white', <FormGroup row>
// padding: 2, <FormControlLabel
px: 2, control={<Checkbox />}
py: 1, label="食材を新規追加"
display: 'flex', checked={newStock.newAddition}
justifyContent: 'flex-end', // ← 左寄せ onChange={(e) => setNewStock({ ...newStock, newAddition: (e.target as HTMLInputElement).checked })}
boxShadow: 'none', // 軽めの上向きシャドウ />
}} </FormGroup>
>
{/* 在庫の食材追加ボタン */}
<Box sx={{
display: 'flex', flexDirection: 'column', alignItems: 'flex-end',
mr: 2
}}>
<Typography variant="caption" color="textSecondary">
</Typography>
<Fab color="primary" onClick={handleOpenAdd} >
<AddIcon />
</Fab>
</Box> </Box>
{/* 新規タスク作成ダイアログ */} <DialogContent>
<Dialog open={isAddOpen} onClose={handleCloseAdd} disableScrollLock={true}> <Box sx={{ pt: 1 }}>
<Box display="flex" alignItems="center" > {/*材料カテゴリ選択 */}
<DialogTitle sx={{ flexGrow: 1 }}>
<Typography variant="h5" > <FormControl sx={{ width: "50%", marginBottom: 2 }}>
<InputLabel id="demo-simple-select-label"></InputLabel>
</Typography> <Select
</DialogTitle> labelId="demo-simple-select-label"
<FormGroup row> value={newStock.category}
<FormControlLabel onChange={(e) => onChangeCategory(e.target.value)}
control={<Checkbox />} >
label="食材を新規追加" <MenuItem value="乳製品"></MenuItem>
checked={newStock.newAddition} <MenuItem value="魚・肉"></MenuItem>
onChange={(e) => setNewStock({ ...newStock, newAddition: (e.target as HTMLInputElement).checked })} <MenuItem value="野菜"></MenuItem>
/> <MenuItem value="調味料">調</MenuItem>
</FormGroup> <MenuItem value="その他"></MenuItem>
</Box> </Select>
<DialogContent> </FormControl>
<Box sx={{ pt: 1 }}>
{/*材料カテゴリ選択 */} {!newStock.newAddition && <FormControl sx={{ width: "100%", marginBottom: 2 }}>
<InputLabel id="demo-simple-select-label"></InputLabel>
<FormControl sx={{ width: "50%", marginBottom: 2 }}> <Select
<InputLabel id="demo-simple-select-label"></InputLabel> labelId="demo-simple-select-label"
<Select value={newStock.stuffId}
labelId="demo-simple-select-label" onChange={(e) => setNewStock({ ...newStock, stuffId: Number(e.target.value) })}
value={newStock.category} >
onChange={(e) => onChangeCategory(e.target.value)} {stuffs.map((stuff) => (
> <MenuItem key={stuff.stuffId} value={stuff.stuffId}>
<MenuItem value="乳製品"></MenuItem> {stuff.stuffName}
<MenuItem value="魚・肉"></MenuItem> </MenuItem>
<MenuItem value="野菜"></MenuItem> ))}
<MenuItem value="調味料">調</MenuItem> </Select>
<MenuItem value="その他"></MenuItem> </FormControl>}
</Select>
</FormControl> {/* タスクタイトル入力フィールド */}
{newStock.newAddition && <TextField
{!newStock.newAddition && <FormControl sx={{ width: "100%", marginBottom: 2 }}> autoFocus
<InputLabel id="demo-simple-select-label"></InputLabel> margin="dense"
<Select label="材料名"
labelId="demo-simple-select-label" fullWidth
value={newStock.stuffId} value={newStock.stuffName}
onChange={(e) => setNewStock({ ...newStock, stuffId: Number(e.target.value) })} onChange={(e) => setNewStock({ ...newStock, stuffName: e.target.value })}
> sx={{ marginBottom: 2 }}
{stuffs.map((stuff) => ( />}
<MenuItem key={stuff.stuffId} value={stuff.stuffId}> {/* 現在の数量入力フィールド */}
{stuff.stuffName} <TextField
</MenuItem> margin="dense"
))} label="現在の数量"
</Select> fullWidth
</FormControl>} value={newStock.amount}
onChange={(e) => {
{/* タスクタイトル入力フィールド */} const value = e.target.value;
{newStock.newAddition && <TextField const parsedValue = parseInt(value, 10); // 数値に変換
autoFocus if (isNaN(parsedValue) || parsedValue >= 1) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は1以上のみOK
margin="dense" setNewStock({ ...newStock, amount: parsedValue }); // number型で保存
label="材料名" }
fullWidth }}
value={newStock.stuffName} // sx={{ width: "50%" }}
onChange={(e) => setNewStock({ ...newStock, stuffName: e.target.value })} type="number"
sx={{ marginBottom: 2 }} inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>} />
{/* 現在の数量入力フィールド */} {/* 購入時数量入力フィールド */}
<TextField <TextField
margin="dense" margin="dense"
label="現在の数量" label="購入時の数量"
fullWidth fullWidth
value={newStock.amount} value={newStock.buyAmount}
onChange={(e) => { onChange={(e) => {
const value = e.target.value; const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換 const parsedValue = parseInt(value, 10); // 数値に変換
if (isNaN(parsedValue) || parsedValue >= 1) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は1以上のみOK if (isNaN(parsedValue) || parsedValue >= 1) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は1以上のみOK
setNewStock({ ...newStock, amount: parsedValue }); // number型で保存 setNewStock({ ...newStock, buyAmount: parsedValue }); // number型で保存
} }
}} }}
// sx={{ width: "50%" }} // sx={{ width: "50%" }}
type="number" type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可 inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/> />
{/* 購入時数量入力フィールド */} {/* 購入価格入力フィールド */}
<TextField <TextField
margin="dense" margin="dense"
label="購入時の数量" label="購入価格"
fullWidth fullWidth
value={newStock.buyAmount} value={newStock.price}
onChange={(e) => { onChange={(e) => {
const value = e.target.value; const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換 const parsedValue = parseInt(value, 10); // 数値に変換
if (isNaN(parsedValue) || parsedValue >= 1) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は1以上のみOK if (isNaN(parsedValue) || parsedValue >= 0) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は0以上のみOK
setNewStock({ ...newStock, buyAmount: parsedValue }); // number型で保存 setNewStock({ ...newStock, price: parsedValue }); // number型で保存
} }
}} }}
// sx={{ width: "50%" }} // sx={{ width: "50%" }}
type="number" type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可 inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/> />
{/* 購入価格入力フィールド */} {/* 購入店舗入力フィールド */}
<TextField <TextField
margin="dense" margin="dense"
label="購入価格" label="購入店舗"
fullWidth fullWidth
value={newStock.price} value={newStock.shop}
onChange={(e) => { onChange={(e) => setNewStock({...newStock, shop: e.target.value})}
const value = e.target.value; />
const parsedValue = parseInt(value, 10); // 数値に変換 {/* 購入日・消費期限を横並びに */}
if (isNaN(parsedValue) || parsedValue >= 0) { // 入力欄をいったん空欄にできるようにする,ただし空欄でない場合は0以上のみOK <Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
setNewStock({ ...newStock, price: parsedValue }); // number型で保存 {/* 購入日入力フィールド */}
} <DatePicker
}} popperClassName="custom-datepicker-popper"
// sx={{ width: "50%" }} selected={newStock.buyDate ? new Date(newStock.buyDate) : null}
type="number" onChange={(date) =>
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可 setNewStock({ ...newStock, buyDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal // ← 他の文字との重なり対策
/> />
{/* 購入店舗入力フィールド */} {/* 消費・賞味期限入力フィールド */}
<TextField <DatePicker
margin="dense" popperClassName="custom-datepicker-popper"
label="購入店舗" selected={newStock.expDate ? new Date(newStock.expDate) : null}
fullWidth onChange={(date) =>
value={newStock.shop} setNewStock({ ...newStock, expDate: date ? formatDateLocal(date) : '' })
onChange={(e) => setNewStock({...newStock, shop: e.target.value})} }
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal
/> />
{/* 購入日・消費期限を横並びに */}
<Box sx={{ display: 'flex', gap: 2, mb: 2 }}>
{/* 購入日入力フィールド */}
<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.buyDate ? new Date(newStock.buyDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, buyDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="購入日(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal // ← 他の文字との重なり対策
/>
{/* 消費・賞味期限入力フィールド */}
<DatePicker
popperClassName="custom-datepicker-popper"
selected={newStock.expDate ? new Date(newStock.expDate) : null}
onChange={(date) =>
setNewStock({ ...newStock, expDate: date ? formatDateLocal(date) : '' })
}
dateFormat="yyyy/MM/dd"
customInput={
<TextField
margin="dense"
label="消費・賞味期限(yyyy/MM/dd)"
fullWidth
/>
}
isClearable
//withPortal
/>
</Box>
</Box> </Box>
</DialogContent> </Box>
<DialogActions> </DialogContent>
<Button onClick={() => setIsAddOpen(false)}></Button> <DialogActions>
<Button onClick={handleCreateStock} variant="contained"> <Button onClick={() => setIsAddOpen(false)}></Button>
<Button onClick={handleCreateStock} variant="contained">
</Button>
</DialogActions> </Button>
</Dialog> </DialogActions>
</Dialog>
{/* 各カテゴリを表示 */}
{CATEGORY_NAMES.map(category => {
return (
<Box sx={{ padding: "1rem" }}>
<Typography variant="h5" component="h1" gutterBottom
onClick={() => setOpenCategory({...openCategory, [category]: !openCategory[category]})}
>
{!openCategory[category] ? <ArrowDownIcon color="primary" /> : <ArrowUpIcon color="primary" />}
{category}
</Typography>
{openCategory[category] && StockTable(stocks, [category])}
</Box>
)
})}
{/* 材料ボタン - 画面下部に固定表示 */}
<Box className="plusButtonWrapper">
<Fab color="primary" onClick={() => setIsAddOpen(true)} className="plusButton">
<AddIcon />
</Fab>
{/* <Typography className="plusButtonLabel">
</Typography> */}
</Box> </Box>
{/* 在庫一覧リスト */} </div>
{/* 乳製品 */}
<Typography variant="h4" component="h1" gutterBottom></Typography>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px', marginBottom: "20px" }}>
{StockTable(stocks, ["乳製品"])}
</div>
{/* 肉・魚 */}
<Typography variant="h4" component="h1" gutterBottom></Typography>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px', marginBottom: "20px" }}>
{StockTable(stocks, ["魚・肉"])}
</div>
{/* 野菜 */}
<Typography variant="h4" component="h1" gutterBottom></Typography>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px', marginBottom: "20px" }}>
{StockTable(stocks, ["野菜"])}
</div>
{/* 調味料 */}
<Typography variant="h4" component="h1" gutterBottom>調</Typography>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px', marginBottom: "20px" }}>
{StockTable(stocks, ["調味料"])}
</div>
{/* その他 */}
<Typography variant="h4" component="h1" gutterBottom></Typography>
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px', marginBottom: "20px" }}>
{StockTable(stocks, ["その他"])}
</div>
<Box sx={{ height: '80px' }} /> {/* フッターの高さと同じくらいに調整 */}
</Container>
); );
}; };

@ -22,8 +22,9 @@ import {
} 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, ShoppingCart as ShoppingCartIcon
} from '@mui/icons-material'; } from '@mui/icons-material';
import '../App.css';
import { ToBuy, Stuff, NewToBuy, NewStock, StuffAndCategoryAndAmount, StuffNameAndAmount, StockHistory, /*Stock*/ } from '../types/types'; import { ToBuy, Stuff, NewToBuy, NewStock, StuffAndCategoryAndAmount, StuffNameAndAmount, StockHistory, /*Stock*/ } from '../types/types';
import { GENERAL_ERRORS, TOBUY_ERRORS, STUFF_HISTORY_ERRORS } from '../constants/errorMessages'; import { GENERAL_ERRORS, TOBUY_ERRORS, STUFF_HISTORY_ERRORS } from '../constants/errorMessages';
import { TOBUY_MESSAGES } from '../constants/normalMessages'; import { TOBUY_MESSAGES } from '../constants/normalMessages';
@ -160,7 +161,7 @@ const TaskListPage: React.FC = () => {
} }
newToBuy.stuffName = newToBuy.stuffName.trim(); // 材料名の前後の空白を削除 newToBuy.stuffName = newToBuy.stuffName.trim(); // 材料名の前後の空白を削除
if (!newToBuy.stuffName) { if (!newToBuy.stuffName) {
showErrorMessage(GENERAL_ERRORS.INVALID_STUFF_NAME); showErrorMessage(GENERAL_ERRORS.INVALID_STUFF_NAME);
return; return;
@ -233,7 +234,7 @@ const TaskListPage: React.FC = () => {
} }
}; };
//履歴表示ダイアログ //履歴表示ダイアログ
const [openHistoryDialog, setOpenHistoryDialog] = useState(false); const [openHistoryDialog, setOpenHistoryDialog] = useState(false);
const [historyTobuy, setHistoryTobuy] = useState<ToBuy | null>(null); const [historyTobuy, setHistoryTobuy] = useState<ToBuy | null>(null);
@ -251,19 +252,20 @@ const TaskListPage: React.FC = () => {
} }
return ( return (
<Container> <div className="mainContainer">
<Typography variant="h4" component="h1" gutterBottom> <div className="mainTitle">
<ShoppingCartIcon sx={{ mr: "0.5em" }} />
</Typography> </div>
{/* タスク一覧表示エリア - 青い背景のコンテナ */} {/* 買うものリスト表示エリア - 背景色のコンテナ */}
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px' }}> <div className="listWrapper">
<List> <List>
{/* タスク一覧をマップして各タスクをリストアイテムとして表示 */} {/* タスク一覧をマップして各タスクをリストアイテムとして表示 */}
{tobuys && tobuys.map((tobuy) => ( {tobuys && tobuys.map((tobuy) => (
<ListItem <ListItem
key={tobuy.tobuyId} key={tobuy.tobuyId}
sx={{ sx={{
bgcolor: 'background.paper', bgcolor: "background.paper",
mb: 1, mb: 1,
borderRadius: 1, borderRadius: 1,
boxShadow: 1, boxShadow: 1,
@ -339,19 +341,16 @@ const TaskListPage: React.FC = () => {
))} ))}
</List> </List>
</div> </div>
{/* 新規材料作成ボタン - 画面下部に固定表示 */}
<Box sx={{ textAlign: 'center', position: 'fixed', bottom: 66, left: '80%', transform: 'translateX(-50%)' }}> {/* 材料追加ボタン - 画面下部に固定表示 */}
<Typography variant="caption" color="textSecondary"> <Box className="plusButtonWrapper">
<Fab color="primary" onClick={() => setOpenAddToBuyDialog(true)} className="plusButton">
<AddIcon />
</Fab>
{/* <Typography className="plusButtonLabel">
</Typography> </Typography> */}
</Box> </Box>
<Fab
color="primary"
sx={{ position: 'fixed', bottom: 90, left: '80%', transform: 'translateX(-50%)' }}
onClick={() => setOpenAddToBuyDialog(true)}
>
<AddIcon />
</Fab>
{/*新規料理追加ボタン - 画面下部に固定表示 */} {/*新規料理追加ボタン - 画面下部に固定表示 */}
{/* <Box sx={{ textAlign: 'center', position: 'fixed', bottom: 66, left: '80%', transform: 'translateX(-50%)' }}> {/* <Box sx={{ textAlign: 'center', position: 'fixed', bottom: 66, left: '80%', transform: 'translateX(-50%)' }}>
@ -413,7 +412,7 @@ const TaskListPage: React.FC = () => {
<StuffHistoryDialog openDialog={openHistoryDialog} setOpenDialog={setOpenHistoryDialog} stuffName={historyTobuy.stuffName} stockHistories={stockHistories} /> <StuffHistoryDialog openDialog={openHistoryDialog} setOpenDialog={setOpenHistoryDialog} stuffName={historyTobuy.stuffName} stockHistories={stockHistories} />
} }
</Container> </div>
); );
}; };

Loading…
Cancel
Save