Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ffe3017
โœจ feat: ๋งˆ์ดํŽ˜์ด์ง€ ์ด๋ฆ„๋ณ€๊ฒฝ, ํŽ˜์ด์ง€ ์„œ๋ฒ„๋กœ ๋ณ€๊ฒฝ
HaeJungg Nov 14, 2024
15249d9
Merge branch 'develop' into Feat/125/MyPageProfile
HaeJungg Nov 14, 2024
a0a4aef
๐Ÿ› fix: User ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ํ• ๋‹นํ•˜๋„๋ก ์ˆ˜์ •
HaeJungg Nov 14, 2024
79105a1
โœจ feat: ๋ฐ์ดํ„ฐ ์—ฐ๊ฒฐ
HaeJungg Nov 14, 2024
fe90461
โœจ feat: ํšŒ์›์ •๋ณด ์ˆ˜์ • api์ถ”๊ฐ€
HaeJungg Nov 15, 2024
7c7efbd
๐Ÿš‘ fix: getuser ์ˆ˜์ •
HaeJungg Nov 18, 2024
a54e378
๐Ÿ“ฆ chore: ์ด๋ฏธ์ง€ ํŒŒ์ผ ๋ณ€๊ฒฝ
HaeJungg Nov 18, 2024
0250543
โœจ feat: 200์ด ๋นˆ ๊ฐ์ฒด๋กœ ์˜ฌ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ
HaeJungg Nov 18, 2024
f867559
๐Ÿ’„ design: ํ”„๋กœํ•„ ํ…Œ๋‘๋ฆฌ ๋””์ž์ธ ์ถ”๊ฐ€
HaeJungg Nov 18, 2024
92b1af1
โœจ feat: ์บ์‹œ๋ฅผ ์ง€์šฐ๊ณ  ์ƒˆ๋กœ ํ”„๋กœํ•„ ํŒจ์น˜๋ฅผ ํ•˜๊ธฐ ์œ„ํ•œ api ์ถ”๊ฐ€
HaeJungg Nov 18, 2024
20522d6
โœจ feat: ํ”„๋กœํ•„ ์ปดํฌ๋„ŒํŠธ ๊ฐœ์„ , edit ๊ฒฝ์šฐ ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ •
HaeJungg Nov 18, 2024
7a72219
๐Ÿ’„ design: ํ—ค๋” 360์—์„œ๋„ ๊นจ์ง€์ง€ ์•Š๋„๋ก ์ˆ˜์ •
HaeJungg Nov 18, 2024
8e373cf
โœจ feat: ํ—ค๋” ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—ฐ๊ฒฐ
HaeJungg Nov 18, 2024
8b87010
โœจ feat: ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ˆ˜์ • api ์ถ”๊ฐ€, ๋“œ๋กญ๋‹ค์šด ์ถ”๊ฐ€
HaeJungg Nov 18, 2024
f92e139
๐Ÿ› fix: ์Šคํ† ๋ฆฌ๋ถ ์ˆ˜์ •
HaeJungg Nov 18, 2024
843083e
๐Ÿ› fix: ํ—ค๋” ์Šคํ† ๋ฆฌ๋ถ ์ˆ˜์ •
HaeJungg Nov 18, 2024
47b8c5f
โœจ feat: auth store์— rehydration ์ฒ˜๋ฆฌ ์ถ”๊ฐ€
HaeJungg Nov 18, 2024
6168d99
๐Ÿ› fix: rehydration ํ›„ ์ธ์ฆ ๋ฐ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ฒ˜๋ฆฌ ์ถ”๊ฐ€
HaeJungg Nov 18, 2024
d157a7e
Merge branch 'develop' into Feat/125/MyPageProfile
HaeJungg Nov 18, 2024
2b952f8
โœจ feat: ๊ธฐ๋ณธ ํ”„๋กœํ•„๋กœ ๋Œ์•„๊ฐ€๋Š” api ์ถ”๊ฐ€
HaeJungg Nov 19, 2024
8cd3ccd
โœจ feat: ์ดˆ๊ธฐ ์ด๋ฏธ์ง€๋กœ ๋„˜์–ด๊ฐ€๋Š” api ์—ฐ๊ฒฐ
HaeJungg Nov 19, 2024
92f9509
Merge branch 'develop' into Feat/125/MyPageProfile
HaeJungg Nov 19, 2024
edbb817
๐Ÿ› fix: lint error ์ˆ˜์ •
HaeJungg Nov 19, 2024
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
4 changes: 4 additions & 0 deletions public/assets/icons/ic-edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions public/assets/icons/profile-edit.svg

