Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Mine/src/components/settings/ProfileSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default function ProfileSettings({ editMode, onCancelEdit, onSave, refCan
autoFocus
onChange={(e) => setDraft({ ...draft, nickname: e.target.value })}
onBlur={() => setEditingField(null)}
className="border-b border- outlgray-100ine-none font-medium16 pb-1 bg-transparent text-gray-100"
className="border-b border-gray-100 outline-none font-medium16 pb-1 bg-transparent text-gray-100"
/>
) : (
<span
Expand Down
17 changes: 7 additions & 10 deletions Mine/src/hooks/usePostMagazine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,16 @@ export default function usePostMagazine() {
const { setToast } = useToastStore()

return useMutation({
mutationFn: async ({ topic, user_mood }: PostMagazineDto) => {
mutationFn: ({ topic, user_mood }: PostMagazineDto) => postMagazine({ topic, user_mood }),
onMutate: () => {
setToast('magazine', 'loading')
try {
const data = await postMagazine({ topic, user_mood })
setToast('magazine', 'success')
return data
} catch (error) {
setToast('magazine', 'error')
throw error
}
},
onSuccess: () => {
setToast('magazine', 'success')
queryClient.invalidateQueries({ queryKey: ['mymagazines'] })
},
onError: () => {
setToast('magazine', 'error')
},
})
}
}
61 changes: 28 additions & 33 deletions Mine/src/pages/main/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { useState, useEffect } from 'react'
import { useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import usePostMagazine from '../../hooks/usePostMagazine'
import landingBg from '../../assets/bg1.png'
import NewMagazineInput from '../../components/NewMagazineInput'
import MakingLoadingPage from './MakingLoadingPage'
import { useAuthStore } from '../../stores/auth'
import { useToastStore } from '../../stores/toastStore'
import LandingPage from '../landing/LandingPage'
import { hasBlockedWord } from '../../utils/blockedWords'
import HarmfulKeywordModal from '../../components/common/HarmfulKeywordModal'
Expand All @@ -17,45 +16,41 @@ export default function MainPage() {
const [userMood, setUserMood] = useState('')
const [isModalOpen, setIsModalOpen] = useState(false)
const { isLoggedIn } = useAuthStore()
const { setToast } = useToastStore()
const navigate = useNavigate()

const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

useEffect(() => {
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current) // 화면이 닫히면 타이머 폭파!
}
}
}, [])

const handleSend = () => {
const currentText = topic.trim()
if (!currentText) return
if (hasBlockedWord(currentText)) {
const trimmedTopic = topic.trim()
if (!trimmedTopic) return
if (hasBlockedWord(trimmedTopic)) {
setIsModalOpen(true)
return // 여기서 함수를 끝내버려서 백엔드로 넘어가지 않게 막습니다!
}
if (isPending) return
postMagazineMutation.mutate({ topic: currentText, user_mood: userMood })
}

useEffect(() => {
if (postMagazineMutation.isPending) {
setToast('magazine', 'loading')
} else if (postMagazineMutation.isSuccess) {
setToast('magazine', 'success')

// 성공 토스트를 1.5초간 보여준 후 매거진 상세 페이지로 부드럽게 이동
setTimeout(() => {
// 백엔드 응답(data) 자체가 ID이거나 객체 내부에 있는 경우 모두 대응
const responseData = postMagazineMutation.data
const newMagazineId = responseData?.magazineId || responseData
if (newMagazineId) navigate(`/${newMagazineId}`)
else navigate('/explore')
}, 1500)
} else if (postMagazineMutation.isError) {
setToast('magazine', 'error')
}
}, [
postMagazineMutation.isPending,
postMagazineMutation.isSuccess,
postMagazineMutation.isError,
postMagazineMutation.data,
navigate,
setToast,
])
// 💡 핵심 수정: mutate 함수 두 번째 인자로 옵션 객체를 넘깁니다!
postMagazineMutation.mutate(
{ topic: trimmedTopic, user_mood: userMood },
{
// API 통신이 "딱 한 번" 성공했을 때만 이 코드가 실행됩니다. (useEffect 버그 해결!)
onSuccess: (data) => {
timerRef.current = setTimeout(() => {
const newMagazineId = data?.magazineId || data
if (newMagazineId) navigate(`/${newMagazineId}`)
}, 1500)
},
}
)
}

if (!isLoggedIn) return <LandingPage />

Expand Down
2 changes: 1 addition & 1 deletion Mine/src/types/magazine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type Section = {
heading: string
thumbnailUrl: string
paragraphs: Paragraph[]
displayOrder: 0
displayOrder: number
sourceUrl: string
sectionId: number
}
Expand Down
Loading