-
Notifications
You must be signed in to change notification settings - Fork 3
Feat/125/my page profile #134
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
Changes from 16 commits
ffe3017
15249d9
a0a4aef
79105a1
fe90461
7c7efbd
a54e378
0250543
f867559
92b1af1
20522d6
7a72219
8e373cf
8b87010
f92e139
843083e
47b8c5f
6168d99
d157a7e
2b952f8
8cd3ccd
92f9509
edbb817
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,11 +1,40 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { fetchApi } from '@/src/utils/api'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { User } from '@/src/types/auth'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function getUser(): Promise<{ data: User }> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function getUser(): Promise<User> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fetchApi<{ data: User }>('/auths/user', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'GET', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }).then((response) => response.data); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ํ์์ ๋ณด ์์ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function updateUserProfile(file: File): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const url = `/auths/user`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const formData = new FormData(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formData.append('file', file); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await fetchApi(url, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'PUT', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| body: formData, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function fetchUpdatedUser() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return fetchApi<{ data: User }>('/auths/user', { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| method: 'GET', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Content-Type': 'application/json', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Cache-Control': 'no-cache', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((response) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return response.data; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .catch((error) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ์ฝ๋ ์ค๋ณต์ ์ ๊ฑฐํ๊ณ ์ฌ์ฌ์ฉ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๋ฆฌํฉํ ๋ง์ ์ ์๋๋ฆฝ๋๋ค: +interface GetUserOptions {
+ skipCache?: boolean;
+}
+
+async function getUserBase(options: GetUserOptions = {}): Promise<User> {
+ const headers: Record<string, string> = {
+ 'Content-Type': 'application/json',
+ };
+
+ if (options.skipCache) {
+ headers['Cache-Control'] = 'no-cache';
+ }
+
+ return fetchApi<{ data: User }>('/auths/user', {
+ method: 'GET',
+ headers,
+ })
+ .then((response) => response.data)
+ .catch((error) => {
+ console.error('์ฌ์ฉ์ ์ ๋ณด ์กฐํ ์ค ์ค๋ฅ ๋ฐ์:', error);
+ throw error;
+ });
+}
+
-export function getUser(): Promise<User> {
- return fetchApi<{ data: User }>('/auths/user', {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- },
- }).then((response) => response.data);
+export function getUser(): Promise<User> {
+ return getUserBase();
}
-export async function fetchUpdatedUser() {
- return fetchApi<{ data: User }>('/auths/user', {
- method: 'GET',
- headers: {
- 'Content-Type': 'application/json',
- 'Cache-Control': 'no-cache',
- },
- })
- .then((response) => {
- return response.data;
- })
- .catch((error) => {
- throw error;
- });
+export async function fetchUpdatedUser(): Promise<User> {
+ return getUserBase({ skipCache: true });
}๐ Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,75 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useEffect, useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { toast } from 'react-toastify'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useRouter } from 'next/navigation'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { fetchUpdatedUser, updateUserProfile } from '@/src/_apis/auth/user-apis'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useAuthStore } from '@/src/store/use-auth-store'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { User } from '@/src/types/auth'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ProfileCardPresenter from './presenter'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function ProfileCard() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const router = useRouter(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { isAuth, setUser } = useAuthStore(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [user, setLocalUser] = useState<User | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isLoading, setIsLoading] = useState(true); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [profileImageUrl, setProfileImageUrl] = useState<string>(''); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const timer = setTimeout(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isAuth) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.push('/login'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const updatedUser = await fetchUpdatedUser(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setLocalUser(updatedUser); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setUser(updatedUser); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setProfileImageUrl(updatedUser.profileImageUrl); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsLoading(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| toast.error('์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 500); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => clearTimeout(timer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [isAuth, router, setUser]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | |
| const timer = setTimeout(async () => { | |
| if (!isAuth) { | |
| router.push('/login'); | |
| } else { | |
| try { | |
| const updatedUser = await fetchUpdatedUser(); | |
| setLocalUser(updatedUser); | |
| setUser(updatedUser); | |
| setProfileImageUrl(updatedUser.profileImageUrl); | |
| setIsLoading(false); | |
| } catch (error) { | |
| toast.error('์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.'); | |
| } | |
| } | |
| }, 500); | |
| return () => clearTimeout(timer); | |
| }, [isAuth, router, setUser]); | |
| useEffect(() => { | |
| let isMounted = true; | |
| const fetchUser = async () => { | |
| if (!isAuth) { | |
| router.push('/login'); | |
| } else { | |
| try { | |
| const updatedUser = await fetchUpdatedUser(); | |
| if (!isMounted) return; | |
| setLocalUser(updatedUser); | |
| setUser(updatedUser); | |
| setProfileImageUrl(updatedUser.profileImageUrl); | |
| setIsLoading(false); | |
| } catch (error) { | |
| if (!isMounted) return; | |
| if (error instanceof Error) { | |
| toast.error(`์ ์ ์ ๋ณด ์กฐํ ์คํจ: ${error.message}`); | |
| } else { | |
| toast.error('์ ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์คํจํ์ต๋๋ค.'); | |
| } | |
| } | |
| } | |
| }; | |
| fetchUser(); | |
| return () => { | |
| isMounted = false; | |
| }; | |
| }, [isAuth, router, setUser]); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ํ์ผ ์ ๋ก๋ ์ฒ๋ฆฌ ๋ก์ง์ ๋ณด์ ๋ฐ ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ ์ด ํ์ํฉ๋๋ค.
ํ์ฌ ๊ตฌํ์์ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ ์ด ํ์ํฉ๋๋ค:
- ํ์ผ ํ์ ๊ฒ์ฆ ๊ฐํ
- ์ ๋ก๋ ์งํ ์ํ ํ์
- URL.createObjectURL ๋ฉ๋ชจ๋ฆฌ ์ ๋ฆฌ
๋ค์๊ณผ ๊ฐ์ด ๊ฐ์ ํ๋ ๊ฒ์ ์ ์๋๋ฆฝ๋๋ค:
+const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/jpg', 'image/png'];
+const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const handleEdit = () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.png,.jpg,.jpeg';
input.onchange = async (event) => {
const file = (event.target as HTMLInputElement)?.files?.[0];
if (file) {
- if (file.size > 5 * 1024 * 1024) {
+ if (!ALLOWED_FILE_TYPES.includes(file.type)) {
+ toast.error('์ง์ํ์ง ์๋ ํ์ผ ํ์์
๋๋ค.');
+ return;
+ }
+
+ if (file.size > MAX_FILE_SIZE) {
alert('5MB ์ดํ์ ํ์ผ๋ง ์
๋ก๋ ๊ฐ๋ฅํฉ๋๋ค.');
return;
}
try {
+ setIsLoading(true);
await updateUserProfile(file);
const tempUrl = URL.createObjectURL(file);
+ // Clean up the temporary URL when we're done with it
+ setTimeout(() => URL.revokeObjectURL(tempUrl), 1000);
setProfileImageUrl(tempUrl);
const updatedUser = await fetchUpdatedUser();
const newProfileImageUrl = `${updatedUser.profileImageUrl}?timestamp=${new Date().getTime()}`;
setProfileImageUrl(newProfileImageUrl);
setUser({ ...updatedUser, profileImageUrl: newProfileImageUrl });
+ toast.success('ํ๋กํ ์ด๋ฏธ์ง๊ฐ ์
๋ฐ์ดํธ๋์์ต๋๋ค.');
} catch (error) {
toast.error('ํ์ผ ์
๋ก๋์ ์คํจํ์ต๋๋ค.');
+ } finally {
+ setIsLoading(false);
}
}
};
input.click();
};Committable suggestion skipped: line range outside the PR's diff.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| 'use client'; | ||
|
|
||
| import { Menu } from '@mantine/core'; | ||
| import { Profile } from '@/src/components/common/profile'; | ||
| import { UserType } from '@/src/types/user'; | ||
|
|
||
| export interface ProfileCardProps { | ||
| data: UserType; | ||
| onEdit: () => void; | ||
| } | ||
|
|
||
| export default function ProfileCardPresenter({ data, onEdit }: ProfileCardProps) { | ||
| return ( | ||
| <div className="flex items-end justify-between"> | ||
| <div className="flex items-center gap-6.5"> | ||
| <figure className="h-20 w-20 md:h-30 md:w-30 lg:h-30 lg:w-30"> | ||
| <Menu | ||
| shadow="sm" | ||
| width={170} | ||
| offset={-5} | ||
| withArrow | ||
| arrowPosition="side" | ||
| position="bottom-start" | ||
| > | ||
| <Menu.Target> | ||
| <div className="h-full w-full"> | ||
| <Profile editable imageUrl={data?.profileImageUrl ?? ''} /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ํ๋กํ ์ด๋ฏธ์ง ๋ก๋ฉ ๋ฐ ์๋ฌ ์ํ ์ฒ๋ฆฌ ํ์ ํ๋กํ ์ด๋ฏธ์ง URL์ด ์๊ฑฐ๋ ๋ก๋ฉ ์ค์ผ ๋์ ์ํ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. -<Profile editable imageUrl={data?.profileImageUrl ?? ''} />
+<Profile
+ editable
+ imageUrl={data?.profileImageUrl ?? ''}
+ loading={!data}
+ onError={() => {/* ์๋ฌ ์ฒ๋ฆฌ ๋ก์ง */}}
+/>
|
||
| </div> | ||
| </Menu.Target> | ||
| <Menu.Dropdown className="translate-x-16 translate-y-2 transform md:translate-x-24 md:translate-y-0 lg:translate-x-24 lg:translate-y-0"> | ||
| <Menu.Item onClick={onEdit}>ํ๋กํ ์ด๋ฏธ์ง ์์ ํ๊ธฐ</Menu.Item> | ||
| <Menu.Item color="red" onClick={() => alert('Delete Profile')}> | ||
| ๊ธฐ๋ณธ ํ๋กํ๋ก ๋์๊ฐ๊ธฐ | ||
| </Menu.Item> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ ๏ธ Refactor suggestion ์ ๊ทผ์ฑ ๋ฐ ๊ตญ์ ํ ๊ฐ์ ํ์
-<Menu.Item onClick={onEdit}>ํ๋กํ ์ด๋ฏธ์ง ์์ ํ๊ธฐ</Menu.Item>
+<Menu.Item onClick={onEdit} aria-label="ํ๋กํ ์ด๋ฏธ์ง ์์ ">
+ {t('profile.edit')}
+</Menu.Item>
-<Menu.Item color="red" onClick={() => alert('Delete Profile')}>
- ๊ธฐ๋ณธ ํ๋กํ๋ก ๋์๊ฐ๊ธฐ
+<Menu.Item
+ color="red"
+ onClick={() => alert('Delete Profile')}
+ aria-label="๊ธฐ๋ณธ ํ๋กํ๋ก ๋ณต์"
+>
+ {t('profile.reset')}
+</Menu.Item>
|
||
| </Menu.Dropdown> | ||
| </Menu> | ||
| </figure> | ||
| <div className="flex flex-col gap-2"> | ||
| <p className="text-xl font-semibold text-gray-900 md:text-2xl lg:text-2xl"> | ||
| {data?.nickname} ๋, ์๋ ํ์ธ์๐ | ||
| </p> | ||
| <dl className="flex text-base font-medium text-gray-700"> | ||
| <dt className="flex-shrink-0 flex-grow-0 basis-20">Email</dt> | ||
| <dd className="flex-1">{data?.email}</dd> | ||
| </dl> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import ProfileCardContainer from '@/src/app/(crew)/my-page/_components/profile-card/container'; | ||
| import ReviewSection from '@/src/app/(crew)/my-page/_components/review-section'; | ||
|
|
||
| export default function MyPage() { | ||
| return ( | ||
| <div className="container mx-auto my-0 min-h-screen max-w-pc bg-gray-50 px-3 py-11 md:px-8 lg:px-11"> | ||
| <div className="lg:gap-4.5 flex flex-col gap-3 md:gap-4"> | ||
| <ProfileCardContainer /> | ||
| </div> | ||
| <ReviewSection /> | ||
| <div /> | ||
| </div> | ||
| ); | ||
| } |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ํ์ผ ์ ๋ก๋ ๊ตฌํ์ ๋ช ๊ฐ์ง ๊ฐ์ ์ด ํ์ํฉ๋๋ค.
๋ค์ ์ฌํญ๋ค์ ๊ณ ๋ คํด ์ฃผ์ธ์:
๋ค์๊ณผ ๊ฐ์ด ์์ ์ ์ ์๋๋ฆฝ๋๋ค:
export async function updateUserProfile(file: File): Promise<void> { const url = `/auths/user`; const formData = new FormData(); formData.append('file', file); await fetchApi(url, { method: 'PUT', + headers: { + 'Content-Type': 'multipart/form-data', + }, body: formData, - }); + }).catch((error) => { + console.error('ํ๋กํ ์ ๋ฐ์ดํธ ์ค ์ค๋ฅ ๋ฐ์:', error); + throw error; + }); }