This file was deleted.

41 changes: 41 additions & 0 deletions src/_apis/auth/user-apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,44 @@ export function getUser(): Promise<User> {
},
}).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
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

์ฝ”๋“œ ์ค‘๋ณต์„ ์ œ๊ฑฐํ•˜๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

getUser์™€ fetchUpdatedUser ํ•จ์ˆ˜๊ฐ€ ์ƒ๋‹น ๋ถ€๋ถ„ ์ค‘๋ณต๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณตํ†ต ๋กœ์ง์„ ์ถ”์ถœํ•˜์—ฌ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฆฌํŒฉํ† ๋ง์„ ์ œ์•ˆ๋“œ๋ฆฝ๋‹ˆ๋‹ค:

+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

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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;
});
}
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 getUserBase();
}
export async function fetchUpdatedUser(): Promise<User> {
return getUserBase({ skipCache: true });
}


// ์œ ์ € ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ดˆ๊ธฐํ™”
export async function resetUserProfileImage(): Promise<void> {
const url = `/auths/profile-image/reset`;

await fetchApi(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
Comment on lines +43 to +50
Copy link

Choose a reason for hiding this comment

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

๐Ÿ› ๏ธ Refactor suggestion

์‘๋‹ต ์ฒ˜๋ฆฌ์™€ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐœ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ดˆ๊ธฐํ™” API์— ๋‹ค์Œ ๊ฐœ์„ ์‚ฌํ•ญ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

  1. ์‘๋‹ต ํƒ€์ž…์ด ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  2. ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆ˜์ •์„ ์ œ์•ˆ๋“œ๋ฆฝ๋‹ˆ๋‹ค:

-export async function resetUserProfileImage(): Promise<void> {
+interface ResetProfileResponse {
+  message: string;
+  success: boolean;
+}
+
+export async function resetUserProfileImage(): Promise<ResetProfileResponse> {
   const url = `/auths/profile-image/reset`;
 
-  await fetchApi(url, {
+  return fetchApi<ResetProfileResponse>(url, {
     method: 'PUT',
     headers: {
       'Content-Type': 'application/json',
     },
-  });
+  }).catch((error) => {
+    console.error('ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ดˆ๊ธฐํ™” ์‹คํŒจ:', error);
+    throw error;
+  });
 }
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function resetUserProfileImage(): Promise<void> {
const url = `/auths/profile-image/reset`;
await fetchApi(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
interface ResetProfileResponse {
message: string;
success: boolean;
}
export async function resetUserProfileImage(): Promise<ResetProfileResponse> {
const url = `/auths/profile-image/reset`;
return fetchApi<ResetProfileResponse>(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
}).catch((error) => {
console.error('ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ดˆ๊ธฐํ™” ์‹คํŒจ:', error);
throw error;
});
}

});
}
103 changes: 103 additions & 0 deletions src/app/(crew)/my-page/_components/profile-card/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
'use client';

import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { useRouter } from 'next/navigation';
import {
fetchUpdatedUser,
resetUserProfileImage,
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, rehydrated, setUser } = useAuthStore();
const [user, setLocalUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [profileImageUrl, setProfileImageUrl] = useState<string>('');

useEffect(() => {
const checkAuthAndLoadUser = async () => {
if (!rehydrated) return; // ์ƒํƒœ ๋ณต์›์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ๋Œ€๊ธฐ

if (!isAuth) {
router.push('/login'); // ์ธ์ฆ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฆฌ๋””๋ ‰์…˜
return;
}

setIsLoading(true);

try {
const updatedUser = await fetchUpdatedUser();
setLocalUser(updatedUser);
setUser(updatedUser);
setProfileImageUrl(updatedUser.profileImageUrl);
} catch {
toast.error('์œ ์ € ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');
} finally {
setIsLoading(false);
}
};

checkAuthAndLoadUser();
}, [isAuth, rehydrated, router, setUser]);

if (!rehydrated) return null;
if (!isAuth) return null;
if (isLoading) return <div>๋กœ๋”ฉ ์ค‘...</div>;
if (!user) return <div>์œ ์ € ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.</div>;

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) {
alert('5MB ์ดํ•˜์˜ ํŒŒ์ผ๋งŒ ์—…๋กœ๋“œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.');
return;
}

try {
await updateUserProfile(file);

const tempUrl = URL.createObjectURL(file);
setProfileImageUrl(tempUrl);

const updatedUser = await fetchUpdatedUser();
const newProfileImageUrl = `${updatedUser.profileImageUrl}?timestamp=${new Date().getTime()}`;
setProfileImageUrl(newProfileImageUrl);
setUser({ ...updatedUser, profileImageUrl: newProfileImageUrl });
} catch (error) {
toast.error('ํŒŒ์ผ ์—…๋กœ๋“œ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');
}
}
};
input.click();
};

