diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index d94e7deb..02c76837 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -3,7 +3,7 @@ import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' import tseslint from 'typescript-eslint' -import { globalIgnores } from 'eslint/config' +import {globalIgnores} from 'eslint/config' export default tseslint.config([ globalIgnores(['dist']), diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg index e7b8dfb1..3f42576c 100644 --- a/frontend/public/vite.svg +++ b/frontend/public/vite.svg @@ -1 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5a75814c..44f1900c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,7 +1,7 @@ -import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; +import {BrowserRouter as Router, Route, Routes} from 'react-router-dom'; import AdminRoute from './components/AdminRoute'; import Layout from './components/Layout'; -import { AuthProvider } from './context/AuthContext'; +import {AuthProvider} from './context/AuthContext'; import AdminLayout from './pages/admin/AdminLayout'; import AdminPage from './pages/admin/AdminPage'; import AdminSchedulePage from './pages/admin/AdminSchedulePage'; diff --git a/frontend/src/api/apiClient.ts b/frontend/src/api/apiClient.ts index 243b84ae..5871ff7f 100644 --- a/frontend/src/api/apiClient.ts +++ b/frontend/src/api/apiClient.ts @@ -1,4 +1,4 @@ -import axios, { type AxiosError, type AxiosRequestConfig, type Method } from 'axios'; +import axios, {type AxiosError, type AxiosRequestConfig, type Method} from 'axios'; import JSONbig from 'json-bigint'; // Create a JSONbig instance that stores big integers as strings diff --git a/frontend/src/api/auth/authAPI.ts b/frontend/src/api/auth/authAPI.ts index 30c9b215..93216199 100644 --- a/frontend/src/api/auth/authAPI.ts +++ b/frontend/src/api/auth/authAPI.ts @@ -1,5 +1,5 @@ import apiClient from '@_api/apiClient'; -import type { CurrentUserContext, LoginRequest, LoginSuccessResponse } from './authTypes'; +import type {CurrentUserContext, LoginRequest, LoginSuccessResponse} from './authTypes'; export const login = async (data: LoginRequest): Promise => { diff --git a/frontend/src/api/payment/paymentAPI.ts b/frontend/src/api/payment/paymentAPI.ts index c5481ec8..d2923e0b 100644 --- a/frontend/src/api/payment/paymentAPI.ts +++ b/frontend/src/api/payment/paymentAPI.ts @@ -1,5 +1,5 @@ import apiClient from "@_api/apiClient"; -import type { PaymentCancelRequest, PaymentConfirmRequest, PaymentCreateResponseV2 } from "./PaymentTypes"; +import type {PaymentCancelRequest, PaymentConfirmRequest, PaymentCreateResponseV2} from "./PaymentTypes"; export const confirmPayment = async (reservationId: string, request: PaymentConfirmRequest): Promise => { return await apiClient.post(`/payments?reservationId=${reservationId}`, request); diff --git a/frontend/src/api/reservation/reservationAPIV2.ts b/frontend/src/api/reservation/reservationAPI.ts similarity index 97% rename from frontend/src/api/reservation/reservationAPIV2.ts rename to frontend/src/api/reservation/reservationAPI.ts index 9bb14321..f2a80d5e 100644 --- a/frontend/src/api/reservation/reservationAPIV2.ts +++ b/frontend/src/api/reservation/reservationAPI.ts @@ -5,7 +5,7 @@ import type { PendingReservationCreateResponse, ReservationDetailRetrieveResponse, ReservationSummaryRetrieveListResponse -} from './reservationTypesV2'; +} from './reservationTypes'; export const createPendingReservation = async (request: PendingReservationCreateRequest): Promise => { return await apiClient.post('/reservations/pending', request); diff --git a/frontend/src/api/reservation/reservationTypesV2.ts b/frontend/src/api/reservation/reservationTypes.ts similarity index 68% rename from frontend/src/api/reservation/reservationTypesV2.ts rename to frontend/src/api/reservation/reservationTypes.ts index bc6eb4e9..5c19d21a 100644 --- a/frontend/src/api/reservation/reservationTypesV2.ts +++ b/frontend/src/api/reservation/reservationTypes.ts @@ -1,7 +1,7 @@ -import type { PaymentRetrieveResponse } from "@_api/payment/PaymentTypes"; -import type { UserContactRetrieveResponse } from "@_api/user/userTypes"; +import type {PaymentRetrieveResponse} from "@_api/payment/PaymentTypes"; +import type {UserContactRetrieveResponse} from "@_api/user/userTypes"; -export const ReservationStatusV2 = { +export const ReservationStatus = { PENDING: 'PENDING', CONFIRMED: 'CONFIRMED', CANCELED: 'CANCELED', @@ -9,12 +9,12 @@ export const ReservationStatusV2 = { EXPIRED: 'EXPIRED' } as const; -export type ReservationStatusV2 = - | typeof ReservationStatusV2.PENDING - | typeof ReservationStatusV2.CONFIRMED - | typeof ReservationStatusV2.CANCELED - | typeof ReservationStatusV2.FAILED - | typeof ReservationStatusV2.EXPIRED; +export type ReservationStatus = + | typeof ReservationStatus.PENDING + | typeof ReservationStatus.CONFIRMED + | typeof ReservationStatus.CANCELED + | typeof ReservationStatus.FAILED + | typeof ReservationStatus.EXPIRED; export interface PendingReservationCreateRequest { scheduleId: string, @@ -33,7 +33,7 @@ export interface ReservationSummaryRetrieveResponse { themeName: string; date: string; startAt: string; - status: ReservationStatusV2; + status: ReservationStatus; } export interface ReservationSummaryRetrieveListResponse { @@ -54,7 +54,7 @@ export interface ReservationDetail { startAt: string; user: UserContactRetrieveResponse; applicationDateTime: string; - payment: PaymentRetrieveResponse; + payment?: PaymentRetrieveResponse; } export interface MostReservedThemeIdListResponse { diff --git a/frontend/src/api/schedule/scheduleAPI.ts b/frontend/src/api/schedule/scheduleAPI.ts index f828fa2b..87d7d0ac 100644 --- a/frontend/src/api/schedule/scheduleAPI.ts +++ b/frontend/src/api/schedule/scheduleAPI.ts @@ -2,7 +2,8 @@ import apiClient from '../apiClient'; import type { AvailableThemeIdListResponse, ScheduleCreateRequest, - ScheduleCreateResponse, ScheduleDetailRetrieveResponse, + ScheduleCreateResponse, + ScheduleDetailRetrieveResponse, ScheduleRetrieveListResponse, ScheduleUpdateRequest } from './scheduleTypes'; diff --git a/frontend/src/api/schedule/scheduleTypes.ts b/frontend/src/api/schedule/scheduleTypes.ts index 6230cf01..9a08ac1e 100644 --- a/frontend/src/api/schedule/scheduleTypes.ts +++ b/frontend/src/api/schedule/scheduleTypes.ts @@ -1,9 +1,11 @@ -export enum ScheduleStatus { - AVAILABLE = 'AVAILABLE', - HOLD = 'HOLD', - RESERVED = 'RESERVED', - BLOCKED = 'BLOCKED', -} +export type ScheduleStatus = 'AVAILABLE' | 'HOLD' | 'RESERVED' | 'BLOCKED'; + +export const ScheduleStatus = { + AVAILABLE: 'AVAILABLE' as ScheduleStatus, + HOLD: 'HOLD' as ScheduleStatus, + RESERVED: 'RESERVED' as ScheduleStatus, + BLOCKED: 'BLOCKED' as ScheduleStatus, +}; export interface AvailableThemeIdListResponse { themeIds: string[]; diff --git a/frontend/src/api/theme/themeAPI.ts b/frontend/src/api/theme/themeAPI.ts index 1c7566ca..3db475d2 100644 --- a/frontend/src/api/theme/themeAPI.ts +++ b/frontend/src/api/theme/themeAPI.ts @@ -3,29 +3,12 @@ import type { AdminThemeDetailRetrieveResponse, AdminThemeSummaryRetrieveListResponse, ThemeCreateRequest, - ThemeCreateRequestV2, ThemeCreateResponse, - ThemeCreateResponseV2, ThemeListRetrieveRequest, ThemeRetrieveListResponse, - ThemeRetrieveListResponseV2, - ThemeUpdateRequest, - UserThemeRetrieveListResponse + ThemeCreateResponse, + ThemeIdListResponse, + ThemeInfoListResponse, + ThemeUpdateRequest } from './themeTypes'; -export const createTheme = async (data: ThemeCreateRequest): Promise => { - return await apiClient.post('/themes', data, true); -}; - -export const fetchThemes = async (): Promise => { - return await apiClient.get('/themes', true); -}; - -export const mostReservedThemes = async (count: number = 10): Promise => { - return await apiClient.get(`/themes/most-reserved-last-week?count=${count}`, false); -}; - -export const delTheme = async (id: string): Promise => { - return await apiClient.del(`/themes/${id}`, true); -}; - export const fetchAdminThemes = async (): Promise => { return await apiClient.get('/admin/themes'); }; @@ -34,8 +17,8 @@ export const fetchAdminThemeDetail = async (id: string): Promise(`/admin/themes/${id}`); }; -export const createThemeV2 = async (themeData: ThemeCreateRequestV2): Promise => { - return await apiClient.post('/admin/themes', themeData); +export const createTheme = async (themeData: ThemeCreateRequest): Promise => { + return await apiClient.post('/admin/themes', themeData); }; export const updateTheme = async (id: string, themeData: ThemeUpdateRequest): Promise => { @@ -46,10 +29,10 @@ export const deleteTheme = async (id: string): Promise => { await apiClient.del(`/admin/themes/${id}`); }; -export const fetchUserThemes = async (): Promise => { - return await apiClient.get('/v2/themes'); +export const fetchUserThemes = async (): Promise => { + return await apiClient.get('/themes'); }; -export const findThemesByIds = async (request: ThemeListRetrieveRequest): Promise => { - return await apiClient.post('/themes/retrieve', request); +export const findThemesByIds = async (request: ThemeIdListResponse): Promise => { + return await apiClient.post('/themes/retrieve', request); }; diff --git a/frontend/src/api/theme/themeTypes.ts b/frontend/src/api/theme/themeTypes.ts index 7fe1327f..ba28bc0d 100644 --- a/frontend/src/api/theme/themeTypes.ts +++ b/frontend/src/api/theme/themeTypes.ts @@ -1,29 +1,4 @@ -export interface ThemeCreateRequest { - name: string; - description: string; - thumbnail: string; -} - -export interface ThemeCreateResponse { - id: string; - name: string; - description: string; - thumbnail: string; -} - -export interface ThemeRetrieveResponse { - id: string; - name: string; - description: string; - thumbnail: string; -} - -export interface ThemeRetrieveListResponse { - themes: ThemeRetrieveResponse[]; -} - - -export interface ThemeV2 { +export interface AdminThemeDetailResponse { id: string; name: string; description: string; @@ -42,7 +17,7 @@ export interface ThemeV2 { updatedBy: string; } -export interface ThemeCreateRequestV2 { +export interface ThemeCreateRequest { name: string; description: string; thumbnailUrl: string; @@ -56,7 +31,7 @@ export interface ThemeCreateRequestV2 { isOpen: boolean; } -export interface ThemeCreateResponseV2 { +export interface ThemeCreateResponse { id: string; } @@ -105,7 +80,7 @@ export interface AdminThemeDetailRetrieveResponse { updatedBy: string; } -export interface UserThemeRetrieveResponse { +export interface ThemeInfoResponse { id: string; name: string; thumbnailUrl: string; @@ -119,32 +94,14 @@ export interface UserThemeRetrieveResponse { expectedMinutesTo: number; } -export interface UserThemeRetrieveListResponse { - themes: UserThemeRetrieveResponse[]; +export interface ThemeInfoListResponse { + themes: ThemeInfoResponse[]; } -export interface ThemeListRetrieveRequest { +export interface ThemeIdListResponse { themeIds: string[]; } -export interface ThemeRetrieveResponseV2 { - id: string; - name: string; - thumbnailUrl: string; - description: string; - difficulty: Difficulty; - price: number; - minParticipants: number; - maxParticipants: number; - availableMinutes: number; - expectedMinutesFrom: number; - expectedMinutesTo: number; -} - -export interface ThemeRetrieveListResponseV2 { - themes: ThemeRetrieveResponseV2[]; -} - // @ts-ignore export enum Difficulty { VERY_EASY = '매우 쉬움', @@ -154,7 +111,7 @@ export enum Difficulty { VERY_HARD = '매우 어려움', } -export function mapThemeResponse(res: any): UserThemeRetrieveResponse { +export function mapThemeResponse(res: any): ThemeInfoResponse { return { ...res, difficulty: Difficulty[res.difficulty as keyof typeof Difficulty], diff --git a/frontend/src/api/user/userAPI.ts b/frontend/src/api/user/userAPI.ts index 7388f7d7..84a2422d 100644 --- a/frontend/src/api/user/userAPI.ts +++ b/frontend/src/api/user/userAPI.ts @@ -1,5 +1,5 @@ import apiClient from "@_api/apiClient"; -import type { UserContactRetrieveResponse, UserCreateRequest, UserCreateResponse } from "./userTypes"; +import type {UserContactRetrieveResponse, UserCreateRequest, UserCreateResponse} from "./userTypes"; export const signup = async (data: UserCreateRequest): Promise => { return await apiClient.post('/users', data, false); diff --git a/frontend/src/assets/react.svg b/frontend/src/assets/react.svg index 6c87de9b..df634bcc 100644 --- a/frontend/src/assets/react.svg +++ b/frontend/src/assets/react.svg @@ -1 +1,2 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/frontend/src/components/AdminRoute.tsx b/frontend/src/components/AdminRoute.tsx index e8354014..c238090d 100644 --- a/frontend/src/components/AdminRoute.tsx +++ b/frontend/src/components/AdminRoute.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Navigate, useLocation } from 'react-router-dom'; -import { useAuth } from '../context/AuthContext'; +import {Navigate, useLocation} from 'react-router-dom'; +import {useAuth} from '../context/AuthContext'; const AdminRoute: React.FC<{ children: JSX.Element }> = ({ children }) => { const { loggedIn, role, loading } = useAuth(); diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index e4440f76..5064a970 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import React, { type ReactNode } from 'react'; +import React, {type ReactNode} from 'react'; import Navbar from './Navbar'; interface LayoutProps { diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx index ceff4b6d..8de67e34 100644 --- a/frontend/src/components/Navbar.tsx +++ b/frontend/src/components/Navbar.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Link, useNavigate } from 'react-router-dom'; -import { useAuth } from 'src/context/AuthContext'; +import {Link, useNavigate} from 'react-router-dom'; +import {useAuth} from 'src/context/AuthContext'; import 'src/css/navbar.css'; const Navbar: React.FC = () => { diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index e7d7868e..e220f436 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -1,6 +1,6 @@ -import { checkLogin as apiCheckLogin, login as apiLogin, logout as apiLogout } from '@_api/auth/authAPI'; -import { PrincipalType, type LoginRequest, type LoginSuccessResponse } from '@_api/auth/authTypes'; -import React, { createContext, useContext, useEffect, useState, type ReactNode } from 'react'; +import {checkLogin as apiCheckLogin, login as apiLogin, logout as apiLogout} from '@_api/auth/authAPI'; +import {type LoginRequest, type LoginSuccessResponse, PrincipalType} from '@_api/auth/authTypes'; +import React, {createContext, type ReactNode, useContext, useEffect, useState} from 'react'; interface AuthContextType { loggedIn: boolean; diff --git a/frontend/src/css/admin-time-page.css b/frontend/src/css/admin-time-page.css deleted file mode 100644 index d9505924..00000000 --- a/frontend/src/css/admin-time-page.css +++ /dev/null @@ -1,120 +0,0 @@ -/* /src/css/admin-time-page.css */ -.admin-time-container { - max-width: 800px; - margin: 40px auto; - padding: 40px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - background-color: #f4f6f8; - border-radius: 16px; -} - -.admin-time-container .page-title { - font-size: 32px; - font-weight: 700; - color: #333d4b; - margin-bottom: 30px; - text-align: center; -} - -.section-card { - background-color: #ffffff; - border-radius: 12px; - padding: 24px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); -} - -.table-header { - display: flex; - justify-content: flex-end; - margin-bottom: 20px; -} - -.table-container table { - width: 100%; - border-collapse: collapse; - font-size: 15px; -} - -.table-container th, -.table-container td { - padding: 12px 16px; - text-align: left; - border-bottom: 1px solid #e5e8eb; - vertical-align: middle; -} - -.table-container th { - background-color: #f9fafb; - color: #505a67; - font-weight: 600; -} - -.table-container tr:last-child td { - border-bottom: none; -} - -.table-container tr:hover { - background-color: #f4f6f8; -} - -.form-input { - width: 100%; - padding: 10px 12px; - font-size: 15px; - border: 1px solid #E5E8EB; - border-radius: 8px; - box-sizing: border-box; - transition: border-color 0.2s, box-shadow 0.2s; -} - -.form-input:focus { - outline: none; - border-color: #3182F6; - box-shadow: 0 0 0 3px rgba(49, 130, 246, 0.2); -} - -.btn { - padding: 8px 16px; - font-size: 15px; - font-weight: 600; - border-radius: 8px; - border: none; - cursor: pointer; - transition: background-color 0.2s; -} - -.btn-primary { - background-color: #3182F6; - color: #ffffff; -} - -.btn-primary:hover { - background-color: #1B64DA; -} - -.btn-secondary { - background-color: #F2F4F6; - color: #4E5968; -} - -.btn-secondary:hover { - background-color: #E5E8EB; -} - -.btn-danger { - background-color: #e53e3e; - color: white; -} - -.btn-danger:hover { - background-color: #c53030; -} - -.editing-row td { - padding-top: 20px; - padding-bottom: 20px; -} - -.editing-row .btn { - margin-right: 8px; -} diff --git a/frontend/src/css/admin-waiting-page.css b/frontend/src/css/admin-waiting-page.css deleted file mode 100644 index 4d840945..00000000 --- a/frontend/src/css/admin-waiting-page.css +++ /dev/null @@ -1,81 +0,0 @@ -/* /src/css/admin-waiting-page.css */ -.admin-waiting-container { - max-width: 1200px; - margin: 40px auto; - padding: 40px; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - background-color: #f4f6f8; - border-radius: 16px; -} - -.admin-waiting-container .page-title { - font-size: 32px; - font-weight: 700; - color: #333d4b; - margin-bottom: 30px; - text-align: center; -} - -.section-card { - background-color: #ffffff; - border-radius: 12px; - padding: 24px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); -} - -.table-container table { - width: 100%; - border-collapse: collapse; - font-size: 15px; -} - -.table-container th, -.table-container td { - padding: 12px 16px; - text-align: left; - border-bottom: 1px solid #e5e8eb; - vertical-align: middle; -} - -.table-container th { - background-color: #f9fafb; - color: #505a67; - font-weight: 600; -} - -.table-container tr:last-child td { - border-bottom: none; -} - -.table-container tr:hover { - background-color: #f4f6f8; -} - -.btn { - padding: 8px 16px; - font-size: 15px; - font-weight: 600; - border-radius: 8px; - border: none; - cursor: pointer; - transition: background-color 0.2s; - margin-right: 8px; -} - -.btn-primary { - background-color: #3182F6; - color: #ffffff; -} - -.btn-primary:hover { - background-color: #1B64DA; -} - -.btn-danger { - background-color: #e53e3e; - color: white; -} - -.btn-danger:hover { - background-color: #c53030; -} diff --git a/frontend/src/css/reservation-v2-1.css b/frontend/src/css/reservation-v2-1.css index 76820556..e8ccbeeb 100644 --- a/frontend/src/css/reservation-v2-1.css +++ b/frontend/src/css/reservation-v2-1.css @@ -327,13 +327,13 @@ } .modal-content { - background-color: #ffffff; - padding: 32px; - border-radius: 16px; - width: 90%; - max-width: 500px; - position: relative; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + background-color: #ffffff !important; + padding: 32px !important; + border-radius: 16px !important; + width: 90% !important; + max-width: 500px !important; + position: relative !important; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1) !important; } .modal-close-button { diff --git a/frontend/src/css/reservation-v2.css b/frontend/src/css/reservation-v2.css deleted file mode 100644 index f93c3581..00000000 --- a/frontend/src/css/reservation-v2.css +++ /dev/null @@ -1,175 +0,0 @@ -#root .flatpickr-input { - display: none; -} - -#root .modal-backdrop { - position: fixed; - top: 0; - left: 0; - z-index: 1050; - width: 100vw; - height: 100vh; - background-color: rgba(0, 0, 0, 0.5) !important; - display: flex; - justify-content: center; - align-items: center; -} - -#root .modal-dialog { - max-width: 500px; - width: 90%; - margin: 1.75rem auto; -} - -/* Toss-style Modal */ -#root .modal-content { - background-color: #fff !important; - border-radius: 16px; - border: none; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - padding: 1.5rem; - display: flex; - flex-direction: column; - pointer-events: auto; - position: relative; -} - -#root .modal-header { - border-bottom: none; - padding: 0 0 1rem 0; - display: flex; - justify-content: space-between; - align-items: center; -} - -#root .modal-title { - font-size: 1.25rem; - font-weight: 600; -} - -#root .btn-close { - background: transparent; - border: 0; - font-size: 1.5rem; - opacity: 0.5; -} - -#root .modal-body { - padding: 1rem 0; - color: #333; -} - -#root .modal-body p { - margin-bottom: 0.5rem; -} - -#root .modal-footer { - border-top: none; - padding: 1rem 0 0 0; - display: flex; - justify-content: flex-end; - gap: 0.5rem; -} - -/* --- Generic Button Styles --- */ -#root .btn-primary, -#root .modal-footer .btn-primary, -#root .btn-wrapper .btn-primary, -#root .button-group .btn-primary, -#root .success-page-actions .btn-primary { - background-color: #007bff; - border-color: #007bff; - color: #fff; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; - padding: 0.75rem 1.5rem; - border-radius: 8px; - text-decoration: none; - font-weight: 500; -} - -#root .btn-secondary, -#root .modal-footer .btn-secondary, -#root .success-page-actions .btn-secondary { - background-color: #f0f2f5; - border-color: #f0f2f5; - color: #333; - padding: 0.75rem 1.5rem; - border-radius: 8px; - text-decoration: none; - font-weight: 500; - transition: background-color 0.15s ease-in-out; -} - -#root .btn-primary:hover, -#root .modal-footer .btn-primary:hover, -#root .btn-wrapper .btn-primary:hover, -#root .button-group .btn-primary:hover, -#root .success-page-actions .btn-primary:hover { - background-color: #0069d9; - border-color: #0062cc; -} - -#root .btn-secondary:hover, -#root .modal-footer .btn-secondary:hover, -#root .success-page-actions .btn-secondary:hover { - background-color: #e2e6ea; -} - - -/* --- Reservation Success Page Styles --- */ -.reservation-success-page { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 3rem 1rem; - text-align: center; - width: 100%; - max-width: 100%; -} - -.reservation-success-page .content-container-title { - font-size: 2rem; - font-weight: 600; - margin-bottom: 1.5rem; - color: #333; -} - -.reservation-info-box { - border: 1px solid #e9ecef; - border-radius: 12px; - padding: 2rem; - background-color: #fff; - min-width: 380px; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); - text-align: left; -} - -.reservation-info-box h3 { - font-size: 1.25rem; - font-weight: 600; - margin-bottom: 1.5rem; - padding-bottom: 1rem; - border-bottom: 1px solid #e9ecef; - text-align: center; -} - -.reservation-info-box .info-item { - font-size: 1.1rem; - margin-bottom: 1rem; - display: flex; - align-items: center; -} - -.reservation-info-box .info-item strong { - font-weight: 500; - color: #495057; - width: 70px; - flex-shrink: 0; -} - -.success-page-actions { - margin-top: 2.5rem; - display: flex; - gap: 1rem; -} diff --git a/frontend/src/css/reservation.css b/frontend/src/css/reservation.css deleted file mode 100644 index de9666b7..00000000 --- a/frontend/src/css/reservation.css +++ /dev/null @@ -1,15 +0,0 @@ -.disabled { - pointer-events: none; - opacity: 0.6; -} - -#theme-slots .theme-slot.active, #time-slots .time-slot.active { - background-color: #0a3711 !important; - color: white; -} - -#time-slots .time-slot.disabled { - background-color: #cccccc; - color: #666666; - cursor: not-allowed; -} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 2b1afe7d..3493ebf6 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -3,9 +3,8 @@ import ReactDOM from 'react-dom/client'; import App from './App'; import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap/dist/js/bootstrap.bundle.min.js'; -import './css/style.css'; -import './css/reservation.css'; -import './css/toss-style.css'; +import '@_css/style.css'; +import '@_css/toss-style.css'; ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index b6381572..a5c22119 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -1,13 +1,13 @@ -import {fetchMostReservedThemeIds} from '@_api/reservation/reservationAPIV2'; +import {fetchMostReservedThemeIds} from '@_api/reservation/reservationAPI'; import '@_css/home-page-v2.css'; import React, {useEffect, useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {findThemesByIds} from '@_api/theme/themeAPI'; -import {type UserThemeRetrieveResponse} from '@_api/theme/themeTypes'; +import {mapThemeResponse, type ThemeInfoResponse} from '@_api/theme/themeTypes'; const HomePage: React.FC = () => { - const [ranking, setRanking] = useState([]); - const [selectedTheme, setSelectedTheme] = useState(null); + const [ranking, setRanking] = useState([]); + const [selectedTheme, setSelectedTheme] = useState(null); const navigate = useNavigate(); useEffect(() => { @@ -26,7 +26,7 @@ const HomePage: React.FC = () => { if (themeIds.length === 0) return; const response = await findThemesByIds({ themeIds: themeIds }); - setRanking(response.themes); + setRanking(response.themes.map(mapThemeResponse)); } catch (err) { console.error('Error fetching ranking:', err); } @@ -35,7 +35,7 @@ const HomePage: React.FC = () => { fetchData(); }, []); - const handleThemeClick = (theme: UserThemeRetrieveResponse) => { + const handleThemeClick = (theme: ThemeInfoResponse) => { setSelectedTheme(theme); }; diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx index f4e130a4..db4704d3 100644 --- a/frontend/src/pages/LoginPage.tsx +++ b/frontend/src/pages/LoginPage.tsx @@ -1,6 +1,6 @@ -import React, { useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; -import { useAuth } from '@_context/AuthContext'; +import React, {useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {useAuth} from '@_context/AuthContext'; import '@_css/login-page-v2.css'; const LoginPage: React.FC = () => { diff --git a/frontend/src/pages/MyReservationPage.tsx b/frontend/src/pages/MyReservationPage.tsx index 6806e8de..d25d07f8 100644 --- a/frontend/src/pages/MyReservationPage.tsx +++ b/frontend/src/pages/MyReservationPage.tsx @@ -1,8 +1,12 @@ -import { cancelPayment } from '@_api/payment/paymentAPI'; -import type { PaymentRetrieveResponse } from '@_api/payment/PaymentTypes'; -import { cancelReservation, fetchDetailById, fetchSummaryByMember } from '@_api/reservation/reservationAPIV2'; -import { ReservationStatusV2, type ReservationDetail, type ReservationSummaryRetrieveResponse } from '@_api/reservation/reservationTypesV2'; -import React, { useEffect, useState } from 'react'; +import {cancelPayment} from '@_api/payment/paymentAPI'; +import type {PaymentRetrieveResponse} from '@_api/payment/PaymentTypes'; +import {cancelReservation, fetchDetailById, fetchSummaryByMember} from '@_api/reservation/reservationAPI'; +import { + type ReservationDetail, + ReservationStatus, + type ReservationSummaryRetrieveResponse +} from '@_api/reservation/reservationTypes'; +import React, {useEffect, useState} from 'react'; import '@_css/my-reservation-v2.css'; const getReservationStatus = (reservation: ReservationSummaryRetrieveResponse): { className: string, text: string } => { @@ -10,14 +14,14 @@ const getReservationStatus = (reservation: ReservationSummaryRetrieveResponse): const reservationDateTime = new Date(`${reservation.date}T${reservation.startAt}`); switch (reservation.status) { - case ReservationStatusV2.CANCELED: + case ReservationStatus.CANCELED: return { className: 'status-canceled', text: '취소됨' }; - case ReservationStatusV2.CONFIRMED: + case ReservationStatus.CONFIRMED: if (reservationDateTime < now) { return { className: 'status-completed', text: '이용완료' }; } return { className: 'status-confirmed', text: '예약확정' }; - case ReservationStatusV2.PENDING: + case ReservationStatus.PENDING: return { className: 'status-pending', text: '입금대기' }; default: return { className: `status-${reservation.status.toLowerCase()}`, text: reservation.status }; @@ -116,7 +120,7 @@ const CancellationView: React.FC<{ 테마: {reservation.themeName} 신청 일시: {formatDisplayDateTime(reservation.applicationDateTime)} - 결제 금액: {reservation.payment.totalAmount.toLocaleString()}원 + {reservation.payment && 결제 금액: {reservation.payment.totalAmount.toLocaleString()}원} { const navigate = useNavigate(); diff --git a/frontend/src/pages/ReservationStep1Page.tsx b/frontend/src/pages/ReservationStep1Page.tsx index 42812f61..b73f607a 100644 --- a/frontend/src/pages/ReservationStep1Page.tsx +++ b/frontend/src/pages/ReservationStep1Page.tsx @@ -1,20 +1,19 @@ -import { isLoginRequiredError } from '@_api/apiClient'; -import { findAvailableThemesByDate, findSchedules, holdSchedule } from '@_api/schedule/scheduleAPI'; -import { ScheduleStatus, type ScheduleRetrieveResponse } from '@_api/schedule/scheduleTypes'; -import { findThemesByIds } from '@_api/theme/themeAPI'; -import { mapThemeResponse, type UserThemeRetrieveResponse } from '@_api/theme/themeTypes'; +import {isLoginRequiredError} from '@_api/apiClient'; +import {findAvailableThemesByDate, findSchedules, holdSchedule} from '@_api/schedule/scheduleAPI'; +import {type ScheduleRetrieveResponse, ScheduleStatus} from '@_api/schedule/scheduleTypes'; +import {findThemesByIds} from '@_api/theme/themeAPI'; +import {mapThemeResponse, type ThemeInfoResponse} from '@_api/theme/themeTypes'; import '@_css/reservation-v2-1.css'; -import React, { useEffect, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; -import { formatDate, formatTime } from 'src/util/DateTimeFormatter'; - +import React, {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {formatDate, formatTime} from 'src/util/DateTimeFormatter'; const ReservationStep1Page: React.FC = () => { const [selectedDate, setSelectedDate] = useState(new Date()); const [viewDate, setViewDate] = useState(new Date()); // For carousel - const [themes, setThemes] = useState([]); - const [selectedTheme, setSelectedTheme] = useState(null); + const [themes, setThemes] = useState([]); + const [selectedTheme, setSelectedTheme] = useState(null); const [schedules, setSchedules] = useState([]); const [selectedSchedule, setSelectedSchedule] = useState(null); const [isThemeModalOpen, setIsThemeModalOpen] = useState(false); @@ -185,7 +184,7 @@ const ReservationStep1Page: React.FC = () => { ); }; - const openThemeModal = (theme: UserThemeRetrieveResponse) => { + const openThemeModal = (theme: ThemeInfoResponse) => { setSelectedTheme(theme); setIsThemeModalOpen(true); }; diff --git a/frontend/src/pages/ReservationStep2Page.tsx b/frontend/src/pages/ReservationStep2Page.tsx index 11c1b738..3f96ef4e 100644 --- a/frontend/src/pages/ReservationStep2Page.tsx +++ b/frontend/src/pages/ReservationStep2Page.tsx @@ -1,11 +1,11 @@ -import { isLoginRequiredError } from '@_api/apiClient'; -import { confirmPayment } from '@_api/payment/paymentAPI'; -import { PaymentType, type PaymentConfirmRequest } from '@_api/payment/PaymentTypes'; -import { confirmReservation } from '@_api/reservation/reservationAPIV2'; +import {isLoginRequiredError} from '@_api/apiClient'; +import {confirmPayment} from '@_api/payment/paymentAPI'; +import {type PaymentConfirmRequest, PaymentType} from '@_api/payment/PaymentTypes'; +import {confirmReservation} from '@_api/reservation/reservationAPI'; import '@_css/reservation-v2-1.css'; -import React, { useEffect, useRef } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; -import { formatDate, formatTime } from 'src/util/DateTimeFormatter'; +import React, {useEffect, useRef} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {formatDate, formatTime} from 'src/util/DateTimeFormatter'; declare global { interface Window { diff --git a/frontend/src/pages/ReservationSuccessPage.tsx b/frontend/src/pages/ReservationSuccessPage.tsx index f6d39a3d..5f86aebf 100644 --- a/frontend/src/pages/ReservationSuccessPage.tsx +++ b/frontend/src/pages/ReservationSuccessPage.tsx @@ -1,7 +1,7 @@ import '@_css/reservation-v2-1.css'; // Reuse the new CSS import React from 'react'; -import { Link, useLocation } from 'react-router-dom'; -import { formatDate, formatTime } from 'src/util/DateTimeFormatter'; +import {Link, useLocation} from 'react-router-dom'; +import {formatDate, formatTime} from 'src/util/DateTimeFormatter'; const ReservationSuccessPage: React.FC = () => { const location = useLocation(); diff --git a/frontend/src/pages/SignupPage.tsx b/frontend/src/pages/SignupPage.tsx index 0ac27557..845ac67d 100644 --- a/frontend/src/pages/SignupPage.tsx +++ b/frontend/src/pages/SignupPage.tsx @@ -1,8 +1,8 @@ -import { signup } from '@_api/user/userAPI'; -import type { UserCreateRequest, UserCreateResponse } from '@_api/user/userTypes'; +import {signup} from '@_api/user/userAPI'; +import type {UserCreateRequest, UserCreateResponse} from '@_api/user/userTypes'; import '@_css/signup-page-v2.css'; -import React, { useState, useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; +import React, {useEffect, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; const MIN_PASSWORD_LENGTH = 8; diff --git a/frontend/src/pages/admin/AdminLayout.tsx b/frontend/src/pages/admin/AdminLayout.tsx index 47034a06..e5ca8e7d 100644 --- a/frontend/src/pages/admin/AdminLayout.tsx +++ b/frontend/src/pages/admin/AdminLayout.tsx @@ -1,4 +1,4 @@ -import React, { type ReactNode } from 'react'; +import React, {type ReactNode} from 'react'; import AdminNavbar from './AdminNavbar'; interface AdminLayoutProps { diff --git a/frontend/src/pages/admin/AdminNavbar.tsx b/frontend/src/pages/admin/AdminNavbar.tsx index 263f203c..8928fb1f 100644 --- a/frontend/src/pages/admin/AdminNavbar.tsx +++ b/frontend/src/pages/admin/AdminNavbar.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { Link, useNavigate } from 'react-router-dom'; -import { useAuth } from '@_context/AuthContext'; +import {Link, useNavigate} from 'react-router-dom'; +import {useAuth} from '@_context/AuthContext'; import '@_css/navbar.css'; const AdminNavbar: React.FC = () => { diff --git a/frontend/src/pages/admin/AdminSchedulePage.tsx b/frontend/src/pages/admin/AdminSchedulePage.tsx index 7f8c5793..9af77826 100644 --- a/frontend/src/pages/admin/AdminSchedulePage.tsx +++ b/frontend/src/pages/admin/AdminSchedulePage.tsx @@ -1,11 +1,21 @@ -import { isLoginRequiredError } from '@_api/apiClient'; -import { createSchedule, deleteSchedule, findScheduleById, findSchedules, updateSchedule } from '@_api/schedule/scheduleAPI'; -import { ScheduleStatus, type ScheduleDetailRetrieveResponse, type ScheduleRetrieveResponse } from '@_api/schedule/scheduleTypes'; -import { fetchAdminThemes } from '@_api/theme/themeAPI'; -import type { AdminThemeSummaryRetrieveResponse } from '@_api/theme/themeTypes'; +import {isLoginRequiredError} from '@_api/apiClient'; +import { + createSchedule, + deleteSchedule, + findScheduleById, + findSchedules, + updateSchedule +} from '@_api/schedule/scheduleAPI'; +import { + type ScheduleDetailRetrieveResponse, + type ScheduleRetrieveResponse, + ScheduleStatus +} from '@_api/schedule/scheduleTypes'; +import {fetchAdminThemes} from '@_api/theme/themeAPI'; +import type {AdminThemeSummaryRetrieveResponse} from '@_api/theme/themeTypes'; import '@_css/admin-schedule-page.css'; -import React, { Fragment, useEffect, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; +import React, {Fragment, useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; const getScheduleStatusText = (status: ScheduleStatus): string => { switch (status) { diff --git a/frontend/src/pages/admin/AdminThemeEditPage.tsx b/frontend/src/pages/admin/AdminThemeEditPage.tsx index 40f561fe..91af8d32 100644 --- a/frontend/src/pages/admin/AdminThemeEditPage.tsx +++ b/frontend/src/pages/admin/AdminThemeEditPage.tsx @@ -1,13 +1,13 @@ -import { isLoginRequiredError } from '@_api/apiClient'; +import {isLoginRequiredError} from '@_api/apiClient'; +import {createTheme, deleteTheme, fetchAdminThemeDetail, updateTheme} from '@_api/theme/themeAPI'; import { - createThemeV2, - deleteTheme, - fetchAdminThemeDetail, - updateTheme -} from '@_api/theme/themeAPI'; -import { Difficulty, type ThemeCreateRequestV2, type ThemeUpdateRequest, type ThemeV2 } from '@_api/theme/themeTypes'; -import React, { useEffect, useState } from 'react'; -import { useLocation, useNavigate, useParams } from 'react-router-dom'; + type AdminThemeDetailResponse, + Difficulty, + type ThemeCreateRequest, + type ThemeUpdateRequest +} from '@_api/theme/themeTypes'; +import React, {useEffect, useState} from 'react'; +import {useLocation, useNavigate, useParams} from 'react-router-dom'; import '@_css/admin-theme-edit-page.css'; const AdminThemeEditPage: React.FC = () => { @@ -17,8 +17,8 @@ const AdminThemeEditPage: React.FC = () => { const isNew = themeId === 'new'; - const [theme, setTheme] = useState(null); - const [originalTheme, setOriginalTheme] = useState(null); + const [theme, setTheme] = useState(null); + const [originalTheme, setOriginalTheme] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isEditing, setIsEditing] = useState(isNew); @@ -35,7 +35,7 @@ const AdminThemeEditPage: React.FC = () => { useEffect(() => { if (isNew) { - const newTheme: ThemeCreateRequestV2 = { + const newTheme: ThemeCreateRequest = { name: '', description: '', thumbnailUrl: '', @@ -55,7 +55,7 @@ const AdminThemeEditPage: React.FC = () => { fetchAdminThemeDetail(themeId) .then(data => { // Map AdminThemeDetailRetrieveResponse to ThemeV2 - const fetchedTheme: ThemeV2 = { + const fetchedTheme: AdminThemeDetailResponse = { id: data.id, name: data.name, description: data.description, @@ -112,7 +112,7 @@ const AdminThemeEditPage: React.FC = () => { try { if (isNew) { - await createThemeV2(theme as ThemeCreateRequestV2); + await createTheme(theme as ThemeCreateRequest); alert('테마가 성공적으로 생성되었습니다.'); navigate(`/admin/theme`); } else { diff --git a/frontend/src/pages/admin/AdminThemePage.tsx b/frontend/src/pages/admin/AdminThemePage.tsx index 82ba9284..8d69b19a 100644 --- a/frontend/src/pages/admin/AdminThemePage.tsx +++ b/frontend/src/pages/admin/AdminThemePage.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from 'react'; -import { useLocation, useNavigate } from 'react-router-dom'; -import { fetchAdminThemes } from '@_api/theme/themeAPI'; +import React, {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {fetchAdminThemes} from '@_api/theme/themeAPI'; import type {AdminThemeSummaryRetrieveResponse} from '@_api/theme/themeTypes'; -import { isLoginRequiredError } from '@_api/apiClient'; +import {isLoginRequiredError} from '@_api/apiClient'; import '@_css/admin-theme-page.css'; const AdminThemePage: React.FC = () => { diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 9fe3fabb..e466cef2 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,4 +1,4 @@ -import { defineConfig } from 'vite' +import {defineConfig} from 'vite' import react from '@vitejs/plugin-react' import tsconfigPaths from 'vite-tsconfig-paths' diff --git a/src/main/kotlin/roomescape/payment/web/PaymentController.kt b/src/main/kotlin/roomescape/payment/web/PaymentController.kt index 3edc2293..0d8093b3 100644 --- a/src/main/kotlin/roomescape/payment/web/PaymentController.kt +++ b/src/main/kotlin/roomescape/payment/web/PaymentController.kt @@ -4,6 +4,7 @@ import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController import roomescape.auth.web.support.CurrentUser @@ -13,11 +14,12 @@ import roomescape.payment.business.PaymentService import roomescape.payment.docs.PaymentAPI @RestController +@RequestMapping("/payments") class PaymentController( private val paymentService: PaymentService ) : PaymentAPI { - @PostMapping("/payments") + @PostMapping override fun confirmPayment( @RequestParam(required = true) reservationId: Long, @Valid @RequestBody request: PaymentConfirmRequest @@ -27,7 +29,7 @@ class PaymentController( return ResponseEntity.ok(CommonApiResponse(response)) } - @PostMapping("/payments/cancel") + @PostMapping("/cancel") override fun cancelPayment( @CurrentUser user: CurrentUserContext, @Valid @RequestBody request: PaymentCancelRequest diff --git a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt index 8902e68a..7f59eb26 100644 --- a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt +++ b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt @@ -45,7 +45,7 @@ interface ReservationAPI { @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) fun cancelReservation( @CurrentUser user: CurrentUserContext, - @PathVariable reservationId: Long, + @PathVariable id: Long, @Valid @RequestBody request: ReservationCancelRequest ): ResponseEntity> diff --git a/src/main/kotlin/roomescape/reservation/web/ReservationController.kt b/src/main/kotlin/roomescape/reservation/web/ReservationController.kt index 81d2dfd1..73c81718 100644 --- a/src/main/kotlin/roomescape/reservation/web/ReservationController.kt +++ b/src/main/kotlin/roomescape/reservation/web/ReservationController.kt @@ -10,11 +10,12 @@ import roomescape.reservation.business.ReservationService import roomescape.reservation.docs.ReservationAPI @RestController +@RequestMapping("/reservations") class ReservationController( private val reservationService: ReservationService ) : ReservationAPI { - @GetMapping("/reservations/popular-themes") + @GetMapping("/popular-themes") override fun findMostReservedThemeIds( @RequestParam count: Int ): ResponseEntity> { @@ -23,7 +24,7 @@ class ReservationController( return ResponseEntity.ok(CommonApiResponse(response)) } - @PostMapping("/reservations/pending") + @PostMapping("/pending") override fun createPendingReservation( @CurrentUser user: CurrentUserContext, @Valid @RequestBody request: PendingReservationCreateRequest @@ -33,7 +34,7 @@ class ReservationController( return ResponseEntity.ok(CommonApiResponse(response)) } - @PostMapping("/reservations/{id}/confirm") + @PostMapping("/{id}/confirm") override fun confirmReservation( @PathVariable("id") id: Long ): ResponseEntity> { @@ -42,18 +43,18 @@ class ReservationController( return ResponseEntity.ok().body(CommonApiResponse()) } - @PostMapping("/reservations/{reservationId}/cancel") + @PostMapping("/{id}/cancel") override fun cancelReservation( @CurrentUser user: CurrentUserContext, - @PathVariable reservationId: Long, + @PathVariable id: Long, @Valid @RequestBody request: ReservationCancelRequest ): ResponseEntity> { - reservationService.cancelReservation(user, reservationId, request) + reservationService.cancelReservation(user, id, request) return ResponseEntity.ok().body(CommonApiResponse()) } - @GetMapping("/reservations/summary") + @GetMapping("/summary") override fun findSummaryByMemberId( @CurrentUser user: CurrentUserContext, ): ResponseEntity> { @@ -62,7 +63,7 @@ class ReservationController( return ResponseEntity.ok(CommonApiResponse(response)) } - @GetMapping("/reservations/{id}/detail") + @GetMapping("/{id}/detail") override fun findDetailById( @PathVariable("id") id: Long ): ResponseEntity> { diff --git a/src/main/kotlin/roomescape/schedule/web/ScheduleController.kt b/src/main/kotlin/roomescape/schedule/web/ScheduleController.kt index 262bd3c4..2d00a870 100644 --- a/src/main/kotlin/roomescape/schedule/web/ScheduleController.kt +++ b/src/main/kotlin/roomescape/schedule/web/ScheduleController.kt @@ -10,10 +10,11 @@ import roomescape.schedule.docs.ScheduleAPI import java.time.LocalDate @RestController +@RequestMapping("/schedules") class ScheduleController( private val scheduleService: ScheduleService ) : ScheduleAPI { - @GetMapping("/schedules/themes") + @GetMapping("/themes") override fun findAvailableThemes( @RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate ): ResponseEntity> { @@ -22,7 +23,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse(response)) } - @GetMapping("/schedules") + @GetMapping override fun findAllTime( @RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate, @RequestParam("themeId") themeId: Long @@ -32,7 +33,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse(response)) } - @GetMapping("/schedules/{id}") + @GetMapping("/{id}") override fun findScheduleDetail( @PathVariable("id") id: Long ): ResponseEntity> { @@ -41,7 +42,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse(response)) } - @PostMapping("/schedules") + @PostMapping override fun createSchedule( @Valid @RequestBody request: ScheduleCreateRequest ): ResponseEntity> { @@ -50,7 +51,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse(response)) } - @PatchMapping("/schedules/{id}/hold") + @PatchMapping("/{id}/hold") override fun holdSchedule( @PathVariable("id") id: Long ): ResponseEntity> { @@ -59,7 +60,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse()) } - @PatchMapping("/schedules/{id}") + @PatchMapping("/{id}") override fun updateSchedule( @PathVariable("id") id: Long, @Valid @RequestBody request: ScheduleUpdateRequest @@ -69,7 +70,7 @@ class ScheduleController( return ResponseEntity.ok(CommonApiResponse(Unit)) } - @DeleteMapping("/schedules/{id}") + @DeleteMapping("/{id}") override fun deleteSchedule( @PathVariable("id") id: Long ): ResponseEntity> { diff --git a/src/main/kotlin/roomescape/theme/web/ThemeController.kt b/src/main/kotlin/roomescape/theme/web/ThemeController.kt index b1b77942..0fde6279 100644 --- a/src/main/kotlin/roomescape/theme/web/ThemeController.kt +++ b/src/main/kotlin/roomescape/theme/web/ThemeController.kt @@ -21,7 +21,7 @@ class ThemeController( return ResponseEntity.ok(CommonApiResponse(response)) } - @GetMapping("/v2/themes") + @GetMapping("/themes") override fun findUserThemes(): ResponseEntity> { val response = themeService.findThemesForReservation() diff --git a/src/main/kotlin/roomescape/user/web/UserController.kt b/src/main/kotlin/roomescape/user/web/UserController.kt index 6e25db39..871dc7d5 100644 --- a/src/main/kotlin/roomescape/user/web/UserController.kt +++ b/src/main/kotlin/roomescape/user/web/UserController.kt @@ -5,6 +5,7 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController import roomescape.auth.web.support.CurrentUser import roomescape.common.dto.CurrentUserContext @@ -13,11 +14,12 @@ import roomescape.user.business.UserService import roomescape.user.docs.UserAPI @RestController +@RequestMapping("/users") class UserController( private val userService: UserService ) : UserAPI { - @PostMapping("/users") + @PostMapping override fun signup( @Valid @RequestBody request: UserCreateRequest ): ResponseEntity> { @@ -26,7 +28,7 @@ class UserController( return ResponseEntity.ok(CommonApiResponse(response)) } - @GetMapping("/users/contact") + @GetMapping("/contact") override fun findContact( @CurrentUser user: CurrentUserContext ): ResponseEntity> {
테마: {reservation.themeName}
신청 일시: {formatDisplayDateTime(reservation.applicationDateTime)}
결제 금액: {reservation.payment.totalAmount.toLocaleString()}원