From 435c40e6d8f7f1964d2bbf0235536cae05239087 Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 01:00:24 +0900 Subject: [PATCH 1/6] Prevent admin access to admin pages for non-admin roles (customer, store) --- .../admin/approval/ApprovalTable.js | 29 +++++++++- src/components/auth/LoginForm.js | 24 +++++++++ src/components/auth/SignUpForm.js | 24 ++++++++- src/components/header/MyInfo.js | 14 +++++ src/components/header/MyInfo.module.scss | 7 +++ src/pages/auth/LoginPage.js | 54 +++++++++++-------- src/pages/auth/SignUpPage.js | 14 ++++- src/pages/customer/CustomerMyPage.js | 4 +- src/utils/authUtil.js | 4 ++ 9 files changed, 144 insertions(+), 30 deletions(-) diff --git a/src/components/admin/approval/ApprovalTable.js b/src/components/admin/approval/ApprovalTable.js index 68e19065..31e4b95f 100644 --- a/src/components/admin/approval/ApprovalTable.js +++ b/src/components/admin/approval/ApprovalTable.js @@ -14,6 +14,8 @@ import ApprovalButtons from "./ApprovalButton"; import TansPagination from "./TansPagination"; import TansTable from "./TansTable"; import ApprovalSummary from "./ApprovalSummary"; +import {checkAuthToken, getRefreshToken, getToken, getUserRole} from "../../../utils/authUtil"; +import {useNavigate} from "react-router-dom"; const ApprovalTable = () => { const [data, setData] = useState([]); @@ -23,6 +25,7 @@ const ApprovalTable = () => { const [startDate, setStartDate] = useState(new Date('2024-07-01')); const [endDate, setEndDate] = useState(new Date()); const [stats, setStats] = useState({}); + const navigate = useNavigate(); const table = useReactTable({ data, @@ -37,6 +40,7 @@ const ApprovalTable = () => { rowSelection, }, }); + const fetchApprovals = async () => { console.log('fetchApprovals 실행중!') @@ -46,6 +50,9 @@ const ApprovalTable = () => { // const token = localStorage.getItem('token'); // const refreshToken = localStorage.getItem('refreshToken'); + let userRole = getUserRole(); + console.log("userRole :",userRole); + const res = await fetch( `/admin/approve?start=${startISO}&end=${endISO}`, { @@ -53,8 +60,8 @@ const ApprovalTable = () => { headers: { 'Content-Type' : 'application/json', 'Cache-Control': 'no-cache', - // 'Authorization' : 'Bearer ' + getUserToken(), - // 'refreshToken': refreshToken, + // 'Authorization' : 'Bearer ' + getToken(), + // 'refreshToken': getRefreshToken(), }, }); if(!res.ok) { @@ -86,6 +93,24 @@ const ApprovalTable = () => { fetchApprovals(); }, [startDate, endDate]); + // useEffect 훅 사용하여 admin이 아닐 경우 접근 제한 + useEffect(() => { + debugger + const userInfo = checkAuthToken(navigate); + + if (userInfo) { + const requiredRole = 'admin'; // 단일 역할을 설정 + const userRole = getUserRole(); // 사용자 역할 가져오기 + + if (userRole !== requiredRole) { // 문자열 비교 + alert('접근 권한이 없습니다.'); + navigate('/main'); + return; + } + } + }, + []); + return (
diff --git a/src/components/auth/LoginForm.js b/src/components/auth/LoginForm.js index 155ed0f2..6c8551ae 100644 --- a/src/components/auth/LoginForm.js +++ b/src/components/auth/LoginForm.js @@ -28,6 +28,27 @@ const LoginForm = ({ userType, onVerificationSent }) => { return emailRegex.test(email); }; + //admin : customer 테이블에 저장되지만, role은 admin으로 저장됨 + const checkAdminDupId = async (email) => { + try { + const response = await fetch(`/customer/check?email=${email}`); + const result = await response.json(); + if (result) { + console.log(`입력하신 이메일 [ ${email} ] 은 customer 회원입니다.`); + setIsExistingUser(true); + return true; + } else { + console.error(`입력하신 이메일 [ ${email} ] 은 customer 회원이 아닙니다.`); + setIsExistingUser(false); + return false; + } + } catch (error) { + console.error('Error:', error); + return false; + } + } + + //customer const checkCustomerDupId = async (email) => { try { const response = await fetch(`/customer/check?email=${email}`); @@ -47,6 +68,7 @@ const LoginForm = ({ userType, onVerificationSent }) => { } } + //store const checkStoreDupId = async (email) => { try { const response = await fetch(`/store/check?email=${email}`); @@ -73,6 +95,8 @@ const LoginForm = ({ userType, onVerificationSent }) => { return await checkCustomerDupId(email); case 'store': return await checkStoreDupId(email); + case 'admin': + return await checkAdminDupId(email); default: return false; } diff --git a/src/components/auth/SignUpForm.js b/src/components/auth/SignUpForm.js index 950ba284..7f6b5392 100644 --- a/src/components/auth/SignUpForm.js +++ b/src/components/auth/SignUpForm.js @@ -31,6 +31,26 @@ const SignUpForm = ({ userType, onVerificationSent }) => { return emailRegex.test(email); }; + //admin : customer 테이블에 저장되지만, role은 admin으로 저장됨 + const checkAdminDupId = async (email) => { + try { + const response = await fetch(`/email/check?email=${email}`); + const result = await response.json(); + if (!result) { + console.log(`입력하신 이메일 [ ${email} ] 은 admin 회원이 아닙니다.`); + setIsExistingUser(false); + return true; + } else { + console.error(`입력하신 이메일 [ ${email} ] 은 admin 회원입니다.`); + setIsExistingUser(true); + return false; + } + } catch (error) { + console.error('Error:', error); + return false; + } + }; + //customer // 새로운 아이디 -> 중복검사 후 no -> 회원가입하기로 유도 const checkCustomerDupId = async (email) => { @@ -79,6 +99,8 @@ const checkDupId = async (email) => { return await checkCustomerDupId(email); case 'store': return await checkStoreDupId(email); + case 'admin' : + return await checkAdminDupId(email); default: return false; } @@ -99,7 +121,7 @@ const sendVerificationLinkForSignUp = async (email) => { }), }); if (response.ok) { - console.log('이메일이 성공적으로 전달되었습니다.',userType,email); + console.log('이메일이 성공적으로 전달되었습니다. usertype, email 확인하기 : ',userType,email); return true; } else { console.error('Failed to send verification link'); diff --git a/src/components/header/MyInfo.js b/src/components/header/MyInfo.js index 4918898c..fd3e2fc7 100644 --- a/src/components/header/MyInfo.js +++ b/src/components/header/MyInfo.js @@ -31,6 +31,8 @@ const MyInfo = () => { localStorage.setItem('userImage', data.productImg); } else if (getUserRole() === 'customer') { localStorage.setItem('userImage', data.profileImage); + } else if (getUserRole() === 'store') { + localStorage.setItem('userImage', data.profileImage); } // 닉네임이 null 일 경우 저장하지 않음 @@ -86,6 +88,18 @@ const MyInfo = () => { onClick={() => handleIconClick("/customer")} /> + ) : getUserRole() === 'admin' ? ( + <> + {/* Admin 아이콘과 프로필 이미지 */} + + Customer Profile handleIconClick("/customer")} + /> + ADMIN + ) : null}
diff --git a/src/components/header/MyInfo.module.scss b/src/components/header/MyInfo.module.scss index 99f4eb40..9ff21145 100644 --- a/src/components/header/MyInfo.module.scss +++ b/src/components/header/MyInfo.module.scss @@ -27,3 +27,10 @@ cursor: pointer; border: #03684e solid; } + +.admin { + position: absolute; + top: 55px; + font-size: 12px; +} + diff --git a/src/pages/auth/LoginPage.js b/src/pages/auth/LoginPage.js index 35ea7dd9..675ae2ea 100644 --- a/src/pages/auth/LoginPage.js +++ b/src/pages/auth/LoginPage.js @@ -28,32 +28,40 @@ const LoginPage = () => {
{!verificationSent && ( // 이메일 발송 후 사용자 유형 버튼 숨기기
- - + + +
)} - -
+ onResendEmail={handleResendEmail} + onVerificationSent={handleVerificationSent} + verificationSent={verificationSent} // verificationSent 상태 전달 + /> +
sign up 🌱 diff --git a/src/pages/auth/SignUpPage.js b/src/pages/auth/SignUpPage.js index fa6a4e2c..29fa4757 100644 --- a/src/pages/auth/SignUpPage.js +++ b/src/pages/auth/SignUpPage.js @@ -12,10 +12,12 @@ const SignUpPage = () => { setUserType(type); }; - const handleSignUp = (email, password) => { - console.log('User Sign Up:', email, password); + const handleSignUp = (email, userType) => { + console.log('User Sign Up:', email, userType); + // 여기서 userType을 백엔드에 전달하여 처리 }; + const handleResendEmail = () => { console.log('이메일 재전송 버튼 누름 !'); }; @@ -48,6 +50,14 @@ const SignUpPage = () => { > Store +
)} { const userInfo = await checkAuthToken(navigate); if (userInfo) { - const requiredRole = 'customer'; // 필요한 role 작성 필요 - if (userInfo.userType !== requiredRole) { + const requiredRoles = ['customer', 'admin']; // 필요한 역할 목록 + if (!requiredRoles.includes(userInfo.userType)) { alert('접근 권한이 없습니다.'); navigate('/main'); return; diff --git a/src/utils/authUtil.js b/src/utils/authUtil.js index ce98a841..6b002c84 100644 --- a/src/utils/authUtil.js +++ b/src/utils/authUtil.js @@ -136,6 +136,10 @@ export const checkAuthToken = async (navigate) => { const userType = tokenInfo.role; const email = tokenInfo.sub; + console.log(tokenInfo); + console.log(userType); + console.log(email); + return {token, refreshToken, userType, email}; } From 3ccf1fc55c28de3876df5527adaba49813a803ba Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 06:59:06 +0900 Subject: [PATCH 2/6] # delete footer --- src/layout/Footer.module.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/layout/Footer.module.scss b/src/layout/Footer.module.scss index 1a379fe1..66981406 100644 --- a/src/layout/Footer.module.scss +++ b/src/layout/Footer.module.scss @@ -119,4 +119,10 @@ margin-bottom: -80px; letter-spacing: 15px; text-align: center; +} + +@media (max-width: 780px) and (max-height: 844px) { + .footer { + display: none; + } } \ No newline at end of file From c54b72f1e5d36d9e2470a755a1f675c6ac0aacd8 Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 07:28:45 +0900 Subject: [PATCH 3/6] header mypage editing.. --- src/layout/Header.js | 102 +++++++++++++++------------ src/layout/Header.module.scss | 94 ++++++++++++++++++++++++ src/pages/customer/CustomerMyPage.js | 6 +- 3 files changed, 153 insertions(+), 49 deletions(-) diff --git a/src/layout/Header.js b/src/layout/Header.js index bba62144..6432e9c9 100644 --- a/src/layout/Header.js +++ b/src/layout/Header.js @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +import {Link, useNavigate} from 'react-router-dom'; import {getToken, getRefreshToken, extractArea} from '../utils/authUtil'; import styles from './Header.module.scss'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -10,6 +10,8 @@ import MyInfo from "../components/header/MyInfo"; import {getCurrentLocation, initializeNaverMapsForHeader, reverseGeocode} from "../utils/locationUtil"; import SidebarModal from "../components/header/SidebarModal"; import SearchInput from "../components/search/SearchInput"; +import SideBar from "../components/store/mypage-edit/SideBar"; +import Edit from "../components/store/mypage-edit/Edit"; // 아이콘을 라이브러리에 추가 library.add(faMagnifyingGlass); @@ -73,54 +75,62 @@ const Header = () => { let userArea = extractArea(); + // 햄버거 버튼 기존 기능 되도록 수정 + const showHandler = () => { + setShow(prev => !prev); + } + return (
- {/* 햄버거 버튼 */} - {width > 400 && } - - {/* 로고 */} -
- - {/* 현재 위치 */} -
-
{userArea}
-
-
Now
-
- - - {/* 상점 검색 칸 */} - {/*로그인을 하지 않아도 검색칸은 보이되, 로그인이 필요한 서비스 안내하기*/} - { - getToken() && -
- - + {/* 햄버거 버튼 */} + {width <= 400 && } + {/*
*/} + {/* */} + {/*
*/} + + + {/* 로고 */} + + + {/* 현재 위치 */} +
+
{userArea}
+
+
Now
+
+ + + {/* 상점 검색 칸 */} + {/*로그인을 하지 않으면 검색창이 사라짐*/} + { + getToken() && +
+ + +
+ } + + {/*리뷰 커뮤니티 메인*/} +
+ + {/* 로그인 및 회원가입 버튼 */} +
+ {isAuthenticated ? ( + + ) : ( + <> + +
+ + + )}
- } - - {/*리뷰 커뮤니티 메인*/} -
- - - {/* 로그인 및 회원가입 버튼 */} -
- {isAuthenticated ? ( - - ) : ( - <> - -
- - - )} -
- {/* 모달 */} - {modalVisible && } -
- ); + {/* 모달 */} + {modalVisible && } + +); } export default Header; diff --git a/src/layout/Header.module.scss b/src/layout/Header.module.scss index eb407e3b..6dcf317c 100644 --- a/src/layout/Header.module.scss +++ b/src/layout/Header.module.scss @@ -29,6 +29,7 @@ button { background-size: contain; background-repeat: no-repeat; margin-left: 70px; + cursor: pointer; } /* 현재 위치 버튼 스타일 */ @@ -150,3 +151,96 @@ button { margin-top: 5px; margin-left: 10px; } + +// 햄버거 버튼 반응형 기능 안됨으로 인한 css 추가 +.container { + width: 80%; + margin: 20px auto 0; + border: 1px solid #ccc; + border-radius: 15px; + display: flex; + background: white; +} + +@media (max-width: 400px) { + .container { + width: 100%; + border: none; + margin-top: 0; + } +} + +// 반응형 헤더 +@media (max-width: 400px) { + .header { + flex-direction: column; + align-items: flex-start; + padding: 10px; + height: auto; + } + + .logoBtn { + height: 50px; + width: 50px; + margin-left: 10px; + margin-bottom: 10px; /* 아래쪽에 여백 추가 */ + } + + .locationPinIcon { + height: 24px; + width: 24px; + margin-left: 10px; + margin-bottom: 5px; + } + + .areaName { + font-size: 16px; + margin-left: 5px; + } + + .selectedAreaCategory { + font-size: 16px; + margin-left: 5px; + margin-bottom: 10px; /* 아래쪽에 여백 추가 */ + } + + .selectedAreaCategoryBtn { + height: 12px; + width: 12px; + margin-left: 5px; + margin-top: 0; + } + + .searchStoreSection { + width: 100%; + margin: 10px 0; + padding: 0 10px; + max-width: 100%; + margin-left: 0; + background-color: rgba(6, 101, 78, 0.5); /* 투명도 증가 */ + } + + .reviewMainIcon { + height: 30px; + width: 30px; + margin-left: 10px; + margin-top: 10px; /* 위쪽에 여백 추가 */ + } + + .loginBtnSection { + flex-direction: column; + gap: 5px; /* 버튼 간격 감소 */ + margin-top: 10px; + } + + .signInBtn, .signUpBtn { + font-size: 16px; + margin: 0; + } + + .dot { + margin-left: 0; + margin-top: 0; + display: none; /* 점 제거 */ + } +} \ No newline at end of file diff --git a/src/pages/customer/CustomerMyPage.js b/src/pages/customer/CustomerMyPage.js index 0ed7f8e0..148af67f 100755 --- a/src/pages/customer/CustomerMyPage.js +++ b/src/pages/customer/CustomerMyPage.js @@ -8,7 +8,7 @@ import FavoriteStore from "../../components/customer/mypage/FavoriteStore"; import SideBarBtn from "../../components/store/mypage-edit/SideBarBtn"; import { jwtDecode } from 'jwt-decode'; -import {authFetch, checkAuthToken} from "../../utils/authUtil"; +import {authFetch, checkAuthToken, getUserRole} from "../../utils/authUtil"; import {useNavigate} from "react-router-dom"; const BASE_URL = window.location.origin; @@ -40,8 +40,8 @@ const CustomerMyPage = () => { const userInfo = await checkAuthToken(navigate); if (userInfo) { - const requiredRole = 'customer'; // 필요한 role 작성 필요 - if (userInfo.userType !== requiredRole) { + const requiredRoles = ['customer', 'admin']; // 필요한 역할 목록 + if (!requiredRoles.includes(userInfo.userType)) { alert('접근 권한이 없습니다.'); navigate('/main'); return; From 4d24d3ad050b02227b0788556b843a0e7efbfe09 Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 07:44:38 +0900 Subject: [PATCH 4/6] body color change to white, fix header --- src/common.module.scss | 6 ++++-- src/layout/Header.module.scss | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/common.module.scss b/src/common.module.scss index d9e3ab52..5e3edb78 100644 --- a/src/common.module.scss +++ b/src/common.module.scss @@ -26,12 +26,14 @@ body { font-family: Helvetica Neue, Helvetica, Arial, sans-serif; margin: 0; padding: 0; - background-color: #F5F5DD; + background-color: #FFFFFF; min-height: 1080px; /* 최소 높이 설정 */ + } -main { +body main { min-height: 1080px; /* 최소 높이 설정 */ + padding-top: 60px; /* 헤더 높이만큼 패딩을 추가 */ } a { diff --git a/src/layout/Header.module.scss b/src/layout/Header.module.scss index 6dcf317c..d68a3ba7 100644 --- a/src/layout/Header.module.scss +++ b/src/layout/Header.module.scss @@ -19,6 +19,11 @@ button { max-width: 1920px; /* 최대 너비를 1920px로 제한 */ margin: 0 auto; /* 중앙 정렬 */ background-color: #F5F5DD; + + position: fixed; /* 화면에 고정 */ + top: 0; /* 화면 상단에 위치 */ + left: 0; /* 왼쪽에 고정 */ + z-index: 1000; /* 다른 요소 위에 위치 */ } /* 로고 버튼 */ From ecf8639913bff94338b1abef673d842bfc891801 Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 08:09:53 +0900 Subject: [PATCH 5/6] delete myInfo image mobile version --- src/components/header/MyInfo.js | 8 ++++++-- src/components/header/MyInfo.module.scss | 10 +++++----- src/layout/Footer.module.scss | 8 ++++---- src/layout/Header.js | 9 +++++---- src/layout/Header.module.scss | 7 +++---- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/components/header/MyInfo.js b/src/components/header/MyInfo.js index fd3e2fc7..e4756d9f 100644 --- a/src/components/header/MyInfo.js +++ b/src/components/header/MyInfo.js @@ -31,7 +31,7 @@ const MyInfo = () => { localStorage.setItem('userImage', data.productImg); } else if (getUserRole() === 'customer') { localStorage.setItem('userImage', data.profileImage); - } else if (getUserRole() === 'store') { + } else if (getUserRole() === 'admin') { localStorage.setItem('userImage', data.profileImage); } @@ -61,8 +61,11 @@ const MyInfo = () => { } return ( + <> + {/*알림창*/} +
- + {/*안녕하세요 {getSubName() ? getSubName() : userInfo.email}님!*/} @@ -103,6 +106,7 @@ const MyInfo = () => { ) : null}
+ ); }; diff --git a/src/components/header/MyInfo.module.scss b/src/components/header/MyInfo.module.scss index 9ff21145..af4efaa2 100644 --- a/src/components/header/MyInfo.module.scss +++ b/src/components/header/MyInfo.module.scss @@ -7,11 +7,6 @@ margin-left: 60px; } -.myInfoContainer { - display: flex; - align-items: center; -} - .myIconContainer { margin-left: auto; /* 오른쪽 끝으로 이동 */ display: flex; @@ -34,3 +29,8 @@ font-size: 12px; } +@media (max-width: 400px) and (max-height: 844px) { + .myIconContainer { + display: none; + } +} diff --git a/src/layout/Footer.module.scss b/src/layout/Footer.module.scss index 66981406..ef929b2f 100644 --- a/src/layout/Footer.module.scss +++ b/src/layout/Footer.module.scss @@ -71,10 +71,10 @@ } .copyRight { - font-size: 24px; + font-size: 22px; position: absolute; - bottom: -35px; right: 100px; + bottom: 1px; } .footerLinks { @@ -116,12 +116,12 @@ font-size: 280px; width: 100%; max-width: 1920px; - margin-bottom: -80px; + margin-bottom: -40px; letter-spacing: 15px; text-align: center; } -@media (max-width: 780px) and (max-height: 844px) { +@media (max-width: 400px) and (max-height: 844px) { .footer { display: none; } diff --git a/src/layout/Header.js b/src/layout/Header.js index 6432e9c9..fd72c041 100644 --- a/src/layout/Header.js +++ b/src/layout/Header.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import {Link, useNavigate} from 'react-router-dom'; -import {getToken, getRefreshToken, extractArea} from '../utils/authUtil'; +import {getToken, getRefreshToken, extractArea, getUserRole} from '../utils/authUtil'; import styles from './Header.module.scss'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import SideBarBtn from "../components/store/mypage-edit/SideBarBtn"; @@ -12,6 +12,7 @@ import SidebarModal from "../components/header/SidebarModal"; import SearchInput from "../components/search/SearchInput"; import SideBar from "../components/store/mypage-edit/SideBar"; import Edit from "../components/store/mypage-edit/Edit"; +import Notification from "../components/socket/Notification"; // 아이콘을 라이브러리에 추가 library.add(faMagnifyingGlass); @@ -84,9 +85,9 @@ const Header = () => {
{/* 햄버거 버튼 */} {width <= 400 && } - {/*
*/} - {/* */} - {/*
*/} +
+ +
{/* 로고 */} diff --git a/src/layout/Header.module.scss b/src/layout/Header.module.scss index d68a3ba7..f93c0184 100644 --- a/src/layout/Header.module.scss +++ b/src/layout/Header.module.scss @@ -187,8 +187,8 @@ button { .logoBtn { height: 50px; width: 50px; - margin-left: 10px; - margin-bottom: 10px; /* 아래쪽에 여백 추가 */ + margin-left: 50px; + margin-bottom: 5px; /* 아래쪽에 여백 추가 */ } .locationPinIcon { @@ -217,11 +217,10 @@ button { } .searchStoreSection { - width: 100%; + width: 120px; margin: 10px 0; padding: 0 10px; max-width: 100%; - margin-left: 0; background-color: rgba(6, 101, 78, 0.5); /* 투명도 증가 */ } From c67da280faed3641d449b093f0a4252211329130 Mon Sep 17 00:00:00 2001 From: Maybaba Date: Tue, 20 Aug 2024 09:35:26 +0900 Subject: [PATCH 6/6] =?UTF-8?q?#=20=EB=B0=98=EC=9D=91=ED=98=95=20=ED=97=A4?= =?UTF-8?q?=EB=8D=94=20=EC=88=98=EC=A0=95=EC=A4=91=20-=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=EC=B0=BD=EC=9D=B4=20=EC=9E=91=EC=95=84=EC=84=9C=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EC=9D=B4=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20?= =?UTF-8?q?=EC=95=88=EB=90=A8=20-=20=ED=96=84=EB=B2=84=EA=B1=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9D=84=20=EB=88=84=EB=A5=B4=EB=A9=B4=20?= =?UTF-8?q?=EB=B0=B0=EA=B2=BD=EC=83=89=EC=9D=B4=20=ED=88=AC=EB=AA=85?= =?UTF-8?q?=ED=95=B4=EC=A7=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/header/MyInfo.js | 3 +- src/components/header/MyInfo.module.scss | 5 ++ .../socket/Notification.module.scss | 11 ++- src/layout/Header.module.scss | 73 ++++++++++--------- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/src/components/header/MyInfo.js b/src/components/header/MyInfo.js index e4756d9f..093c6896 100644 --- a/src/components/header/MyInfo.js +++ b/src/components/header/MyInfo.js @@ -63,7 +63,8 @@ const MyInfo = () => { return ( <> {/*알림창*/} - + +
diff --git a/src/components/header/MyInfo.module.scss b/src/components/header/MyInfo.module.scss index af4efaa2..c6236c2c 100644 --- a/src/components/header/MyInfo.module.scss +++ b/src/components/header/MyInfo.module.scss @@ -33,4 +33,9 @@ .myIconContainer { display: none; } + + .notificationIcon { + position: absolute; + left: 40px + } } diff --git a/src/components/socket/Notification.module.scss b/src/components/socket/Notification.module.scss index 2caab420..e51a52aa 100644 --- a/src/components/socket/Notification.module.scss +++ b/src/components/socket/Notification.module.scss @@ -68,4 +68,13 @@ 50% { opacity: 0; } -} \ No newline at end of file +} + +// header 알림아이콘 반응형 크기 +@media (max-width: 400px) { + + .notify-icon { + position: absolute; + right: 10px; + } +} diff --git a/src/layout/Header.module.scss b/src/layout/Header.module.scss index f93c0184..ea2f53a7 100644 --- a/src/layout/Header.module.scss +++ b/src/layout/Header.module.scss @@ -178,63 +178,70 @@ button { // 반응형 헤더 @media (max-width: 400px) { .header { - flex-direction: column; - align-items: flex-start; + flex-direction: row; /* 요소들을 가로로 정렬 */ + align-items: center; /* 세로 가운데 정렬 */ padding: 10px; - height: auto; + height: 60px; } .logoBtn { - height: 50px; - width: 50px; - margin-left: 50px; - margin-bottom: 5px; /* 아래쪽에 여백 추가 */ + position: absolute; + height: 40px; + width: 40px; + margin-left: 60px; } .locationPinIcon { - height: 24px; - width: 24px; - margin-left: 10px; - margin-bottom: 5px; + //position: absolute; + //height: 32px; /* 크기를 줄이지 않음 */ + //width: 32px; + //margin-left: 10px; + display: none; } - .areaName { - font-size: 16px; + .selectedAreaCategoryBtn { + position: absolute; + height: 15px; + width: 15px; margin-left: 5px; + margin-top: 0; + left: 200px; } - .selectedAreaCategory { - font-size: 16px; - margin-left: 5px; - margin-bottom: 10px; /* 아래쪽에 여백 추가 */ + // 각종 기능은 드롭다운모달로 볼 수있게 설정? + .reviewMainIcon { + //position: absolute; + //right: 5px; + //height: 40px; /* 크기를 줄이지 않음 */ + //width: 40px; + //margin-left: 10px; + display: none; } - .selectedAreaCategoryBtn { - height: 12px; - width: 12px; + //반응형일시 현재위치 렌더링 안함, 드롭다운으로 볼 수 있게 설정해보기. + .areaName { + display: none; + } + + .selectedAreaCategory { + font-size: 16px; margin-left: 5px; - margin-top: 0; + margin-bottom: 0; /* 아래쪽 여백 제거 */ } .searchStoreSection { width: 120px; - margin: 10px 0; padding: 0 10px; - max-width: 100%; background-color: rgba(6, 101, 78, 0.5); /* 투명도 증가 */ - } - - .reviewMainIcon { - height: 30px; - width: 30px; - margin-left: 10px; - margin-top: 10px; /* 위쪽에 여백 추가 */ + margin-left: 0; /* or 조정된 값으로 변경 */ } .loginBtnSection { - flex-direction: column; - gap: 5px; /* 버튼 간격 감소 */ - margin-top: 10px; + display: flex; + flex-direction: row; /* 버튼들을 가로로 정렬 */ + gap: 5px; + margin-left: auto; /* 오른쪽으로 밀기 */ + margin-top: 0; } .signInBtn, .signUpBtn {