운동관리 - todayExercise 등록
ㆍProject Diary/Next.js + Prisma + MariaDB (KiloFlow)
이 글에서는 사용자가 오늘의 운동을 등록하는 기능을 구현합니다.
데이터베이스
users 테이블
model users {
user_id Int @id @default(autoincrement())
email String @unique
password String
nickname String
profile_image String @default("default_image_url")
isInitialSetupComplete Boolean @default(false)
created_at DateTime @default(now())
userProfile UserProfile?
recommends recommend[]
userFoodList userFoodList[]
todayFood todayFood[]
todayExercise todayExercise[] // 추가된 부분
@@index([user_id])
}
todayExercise 테이블
model todayExercise {
id Int @id @default(autoincrement())
user_id Int
exercise_id Int
duration Int
calories Float
added_at DateTime @default(now())
user users @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
@@index([user_id])
}
프론트엔드
ExerciseDetail 컴포넌트
1. 운동 시간 변경 핸들러
// 운동 시간 변경 핸들러
const changeMin = (e: React.ChangeEvent<HTMLInputElement>) => {
setMin(parseInt(e.target.value)); // 입력된 운동 시간을 상태에 저장
};
- setMin(parseInt(e.target.value)) : 입력된 운동 시간을 정수로 변환하여 상태에 저장합니다.
2. 오늘의 운동 추가 함수
// 오늘의 운동 추가 함수
const addTodayExercise = async () => {
const calories = (MET * 3.5 * userWeight * min) / 200; // 운동 시간에 따른 소모 칼로리 계산
try {
const res = await fetch('/api/exercise/todayExercise', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: currentUserID, // 현재 사용자 ID
exercise_id: id, // 운동 ID
duration: min, // 운동 시간
calories: calories, // 계산된 소모 칼로리
}),
});
if (res.ok) {
const rec = await res.json();
const newExerciseData = [...exerciseData, { calories }];
setExerciseData(newExerciseData); // 새로운 운동 데이터를 상태에 추가
const newAchievement = achievement;
try {
const res = await fetch(
`/api/achievement/get?user_id=${currentUserID}&date=${new Date().toISOString().split('T')[0]}`,
{
method: 'GET',
}
);
if (res.ok) {
await fetch('/api/achievement/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: currentUserID,
date: new Date().toISOString().split('T')[0],
achievement: newAchievement,
}),
});
router.back();
} else {
await fetch('/api/achievement/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_id: currentUserID,
date: new Date().toISOString().split('T')[0],
achievement: newAchievement,
}),
});
router.back();
}
} catch (error) {
console.error('Failed to update or create achievement:', error);
}
alert(`${name} ${rec.message}`);
router.back();
} else {
alert('추가에 실패했습니다.');
}
} catch (err) {
alert('추가에 실패했습니다.');
}
};
- const calories = (MET * 3.5 * userWeight * min) / 200 :
동 시간에 따른 소모 칼로리를 계산합니다. - const res = await fetch('/api/exercise/todayExercise', {...}) :
todayExercise API에 POST 요청을 보냅니다. - body: JSON.stringify({ user_id: currentUserID, exercise_id: id, duration: min, calories: calories }) :
현재 사용자 ID, 운동 ID, 운동 시간, 계산된 소모 칼로리를 JSON 형식으로 요청 본문에 포함합니다. - const newExerciseData = [...exerciseData, { calories }] :
새로운 운동 데이터를 기존 운동 데이터 배열에 추가합니다.
백엔드
todayExercise API엔드포인트
import type { NextApiRequest, NextApiResponse } from "next";
import prisma from "../../../lib/prisma";
// todayExercise 등록을 처리하는 API 핸들러 함수
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "POST") { // POST 요청 처리
try {
const { user_id, exercise_id, duration, calories } = req.body; // 요청 본문에서 필요한 데이터 추출
// todayExercise 테이블에 새로운 레코드 생성
await prisma.todayExercise.create({
data: {
user_id: Number(user_id), // 사용자 ID
exercise_id: exercise_id, // 운동 ID
duration: duration, // 운동 시간
calories: calories, // 소모 칼로리
},
});
// 성공 메시지 반환
return res.status(200).json({ message: "추가가 완료되었습니다." });
} catch (error: any) {
// 에러 처리
console.log("서버에러", error);
return res.status(500).json({
error: "서버에서 오류가 발생했습니다.",
details: error.message,
});
}
} else {
return res.status(405).json({ error: `Method ${req.method} Not Allowed` });
}
}