diff --git a/env.development b/env.development new file mode 100644 index 0000000..c0e7760 --- /dev/null +++ b/env.development @@ -0,0 +1,3 @@ +VITE_API_BASE_URL=https://rolling-api.vercel.app +VITE_KAKAO_JAVASCRIPT_KEY=96d45a096ca60ab6ab02381934d8931d +VITE_KAKAO_MESSAGE_TEMPLATE_ID=123537 \ No newline at end of file diff --git a/env.production b/env.production new file mode 100644 index 0000000..e6e5ac0 --- /dev/null +++ b/env.production @@ -0,0 +1,3 @@ +VITE_API_BASE_URL=https://rolling-api.vercel.app +VITE_KAKAO_JAVASCRIPT_KEY=17836dd1144957610d3ad75f6c352274 +VITE_KAKAO_MESSAGE_TEMPLATE_ID=123533 \ No newline at end of file diff --git a/index.html b/index.html index 6a716f4..fd0ef1f 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,11 @@ - + + Main Page; + return ( + + + +
+
+ Point. 01 +
+

누구나 손쉽게, 온라인 롤링페이퍼를 만들 수 있어요

+

로그인 없이 자유롭게 만들어요.

+
+ + + + + +
+ + +
+ 올이모지 +
+
+
+ Point. 02 +
+

서로에게 이모지로 감정을 표현해보세요

+

롤링 페이지에 이모지를 추가할 수 있어요.

