Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build-and-push:
Expand All @@ -25,7 +22,10 @@ jobs:
- name: Build and Push Docker image
run: |
IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/docker-test-app
docker build -t $IMAGE_NAME:latest .
docker build \
--build-arg DATABASE_URL=${{ secrets.DATABASE_URL }} \
--build-arg JWT_SECRET=${{ secrets.JWT_SECRET }} \
-t $IMAGE_NAME:latest .
docker push $IMAGE_NAME:latest

deploy:
Expand Down
28 changes: 23 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# 베이스 이미지 설정
FROM node:16
# Node.js 18.18.0 이미지를 사용
FROM node:18.18.0

# 빌드 타임 환경 변수 설정
ARG DATABASE_URL
ARG JWT_SECRET

# 런타임 환경 변수 설정
ENV DATABASE_URL=$DATABASE_URL
ENV JWT_SECRET=$JWT_SECRET

# 작업 디렉토리 설정
WORKDIR /usr/src/app
Expand All @@ -8,11 +16,21 @@ WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install

# 소스 코드 복사
# Prisma CLI 설치 (글로벌 또는 프로젝트 내 설치에 따라 조정)
RUN npx prisma --version

# Prisma schema 파일 복사 (Prisma CLI 실행 전에 필요)
COPY prisma ./prisma

# Prisma 명령어 실행 (예: generate와 migrate)
RUN npx prisma generate
RUN npx prisma migrate deploy

# 애플리케이션 소스 코드 복사
COPY . .

# 포트 설정
# 포트 노출
EXPOSE 3000

