diff --git a/client/public/data/drinks.json b/client/public/data/drinks.json new file mode 100644 index 0000000..7a73493 --- /dev/null +++ b/client/public/data/drinks.json @@ -0,0 +1,705 @@ +[ +{ + "drinkName": "치키피치", + "preferenceLevel":4.6, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/CheekyPeach.jpg" +},{ + "drinkName": "P.S 화이트 스파클링", + "preferenceLevel":5, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/PS_WhiteSparkling.jpg" +},{ + "drinkName": "멜론서리", + "preferenceLevel":5, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/MellonSeoli.jpg" +},{ + "drinkName": "오롯이 복숭아", + "preferenceLevel":9, + "area": "세종특별자치시", + "type": "과실주", + "postImage": "/images/fruitWine/OlosiPeache.jpg" +},{ + "drinkName": "너브내스파클링사과와인", + "preferenceLevel":8.5, + "area": "강원도", + "type": "과실주", + "postImage": "/images/fruitWine/NervneSparklingAppleWine.jpg" +},{ + "drinkName": "로제사이더 오미한잔", + "preferenceLevel":4.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/RoseCiderOmihanjan.jpg" +},{ + "drinkName": "세인트하우스 살구와인", + "preferenceLevel":12, + "area": "충청남도 ", + "type": "과실주", + "postImage": "/images/fruitWine/SaintHouseApricotWine.jpg" +},{ + "drinkName": "머루와인", + "preferenceLevel":12, + "area": "전라북도", + "type": "과실주", + "postImage": "/images/fruitWine/MeruWine.jpg" +},{ + "drinkName": "그랑꼬또 청수", + "preferenceLevel":12, + "area": "경기도", + "type": "과실주", + "postImage": "/images/fruitWine/GradcoteauFreshWater.jpg" +},{ + "drinkName": "베베마루 설레임 로제 스위트와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/RoséSweetWine.jpg" +},{ + "drinkName": "산막와이너리, 화몽", + "preferenceLevel":13, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/Hwamong.jpg" +},{ + "drinkName": "산막와이너리, 비원퓨어", + "preferenceLevel":13, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/BiwonPure.jpg" +},{ + "drinkName": "크라테 화이트스위트", + "preferenceLevel":11.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/KratteWhiteSweet.jpg" +},{ + "drinkName": "김천대학교 자두사랑 자두와인", + "preferenceLevel":12, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/GimcheonUniversityPlumWine.jpg" +},{ + "drinkName": "미르아토 로제와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/MiratoRoseWine.jpg" +},{ + "drinkName": "산머루와인 달콤한 스위트", + "preferenceLevel":10.5, + "area": "경상남도", + "type": "과실주", + "postImage": "/images/fruitWine/SweetSweet.jpg" +},{ + "drinkName": "2016년산 하미앙 드라이", + "preferenceLevel":12, + "area": "경상남도", + "type": "과실주", + "postImage": "/images/fruitWine/HamianDry.jpg" +},{ + "drinkName": "고도리 로제와인", + "preferenceLevel":12, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/GodoriRoseWine.jpg" +},{ + "drinkName": "소계리 595 스위트 레드와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/559SweetRedWine.jpg" +},{ + "drinkName": "끌로너와 스위트와인", + "preferenceLevel":12, + "area": "강원도", + "type": "과실주", + "postImage": "/images/fruitWine/ClonerAndSweetWine.jpg" +},{ + "drinkName": "고도리 샤인머스캣 화이트와인", + "preferenceLevel":10.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/ShineMuscatWhiteWine.jpg" +},{ + "drinkName": "포엠 화이트와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/PoemWhiteWine.jpg" +},{ + "drinkName": "산막와이너리, 초련", + "preferenceLevel":20, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/Choryun.jpg" +},{ + "drinkName": "코이버펑크, 머스캣 베일리 에이 2017", + "preferenceLevel":12.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/MuscatBaileyA.jpg" +},{ + "drinkName": "산막와이너리, 아로퓨어", + "preferenceLevel":13, + "area": "충청북도 ", + "type": "과실주", + "postImage": "/images/fruitWine/Aropure.jpg" +},{ + "drinkName": "뱅꼬레 더감", + "preferenceLevel":12, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/BancoreDeogam.jpg" +},{ + "drinkName": "샤토미소 아이스와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/SyatomisoIceWine.jpg" +},{ + "drinkName": "산머루와인 깊은맛 드라이", + "preferenceLevel":12, + "area": "경라남도", + "type": "과실주", + "postImage": "/images/fruitWine/MeruWineDeepDry.jpg" +},{ + "drinkName": "너브내 로제 스파클링", + "preferenceLevel":12, + "area": "강원도", + "type": "과실주", + "postImage": "/images/fruitWine/NeubnaeRoséSparkling.jpg" +},{ + "drinkName": "달 1614 스위트와인", + "preferenceLevel":12, + "area": "전라북도", + "type": "과실주", + "postImage": "/images/fruitWine/Moon1614SweetWine.jpg" +},{ + "drinkName": "샤토미소 웨딩 자두와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/WeddingPlumWine.jpg" +},{ + "drinkName": "코이버펑크, 카베르네 소비뇽 2019", + "preferenceLevel":12.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/CabernetSauvignon.jpg" +},{ + "drinkName": "포엠 로제와인", + "preferenceLevel":12, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/PoemRoséWine.jpg" +},{ + "drinkName": "2016년산 하미앙 스위트", + "preferenceLevel":10.5, + "area": "경라남도", + "type": "과실주", + "postImage": "/images/fruitWine/HamiangSweet.jpg" +},{ + "drinkName": "베리와인1168 스위트와인", + "preferenceLevel":13, + "area": "충청북도", + "type": "과실주", + "postImage": "/images/fruitWine/1168SweetWine.jpg" +},{ + "drinkName": "오크와인", + "preferenceLevel":12, + "area": "경라남도", + "type": "과실주", + "postImage": "/images/fruitWine/OakWine.jpg" +},{ + "drinkName": "너브내 스파클링 화이트", + "preferenceLevel":12, + "area": "강원도", + "type": "과실주", + "postImage": "/images/fruitWine/SparklingWhite.jpg" +},{ + "drinkName": "소백산(샤토소백) 스위트 레드와인", + "preferenceLevel":12, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/SobakSweetRedWine.jpg" +},{ + "drinkName": "크라테 미디엄드라이", + "preferenceLevel":11.5, + "area": "경상북도", + "type": "과실주", + "postImage": "/images/fruitWine/MediumDry.jpg" +},{ + "drinkName": "2018년산 하미앙 오크와인", + "preferenceLevel":12, + "area": "경라남도", + "type": "과실주", + "postImage": "/images/fruitWine/HamianOakWine.jpg" +}, + + {"drinkName":"소풍", + "preferenceLevel":5.5, + "area":"경상남도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju1.jpg" + }, + + {"drinkName":"가와지탁주", + "preferenceLevel":7.5, + "area":"경기도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju2.jpg" + }, + + {"drinkName":"연희유자", + "preferenceLevel":10, + "area":"서울특별시", + "type":"탁주", + "postImage":"/images/cheongtakju/takju3.jpg" + }, + + {"drinkName":"팔팔막걸리", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju4.jpg" + }, + + {"drinkName":"설레 7도", + "preferenceLevel":7, + "area":"경상남도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju5.jpg" + }, + + {"drinkName":"보은주", + "preferenceLevel":10, + "area":"충청북도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju6.jpg" + }, + + {"drinkName":"바텐더의막걸리", + "preferenceLevel":14, + "area":"서울특별시", + "type":"탁주", + "postImage":"/images/cheongtakju/takju7.jpg" + }, + + {"drinkName":"김유정역", + "preferenceLevel":6, + "area":"강원도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju8.jpg" + }, + + {"drinkName":"님 그리다", + "preferenceLevel":6, + "area":"경상남도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju9.jpg" + }, + + {"drinkName":"일엽편주", + "preferenceLevel":12, + "area":"경상북도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju10.jpg" + }, + + {"drinkName":"입장탁주", + "preferenceLevel":7, + "area":"충청남도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju11.jpg" + }, + + {"drinkName":"메들리손막걸리", + "preferenceLevel":8, + "area":"경기도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju12.jpg" + }, + + {"drinkName":"자작막걸리", + "preferenceLevel":12, + "area":"강원도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju13.jpg" + }, + + {"drinkName":"냥이탁주 화이트", + "preferenceLevel":10.5, + "area":"경기도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju14.jpg" + }, + + {"drinkName":"대대포9", + "preferenceLevel":9, + "area":"전라남도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju15.jpg" + }, + + {"drinkName":"아임프리6.0", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postImage":"/images/cheongtakju/takju16.jpg" + }, + + {"drinkName":"냥이탁주 9도", + "preferenceLevel":9, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju17.jpg" + }, + + {"drinkName":"골목막걸리 프리미엄 12", + "preferenceLevel":12, + "area":"충청남도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju18.jpg" + }, + + {"drinkName":"과천미주", + "preferenceLevel":9, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju19.jpg" + }, + + {"drinkName":"복순도가 슈퍼드라이", + "preferenceLevel":6.5, + "area":"울산광역시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju20.jpg" + }, + + {"drinkName":"옹근달 본막걸리", + "preferenceLevel":15, + "area":"인천광역시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju21.jpg" + }, + + {"drinkName":"산정호수 동정춘막걸리", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju22.jpg" + }, + + {"drinkName":"단홍", + "preferenceLevel":13.5, + "area":"서울특별시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju23.jpg" + }, + + {"drinkName":"오산막걸리", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju24.jpg" + }, + + {"drinkName":"일곱쌀", + "preferenceLevel":7, + "area":"서울특별시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju25.jpg" + }, + + {"drinkName":"탁112클래식", + "preferenceLevel":12, + "area":"인천광역시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju26.jpg" + }, + + {"drinkName":"생 옥수수 동동주", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju27.jpg" + }, + + {"drinkName":"담향 대대포 블루", + "preferenceLevel":6, + "area":"전라남도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju28.jpg" + }, + + {"drinkName":"도갓집 막걸리", + "preferenceLevel":6, + "area":"전라남도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju29.jpg" + }, + + {"drinkName":"한영석 하향주", + "preferenceLevel":13.8, + "area":"전라북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju30.jpg" + }, + + {"drinkName":"이화주(술샘)", + "preferenceLevel":8, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju31.jpg" + }, + + {"drinkName":"관악산생막걸리", + "preferenceLevel":6, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju32.jpg" + }, + + {"drinkName":"하얀까마귀", + "preferenceLevel":8, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju33.jpg" + }, + + {"drinkName":"정감생막걸리", + "preferenceLevel":6, + "area":"경상남도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju34.jpg" + }, + + {"drinkName":"눈내린여름밤", + "preferenceLevel":12, + "area":"서울특별시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju35.jpg" + }, + + {"drinkName":"한강의설레임", + "preferenceLevel":11, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju36.jpg" + }, + + {"drinkName":"시향가 미니캔막걸리", + "preferenceLevel":8, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju37.jpg" + }, + + {"drinkName":"강냉이 막걸리", + "preferenceLevel":6, + "area":"충청북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju38.jpg" + }, + + {"drinkName":"말이야 막걸리야", + "preferenceLevel":6, + "area":"전라남도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju39.jpg" + }, + + {"drinkName":"연꽃담은술", + "preferenceLevel":8, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju40.jpg" + }, + + {"drinkName":"냥이탁주 fresh", + "preferenceLevel":5, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju41.jpg" + }, + + {"drinkName":"주홍춘", + "preferenceLevel":10, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju42.jpg" + }, + + {"drinkName":"양조학당 뜰", + "preferenceLevel":12, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju43.jpg" + }, + + {"drinkName":"금풍양조", + "preferenceLevel":6.9, + "area":"인천광역시", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju44.jpg" + }, + + {"drinkName":"영일만친구 막걸리", + "preferenceLevel":6, + "area":"경상북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju45.jpg" + }, + + {"drinkName":"선희주", + "preferenceLevel":12, + "area":"충청북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju46.jpg" + }, + + {"drinkName":"연오랑탁주", + "preferenceLevel":12, + "area":"경상북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju47.jpg" + }, + + {"drinkName":"청혼 화이트", + "preferenceLevel":13, + "area":"경기도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju48.jpg" + }, + + {"drinkName":"오희 스파클링 막걸리", + "preferenceLevel":8.5, + "area":"경상북도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju49.jpg" + }, + + {"drinkName":"곤드레생막걸리", + "preferenceLevel":6, + "area":"강원도", + "type":"탁주", + "postIamge":"/images/cheongtakju/takju50.jpg" + }, + + {"drinkName":"세종대왕어주 약주", + "preferenceLevel":15, + "area":"충청북도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju1.jpg" + }, + + {"drinkName":"주교주", + "preferenceLevel":16, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju2.jpg" + }, + + {"drinkName":"일엽편주", + "preferenceLevel":15, + "area":"경상북도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju3.jpg" + }, + + {"drinkName":"모월 연", + "preferenceLevel":13, + "area":"강원도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju4.jpg" + }, + + {"drinkName":"메들리아카시아", + "preferenceLevel":7, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju5.jpg" + }, + + {"drinkName":"경산대추약주 추", + "preferenceLevel":16, + "area":"경상북도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju6.jpg" + }, + + {"drinkName":"보리수헤는밤", + "preferenceLevel":8, + "area":"충청남도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju7.jpg" + }, + + {"drinkName":"지란지교 약주", + "preferenceLevel":17, + "area":"전라북도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju8.jpg" + }, + + {"drinkName":"모월 청", + "preferenceLevel":16, + "area":"강원도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju9.jpg" + }, + + {"drinkName":"담골드", + "preferenceLevel":12, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju10.jpg" + }, + + {"drinkName":"청혼 블루", + "preferenceLevel":15, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju11.jpg" + }, + + {"drinkName":"복단지", + "preferenceLevel":14, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju12.jpg" + }, + + {"drinkName":"서설", + "preferenceLevel":13, + "area":"경기도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju13.jpg" + }, + + {"drinkName":"호산춘", + "preferenceLevel":18, + "area":"경상북도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju14.jpg" + }, + + {"drinkName":"일지춘", + "preferenceLevel":15, + "area":"강원도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju15.jpg" + }, + + {"drinkName":"과하주 온", + "preferenceLevel":18.5, + "area":"강원도", + "type":"청주", + "postIamge":"/images/cheongtakju/cheongju16.jpg" + } +] \ No newline at end of file diff --git a/client/public/images/search-icon.jpg b/client/public/images/search-icon.jpg new file mode 100644 index 0000000..885905a Binary files /dev/null and b/client/public/images/search-icon.jpg differ diff --git a/client/src/App.js b/client/src/App.js index 6320009..ced85c5 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -5,6 +5,8 @@ import FruitWinePage from "./pages/FruitWinePage"; import SignInPage from "./pages/SignInPage"; import Mypage from "./pages/mypage"; import SignUpPage from "./pages/SignUpPage"; +import SearchPage from "./components/search/search"; +import ResultsPage from "./pages/searchresult"; import { BrowserRouter, Router, Route, Routes, Link } from "react-router-dom"; function App() { @@ -18,6 +20,8 @@ function App() { } /> } /> } /> + } /> + } /> diff --git a/client/src/api/mypageapi.js b/client/src/api/mypageapi.js new file mode 100644 index 0000000..5229174 --- /dev/null +++ b/client/src/api/mypageapi.js @@ -0,0 +1,92 @@ +import axios from "axios"; + +// Axios 인스턴스 생성 +const apiClient = axios.create({ + baseURL: process.env.REACT_APP_API_ROUTE, // .env에서 설정한 baseURL 사용 +}); + +// 1. 내 정보 확인 +const getUserInfo = async () => { + try { + const response = await apiClient.get("/api/mypage/info"); + if (response.data.code === "200") { + return response.data.data; // 내 정보 반환 + } else { + throw new Error(response.data.message || "내 정보 조회 실패"); + } + } catch (error) { + console.error("내 정보 조회 중 에러 발생:", error.message); + throw error; + } +}; + +// 2. 북마크 확인 +const getUserBookmarks = async () => { + try { + const response = await apiClient.get("/api/mypage/bookmarks"); + if (response.data.code === "200") { + return response.data.data; // 북마크 반환 + } else { + throw new Error(response.data.message || "북마크 조회 실패"); + } + } catch (error) { + console.error("북마크 조회 중 에러 발생:", error.message); + throw error; + } +}; + +// 3. 이름 수정 +const updateUserInfo = async (name) => { + try { + const response = await apiClient.post("/api/mypage/updateInfo", { + name, + }); + if (response.data.code === "200") { + return response.data.data; // 수정된 정보 반환 + } else { + throw new Error(response.data.message || "이름 수정 실패"); + } + } catch (error) { + console.error("이름 수정 중 에러 발생:", error.message); + throw error; + } +}; + +// 4. 선호 도수 설정 +const updateUserPreference = async (preference) => { + try { + const response = await apiClient.post("/api/mypage/updatePreference", { + preference, + }); + if (response.data.code === "200") { + return response.data.data; // 선호도수 설정 결과 반환 + } else { + throw new Error(response.data.message || "선호도수 설정 실패"); + } + } catch (error) { + console.error("선호도수 설정 중 에러 발생:", error.message); + throw error; + } +}; + +// 5. 프로필 사진 수정 +const updateUserProfileImage = async (formData) => { + try { + const response = await apiClient.post("/api/mypage/updateProfileImage", formData, { + headers: { + "Content-Type": "multipart/form-data", // 이미지 업로드를 위한 헤더 설정 + }, + }); + if (response.data.code === "200") { + return response.data.data; // 프로필 사진 수정 결과 반환 + } else { + throw new Error(response.data.message || "프로필 사진 수정 실패"); + } + } catch (error) { + console.error("프로필 사진 수정 중 에러 발생:", error.message); + throw error; + } +}; + +// API 함수들을 export +export { getUserInfo, getUserBookmarks, updateUserInfo, updateUserPreference, updateUserProfileImage }; diff --git a/client/src/api/searchapi.js b/client/src/api/searchapi.js new file mode 100644 index 0000000..21c4782 --- /dev/null +++ b/client/src/api/searchapi.js @@ -0,0 +1,25 @@ +import axios from "axios"; + +// Axios 인스턴스 생성 +const apiClient = axios.create({ + baseURL: process.env.REACT_APP_API_ROUTE, // .env에 설정된 baseURL +}); + +const searchapi = async (drinkName) => { + try { + const response = await apiClient.get(`/api/post/search?drinkName=${drinkName}`); + + // 성공 응답 처리 + if (response.data.code === "200") { + console.log(response) + return response.data.data.searchResult.content; // 검색 결과 반환 + } else { + throw new Error(response.data.message || "전통주 검색 실패"); + } + } catch (error) { + console.error("API 호출 중 에러 발생:", error.message); + throw error; // 에러를 상위 호출로 전달 + } +}; + +export default searchapi; diff --git a/client/src/components/search/search.css b/client/src/components/search/search.css index c00f0d5..2552c58 100644 --- a/client/src/components/search/search.css +++ b/client/src/components/search/search.css @@ -1,67 +1,29 @@ -/* searchpage.css */ - /* 페이지 전체 레이아웃 */ .search-container { - display: flex; - flex-direction: column; - align-items: center; - padding: 20px; - max-width: 600px; - margin: 0 auto; - } - - /* 검색창 스타일 */ - .search-input { - width: 100%; - padding: 10px; - font-size: 16px; - border: 1px solid #ddd; - border-radius: 5px; - margin-bottom: 15px; - } - - /* 검색 버튼 스타일 */ - .search-button { - padding: 10px 20px; - font-size: 16px; - background-color: #4CAF50; - color: white; - border: none; - border-radius: 5px; - cursor: pointer; - margin-bottom: 20px; - transition: background-color 0.3s ease; - } - - .search-button:hover { - background-color: #45a049; - } - - /* 결과 리스트 스타일 */ - .results-list { - list-style: none; - padding: 0; - width: 100%; - } - - .result-item { - padding: 15px; - margin-bottom: 10px; - border: 1px solid #ddd; - border-radius: 5px; - background-color: #f9f9f9; - font-size: 18px; - } - - /* 텍스트 정렬 */ - .result-item h3 { - margin: 0; - font-size: 20px; - color: #333; - } - - .result-item p { - margin: 5px 0 0; - color: #666; - } - \ No newline at end of file + display: flex; + align-items: center; + justify-content: center; /* 수평 중앙 정렬 */ + background-color: #d6d1c9; + border-radius: 20px; + padding: 10px 15px; + max-width: 600px; + margin-top: 90px; + margin-left: auto; + margin-right: auto; /* 좌우 중앙 정렬 */ +} + +.search-input { + flex: 1; + border: none; + outline: none; + background-color: transparent; + font-size: 16px; + color: #333; +} + +/* 검색 아이콘 스타일 */ +.search-icon { + width: 20px; + height: 20px; + cursor: pointer; +} diff --git a/client/src/components/search/search.js b/client/src/components/search/search.js index 8561a04..4b6214a 100644 --- a/client/src/components/search/search.js +++ b/client/src/components/search/search.js @@ -1,34 +1,45 @@ -import React, { useState, useEffect } from "react"; -import axios from "axios"; +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import "./search.css"; function SearchPage() { const [searchQuery, setSearchQuery] = useState(""); - const [data, setData] = useState([]); - - // 데이터 가져오기 - useEffect(() => { - axios.get("https://example.com/api/drinks") // 실제 API URL로 대체 - .then(response => setData(response.data)) - .catch(error => console.error("Error fetching data:", error)); - }, []); + const [error, setError] = useState(null); + const navigate = useNavigate(); - const filteredData = data.filter(item => - item.name.toLowerCase().includes(searchQuery.toLowerCase()) - ); + const handleSearch = () => { + if (searchQuery.trim() === "") { + setError("검색어를 입력해주세요."); // 검색어가 비어있으면 에러 처리 + return; + } + setError(null); + // 검색 결과 페이지로 이동, 쿼리 파라미터에 검색어 전달 + navigate(`/results?query=${encodeURIComponent(searchQuery)}`); + }; + + const handleKeyPress = (e) => { + if (e.key === "Enter") { + handleSearch(); + } + }; return ( -
+
setSearchQuery(e.target.value)} + onKeyDown={handleKeyPress} + className="search-input" + /> + search icon -
    - {filteredData.map(item => ( -
  • {item.name}
  • - ))} -
