본문 바로가기

사이드 프로젝트

카페 추천 웹사이트(카페추천리스트 페이지 수정, 메인페이지 수정)

기존의 디자인했던 것에 추가되는부분이 알람과 마이페이지부터 수정하겠습니다.

 

알림버튼은 아이콘을 사용할 예정이기 때문에

npm install react-icons --save

를 사용해서 설치를 해준다. 설치가 완료되면

React Icons 해당 사이트에서 사용할 아이콘을 골라준다.(저는 알림버튼을 대체할 종모양 => fa FaBell)

 

그 다음 해당 아이콘을 사용할 react파일에 import해준다.

import { FaBell } from "react-icons/fa";

 

여기서 주의할 점은 'react-icons/fi' 이 부분이다.
위의 사진을 자세히 보면 아이콘의 이름들이 파스칼 케이스로 되어 있는 것을 볼 수 있다.

(파스칼 케이스 : 첫 글자와 중간 글자가 모두 대문자)

 

여기서 파스칼 케이스 중 첫 번째 부분을 'react-icons/' 뒤에 소문자로 써야 한다. 내가 사용한 'FiMenu'를 예로 들면, 'FiMenu'의 첫 번째 부분인 'Fi'를 소문자 'fi'로 바꿔 'react-icons/fi' 이렇게 써야 정상적으로 작동이 된다.

 

 

import { FaBell } from "react-icons/fa";
<li>
     <button onClick={handleAlertClick} className={styles.alram}>
         <FaBell size={24} />
     </button>
</li>
 

저는 이렇게 사용해줬습니다.

 

코드 작성후 결과물

 

그 다음 지역 선택과 맛집 선택(카테고리들)이 세로로 배치되어 있어서 가로로 배치되도록 수정합니다.

 

 

<div className={styles.categorySelect}>
                <label htmlFor="region">지역 선택:</label>
                <select
                    id="region"
                    value={selectedRegion}
                    onChange={(e) => setSelectedRegion(e.target.value)}
                >
                    <option value="all">모두 보기</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>
                    <option value="충북">충북</option>
                    <option value="제주">제주</option>
                </select>
            </div>

            <div className={styles.categorySelect}>
                <label htmlFor="category">맛집 선택:</label>
                <select
                    id="category"
                    value={selectedCategory}
                    onChange={(e) => setSelectedCategory(e.target.value)}
                >
                    <option value="all">모두 보기</option>
                    <option value="뷰맛집">뷰 맛집</option>
                    <option value="빵맛집">빵 맛집</option>
                    <option value="커피맛집">커피 맛집</option>
                </select>
            </div>

해당 코드에 감싸는 div를 하나 더 추가 하겠습니다.

 

<div className={styles.selectContainer}>
                <div className={styles.categorySelect}>
                    <label htmlFor="region">지역 선택:</label>
                    <select
                        id="region"
                        value={selectedRegion}
                        onChange={(e) => setSelectedRegion(e.target.value)}
                    >
                        <option value="all">모두 보기</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>
                        <option value="충북">충북</option>
                        <option value="제주">제주</option>
                    </select>
                </div>
       
                <div className={styles.categorySelect}>
                    <label htmlFor="category">맛집 선택:</label>
                    <select
                        id="category"
                        value={selectedCategory}
                        onChange={(e) => setSelectedCategory(e.target.value)}
                    >
                        <option value="all">모두 보기</option>
                        <option value="뷰맛집">뷰 맛집</option>
                        <option value="빵맛집">빵 맛집</option>
                        <option value="커피맛집">커피 맛집</option>
                    </select>
                </div>
            </div>

그리고 css를 고칩니다.

 

.selectContainer {
    display: flex; /* Flexbox 사용 */
    justify-content: space-between; /* 공간을 균등하게 배분 */
    align-items: center; /* 수직 정렬 */
    margin: 20px auto; /* 상단 여백 및 중앙 정렬 */
    width: 20%; /* 원하는 너비 설정 */
}

.categorySelect {
    margin-right: 20px; /* 오른쪽 여백 추가 */
    flex: 1; /* 각 선택 박스가 공간을 차지하도록 설정 */
}

 

수정 후 결과

 

 

 


 

메인페이지 수정

 

이미지 클릭시 회원가입 팝업 창 띄우기 계정 생성 후 => 로그인 팝업창 => 로그인 시 CafeList로 이동

import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom'; // useHistory 훅 임포트
import styles from './CafeMain.module.css';
import { Link } from 'react-router-dom';

const images = [
    { id: 1, url: require('../img/slide1.jpg'), link: '/cafeList' },
    { id: 2, url: require('../img/slide2.jpg'), link: '/cafeList' },
    { id: 3, url: require('../img/slide3.jpg'), link: '/cafeList' },
];