const handleDeleteProfile = async () => {
try {
await resetUserProfileImage();
const updatedUser = await fetchUpdatedUser();
setProfileImageUrl(''); // ์ดˆ๊ธฐํ™”๋œ ์ด๋ฏธ์ง€ ๋ฐ˜์˜
setLocalUser(updatedUser);
setUser(updatedUser);
toast.success('ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๊ฐ€ ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
} catch (error) {
toast.error('ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์ดˆ๊ธฐํ™”์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.');
}
};

return (
<ProfileCardPresenter
data={{ ...user, profileImageUrl }}
onEdit={handleEdit}
onDelete={handleDeleteProfile}
/>
);
}
51 changes: 51 additions & 0 deletions src/app/(crew)/my-page/_components/profile-card/presenter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'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;
onDelete: () => void;
}

export default function ProfileCardPresenter({ data, onEdit, onDelete }: 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 ?? ''} />
Copy link

Choose a reason for hiding this comment

The 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={() => {/* ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋กœ์ง */}}
+/>

Committable suggestion skipped: line range outside the PR's diff.

</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={onDelete}>
๊ธฐ๋ณธ ํ”„๋กœํ•„๋กœ ๋Œ์•„๊ฐ€๊ธฐ
</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
Expand Up @@ -3,23 +3,15 @@
import { useState } from 'react';
import { Divider } from '@mantine/core';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import ProfileCardContainer from '@/src/app/(crew)/mypage/_components/profile-card/container';
import { fetchWritableGatheringData } from '@/src/app/(crew)/api/mock-api/writable-gathering';
import { fetchMyReviewData } from '@/src/app/api/mock-api/review';
import ReviewCardList from '@/src/components/common/review-list/review-card-list';
import Tabs from '@/src/components/common/tab';
import WritableGatheringCardList from '@/src/components/common/writable-gathering-card/writable-gathering-card-list';
import { ReviewInformResponse } from '@/src/types/review';
import { WritableGatheringCardInformResponse } from '@/src/types/writable-gathering-card';
import { fetchMyReviewData } from '../../api/mock-api/review';
import { fetchWritableGatheringData } from '../api/mock-api/writable-gathering';

const mockData = {
id: 1,
profileImageUrl: '',
nickname: '์œจ์œจ',
email: '[email protected]',
};

