エラーハンドリングを追加

feature-frontend-design-fix
Masaharu.Kato 4 months ago
parent c790bebb92
commit 0e5e226755
  1. 16
      frontend/src/components/AddByRecipeDialog.tsx
  2. 1
      frontend/src/components/Layout.tsx
  3. 4
      frontend/src/components/StuffHistoryDialog.tsx
  4. 7
      frontend/src/constants/normalMessages.ts
  5. 2
      frontend/src/pages/RecipeList.tsx
  6. 24
      frontend/src/pages/StockPage.tsx
  7. 2
      frontend/src/pages/TaskListPage.tsx

@ -37,8 +37,8 @@ const AddByRecipeDialog = ({
openDialog: boolean, openDialog: boolean,
setOpenDialog: (open: boolean) => void, setOpenDialog: (open: boolean) => void,
recipeId: number, recipeId: number,
numOfPeople: number, numOfPeople: string,
setNumOfPeaple: (num: number) => void, setNumOfPeaple: (num: string) => void,
checked: boolean, checked: boolean,
setChecked: (checked: boolean) => void setChecked: (checked: boolean) => void
}) => { }) => {
@ -109,14 +109,15 @@ const AddByRecipeDialog = ({
margin="dense" margin="dense"
label="何人前" label="何人前"
fullWidth fullWidth
// min={1}
defaultValue={1} defaultValue={1}
value={numOfPeople} value={numOfPeople}
onChange={(e) => { onChange={(e) => {
setNumOfPeaple(parseInt(e.target.value, 10)); // const num = parseInt(e.target.value, 10);
// setNumOfPeaple(!isNaN(num) ? num : '');
setNumOfPeaple(e.target.value);
}} }}
sx={{ minWidth: "8px", width: "100%" }} sx={{ minWidth: "8px", width: "100%" }}
inputProps={{ inputMode: "numeric", pattern: "[0-9]*" }} // ここで整数のみ許可 inputProps={{ inputMode: "numeric", min: 1, pattern: "[0-9]*" }} // ここで整数のみ許可
/> />
</div> </div>
@ -131,11 +132,12 @@ const AddByRecipeDialog = ({
variant="contained" variant="contained"
color="primary" color="primary"
onClick={async () => { onClick={async () => {
if (!numOfPeople || isNaN(numOfPeople)) { const num = parseInt(numOfPeople, 10);
if (!num || isNaN(num)) {
showErrorMessage('人数が正しく入力されていません。'); showErrorMessage('人数が正しく入力されていません。');
return; return;
} }
const finalAddResult = await toBuyApi.addByRecipe(recipe.recipeId, numOfPeople, checked); const finalAddResult = await toBuyApi.addByRecipe(recipe.recipeId, num, checked);
setOpenDialog(false); setOpenDialog(false);
if (finalAddResult.data.length === 0) { if (finalAddResult.data.length === 0) {
showInfoMessage('必要な食材が在庫にあったのでリストには追加されませんでした!'); showInfoMessage('必要な食材が在庫にあったのでリストには追加されませんでした!');

@ -101,6 +101,7 @@ const Layout: React.FC = () => {
const [msgType, setMsgType] = useState<AlertColor>('info'); const [msgType, setMsgType] = useState<AlertColor>('info');
const showMessage = (msg: string, sev: AlertColor) => { const showMessage = (msg: string, sev: AlertColor) => {
console.log('ShowMessage:', msg, sev);
setMsgText(msg); setMsgText(msg);
setMsgType(sev); setMsgType(sev);
setMsgOpen(true); setMsgOpen(true);

@ -32,7 +32,7 @@ const StuffHistoryDialog = ({
}) => { }) => {
return ( return (
<Dialog open={openDialog} onClose={() => setOpenDialog(false)} disableScrollLock={true} PaperProps={{ sx: { minWidth: '300px', maxHeight: '80vh' } }}> <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' }}> <DialogTitle sx={{ m: 0, p: 2, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
: {stuffName} : {stuffName}
<IconButton <IconButton
@ -68,7 +68,7 @@ const StuffHistoryDialog = ({
{/* 各ヘッダーセルに white-space: nowrap; を適用 */} {/* 各ヘッダーセルに white-space: nowrap; を適用 */}
<TableCell sx={{ whiteSpace: 'nowrap' }}></TableCell> <TableCell sx={{ whiteSpace: 'nowrap' }}></TableCell>
{/* 「購入店舗」ヘッダーも nowrap にし、minWidth でスクロールを考慮 */} {/* 「購入店舗」ヘッダーも nowrap にし、minWidth でスクロールを考慮 */}
<TableCell sx={{ whiteSpace: 'nowrap', minWidth: '150px' }}></TableCell> <TableCell sx={{ whiteSpace: 'nowrap', minWidth: '120px' }}></TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell> <TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell>
<TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell> <TableCell align="right" sx={{ whiteSpace: 'nowrap' }}></TableCell>
</TableRow> </TableRow>

@ -14,3 +14,10 @@ export const RECIPE_MESSAGES = {
SAVED_AND_ADDED: 'レシピが保存されて買うものリストに追加されました!', SAVED_AND_ADDED: 'レシピが保存されて買うものリストに追加されました!',
NO_ADDITIONALS: '必要な食材が在庫にあったのでリストには追加されませんでした。', NO_ADDITIONALS: '必要な食材が在庫にあったのでリストには追加されませんでした。',
} }
// 在庫リスト
export const STOCK_MESSAGES = {
CREATE_OK: '在庫リストに追加されました!',
UPDATE_OK: '在庫情報が編集されました!',
DELETE_OK: '在庫リストから削除されました!',
};

@ -54,7 +54,7 @@ const RecipeList: React.FC = () => {
const [openAddByRecipeDialog, setOpenAddByRecipeDialog] = useState(false); const [openAddByRecipeDialog, setOpenAddByRecipeDialog] = useState(false);
const [addByRecipeId, setAddByRecipeId] = useState(0); const [addByRecipeId, setAddByRecipeId] = useState(0);
const [numOfPeople, setNumOfPeople] = useState(1); const [numOfPeople, setNumOfPeople] = useState('1');
const [checked, setChecked] = useState(false); const [checked, setChecked] = useState(false);
const openRecipeById = (recipeId: number) => { const openRecipeById = (recipeId: number) => {

@ -35,6 +35,7 @@ import { ja } from 'date-fns/locale/ja'; // date-fnsの日本語ロケールを
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';
import BuyExpDateSelect from '../components/BuyExpDateSelect'; import BuyExpDateSelect from '../components/BuyExpDateSelect';
import { STOCK_MESSAGES } from '../constants/normalMessages';
/*// yyyy-MM-dd形式で返す関数 /*// yyyy-MM-dd形式で返す関数
const formatDateLocal = (date: Date) => { const formatDateLocal = (date: Date) => {
@ -80,7 +81,7 @@ const StockPage: React.FC = () => {
// 在庫の編集状態 // 在庫の編集状態
const [editStock, setEditStock] = useState<Stock | null>(null); const [editStock, setEditStock] = useState<Stock | null>(null);
const { showErrorMessage, showWarningMessage } = useMessage(); const { showErrorMessage, showWarningMessage, showSuccessMessage } = useMessage();
// カテゴリ名一覧 // カテゴリ名一覧
const CATEGORY_NAMES = [ const CATEGORY_NAMES = [
@ -174,6 +175,7 @@ const StockPage: React.FC = () => {
console.log("送信するデータ:", updatedStock); // 送信前のデータを確認 console.log("送信するデータ:", updatedStock); // 送信前のデータを確認
await stockApi.addStock(updatedStock); // 修正したオブジェクトを API に送信 await stockApi.addStock(updatedStock); // 修正したオブジェクトを API に送信
showSuccessMessage(STOCK_MESSAGES.CREATE_OK);
// await stockApi.addStock(newStock); // await stockApi.addStock(newStock);
setIsAddOpen(false); // ダイアログを閉じる setIsAddOpen(false); // ダイアログを閉じる
@ -192,10 +194,12 @@ const StockPage: React.FC = () => {
try { try {
await stockApi.updateStock(request); await stockApi.updateStock(request);
fetchStocks(); // 削除後の買うもの一覧を再取得 fetchStocks(); // 削除後の買うもの一覧を再取得
// showSuccessMessage(STOCK_MESSAGES.UPDATE_OK);
} catch (error) { } catch (error) {
console.error(`${STOCK_ERRORS.UPDATE_FAILED}:`, error); console.error(`${STOCK_ERRORS.UPDATE_FAILED}:`, error);
showErrorMessage(STOCK_ERRORS.UPDATE_FAILED); // showErrorMessage(STOCK_ERRORS.UPDATE_FAILED);
} }
}; };
/** /**
@ -205,6 +209,9 @@ const StockPage: React.FC = () => {
const handleDeleteStock = async (stockId: number) => { const handleDeleteStock = async (stockId: number) => {
try { try {
await stockApi.deleteStock(stockId); await stockApi.deleteStock(stockId);
showSuccessMessage(STOCK_MESSAGES.DELETE_OK);
fetchStocks(); // 削除後の買うもの一覧を再取得 fetchStocks(); // 削除後の買うもの一覧を再取得
} catch (error) { } catch (error) {
console.error(`${STOCK_ERRORS.DELETE_FAILED}:`, error); console.error(`${STOCK_ERRORS.DELETE_FAILED}:`, error);
@ -288,14 +295,14 @@ const StockPage: React.FC = () => {
setIsDeleteOpen(true); // 削除ダイアログを開く setIsDeleteOpen(true); // 削除ダイアログを開く
return; return;
} }
if (!numericAmount || !numericBuyAmount) { if (!numericAmount /* || !numericBuyAmount */) {
showErrorMessage(GENERAL_ERRORS.INVALID_AMOUNT); showErrorMessage(GENERAL_ERRORS.INVALID_AMOUNT);
return; return;
} }
if (!numericPrice) { // if (!numericPrice) {
showErrorMessage(GENERAL_ERRORS.INVALID_PRICE); // showErrorMessage(GENERAL_ERRORS.INVALID_PRICE);
return; // return;
} // }
const lastUpdate = new Date().toISOString().substring(0, 10); const lastUpdate = new Date().toISOString().substring(0, 10);
@ -314,6 +321,9 @@ const StockPage: React.FC = () => {
await handleUpdateStock(updateRequest); await handleUpdateStock(updateRequest);
console.log(STOCK_MESSAGES.UPDATE_OK)
showSuccessMessage(STOCK_MESSAGES.UPDATE_OK);
setSelectedRow(editStock); // 更新後に選択行を反映 setSelectedRow(editStock); // 更新後に選択行を反映
fetchStocks(); // 最新データを取得 fetchStocks(); // 最新データを取得
setSelectedRow(null); // 選択解除 setSelectedRow(null); // 選択解除

@ -33,6 +33,7 @@ import AddStuffAmountDialog from '../components/AddStuffAmountDialog';
import BuyDialog from '../components/BuyDialog'; import BuyDialog from '../components/BuyDialog';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import DatePicker from 'react-datepicker'; import DatePicker from 'react-datepicker';
import MessageAlert from '../components/MessageAlert';
import { useMessage } from '../components/MessageContext'; import { useMessage } from '../components/MessageContext';
import StuffHistoryDialog from '../components/StuffHistoryDialog'; import StuffHistoryDialog from '../components/StuffHistoryDialog';
@ -172,6 +173,7 @@ const TaskListPage: React.FC = () => {
console.log(newToBuy) console.log(newToBuy)
await toBuyApi.addToBuy(newToBuy); await toBuyApi.addToBuy(newToBuy);
setOpenAddToBuyDialog(false); // ダイアログを閉じる setOpenAddToBuyDialog(false); // ダイアログを閉じる
// alert(TOBUY_MESSAGES.CREATE_OK);
showSuccessMessage(TOBUY_MESSAGES.CREATE_OK); showSuccessMessage(TOBUY_MESSAGES.CREATE_OK);
setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット setNewToBuy(EMPTY_TOBUY); // 入力内容をリセット
fetchTasks(); // 作成後のタスク一覧を再取得 fetchTasks(); // 作成後のタスク一覧を再取得

Loading…
Cancel
Save