Skip to content

Commit

Permalink
Merge pull request #5 from taejun0/feature/#2
Browse files Browse the repository at this point in the history
feature: 홈페이지 구현
  • Loading branch information
taejun0 authored Nov 2, 2024
2 parents 39dfa26 + 77091ca commit 5c30d02
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 5 deletions.
52 changes: 52 additions & 0 deletions src/components/LetterPaper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useState } from "react";
import styled from "styled-components";
import Modal from "@components/common/Modal";
import BackgroundImage from "/images/BackgroundImage.svg";

const StyledLetterPaper = styled.div`
cursor: pointer;
padding: 20px;
border-radius: 8px;
background-image: url(${BackgroundImage});
background-size: cover;
background-repeat: no-repeat;
background-position: center;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); /* 그림자 추가 */
margin-bottom: 10px;
`;

const LetterPaper = ({ letter, onClick }) => {
const { letter: letterContent, sendAt } = letter;
const [isModalOpen, setIsModalOpen] = useState(false);
const sendDate = new Date(sendAt);
const currentDate = new Date();

const handleClick = () => {
if (sendDate > currentDate) {
onClick("이 편지는 아직 열 수 없습니다.");
} else {
setIsModalOpen(true);
}
};

const closeModal = () => {
setIsModalOpen(false);
};

return (
<>
<StyledLetterPaper onClick={handleClick}>
{sendDate > currentDate ? "비공개 편지" : letterContent}
</StyledLetterPaper>
{isModalOpen && (
<Modal onClose={closeModal}>
<h2>편지 내용</h2>
<p>{letterContent}</p>
<button onClick={closeModal}>닫기</button>
</Modal>
)}
</>
);
};

export default LetterPaper;
49 changes: 49 additions & 0 deletions src/components/common/Modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// components/common/Modal.js
import React from "react";
import styled from "styled-components";

const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5); /* 반투명한 배경 */
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
`;

const ModalContent = styled.div`
background: white;
border-radius: 8px;
padding: 20px;
max-width: 500px;
width: 100%;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); /* 모달 창 그림자 */
position: relative;
`;

const CloseButton = styled.button`
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
font-size: 20px;
cursor: pointer;
`;

const Modal = ({ children, onClose }) => {
return (
<Overlay onClick={onClose}>
<ModalContent onClick={(e) => e.stopPropagation()}>
<CloseButton onClick={onClose}>&times;</CloseButton>
{children}
</ModalContent>
</Overlay>
);
};

export default Modal;
25 changes: 25 additions & 0 deletions src/hooks/usegiveLetters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState, useEffect } from "react";
import { getReceivedLetters, getSentLetters } from "@services/lettergiveService";

export const usegiveLetters = (type) => {
const [letters, setLetters] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
const fetchLetters = async () => {
setLoading(true);
try {
const data = type === "received" ? await getReceivedLetters() : await getSentLetters();
setLetters(data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchLetters();
}, [type]);

return { letters, loading, error };
};
42 changes: 37 additions & 5 deletions src/pages/LetterInventoryPage/LetterInventoryPage.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
import * as S from "./styled";
import { useState } from "react";
import { usegiveLetters } from "@hooks/usegiveLetters";
import LetterPaper from "@components/LetterPaper";
import { toast } from "react-toastify";
import ToastOne from "@components/common/Toasts/ToastOne";

export const LetterInventoryPage = () => {
const [type, setType] = useState("received");
const { letters, loading, error } = usegiveLetters(type);

// 데이터 검증: letters가 배열이 아닐 경우 빈 배열로 설정
const validLetters = Array.isArray(letters) ? letters : [];

const handleOptionClick = (selectedType) => {
setType(selectedType);
};

const showToast = (message) => {
toast.info(message, { autoClose: 2000 });
};

if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message || "An unexpected error occurred"}</div>;

return (
<S.Wrapper>
<S.MiniHeader>
<S.HeaderOption>받은 편지</S.HeaderOption>
<S.HeaderOption>보낸 편지</S.HeaderOption>
<S.HeaderOption onClick={() => handleOptionClick("received")}>받은 편지</S.HeaderOption>
<S.HeaderOption onClick={() => handleOptionClick("sent")}>보낸 편지</S.HeaderOption>
</S.MiniHeader>
<div>
{validLetters.length === 0 ? (
<div>아직 편지함에 편지가 없습니다!</div>
) : (
validLetters.map((letter, index) => (
<LetterPaper key={index} letter={letter} onClick={showToast} />
))
)}
</div>
<ToastOne />
</S.Wrapper>
)
}
);
};

export default LetterInventoryPage;
export default LetterInventoryPage;
2 changes: 2 additions & 0 deletions src/pages/LetterInventoryPage/styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export const Wrapper = styled.div`
flex-direction: column;
justify-content: center;
align-items: center;
gap: 100px;
`;

export const MiniHeader = styled.div`
Expand Down
9 changes: 9 additions & 0 deletions src/pages/homepage/HomePage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ import * as S from "./styled";
export const HomePage = () => {
return (
<S.Wrapper>
<S.MainText>
“미래의 너에게, 오늘의 나를 담아 보내요.” <br />
</S.MainText>
<S.SubText>
이건 단순한 편지가 아니에요.<br /> 시간을 넘어 미래로 전해지는 감성 타임캡슐입니다.<br /> 당신은 오늘의 이야기, 소중한 추억, 누군가를 향한 진심을 편지에 담아, 그 편지가 열릴 날과 시간을 정할 수 있어요.<br /> 그리고 그날이 되기 전까지, 그 편지는 고이 봉인된 채로 기다립니다. 기다림 속에서 더욱 빛날 당신의 마음을 미래에 전해보세요. <br /><br />

편지를 받는 순간의 설렘, 기다림이 만들어내는 따뜻한 감동, 그 모든 것을 우리는 사랑합니다.<br /> 당신의 편지를 기다릴 누군가는 그 순간, 당신의 이야기에 웃고, 울고, 마음 깊이 감동받을지도 몰라요.<br /><br />

이건 단지 메시지를 보내는 것이 아니라, 오늘의 나를 미래에 남겨두는 특별한 방법입니다.<br /> 그리운 마음을 더 깊이 새기고 싶을 때, 사랑하는 이에게 진심을 담고 싶을 때, 우리의 타임캡슐 편지는 당신의 이야기를 더 아름답게 전해줄 거예요.<br />
</S.SubText>
</S.Wrapper>
)
}
Expand Down
23 changes: 23 additions & 0 deletions src/pages/homepage/styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,27 @@ export const Wrapper = styled.div`
flex-direction: column;
justify-content: center;
align-items: center;
padding: 15px;
`;


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: 3;
`;

export const SubText = styled.div`
color: ${({theme}) => theme.colors.black};
font-family: ${({theme}) => theme.fonts.GowunDodum["font-family"]};
font-size: 14px;
font-style: normal;
font-weight: 300;
line-height: 1.4;
`;
21 changes: 21 additions & 0 deletions src/services/lettergiveService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { instance } from "./instance";

export const getReceivedLetters = async () => {
try {
const response = await instance.get("/get/received/letter");
return response.data;
} catch (error) {
console.error("Failed to fetch received letters", error); // 에러 출력
throw error; // 에러를 다시 던짐
}
};

export const getSentLetters = async () => {
try {
const response = await instance.get("/get/sent/letter");
return response.data;
} catch (error) {
console.error("Failed to fetch sent letters", error); // 에러 출력
throw error; // 에러를 다시 던짐
}
};

0 comments on commit 5c30d02

Please sign in to comment.