-
Notifications
You must be signed in to change notification settings - Fork 2
feat: 내 편지함 기능 구현 1차 #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,21 @@ | ||
| import axios from 'axios'; | ||
|
|
||
| export const client = axios.create({ | ||
| const client = axios.create({ | ||
| baseURL: import.meta.env.VITE_API_URL, | ||
| }); | ||
|
|
||
| // client.interceptors.request.use( | ||
| // (config) => { | ||
| // const token = localStorage.getItem('authToken'); | ||
| // if (token) { | ||
| // config.headers['Authorization'] = `Bearer ${token}`; | ||
| // } | ||
| // return config; | ||
| // }, | ||
| // (error) => { | ||
| // //TODO: 에러처리 | ||
| // return Promise.reject(error); | ||
| // }, | ||
| // ); | ||
|
|
||
| export default client; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| import { client } from './client'; | ||
| import client from './client'; | ||
|
|
||
| const getLetter = async ( | ||
| letterId: string, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import client from './client'; | ||
|
|
||
| export const getMailbox = async () => { | ||
| try { | ||
| const response = await client.get('/api/mailbox'); | ||
| if (!response) throw new Error('error while fetching mailbox data'); | ||
| return response.data; | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| export const getMailboxDetail = async (id: number) => { | ||
| try { | ||
| const response = await client.get(`/api/mailbox/${id}`); | ||
| if (!response) throw new Error('error while fetching mailbox detail data'); | ||
| return response.data; | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
|
|
||
| export const postMailboxDisconnect = async (id: number) => { | ||
| try { | ||
| const response = await client.post(`/api/mailbox/${id}/disconnect`); | ||
| if (!response) throw new Error('error while disconnecting mailbox'); | ||
| return response; | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import client from './client'; | ||
|
|
||
| export const postShareProposals = async ( | ||
| letterIds: number[], | ||
| requesterId: number, | ||
| recipientId: number, | ||
| message: string, | ||
| ) => { | ||
| try { | ||
| const response = await client.post('/api/share-proposals', { | ||
| letterIds: letterIds, | ||
| requesterId: requesterId, | ||
| recipientId: recipientId, | ||
| message: message, | ||
| }); | ||
| if (!response) throw new Error('error while fetching mailbox data'); | ||
| return response; | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,54 +1,66 @@ | ||
| import { Link } from 'react-router'; | ||
| import { useNavigate } from 'react-router'; | ||
| import { twMerge } from 'tailwind-merge'; | ||
|
|
||
| interface LetterBoxItemProps { | ||
| boxId: number; | ||
| zipCode: string; | ||
| letterCount: number; | ||
| isChecked?: boolean; | ||
| isClosed?: boolean; | ||
| } | ||
|
|
||
| const LetterBoxItem = ({ | ||
| boxId, | ||
| zipCode, | ||
| letterCount, | ||
| isChecked = false, | ||
| isClosed = false, | ||
| }: LetterBoxItemProps) => { | ||
| const navigate = useNavigate(); | ||
| const handleClickItem = (id: number) => { | ||
| navigate(`${id}`, { | ||
| state: { | ||
| id, | ||
| zipCode, | ||
| isClosed, | ||
| }, | ||
| }); | ||
| }; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 navigate에 인자가 각각 무슨 역할을 하는건가용? 저는 navigate('/') 같은 라우팅만 해봐서요!! |
||
| return ( | ||
| <Link to="id"> | ||
| <article className="flex h-fit w-fit flex-col items-center"> | ||
| <div className="text-gray-70 flex h-25 w-20 flex-col gap-1.5 bg-linear-to-b from-[#D5B695] to-[#B3895D] p-1.5"> | ||
| <p | ||
| <article | ||
| className="flex h-fit w-fit flex-col items-center" | ||
| onClick={() => handleClickItem(boxId)} | ||
| > | ||
| <div className="text-gray-70 flex h-25 w-20 flex-col gap-1.5 bg-linear-to-b from-[#D5B695] to-[#B3895D] p-1.5"> | ||
| <p | ||
| className={twMerge( | ||
| 'body-m from-white px-1', | ||
| isClosed | ||
| ? 'bg-[repeating-linear-gradient(#D9D9D9,#D9D9D9_17px,#C2C2C2_17px,#C2C2C2_23px)]' | ||
| : 'bg-linear-to-b', | ||
| isChecked ? 'to-[#FFF5ED]' : 'to-[#FFF4F2]', | ||
| )} | ||
| > | ||
| {zipCode} | ||
| </p> | ||
| {isClosed ? ( | ||
| <div className="flex grow flex-col bg-[repeating-linear-gradient(#D9D9D9,#D9D9D9_15px,#C2C2C2_15px,#C2C2C2_20px)]" /> | ||
| ) : ( | ||
| <div | ||
| className={twMerge( | ||
| 'body-m from-white px-1', | ||
| isClosed | ||
| ? 'bg-[repeating-linear-gradient(#D9D9D9,#D9D9D9_17px,#C2C2C2_17px,#C2C2C2_23px)]' | ||
| : 'bg-linear-to-b', | ||
| isChecked ? 'to-[#FFF5ED]' : 'to-[#FFF4F2]', | ||
| 'flex grow flex-col bg-linear-to-b', | ||
| isChecked ? 'from-[#FFF7E3] to-[#FFE197]' : 'from-[#FFF4F2] to-[#FFE6E3]', | ||
| )} | ||
| > | ||
| {zipCode} | ||
| </p> | ||
| {isClosed ? ( | ||
| <div className="flex grow flex-col bg-[repeating-linear-gradient(#D9D9D9,#D9D9D9_15px,#C2C2C2_15px,#C2C2C2_20px)]" /> | ||
| ) : ( | ||
| <div | ||
| className={twMerge( | ||
| 'flex grow flex-col bg-linear-to-b', | ||
| isChecked ? 'from-[#FFF7E3] to-[#FFE197]' : 'from-[#FFF4F2] to-[#FFE6E3]', | ||
| )} | ||
| > | ||
| <p className="body-r mt-auto mr-[1px] text-right">{letterCount}통</p> | ||
| </div> | ||
| )} | ||
| </div> | ||
| <div className="flex flex-col items-center"> | ||
| <div className="h-[7px] w-23 bg-[#D7A877]" /> | ||
| <div className="h-[3px] w-20 bg-[#A88156]" /> | ||
| <div className="h-1 w-18 bg-[#917B63]" /> | ||
| </div> | ||
| </article> | ||
| </Link> | ||
| <p className="body-r mt-auto mr-[1px] text-right">{letterCount}통</p> | ||
| </div> | ||
| )} | ||
| </div> | ||
| <div className="flex flex-col items-center"> | ||
| <div className="h-[7px] w-23 bg-[#D7A877]" /> | ||
| <div className="h-[3px] w-20 bg-[#A88156]" /> | ||
| <div className="h-1 w-18 bg-[#917B63]" /> | ||
| </div> | ||
| </article> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,81 @@ | ||
| import { useEffect, useState } from 'react'; | ||
|
|
||
| import { getMailbox } from '@/apis/mailBox'; | ||
| import DoorImg from '@/assets/images/door.png'; | ||
| import ClosedWindowImg from '@/assets/images/window-disabled.png'; | ||
| import PageTitle from '@/components/PageTitle'; | ||
| import { chunkBox } from '@/utils/chunkBox'; | ||
|
|
||
| import LetterBoxItem from './components/LetterBoxItem'; | ||
|
|
||
| const DUMMY_COUNT = 200; | ||
|
|
||
| interface LetterBoxData { | ||
| letterMatchingId: number; | ||
| oppositeZipCode: string; | ||
| active: boolean; | ||
| oppositeRead: boolean; | ||
| // totalLetters: number; | ||
| } | ||
| const LetterBoxPage = () => { | ||
| const [letterBox, setLetterBox] = useState<LetterBoxData[]>([]); | ||
|
|
||
| const fetchMailLists = async () => { | ||
| try { | ||
| const response = await getMailbox(); | ||
| if (!response) throw new Error(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오오오 try문 코드 안에서 에러코드를 안 만들고 있었는데 이렇게 만들어야 에러 파악이 더 체계적으로 이루어지는군용 저도 예외처리 코드 수정해보겠습니다!!👍👍👍👍 |
||
| const data: LetterBoxData[] = response.data; | ||
| // 정렬? | ||
| setLetterBox(data); | ||
| } catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
| useEffect(() => { | ||
| fetchMailLists(); | ||
| }, []); | ||
|
|
||
| return ( | ||
| <main className="flex grow flex-col items-center px-5 pt-20"> | ||
| <PageTitle>내 편지함</PageTitle> | ||
| <div className="w-full max-w-94"> | ||
| <p className="body-sb mt-16 mb-[7px] place-self-start text-gray-50"> | ||
| 나와 연락한 사람들 {DUMMY_COUNT} | ||
| 나와 연락한 사람들 {letterBox?.length} | ||
| </p> | ||
| <section className="letter-box-bg flex grow flex-col items-center px-4 pt-5"> | ||
| <div className="flex w-full flex-col gap-5"> | ||
| {chunkBox( | ||
| Array.from({ length: 12 }).map((_, index) => ( | ||
| <LetterBoxItem | ||
| key={index} | ||
| zipCode="12E12" | ||
| letterCount={90} | ||
| isChecked={index % 2 === 0} | ||
| /> | ||
| )), | ||
| ).map((row, index) => ( | ||
| <div key={index} className="flex justify-between"> | ||
| {row} | ||
| </div> | ||
| ))} | ||
| {letterBox.length > 0 ? ( | ||
| chunkBox( | ||
| letterBox.map((data: LetterBoxData, index) => ( | ||
| <LetterBoxItem | ||
| boxId={data.letterMatchingId} | ||
| key={index} | ||
| zipCode={data.oppositeZipCode} | ||
| letterCount={90} | ||
| isChecked={data.oppositeRead} | ||
| isClosed={data.active} | ||
| /> | ||
| )), | ||
| ).map((row, index) => | ||
| row.length === 3 ? ( | ||
| <div key={index} className="flex justify-between"> | ||
| {row} | ||
| </div> | ||
| ) : ( | ||
| <div key={index} className="flex justify-between"> | ||
| {row} | ||
| <img src={ClosedWindowImg} alt="닫힌 문 이미지" className="h-28 w-23" /> | ||
| {row.length === 1 && ( | ||
| <img src={ClosedWindowImg} alt="닫힌 문 이미지" className="h-28 w-23" /> | ||
| )} | ||
| </div> | ||
| ), | ||
| ) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. letterBox를 3개씩 분류해 배열에 담고 그걸 반복문 돌려서 3개가 안 담긴 배열엔 닫힌 문을 채워서 UI를 나타내신건가용(그냥 질문입니당) |
||
| ) : ( | ||
| <p className="body-m text-gray-60 text-center">아직 주고 받은 편지가 없어요</p> | ||
| )} | ||
| <div className="flex justify-between"> | ||
| <LetterBoxItem zipCode="12E12" letterCount={90} isClosed /> | ||
| <img src={ClosedWindowImg} alt="닫힌 문 이미지" className="h-28 w-23" /> | ||
| <img src={DoorImg} alt="출입문 이미지" /> | ||
| <LetterBoxItem zipCode="12E12" letterCount={90} isClosed /> | ||
| <img src={ClosedWindowImg} alt="닫힌 문 이미지" className="h-28 w-23" /> | ||
| </div> | ||
| </div> | ||
| </section> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
취향차이일거 같지만 저는 post보낼때 데이터를 따로 변수에 담아서 인자 1개로 전송하는 편입니당!
const postLetter = async (data: LetterRequest, callBack?: () => void) => {
try {
const res = await client.post('/api/letters', data);
if (callBack) callBack();
console.log(res);
} catch (error) {
console.error(error);
}
};
const LETTER_REQUEST: LetterRequest = {
receiverId: null,
parentLetterId: null,
title: letterTitle,
content: letterText,
category: category,
paperType: paperType,
fontType: fontType,
};