Skip to content
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

refactor(fe): use tanstack query for settings page #2308

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
126 changes: 63 additions & 63 deletions apps/frontend/app/(client)/(main)/settings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
'use client'

import { safeFetcherWithAuth } from '@/libs/utils'
import type { SettingsFormat } from '@/types/type'
import { valibotResolver } from '@hookform/resolvers/valibot'
import { useMutation, useQuery } from '@tanstack/react-query'
import { useRouter, useSearchParams } from 'next/navigation'
import { useEffect, useRef } from 'react'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { updateUserProfile } from '../../_libs/apis/profile'
import { profileQueries } from '../../_libs/queries/profile'
import { ConfirmModal } from './_components/ConfirmModal'
import { CurrentPwSection } from './_components/CurrentPwSection'
import { IdSection } from './_components/IdSection'
Expand All @@ -20,7 +22,6 @@ import { SaveButton } from './_components/SaveButton'
import { StudentIdSection } from './_components/StudentIdSection'
import { TopicSection } from './_components/TopicSection'
import { SettingsProvider } from './_components/context'
import type { Profile } from './_components/context'
import { useCheckPassword } from './_libs/hooks/useCheckPassword'
import { getSchema } from './_libs/schemas'
import { useConfirmNavigation } from './_libs/utils'
Expand All @@ -38,31 +39,28 @@ export default function Page() {
const updateNow = searchParams.get('updateNow')
const router = useRouter()
const bypassConfirmation = useRef<boolean>(false)
const [defaultProfileValues, setdefaultProfileValues] = useState<Profile>({
username: '',
userProfile: {
realName: ''

const { data: defaultProfileValues, isLoading } = useQuery({
...profileQueries.fetch(),
initialData: {
username: '',
userProfile: {
realName: ''
},
studentId: '',
major: ''
},
studentId: '',
major: ''
retry: false
})

// Fetch default profile values
const [majorValue, setMajorValue] = useState(defaultProfileValues.major)

useEffect(() => {
const fetchDefaultProfile = async () => {
try {
const data: Profile = await safeFetcherWithAuth.get('user').json()
setMajorValue(data.major)
setdefaultProfileValues(data)
setIsLoading(false)
} catch (error) {
console.error('Failed to fetch profile:', error)
toast.error('Failed to load profile data')
setIsLoading(false)
}
if (!isLoading && defaultProfileValues.major) {
console.log('Setting majorValue:', defaultProfileValues.major)
setMajorValue(defaultProfileValues.major)
Comment on lines +59 to +61
Copy link
Contributor

@eunnbi eunnbi Feb 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!isLoading && defaultProfileValues.major) {
console.log('Setting majorValue:', defaultProfileValues.major)
setMajorValue(defaultProfileValues.major)
if (defaultProfileValues.major) {
setMajorValue(defaultProfileValues.major)

console.log 지워주세요!
isLoading 값을 사용할 필요는 없는 것 같아요!

}
fetchDefaultProfile()
}, [])
}, [defaultProfileValues.major, isLoading])

const {
register,
Expand Down Expand Up @@ -91,6 +89,7 @@ export default function Page() {

const { isConfirmModalOpen, setIsConfirmModalOpen, confirmAction } =
useConfirmNavigation(bypassConfirmation, Boolean(updateNow))

const {
isPasswordCorrect,
newPasswordAble,
Expand All @@ -102,8 +101,6 @@ export default function Page() {
const [newPasswordShow, setNewPasswordShow] = useState<boolean>(false)
const [confirmPasswordShow, setConfirmPasswordShow] = useState<boolean>(false)
const [majorOpen, setMajorOpen] = useState<boolean>(false)
const [majorValue, setMajorValue] = useState<string>('')
const [isLoading, setIsLoading] = useState<boolean>(true)

const isPasswordsMatch = newPassword === confirmPassword && newPassword !== ''
const saveAblePassword: boolean =
Expand All @@ -121,53 +118,56 @@ export default function Page() {
(!newPassword && !confirmPassword))
const saveAbleUpdateNow =
Boolean(studentId) && majorValue !== 'none' && !errors.studentId
// 일치 여부에 따라 New Password Input, Re-enter Password Input 창의 border 색상을 바꿈

useEffect(() => {
if (isPasswordsMatch) {
setValue('newPassword', newPassword)
setValue('confirmPassword', confirmPassword)
}
}, [isPasswordsMatch, newPassword, confirmPassword])
const onSubmit = async (data: SettingsFormat) => {
try {
// 필요 없는 필드 제외 (defaultProfileValues와 값이 같은 것들은 제외)
const updatePayload: UpdatePayload = {}
if (data.realName !== defaultProfileValues.userProfile?.realName) {
updatePayload.realName = data.realName
}
if (majorValue !== defaultProfileValues.major) {
updatePayload.major = majorValue
}
if (data.currentPassword !== 'tmppassword1') {
updatePayload.password = data.currentPassword
}
if (data.newPassword !== 'tmppassword1') {
updatePayload.newPassword = data.newPassword
}
if (updateNow && data.studentId !== '0000000000') {
updatePayload.studentId = data.studentId
}
const response = await safeFetcherWithAuth.patch('user', {
json: updatePayload
})
if (response.ok) {
toast.success('Successfully updated your information')
bypassConfirmation.current = true
setTimeout(() => {
if (updateNow) {
router.push('/')
} else {
window.location.reload()
}
}, 1500)
}
} catch (error) {
}, [isPasswordsMatch, newPassword, confirmPassword, setValue])

const { mutate } = useMutation({
mutationFn: updateUserProfile,
onError: (error) => {
console.error(error)
toast.error('Failed to update your information, Please try again')
setTimeout(() => {
window.location.reload()
}, 1500)
},
onSuccess: () => {
toast.success('Successfully updated your information')
bypassConfirmation.current = true
setTimeout(() => {
if (updateNow) {
router.push('/')
} else {
window.location.reload()
}
}, 1500)
}
})

const onSubmit = (data: SettingsFormat) => {
const updatePayload: UpdatePayload = {}

if (data.realName !== defaultProfileValues.userProfile?.realName) {
updatePayload.realName = data.realName
}
if (majorValue !== defaultProfileValues.major) {
updatePayload.major = majorValue
}
if (data.currentPassword !== 'tmppassword1') {
updatePayload.password = data.currentPassword
}
if (data.newPassword !== 'tmppassword1') {
updatePayload.newPassword = data.newPassword
}
if (updateNow && data.studentId !== '0000000000') {
updatePayload.studentId = data.studentId
}

mutate(updatePayload)
}

const resetToSubmittableValue = (
Expand All @@ -193,6 +193,7 @@ export default function Page() {

const settingsContextValue = {
defaultProfileValues,
isLoading,
passwordState: {
passwordShow,
setPasswordShow,
Expand All @@ -211,10 +212,9 @@ export default function Page() {
register,
errors
},
updateNow: Boolean(updateNow),
isLoading
updateNow: Boolean(updateNow)
//isLoading
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//isLoading

}

return (
<div className="flex w-full gap-20 py-6">
{/* Logo */}
Expand Down
22 changes: 22 additions & 0 deletions apps/frontend/app/(client)/_libs/apis/profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { safeFetcherWithAuth } from '@/libs/utils'

export interface Profile {
username: string // ID
userProfile: {
realName: string
}
studentId: string
major: string
}

export const fetchUserProfile = async (): Promise<Profile> => {
return await safeFetcherWithAuth.get('user').json()
}

export const updateUserProfile = async (
updatePayload: Partial<Profile & { password?: string; newPassword?: string }>
): Promise<Response> => {
return await safeFetcherWithAuth.patch('user', {
json: updatePayload
})
}
9 changes: 9 additions & 0 deletions apps/frontend/app/(client)/_libs/queries/profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { fetchUserProfile } from '../apis/profile'

export const profileQueries = {
all: () => ['userProfile'] as const,
fetch: () => ({
queryKey: profileQueries.all(),
queryFn: fetchUserProfile
})
}
Loading