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
17 changes: 5 additions & 12 deletions back/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,12 @@ const app = express();
// origin: 'http://localhost:3000',
// credentials: true
// }));
// app.use(cors({
// origin: ['http://localhost:3000', 'https://st-available-room.netlify.app'],
// methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
// allowedHeaders: ['Content-Type', 'Authorization'],
// credentials: true
// }));
app.use(cors({
origin: ['http://localhost:3000','https://st-available-room.netlify.app'], // ✅ 프론트 배포 URL 정확히 명시
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true // ✅ 쿠키/헤더 인증 정보 허용
}));

origin: 'http://localhost:3000', // 프론트 주소
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
}));
app.use(express.json());

app.use('/api/users', userRoutes);
Expand Down
8 changes: 8 additions & 0 deletions front/src/api/axios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import axios from 'axios';

const instance = axios.create({
baseURL: 'http://localhost:8080/api', // 변경 시 여기만 수정
withCredentials: true
});

export default instance;
9 changes: 0 additions & 9 deletions front/src/api/instance.js

This file was deleted.

14 changes: 7 additions & 7 deletions front/src/pages/HotspotPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Footer from '../components/Footer';
import HotspotCard from '../components/HotspotCard';
import RoomSelectModal from '../components/RoomSelectModal';
import { useNavigate } from 'react-router-dom';
import api from '../api/instance';
import axios from 'axios';
import '../styles/HotspotPage.css';

