diff --git a/src/components/TextField.tsx b/src/components/TextField.tsx index 6006269..dc67479 100644 --- a/src/components/TextField.tsx +++ b/src/components/TextField.tsx @@ -82,7 +82,7 @@ const Input = forwardRef( ref: Ref, ) => { const wrapperClassNames = cn( - "flex w-fit gap-1.5 border rounded-[0.375rem] border-gray-30 focus-within:border-blue-20 placeholder:text-gray-40 ", + "flex w-fit gap-1.5 border rounded-[0.375rem] border-gray-30 focus-within:border-blue-20 placeholder:text-gray-40 bg-white", { "w-full": fullWidth, "bg-gray-20 text-gray-40": disabled, @@ -136,7 +136,7 @@ const TextArea = forwardRef( ref: Ref, ) => { const wrapperClassNames = cn( - "flex w-fit gap-1.5 border rounded-[0.375rem] border-gray-30 focus-within:border-blue-20 placeholder:text-gray-40 ", + "flex w-fit gap-1.5 border rounded-[0.375rem] border-gray-30 focus-within:border-blue-20 placeholder:text-gray-40 bg-white", { "w-full": fullWidth, "bg-gray-20 text-gray-40": disabled, diff --git a/src/hooks/useUserStore.tsx b/src/hooks/useUserStore.tsx index 3e976cc..a7ae2ce 100644 --- a/src/hooks/useUserStore.tsx +++ b/src/hooks/useUserStore.tsx @@ -16,6 +16,7 @@ interface UserState { user: User | null; token: string | null; isLoggedIn: boolean; + updateUser: (partial: Partial) => void; setUserAndToken: (user: User, token: string) => void; updateShopId: (shopId: string) => void; clearUser: () => void; @@ -28,6 +29,14 @@ export const useUserStore = create()( token: null, isLoggedIn: false, + updateUser: (partial) => { + const current = get(); + if (!current.user) return; + set({ + user: { ...current.user, ...partial }, + }); + }, + setUserAndToken: (user, token) => set({ user, diff --git a/src/pages/ProfileEditPage.tsx b/src/pages/ProfileEditPage.tsx index cf250c8..892cf57 100644 --- a/src/pages/ProfileEditPage.tsx +++ b/src/pages/ProfileEditPage.tsx @@ -31,7 +31,7 @@ const FIELD_LABELS: Record = { export default function ProfileEditPage() { const navigate = useNavigate(); - const { user } = useUserStore(); + const { user, updateUser } = useUserStore(); const [isSubmitting, setIsSubmitting] = useState(false); const openModal = useModalStore((state) => state.openModal); @@ -43,9 +43,35 @@ export default function ProfileEditPage() { }); useEffect(() => { - async function fetchUser() { + if (!user) { + openModal({ + type: "alert", + iconType: "warning", + message: "로그인 후에 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.AUTH.SIGNIN), + }); + return; + } + if (user.type === "employer") { + openModal({ + type: "alert", + iconType: "warning", + message: "알바생 계정으로만 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.SHOP.ROOT), + }); + return; + } + }, []); + + useEffect(() => { + const fetchUser = async () => { if (!user?.id) return; const res = await getUser(user.id); + + if (!res.data.item?.name) { + navigate(ROUTES.PROFILE.REGISTER); + return; + } const { name, phone, address, bio } = res.data.item; setForm({ name: name ?? "", @@ -53,24 +79,16 @@ export default function ProfileEditPage() { address, bio: bio ?? "", }); - } + }; fetchUser(); - }, [user?.id]); + }, [user?.id, navigate]); const handleChange = (key: keyof FormType, value: string | SeoulDistrict) => { setForm((prev) => ({ ...prev, [key]: value })); }; const handleSubmit = async () => { - if (!user?.id) { - openModal({ - type: "alert", - iconType: "warning", - message: "로그인 정보가 없습니다.", - }); - return; - } - + if (!user?.id) return; if (isSubmitting) return; const requiredFields: Array = ["name", "phone", "address"]; @@ -99,6 +117,7 @@ export default function ProfileEditPage() { try { await putUser(user.id, payload); + updateUser(payload); openModal({ type: "message", iconType: "none", @@ -120,72 +139,74 @@ export default function ProfileEditPage() { }; return ( -
{ - e.preventDefault(); - handleSubmit(); - }} - > -
-

- 내 프로필 -

- -
- -
- handleChange("name", e.target.value)} - maxLength={20} - /> - { - const formatted = autoHyphenFormatter(e.target.value); - handleChange("phone", formatted); - }} - /> - ({ label: d, value: d }))} + value={form.address} + onValueChange={(value) => handleChange("address", value)} + /> +
+
+ handleChange("bio", e.target.value)} + /> +
+
+ +
+
+ ); } diff --git a/src/pages/ProfileRegisterPage.tsx b/src/pages/ProfileRegisterPage.tsx index bf5d91c..20dafb0 100644 --- a/src/pages/ProfileRegisterPage.tsx +++ b/src/pages/ProfileRegisterPage.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import type { AxiosError } from "axios"; import { useNavigate } from "react-router-dom"; @@ -31,7 +31,7 @@ const FIELD_LABELS: Record = { export default function ProfileRegisterPage() { const navigate = useNavigate(); - const { user } = useUserStore(); + const { user, updateUser } = useUserStore(); const [isSubmitting, setIsSubmitting] = useState(false); const openModal = useModalStore((state) => state.openModal); @@ -42,20 +42,36 @@ export default function ProfileRegisterPage() { bio: "", }); - const handleChange = (key: keyof FormType, value: string | SeoulDistrict) => { - setForm((prev) => ({ ...prev, [key]: value })); - }; - - const handleSubmit = async () => { - if (!user?.id) { + useEffect(() => { + if (!user) { openModal({ type: "alert", iconType: "warning", - message: "로그인 정보가 없습니다.", + message: "로그인 후에 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.AUTH.SIGNIN), }); return; } + if (user.type === "employer") { + openModal({ + type: "alert", + iconType: "warning", + message: "알바생 계정으로만 이용 가능한 기능입니다.", + onClose: () => navigate(ROUTES.SHOP.ROOT), + }); + return; + } + if (user.name) { + navigate(ROUTES.PROFILE.EDIT); + } + }, []); + + const handleChange = (key: keyof FormType, value: string | SeoulDistrict) => { + setForm((prev) => ({ ...prev, [key]: value })); + }; + const handleSubmit = async () => { + if (!user?.id) return; if (isSubmitting) return; const requiredFields: Array = ["name", "phone", "address"]; @@ -84,6 +100,7 @@ export default function ProfileRegisterPage() { try { await putUser(user.id, payload); + updateUser(payload); openModal({ type: "message", iconType: "none", @@ -105,72 +122,74 @@ export default function ProfileRegisterPage() { }; return ( -
{ - e.preventDefault(); - handleSubmit(); - }} - > -
-

- 내 프로필 -

- -
- -
- handleChange("name", e.target.value)} - maxLength={20} - /> - { - const formatted = autoHyphenFormatter(e.target.value); - handleChange("phone", formatted); - }} - /> - ({ label: d, value: d }))} + value={form.address} + onValueChange={(value) => handleChange("address", value)} + /> +
+
+ handleChange("bio", e.target.value)} + /> +
+
+ +
+
+ ); }