Merge remote-tracking branch 'origin/feature_frontend_dishList_ui' into develop-frontend

feature-frontend-top
Masaharu.Kato 4 months ago
commit d7593dc723
  1. 2
      backend/src/main/java/com/example/todoapp/controller/ToBuysController.java
  2. 2
      backend/src/main/java/com/example/todoapp/model/ToBuys.java
  3. 6
      backend/src/main/java/com/example/todoapp/service/ToBuysService.java
  4. 99
      frontend/src/pages/AddRecipe.tsx
  5. 1
      frontend/src/pages/StockPage.tsx
  6. 4
      frontend/src/services/api.ts

@ -119,7 +119,7 @@ public class ToBuysController {
resp.setStuffId(stuff.getStuffId()); resp.setStuffId(stuff.getStuffId());
resp.setStuffName(stuff.getStuffName()); resp.setStuffName(stuff.getStuffName());
resp.setAmount(toBuy.getAmount()); resp.setAmount(toBuy.getAmount());
resp.setShop(toBuy.getStore()); resp.setShop(toBuy.getShop());
return resp; return resp;
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());

@ -75,7 +75,7 @@ public class ToBuys {
* 購入するお店 * 購入するお店
*/ */
@Column(nullable = false) @Column(nullable = false)
private String store; private String shop;
} }

@ -104,7 +104,7 @@ public class ToBuysService {
toBuys.setUser(user); toBuys.setUser(user);
toBuys.setStuff(stuff); toBuys.setStuff(stuff);
toBuys.setAmount(toBuyDTO.getAmount()); toBuys.setAmount(toBuyDTO.getAmount());
toBuys.setStore(toBuyDTO.getShop()); toBuys.setShop(toBuyDTO.getShop());
return toBuysRepository.save(toBuys); return toBuysRepository.save(toBuys);
} }
@ -155,7 +155,7 @@ public class ToBuysService {
toBuys.setUser(user); toBuys.setUser(user);
toBuys.setStuff(stuffs); toBuys.setStuff(stuffs);
toBuys.setAmount(toBuyDTO.getAmount()); toBuys.setAmount(toBuyDTO.getAmount());
toBuys.setStore(toBuyDTO.getShop()); toBuys.setShop(toBuyDTO.getShop());
// データベースに保存 // データベースに保存
return toBuysRepository.save(toBuys); return toBuysRepository.save(toBuys);
@ -248,7 +248,7 @@ public class ToBuysService {
toBuy.setUser(user); toBuy.setUser(user);
toBuy.setStuff(stuff); toBuy.setStuff(stuff);
toBuy.setAmount(requiredAmount); toBuy.setAmount(requiredAmount);
toBuy.setStore(""); toBuy.setShop("");
} }
toBuy = toBuysRepository.save(toBuy); toBuy = toBuysRepository.save(toBuy);

