Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature 18 PR #23

Merged
merged 8 commits into from
Jan 21, 2025
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,7 @@ MigrationBackup/
.ionide/

# End of https://www.toptal.com/developers/gitignore/api/intellij,java,react,node,vs

#custom
db_dev.mv.db
db_dev.trace.db
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Configuration
@RequiredArgsConstructor
public class BaseInitData {
private final CartService cartService;
private final MenuService menuService;
private final OrderService orderService;
private final ResourceLoader resourceLoader; // ResourceLoader 추가

@Value("${upload.path}")
String savePath;

Expand All @@ -45,15 +45,18 @@ public ApplicationRunner baseInitDataApplicationRunner() {
public void makeSampleMenus() throws IOException {
if (menuService.count() > 0) return;

for (int i = 1; i <= 8; i++) {
String fileName = String.format("menu%d.jpg", i );
Path filePath = Paths.get(savePath + fileName);
for (int i = 1; i <= 35; i++) {
int num = ((i-1) % 8) + 1;
String fileName = String.format("menu%d.jpg", num);

// Resource를 사용하여 classpath에서 이미지 파일 읽기
Resource resource = resourceLoader.getResource("classpath:static/images/" + fileName);

MultipartFile multipartFile = new MockMultipartFile(
fileName,
fileName,
"image/jpeg",
Files.readAllBytes(filePath)
resource.getInputStream().readAllBytes()
) {
};

Expand All @@ -65,28 +68,5 @@ public void makeSampleMenus() throws IOException {
.build();
menuService.create(menuRequestDto, multipartFile);
}

// String[] menuTypes = {"커피", "주스", "스무디", "티", "에이드"};
// String[] descriptionsTemplate = {
// "깊고 진한 맛의 ",
// "상큼하고 달콤한 ",
// "시원하고 청량한 ",
// "부드럽고 향긋한 ",
// "달콤쌉싸름한 "
// };
//
// for (int i = 1; i <= 200; i++) {
// // 메뉴 종류를 랜덤하게 선택
// String menuType = menuTypes[i % 5];
// String description = descriptionsTemplate[i % 5];
//
// menuService.create(
// menuType + " " + i + "호", // 예: "커피 1호", "주스 2호" 등
// description + menuType + "입니다.", // 예: "깊고 진한 맛의 커피입니다."
// ((i % 3) + 3) * 1000, // 3000~5000원 범위의 가격
// 100 + (i % 50), // 100~149개 범위의 재고
// "menu" + i + ".jpg" // menu1.jpg, menu2.jpg 등
// );
// }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Collections;
import java.util.List;

@Configuration
@EnableWebSecurity
Expand Down Expand Up @@ -49,7 +49,16 @@ SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.logoutUrl("/logout")
.logoutSuccessUrl("/") // 로그아웃 성공 후 리다이렉트
)
.cors(cors -> cors.configurationSource(corsConfigurationSource()));
.cors(corsCustomizer -> corsCustomizer.configurationSource(request -> {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:3000");
config.setAllowedOriginPatterns(Collections.singletonList("http://localhost:3000"));
config.setAllowedMethods(List.of("GET", "POST", "DELETE", "PATCH", "OPTION", "PUT"));
config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
return config;
}))
;

return http.build();
}
Expand Down Expand Up @@ -78,26 +87,4 @@ public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public CorsFilter corsFilter() {
return new CorsFilter(corsConfigurationSource());
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();

configuration.addAllowedOrigin("http://localhost:3000"); // 허용할 주소 설정
configuration.addAllowedMethod("GET"); // 메서드 허용
configuration.addAllowedMethod("POST"); // 메서드 허용
configuration.addAllowedMethod("PUT"); // 메서드 허용
configuration.addAllowedMethod("DELETE"); // 메서드 허용
configuration.addAllowedHeader("*"); // 헤더 허용
configuration.setAllowCredentials(true); // 자격 증명 허용 설정
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);

return source;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,6 @@ public Page<Menu> getAllMenus(int page, MenuSortType sortType) {
List<Sort.Order> sorts = new ArrayList<>();
sorts.add(sortType.getOrder());

// 전체 데이터 수를 먼저 확인
long totalCount = menuRepository.count();
int totalPages = (int) Math.ceil((double) totalCount / PAGE_SIZE);

// 페이지 번호 보정
if (page < 0) {
page = 0;
} else if (totalCount > 0 && page >= totalPages) {
page = totalPages - 1;
}

Pageable pageable = PageRequest.of(page, PAGE_SIZE, Sort.by(sorts));
return menuRepository.findAll(pageable);
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"ajv-keywords": "^5.1.0",
"axios": "^1.7.9",
"cra-template": "1.2.0",
"date-fns": "^4.1.0",
"lucide-react": "^0.473.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
Expand Down
51 changes: 29 additions & 22 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import OrderPage from './screens/OrderScreen';
import EmailInput from './screens/EmailInput';
import OrderList from './screens/OrderList';
import OrderDetail from './screens/OrderDetail';
import OrderModify from './screens/OrderModify';
import MainMenuScreen from './screens/MainMenuScreen';
import OrderListScreen from "./screens/OrderListScreen";
import NoticeScreen from './screens/NoticeScreen';
import EventsScreen from './screens/EventsScreen';

import './App.css';
import LoginPage from "./components/login";
import AddMenuPage from "./screens/addMenu";
Expand All @@ -15,27 +18,31 @@ import AdminOrderList from './screens/AdminOrderList';
import Login from './components/login';

function App() {
return (
<Router>
<Routes>
<Route path="/order" element={<OrderPage />} />
<Route path="/order/email" element={<EmailInput />} />
<Route path="/order/list" element={<OrderList />} />
<Route path="/order/detail/:id" element={<OrderDetail />} />
<Route path="/order/modify/:id" element={<OrderModify />} />
{/* /login 경로에 LoginPage 컴포넌트를 렌더링 */}
<Route path="/login" element={<LoginPage />} />
{/* 기본 경로 설정 */}
{/* <Route path="/" element={<h1>Welcome to the Home Page</h1>} /> */}
<Route path="/admin" element={<Login/>} />
<Route path="/admin/addMenu" element={<AddMenuPage/>}/>
<Route path="/admin/order/:id" element={<AdminOrderDetail />} />
<Route path="/admin/orders" element={<AdminOrderList />} />
<Route path="/" element={<MainMenuScreen />} />
<Route path="/order_list" element={<OrderListScreen />} />
</Routes>
</Router>
);
return (
<Router>
<Routes>
<Route path="/" element={<MainMenuScreen/>}/>
<Route path="/order_list" element={<OrderListScreen/>}/>
<Route path="/notice" element={<NoticeScreen/>}/>
<Route path="/events" element={<EventsScreen/>}/>
<Route path="/order" element={<OrderPage/>}/>
<Route path="/order/email" element={<EmailInput/>}/>
<Route path="/order/list" element={<OrderList/>}/>
<Route path="/order/detail/:id" element={<OrderDetail/>}/>
<Route path="/order/modify/:id" element={<OrderModify/>}/>
{/* /login 경로에 LoginPage 컴포넌트를 렌더링 */}
<Route path="/login" element={<LoginPage/>}/>
{/* 기본 경로 설정 */}
{/* <Route path="/" element={<h1>Welcome to the Home Page</h1>} /> */}
<Route path="/admin" element={<Login/>}/>
<Route path="/admin/addMenu" element={<AddMenuPage/>}/>
<Route path="/admin/order/:id" element={<AdminOrderDetail/>}/>
<Route path="/admin/orders" element={<AdminOrderList/>}/>
<Route path="/" element={<MainMenuScreen/>}/>
<Route path="/order_list" element={<OrderListScreen/>}/>
</Routes>
</Router>
);
}

export default App;
28 changes: 24 additions & 4 deletions frontend/src/DL/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const addMenu = async (menuData,image) => {
try {
const formData = new FormData();
formData.append("menu", JSON.stringify(menuData)); // JSON으로 변환 후 추가
formData.append("image", image);
formData.append("image", image);

const response = await api.post(`/admin/menus`, formData, {
headers: {
Expand Down Expand Up @@ -101,9 +101,29 @@ export const cancelOrder = (email, id) => api.delete(`/order/${email}/${id}`);


// 메뉴 전체 조회
// export const getAllMenu = () => api.get(`/menus`);
export const getAllMenu = (page = 0) => {
return api.get(`/menus?page=${page}`);
// DL/api.js
export const getAllMenu = (page = 0, sort = 'recent') => {
let sortParam;
switch(sort) {
case 'viewsDesc':
sortParam = 'VIEWS_DESC';
break;
case 'recent':
sortParam = 'RECENT';
break;
case 'oldest':
sortParam = 'OLDEST';
break;
case 'priceDesc':
sortParam = 'PRICE_DESC';
break;
case 'priceAsc':
sortParam = 'PRICE_ASC';
break;
default:
sortParam = 'RECENT';
}
return api.get(`/menus?page=${page}&sortType=${sortParam}`);
};

// 특정 메뉴 조회
Expand Down
21 changes: 7 additions & 14 deletions frontend/src/components/Navbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,19 @@ const Navbar = () => {
주문 조회
</Link>
</li>
<li className="ml-8 relative">
<Link
to="/order"
className="text-white no-underline"
onClick={() => {
const cartItems = localStorage.getItem("cartItems");
console.log("장바구니 데이터 확인:", JSON.parse(cartItems || "[]"));
}}
>
장바구니
</Link>
<li className="ml-8 relative">
<Link to="/order" className="text-white no-underline">
장바구니
</Link>
</li>
<li
className="ml-8 relative"
onMouseEnter={() => setShowDropdown(true)}
onMouseLeave={() => setShowDropdown(false)}
>
<Link to="/admin" className="text-white no-underline">
관리자 페이지
</Link>
<span className="text-white cursor-pointer">
관리자 페이지
</span>
{showDropdown && (
<ul className="absolute top-full right-0 bg-[#333] py-2 min-w-[150px] rounded shadow-md list-none">
<li className="m-0 p-2 hover:bg-[#444]">
Expand Down
Loading