- 회원가입
- 로그인
- 로그아웃
- 아이디/비밀번호 찾기
- 프로필 변경
- 손님/사장 권한 변경
- 사용자의 현재 위치(lon, lat)를 중심으로 0.005 단위 반경 내의 식당 조회
- 검색한 주소를 중심으로 0.005 단위 반경 내의 식당 조회
- 별점별 지도 마크 아이콘 분류
- 가게 등록, 조회, 수정, 삭제
- 가게 검색 및 조회
- 즐겨찾기
- 사용자 위치 주변 별점순, 리뷰순 TOP3 식당 조회
- 예약 조회, 수락, 거부
- 예약, 예약 조회
- 휴대폰 인증
- 리뷰에 대한 댓글 등록, 조회, 수정, 삭제
- 리뷰 등록, 조회, 수정, 삭제
- 사장님에게 1:1 문의
- 채팅 수신 시 알림 발생
- 현재 위치의 날씨 정보 표시
- 날씨에 따른 메뉴 추천, 가게 추천
- 추천된 메뉴를 기반으로 한 랜덤 돌림판
- 게시물 등록, 조회, 수정, 삭제
- 댓글 등록, 조회, 수정, 삭제
// 주소 입력 값 가져오기
var inputAddress = document.querySelector('#searchAddress').value;
// 정보 창 초기화
var infowindow = new kakao.maps.InfoWindow({zIndex:1});
// 사용자의 위치 설정
var locPosition = new kakao.maps.LatLng(myY, myX);
// 지도 컨테이너 및 옵션 설정
var mapContainer = document.getElementById('map'),
mapOption = {
center: new kakao.maps.LatLng(33.450701, 126.570667),
level: 3
};
// 지도 생성
var map = new kakao.maps.Map(mapContainer, mapOption);
// 사용자 정의 오버레이 초기화
var overlay = new kakao.maps.CustomOverlay({
yAnchor: 1.2,
zIndex:2
});
// 식당 리스트를 순회하며 마커와 오버레이 생성
resArr.forEach(function(element) {
var imageSrc,
imageSize = new kakao.maps.Size(45, 50),
imageOption = {offset: new kakao.maps.Point(21, 47)};
// 평점에 따른 마커 이미지 결정
if (element.averageStar > 4.5) imageSrc = '/image/mark/red.png';
else if (element.averageStar > 4) imageSrc = '/image/mark/yellow.png';
else if (element.averageStar > 3) imageSrc = '/image/mark/green.png';
else imageSrc = '/image/mark/blue.png';
// 마커 이미지 설정 및 마커 생성
var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption)
var marker = new kakao.maps.Marker({
map: map,
position: new kakao.maps.LatLng(element.y, element.x),
clickable: true,
image: markerImage
});
// 각 식당의 오버레이 정보 및 스타일 설정
var tmpOverlay = new kakao.maps.CustomOverlay({
content: '<div class="badge text-dark" style="background:white; border:1px solid tan;">'+element.name+'</div>',
position: marker.getPosition(),
map: map,
yAnchor: 2.6
});
// 오버레이 내용과 스타일 설정
// 마커 클릭 이벤트 리스너 추가
kakao.maps.event.addListener(marker, 'click', function() {
overlay.setContent(content);
overlay.setPosition(marker.getPosition());
overlay.setMap(map);
tmpOverlay.setMap(null);
});
});
// 사용자의 위치 주변 맛집 표시
if (inputAddress == 'aroundMe') {
displayMarker_myLocation(locPosition);
} else if (inputAddress !== 'searchKeyword') {
// 사용자가 입력한 주소에 마커 및 정보창 표시
var marker = new kakao.maps.Marker({
map: map,
position: locPosition
});
// 정보창 내용 설정 및 표시
var infowindow = new kakao.maps.InfoWindow({
content: '<div style="width:150px;text-align:center;padding:6px 0;">' + inputAddress + '</div>'
});
infowindow.open(map, marker);
}
// 지도 중심을 사용자의 위치로 설정
map.setCenter(locPosition);
// 사용자의 현재 위치에 마커 표시 함수
function displayMarker_myLocation(locPosition) {
// 사용자 위치 마커 이미지 설정 및 생성
var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imageOption)
var marker = new kakao.maps.Marker({
map: map,
position: locPosition,
image: markerImage
});
}
<!-- 예약 날짜 선택 -->
<div class="my-3">
<label for="datepicker" class="form-label border-bottom">예약 날짜</label>
<div class="input-group">
<button type="button" id="datepicker" class="버튼 btn">날짜 선택</button>
<input type="text" id="selectedDate" class="form-control" readonly>
</div>
</div>
<!-- 예약 시간 선택 -->
<div class="mb-3">
<label for="timepicker" class="form-label border-bottom">예약시간</label>
<div class="input-group">
<button type="button" id="timepicker" class="버튼 btn">시간 선택</button>
<input type="text" id="selectedTime" class="form-control" readonly>
</div>
</div>
<!-- 예약 인원 수 조절 -->
<div class="mb-3">
<label for="inputCount" class="form-label border-bottom">인원 수</label>
<div class="btn-group border" style="width:50%;">
<button type="button" class="버튼 btn" onclick="decreaseCount()">-</button>
<input type="button" class="btn" id="inputCount" value="1" style="border:1px solid black;">
<button type="button" class="버튼 btn" onclick="increaseCount()">+</button>
</div>
</div>
<!-- 전화번호 인증 -->
<div class="mb-3">
<button type="button" class="버튼 btn btn-sm me-2" data-bs-toggle="modal" data-bs-target="#exampleModal" id="verBtn">
전화번호 인증
</button>
<div class="d-flex justify-content-between align-items-start" style="width:70%;">
<input type="text" class="form-control" id="verKey" placeholder="인증번호 입력">
<input type="button" class="버튼 btn" value="확인" onclick="checkVerificationKey()">
</div>
</div>
<!-- 예약 버튼 -->
<div class="d-flex justify-content-end align-items-center">
<input id="reserveBtn" type="button" class="버튼 btn" value="예약">
</div>
// 예약 버튼 클릭 이벤트 처리
const reserve = document.getElementById("reserveBtn");
reserve.addEventListener('click', function() {
if (document.getElementById('selectedDate').value == "")
alert("예약 날짜를 선택해주세요.");
else if (document.getElementById('selectedTime').value == "")
alert("예약 시간을 선택해주세요.");
else if (document.getElementById('inputCount').value == "")
alert("인원 수를 선택해주세요.");
else if (!document.getElementById('verResult').classList.contains('valid-feedback'))
alert("인증이 완료되지 않았습니다.");
else {
// 여기에 예약 처리 로직 추가
}
});
// 예약 날짜 및 시간 선택기 초기화
document.addEventListener("DOMContentLoaded", function () {
// 날짜 및 시간 선택기 설정 코드
});
// 인원 수 조절 함수
function increaseCount() { /*...*/ }
function decreaseCount() { /*...*/ }
// 전화번호 인증 처리 함수
function checkVerificationKey() { /*...*/ }
@PreAuthorize("isAuthenticated()")
@PostMapping("/{id}")
public String reserve(@PathVariable("id") Integer id, Principal principal, @RequestParam("date") LocalDate date,
@RequestParam("time") LocalTime time, @RequestParam("count") int count) {
SiteUser user = this.siteUserService.getUser(principal.getName());
Restaurant restaurant = this.restaurantService.getRestaurant(id);
this.reservationService.reserveRestaurant(user, restaurant, date, time, count);
return String.format("redirect:/restaurant/detail/%s", id);
}
<!-- 채팅 목록 -->
<div class="chatList">
<h3 class="border-bottom pb-2">채팅 목록</h3>
<div th:if="${roomList.isEmpty()}" class="p-5 text-center">
<h3 style="color:gray;">채팅 내역 없음</h3>
</div>
<ul class="list-group" th:if="${!roomList.isEmpty()}">
<li class="list-group-item d-flex justify-content-between align-items-center"
th:each="chat : ${roomList}" th:classappend="${chat.room == room} ? 'activeRoom'">
<!-- 채팅방 링크와 삭제 버튼 -->
</li>
</ul>
</div>
<!-- 채팅 내용 영역 -->
<div class="chatContent">
<div class="chatRoom card my-3">
<!-- 채팅 상대방 헤더 -->
<div class="card-header p-3 d-flex justify-content-between" style="background:#9FB3CD">
<h4 th:text="|${restaurant.name} >|" th:if="${user.loginId == customer.loginId}"></h4>
<h4 th:text="|${target.name} >|" th:if="${user.loginId == owner.loginId}"></h4>
<!-- 아이콘 버튼들 -->
</div>
<!-- 실제 채팅 메시지가 표시되는 부분 -->
<div class="chatContainer card-body">
<div th:each="chat : ${chatList}">
<!-- 각 채팅 메시지 내용 -->
</div>
<div id="chatMessages" class="my-2"></div>
</div>
<!-- 채팅 메시지 입력 폼 -->
<form id="messageForm">
<!-- 입력 필드와 전송 버튼 -->
</form>
</div>
</div>
$(function () {
// 새로운 채팅 메시지가 도착했을 때 알림 표시를 업데이트하는 로직
$('.confirm').each(function(index, element) {
if ($(element).attr('data-value') == 'false') {
$(element).show();
}
});
// WebSocket 연결을 설정하는 함수
var stompClient = null;
function connect() {
var socket = new SockJS('/ws'); // SockJS를 사용한 WebSocket 연결
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
// 특정 채팅방 구독
stompClient.subscribe('/topic/' + $("#room").val(), function (chatMessage) {
showMessage(JSON.parse(chatMessage.body)); // 메시지 수신 시 처리
});
// 알림 구독
stompClient.subscribe('/topic/room', function (chatMessage) {
showAlarm(JSON.parse(chatMessage.body)); // 알림 수신 시 처리
});
});
}
// 새로운 알림을 표시하는 함수
function showAlarm(data) {
if (data.room != $('#room').val()) {
var elementId = '#alarm_' + data.room;
$(elementId).show();
}
}
// WebSocket 연결을 해제하는 함수
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
}
// 채팅 메시지를 전송하는 함수
function sendMessage() {
var target = $("#target").val();
var writer = $("#user").val();
var messageInput = $("#messageInput").val();
var room = $("#room").val();
var restaurantId = $("#restaurantId").val();
// 서버에 메시지 전송
stompClient.send("/app/chat", {}, JSON.stringify({
content: messageInput,
writer: writer,
target: target,
room: room,
restaurant: restaurantId,
type: 'chat'
}));
$("#messageInput").val("");
}
// 새로운 채팅 메시지를 화면에 표시하는 함수
function showMessage(message) {
var userImage = [[${user.image}]]; // 사용자 이미지
var targetImage = [[${target.image}]]; // 대상 사용자 이미지
// 메시지를 화면에 추가하는 로직
}
// 메시지 전송 폼 이벤트 핸들러
$("#messageForm").submit(function (e) {
e.preventDefault();
sendMessage();
});
// 페이지 로드 시 WebSocket 연결
connect();
// 페이지를 벗어날 때 알림 확인 처리
$(window).on('beforeunload', function(e) {
// 알림 확인 요청을 서버로 전송
});
});