+ {error &&

{error}

}
); } diff --git a/client/src/pages/CheongtakjuPage.js b/client/src/pages/CheongtakjuPage.js index 4f52eff..0eb2118 100644 --- a/client/src/pages/CheongtakjuPage.js +++ b/client/src/pages/CheongtakjuPage.js @@ -3,12 +3,13 @@ import AlcoholList from "../components/alcoholList/AlcoholList"; import SearchBar from "../components/navSearchBar/SearchBar"; import Footer from "../components/common/Footer"; import cheongTakjuListApi from "../api/cheongTakjuListApi"; +import SearchPage from "../components/search/search"; const CheongtakjuPage = () => { return (
- +
diff --git a/client/src/pages/FruitWinePage.js b/client/src/pages/FruitWinePage.js index 4289129..33643e2 100644 --- a/client/src/pages/FruitWinePage.js +++ b/client/src/pages/FruitWinePage.js @@ -3,12 +3,13 @@ import SearchBar from "../components/navSearchBar/SearchBar"; import AlcoholList from "../components/alcoholList/AlcoholList"; import fruitWineListApi from "../api/fruitWineListApi"; import Footer from "../components/common/Footer"; +import SearchPage from "../components/search/search"; const FruitWinePage = () => { return (
- +
diff --git a/client/src/pages/mypage.css b/client/src/pages/mypage.css index 7ae2648..958ffa7 100644 --- a/client/src/pages/mypage.css +++ b/client/src/pages/mypage.css @@ -101,6 +101,11 @@ outline: none; /* 포커스 시 테두리도 제거 */ background-color: #f6f6f6; text-align: right; + font-size: 16px; /* 텍스트 입력 크기 */ +} + +.percentage { + font-size: 16px !important; /* 입력 텍스트와 동일한 크기 */ } .preference-score span:first-child { @@ -114,7 +119,13 @@ /* 담은 술 섹션 */ .favorite-alcohol h4 { + margin-bottom: 10px; +} + +.add-btn{ + border: none; margin-bottom: 30px; + cursor: pointer; } .alcohol-grid { @@ -137,11 +148,12 @@ color: #888; } -.alcohol-item.add-more { +/* .alcohol-item.add-more { background-color: #d0d0d0; font-weight: bold; cursor: pointer; } +*/ .alcohol-item.empty { background-color: #f0f0f0; @@ -165,3 +177,9 @@ .profile-info h2 { margin: 0; /* 기본 마진 제거 */ } + +.nickname-error { + color: red; + font-size: 12px; + margin-top: 5px; +} \ No newline at end of file diff --git a/client/src/pages/mypage.js b/client/src/pages/mypage.js index 28f3417..05e17b1 100644 --- a/client/src/pages/mypage.js +++ b/client/src/pages/mypage.js @@ -1,29 +1,76 @@ -import React, { useState, useRef } from "react"; +import React, { useState, useRef, useEffect } from "react"; import "./mypage.css"; // CSS 파일을 불러옵니다 import Header from "../components/common/Header"; +import { useNavigate } from "react-router-dom"; +import { getUserInfo, getUserBookmarks, updateUserInfo, updateUserPreference, updateUserProfileImage } from "../api/mypageapi"; // API 함수 import function Mypage() { const [isEditing, setIsEditing] = useState(false); // 편집 모드 상태 const [nickname, setNickname] = useState("Nickname"); // 닉네임 상태 + const [nicknameError, setNicknameError] = useState(""); // 닉네임 오류 메시지 상태 const [preferenceScore, setPreferenceScore] = useState(""); // 선호도수 상태 const [profileImage, setProfileImage] = useState("default-avatar.png"); // 프로필 이미지 상태 - const fileInputRef = useRef(null); // 파일 입력을 위한 ref 생성 + const navigate = useNavigate(); + + // 페이지 로딩 시 사용자 정보 가져오기 + useEffect(() => { + const fetchUserInfo = async () => { + try { + const userInfo = await getUserInfo(); + setNickname(userInfo.nickname); + setPreferenceScore(userInfo.preference || ""); + setProfileImage(userInfo.profileImage || "default-avatar.png"); + } catch (error) { + console.error("사용자 정보 조회 중 오류 발생:", error.message); + } + }; + + fetchUserInfo(); + }, []); const handleEditClick = () => { setIsEditing(true); // 편집 모드로 변경 + setNicknameError(""); // 편집 모드 들어갈 때 오류 메시지 초기화 }; - const handleSaveClick = () => { + const handleSaveClick = async () => { setIsEditing(false); // 편집 모드 해제 - }; - const handlePreferenceChange = (e) => { - setPreferenceScore(e.target.value); // 선호도수 상태 업데이트 + try { + // 닉네임 수정 + if (nickname !== "") { + await updateUserInfo(nickname); + } + // 선호 도수 설정 + if (preferenceScore !== "") { + await updateUserPreference(preferenceScore); + } + // 프로필 사진 수정 + if (profileImage !== "default-avatar.png") { + await updateUserProfileImage(profileImage); + } + } catch (error) { + console.error("수정 중 오류 발생:", error.message); + } }; const handleNicknameChange = (e) => { - setNickname(e.target.value); // 닉네임 상태 업데이트 + const newNickname = e.target.value; + if (newNickname.length <= 10) { + setNickname(newNickname); // 닉네임 상태 업데이트 + setNicknameError(""); // 오류 메시지 초기화 + } else { + setNicknameError("글자수가 초과되었습니다"); // 글자수가 초과된 경우 오류 메시지 설정 + } + }; + + const handlePreferenceChange = (e) => { + const value = e.target.value; + + if (/^\d*$/.test(value)) { + setPreferenceScore(value); // 숫자만 입력된 경우 상태 업데이트 + } }; const handleImageChange = (e) => { @@ -45,6 +92,14 @@ function Mypage() { fileInputRef.current.click(); // 파일 입력 클릭 }; + const handleNicknameFocus = () => { + setNickname(""); // 입력란 클릭 시 빈 칸으로 설정 + }; + + const handleAddAlcoholClick = () => { + navigate("/cheongtakju"); + }; + return (
@@ -58,8 +113,10 @@ function Mypage() { + {nicknameError &&

{nicknameError}

}
+

담은 술

-
-
-
-
-
- {/* 두 번째 줄 */} -
-
-
-
+
-
+ +
+
+
+
+
+
+ {/* 두 번째 줄 */} +
+
+
+
diff --git a/client/src/pages/searchresult.css b/client/src/pages/searchresult.css new file mode 100644 index 0000000..d980110 --- /dev/null +++ b/client/src/pages/searchresult.css @@ -0,0 +1,89 @@ +.AlcoholList { + display: flex; + flex-direction: column; + justify-content: center; + margin: 5%; + align-items: center; +} + +.alcohol-container { + display: grid; + grid-template-columns: repeat(5, 1fr); /* 5열 */ + gap: 3%; /* 아이템 간격 */ + width: 75%; +} + +.alcohol-item-wrap { + display: flex; + flex-direction: column; /* 이미지와 텍스트 수직 정렬 */ + align-items: center; + text-align: center; + padding: 10px; + text-decoration: none; +} + +.alcohol-image { + width: 100%; + height: auto; + aspect-ratio: 5 / 6; + object-fit: contain; + border-radius: 8px; + background-color: rgb(239, 239, 239); +} + +.alcohol-name { + margin-top: 8px; + font-size: 13px; + font-weight: bold; + color: rgb(78, 75, 69); + + min-width: 100px; + max-width: 100px; /* 부모 요소 너비 제한 */ +} + +.alcohol-image:hover, +.alcohol-name:hover { + cursor: pointer; +} + +.link-img-tag, +.link-name-tag { + text-decoration: none; + color: inherit; + display: inline-block; +} + +/* 페이지네이션 CSS */ +.pagination { + display: flex; + justify-content: center; + align-items: center; + margin-top: 3%; +} + +.pagination button { + margin: 0 5px; + padding: 8px 12px; + font-size: 14px; + cursor: pointer; + border: none; + background-color: rgba(255, 255, 255, 0); + border-radius: 4px; + transition: background-color 0.3s; +} + +.pagination button:hover { + background-color: rgba(75, 72, 68, 0.445); + color: white; +} + +.pagination button:disabled { + cursor: not-allowed; + opacity: 0.5; +} + +.pagination .active-page { + font-weight: bold; + background-color: rgba(255, 255, 255, 0); + color: rgb(0, 0, 0); +} diff --git a/client/src/pages/searchresult.js b/client/src/pages/searchresult.js new file mode 100644 index 0000000..aebae7d --- /dev/null +++ b/client/src/pages/searchresult.js @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from "react"; +import { useLocation } from "react-router-dom"; +import searchapi from "../api/searchapi"; +import Header from "../components/common/Header"; +import SearchPage from "../components/search/search"; +import Footer from "../components/common/Footer"; +import "./searchresult.css"; + + +function ResultsPage() { + const location = useLocation(); + const queryParams = new URLSearchParams(location.search); + const searchQuery = queryParams.get("query"); + + const [filteredData, setFilteredData] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchData = async () => { + try { + setLoading(true); + setError(null); + const result = await searchapi(searchQuery); + setFilteredData(result || []); + } catch (err) { + setError("검색 중 문제가 발생했습니다."); + } finally { + setLoading(false); + } + }; + + if (searchQuery) { + fetchData(); + } + }, [searchQuery]); + + return ( +
+
+ +
+

검색 결과: {searchQuery}

+ {loading &&

검색 중...

} + {error &&

{error}

} +
    + {filteredData.length > 0 ? ( + filteredData.map((item, index) => ( +
  • +
    {item.drinkName}
    +
    {item.preferenceLevel}
    +
    {item.area}
    +
    {item.type}
    + {item.drinkName} +
  • + )) + ) : ( +

    검색 결과가 없습니다.

    + )} +
+
+
+ ); +} + +export default ResultsPage;