export default function CafeMain() {
    const [currentIndex, setCurrentIndex] = useState(0);
    const [showSignupPopup, setShowSignupPopup] = useState(false); // 회원가입 팝업 상태 추가
    const [showLoginPopup, setShowLoginPopup] = useState(false); // 로그인 팝업 상태 추가
    const [emailText, setEmailText] = useState(""); // 이메일 텍스트 상태 추가
    const [emailDomain, setEmailDomain] = useState("gmail.com"); // 이메일 도메인 상태 추가
    const [nickname, setNickname] = useState(""); // 닉네임 상태 추가

    const navigate = useNavigate(); // useHistory 훅 사용

    useEffect(() => {
        const interval = setInterval(() => {
            setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length);
        }, 3000); // 3초마다 이미지 변경
        return () => clearInterval(interval); // 컴포넌트 언마운트 시 인터벌 정리
    }, []);

    const handleImageClick = () => {
        setShowSignupPopup(true); // 회원가입 팝업 표시
    }
   
    const closeSignupPopup = () => {
        setShowSignupPopup(false); // 회원가입 팝업 닫기
    }

    const handleEmailChange = (e) => {
        setEmailText(e.target.value); // 이메일 텍스트 업데이트
    }

    const handleDomainChange = (e) => {
        setEmailDomain(e.target.value); // 이메일 도메인 업데이트
    }

    const handleNicknameChange = (e) => {
        setNickname(e.target.value); // 닉네임 업데이트
    }

    const handleSignupSubmit = (e) => {
        e.preventDefault(); // 폼 제출 기본 동작 방지
        // 여기서 회원가입 처리 로직을 추가하고 로그인 팝업 보여주기
        console.log(`가입할 이메일: ${emailText}@${emailDomain}, 닉네임: ${nickname}`); // 가입할 정보 출력
        setShowSignupPopup(false); // 회원가입 팝업 닫기
        setShowLoginPopup(true); // 로그인 팝업 열기
    };

    const checkEmail = () => {
        console.log(`Checking email: ${emailText}@${emailDomain}`);
        // 실제 API 호출을 통해 이메일 중복을 확인하는 로직 추가
    };

    const checkNickname = () => {
        console.log(`Checking nickname: ${nickname}`);
        // 실제 API 호출을 통해 닉네임 중복을 확인하는 로직 추가
    };

    const closeLoginPopup = () => {
        setShowLoginPopup(false); // 로그인 팝업 닫기
    }

    const handleLoginSubmit = (e) => {
        e.preventDefault(); // 기본 폼 제출 방지
        // 로그인 처리 로직이 여기에 추가
        navigate('/cafeList'); // CafeList로 이동
    }

    return (
        <div className={styles.bgImg}>
            <div className={styles.header}>
                <h1>
                    <Link to="/">CAFE 추천</Link>
                </h1>
                <div className={styles.contentWrap}>
                    {images.map((image, index) => (
                        <div
                            key={image.id}
                            className={`${styles.contentImg} ${currentIndex === index ? styles.visible : styles.hidden}`}
                            style={{ backgroundImage: `url(${image.url})` }}
                            onClick={handleImageClick}  // 클릭 이벤트 핸들러
                        >
                        </div>
                    ))}
                </div>
            </div>

            {/* 회원가입 팝업 */}
            {showSignupPopup && (
                <div className={styles.loginPopup}>
                    <div className={styles.popupContent}>
                        <span className={styles.closeButton} onClick={closeSignupPopup}>×</span>
                        <h2>회원가입</h2>
                        <form onSubmit={handleSignupSubmit}>
                            <div>
                                <label htmlFor="email">이메일:</label>
                                <div className={styles.emailContainer}>
                                    <input
                                        type="text"
                                        id="email"
                                        name="email"
                                        value={emailText}
                                        onChange={handleEmailChange}
                                        required
                                        placeholder="이메일 입력"
                                    />
                                    <select
                                        value={emailDomain}
                                        onChange={handleDomainChange}
                                        className={styles.emailSelect}
                                    >
                                        <option value="gmail.com">@gmail.com</option>
                                        <option value="naver.com">@naver.com</option>
                                        <option value="kakao.com">@kakao.com</option>
                                    </select>
                                    <button type="button" onClick={checkEmail} className={styles.checkButton}>중복 확인</button>
                                </div>
                            </div>
                            <div>
                                <label htmlFor="nickname">닉네임:</label>
                                <div className={styles.nicknameContainer}>
                                    <input
                                        type="text"
                                        id="nickname"
                                        name="nickname"
                                        value={nickname}
                                        onChange={handleNicknameChange}
                                        required
                                    />
                                    <button type="button" onClick={checkNickname} className={styles.checkButton}>중복 확인</button>
                                </div>
                            </div>
                            <div>
                                <label htmlFor="password">비밀번호:</label>
                                <input type="password" id="password" name="password" required />
                            </div>
                            <div>
                                <label htmlFor="confirmPassword">비밀번호 확인:</label>
                                <input type="password" id="confirmPassword" name="confirmPassword" required />
                            </div>
                            <button type="submit">계정 만들기</button>
                        </form>
                    </div>
                </div>
            )}

            {/* 로그인 팝업 */}
            {showLoginPopup && (
                <div className={styles.loginPopup}>
                    <div className={styles.popupContent}>
                        <span className={styles.closeButton} onClick={closeLoginPopup}>×</span>
                        <h2>로그인</h2>
                        <form onSubmit={handleLoginSubmit}>
                            <div>
                                <label htmlFor="loginEmail">이메일:</label>
                                <input type="email" id="loginEmail" name="loginEmail" required placeholder="이메일 입력" />
                            </div>
                            <div>
                                <label htmlFor="loginPassword">비밀번호:</label>
                                <input type="password" id="loginPassword" name="loginPassword" required placeholder="비밀번호 입력" />
                            </div>
                            <button type="submit">로그인</button>
                        </form>
                    </div>
                </div>
            )}
        </div>
    )
}