+
+
+
+
+
+ + + +
+
+ ); } export default MainPage; diff --git a/src/styles/style.css b/src/styles/style.css new file mode 100644 index 0000000..f42223d --- /dev/null +++ b/src/styles/style.css @@ -0,0 +1,530 @@ +* { + margin: 20px opx; + padding: 0; + box-sizing: border-box; + font-family: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI', + Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} + +body { + background-color: #ffffff; + color: #333; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 40px 20px; + transition: all 0.3s ease; + background-color: #f6f8ff; +} + +.container:first-of-type { + padding-top: 100px; /* 헤더 높이 + 추가 여백 */ +} + +.container .empty-space { + height: 30px; /* 헤더 높이 */ + background-color: #ffffff; + width: 100%; + margin: 0 auto; +} + +/* Header Styles */ +.header { + display: flex; + justify-content: space-between; + align-items: center; + height: 62px; + position: fixed; + top: 0; + left: 0; + right: 0; + background-color: #fff; + z-index: 1000; + padding: 0 20px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); +} + +.container .header { + position: fixed; + width: 100%; + max-width: none; + left: 0; + transform: none; + padding: 0 20px; +} + +.nav { + width: 100%; +} + +.nav ul { + display: flex; + list-style: none; + width: 100%; +} + +.nav ul li { + margin-right: 20px; +} + +.nav ul li a { + text-decoration: none; + color: #333; + font-weight: 500; + transition: color 0.3s ease; +} + +.nav ul li a:hover { + color: #8c4ff8; +} + +.create-paper-btn { + background-color: #8c4ff8; + color: white; + border: none; + border-radius: 8px; + padding: 10px 20px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: background-color 0.3s ease; + width: 180px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; +} + +.create-paper-btn:hover { + background-color: #7a3dd6; +} + +/* Point Sections */ +.point-section { + margin-bottom: 80px; +} + +.point-badge { + display: inline-block; + background-color: #8c4ff8; + color: white; + font-weight: 600; + padding: 8px 16px; + border-radius: 20px; + margin-bottom: 20px; +} + +.point-content h2 { + font-size: 28px; + font-weight: 700; + margin-bottom: 12px; + color: #333; +} + +.point-content p { + font-size: 16px; + color: #666; + margin-bottom: 30px; +} + +/* Cards Wrapper & Container */ +.cards-wrapper { + width: 100%; + overflow: hidden; + position: relative; +} + +.cards-container { + display: flex; + gap: 20px; + overflow-x: auto; + padding: 10px 0; + position: relative; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ +} + +.cards-container::-webkit-scrollbar { + display: none; /* Chrome, Safari, Opera */ +} + +.cards-container::-webkit-scrollbar-track { + background: transparent; +} + +.cards-container::-webkit-scrollbar-thumb { + background-color: transparent; + border-radius: 6px; +} + +.scroll-hint { + text-align: center; + font-size: 12px; + color: #999; + margin-top: 10px; + opacity: 0.7; + transition: opacity 0.5s ease; +} + +/* Card Styles */ +.card { + background: white; + border-radius: 16px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05); + width: 300px; + min-width: 300px; + padding: 20px; + display: flex; + flex-direction: column; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); +} + +.card-header { + display: flex; + align-items: center; + margin-bottom: 15px; +} + +.profile-img { + width: 40px; + height: 40px; + border-radius: 50%; + object-fit: cover; + margin-right: 12px; +} + +.card-author { + display: flex; + flex-direction: column; +} + +.card-author span:first-child { + font-weight: 600; + font-size: 14px; +} + +.tag { + display: inline-block; + font-size: 12px; + padding: 2px 8px; + border-radius: 12px; + background-color: #e9f3ff; + color: #4a90e2; +} + +.tag-purple { + background-color: #f0e7ff; + color: #8c4ff8; +} + +.card-body { + flex-grow: 1; + margin-bottom: 15px; + font-size: 14px; + line-height: 1.5; +} + +.card-footer { + font-size: 12px; + color: #999; +} + +/* Add Card Button */ +.add-card { + background: white; + border-radius: 16px; + border: 2px dashed #ddd; + width: 300px; + min-width: 300px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; +} + +.add-icon { + font-size: 32px; + color: #999; +} + +/* Reactions Section */ +.reactions-section { + margin-bottom: 80px; +} + +.reactions-container { + position: relative; + width: fit-content; +} + +.reaction-row { + display: flex; + gap: 10px; + margin-bottom: 10px; +} + +.reaction-count { + display: flex; + align-items: center; + background: #f0f0f0; + border-radius: 20px; + padding: 6px 12px; + font-size: 14px; + font-weight: 500; +} + +.emoji { + margin-right: 5px; +} + +.reactions-dropdown { + position: absolute; + top: 100%; + left: 0; + background: white; + border-radius: 12px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + padding: 15px; + z-index: 10; + margin-top: 10px; + width: 300px; +} + +/* Media Queries */ +/* 태블릿 디바이스 */ +@media (max-width: 1024px) { + .container { + max-width: 90%; + padding: 30px 15px; + } + + .point-section { + margin-bottom: 60px; + } + + .point-content h2 { + font-size: 26px; + } + + .cards-wrapper { + width: 100%; + max-width: 100%; + overflow-x: auto; + padding-bottom: 15px; + margin: 0 auto; + } + + .cards-container { + width: 100%; + padding: 10px 15px 5px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 20px; + overflow-x: visible; + justify-content: center; + } + + .card, + .add-card { + width: 100%; + min-width: auto; + max-width: 100%; + transition: transform 0.3s ease, box-shadow 0.3s ease; + } +} + +/* 모바일 디바이스 */ +@media (max-width: 768px) { + .container { + padding: 20px 15px; + } + + .container:first-of-type { + padding-top: 80px; + } + + .header { + padding: 0 15px; + height: 60px; + } + + .create-paper-btn { + font-size: 12px; + padding: 8px 15px; + width: 150px; + } + + .point-badge { + padding: 6px 12px; + font-size: 14px; + } + + .point-content h2 { + font-size: 22px; + margin-bottom: 10px; + } + + .point-content p { + font-size: 14px; + margin-bottom: 20px; + } + + .cards-wrapper { + margin: 0 auto; + width: 100%; + overflow-x: hidden; + overflow-y: visible; + padding-bottom: 10px; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + } + + .cards-wrapper::-webkit-scrollbar { + display: none; /* Chrome, Safari, Opera */ + } + + .cards-container { + display: flex; + flex-direction: column; + overflow-x: hidden; + padding: 0 15px 10px; + width: 100%; + max-width: 100%; + gap: 20px; + } + + .card, + .add-card { + width: 100%; + min-width: auto; + max-width: 100%; + margin: 0 auto; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + } + + .reaction-row { + flex-wrap: wrap; + } + + .reactions-dropdown { + width: 100%; + max-width: 280px; + } + + /* 스크롤 인디케이터 스타일 */ + .scroll-indicator { + margin: 15px auto 0; + width: 80%; + height: 4px; + background: #eee; + border-radius: 2px; + overflow: hidden; + } + + .scroll-indicator span { + display: block; + height: 100%; + width: 33.33%; + background: #8c4ff8; + border-radius: 2px; + transition: transform 0.3s ease; + } + + .cta-button { + padding: 12px 25px; + font-size: 14px; + width: 80%; + max-width: 300px; + } +} + +/* CTA Section Styles */ +.cta-section { + text-align: center; + margin-bottom: 60px; +} + +.cta-button { + background-color: #8c4ff8; + color: white; + border: none; + border-radius: 8px; + padding: 15px 30px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 12px rgba(140, 79, 248, 0.2); +} + +.cta-button:hover { + background-color: #7a3dd6; + transform: translateY(-2px); + box-shadow: 0 6px 16px rgba(140, 79, 248, 0.3); +} + +/* 작은 모바일 디바이스 */ +@media (max-width: 480px) { + .point-section { + margin-bottom: 40px; + } + + .point-content h2 { + font-size: 20px; + } + + .card, + .add-card { + width: 100%; + min-width: auto; + max-width: 100%; + padding: 15px; + margin: 0 auto; + border-radius: 14px; + } + + .cards-wrapper { + padding: 0; + margin: 0 auto; + width: 100%; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ + } + + .cards-wrapper::-webkit-scrollbar { + display: none; /* Chrome, Safari, Opera */ + } + + .cards-container { + width: 100%; + padding: 0 15px 10px; + gap: 15px; + } + + .card-body { + font-size: 13px; + } + + .reaction-count { + padding: 4px 10px; + font-size: 13px; + } + + .scroll-indicator { + width: 90%; + margin: 10px auto 0; + } + + .cta-button { + padding: 10px 20px; + font-size: 13px; + width: 90%; + } +} diff --git a/src/utils/script.js b/src/utils/script.js new file mode 100644 index 0000000..8d05dd0 --- /dev/null +++ b/src/utils/script.js @@ -0,0 +1,170 @@ +document.addEventListener("DOMContentLoaded", function () { + // 모바일 메뉴 토글 기능 + const mobileMenuBtn = document.querySelector(".mobile-menu-btn"); + const navMenu = document.querySelector(".nav ul"); + const createPaperBtnMobile = document.querySelector(".create-paper-btn"); + + if (mobileMenuBtn && navMenu) { + mobileMenuBtn.addEventListener("click", function () { + if (navMenu.style.display === "flex") { + navMenu.style.display = "none"; + mobileMenuBtn.classList.remove("active"); + } else { + navMenu.style.display = "flex"; + navMenu.style.flexDirection = "column"; + navMenu.style.position = "absolute"; + navMenu.style.top = "60px"; + navMenu.style.right = "20px"; + navMenu.style.backgroundColor = "white"; + navMenu.style.padding = "15px"; + navMenu.style.borderRadius = "8px"; + navMenu.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.1)"; + navMenu.style.zIndex = "100"; + mobileMenuBtn.classList.add("active"); + } + }); + } + + // 이모지 반응 토글 기능 + const reactionsContainer = document.querySelector(".reactions-container"); + const reactionsDropdown = document.querySelector(".reactions-dropdown"); + const reactionAdd = document.querySelector(".reaction-add"); + + // 초기에는 드롭다운 숨기기 + if (reactionsDropdown) { + reactionsDropdown.style.display = "none"; + } + + // 이모지 추가 버튼 클릭 시 드롭다운 토글 + if (reactionAdd) { + reactionAdd.addEventListener("click", function (e) { + e.stopPropagation(); + if (reactionsDropdown.style.display === "none") { + reactionsDropdown.style.display = "block"; + } else { + reactionsDropdown.style.display = "none"; + } + }); + } + + // 드롭다운 외부 클릭 시 닫기 + document.addEventListener("click", function (event) { + if (reactionsContainer && !reactionsContainer.contains(event.target)) { + if (reactionsDropdown) { + reactionsDropdown.style.display = "none"; + } + } + }); + + // 새 카드 추가 버튼 기능 + const addCardButton = document.querySelector(".add-card"); + if (addCardButton) { + addCardButton.addEventListener("click", function () { + alert("새 메시지를 작성할 수 있는 폼이 열립니다."); + // 실제 구현에서는 모달 폼을 열거나 페이지 이동 등의 기능 구현 + }); + } + + // 이모지 반응 클릭 시 카운트 증가 (예시 기능) + const reactionCounts = document.querySelectorAll(".reaction-count"); + reactionCounts.forEach(function (reaction) { + reaction.addEventListener("click", function (e) { + e.stopPropagation(); // 상위 이벤트 전파 방지 + const countElement = this.querySelector("span:last-child"); + if (countElement) { + let count = parseInt(countElement.textContent); + countElement.textContent = count + 1; + } + }); + }); + + // CTA 버튼 클릭 이벤트 + const ctaButton = document.querySelector(".cta-button"); + if (ctaButton) { + ctaButton.addEventListener("click", function () { + window.location.href = "#"; // 실제 구현에서는 롤링페이퍼 목록 페이지로 이동 + }); + } + + // 롤링페이퍼 만들기 버튼 클릭 이벤트 + const createPaperBtn = document.querySelector(".create-paper-btn"); + if (createPaperBtn) { + createPaperBtn.addEventListener("click", function () { + window.location.href = "#"; // 실제 구현에서는 롤링페이퍼 생성 페이지로 이동 + }); + } + + // 반응형 디자인을 위한 추가 기능 + function handleResize() { + // 화면 크기에 따라 동적으로 조정이 필요한 요소들 처리 + const windowWidth = window.innerWidth; + const cardsContainer = document.querySelector(".cards-container"); + const cardsWrapper = document.querySelector(".cards-wrapper"); + + // 모바일 메뉴 처리 + if (windowWidth > 768) { + const navMenu = document.querySelector(".nav ul"); + if (navMenu) { + navMenu.removeAttribute("style"); + } + } + + // 카드 컨테이너 스크롤 처리 + if (cardsContainer && cardsWrapper) { + // 스크롤 인디케이터 추가 (모바일에서만) + if (windowWidth <= 768) { + if (!document.querySelector(".scroll-indicator")) { + const scrollIndicator = document.createElement("div"); + scrollIndicator.className = "scroll-indicator"; + const scrollIndicatorSpan = document.createElement("span"); + scrollIndicator.appendChild(scrollIndicatorSpan); + cardsWrapper.after(scrollIndicator); + } + } else { + // 태블릿/데스크톱에서는 스크롤 표시기 제거 + const scrollIndicator = document.querySelector(".scroll-indicator"); + if (scrollIndicator) { + scrollIndicator.remove(); + } + } + } + } + + // 초기 로드 및 리사이즈 시 실행 + handleResize(); + window.addEventListener("resize", handleResize); + + // 화면 방향 변경 감지 + window.addEventListener("orientationchange", () => { + setTimeout(handleResize, 300); // 방향 변경 후 약간의 지연 시간을 두고 실행 + }); + + // 카드 컨테이너 스크롤 이벤트 + const cardsContainer = document.querySelector(".cards-container"); + if (cardsContainer) { + cardsContainer.addEventListener("scroll", function () { + const scrollIndicator = document.querySelector(".scroll-indicator span"); + if (scrollIndicator) { + const scrollPercentage = + (this.scrollLeft / (this.scrollWidth - this.clientWidth)) * 100; + scrollIndicator.style.width = scrollPercentage + "%"; + } + }); + } + // 카드 컨테이너 가로 스크롤 감추기이벤트 + const cardsContainer = document.querySelector(".cards-container"); + if (cardsContainer) { + // 모바일 환경에서 가로 스크롤 기능 비활성화 + if (window.innerWidth <= 768) { + cardsContainer.style.overflowX = "hidden"; + cardsContainer.style.overflowY = "auto"; + + // 스크롤 인디케이터 제거 + const scrollIndicator = document.querySelector(".scroll-indicator"); + if (scrollIndicator) { + scrollIndicator.style.display = "none"; + } + } else { + } + } +});