# 앱 실행 명령어
# 애플리케이션 시작
CMD ["npm", "start"]
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
"license": "ISC",
"description": "",
"dependencies": {
"@prisma/client": "^6.1.0",
"bcrypt": "^5.1.1",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"dotenv": "^16.4.7",
"express": "^4.21.1",
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0",
"prisma": "^6.1.0",
"superstruct": "^2.0.2",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.1"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
-- CreateEnum
CREATE TYPE "Role" AS ENUM ('TRAINER', 'MEMBER');

-- CreateEnum
CREATE TYPE "Status" AS ENUM ('SCHEDULED', 'COMPLETED', 'CANCELED');

-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT NOT NULL,
"name" TEXT NOT NULL,
"role" "Role" NOT NULL DEFAULT 'MEMBER',
"profileImage" TEXT,
"phoneNumber" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "Member" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,

CONSTRAINT "Member_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "Trainer" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,

CONSTRAINT "Trainer_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "Schedule" (
"id" SERIAL NOT NULL,
"date" TIMESTAMP(3) NOT NULL,
"location" TEXT,
"status" "Status" NOT NULL DEFAULT 'SCHEDULED',
"memberId" INTEGER NOT NULL,
"trainerId" INTEGER NOT NULL,

CONSTRAINT "Schedule_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "_MemberToTrainer" (
"A" INTEGER NOT NULL,
"B" INTEGER NOT NULL,

CONSTRAINT "_MemberToTrainer_AB_pkey" PRIMARY KEY ("A","B")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");

-- CreateIndex
CREATE UNIQUE INDEX "Member_userId_key" ON "Member"("userId");

-- CreateIndex
CREATE UNIQUE INDEX "Trainer_userId_key" ON "Trainer"("userId");

-- CreateIndex
CREATE INDEX "_MemberToTrainer_B_index" ON "_MemberToTrainer"("B");

-- AddForeignKey
ALTER TABLE "Member" ADD CONSTRAINT "Member_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Trainer" ADD CONSTRAINT "Trainer_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_memberId_fkey" FOREIGN KEY ("memberId") REFERENCES "Member"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_trainerId_fkey" FOREIGN KEY ("trainerId") REFERENCES "Trainer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_MemberToTrainer" ADD CONSTRAINT "_MemberToTrainer_A_fkey" FOREIGN KEY ("A") REFERENCES "Member"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "_MemberToTrainer" ADD CONSTRAINT "_MemberToTrainer_B_fkey" FOREIGN KEY ("B") REFERENCES "Trainer"("id") ON DELETE CASCADE ON UPDATE CASCADE;
12 changes: 12 additions & 0 deletions prisma/migrations/20250105104938_add_user_username/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
Warnings:

- A unique constraint covering the columns `[username]` on the table `User` will be added. If there are existing duplicate values, this will fail.
- Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty.

*/
-- AlterTable
ALTER TABLE "User" ADD COLUMN "username" TEXT NOT NULL;

-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
11 changes: 11 additions & 0 deletions prisma/migrations/20250106143055_add_schedule_status/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- AlterEnum
-- This migration adds more than one value to an enum.
-- With PostgreSQL versions 11 and earlier, this is not possible
-- in a single migration. This can be worked around by creating
-- multiple migrations, each migration adding only one value to
-- the enum.


ALTER TYPE "Status" ADD VALUE 'MEMBER_PROPOSED';
ALTER TYPE "Status" ADD VALUE 'TRAINER_PROPOSED';
ALTER TYPE "Status" ADD VALUE 'REJECTED';
33 changes: 33 additions & 0 deletions prisma/migrations/20250115105416_add_trainer_member/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Warnings:

- You are about to drop the `_MemberToTrainer` table. If the table is not empty, all the data it contains will be lost.

*/
-- DropForeignKey
ALTER TABLE "_MemberToTrainer" DROP CONSTRAINT "_MemberToTrainer_A_fkey";

-- DropForeignKey
ALTER TABLE "_MemberToTrainer" DROP CONSTRAINT "_MemberToTrainer_B_fkey";

-- DropTable
DROP TABLE "_MemberToTrainer";

-- CreateTable
CREATE TABLE "TrainerMember" (
"id" SERIAL NOT NULL,
"memberId" INTEGER NOT NULL,
"trainerId" INTEGER NOT NULL,
"ptStartDate" TIMESTAMP(3) NOT NULL,

CONSTRAINT "TrainerMember_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "TrainerMember_memberId_trainerId_key" ON "TrainerMember"("memberId", "trainerId");

-- AddForeignKey
ALTER TABLE "TrainerMember" ADD CONSTRAINT "TrainerMember_memberId_fkey" FOREIGN KEY ("memberId") REFERENCES "Member"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "TrainerMember" ADD CONSTRAINT "TrainerMember_trainerId_fkey" FOREIGN KEY ("trainerId") REFERENCES "Trainer"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
3 changes: 3 additions & 0 deletions prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "postgresql"
99 changes: 99 additions & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
email String @unique
username String @unique // 사용자 고유 아이디
password String
name String
role Role @default(MEMBER) // 역할 구분
profileImage String? // 프로필 이미지 (선택적)
phoneNumber String? // 연락처 (선택적)
createdAt DateTime @default(now())

// 관계
member Member?
trainer Trainer?
}

model Member {
id Int @id @default(autoincrement())
userId Int @unique
user User @relation(fields: [userId], references: [id])
trainers TrainerMember[] // 연결된 트레이너 목록
schedules Schedule[] // 관련된 스케줄 목록
}

model Trainer {
id Int @id @default(autoincrement())
userId Int @unique
user User @relation(fields: [userId], references: [id])
members TrainerMember[] // 관리하는 회원 목록
schedules Schedule[] // PT 스케줄
}

model TrainerMember {
id Int @id @default(autoincrement())
memberId Int
trainerId Int
member Member @relation(fields: [memberId], references: [id])
trainer Trainer @relation(fields: [trainerId], references: [id])

// 추가 정보
ptStartDate DateTime // PT 시작일

// 고유 제약조건
@@unique([memberId, trainerId]) // 한 회원-트레이너 조합은 중복될 수 없음
}

model Schedule {
id Int @id @default(autoincrement())
date DateTime // PT 날짜 및 시간
location String? // PT 장소 (선택적)
status Status @default(SCHEDULED) // 일정 상태
trainingTarget String
comment String?
exerciseDetails ExerciseDetail[]
memberId Int
trainerId Int
member Member @relation(fields: [memberId], references: [id])
trainer Trainer @relation(fields: [trainerId], references: [id])
}

model ExerciseDetail {
id Int @id @default(autoincrement())
scheduleId Int // FitnessGoal과 연결
schedule Schedule @relation(fields: [scheduleId], references: [id])
exerciseName String // 운동 이름 (예: 스쿼트, 데드리프트)
reps Int // 반복 횟수
sets Int // 세트 수
weight Float? // 무게 (선택적, 예: kg)
duration Int? // 운동 시간 (선택적, 예: 분)
}

enum Role {
TRAINER
MEMBER
}

enum Status {
MEMBER_PROPOSED // 멤버가 제안한 상태
TRAINER_PROPOSED // 트레이너가 제안한 상태
REJECTED // 거절 상태
SCHEDULED // PT가 확정된 상태
COMPLETED // 완료된 상태
CANCELED // 취소된 상태
}
4 changes: 2 additions & 2 deletions src/config/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const options = {
definition: {
openapi: '3.0.0',
info: {
title: 'Project Setup Template API',
title: 'Project PTLink API',
version: '1.0.0',
description: 'API documentation for Project Setup Template',
description: 'API documentation for PTLink',
},
servers: [
{
Expand Down
Loading