Skip to content

Commit

Permalink
feat : 일기 수정 로직 추가 (#222)
Browse files Browse the repository at this point in the history
* feat : 일기 수정 기능 추가

* feat : 일기 수정 로직 작성
  • Loading branch information
cmlim0070 authored Nov 6, 2024
1 parent 47f9b3e commit 24537ee
Show file tree
Hide file tree
Showing 17 changed files with 349 additions and 72 deletions.
13 changes: 12 additions & 1 deletion src/app/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import SignPage from '@/pages/SignPage/SignPage';
import MyPage from '@/pages/MyPage/MyPage';
import { DetailPage } from '@/pages/DetailPage';
import AccountPage from '@/pages/AccountPage/AccountPage';
import defaultApi from '@/shared/api/api';

const api = defaultApi();

const router = createBrowserRouter([
{
Expand All @@ -28,7 +31,15 @@ const router = createBrowserRouter([
},
{
path: '/diaryWrite/:date',
element: <DiaryWritePage />
element: <DiaryWritePage mode="create" />
},
{
path: '/diaryWrite/:id/edit',
element: <DiaryWritePage mode="edit" />,
loader: async ({ params }) => {
const preLoadDiary = await api.get(`/diary/${params.id}`);
return preLoadDiary.data;
}
},
{
path: '/join',
Expand Down
47 changes: 45 additions & 2 deletions src/entities/diary/diaryService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { postDiaryApi } from '@/shared/api/diary';
import { DiaryDescDataType, PostDiaryType } from '@/shared/model/diaryType';
import { postDiaryApi, putDiaryApi } from '@/shared/api/diary';
import {
DiaryDescDataType,
PostDiaryType,
putDiaryType
} from '@/shared/model/diaryType';
import { MoodDataType, MusicItem } from '../music/model/type';

export const diaryService = {
Expand All @@ -12,6 +16,15 @@ export const diaryService = {
}
},

async editDiary(diary: putDiaryType) {
try {
await putDiaryApi(diary);
return { success: true };
} catch (error) {
return { success: false, error };
}
},

formatDiaryData(
userDiaryState: DiaryDescDataType,
userEmotionState: MoodDataType,
Expand Down Expand Up @@ -40,5 +53,35 @@ export const diaryService = {
artist: selectedMusic?.artist || '',
music_id: selectedMusic?.youtubeId || ''
};
},

formatDiaryEditData(
userDiaryState: DiaryDescDataType,
userEmotionState: MoodDataType,
selectedMusic: MusicItem,
userEmail: string,
id: string
): putDiaryType {
return {
title: userDiaryState?.title || '',
content: userDiaryState?.content || '',
is_public: userDiaryState?.isPublic ?? false,
music_url: selectedMusic?.youtubeId || '',
author_email: userEmail,
mood: userEmotionState?.mood || '',
emotion: userEmotionState?.emotion || '',
sub_emotion: userEmotionState?.subEmotions
? JSON.stringify(
userEmotionState.subEmotions.filter(
(emotion) => emotion !== null && emotion.trim() !== ''
)
)
: '',
id: id || '',
music_title: selectedMusic?.title || '',
music_imgurl: selectedMusic?.thumbnailUrl || '',
artist: selectedMusic?.artist || '',
music_id: selectedMusic?.youtubeId || ''
};
}
};
8 changes: 5 additions & 3 deletions src/entities/music/model/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@ export interface gptQueryParamsType {
}

export type gptAnswerType = string[];

// TODO - 이 타입 삭제
export interface MoodDataType {
mood: ConditionType;
emotion: string | null;
subEmotions: (string | null)[];
mood: ConditionType | undefined;
emotion: string | null | undefined;
subEmotions: (string | null)[] | undefined;
}

export interface ReRecommendGptButtonProps {
Expand Down
7 changes: 4 additions & 3 deletions src/features/diary-write/emotion/ui/EmotionButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import { Emotions } from '@/shared/model/EmotionEnum';

// TODO - 초기값이 undefined로 들어오는데 null로 들어오도록 변경
export const EmotionButtonGroup: React.FC<EmotionButtonGroupProps> = ({
initialKeywords = [null, null, null, null, null],
initialKeywords,
onKeywordsChange
}) => {
const [keywords, setKeywords] =
useState<(Emotions | null)[]>(initialKeywords);
const [keywords, setKeywords] = useState<(Emotions | null)[]>(
initialKeywords || Array(5).fill(null)
);
const [activeButton, setActiveButton] = useState(0);
const [lastClicked, setLastClicked] = useState<
'keyword' | 'emotion' | null
Expand Down
6 changes: 1 addition & 5 deletions src/pages/DiaryWritePage/hooks/useDiaryForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ export const useDiaryForm = () => {
const validators = {
isDiaryValid: (diary: DiaryDescDataType | null): boolean => {
if (!diary) return false;
return Boolean(
diary.title?.trim() &&
diary.content?.trim() &&
typeof diary.isPublic === 'boolean'
);
return Boolean(diary.title?.trim() && diary.content?.trim());
},

isEmotionValid: (emotion: MoodDataType | null): boolean => {
Expand Down
5 changes: 5 additions & 0 deletions src/pages/DiaryWritePage/model/type.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { ConditionType } from '@/shared/model/conditionTypes';
import { DiaryData } from '@/shared/model/diaryType';

export interface MoodDataType {
mood: ConditionType;
emotion: string | null;
subEmotions: (string | null)[];
}

export interface DiaryWritePageProps {
mode: 'create' | 'edit';
}
138 changes: 123 additions & 15 deletions src/pages/DiaryWritePage/ui/DiaryWritePage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useNavigate, useParams } from 'react-router-dom';
import { useLoaderData, useNavigate, useParams } from 'react-router-dom';
import { useDiaryForm } from '../hooks/useDiaryForm';
import { useStepNavigation } from '../hooks/useStepNavigation';
import { useMusicRecommendation } from '../hooks/useMusicRecommendation';
Expand All @@ -17,11 +17,18 @@ import {
} from './DiaryWritePage.styled';
import { useEffect, useRef } from 'react';
import { useAuthStore } from '@/features/login/hooks/useAuthStore';
import { DiaryWritePageProps } from '../model/type';
import { DiaryType } from '@/shared/model/diaryType';
import { ConditionType } from '@/shared/model/conditionTypes';

// TODO - 이미 일기가 작성되어있는 날의 경우 수정, 삭제가 가능하도록 처리
export const DiaryWritePage = () => {
// TODO - 로직 분리
export const DiaryWritePage = ({ mode }: DiaryWritePageProps) => {
const userEmail = useAuthStore((state) => state.email);
const { date } = useParams();

const { id } = useParams();
const preLoadDiaryData = useLoaderData() as DiaryType;

const navigate = useNavigate();
const { addToast } = useToastStore();
const {
Expand All @@ -43,6 +50,66 @@ export const DiaryWritePage = () => {
const emotionRef = useRef<HTMLDivElement>(null);
const musicRef = useRef<HTMLDivElement>(null);

// 수정 모드 초기값
const initialdiary =
mode === 'edit'
? {
title: preLoadDiaryData?.title || '',
content: preLoadDiaryData?.content || '',
isPublic: preLoadDiaryData?.is_public || false
}
: {
title: '',
content: '',
isPublic: false
};

const parsedSubEmotions =
mode === 'edit' && preLoadDiaryData?.sub_emotion
? (JSON.parse(preLoadDiaryData.sub_emotion) as (string | null)[])
: [];

const initialEmotion =
mode === 'edit'
? {
mood: (preLoadDiaryData?.mood as ConditionType) || null,
emotion: preLoadDiaryData?.emotion || '',
subEmotions: parsedSubEmotions
}
: {
mood: null,
emotion: '',
subEmotions: []
};

const initialMusic =
mode === 'edit'
? {
title: preLoadDiaryData?.music_title || '',
artist: preLoadDiaryData?.artist || '',
thumbnailUrl: preLoadDiaryData?.music_imgurl || '',
youtubeId: preLoadDiaryData?.music_id || ''
}
: {
title: '',
artist: '',
thumbnailUrl: '',
youtubeId: ''
};

useEffect(() => {
setUserDiaryState(initialdiary);
setUserEmotionState(initialEmotion);
setSelectedMusic(initialMusic);
}, []);

useEffect(() => {
validators.isDiaryValid(userDiaryState);
validators.isEmotionValid(userEmotionState);
validators.isMusicValid(selectedMusic);
}, [userDiaryState, userEmotionState, selectedMusic]);

// 위젯 단계
useEffect(() => {
const scrollToRef = (ref: React.RefObject<HTMLDivElement>) => {
ref.current?.scrollIntoView({
Expand All @@ -67,10 +134,7 @@ export const DiaryWritePage = () => {
}
}, [currentStep]);

useEffect(() => {
console.log(currentStep);
}, [currentStep]);

// 제출
const handleSubmitAll = async () => {
try {
const diaryData = diaryService.formatDiaryData(
Expand All @@ -81,8 +145,6 @@ export const DiaryWritePage = () => {
date || ''
);

console.log(diaryData);

const { success, error } =
await diaryService.submitDiary(diaryData);

Expand All @@ -97,6 +159,35 @@ export const DiaryWritePage = () => {
}
};

// 수정
const handleEditSubmit = async () => {
try {
if (!id) {
throw new Error('일기 ID를 가져올 수 없어요.');
}

const diaryData = diaryService.formatDiaryEditData(
userDiaryState!,
userEmotionState!,
selectedMusic!,
userEmail,
id
);

const { success, error } = await diaryService.editDiary(diaryData);

if (success) {
addToast('일기를 수정했어요.', 'success');
navigate('/');
} else {
addToast('일기 수정에 실패했습니다.', 'error');
}
} catch (error) {
addToast('일기 수정에 실패했습니다.', 'error');
}
};

// gpt 추천
const callFetchRecommendations = async () => {
try {
await fetchRecommendations(
Expand All @@ -112,6 +203,7 @@ export const DiaryWritePage = () => {
}
};

// 다름 버튼 클릭
const handleEmotionNext = async () => {
if (!validators.isEmotionValid(userEmotionState)) {
return;
Expand All @@ -120,6 +212,18 @@ export const DiaryWritePage = () => {
callFetchRecommendations();
};

const handleButtonClick = () => {
if (!validators.isMusicValid(selectedMusic)) {
return;
}

if (mode === 'edit') {
handleEditSubmit();
} else {
handleSubmitAll();
}
};

return (
<Container>
<Section>
Expand All @@ -128,6 +232,10 @@ export const DiaryWritePage = () => {
onDiarySubmit={setUserDiaryState}
isActive={currentStep === 1}
disabled={currentStep !== 1}
initialTitle={initialdiary?.title || ''}
initialContent={initialdiary?.content || ''}
initialIsPublic={initialdiary?.isPublic || false}
editTargetDate={preLoadDiaryData?.title_date}
/>
<DisabledOverlay disabled={currentStep !== 1} />
<ButtonContainer>
Expand All @@ -153,6 +261,9 @@ export const DiaryWritePage = () => {
onMoodSelect={setUserEmotionState}
isActive={currentStep === 2}
disabled={currentStep !== 2}
initialmood={initialEmotion?.mood}
initialemotion={initialEmotion?.emotion}
initialsubemotions={initialEmotion?.subEmotions}
/>
<DisabledOverlay disabled={currentStep !== 2} />
<ButtonContainer>
Expand Down Expand Up @@ -195,6 +306,7 @@ export const DiaryWritePage = () => {
disabled={currentStep !== 3}
isLoading={isLoading}
onRecommend={callFetchRecommendations}
initialData={initialMusic}
/>
<DisabledOverlay disabled={currentStep !== 3} />
<ButtonContainer>
Expand All @@ -214,14 +326,10 @@ export const DiaryWritePage = () => {
fontSize="16px"
height="60px"
isActive={validators.isMusicValid(selectedMusic)}
onClick={() => {
if (validators.isMusicValid(selectedMusic)) {
handleSubmitAll();
}
}}
onClick={handleButtonClick}
width="200px"
>
게시하기
{mode === 'edit' ? '수정하기' : '게시하기'}
</Button>
</ButtonContainer>
</WidgetWrapper>
Expand Down
Loading

0 comments on commit 24537ee

Please sign in to comment.