export default function MyPage() {
export default function ReviewSection() {
const myPageTabs = [
{ label: '์ž‘์„ฑ ๊ฐ€๋Šฅํ•œ ๋ฆฌ๋ทฐ', id: 'available-review' },
{ label: '์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ', id: 'my-review' },
Expand All @@ -43,15 +35,12 @@ export default function MyPage() {
isFetchingNextPage: isFetchingGatheringNextPage,
} = useInfiniteScroll<WritableGatheringCardInformResponse>({
queryKey: ['crew'],
queryFn: ({ pageParam = 0 }) => {
return fetchWritableGatheringData(pageParam, 3);
},
queryFn: ({ pageParam = 0 }) => fetchWritableGatheringData(pageParam, 3),
getNextPageParam: (lastPage, allPages) =>
lastPage.hasNextPage ? allPages.length + 1 : undefined,
});

const renderTabContent = () => {
// TODO : ๋ฆฌํ„ด ๊ฐ’ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ต์ฒด
switch (currentTab) {
case 'my-review':
return (
Expand All @@ -73,27 +62,20 @@ 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 data={mockData} />
</div>
<div className="mt-12 flex flex-col">
<h3 className="text-2xl font-semibold text-gray-900">๋‚˜์˜ ๋ฆฌ๋ทฐ ๋ชจ์•„๋ณด๊ธฐ</h3>
<Divider mt={16} mb={24} size={2} />
<div className="flex justify-start">
<Tabs
variant="review"
tabs={myPageTabs}
activeTab={currentTab}
onTabClick={(id) => {
setCurrentTab(id);
}}
/>
</div>
<div className="pt-12">{renderTabContent()}</div>
<div className="mt-12 flex flex-col">
<h3 className="text-2xl font-semibold text-gray-900">๋‚˜์˜ ๋ฆฌ๋ทฐ ๋ชจ์•„๋ณด๊ธฐ</h3>
<Divider mt={16} mb={24} size={2} />
<div className="flex justify-start">
<Tabs
variant="review"
tabs={myPageTabs}
activeTab={currentTab}
onTabClick={(id) => setCurrentTab(id)}
/>
</div>
<div />
<div className="pt-12">{renderTabContent()}</div>
</div>
);
}
14 changes: 14 additions & 0 deletions src/app/(crew)/my-page/page.tsx
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>
);
}
14 changes: 0 additions & 14 deletions src/app/(crew)/mypage/_components/profile-card/container.tsx

This file was deleted.

36 changes: 0 additions & 36 deletions src/app/(crew)/mypage/_components/profile-card/presenter.tsx

This file was deleted.

9 changes: 6 additions & 3 deletions src/components/common/header/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import HeaderPresenter from '@/src/components/common/header/presenter';
*
* @param {boolean} isAuth - ๋กœ๊ทธ์ธ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ƒํƒœ (true: ๋กœ๊ทธ์ธ๋จ, false: ๋น„๋กœ๊ทธ์ธ)
* @param {function} handleLogout - ๋กœ๊ทธ์•„์›ƒ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•จ์ˆ˜
* @param {function} toggleCookie - ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ์ฟ ํ‚ค ์ƒํƒœ๋ฅผ ํ† ๊ธ€ํ•˜๋Š” ํ•จ์ˆ˜ (์ปดํฌ๋„ŒํŠธ ์‹คํ—˜์šฉ)
*/

export default function Header() {
const { isAuth, logout } = useAuthStore();
const { isAuth, user, logout } = useAuthStore(); // user ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

const router = useRouter();

Expand All @@ -24,7 +23,11 @@ export default function Header() {

return (
<div>
<HeaderPresenter isAuth={isAuth} handleLogout={handleLogout} />
<HeaderPresenter
isAuth={isAuth}
handleLogout={handleLogout}
profileImageUrl={user?.profileImageUrl}
/>
</div>
);
}
Loading
Loading