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

Feat: 마이페이지 마크업 #14

Merged
merged 7 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
2 changes: 1 addition & 1 deletion src/app/domain/[id]/DomainCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Chip } from '@/components/Chip';
import SubscribeButton from '@/components/SubscribeButton';
import type { DomainType } from '@/types/article';
import type { DomainType } from '@/types/';
import Image from 'next/image';
import Link from 'next/link';
import WebsiteIcon from '@/assets/icons/WebsiteIcon.svg';
Expand Down
4 changes: 2 additions & 2 deletions src/app/domain/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import MainPageHeader from '@/components/Header/MainPageHeader';
import DomainListTap from '@/components/ListTap/DomainListTap';
import AlternateListTap from '@/components/ListTap/AlternateListTap';
import Image from 'next/image';
import ArticleCard from '@/components/Article/ArticleCard';
import DomainCard from '@/app/domain/[id]/DomainCard';
Expand All @@ -23,7 +23,7 @@ const DomainPage = async ({ params }: DomainPageProps) => {
<div className='absolute bottom-0 w-full h-2/5 bg-gradient-to-t from-white' />
</div>
<div className='relative -top-10 text-h1'>{domainData.name}</div>
<DomainListTap />
<AlternateListTap tapName='지난 아티클' tapCount={domainArticleData.length} />
<div className='flex flex-col w-full gap-4'>
{domainArticleData.map(article => (
<ArticleCard key={article.id} {...article} currentTab={'currentTab'} />
Expand Down
4 changes: 2 additions & 2 deletions src/app/main/CategoryTab.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ArticleCard from '@/components/Article/ArticleCard';
import { Chip } from '@/components/Chip';
import type { ArticleType } from '@/types/article';
import type { ArticleType } from '@/types';
import RecommendArea from '@/app/main/TodayTab/RecommendArea';

interface CategoryTabProps {
Expand Down Expand Up @@ -28,7 +28,7 @@ const CategoryTab = async ({ currentTab }: CategoryTabProps) => {
export default CategoryTab;

// currentTab을 props로 넘겨서 해당 탭에 맞는 데이터를 fetch
const getCategoryArticleData = async (currentTab: string): Promise<Article[]> => {
const getCategoryArticleData = async (currentTab: string): Promise<ArticleType[]> => {
return [
{
id: 'randomString111',
Expand Down
48 changes: 17 additions & 31 deletions src/app/main/TodayTab/RecommendArea.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import { Chip } from '@/components/Chip';
import DomainListItem from '@/components/Domain/DomainListItem';
import SubscribeButton from '@/components/SubscribeButton';
import Image from 'next/image';

const RecommendArea = async () => {
const recommendBrandData = await getRecommendBrandData();
const recommendDomainData = await getRecommendDomainData();

return (
<div className='flex flex-col gap-3 w-brandCard'>
<div className='flex flex-col gap-3 min-w-domainCard'>
<div className='flex flex-col'>
<span className='text-body3'>채현님이 놓치고 있는 뉴스레터</span>
<span className='text-caption text-darkgrey'>더 많은 인사이트를 얻으세요</span>
</div>
<div className='flex flex-col'>
{recommendBrandData.map((brand, index) => (
{recommendDomainData.map((domain, index) => (
<div
key={brand.id}
className={`${index !== recommendBrandData.length - 1 && 'border-b border-lightgrey'} flex flex-row justify-between w-full py-3`}
key={index}
className={`${index === recommendDomainData.length - 1 ? 'border-b-white' : 'border-b-lightgrey'} border-b`}
>
<span className='flex flex-row items-center gap-3'>
<Image
src={brand.thumbnail}
alt={`thumbnail-${brand.brandName}`}
width={48}
height={48}
className='rounded-full'
/>
<span className='flex flex-row gap-1 h-fit'>
<span className='text-body3'>{brand.brandName}</span>
<Chip text={brand.type} />
</span>
</span>
<span className='py-2'>
<SubscribeButton isSubscribed={brand.subscribed} />
</span>
<DomainListItem domainData={domain} isSubscribed={domain.isSubscribed} />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

이 부분은 중복되는 UI 로직이 있어서 DomainListItem으로 뺐습니다

Copy link
Contributor

Choose a reason for hiding this comment

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

확인해보고 싶어서 서버 켜봤는데 오류뜨는지라... ㅜ 확인이 쉽지않네요 ㅎㅎ..
나중에 다시 확인해보겠습니당

</div>
))}
</div>
Expand All @@ -42,28 +28,28 @@ const RecommendArea = async () => {

export default RecommendArea;

moong23 marked this conversation as resolved.
Show resolved Hide resolved
const getRecommendBrandData = async () => {
const getRecommendDomainData = async () => {
return [
{
id: 'randomString111',
brandName: '요즘IT',
thumbnail: 'https://picsum.photos/48',
name: '요즘IT',
profile: 'https://picsum.photos/48',
type: 'IT/테크',
subscribed: false,
isSubscribed: false,
},
{
id: 'randomString112',
brandName: '요즘IT',
thumbnail: 'https://picsum.photos/48',
name: '요즘IT',
profile: 'https://picsum.photos/48',
type: 'IT/테크',
subscribed: false,
isSubscribed: false,
},
{
id: 'randomString113',
brandName: '요즘IT',
thumbnail: 'https://picsum.photos/48',
name: '요즘IT',
profile: 'https://picsum.photos/48',
type: 'IT/테크',
subscribed: false,
isSubscribed: false,
},
];
};
4 changes: 2 additions & 2 deletions src/app/main/TodayTab/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ArticleCard from '@/components/Article/ArticleCard';
import { Chip } from '@/components/Chip';
import type { ArticleType } from '@/types/article';
import type { ArticleType } from '@/types';
import { formatToYMD } from '@/utils/formatDate/formatToYMD';
import Image from 'next/image';
import DoubleArrow from '@/assets/icons/DoubleArrow.svg';
Expand Down Expand Up @@ -37,7 +37,7 @@ const TodayTab = async () => {
};
export default TodayTab;

const getMainPageArticleData = async (): Promise<Article[]> => {
const getMainPageArticleData = async (): Promise<ArticleType[]> => {
return [
{
id: 'randomString111',
Expand Down
7 changes: 0 additions & 7 deletions src/app/mypage/ProfileCard.tsx

This file was deleted.

33 changes: 33 additions & 0 deletions src/app/mypage/UserDataCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Chip } from '@/components/Chip';
import { UserDataType } from '@/types';
import Image from 'next/image';
import { GET } from '@/network';

const UserDataCard = async () => {
//TODO: 추후 로그인 로직 완성 후 주석 교체
const userData: UserDataType = await getUserData();
// const userData = cookies().get('userData');

Comment on lines +7 to +10
Copy link
Contributor Author

Choose a reason for hiding this comment

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

UserDataCard에서 유저의 정보(이름, 이메일, 태그 유형, 프로필사진)를 받아오기 위해

  1. API 호출을 해야하는가
  2. 저장소에서 가져와야하는가

에서 2번을 선택했는데, next의 SSR특성상 localStorage에는 접근할 수 없어서
유저 정보를 로그인하면 쿠키에 저장하고, 필요한 곳에서 쿠키를 꺼내어 쓰는거로 설계를 했는데요,
혹시 이해가 안가는 부분이나, 더 나은 방법이 있다면 말씀주세요!

Copy link
Contributor

Choose a reason for hiding this comment

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

한번에 코멘트 남길게요!

return (
<div className='flex flex-col w-full h-full gap-3'>
<Image src={userData.profile} alt='profile' width={80} height={80} className='rounded-full' />
<div className='flex flex-col'>
<span className='text-h2'>{userData.name}</span>
<span className='text-body3'>{userData.email}</span>
</div>
<div className='flex flex-row gap-2'>
{userData.typeList.map(type => (
<Chip key={type} text={type} />
))}
</div>
</div>
);
};

export default UserDataCard;

// TODO: 추후 로그인 로직 완성 후 아래 제거
const getUserData = async () => {
const response = await GET('/userData');
return response.data;
};
36 changes: 34 additions & 2 deletions src/app/mypage/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
import MainPageHeader from '@/components/Header/MainPageHeader';
import { PropsWithChildren } from 'react';
import type { PropsWithChildren } from 'react';
import Link from 'next/link';
import UserDataCard from '@/app/mypage/UserDataCard';

export default async function MypageLayout({ children }: Readonly<PropsWithChildren>) {
return (
<>
<MainPageHeader />
<div className='flex flex-col w-content'>
<div className='flex justify-center w-full h-full'>{children}</div>
<div className='flex justify-center w-full h-full'>
<div className='flex flex-row gap-10 w-content'>
{children}
<div className='border-l border-lightgrey' />
<div className='flex flex-col justify-between h-[calc(100vh-11.25rem)]'>
<div className='pt-20'>
<span className='w-full bg-red h-[200px]'>
<UserDataCard />
</span>
</div>
<div className='flex flex-col gap-3 pb-6 text-caption'>
<Link href='/setting'>설정</Link>
<Link href='/contact'>문의하기</Link>
<div className='flex flex-row gap-4'>
<Link
href='/privacy' // Link to Privacy Policy
className='underline decoration-black underline-offset-2'
>
이용 약관
</Link>
<Link
href='/terms' // Link to Terms of Service
className='underline decoration-black underline-offset-2'
>
개인정보 처리방침
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
Expand Down
51 changes: 47 additions & 4 deletions src/app/mypage/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,52 @@
const MyPage = () => {
import type { UserDataType } from '@/types';
import Link from 'next/link';
import { GET } from '@/network';

interface MyPageProps {
userData: UserDataType;
}

const MyPage = async () => {
//TODO: 추후 로그인 로직 완성 후 주석 교체
const userData: UserDataType = await getUserData();
// const userData = cookies().get('userData');

return (
<>
<>Test123</>
</>
<div className='flex flex-col gap-12 w-articleCard'>
<div className='relative w-full aspect-[792/216] bg-blue'>
<div className='absolute bottom-0 w-full h-2/5 bg-gradient-to-t from-white' />
<div className='absolute ml-4 -bottom-6 text-h1'>{userData?.name}</div>
</div>
<div className='flex flex-col w-full gap-8 pl-4 text-btn1'>
<Link
className='w-fit'
href='/mypage/subscribe' // Link to Subscribe Management Page
>
뉴스레터 구독 관리
</Link>
<Link
href='/logout' // Link to Logout
className='flex flex-col gap-1 w-fit'
>
로그아웃
<span className='text-caption'>다시 로그인 할 때까지 계정이 비활성화됩니다.</span>
</Link>
<Link
href='/withdrawl' // Link to Withdrawal
className='flex flex-col gap-1 w-fit text-darkgrey'
>
회원 탈퇴
<span className='text-caption'>개인 정보 및 설정이 모두 영구적으로 삭제됩니다</span>
</Link>
</div>
</div>
);
};

export default MyPage;

// TODO: 추후 로그인 로직 완성 후 아래 제거
const getUserData = async () => {
const response = await GET('/userData');
return response.data;
};
38 changes: 38 additions & 0 deletions src/app/mypage/subscribe/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import DomainListItem from '@/components/Domain/DomainListItem';
import AlternateListTap from '@/components/ListTap/AlternateListTap';
import ListItem from '@/components/ListTap/ListItem';
import SubscribeButton from '@/components/SubscribeButton';
import { GET } from '@/network';

interface SubscribeDataType {
id: string;
name: string;
type: string;
}

const SubscribePage = async () => {
const subscribeList: SubscribeDataType[] = await getSubscribeList();

return (
<div className='flex flex-col gap-6 w-articleCard pt-[7.625rem]'>
<div className='flex flex-col gap-2'>
<span className='text-caption text-darkgrey'>{`마이페이지 >`}</span>
<span className='text-h2'>뉴스레터 구독 관리</span>
<span className='text-body3'>InspoMailClub에서 더 이상 읽고 싶지 않은 뉴스레터를 선택하세요</span>
</div>
<AlternateListTap tapName='발신인' tapCount={subscribeList.length} />
<div className='flex flex-col max-w-max_domainCard'>
{subscribeList.map(subscribe => (
<DomainListItem domainData={subscribe} isSubscribed={true} />
))}
</div>
</div>
);
};

export default SubscribePage;

const getSubscribeList = async () => {
const response = await GET('/subscribeList');
return response.data;
};
2 changes: 1 addition & 1 deletion src/components/Article/ArticleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ArticleType } from '@/types/article';
import type { ArticleType } from '@/types';
import Image from 'next/image';
import { formatToMonthDayKorean } from '@/utils/formatDate/formatToMonthDayKorean';
import Link from 'next/link';
Expand Down
36 changes: 0 additions & 36 deletions src/components/ArticleCard.tsx

This file was deleted.

Loading