어제 못한 유저 페이지 프론트 구현
main은 css 는 완료 했고 js도 버그를 제외한 기능 완료
info, cart, order, review의 html과 css 적용 완료
남은건 java script의 적용과 버그 수정과 더미 db 파일 적용
숫자 증감이나 별 클릭시 표시
info.html - 숫자 증감과 체크 사용자 버튼 구현
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title></title>
<link href="/css/style.css" rel="stylesheet">
<link href="/css/user/info.css" rel="stylesheet" type="text/css">
<script src="/js/user/info.js" type="text/javascript" defer></script>
</head>
<body>
<div class="innerBox">
<header></header>
<div class="container">
<form action="/user/info" method="post" class="info-form">
<div class="menu-image">
<img src="/images/sample.png" alt="음식 이미지" class="menu-img">
</div>
<div class="info">
<div class="title">짜파게티</div>
<div class="contents">맛있는 짜파게티 김치 미포함</div>
<div class="price">300원</div>
</div>
<div class="option">
<div class="title">
<div class="text">매운맛</div>
<div class="select">필수</div>
</div>
<div class="contents">
<label class="select">
<input type="radio" name="spiciness" class="check" value="spicy">
<label></label>
<span class="content">맵게 해주세요</span>
<span class="price">+3000원</span>
</label>
<label class="select">
<input type="radio" name="spiciness" class="check" value="not-spicy">
<label></label>
<span class="content">안맵게 해주세요</span>
<span class="price">+4000원</span>
</label>
</div>
</div>
<div class="option">
<div class="title">
<div class="text">토핑</div>
<div class="select">선택</div>
</div>
<div class="contents">
<label class="select">
<input type="checkbox" class="check">
<label></label>
<span class="content">치즈</span>
<span class="price">1000원</span>
</label>
<label class="select">
<input type="checkbox" class="check">
<label></label>
<span class="content">감자</span>
<span class="price">1000원</span>
</label>
</div>
</div>
<div class="count">
<div class="inner">
<div class="text">수량</div>
<div class="num">
<input type="button" class="minus" value="-">
<div class="text">1</div>
<input type="button" class="plus" value="+">
</div>
</div>
<input type="button" class="submit button" value="300원 담기" onclick="infosubmit(form)">
</div>
</form>
</div>
<footer></footer>
</div>
</body>
</html>
info.css
@charset "UTF-8";
.container form{
width: 100%;
margin: 0;
padding: 0;
margin-bottom: var(--fixedBtn-height);
}
/* 메인 사진 */
.container .menu-image{
width: 100%;
height: 250px;
overflow: hidden;
}
.container .menu-image img{
width: 100%;
height: auto;
object-fit: cover;
object-position: center top;
}
/* 음식 설명 */
.container .info{
padding: var(--padding);
margin: 0;
display: flex;
flex-direction: column;
position: relative;
}
.container .info .title{
font-size: var(--font-big);
font-weight: bold;
margin-bottom: 10px;
color: var(--black);
}
.container .info .contents{
font-size: var(--font-small);
color: var(--light-gray);
}
.container .info .price{
font-size: var(--font-middle);
color: var(--black);
text-align: right;
}
/* 옵션 사용자 버튼 */
.check{
display: none;
}
/* 라벨의 가상 요소를 이용해 체크박스 스타일링 */
.select .check[type="checkbox"] + label::before {
content: '\f0c8'; /* Font Awesome의 square 아이콘 */
font-family: 'Font Awesome 5 Free';
font-weight: 500;
color: var(--light-gray);
font-size: var(--font-middle);
margin-right: var(--padding);
}
/* 체크된 체크박스의 스타일 */
.select .check[type="checkbox"]:checked + label::before {
content: '\f14a'; /* Font Awesome의 check-square 아이콘 */
color: var(--orange);
}
/* 라벨의 가상 요소를 이용해 라디오 버튼 스타일링 */
.select .check[type="radio"] + label::before {
content: '\f111'; /* Font Awesome의 circle 아이콘 */
font-family: 'Font Awesome 5 Free';
font-weight: 500;
color: var(--light-gray);
font-size: var(--font-middle);
margin-right: var(--padding);
}
/* 체크된 라디오 버튼의 스타일 */
.select .check[type="radio"]:checked + label::before {
content: '\f058'; /* Font Awesome의 check-circle 아이콘 */
color: var(--orange);
}
/* 옵션 */
.container .option{
margin: 0;
display: flex;
flex-direction: column;
}
/* 옵션 이름 부분 */
.container .option .title{
padding: var(--padding);
width: 100%;
display: flex;
justify-content: space-between;
background-color: var(--extra-light-gray);
color: var(--light-gray);
}
.container .option .title .text{
padding: 10px;
color: var(--gray);
}
.container .option .title .select{
padding: 10px;
background-color: var(--light-gray);
color: var(--gray);
}
/* 옵션 내용 선택 부분 */
.container .option .contents{
padding: var(--padding);
width: 100%;
display: flex;
flex-direction: column;
}
.container .option .contents .select{
display: flex;
padding: 10px 0;
}
.container .option .contents .select .content{
flex: 1;
}
/* 수량 */
.container .count {
position: fixed;
left: 50%;
bottom: 0;
margin: 0;
/* 자신의 너비의 반만큼 왼쪽으로 이동하여 정확히 중앙에 위치하도록 조정 */
transform: translateX(-50%);
width: var(--innerBox-width);
background-color: white;
z-index: 1; /* 필요에 따라 조정 */
padding: var(--padding);
}
.container .count .inner{
display: flex;
justify-content: space-between; /* 내부 요소를 양 끝으로 정렬 */
width: 100%; /* 부모 컨테이너의 전체 너비 사용 */
padding: 0 20px; /* 좌우 패딩 추가로 내부 요소들 사이 간격 조정 */
margin-bottom: 10px;
}
.container .count .inner .text {
font-size: var(--font-content); /* 필요에 따라 조정 */
color: var(--black);
display: flex;
justify-content: center;
align-items: center;
}
.container .count .inner .num {
padding: 5px;
display: flex;
justify-content: right;
border: 2px solid var(--light-gray);
}
.container .count .inner .num .minus,
.container .count .inner .num .plus{
padding: 0 15px;
display: flex;
justify-content: center;
align-items: center;
border: 0;
background-color: var(--white);
font-size: var(--font-content); /* 버튼 내 텍스트 크기 */
cursor: pointer; /* 마우스 커서 변경 */
}
.container .count .inner .num .text{
width: 40px;
display: flex;
justify-content: center;
align-items: center;
font-size: var(--font-content); /* 필요에 따라 조정 */
}
/* 버튼 */
.container .count .submit{
width: calc(100% - 20px); /* 패딩 고려하여 너비 조정 */
}
info.js
/* form 하기 전에 체크 */
function infosubmit(form) {
form.submit();
}
// 수량 증감 액션
const minus = document.querySelector('.minus');
const plus = document.querySelector('.plus');
const text = document.querySelector('.count .inner .num .text');
// 수량 증가 함수
function plusNum() {
let num = parseInt(text.innerHTML);
if (num < 100) {
num += 1;
text.innerHTML = num;
}
}
// 수량 감소 함수
function minusNum() {
let num = parseInt(text.innerHTML);
if (num > 1) {
num -= 1;
text.innerHTML = num;
}
}
// 마이너스 버튼 눌렀을 때
minus.addEventListener('mousedown', e => {
minusNum(); // 수량 감소
});
// 플러스 버튼 눌렀을 때
plus.addEventListener('mousedown', e => {
plusNum(); // 수량 증가
});
cart.html - 숫자 증감을 개별적으로 구현 메뉴추가 메인 링
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>장바구니</title>
<link href="/css/style.css" rel="stylesheet">
<link href="/css/user/cart.css" rel="stylesheet" type="text/css">
<script src="/js/user/cart.js" type="text/javascript" defer></script>
</head>
<body>
<div class="innerBox">
<header></header>
<div class="container">
<form action="/user/order" method="post">
<div class="restaurant-name">더조은 식당</div>
<div class="orders">
<div class="menu">
<div class="text">
<div class="title">짜파게티</div>
<div class="menu-price">가격 : 5,000원</div>
<div class="option">옵션 : 안맵게 해주세요(-3000원)</div>
<div class="total-price">3000원</div>
</div>
</div>
<div class="etc">
<div class="image">
<img src="/images/sample.png" alt="음식 이미지" class="img">
</div>
<div class="num">
<input type="button" class="minus" value="-">
<div class="text">2</div>
<input type="button" class="plus" value="+">
</div>
</div>
</div>
<div class="orders">
<div class="menu">
<div class="text">
<div class="title">짜파게티2</div>
<div class="menu-price">가격 : 4,000원</div>
<div class="option">옵션 : 맵게 해주세요(3000원)</div>
<div class="total-price">10000원</div>
</div>
</div>
<div class="etc">
<div class="image">
<img src="/images/sample.png" alt="음식 이미지" class="img">
</div>
<div class="num">
<input type="button" class="minus" value="-">
<div class="text">3</div>
<input type="button" class="plus" value="+">
</div>
</div>
</div>
<div class="menu-plus">
+메뉴추가
</div>
<div class="request">
<label for="contents" class="title">요청사항</label>
<textarea class="contents" id="contents" name="contents" placeholder="내용을 입력하세요" rows="4"></textarea>
<input type="button" class="submit button" onclick="cartsubmit(form)" value="3000원 주문하기">
</div>
</form>
</div>
<footer></footer>
</div>
</body>
</html>
cart.css
@charset "UTF-8";
.container form{
margin: 0;
width: 100%;
padding: 0;
}
form>div{
margin: 0;
padding: 20px;
}
/* 식당 이름 */
.container form .restaurant-name{
font-size: var(--font-middle);
font-weight: bold;
border-top: 1px solid var(--light-gray);
}
/* 주문 리스트 */
.container form .orders{
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
border-top: 1px solid var(--light-gray);
}
.container form .orders .menu{}
.container form .orders .menu .text{
}
.container form .orders .menu .text .title,
.container form .orders .menu .text .total-price{
font-size: var(--font-content);
color: var(--black);
padding-bottom: 10px;
}
.container form .orders .menu .text .menu-price,
.container form .orders .menu .text .option
{
font-size: var(--font-small);
color: var(--gray);
padding-bottom: 10px;
}
.container form .orders .menu .text .total-price{
padding-top: 10px;
}
.container form .orders .etc{
display: flex;
flex-direction: column;
justify-content: space-between;
}
.container form .orders .etc .image{
margin-left: auto; /* 오른쪽 정렬 */
width: 90px;
height: 90px;
overflow: hidden;
}
.container form .orders .etc .image img{
width: 100%;
height: auto;
}
.container form .orders .etc .num{
padding: 5px;
display: flex;
border: 1px solid var(--light-gray);
}
.container form .orders .etc .num .minus,
.container form .orders .etc .num .plus{
padding: 0 15px;
display: flex;
justify-content: center;
align-items: center;
border: 0;
background-color: var(--white);
font-size: var(--font-content); /* 버튼 내 텍스트 크기 */
cursor: pointer; /* 마우스 커서 변경 */
}
.container form .orders .etc .num .text{
width: 40px;
display: flex;
justify-content: center;
align-items: center;
font-size: var(--font-content); /* 필요에 따라 조정 */
}
/* 새로운 매뉴 추가 */
.container form .menu-plus{
background-color: var(--extra-light-gray);
text-align: center;
color: var(--gray);
}
/* 요청사항 */
.container form .request{
padding-top: 40px;
}
.container form .request .title{
font-weight: bold;
}
.container form .request .contents{
border: 1px solid var(--light-gray);
}
.container form .request .submit{}
cart.js
// form 관련
function cartsubmit(form){
form.submit();
}
// 숫자 증감
const minus = document.querySelectorAll('.minus');
const plus = document.querySelectorAll('.plus');
// 수량 증가 함수
function plusNum(text) {
let num = parseInt(text.innerHTML);
if (num < 100) {
num += 1;
text.innerHTML = num;
}
}
// 수량 감소 함수
function minusNum(text) {
let num = parseInt(text.innerHTML);
if (num > 1) {
num -= 1;
text.innerHTML = num;
}
}
minus.forEach( e =>{
e.addEventListener('mousedown', () => {
// 'text' 요소를 이 버튼과 가장 가까운 상위 요소에서 찾습니다.
const text = e.closest('.num').querySelector('.text');
minusNum(text); // 수량 감소
});
});
plus.forEach( e =>{
e.addEventListener('mousedown', () => {
// 'text' 요소를 이 버튼과 가장 가까운 상위 요소에서 찾습니다.
const text = e.closest('.num').querySelector('.text');
plusNum(text); // 수량 증가
});
});
// 메뉴 추가 버튼 클릭 시 메인으로
const menuPlus = document.querySelector(".menu-plus");
menuPlus.addEventListener('click', () =>{
location.href = '/user/main';
});
order.html - 여긴 그냥 스타일 다듬기
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/css/style.css" type="text/css">
<link rel="stylesheet" href="/css/manager/order.css" type="text/css">
<script src="/js/manager/order.js" defer type="text/javascript"></script>
</head>
<body>
<div class="innerBox">
<header>
<div>
<a href=""><i class="fas fa-home"></i></a>
</div>
<p>주문관리</p>
<div>
<a href="#"></a>
</div>
</header>
<div class="container">
<ul class="order-state-summary">
<li class="call">
<p class="state-name">호출</p>
<p class="state-content"><span>9</span>건</p>
</li>
<li class="wait">
<p class="state-name">주문</p>
<p class="state-content"><span>3</span>건</p>
</li>
<li class="okay">
<p class="state-name">승인</p>
<p class="state-content"><span>1</span>건</p>
</li>
</ul>
<button onclick="location.href='/manager/sales'">총 매출 확인하기 ></button>
<ul class="list-select">
<li class="on">전체</li>
<li>호출</li>
<li>대기</li>
<li>승인</li>
</ul>
<ul class="order-list">
<li>
<div class="content-summary">
<div class="left">
<p class="order-title call">호출</p>
<p class="order-subtitle">와주세요</p>
<span class="table-name">1번 테이블</span>
</div>
<div class="right">
<span class="time">13:00</span>
</div>
</div>
</li>
<li>
<div class="content-summary">
<div class="left">
<p class="order-title wait">주문</p>
<span class="table-name">1번 테이블</span>
</div>
<div class="right">
<span class="time">13:00</span>
<button><i class="fas fa-chevron-down"></i></button>
</div>
</div>
<table class="info">
<tr>
<th>상품이름</th>
<th>수량</th>
<th>금액</th>
</tr>
<tr>
<td>짜파게티</td>
<td>2</td>
<td>3,000</td>
</tr>
<tr>
<td>토마토 파스타</td>
<td>23</td>
<td>9,000</td>
</tr>
<tr>
<td>총 합계</td>
<td>25</td>
<td>267,000</td>
</tr>
</table>
</li>
</ul>
</div>
</div>
</body>
</html>
order.css
@charset "UTF-8";
.container>div{
margin: 0;
padding: 20px;
border-bottom: 1px solid var(--light-gray);
}
/* 식당 이름 */
.container .restaurant-name{
width: 100%;
font-size: var(--font-middle);
font-weight: bold;
text-align: left;
}
/* 주문 목록 */
.container .order{
width: 100%;
display: flex;
justify-content: space-between;
}
.container .order .content{}
.container .order .content .title{
font-size: var(--font-content);
color: var(--black);
padding-bottom: 10px;
}
.container .order .content .before-price,
.container .order .content .option{
font-size: var(--font-small);
color: var(--gray);
padding-bottom: 10px;
}
.container .order .content .option{
padding-bottom: 0;
}
.container .order .after-price{
display: flex;
align-items: end;
}
/* 총 금액 */
.container .total-price{
border-bottom: 0;
width: 100%;
display: flex;
justify-content: space-between;
}
.container .total-price .title{}
.container .total-price .content{}
/* 요청사항 */
.container .request{
border-bottom: 0;
width: 100%;
background-color: var(--extra-light-gray);
}
.container .request .title{
padding-bottom: 20px;
}
.container .request .content{
font-size: var(--font-small);
color: var(--gray);
}
/* 기타? */
.container .etc{
border-bottom: 0;
width: 100%;
padding: 20px;
}
/* 경고 문구 */
.container .etc .warning{
font-size: var(--font-small);
color: var(--red);
padding-bottom: 20px;
text-align: center;
}
/* 버튼 */
.container .etc .submit{
width: 100%;
}
order.js
없음 나중에 백엔드 구현할때 할듯
review.html - 여긴 별 클릭 했을시 값변경과 별 색 변경
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>리뷰작성</title>
<link href="/css/style.css" rel="stylesheet">
<link href="/css/user/review.css" rel="stylesheet" type="text/css">
<script src="/js/user/review.js" type="text/javascript" defer></script>
</head>
<body>
<div class="innerBox">
<header></header>
<div class="container">
<form action="/user/review" method="post">
<div class="restaurant-name">더조은 식당</div>
<div class="stars">
<div class="star-span">
<span><i class="fas fa-star"></i></span>
<span><i class="fas fa-star"></i></span>
<span><i class="fas fa-star"></i></span>
<span><i class="fas fa-star"></i></span>
<span><i class="fas fa-star"></i></span>
<input type="hidden" name="star" id="star" class="star">
</div>
</div>
<div class="nickname">
<label class="title">닉네임</label>
<input type="text" class="contents" placeholder="닉네임을 입력해 주세요"></input>
</div>
<div class="review">
<label class="title">리뷰 내용</label>
<textarea class="contents" cols="3" rows="5"></textarea>
</div>
<div class="buttons">
<input type="button" class="submit button" onclick="reviewCheck(form)" value="리뷰 작성">
</div>
</form>
</div>
<footer></footer>
</div>
</body>
</html>
review.css
@charset "UTF-8";
.container form{
margin: 0;
padding: 0;
}
form{
width: 100%;
}
form>div{
margin: 0;
padding: 20px;
}
/* 식당 이름 */
.container form .restaurant-name{
width: 100%;
font-size: var(--font-middle);
font-weight: bold;
text-align: left;
}
/* 별 */
.container form .stars{
width: 100%;
padding: 0 20px;
}
.container form .stars .star-span{
font-size: var(--font-big);
color: var(--light-gray);
cursor: default;
}
.container form .stars .star-span span{
margin: -2px;
cursor: pointer;
}
/* 닉네임 */
.container form .nickname{
width: 100%;
}
.container form .nickname .title{
margin-bottom: 10px;
}
.container form .nickname .contents{
border: 1px solid var(--light-gray);
}
/* 리뷰 내용 */
.container form .review{
width: 100%;
}
.container form .review .title{
margin-bottom: 10px;
}
.container form .review .contents{
margin: 0;
border: 1px solid var(--light-gray);
}
/* 버튼 */
.container form .buttons{
padding-top: 0;
}
.container form .buttons .submit{
font-size: var(--font-middle);
}
review.js
function reviewCheck(form){
form.submit();
}
// 별 클릭시 색 변하는 이벤트
const stars = document.querySelectorAll('.star-span span');
const text = document.querySelector('.star-span .star');
stars.forEach( (e, idx) =>{
e.addEventListener('click', () =>{
updateStars(idx);
})
});
// 별을 i 번째 만큼 색 바꿈
function updateStars(idx){
stars.forEach( (e, i) =>{
text.value = idx+1;
if(i <= idx){
e.style.color = '#FFBE3F';
}else{
e.style.color = '#c2c2c2';
}
});
}
main구현할때 gpt 한테 다 해달래 했더니 너무 복잡해짐
나머진 최대한 혼자서 해서 수정이 쉬웠는데
편한데 수정이 어렵다는 단점이 있음
'공부 > Ganju' 카테고리의 다른 글
| [Spring/AWS] 팀프로젝트 9일차 (0) | 2024.04.08 |
|---|---|
| [Spring/AWS] 팀프로젝트 8일차 (0) | 2024.04.06 |
| [Spring/AWS] 팀프로젝트 6일차 (0) | 2024.04.03 |
| [Spring/AWS] 팀프로젝트 5일차 (0) | 2024.04.02 |
| [Spring/AWS] 팀프로젝트 4일차 (0) | 2024.04.02 |






