카페 지도 & 추천 웹사이트 - ECHub
< 웹 페이지 정의 >
ECHub : Ewha Cafe hub (이화여대 주변 카페 지도 웹페이지)
사용자에게 이화여대 인근 카페의 정보를 제공하며, 지도에 각 카페의 위치를 시작적으로 나타냄
- 해시태그 & 키워드 검색
- 카페 정보 제공 ( 주소, 전화번호, 영업상태, 대표메뉴 )
- 사용자 리뷰
- 지도와 연동
요구사항 정의
기능/서비스 정의서 작성
(어떤 서비스를 제공할 것이며 그 서비스를 제공 하기 위해서는 어떤 기능이 필요한지 정의)
데이터베이스 정의
화면 정의서 작성
로그인과 회원가입 기능은 상단에 배치를 하여 클릭시 팝업창으로 뜨도록 해 사용자가 쉽게 접근할 수 있도록 함.
해시태그는 초안 처럼 모든 해시태그를 나열하는 것이 아니라, 필요한 해시태그만 보이고,
전체 해시태그를 볼 수 있는 드롭다운 메뉴를 <Aside>에 추가
또한 카페의 기본정보에서 매장 규모는 주관적일 수 있으니 제외하고 대신
해당 카페가 현재시간을 기준으로 영업중인지에 대해 영업상태 기능을 추가
Map 에서는 마커에 마우스를 갖다대면 팝업창이 뜨고 카페의 간단한 기본 정보를 띄울 수 있게 하였고, Map 의 지도 확대, 축소 기능도 추가하여 사용자가 한눈에 카페를 확인할 수 있도록 기능을 추가하여 화면 정의서를 최종 수정
커밋 규칙
- 메시지 구조 : <type> : <subject>
- 타입은 소문자로
- 제목 첫 글자는 대문자 (영어)
- 제목 끝에 마침표 넣지 않기
- <type>
feat : 새로운 기능에 대한 커밋
fix : 버그 수정에 대한 커밋
build : 빌드 관련 파일 수정에 대한 커밋
chore : 그 외 자잘한 수정에 대한 커밋
docs : 문서 수정에 대한 커밋
style : 코드 스타일 혹은 포맷 등에 관한 커밋
refactor : 코드 리팩토링에 대한 커밋
test : 테스트 코드 수정에 대한 커밋
<화면 레이아웃 작업>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ECC 1팀 카페지도</title>
<link rel="stylesheet" href="EccStyle.css">
</head>
<body>
<header>
<div id="logo">
<h2>1 project</h2>
</div>
<div id="siteName">
<h1>Ewha w. univ cafe Map</h1>
</div>
<div id="loginBtnContainer">
<button onclick="openPopup()">로그인</button>
</div>
<!-- <button type="button">로그인</button>
<button type="button">회원가입</button>
<button onclick="openPopup()">Show Popup</button>
<div id="loginPopup">
<button onclick="closePopup()">Close Popup</button>
</div>
<script>
function openPopup() {
document.getElementById('popup').style.display = 'block';
}
function closePopup() {
document.getElementById('popup').style.display = 'none';
}
</script>-->
</header>
<aside>
<div id="side">
<form action="" method="GET">
<label for="cafe-search"></label>
<input type="search" id="cafe-search" name="ps" placeholder="Search">
</form>
<br>
<select id="hashtags" name="hashtags">
<option value=""># 해시태그</option>
<option value=""># 매장이_넓어요</option>
<option value="학생"># 인스타_핫플</option>
<option value="학생"># 대화하기_좋아요</option>
<option value="학생"># 포토존</option>
<option value="학생"># 친절해요</option>
<option value="학생"># 매장이_청결해요</option>
<option value="학생"># 가성비가_좋아요</option>
<option value="학생"># 카공하기_좋아요</option>
<option value="학생"># 분위기_있어요</option>
<option value="학생"># 특별한_메뉴가_있어요</option>
<option value="학생"># 음료가_맛있어요</option>
<option value="학생"># 디저트가_맛있어요</option>
<option value="학생"># 화장실이_깨끗해요</option>
</select>
<br><br>
<div class="cafe-box">
<div class="cafe-name">카페명</div>
<div class="operating-hours">영업시간 : 09:00-08:00</div>
<div class="operating-state">영업상태</div>
<div class="menu">대표메뉴</div>
</div>
<div class="cafe-box">
<div class="cafe-name">카페명</div>
<div class="operating-hours">영업시간 : 09:00-08:00</div>
<div class="operating-state">영업상태</div>
<div class="menu">대표메뉴</div>
</div>
</aside>
<section>
<div id="map" style="width:600px;height:600px;"></div>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=843de9881c04c74982ab3924b1e63164&libraries=services"></script>
<script>
var mapContainer = document.getElementById('map');
var mapOptions = {
center: new kakao.maps.LatLng(37.559716, 126.945468),
level: 3
};
var map = new kakao.maps.Map(mapContainer, mapOptions); //지도생성
var ps = new kakao.maps.services/Places(); //장소검색 객체생성
</script>
</section>
<div> <!--로그인 버튼-->
<div id="loginPopup">
<h2>로그인</h2>
<form id="loginForm">
<label for="username">아이디:</label>
<input type="text" id="username" name="username" required>
<label for="password">비밀번호:</label>
<input type="password" id="password" name="password" required>
<button type="button" id="loginBtn" onclick="login()">로그인</button>
</form>
<button onclick="closePopup()">닫기</button>
</div>
</div>
<script>
function openPopup() {
document.getElementById('loginPopup').style.display = 'block';
}
function closePopup() {
document.getElementById('loginPopup').style.display = 'none';
}
function login() {
// 로그인 처리 로직 추가
alert('로그인 성공!');
closePopup();
}
</script>
</body>
</html>
3주차때는 레이아웃 작업을 시작했고, 프론트의 작업 영역이 겹치지 않도록 해서 aside 파트, map 파트를 두개로 나눠서 작업을 진행.
먼저 html과 css 로 작업을 레이아웃 작업 진행.
Aside 부분에는 검색창과, 해시태그 드롭다운, 그리고 카페 기본 정보를 card 형식으로 묶어서 작업을 진행.
지도는 카카오 개발자 사이트에서 앱 키를 발급받아서 카카오에서 제공하는 지도 api 를 이용하여 지도 연동 작업을 진행.
Hashtags.jsx 에서는 선택된 해시태그들은 상위 컴포넌트로 전달되어야 하므로,
onSelectHashtag 함수를 수정하여 여러 해시태그를 처리할 수 있도록 변경
SideBar.jsx에서는 Search 컴포넌트의 검색어와 Hashtags 컴포넌트에서 선택된 해시태그들을 상태로 관리.
이 상태들을 기반으로 Card 컴포넌트에 필터링 조건을 전달.
Card.jsx에서는 전달받은 검색어와 해시태그 배열을 사용하여 카페 데이터를 필터링합니다. 검색어는 카페명으로 필터링하고, 선택된 해시태그들이 카페의 해시태그에 모두 포함되어 있는지 확인하여 필터링합니다.
**Card.jsx**에 구현한 것
- selectedTag 상태를 사용하여, 해당 태그를 포함하는 카페만 필터링합니다.
- **selectedTag**는 단일 문자열 값이며, 선택된 해시태그의 값을 나타냅니다.
- useEffect 훅 내에서 모든 카페 데이터를 불러오는 대신, 선택된 해시태그가 변경될 때마다 필터링 로직을 적용합니다.
<사이드바 기능 작업>
사진과 같이 지도 연동을 완료한 모습이고, aside 는 추가적으로 카페의 기본 정보를 추가하였고 , html 을 리액트로 코드를 바꿔서 카페 기본 정보는 card 컴포넌트, 검색창은 search, 해시태그는 hashtag 컴포넌트로 나눠서 main과 sidebar 상위 컴포넌트에서 연결.
그 외의 컴포넌트도 추가하여 기능별로 분리해 작업 .
<사이드바 기능 및 css 구현완료 & 지도 마커 인포>
이후 cardinfo 컴포넌트를 추가로 만들어서 카페 기본 정보 card 컴포넌트에서 리액트 라우팅 기능을 추가해 해당 카페의 상세페이지 cardinfo 로 연결완료.
cardinfo 즉 카페 상세페이지로 들어가게되면 카페명, 카페 사진, 해당 해시태그, 운영시간, 메뉴 등의 자세한 정보가 뜨도록 컴포넌트 제작.
또한 리뷰를 작성하고 저장하는 컴포넌트도 제작.
뒤로가기 버튼을 누르면 cardinfo 에서 main 페이지로 돌아가도록 라우팅 작업도 완료 .
또한 지도도 백엔드와 연동하여 카페 실시간 영업 정보 인포윈도우로 표출.
로그인 회원가입 마이페이지는 구현에 시간이 걸려 최종 데이커 연동에서는 삭제.
<사이드바 백엔드 데이터 연동>
마지막 주차에서는 백엔드와 데이터 연동 작업을 진행.
저희는 axios(액시오스) 라이브러리를 사용하여 백엔드 데이터 연동.
api를 통해 가져온 카페 데이터 리스트를 useState 훅을 사용하여 저장하였고, useeffect 훅을 사용해 컴포넌트가 마운트될때 카페 데이터를 비동기적으로 불러왔고, 데이터를 받아오면 상태 업데이트를 하여 카페 데이터를 맵핑.
또한 검색기능과 , 해시태그 기능을 위해 검색 쿼리와 선택된 해시태그에 따라 카페 데이터를 필터링하는 기능도 추가.
배포 링크: ECC 1팀 카페지도 (ewhacafeuhub.netlify.app)
Ewha Cafe Hub
ewhacafeuhub.netlify.app
https://github.com/Ravende/ECHub
GitHub - Ravende/ECHub
Contribute to Ravende/ECHub development by creating an account on GitHub.
github.com