diff --git a/package.json b/package.json index e83a19b..e4b2dd9 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "dependencies": { "axios": "^1.7.7", "react": "^18.3.1", + "react-datepicker": "^7.5.0", "react-dom": "^18.3.1", "react-router-dom": "^6.26.2", + "react-toastify": "^10.0.6", "styled-components": "^6.1.13" }, "devDependencies": { diff --git a/public/fonts/GowunDodum.ttf b/public/fonts/GowunDodum.ttf new file mode 100644 index 0000000..2d87cc8 Binary files /dev/null and b/public/fonts/GowunDodum.ttf differ diff --git a/public/images/BackgroundImage.svg b/public/images/BackgroundImage.svg new file mode 100644 index 0000000..8dbab4e --- /dev/null +++ b/public/images/BackgroundImage.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/Letters/LetterOne.jsx b/src/components/Letters/LetterOne.jsx new file mode 100644 index 0000000..8ebabc7 --- /dev/null +++ b/src/components/Letters/LetterOne.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import * as S from "./styled"; + +export const LetterOne = ({ onNext, letterContent, setLetterContent }) => { + const handleChange = (e) => setLetterContent(e.target.value); + + return ( + + + +
+ 다음 +
+
+ ); +}; diff --git a/src/components/Letters/LetterTwo.jsx b/src/components/Letters/LetterTwo.jsx new file mode 100644 index 0000000..d54eaab --- /dev/null +++ b/src/components/Letters/LetterTwo.jsx @@ -0,0 +1,116 @@ +import React, { useState } from "react"; +import * as S from "./styled"; + +export const LetterTwo = ({ + onPrev, + onSubmit, + receiverInfo, + setReceiverInfo, + selectedYear, + setSelectedYear, + selectedDate, + setSelectedDate, + selectedTime, + setSelectedTime +}) => { + const handleYearChange = (date) => { + setSelectedYear(date); + setReceiverInfo((prevInfo) => ({ + ...prevInfo, + year: date.getFullYear(), + })); + }; + + const handleDateChange = (date) => { + setSelectedDate(date); + setReceiverInfo((prevInfo) => ({ + ...prevInfo, + monthDay: `${date.getMonth() + 1}-${date.getDate()}`, + })); + }; + + const handleTimeChange = (date) => { + setSelectedTime(date); + setReceiverInfo((prevInfo) => ({ + ...prevInfo, + time: `${date.getHours()}:${date.getMinutes().toString().padStart(2, "0")}`, + })); + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setReceiverInfo((prevInfo) => ({ + ...prevInfo, + [name]: value, + })); + }; + + return ( + + + 수신인 전화번호를 입력해 주세요. + + : + +
+
+
+ + 몇 년도에 보낼까요? + + : + + 년도 + + + + 몇 월 며칠에 보낼까요? + + : + +
+
+
+ + 몇 시 몇 분에 보낼까요? + + : + +
+
+
+ + + 이전 + 완료 + +
+ ); +}; diff --git a/src/components/Letters/styled.js b/src/components/Letters/styled.js new file mode 100644 index 0000000..f84947a --- /dev/null +++ b/src/components/Letters/styled.js @@ -0,0 +1,109 @@ +import styled from "styled-components"; +import backgroundImage from "/images/BackgroundImage.svg"; +import DatePicker from "react-datepicker"; +import "react-datepicker/dist/react-datepicker.css"; + + + +export const Wrapper = styled.div` + position: relative; + width: 350px; + height: 540px; + background: url(${backgroundImage}) no-repeat center center fixed; + background-size: cover; + box-shadow: 0px 0px 30px 0px rgba(0, 0, 0, 0.25); +`; + +export const Wrapper2 = styled.div` + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: center; + position: relative; + width: 350px; + height: 540px; + background: url(${backgroundImage}) no-repeat center center fixed; + background-size: cover; + box-shadow: 0px 0px 30px 0px rgba(0, 0, 0, 0.25); +`; + +export const Textinput = styled.textarea` + width: 100%; + height: 100%; + padding: 30px; + outline: none; + resize: none; + + color: ${({theme}) => theme.colors.black}; + + font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]}; + font-size: 14px; + font-style: normal; + font-weight: 700; + line-height: 1.4; +`; + +export const Button = styled.button` + cursor: pointer; + + color: ${({theme}) => theme.colors.black}; + + font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]}; + font-size: 14px; + font-style: normal; + font-weight: 700; +`; + +export const Section = styled.div` + display: flex; + flex-direction: column; + width: 100%; + justify-content: center; + align-items: center; + gap: 20px; +`; + +export const MainText = styled.div` + color: ${({theme}) => theme.colors.black}; + + font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]}; + font-size: 18px; + font-style: normal; + font-weight: 300; + line-height: 1.4; +`; + +export const Buttons = styled.div` + display: flex; + position: absolute; + width: 100%; + bottom: 0; + padding: 15px; + justify-content: space-between; + + cursor: pointer; +`; + +export const Rowing = styled.div` + display: flex; + flex-direction: row; + width: 60%; + gap: 4px; + justify-content: space-around; +`; + +export const CustomDatePicker = styled(DatePicker)` + color: ${({theme}) => theme.colors.black}; + + font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]}; + font-size: 14px; + font-style: normal; + font-weight: 700; + + background: inherit; + outline: none; + display: flex; + width: 80px; + + transform: translateY(5px); +`; \ No newline at end of file diff --git a/src/components/common/Toasts/ToastOne.jsx b/src/components/common/Toasts/ToastOne.jsx new file mode 100644 index 0000000..0588da7 --- /dev/null +++ b/src/components/common/Toasts/ToastOne.jsx @@ -0,0 +1,17 @@ +import React from "react"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; + +const ToastOne = () => { + return ( + + ); +}; + +export default ToastOne; diff --git a/src/components/layout/footer/Footer.jsx b/src/components/layout/footer/Footer.jsx index 857fd3a..2ea10b4 100644 --- a/src/components/layout/footer/Footer.jsx +++ b/src/components/layout/footer/Footer.jsx @@ -1,9 +1,15 @@ +import React from "react"; import * as S from "./styled"; +import { useNavigate } from "react-router-dom"; export const Footer = () => { + const navigation = useNavigate(); + return ( - <> - - - ) -} \ No newline at end of file + + navigation("/homepage")}>홈 + navigation("/letter")}>편지 작성하기 + navigation("/inventory")}>편지 보관함 + + ); +}; \ No newline at end of file diff --git a/src/components/layout/footer/styled.js b/src/components/layout/footer/styled.js index 38f3eeb..e264fb3 100644 --- a/src/components/layout/footer/styled.js +++ b/src/components/layout/footer/styled.js @@ -1 +1,21 @@ -import styled from "styled-components"; \ No newline at end of file +import styled from "styled-components"; + +export const Wrapper = styled.div` + display: flex; + width: 100%; + justify-content: space-evenly; + position: absolute; + bottom: 50px; +`; + +export const Text = styled.div` + display: flex; + + cursor: pointer; + + font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]}; + color: ${({theme}) => theme.colors.black}; + font-size: 20px; + font-weight: 400; + font-style: normal; +`; \ No newline at end of file diff --git a/src/constant/routeConstants.js b/src/constant/routeConstants.js index f419d03..23f1cdc 100644 --- a/src/constant/routeConstants.js +++ b/src/constant/routeConstants.js @@ -1,7 +1,10 @@ // src/constants/routeConstants.js export const ROUTE_PATHS = { - HOME: "/", + LOGIN: "/", + HOME: "/homepage", ABOUT: "/about", + LETTER: "/letter", + INVENTORY: "/inventory", CONTACT: "/contact", NOT_FOUND: "*", }; diff --git a/src/layouts/DefaultLayout.jsx b/src/layouts/DefaultLayout.jsx index 2bf9b19..a134798 100644 --- a/src/layouts/DefaultLayout.jsx +++ b/src/layouts/DefaultLayout.jsx @@ -1,11 +1,17 @@ -import { Outlet } from "react-router-dom"; +import { Outlet, useLocation } from "react-router-dom"; import styled from "styled-components"; +import { Footer } from "@components/layout/footer/Footer"; const DefaultLayout = () => { + const location = useLocation(); + + const isRoot = location.pathname === "/"; + return ( <> + {!isRoot &&