@ -4,7 +4,6 @@
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { import {
Container,
Typography, Typography,
Tooltip, Tooltip,
List, List,
@ -12,7 +11,6 @@ import {
ListItemText, ListItemText,
ListItemSecondaryAction, ListItemSecondaryAction,
IconButton, IconButton,
Checkbox,
Fab, Fab,
Dialog, Dialog,
DialogTitle, DialogTitle,
@ -21,12 +19,6 @@ import {
TextField, TextField,
Button, Button,
Box, Box,
MenuItem,
Select,
FormControl,
InputLabel,
ListItemIcon,
AlertColor
} 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,
@ -48,6 +40,9 @@ const AddRecipe: React.FC = () => {
// 編集時,既存情報を読み込んだかどうか // 編集時,既存情報を読み込んだかどうか
const [recipeLoaded, setRecipeLoaded] = useState(false); const [recipeLoaded, setRecipeLoaded] = useState(false);
// 何人分かを格納する
const [numOfPeaple, setNumOfPeaple] = useState<number>(1);
const [openNumOfPeapleDialog, setOpenNumOfPeapleDialog] = useState(false);
// 料理名,説明 // 料理名,説明
const [recipeName, setRecipeName] = useState<string>(''); const [recipeName, setRecipeName] = useState<string>('');
const [recipeSummary, setRecipeSummary] = useState<string>(''); const [recipeSummary, setRecipeSummary] = useState<string>('');
@ -84,17 +79,20 @@ const AddRecipe: React.FC = () => {
if (!recipeName) { if (!recipeName) {
showErrorMessage('レシピ名が入力されていません!') showErrorMessage('レシピ名が入力されていません!')
console.log("yes1");
return false; return false;
} }
if (!items.length) { if (!items.length) {
showErrorMessage('材料が追加されていません!') showErrorMessage('材料が追加されていません!')
console.log("yes2");
return false; return false;
} }
try { try {
if (!recipeId) { if (!recipeId) {
// 新規追加 console.log("yes3");
// 新規追加
const response = await recipeApi.addRecipe({ const response = await recipeApi.addRecipe({
recipeName, recipeName,
summary: recipeSummary, summary: recipeSummary,
@ -113,10 +111,26 @@ const AddRecipe: React.FC = () => {
showErrorMessage('レシピの送信に失敗しました。同じ料理名が存在する可能性があります。'); showErrorMessage('レシピの送信に失敗しました。同じ料理名が存在する可能性があります。');
return false; return false;
} }
console.log("yes4");
return recipeId; return recipeId;
} }
const checkRecipeAndItems = async () => {
if (!recipeName) {
showErrorMessage('レシピ名が入力されていません!')
console.log("yes1");
return false;
}
if (!items.length) {
showErrorMessage('材料が追加されていません!')
console.log("yes2");
return false;
}
return true;
}
const handleSubmit = async () => { const handleSubmit = async () => {
const recipeId = await handleSaveRecipe(); const recipeId = await handleSaveRecipe();
if (!recipeId) return; if (!recipeId) return;
@ -125,13 +139,34 @@ const AddRecipe: React.FC = () => {
} }
const handleSubmitAndAddToBuy = async () => { const handleSubmitAndAddToBuy = async () => {
console.log("too");
console.log(recipeName);
const recipeId = await handleSaveRecipe(); const recipeId = await handleSaveRecipe();
console.log("before");
if (!recipeId) return false; if (!recipeId) return false;
await toBuyApi.addByRecipe(recipeId); console.log("ds");
if (!numOfPeaple) {
showErrorMessage('人数が入力されていません!')
console.log("yes2");
return false;
}
await toBuyApi.addByRecipe(recipeId, numOfPeaple);
showSuccessMessage('レシピが保存されて買うものリストに追加されました!'); showSuccessMessage('レシピが保存されて買うものリストに追加されました!');
navigate('/tasks'); navigate('/tasks');
} }
const openNumOfPeopleDialog = async () => {
const check = await checkRecipeAndItems();
if (!check) return false;
setOpenNumOfPeapleDialog(true);
}
const cancelNumOfPeopleDialog = async () => {
const recipeId = await handleSaveRecipe();
if (!recipeId) return false;
setOpenNumOfPeapleDialog(false);
}
// コンポーネントマウント時にタスク一覧を取得 // コンポーネントマウント時にタスク一覧を取得
useEffect(() => { useEffect(() => {
loadRecipe(); loadRecipe();
@ -211,6 +246,7 @@ const AddRecipe: React.FC = () => {
))}</List>)} ))}</List>)}
<div style={{ position: "fixed", left: "80%", transform: 'translateX(-50%)', bottom: "10%" }}> <div style={{ position: "fixed", left: "80%", transform: 'translateX(-50%)', bottom: "10%" }}>
<Box sx={{ textAlign: 'center' }}> <Box sx={{ textAlign: 'center' }}>
@ -226,7 +262,7 @@ const AddRecipe: React.FC = () => {
<SaveIcon sx={{ fontSize: "1.5rem", marginRight: "0.5rem" }} /> <SaveIcon sx={{ fontSize: "1.5rem", marginRight: "0.5rem" }} />
</Button> </Button>
<Button variant='contained' color="primary" onClick={handleSubmitAndAddToBuy}> <Button variant='contained' color="primary" onClick={openNumOfPeopleDialog}>
<ListAltIcon sx={{ fontSize: "1.5rem", marginRight: "0.5rem" }} /> <ListAltIcon sx={{ fontSize: "1.5rem", marginRight: "0.5rem" }} />
</Button> </Button>
@ -272,6 +308,45 @@ const AddRecipe: React.FC = () => {
setOpenAmountDialog(false); setOpenAmountDialog(false);
}} /> }} />
{/* 人数入力ダイアログ */}
<Dialog open={openNumOfPeapleDialog} onClose={() => setOpenNumOfPeapleDialog(false)} disableScrollLock={true}
style={{ width : '100%', position : 'fixed', left: '50%', transform: 'translateX(-50%)' }}
>
<Box display="flex" alignItems="center"
>
<DialogTitle sx={{ flexGrow: 1 }}></DialogTitle>
</Box>
<DialogContent>
<div>
{/* 人数入力フィールド */}
<TextField
margin="dense"
label="何人前"
fullWidth
value={numOfPeaple}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (/*!isNaN(parsedValue) && */ isNaN(parsedValue) || parsedValue >= 1) { //負数除外
setNumOfPeaple(parsedValue); // number型で保存
}
}}
sx={{ minWidth: "8px", width: "100%" }}
type="number"
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可
/>
</div>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpenNumOfPeapleDialog(false)}></Button>
<Button onClick={() => handleSubmitAndAddToBuy()} variant="contained"
style={{ width: '40%', fontSize: 'clamp(12px, 3vw, 20px)' }}
>
</Button>
</DialogActions>
</Dialog>
</Box> </Box>
} }
</> </>

@ -39,6 +39,7 @@ const formatDateLocal = (date: Date) => {
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
}; };
// 新規在庫の初期状態 // 新規在庫の初期状態
const EMPTY_STOCK: Omit<Stock, 'stockId' | 'stuffId'> & { stuffId: number | null } & { newAddition: boolean } = { const EMPTY_STOCK: Omit<Stock, 'stockId' | 'stuffId'> & { stuffId: number | null } & { newAddition: boolean } = {
stuffId: null, stuffId: null,

@ -132,11 +132,11 @@ export const toBuyApi = {
}, },
addByRecipe: async (recipeId: number): Promise<any> => { addByRecipe: async (recipeId: number, servings: number): Promise<any> => {
const response = await fetch(`${API_BASE_URL}/api/tobuy/addByRecipe`, { const response = await fetch(`${API_BASE_URL}/api/tobuy/addByRecipe`, {
method: 'POST', method: 'POST',
headers: getHeaders(), headers: getHeaders(),
body: JSON.stringify({ recipeId }), body: JSON.stringify({ recipeId, servings }),
}) })
if (!response.ok) { if (!response.ok) {
throw new Error(TOBUY_ERRORS.CREATE_FAILED); throw new Error(TOBUY_ERRORS.CREATE_FAILED);

Loading…
Cancel
Save