From 51b2151c704b83f123c125346f929f0d36e91c9e Mon Sep 17 00:00:00 2001 From: Hyeonjun0527 Date: Mon, 9 Feb 2026 01:25:01 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20Clarity=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B7=B8=EB=A3=B9=20=EC=8A=A4=ED=84=B0=EB=94=94=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=8F=BC=20=EC=B4=88=EA=B8=B0=EA=B0=92=20=EC=95=88?= =?UTF-8?q?=EC=A0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서버 레이아웃의 Clarity.init()를 클라이언트 전용 컴포넌트로 이동 - service/landing 레이아웃에 ClarityInit 적용 - edit 모드에서 데이터 로딩 전 GroupStudyForm 마운트 방지 - phone verification store의 persist partialize/onRehydrateStorage 타입 명시 - 전화번호 인증 동기화 시 memberId 저장/반영 로직 보강 --- src/app/(landing)/layout.tsx | 17 ++++- src/app/(service)/layout.tsx | 19 +++++- src/components/analytics/clarity-init.tsx | 29 +++++++++ .../phone-verification/model/store.ts | 65 +++++++++++++++++++ .../model/use-phone-auth-mutation.ts | 15 +++++ .../model/use-phone-verification-status.ts | 25 +++++++ .../study/group/ui/group-study-form-modal.tsx | 36 +++++++--- 7 files changed, 196 insertions(+), 10 deletions(-) create mode 100644 src/components/analytics/clarity-init.tsx diff --git a/src/app/(landing)/layout.tsx b/src/app/(landing)/layout.tsx index e59c25bd..047b43cc 100644 --- a/src/app/(landing)/layout.tsx +++ b/src/app/(landing)/layout.tsx @@ -1,10 +1,10 @@ import '../global.css'; -import Clarity from '@microsoft/clarity'; import { GoogleTagManager } from '@next/third-parties/google'; import { clsx } from 'clsx'; import type { Metadata } from 'next'; import localFont from 'next/font/local'; +import ClarityInit from '@/components/analytics/clarity-init'; import PageViewTracker from '@/components/analytics/page-view-tracker'; import MainProvider from '@/providers'; import { getOrganizationSchema, getWebsiteSchema } from '@/utils/seo'; @@ -61,11 +61,19 @@ export default async function LandingPageLayout({ }: Readonly<{ children: React.ReactNode; }>) { +<<<<<<< Updated upstream const initialAccessToken = await getServerCookie('accessToken'); if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { Clarity.init(CLARITY_PROJECT_ID); } +||||||| Stash base + if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { + Clarity.init(CLARITY_PROJECT_ID); + } + +======= +>>>>>>> Stashed changes const organizationSchema = getOrganizationSchema(); const websiteSchema = getWebsiteSchema(); @@ -93,7 +101,14 @@ export default async function LandingPageLayout({ +<<<<<<< Updated upstream +||||||| Stash base + +======= + + +>>>>>>> Stashed changes
{/** 1400 + 48*2 패딩 양옆 48로 임의적용 */} diff --git a/src/app/(service)/layout.tsx b/src/app/(service)/layout.tsx index fa8b7e2b..d3d76d74 100644 --- a/src/app/(service)/layout.tsx +++ b/src/app/(service)/layout.tsx @@ -1,11 +1,11 @@ import '../global.css'; -import Clarity from '@microsoft/clarity'; import { GoogleTagManager } from '@next/third-parties/google'; import { clsx } from 'clsx'; import type { Metadata } from 'next'; import localFont from 'next/font/local'; import React from 'react'; +import ClarityInit from '@/components/analytics/clarity-init'; import PageViewTracker from '@/components/analytics/page-view-tracker'; import MainProvider from '@/providers'; import { getServerCookie } from '@/utils/server-cookie'; @@ -33,16 +33,33 @@ export default async function ServiceLayout({ }: Readonly<{ children: React.ReactNode; }>) { +<<<<<<< Updated upstream const initialAccessToken = await getServerCookie('accessToken'); if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { Clarity.init(CLARITY_PROJECT_ID); } +||||||| Stash base + if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { + Clarity.init(CLARITY_PROJECT_ID); + } + +======= +>>>>>>> Stashed changes return ( {GTM_ID && } +<<<<<<< Updated upstream +||||||| Stash base + + +======= + + + +>>>>>>> Stashed changes
diff --git a/src/components/analytics/clarity-init.tsx b/src/components/analytics/clarity-init.tsx new file mode 100644 index 00000000..0224ef77 --- /dev/null +++ b/src/components/analytics/clarity-init.tsx @@ -0,0 +1,29 @@ +'use client'; + +import Clarity from '@microsoft/clarity'; +import { useEffect } from 'react'; +import type { ReactElement } from 'react'; + +declare global { + interface Window { + __clarityInitialized?: boolean; + } +} + +interface ClarityInitProps { + projectId?: string; +} + +export default function ClarityInit({ + projectId, +}: ClarityInitProps): ReactElement { + useEffect(() => { + if (!projectId || typeof window === 'undefined') return; + if (window.__clarityInitialized) return; + + Clarity.init(projectId); + window.__clarityInitialized = true; + }, [projectId]); + + return <>; +} diff --git a/src/features/phone-verification/model/store.ts b/src/features/phone-verification/model/store.ts index 32eb3afd..87cbe049 100644 --- a/src/features/phone-verification/model/store.ts +++ b/src/features/phone-verification/model/store.ts @@ -4,39 +4,90 @@ import { persist } from 'zustand/middleware'; interface PhoneVerificationState { isVerified: boolean; phoneNumber: string | null; +<<<<<<< Updated upstream verifiedAt: string | null; memberId: number | null; hasHydrated: boolean; setVerified: (phoneNumber: string, memberId?: number) => void; +||||||| Stash base + verifiedAt: Date | null; + setVerified: (phoneNumber: string) => void; +======= + verifiedAt: string | null; + memberId: number | null; + hasHydrated: boolean; + setVerified: (phoneNumber: string, memberId?: number) => void; + setHasHydrated: (hasHydrated: boolean) => void; +>>>>>>> Stashed changes reset: () => void; setHasHydrated: (hasHydrated: boolean) => void; } +type PersistedPhoneVerificationState = Pick< + PhoneVerificationState, + 'isVerified' | 'phoneNumber' | 'verifiedAt' | 'memberId' +>; + export const usePhoneVerificationStore = create()( persist( (set) => ({ isVerified: false, +<<<<<<< Updated upstream phoneNumber: null as string | null, verifiedAt: null as string | null, memberId: null as number | null, hasHydrated: false, setVerified: (phoneNumber, memberId) => set({ +||||||| Stash base + phoneNumber: '', + verifiedAt: new Date(), + setVerified: (phoneNumber) => + set({ +======= + phoneNumber: null, + verifiedAt: null, + memberId: null, + hasHydrated: false, + setVerified: (phoneNumber, memberId) => + set((state) => ({ +>>>>>>> Stashed changes isVerified: true, phoneNumber, +<<<<<<< Updated upstream verifiedAt: new Date().toISOString(), ...(memberId !== undefined ? { memberId } : {}), +||||||| Stash base + verifiedAt: new Date(), +======= + verifiedAt: new Date().toISOString(), + memberId: memberId ?? state.memberId, + })), + setHasHydrated: (hasHydrated) => + set({ + hasHydrated, +>>>>>>> Stashed changes }), reset: () => set({ isVerified: false, +<<<<<<< Updated upstream phoneNumber: null as string | null, verifiedAt: null as string | null, memberId: null as number | null, +||||||| Stash base + phoneNumber: null, + verifiedAt: null, +======= + phoneNumber: null, + verifiedAt: null, + memberId: null, +>>>>>>> Stashed changes }), setHasHydrated: (hasHydrated) => set({ hasHydrated }), }), { +<<<<<<< Updated upstream name: 'phone-verification-storage', partialize: (state) => ({ isVerified: state.isVerified, @@ -47,6 +98,20 @@ export const usePhoneVerificationStore = create()( onRehydrateStorage: () => (state) => { state?.setHasHydrated(true); }, +||||||| Stash base + name: 'phone-verification-storage', // 로컬 스토리지에 저장 +======= + name: 'phone-verification-storage', + partialize: (state): PersistedPhoneVerificationState => ({ + isVerified: state.isVerified, + phoneNumber: state.phoneNumber, + verifiedAt: state.verifiedAt, + memberId: state.memberId, + }), + onRehydrateStorage: () => (state) => { + state?.setHasHydrated(true); + }, +>>>>>>> Stashed changes }, ), ); diff --git a/src/features/phone-verification/model/use-phone-auth-mutation.ts b/src/features/phone-verification/model/use-phone-auth-mutation.ts index 2e0b0a9b..46c7ca64 100644 --- a/src/features/phone-verification/model/use-phone-auth-mutation.ts +++ b/src/features/phone-verification/model/use-phone-auth-mutation.ts @@ -39,12 +39,27 @@ export const useVerifyPhoneCodeMutation = (memberId?: number) => { mutationFn: verifyPhoneCode, onSuccess: async (data, variables) => { if (data.success) { +<<<<<<< Updated upstream // 현재 사용자의 memberId 가져오기 (쿠키에서) +||||||| Stash base + // 인증 상태 저장 + setVerified(variables.phoneNumber); + + // 현재 사용자의 memberId 가져오기 (쿠키에서) +======= +>>>>>>> Stashed changes const currentMemberId = memberId ?? Number(getCookie('memberId')); +<<<<<<< Updated upstream // 인증 상태 저장 (memberId 포함) setVerified(variables.phoneNumber, currentMemberId || undefined); +||||||| Stash base +======= + // 인증 상태 저장 + setVerified(variables.phoneNumber, currentMemberId || undefined); + +>>>>>>> Stashed changes // 프로필 정보 쿼리키 갱신 if (currentMemberId) { await queryClient.invalidateQueries({ diff --git a/src/features/phone-verification/model/use-phone-verification-status.ts b/src/features/phone-verification/model/use-phone-verification-status.ts index c542c2e4..b11cab62 100644 --- a/src/features/phone-verification/model/use-phone-verification-status.ts +++ b/src/features/phone-verification/model/use-phone-verification-status.ts @@ -144,6 +144,7 @@ export function usePhoneVerificationStatus( useEffect(() => { if (isProfileLoading || !userProfile || !memberId) return; +<<<<<<< Updated upstream const current = usePhoneVerificationStore.getState(); if (resolvedServerIsVerified) { @@ -154,6 +155,17 @@ export function usePhoneVerificationStatus( current.phoneNumber !== serverPhoneNumber ) { store.setVerified(serverPhoneNumber ?? '', memberId); +||||||| Stash base + if (serverPhoneNumber) { + // 서버에 전화번호가 있으면 Zustand도 동기화 + if (!zustandIsVerified || zustandPhoneNumber !== serverPhoneNumber) { + setVerified(serverPhoneNumber); +======= + if (serverPhoneNumber) { + // 서버에 전화번호가 있으면 Zustand도 동기화 + if (!zustandIsVerified || zustandPhoneNumber !== serverPhoneNumber) { + setVerified(serverPhoneNumber, memberId ?? undefined); +>>>>>>> Stashed changes } } else { // 서버가 미인증 → 같은 유저 캐시 제거 @@ -167,8 +179,21 @@ export function usePhoneVerificationStatus( userProfile, memberId, serverIsVerified, +<<<<<<< Updated upstream serverPhoneNumber, resolvedServerIsVerified, +||||||| Stash base + zustandIsVerified, + zustandPhoneNumber, + setVerified, + reset, +======= + zustandIsVerified, + zustandPhoneNumber, + setVerified, + reset, + memberId, +>>>>>>> Stashed changes ]); // memberId 변경(계정 전환 / 로그아웃) 시 스토어 리셋 diff --git a/src/features/study/group/ui/group-study-form-modal.tsx b/src/features/study/group/ui/group-study-form-modal.tsx index f38a8e63..1d1392dc 100644 --- a/src/features/study/group/ui/group-study-form-modal.tsx +++ b/src/features/study/group/ui/group-study-form-modal.tsx @@ -99,8 +99,14 @@ export default function GroupStudyFormModal({ }; const refineStudyDetail = (value: GroupStudyFullResponseDto) => { +<<<<<<< Updated upstream if (isGroupStudyLoading) return; +||||||| Stash base + if (isLoading) return; + +======= +>>>>>>> Stashed changes const refinedClassification = value.basicInfo?.classification ?? classification; const originalType = value.basicInfo?.type; @@ -232,6 +238,11 @@ export default function GroupStudyFormModal({ } }, [open, mode]); + const editDefaultValues = + mode === 'edit' && groupStudyInfo + ? refineStudyDetail(groupStudyInfo) + : null; + return ( <> - + {mode === 'create' && ( + + )} + {mode === 'edit' && isLoading && ( + + 스터디 정보를 불러오는 중입니다... + + )} + {mode === 'edit' && !isLoading && editDefaultValues && ( + + )} From b90519e35f1c3bc455f020154b2d79c9dcc06de3 Mon Sep 17 00:00:00 2001 From: Hyeonjun0527 Date: Mon, 9 Feb 2026 01:39:52 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20Clarity=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B7=B8=EB=A3=B9=20=EC=8A=A4=ED=84=B0=EB=94=94=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=ED=8F=BC=20=EC=B4=88=EA=B8=B0=EA=B0=92=20=EC=95=88?= =?UTF-8?q?=EC=A0=95=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 서버 레이아웃의 Clarity.init()를 클라이언트 전용 컴포넌트로 이동 - service/landing 레이아웃에 ClarityInit 적용 - edit 모드에서 데이터 로딩 전 GroupStudyForm 마운트 방지 - phone verification store의 persist partialize/onRehydrateStorage 타입 명시 - 전화번호 인증 동기화 시 memberId 저장/반영 로직 보강 fix: 타입체크 --- src/app/(landing)/layout.tsx | 18 ------ src/app/(service)/layout.tsx | 19 ------ src/components/ui/toast.tsx | 7 ++- .../phone-verification/model/store.ts | 60 ------------------- .../model/use-phone-auth-mutation.ts | 17 ------ .../model/use-phone-verification-status.ts | 55 +++++------------ .../study/group/ui/group-study-form-modal.tsx | 14 +---- 7 files changed, 21 insertions(+), 169 deletions(-) diff --git a/src/app/(landing)/layout.tsx b/src/app/(landing)/layout.tsx index 047b43cc..296f2063 100644 --- a/src/app/(landing)/layout.tsx +++ b/src/app/(landing)/layout.tsx @@ -61,19 +61,7 @@ export default async function LandingPageLayout({ }: Readonly<{ children: React.ReactNode; }>) { -<<<<<<< Updated upstream const initialAccessToken = await getServerCookie('accessToken'); - if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { - Clarity.init(CLARITY_PROJECT_ID); - } - -||||||| Stash base - if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { - Clarity.init(CLARITY_PROJECT_ID); - } - -======= ->>>>>>> Stashed changes const organizationSchema = getOrganizationSchema(); const websiteSchema = getWebsiteSchema(); @@ -101,14 +89,8 @@ export default async function LandingPageLayout({ -<<<<<<< Updated upstream -||||||| Stash base - -======= - ->>>>>>> Stashed changes
{/** 1400 + 48*2 패딩 양옆 48로 임의적용 */} diff --git a/src/app/(service)/layout.tsx b/src/app/(service)/layout.tsx index d3d76d74..fc5d3bd8 100644 --- a/src/app/(service)/layout.tsx +++ b/src/app/(service)/layout.tsx @@ -33,33 +33,14 @@ export default async function ServiceLayout({ }: Readonly<{ children: React.ReactNode; }>) { -<<<<<<< Updated upstream const initialAccessToken = await getServerCookie('accessToken'); - if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { - Clarity.init(CLARITY_PROJECT_ID); - } -||||||| Stash base - if (typeof window !== 'undefined' && CLARITY_PROJECT_ID) { - Clarity.init(CLARITY_PROJECT_ID); - } - -======= ->>>>>>> Stashed changes return ( {GTM_ID && } -<<<<<<< Updated upstream -||||||| Stash base - - -======= - - ->>>>>>> Stashed changes
diff --git a/src/components/ui/toast.tsx b/src/components/ui/toast.tsx index ffc932de..9eaba48b 100644 --- a/src/components/ui/toast.tsx +++ b/src/components/ui/toast.tsx @@ -5,6 +5,8 @@ import React, { useEffect, useState } from 'react'; import { createPortal } from 'react-dom'; import { cn } from '@/components/ui/(shadcn)/lib/utils'; +const EXIT_DURATION = 200; + interface ToastProps { message: string; isVisible: boolean; @@ -22,7 +24,6 @@ export default function Toast({ }: ToastProps) { const [isRendered, setIsRendered] = useState(isVisible); const [isExiting, setIsExiting] = useState(false); - const exitDuration = 200; useEffect(() => { if (isVisible) { @@ -40,11 +41,11 @@ export default function Toast({ const timer = setTimeout(() => { setIsRendered(false); setIsExiting(false); - }, exitDuration); + }, EXIT_DURATION); return () => clearTimeout(timer); } - }, [isVisible, duration, onClose]); + }, [isVisible, duration, onClose, isRendered]); if (!isRendered) return null; if (typeof document === 'undefined') return null; diff --git a/src/features/phone-verification/model/store.ts b/src/features/phone-verification/model/store.ts index 87cbe049..74894aae 100644 --- a/src/features/phone-verification/model/store.ts +++ b/src/features/phone-verification/model/store.ts @@ -4,21 +4,10 @@ import { persist } from 'zustand/middleware'; interface PhoneVerificationState { isVerified: boolean; phoneNumber: string | null; -<<<<<<< Updated upstream verifiedAt: string | null; memberId: number | null; hasHydrated: boolean; setVerified: (phoneNumber: string, memberId?: number) => void; -||||||| Stash base - verifiedAt: Date | null; - setVerified: (phoneNumber: string) => void; -======= - verifiedAt: string | null; - memberId: number | null; - hasHydrated: boolean; - setVerified: (phoneNumber: string, memberId?: number) => void; - setHasHydrated: (hasHydrated: boolean) => void; ->>>>>>> Stashed changes reset: () => void; setHasHydrated: (hasHydrated: boolean) => void; } @@ -32,75 +21,27 @@ export const usePhoneVerificationStore = create()( persist( (set) => ({ isVerified: false, -<<<<<<< Updated upstream phoneNumber: null as string | null, verifiedAt: null as string | null, memberId: null as number | null, hasHydrated: false, - setVerified: (phoneNumber, memberId) => - set({ -||||||| Stash base - phoneNumber: '', - verifiedAt: new Date(), - setVerified: (phoneNumber) => - set({ -======= - phoneNumber: null, - verifiedAt: null, - memberId: null, - hasHydrated: false, setVerified: (phoneNumber, memberId) => set((state) => ({ ->>>>>>> Stashed changes isVerified: true, phoneNumber, -<<<<<<< Updated upstream - verifiedAt: new Date().toISOString(), - ...(memberId !== undefined ? { memberId } : {}), -||||||| Stash base - verifiedAt: new Date(), -======= verifiedAt: new Date().toISOString(), memberId: memberId ?? state.memberId, })), - setHasHydrated: (hasHydrated) => - set({ - hasHydrated, ->>>>>>> Stashed changes - }), reset: () => set({ isVerified: false, -<<<<<<< Updated upstream phoneNumber: null as string | null, verifiedAt: null as string | null, memberId: null as number | null, -||||||| Stash base - phoneNumber: null, - verifiedAt: null, -======= - phoneNumber: null, - verifiedAt: null, - memberId: null, ->>>>>>> Stashed changes }), setHasHydrated: (hasHydrated) => set({ hasHydrated }), }), { -<<<<<<< Updated upstream - name: 'phone-verification-storage', - partialize: (state) => ({ - isVerified: state.isVerified, - phoneNumber: state.phoneNumber, - verifiedAt: state.verifiedAt, - memberId: state.memberId, - }), - onRehydrateStorage: () => (state) => { - state?.setHasHydrated(true); - }, -||||||| Stash base - name: 'phone-verification-storage', // 로컬 스토리지에 저장 -======= name: 'phone-verification-storage', partialize: (state): PersistedPhoneVerificationState => ({ isVerified: state.isVerified, @@ -111,7 +52,6 @@ export const usePhoneVerificationStore = create()( onRehydrateStorage: () => (state) => { state?.setHasHydrated(true); }, ->>>>>>> Stashed changes }, ), ); diff --git a/src/features/phone-verification/model/use-phone-auth-mutation.ts b/src/features/phone-verification/model/use-phone-auth-mutation.ts index 46c7ca64..a3b87aae 100644 --- a/src/features/phone-verification/model/use-phone-auth-mutation.ts +++ b/src/features/phone-verification/model/use-phone-auth-mutation.ts @@ -39,27 +39,10 @@ export const useVerifyPhoneCodeMutation = (memberId?: number) => { mutationFn: verifyPhoneCode, onSuccess: async (data, variables) => { if (data.success) { -<<<<<<< Updated upstream - // 현재 사용자의 memberId 가져오기 (쿠키에서) -||||||| Stash base - // 인증 상태 저장 - setVerified(variables.phoneNumber); - - // 현재 사용자의 memberId 가져오기 (쿠키에서) -======= ->>>>>>> Stashed changes const currentMemberId = memberId ?? Number(getCookie('memberId')); -<<<<<<< Updated upstream - // 인증 상태 저장 (memberId 포함) - setVerified(variables.phoneNumber, currentMemberId || undefined); - -||||||| Stash base -======= // 인증 상태 저장 setVerified(variables.phoneNumber, currentMemberId || undefined); - ->>>>>>> Stashed changes // 프로필 정보 쿼리키 갱신 if (currentMemberId) { await queryClient.invalidateQueries({ diff --git a/src/features/phone-verification/model/use-phone-verification-status.ts b/src/features/phone-verification/model/use-phone-verification-status.ts index b11cab62..adbbf79c 100644 --- a/src/features/phone-verification/model/use-phone-verification-status.ts +++ b/src/features/phone-verification/model/use-phone-verification-status.ts @@ -83,9 +83,7 @@ export function usePhoneVerificationStatus( // 서버 데이터 기반 인증 상태 계산 const serverHasIsVerified = typeof userProfile?.isVerified === 'boolean'; - const serverIsVerified = serverHasIsVerified - ? userProfile!.isVerified - : false; + const serverIsVerified = serverHasIsVerified ? userProfile.isVerified : false; const serverPhoneNumber = userProfile?.memberProfile?.tel ?? null; // 스토어가 현재 유저 소유인지 확인 (계정 전환 대응) @@ -144,7 +142,6 @@ export function usePhoneVerificationStatus( useEffect(() => { if (isProfileLoading || !userProfile || !memberId) return; -<<<<<<< Updated upstream const current = usePhoneVerificationStore.getState(); if (resolvedServerIsVerified) { @@ -154,46 +151,22 @@ export function usePhoneVerificationStatus( current.memberId !== memberId || current.phoneNumber !== serverPhoneNumber ) { - store.setVerified(serverPhoneNumber ?? '', memberId); -||||||| Stash base - if (serverPhoneNumber) { - // 서버에 전화번호가 있으면 Zustand도 동기화 - if (!zustandIsVerified || zustandPhoneNumber !== serverPhoneNumber) { - setVerified(serverPhoneNumber); -======= - if (serverPhoneNumber) { - // 서버에 전화번호가 있으면 Zustand도 동기화 - if (!zustandIsVerified || zustandPhoneNumber !== serverPhoneNumber) { - setVerified(serverPhoneNumber, memberId ?? undefined); ->>>>>>> Stashed changes - } - } else { - // 서버가 미인증 → 같은 유저 캐시 제거 - if (current.isVerified && current.memberId === memberId) { - store.reset(); + current.setVerified(serverPhoneNumber ?? '', memberId); } + + return; + } + + // 서버가 미인증 → 같은 유저 캐시 제거 + if (current.isVerified && current.memberId === memberId) { + current.reset(); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [ isProfileLoading, userProfile, memberId, - serverIsVerified, -<<<<<<< Updated upstream - serverPhoneNumber, resolvedServerIsVerified, -||||||| Stash base - zustandIsVerified, - zustandPhoneNumber, - setVerified, - reset, -======= - zustandIsVerified, - zustandPhoneNumber, - setVerified, - reset, - memberId, ->>>>>>> Stashed changes + serverPhoneNumber, ]); // memberId 변경(계정 전환 / 로그아웃) 시 스토어 리셋 @@ -203,17 +176,17 @@ export function usePhoneVerificationStatus( prevMemberIdRef.current = memberId; if (prev !== null && prev !== memberId) { - store.reset(); + usePhoneVerificationStore.getState().reset(); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [memberId]); // 인증 완료 시 호출 — memberId를 자동 주입 const setVerified = useCallback( (phone: string) => { - store.setVerified(phone, memberId ?? undefined); + usePhoneVerificationStore + .getState() + .setVerified(phone, memberId ?? undefined); }, - // eslint-disable-next-line react-hooks/exhaustive-deps [memberId], ); diff --git a/src/features/study/group/ui/group-study-form-modal.tsx b/src/features/study/group/ui/group-study-form-modal.tsx index 1d1392dc..b485fe7e 100644 --- a/src/features/study/group/ui/group-study-form-modal.tsx +++ b/src/features/study/group/ui/group-study-form-modal.tsx @@ -99,14 +99,6 @@ export default function GroupStudyFormModal({ }; const refineStudyDetail = (value: GroupStudyFullResponseDto) => { -<<<<<<< Updated upstream - if (isGroupStudyLoading) return; - -||||||| Stash base - if (isLoading) return; - -======= ->>>>>>> Stashed changes const refinedClassification = value.basicInfo?.classification ?? classification; const originalType = value.basicInfo?.type; @@ -122,7 +114,7 @@ export default function GroupStudyFormModal({ return { classification: refinedClassification, studyLeaderParticipation: - value.basicInfo.studyLeaderParticipation ?? false, + value.basicInfo?.studyLeaderParticipation ?? false, type: refinedType, targetRoles: value.basicInfo?.targetRoles, maxMembersCount: value.basicInfo?.maxMembersCount?.toString() ?? '', @@ -267,12 +259,12 @@ export default function GroupStudyFormModal({ onSubmit={handleSubmitForm} /> )} - {mode === 'edit' && isLoading && ( + {mode === 'edit' && isGroupStudyLoading && ( 스터디 정보를 불러오는 중입니다... )} - {mode === 'edit' && !isLoading && editDefaultValues && ( + {mode === 'edit' && !isGroupStudyLoading && editDefaultValues && (