const CATEGORIES = [
Expand All @@ -31,16 +31,16 @@ const HotspotPage = () => {
try {
let response;
if (category === 'Auditorium Size / Large Hall') {
response = await api.get('/analytics/popular-buildings/by-large-group');
response = await axios.get('http://localhost:8080/api/analytics/popular-buildings/by-large-group');
} else if (category === 'Study Friendly') {
response = await api.get('/analytics/popular-buildings/by-purpose?purpose=Study');
response = await axios.get('http://localhost:8080/api/analytics/popular-buildings/by-purpose?purpose=Study');
} else if (category === 'Meeting & Presentation / Collab Zones') {
response = await api.get('/analytics/popular-buildings/by-purpose?purpose=Meeting');
response = await axios.get('http://localhost:8080/api/analytics/popular-buildings/by-purpose?purpose=Meeting');
}

const hotspotData = Array.isArray(response.data) ? response.data : [response.data];

const allBuildingsRes = await api.get('/buildings');
const allBuildingsRes = await axios.get('http://localhost:8080/api/buildings');
const allBuildings = allBuildingsRes.data.buildings;

const matched = hotspotData.map((item, i) => {
Expand Down Expand Up @@ -87,7 +87,7 @@ const HotspotPage = () => {

const handleReserve = async (building) => {
try {
const res = await api.get(`/buildings/rooms?buildingNo=${building.id}`);
const res = await axios.get(`http://localhost:8080/api/buildings/rooms?buildingNo=${building.id}`);
const availableRooms = res.data.rooms.map(room => ({
room: `Room ${room}`,
time: '8:00 - 17:50',
Expand Down Expand Up @@ -169,4 +169,4 @@ const HotspotPage = () => {
);
};

export default HotspotPage;
export default HotspotPage;
16 changes: 8 additions & 8 deletions front/src/pages/LoginPage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import api from '../api/instance';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';
import Header from '../components/Header';
import Footer from '../components/Footer';
Expand All @@ -17,10 +17,10 @@ const LoginPage = () => {

const handleLogin = async () => {
try {
const res = await api.post('/users/login', form);
const res = await axios.post('http://localhost:8080/api/users/login', form);
localStorage.setItem('token', res.data.token);
localStorage.setItem('user', JSON.stringify(res.data.user));
navigate('/'); // 메인 페이지로 이동
navigate('/'); // 메인 페이지로 이동
} catch (err) {
console.warn('⚠️ 백엔드 로그인 실패 - mock 처리로 우회');

Expand All @@ -39,8 +39,8 @@ const LoginPage = () => {
};

const handleSubmit = (e) => {
e.preventDefault(); // 새로고침 방지
handleLogin(); // 로그인 실행
e.preventDefault(); // 새로고침 방지
handleLogin(); // 로그인 실행
};

return (
Expand All @@ -56,7 +56,7 @@ const LoginPage = () => {
</h1>
</div>

{/*form으로 감싸고 onSubmit 적용 */}
{/*form으로 감싸고 onSubmit 적용 */}
<form className="login-box" onSubmit={handleSubmit}>
<h2 className="login-label">Log in</h2>

Expand Down Expand Up @@ -85,7 +85,7 @@ const LoginPage = () => {
</div>

<div className="login-buttons">
<button type="submit">Log in</button> {/* 기본 로그인 */}
<button type="submit">Log in</button> {/* 기본 로그인 버튼 */}
<button type="button" onClick={() => navigate('/signup')}>Sign in</button>
</div>
</form>
Expand All @@ -95,4 +95,4 @@ const LoginPage = () => {
);
};

export default LoginPage;
export default LoginPage;
2 changes: 1 addition & 1 deletion front/src/pages/MainPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ const MainPage = () => {
);
};

export default MainPage;
export default MainPage;
16 changes: 8 additions & 8 deletions front/src/pages/MyReservationPage.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react';
import api from '../api/instance';
import axios from 'axios';
import Header from '../components/Header';
import Footer from '../components/Footer';
import Modal from '../components/Modal';
import '../styles/MyReservationPage.css';

// 이미지 경로 매핑
// 이미지 경로 매핑
const getBuildingImage = (number) => {
try {
return require(`../assets/buildings img/${number}.png`);
Expand All @@ -21,10 +21,10 @@ const MyReservationPage = () => {
const [modalStep, setModalStep] = useState('confirm');
const [selectedReservation, setSelectedReservation] = useState(null);

// 건물 리스트 받아오기
// 🧭 건물 리스트 받아오기
const fetchBuildings = async () => {
try {
const res = await api.get('/buildings');
const res = await axios.get('http://localhost:8080/api/buildings');
setBuildings(res.data.buildings || []);
} catch (err) {
console.warn('⚠️ 건물 정보 fetch 실패, fallback mock 사용');
Expand All @@ -35,11 +35,11 @@ const MyReservationPage = () => {
}
};

// 예약 정보 불러오기
// 🗓️ 예약 정보 불러오기
const fetchReservations = async () => {
try {
const token = localStorage.getItem('token');
const res = await api.get('/reservations/my', {
const res = await axios.get('http://localhost:8080/api/reservations/my', {
headers: { Authorization: `Bearer ${token}` }
});
setReservations(res.data);
Expand Down Expand Up @@ -85,7 +85,7 @@ const MyReservationPage = () => {
const confirmCancel = async () => {
try {
const token = localStorage.getItem('token');
await api.delete(`/reservations/${selectedReservation._id}`, {
await axios.delete(`http://localhost:8080/api/reservations/${selectedReservation._id}`, {
headers: { Authorization: `Bearer ${token}` }
});
setReservations(reservations.filter(r => r._id !== selectedReservation._id));
Expand Down Expand Up @@ -163,4 +163,4 @@ const MyReservationPage = () => {
);
};

export default MyReservationPage;
export default MyReservationPage;
20 changes: 10 additions & 10 deletions front/src/pages/ProfilePage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import api from '../api/instance';
import axios from 'axios';
import Header from '../components/Header';
import Footer from '../components/Footer';
import BuildingCard from '../components/BuildingCard';
Expand Down Expand Up @@ -37,7 +37,7 @@ const MOCK_BUILDINGS = [
},
];

// mock 유저 미리 설정
// mock 유저 미리 설정
const MOCK_USER = {
name: '홍길동',
studentNumber: '202312345',
Expand All @@ -58,23 +58,23 @@ const ProfilePage = () => {
const token = localStorage.getItem('token');
if (!token) throw new Error('No token');

const res = await api.get('/users/me', {
const res = await axios.get('http://localhost:8080/api/users/me', {
headers: { Authorization: `Bearer ${token}` }
});

const userData = res.data.user;
setUser(userData);

// 서버에서 전체 건물 목록 받아오기
const buildingsRes = await api.get('/api/buildings');
// 서버에서 전체 건물 목록 받아오기
const buildingsRes = await axios.get('http://localhost:8080/api/buildings');
const buildingData = buildingsRes.data.buildings;

// building.name과 userData.favorites 비교 후 매칭
// building.name과 userData.favorites를 비교해 매칭
const matched = await Promise.all(
buildingData
.filter(b => userData.favorites.includes(b.buildingName))
.map(async (b) => {
const roomRes = await api.get(`/buildings/rooms?buildingNo=${b.buildingNo}`);
const roomRes = await axios.get(`http://localhost:8080/api/buildings/rooms?buildingNo=${b.buildingNo}`);
const availableRooms = roomRes.data.rooms || [];

return {
Expand Down Expand Up @@ -123,13 +123,13 @@ const ProfilePage = () => {

if (token) {
if (isAlreadyFavorite) {
await api.delete('/users/favorites', {
await axios.delete('http://localhost:8080/api/users/favorites', {
headers: { Authorization: `Bearer ${token}` },
data: { building: buildingName },
});
updatedFavorites = user.favorites.filter((n) => n !== buildingName);
} else {
await api.post('/users/favorites', { building: buildingName }, {
await axios.post('http://localhost:8080/api/users/favorites', { building: buildingName }, {
headers: { Authorization: `Bearer ${token}` },
});
updatedFavorites = [...user.favorites, buildingName];
Expand Down Expand Up @@ -199,4 +199,4 @@ const ProfilePage = () => {
);
};

export default ProfilePage;
export default ProfilePage;
16 changes: 8 additions & 8 deletions front/src/pages/ReservePage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import api from '../api/instance';
import axios from 'axios';
import Header from '../components/Header';
import Footer from '../components/Footer';
import BuildingCard from '../components/BuildingCard';
Expand Down Expand Up @@ -54,8 +54,8 @@ const ReservePage = () => {
try {
const token = localStorage.getItem('token');
const [buildingsRes, userRes] = await Promise.all([
api.get('/buildings'),
api.get('/users/me', {
axios.get('http://localhost:8080/api/buildings'),
axios.get('http://localhost:8080/api/users/me', {
headers: { Authorization: `Bearer ${token}` }
}),
]);
Expand All @@ -65,7 +65,7 @@ const ReservePage = () => {

const buildingList = await Promise.all(
buildingData.map(async (b) => {
const roomRes = await api.get(`/buildings/rooms?buildingNo=${b.buildingNo}`);
const roomRes = await axios.get(`http://localhost:8080/api/buildings/rooms?buildingNo=${b.buildingNo}`);
const availableRooms = roomRes.data.rooms || [];
return {
id: String(b.buildingNo),
Expand Down Expand Up @@ -99,15 +99,15 @@ const ReservePage = () => {

try {
if (isAlreadyFavorite) {
await api.delete('/users/favorites', {
await axios.delete('http://localhost:8080/api/users/favorites', {
headers: { Authorization: `Bearer ${token}` },
data: { building: buildingName },
});
const updated = favoriteIds.filter(name => name !== buildingName);
setFavoriteIds(updated);
localStorage.setItem('favorites', JSON.stringify(updated));
} else {
await api.post('/users/favorites', { building: buildingName }, {
await axios.post('http://localhost:8080/api/users/favorites', { building: buildingName }, {
headers: { Authorization: `Bearer ${token}` },
});
const updated = [...favoriteIds, buildingName];
Expand All @@ -133,7 +133,7 @@ const ReservePage = () => {

const filteredBuildings = buildings
.filter(b => b.name.toLowerCase().includes(searchTerm.toLowerCase()))
.filter(b => b.availableRooms.length > 0); // 없는 건물 제외
.filter(b => b.availableRooms.length > 0); // ✅ 방이 없는 건물 제외

const favoriteBuildings = filteredBuildings.filter(b => favoriteIds.includes(b.name));
const nonFavoriteBuildings = filteredBuildings.filter(b => !favoriteIds.includes(b.name));
Expand Down Expand Up @@ -195,4 +195,4 @@ const ReservePage = () => {
);
};

export default ReservePage;
export default ReservePage;
12 changes: 6 additions & 6 deletions front/src/pages/RoomDetailPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import api from '../api/instance';
import axios from 'axios';
import Header from '../components/Header';
import Footer from '../components/Footer';
import Modal from '../components/Modal';
Expand Down Expand Up @@ -84,7 +84,7 @@ const RoomDetailPage = () => {

const fetchAvailability = async () => {
try {
const res = await api.get('/timetable/availability', {
const res = await axios.get('http://localhost:8080/api/timetable/availability', {
params: { building, room, week: formatDate(startOfWeek) }
});
applyGridFromAvailability(res.data.availability);
Expand Down Expand Up @@ -148,8 +148,8 @@ const RoomDetailPage = () => {
const endTime = startTimes[r + selected.length] || '18:00';

try {
await api.post(
'/reservations',
await axios.post(
'http://localhost:8080/api/reservations',
{
building,
room,
Expand All @@ -168,7 +168,7 @@ const RoomDetailPage = () => {
} catch (err) {
setShowConfirm(false);
alert(err.response?.status === 409
? 'Some of the selected periods have already been reserved or were booked by you today—cannot reserve again. '
? 'Some of the selected periods have already been reserved'
: 'Reservation failed. Try again.');
}
};
Expand Down Expand Up @@ -278,4 +278,4 @@ const RoomDetailPage = () => {
);
};

export default RoomDetailPage;
export default RoomDetailPage;
Loading