Skip to content

Commit 9fc534a

Browse files
committed
design:애니메이션 요소, 테마 제외한 퍼블리싱 완료
1 parent 99896f5 commit 9fc534a

21 files changed

+659
-130
lines changed

src/pages/Write/CategorySelect.tsx

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,94 @@
1-
export default function CategorySelect() {
1+
import { useState } from 'react';
2+
import { Link } from 'react-router';
3+
4+
import useWrite from '@/stores/writeStore';
5+
6+
import CategoryList from './components/CategoryList';
7+
import ResultLetter from './components/ResultLetter';
8+
import WritePageButton from './components/WritePageButton';
9+
import { T_prev_letter, T_step } from './write';
10+
11+
export default function CategorySelect({
12+
setStep,
13+
prevLetter,
14+
}: {
15+
setStep: React.Dispatch<React.SetStateAction<T_step>>;
16+
prevLetter: T_prev_letter;
17+
}) {
18+
const [send, setSend] = useState<boolean>(false);
19+
20+
const stamp = useWrite((state) => state.stamp);
221
return (
3-
<div>
4-
<div className="mt-25 flex justify-center">
5-
<span className="body-b rounded-full bg-white px-6 py-4">어떤 답장을 받고 싶나요?</span>
22+
<>
23+
<div className="flex h-full min-h-[calc(100vh-40px)] w-full flex-col items-center">
24+
<div className="absolute right-5">
25+
{!send && !prevLetter && (
26+
<WritePageButton
27+
text="이전 단계"
28+
onClick={() => {
29+
setStep('edit');
30+
}}
31+
bgColor="white"
32+
/>
33+
)}
34+
</div>
35+
36+
{send || prevLetter ? (
37+
<span className="body-b text-gray-60 mt-15 rounded-full bg-white px-6 py-4">
38+
편지 작성이 완료 되었어요!
39+
</span>
40+
) : (
41+
<span className="body-b text-gray-60 mt-15 rounded-full bg-white px-6 py-4">
42+
어떤 답장을 받고 싶나요?
43+
</span>
44+
)}
45+
46+
{prevLetter && (
47+
<div className="mt-25 flex w-full max-w-[300px] flex-col items-center gap-5">
48+
<ResultLetter stampName="답변자" />
49+
<div className="flex flex-col items-center">
50+
<span className="body-sb text-gray-60">작성하신 편지는</span>
51+
<span className="body-sb text-gray-60">
52+
<span>{'00'}시간 </span>
53+
<span>{'00'}</span>
54+
<span>{'00'}초 후에 도착합니다.</span>
55+
</span>
56+
</div>
57+
</div>
58+
)}
59+
60+
{send && (
61+
<div className="mt-25 flex w-full max-w-[300px] flex-col items-center gap-5">
62+
<ResultLetter stampName={stamp!} />
63+
<span className="body-sb text-gray-60">두근두근! 답장이 언제 올까요?</span>
64+
</div>
65+
)}
66+
67+
{!send && !prevLetter && <CategoryList />}
68+
69+
{send || prevLetter ? (
70+
<Link
71+
to={'/'}
72+
className="bg-primary-3 body-m mt-auto flex h-10 w-[280px] cursor-pointer items-center justify-center rounded-lg"
73+
>
74+
홈으로 돌아가기
75+
</Link>
76+
) : (
77+
<div
78+
role="button"
79+
className="bg-primary-3 body-m mt-auto flex h-10 w-[280px] cursor-pointer items-center justify-center rounded-lg"
80+
onClick={() => {
81+
if (stamp) {
82+
setSend(true);
83+
} else {
84+
alert('우표 선택을 해주세요');
85+
}
86+
}}
87+
>
88+
편지 전송
89+
</div>
90+
)}
691
</div>
7-
</div>
92+
</>
893
);
994
}

src/pages/Write/FontOption.tsx

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/pages/Write/LetterEditor.tsx

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,99 @@
11
import { useRef } from 'react';
2+
import { twMerge } from 'tailwind-merge';
3+
4+
import useWrite from '@/stores/writeStore';
25

36
import WritePageButton from './components/WritePageButton';
47
import OptionSlide from './OptionSlide';
8+
import { T_prev_letter, T_step } from './write';
59

6-
export default function LetterEditor() {
10+
export default function LetterEditor({
11+
setStep,
12+
prevLetter,
13+
}: {
14+
setStep: React.Dispatch<React.SetStateAction<T_step>>;
15+
prevLetter: T_prev_letter;
16+
}) {
17+
const titleRef = useRef<HTMLInputElement>(null);
718
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
819

20+
const font = useWrite((state) => state.font);
21+
22+
const letterTitle = useWrite((state) => state.letterTitle);
23+
const setLetterTitle = useWrite((state) => state.setLetterTitle);
24+
25+
const letterText = useWrite((state) => state.letterText);
26+
const setLetterText = useWrite((state) => state.setLetterText);
27+
28+
const editorStyle = twMerge(
29+
`body-r basic-theme h-auto w-full px-6 focus:outline-none`,
30+
`${font}`,
31+
);
32+
933
const handleResizeHeight = () => {
1034
if (textareaRef.current !== null) {
1135
textareaRef.current.style.height = 'auto'; //height 초기화
12-
textareaRef.current.style.height = textareaRef.current.scrollHeight + 'px';
36+
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
1337
}
1438
};
39+
1540
return (
16-
<>
17-
{/* <OptionSlide /> */}
18-
<div className="flex min-h-full w-full justify-end gap-3">
19-
<WritePageButton
20-
text="연락 끊기"
21-
onClick={() => {
22-
console.log('연락 끊기');
23-
}}
24-
/>
25-
<WritePageButton
26-
text="작성 완료"
27-
onClick={() => {
28-
console.log('작성 완료');
29-
}}
30-
/>
41+
<div className="mb-12">
42+
<OptionSlide prevLetter={prevLetter} />
43+
<div className="absolute right-5">
44+
{prevLetter ? (
45+
<WritePageButton
46+
text="답장 전송"
47+
onClick={() => {
48+
if (letterTitle.trim() !== '' && letterText.trim() !== '') {
49+
setStep('category');
50+
} else {
51+
alert('편지 제목, 내용이 작성되었는지 확인해주세요');
52+
}
53+
}}
54+
/>
55+
) : (
56+
<WritePageButton
57+
text="다음 단계"
58+
onClick={() => {
59+
if (letterTitle.trim() !== '' && letterText.trim() !== '') {
60+
setStep('category');
61+
} else {
62+
alert('편지 제목, 내용이 작성되었는지 확인해주세요');
63+
}
64+
}}
65+
/>
66+
)}
3167
</div>
3268
<div className="flex flex-col gap-3 px-6">
33-
<div className="body-b mt-7 flex">
69+
<div className="body-b mt-15 flex">
3470
<span>TO. </span>
3571
<span>{'12EE1'}</span>
3672
</div>
3773
<input
3874
type="text"
3975
placeholder="제목을 입력해주세요."
40-
className="body-sb placeholder:text-gray-40 placeholder:border-0 focus:outline-0"
76+
className="body-sb placeholder:text-gray-40 placeholder:border-0 focus:outline-none"
77+
onChange={() => {
78+
setLetterTitle(titleRef.current!.value!);
79+
}}
80+
ref={titleRef}
81+
value={letterTitle}
4182
/>
4283
</div>
4384
<div className="mt-9">
4485
<textarea
45-
rows={20}
46-
className="body-r basic-theme h-auto w-full px-6 focus:outline-none"
86+
rows={18}
87+
className={editorStyle}
4788
placeholder="클릭해서 내용을 작성하세요"
48-
onChange={handleResizeHeight}
89+
onChange={() => {
90+
handleResizeHeight();
91+
setLetterText(textareaRef.current!.value!);
92+
}}
4993
ref={textareaRef}
94+
value={letterText}
5095
></textarea>
5196
</div>
52-
</>
97+
</div>
5398
);
5499
}

src/pages/Write/OptionSlide.tsx

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,85 @@
1-
import { Component, useRef } from 'react';
2-
import FontOption from './FontOption';
3-
import PreviousLetterOption from './PreviousLetterOption';
1+
import { useRef, useState } from 'react';
2+
import { twMerge } from 'tailwind-merge';
3+
4+
import FontOption from './components/FontOption';
5+
import PreviousLetterOption from './components/PreviousLetterOption';
6+
import ThemeOption from './components/ThemeOption';
47
import WritePageButton from './components/WritePageButton';
8+
import { T_option, T_prev_letter } from './write';
9+
10+
function OptionSlide({ prevLetter }: { prevLetter: T_prev_letter }) {
11+
const [clicked, setClicked] = useState<T_option>(null);
12+
const [slideActive, setSlideActive] = useState<boolean>(false);
13+
const buttonTitle = ['편지지', '글꼴', '이전 편지 내용'];
14+
15+
const headRef = useRef<HTMLDivElement>(null);
16+
17+
const slideStyle = twMerge(
18+
`bg-primary-3 fixed bottom-0 left-[50%] flex w-full max-w-[600px] translate-x-[-50%] flex-col rounded-t-[20px] translate-y-[calc(100%-${headRef.current?.offsetHeight}px)] duration-300`,
19+
`${slideActive && 'translate-y-[0]'}`,
20+
);
21+
// 슬라이드 계산부터 시작
522

6-
function OptionSlide() {
7-
const letterRef = useRef<Component>(null);
823
return (
9-
<div className="bg-primary-3 absolute bottom-0 left-0 flex h-110 w-full flex-col rounded-t-[20px]">
10-
<div className="border-primary-1 flex items-center justify-between border-b-2 px-4 pt-6 pb-4">
24+
<div className={slideStyle}>
25+
<div
26+
className="border-primary-1 flex cursor-pointer items-center justify-between border-b-2 px-4 pt-6 pb-4"
27+
ref={headRef}
28+
>
1129
<div className="bg-primary-1 absolute top-3 left-[50%] h-[3px] w-7.5 translate-x-[-50%] translate-y-[-50%]"></div>
1230
<div className="flex gap-2">
13-
<WritePageButton text="편지지" bgColor="white" rounded="lg" />
14-
<WritePageButton text="글꼴" bgColor="white" rounded="lg" />
31+
<WritePageButton
32+
text={buttonTitle[0]}
33+
bgColor="white"
34+
rounded="lg"
35+
clicked={clicked}
36+
onClick={() => {
37+
if (clicked !== buttonTitle[0]) {
38+
setClicked('편지지');
39+
setSlideActive(() => true);
40+
} else {
41+
setClicked(null);
42+
setSlideActive(() => false);
43+
}
44+
}}
45+
/>
46+
<WritePageButton
47+
text={buttonTitle[1]}
48+
bgColor="white"
49+
rounded="lg"
50+
clicked={clicked}
51+
onClick={() => {
52+
if (clicked !== buttonTitle[1]) {
53+
setClicked('글꼴');
54+
setSlideActive(() => true);
55+
} else {
56+
setClicked(null);
57+
setSlideActive(() => false);
58+
}
59+
}}
60+
/>
1561
</div>
16-
<WritePageButton text="이전 편지 내용" bgColor="white" rounded="lg" />
17-
</div>
18-
<div className="flex w-full flex-col gap-3 px-4 pt-3 pb-[30px]">
19-
{/* <ThemeOption /> */}
20-
{/* <FontOption /> */}
21-
<PreviousLetterOption />
62+
{prevLetter && (
63+
<WritePageButton
64+
text={buttonTitle[2]}
65+
bgColor="white"
66+
rounded="lg"
67+
clicked={clicked}
68+
onClick={() => {
69+
if (clicked !== buttonTitle[2]) {
70+
setClicked('이전 편지 내용');
71+
setSlideActive(() => true);
72+
} else {
73+
setClicked(null);
74+
setSlideActive(() => false);
75+
}
76+
}}
77+
/>
78+
)}
2279
</div>
80+
{clicked === '편지지' && <ThemeOption />}
81+
{clicked === '글꼴' && <FontOption />}
82+
{clicked === '이전 편지 내용' && <PreviousLetterOption prevLetter={prevLetter} />}
2383
</div>
2484
);
2585
}

src/pages/Write/PreviousLetterOption.tsx

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)