CafeMain.js코드

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

a {
    text-decoration: none;
    color: black;
}

li {
    list-style: none;
}

img {
    display: block;
    width: 100%;
}

.header {
    text-align: center;
    margin-top: 40px;
}

.header > h1 > a {
    color: #001F3F;
}

.bgImg {
    display: flex;
    justify-content: center; /* 수평 중앙 정렬 */
    background-image: url('../img/main_bg.avif'); /* 배경 이미지 설정 */
    background-size: cover; /* 배경 이미지 크기 조정 */
    background-position: center; /* 배경 이미지 중앙 정렬 */
    height: 100vh; /* 원하는 높이 설정 */
    width: 100%; /* 전체 너비 */
    position: relative;
}

.contentWrap {
    margin-top: 20px;
    position: relative; /* 자식 요소의 절대 위치 설정을 위해 필요 */
    overflow: hidden; /* 자식 요소가 넘어가는 부분 숨기기 */
    height: 700px; /* 슬라이드 높이 설정 */
    width: 1420px;
}

.contentImg {
    background-size: cover; /* 배경 이미지 크기 조정 */
    background-position: center; /* 배경 이미지 중앙 정렬 */
    width: 100%; /* 전체 너비 */
    height: 100%; /* 부모 요소에 맞게 높이 설정 */
    position: absolute; /* 절대 위치 */
    transition: opacity 1s ease-in-out; /* 부드러운 전환 효과 */
    opacity: 0;
}

.visible {
    opacity: 1; /* 보이는 상태 */
}

.hidden {
    opacity: 0; /* 숨겨진 상태 */
}

/* 로그인 및 회원가입 팝업 */
.loginPopup {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.6); /* 반투명 배경 */
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.popupContent {
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    width: 400px; /* 팝업 너비 조정 */
    position: relative;
}

.closeButton {
    position: absolute;
    top: 10px;
    right: 10px;
    cursor: pointer;
    font-size: 20px;
}

h2 {
    margin-bottom: 15px;
}

form {
    display: flex;
    flex-direction: column;
}

label {
    margin-bottom: 5px;
    text-align: left; /* 레이블 왼쪽 정렬 */
}

input {
    margin-bottom: 15px;
    padding: 8px;
    border: 1px solid #ccc;
    border-radius: 4px;
    width: 100%; /* 입력 필드 너비를 100%로 설정 */
    box-sizing: border-box; /* 패딩과 보더를 포함하여 전체 너비 설정 */
}

button {
    padding: 10px;
    margin: 5px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

button:hover {
    background-color: #0056b3;
}

/* 이메일 입력 및 도메인 선택 */
.emailContainer {
    display: flex; /* Flexbox를 사용하여 가로 배치 */
    align-items: center; /* 수직 중앙 정렬 */
}

.emailContainer input {
    margin-right: 10px; /* 오른쪽 여백 추가 */
}

.emailSelect {
    padding: 10px; /* 패딩 추가 */
    border: 1px solid #ccc; /* 테두리 설정 */
    border-radius: 4px; /* 모서리 둥글게 */
    margin: 0 10px 15px 0;
}

/* 닉네임 입력 및 중복 확인 버튼 */
.nicknameContainer {
    display: flex; /* Flexbox를 사용하여 가로 배치 */
    align-items: center; /* 수직 중앙 정렬 */
}

.checkButton {
    padding: 8px 12px; /* 버튼 패딩 */
    background-color: #007bff; /* 버튼 배경 색상 */
    color: white; /* 버튼 텍스트 색상 */
    border: none; /* 테두리 제거 */
    border-radius: 4px; /* 모서리 둥글게 */
    cursor: pointer; /* 커서 포인터 변경 */
    margin-left: 10px; /* 버튼과 입력 필드 사이의 여백 */
    width: 80px;
    height: 37px;
    font-size: 12px; /* 폰트 크기 조정 */
    font-weight: bold;
}

.checkButton:hover {
    background-color: #0056b3; /* 호버 시 배경 색상 변경 */
}

.emailCheckButton {
    width: 120px; /* 이메일 중복 확인 버튼 너비 */
    height: 37px;
    font-size: 12px; /* 폰트 크기 조정 */
    font-weight: bold;
}

 

CafeMain.module.css코드

실행 결과(영상)

메인페이지 시연영상.mp4
1.97MB

 

 

오늘은 이렇게 마무리~