買うものリストの表示を実装

dev-frontend-with-api
Masaharu.Kato 5 months ago
parent 9fdcb04598
commit 21d8816506
  1. 78
      frontend/src/pages/TaskListPage.tsx
  2. 93
      frontend/src/services/api.ts
  3. 12
      frontend/src/types/types.ts

@ -3,7 +3,7 @@
*
*/
import React, { useState, useEffect } from 'react';
import { taskApi } from '../services/api';
import { toBuyApi } from '../services/api';
import {
Container,
Typography,
@ -31,7 +31,7 @@ import {
Add as AddIcon, Delete as DeleteIcon, ShoppingBasket as ShoppingBasketIcon,
SoupKitchen as SoupKitchenIcon
} from '@mui/icons-material';
import { Task } from '../types/types';
import { ToBuy } from '../types/types';
import { TASK_ERRORS } from '../constants/errorMessages';
//import { FaCarrot } from "react-icons/fa6"; //エラー起きる いったん保留
import CategoryDropDown from "../components/CategoryDropDown";
@ -40,15 +40,21 @@ import CategoryDropDown from "../components/CategoryDropDown";
// 新規タスクの初期状態
const EMPTY_TASK = { id: 0, title: '', amount: 0, completed: false };
const EMPTY_TASK: Omit<ToBuy, 'tobuy_id'> & {category: string} = {
stuff_id: 0,
stuff_name: '',
amount: 0,
shop: '',
category: '',
}
const TaskListPage: React.FC = () => {
// タスク一覧の状態管理
const [tasks, setTasks] = useState<Task[]>([]);
const [tobuys, setToBuys] = useState<ToBuy[]>([]);
// 新規タスク作成ダイアログの表示状態
const [openDialog, setOpenDialog] = useState(false);
// 新規タスクの入力内容
const [newTask, setNewTask] = useState(EMPTY_TASK);
const [newToBuy, setNewToBuy] = useState(EMPTY_TASK);
// コンポーネントマウント時にタスク一覧を取得
useEffect(() => {
@ -61,36 +67,36 @@ const TaskListPage: React.FC = () => {
*/
const fetchTasks = async () => {
try {
const tasks = await taskApi.getTasks();
setTasks(tasks);
const tobuys = await toBuyApi.getToBuys();
setToBuys(tobuys.tobuy_array);
} catch (error) {
console.error(`${TASK_ERRORS.FETCH_FAILED}:`, error);
}
};
/**
*
* APIに更新を要求
*/
const handleToggleComplete = async (taskId: number) => {
try {
const task = tasks.find(t => t.id === taskId);
if (!task) return;
// /**
// * タスクの完了状態を切り替えるハンドラー
// * 対象タスクの完了状態を反転させてAPIに更新を要求
// */
// const handleToggleComplete = async (taskId: number) => {
// try {
// const task = tasks.find(t => t.id === taskId);
// if (!task) return;
await taskApi.updateTask(taskId, { ...task, completed: !task.completed });
fetchTasks(); // 更新後のタスク一覧を再取得
} catch (error) {
console.error(`${TASK_ERRORS.UPDATE_FAILED}:`, error);
}
};
// await toBuyApi.updateTask(taskId, { ...task, completed: !task.completed });
// fetchTasks(); // 更新後のタスク一覧を再取得
// } catch (error) {
// console.error(`${TASK_ERRORS.UPDATE_FAILED}:`, error);
// }
// };
/**
*
* IDのタスクをAPIを通じて削除
*/
const handleDeleteTask = async (taskId: number) => {
const handleDeleteTask = async (toBuyId: number) => {
try {
await taskApi.deleteTask(taskId);
await toBuyApi.deleteToBuy(toBuyId);
fetchTasks(); // 削除後のタスク一覧を再取得
} catch (error) {
console.error(`${TASK_ERRORS.DELETE_FAILED}:`, error);
@ -104,9 +110,9 @@ const TaskListPage: React.FC = () => {
*/
const handleCreateTask = async () => {
try {
await taskApi.createTask(newTask);
await toBuyApi.addToBuy(newToBuy);
setOpenDialog(false); // ダイアログを閉じる
setNewTask(EMPTY_TASK); // 入力内容をリセット
setNewToBuy(EMPTY_TASK); // 入力内容をリセット
fetchTasks(); // 作成後のタスク一覧を再取得
} catch (error) {
console.error(`${TASK_ERRORS.CREATE_FAILED}:`, error);
@ -122,9 +128,9 @@ const TaskListPage: React.FC = () => {
<div style={{ border: '3px solid black', borderRadius: '8px', backgroundColor: '#add8e6', height: 'auto', padding: '20px' }}>
<List>
{/* タスク一覧をマップして各タスクをリストアイテムとして表示 */}
{tasks.map((task) => (
{tobuys.map((tobuy) => (
<ListItem
key={task.id}
key={tobuy.tobuy_id}
sx={{
bgcolor: 'background.paper',
mb: 1,
@ -133,16 +139,18 @@ const TaskListPage: React.FC = () => {
}}
>
{/* タスク完了状態を切り替えるチェックボックス */}
{/*}
<Checkbox
checked={task.completed}
onChange={() => handleToggleComplete(task.id)}
/>
*/}
{/* タスクのタイトルと説明 - 完了状態に応じて取り消し線を表示 */}
<ListItemText
primary={task.title}
secondary={task.description}
primary={tobuy.stuff_name}
secondary={tobuy.amount}
sx={{
textDecoration: task.completed ? 'line-through' : 'none',
textDecoration: false ? 'line-through' : 'none',
}}
/>
{/* 買い物リスト:食材情報記入ボタン */}
@ -174,7 +182,7 @@ const TaskListPage: React.FC = () => {
<IconButton
edge="end"
aria-label="delete"
onClick={() => handleDeleteTask(task.id)}
onClick={() => handleDeleteTask(tobuy.tobuy_id)}
>
<DeleteIcon />
</IconButton>
@ -219,8 +227,8 @@ const TaskListPage: React.FC = () => {
margin="dense"
label="材料名"
fullWidth
value={newTask.title}
onChange={(e) => setNewTask({ ...newTask, title: e.target.value })}
value={newToBuy.stuff_name}
onChange={(e) => setNewToBuy({ ...newToBuy, stuff_name: e.target.value })}
sx={{ marginBottom: 2 }}
/>
{/* 数量入力フィールド */}
@ -228,12 +236,12 @@ const TaskListPage: React.FC = () => {
margin="dense"
label="数量"
fullWidth
value={newTask.amount}
value={newToBuy.amount}
onChange={(e) => {
const value = e.target.value;
const parsedValue = parseInt(value, 10); // 数値に変換
if (!isNaN(parsedValue)) {
setNewTask({ ...newTask, amount: parsedValue }); // number型で保存
setNewToBuy({ ...newToBuy, amount: parsedValue }); // number型で保存
}
}}
sx={{ width: "20%" }}

@ -3,7 +3,7 @@
* APIとの通信を担当するモジュール
*
*/
import { LoginCredentials, RegisterCredentials, AuthResponse, Task } from '../types/types';
import { LoginCredentials, RegisterCredentials, AuthResponse, Task, ToBuy } from '../types/types';
import { AUTH_ERRORS, TASK_ERRORS } from '../constants/errorMessages';
// APIのベースURL - 環境変数から取得するか、デフォルト値を使用
@ -82,7 +82,98 @@ export const authApi = {
},
};
/**
* API機能を提供するオブジェクト
*
*/
export const toBuyApi = {
/**
*
* @returns
*/
getToBuys: async (): Promise<{ "tobuy_array": ToBuy[] }> => {
// const response = await fetch(`${API_BASE_URL}/api/tobuy/get`, {
// headers: getHeaders(), // 認証トークンを含むヘッダー
// });
// if (!response.ok) {
// throw new Error(TASK_ERRORS.FETCH_FAILED);
// }
// return response.json();
return {
"tobuy_array": [
{
"tobuy_id": 1,
"stuff_id": 2,
"stuff_name": "じゃがいも",
"amount": 3,
"shop": "shopXXX"
},
{
"tobuy_id": 2,
"stuff_id": 5,
"stuff_name": "にんじん",
"amount": 1
}
]
}
},
/**
*
* @param tobuy
* @returns
*/
addToBuy: async (tobuy: Omit<ToBuy, 'tobuy_id'> & { category: string }): Promise<any> => {
// const response = await fetch(`${API_BASE_URL}/api/tasks`, {
// method: 'POST',
// headers: getHeaders(),
// body: JSON.stringify(tobuy),
// });
// if (!response.ok) {
// throw new Error(TASK_ERRORS.CREATE_FAILED);
// }
// return response.json();
return {
"result": true,
"tobuy_id": 1,
"stuff_id": 6,
"message": "追加に成功しました",
}
},
/**
*
* @param id ID
*/
deleteToBuy: async (tobuy_id: number): Promise<{ result: boolean }> => {
// const response = await fetch(`${API_BASE_URL}/api/tobuy/delete`, {
// method: 'DELETE',
// headers: getHeaders(),
// body: JSON.stringify({tobuy_id}),
// });
// if (!response.ok) {
// throw new Error(TASK_ERRORS.DELETE_FAILED);
// }
return {
"result": true
}
},
}
/**
* ()
* API機能を提供するオブジェクト
*
*/

@ -12,6 +12,18 @@ export interface Task {
updatedAt: string; // タスク更新日時
}
/**
*
*
*/
export interface ToBuy {
tobuy_id: number,
stuff_id: number,
stuff_name: string,
amount: number,
shop?: string,
}
/**
*
*

Loading…
Cancel
Save