Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
301244a
✨ Feat: my-gathering λ²„νŠΌ μΆ”κ°€ 및 ν•˜μœ„ μ»΄ν¬λ„ŒνŠΈ 뢄리
minkyung5x5 Nov 5, 2024
cdd2d66
✨ Feat: ν•˜μœ„ νŽ˜μ΄μ§€λ‘œ 뢄리
minkyung5x5 Nov 5, 2024
6ac5383
Merge branch 'develop' into Feat/60/my-gathering-page
minkyung5x5 Nov 5, 2024
a8ace8f
✨ Feat: GatheringList μΆ”κ°€
minkyung5x5 Nov 6, 2024
e37ca96
Merge branch 'develop' into Feat/60/my-gathering-page
minkyung5x5 Nov 6, 2024
57f9da5
πŸ’„ Style: gatheringlist max-w μ‚­μ œ
minkyung5x5 Nov 6, 2024
76df121
πŸ’„ Style: 전체 λ ˆμ΄μ•„μ›ƒμ— flex-1 μΆ”κ°€
minkyung5x5 Nov 6, 2024
b7f92d1
✨ Feat: gatheringListWithDate μ»΄ν¬λ„ŒνŠΈ μΆ”κ°€
minkyung5x5 Nov 6, 2024
7c9cbf3
πŸ’„ Style: gatheringListWithDate UI μˆ˜μ •
minkyung5x5 Nov 6, 2024
706cac6
✨ Feat: popoverCalendar μΆ”κ°€, πŸ› Fix: card λͺ¨λ°”μΌν™˜κ²½ 이미지 μ‚¬μ΄μ¦ˆ μˆ˜μ •
minkyung5x5 Nov 6, 2024
5ecbd76
✨ Feat: μ°Έμ—¬ν•œ λͺ¨μž„ νŽ˜μ΄μ§€ μΆ”κ°€
minkyung5x5 Nov 6, 2024
1d78a85
✨ Feat: gathering Detail Modal API μΆ”κ°€
minkyung5x5 Nov 6, 2024
a61c8be
Merge branch 'develop' into Feat/60/my-gathering-page
minkyung5x5 Nov 6, 2024
83bc73c
Merge branch 'develop' into Feat/60/my-gathering-page
minkyung5x5 Nov 6, 2024
46df06f
πŸ› fix: κ²½λ‘œμˆ˜μ •
minkyung5x5 Nov 6, 2024
1fc4c03
πŸ› fix: prettier error μˆ˜μ •
minkyung5x5 Nov 6, 2024
eb84994
πŸ› fix: api dummydata둜 μž„μ‹œ μˆ˜μ •
minkyung5x5 Nov 6, 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
35 changes: 35 additions & 0 deletions mock.json
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,40 @@
"isConfirmed": true,
"gatheringCount": 5
}
],
"gatheringDetail": [
{
"id": 1,
"title": "μ‹ λ‚˜λŠ” μš΄λ™...즐거운..μ½”λ”©..",
"introduce": "κ³΅μ§€μ‚¬ν•­μž…λ‹ˆλ‹€. λ‹€λ“€ 이번 약속 μžŠμ§€ μ•ŠμœΌμ…¨μ£ ? κΌ­ μ°Έμ—¬ λΆ€νƒλ“œλ¦½λ‹ˆλ‹€~",
"dateTime": "2024-10-29T00:32:12.306Z",
"location": "μ„œμšΈμ‹œ 강남ꡬ 역삼동 μ˜€ν”ΌμŠ€νƒ€μ›Œ 3μΈ΅",
"currentCount": 3,
"totalCount": 10,
"imageUrl": "https://www.dabur.com/Blogs/Doshas/Importance%20and%20Benefits%20of%20Yoga%201020x450.jpg",
"isLiked": false,
"isGatherCaptain": false,
"isParticipant": true,
"participants": [
{
"id": 1,
"profileImageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUMrcQB5OJ-ETzPc6wHnjxjC-36__MGw3JcA&s",
"nickname": "럽윈즈올",
"email": "[email protected]"
},
{
"id": 2,
"profileImageUrl": "https://imgcdn.stablediffusionweb.com/2024/5/13/c0541236-e690-4dff-a27e-30a0355e5ea0.jpg",
"nickname": "λͺ¨λ‹λŸ¬λ„ˆ",
"email": "[email protected]"
},
{
"id": 3,
"profileImageUrl": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUMrcQB5OJ-ETzPc6wHnjxjC-36__MGw3JcA&s",
"nickname": "동글동글이",
"email": "[email protected]"
}
]
}
]
}
11 changes: 11 additions & 0 deletions src/_apis/gathering/gathering-apis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { fetchApi } from '@/src/utils/api';
import { GatheringDetailType } from '@/src/types/gathering-data';

export function getGathering(): Promise<GatheringDetailType> {
return fetchApi<GatheringDetailType>('/gatheringDetail/1', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
}).then((response) => response); // TODO: data μΆ”μΆœ
}
11 changes: 11 additions & 0 deletions src/_queries/gathering/gathering-queries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { getGathering } from '@/src/_apis/gathering/gathering-apis';
import { transformKeysToCamel } from '@/src/utils/transform-keys';
import { GatheringDetailType } from '@/src/types/gathering-data';

export function useGetGatheringQuery() {
return {
queryKey: ['gatheringDetail'],
queryFn: getGathering,
select: (data: GatheringDetailType) => transformKeysToCamel(data),
};
}
2 changes: 1 addition & 1 deletion src/app/(crew)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function RootLayout({
<>
<Header />
<div className="flex min-h-screen flex-col items-center bg-gray-50">
<main className="container flex min-h-screen max-w-pc flex-col md:shadow-bg">
<main className="container flex min-h-screen max-w-pc flex-1 flex-col md:shadow-bg">
{children}
</main>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use client';

import { useMemo } from 'react';
import { formatDate } from '@/src/utils/format-date';
import ScheduledGatheringCard from '@/src/components/common/gathering-card/scheduled-gathering-card/container';
import { GatheringCardProps } from '@/src/types/gathering-data';

interface GatheringListWithDateProps {
gatheringList: GatheringCardProps[];
}

export default function GatheringListWithDate({ gatheringList }: GatheringListWithDateProps) {
const gatheringListWithDateInfo = useMemo(() => {
return gatheringList.map((gathering, index) => {
const isNewDate =
index === 0 ||
formatDate(gathering.dateTime).date !== formatDate(gatheringList[index - 1].dateTime).date;
return { ...gathering, isNewDate };
});
}, [gatheringList]);

return (
<div className="m-4 md:mt-[32.5px]">
{gatheringListWithDateInfo.map((gathering) => (
<div key={gathering.id} className="md:flex">
<div className="relative w-1/6 md:border-r-2 md:border-gray-200">
{gathering.isNewDate && (
<div>
<div className="md:corner-dot" />
<div className="hidden flex-nowrap md:block">
<div className="text-lg font-semibold">{formatDate(gathering.dateTime).date}</div>
<div className="text-base font-medium text-gray-500">μ›”μš”μΌ</div>
</div>
</div>
)}
</div>
<div className={`${gathering.isNewDate ? 'pb-' : 'p-'} flex-1 pb-6 md:pl-8`}>
<ScheduledGatheringCard key={gathering.id} data={gathering} />
</div>
</div>
))}
</div>
);
}
78 changes: 78 additions & 0 deletions src/app/(crew)/my-gathering/creation/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use client';

import { useEffect, useState } from 'react';
import GatheringListWithDate from '@/src/app/(crew)/my-gathering/_component/gathering-list-with-date';
import PopOverCalendar from '@/src/components/common/input/pop-over-calendar';
import { GatheringCardProps } from '@/src/types/gathering-data';

export default function CreationPage() {
const [selectedDate, setSelectedDate] = useState(new Date());

useEffect(() => {}, [selectedDate]);
const creationGatheringList: GatheringCardProps[] = [
{
id: 1,
crewTitle: 'Power Pole',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-10-30T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
{
id: 2,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-10-30T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
{
id: 3,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-11-11T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
{
id: 4,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-11-21T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
];

return (
<div className="">
<div className="pl-4 md:pt-2">
<PopOverCalendar value={selectedDate} onChange={(d) => setSelectedDate(d)} />
</div>
<GatheringListWithDate gatheringList={creationGatheringList} />
</div>
);
}
function setState(arg0: Date) {
throw new Error('Function not implemented.');
}
10 changes: 10 additions & 0 deletions src/app/(crew)/my-gathering/favorite/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import GatheringList from '@/src/components/gathering-list/gathering-list';
import { gatheringData } from '@/src/mock/gathering-data';

export default function FavoritePage() {
return (
<div className="md:mt-[45px]">
<GatheringList gatheringData={gatheringData} />
</div>
);
}
48 changes: 48 additions & 0 deletions src/app/(crew)/my-gathering/layout.tsx
Copy link
Contributor

Choose a reason for hiding this comment

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

μ΄λŸ°μ‹μœΌλ‘œλ„ ν•˜λŠ”κ΅°μš”.... μ—­μ‹œ 깔끔~~~ πŸ‘πŸ‘πŸ‘

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client';

import { useEffect, useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Button } from '@mantine/core';

const buttonData = [
{ id: 1, label: 'μ°Έμ—¬ν•œ 약속', route: '/my-gathering/participation' },
{ id: 2, label: 'λ§Œλ“  약속', route: '/my-gathering/creation' },
{ id: 3, label: 'μ°œν•œ 약속', route: '/my-gathering/favorite' },
];

const getSelectedButtonIndex = (currentPath: string) => {
return buttonData.findIndex(({ route }) => currentPath.endsWith(route.split('/').pop()!)) + 1;
};

export default function MyGatheringLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const currentPath = usePathname();

const [selectedButton, setSelectedButton] = useState(getSelectedButtonIndex(currentPath));

useEffect(() => {
const newIdx = getSelectedButtonIndex(currentPath);
setSelectedButton(newIdx);
}, [currentPath]);

return (
<div className="mt-4 md:mx-[46px] md:mt-[45px]">
<div className="m-4 grid grid-cols-3 gap-2 md:gap-4">
{buttonData.map(({ id, label, route }) => (
<Link key={id} href={route}>
<Button
className={`${id === selectedButton ? 'btn-filled' : 'btn-outlined'} w-full text-sm font-bold md:text-lg`}
>
{label}
</Button>
</Link>
))}
</div>
{children}
</div>
);
}
16 changes: 3 additions & 13 deletions src/app/(crew)/my-gathering/page.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
'use client';

import { useState } from 'react';
import CalendarFilter from '@/src/components/common/input/calendar-filter';

const toDoDates = [new Date('2024-10-12'), new Date('2024-10-15')];
import { redirect } from 'next/navigation';

export default function MyGatheringPage() {
const [date, setDate] = useState<Date>(new Date());

return (
<div className="container mx-auto my-0 max-w-pc px-5 lg:px-0">
<CalendarFilter value={date} toDoDates={toDoDates} onChange={setDate} />
</div>
);
redirect('/my-gathering/participation');
return null;
}
65 changes: 65 additions & 0 deletions src/app/(crew)/my-gathering/participation/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use client';

import { useEffect, useState } from 'react';
import GatheringListWithDate from '@/src/app/(crew)/my-gathering/_component/gathering-list-with-date';
import PopOverCalendar from '@/src/components/common/input/pop-over-calendar';
import { GatheringCardProps } from '@/src/types/gathering-data';

export default function ParticipationPage() {
const [selectedDate, setSelectedDate] = useState(new Date());

useEffect(() => {}, [selectedDate]);
const creationGatheringList: GatheringCardProps[] = [
{
id: 1,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-10-30T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
{
id: 2,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-10-30T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
{
id: 3,
crewTitle: 'ν’€ μ—” 그레이슀 μŠ€νŠœλ””μ˜€',
crewMainLocation: 'μ„œμšΈμ‹œ',
crewSubLocation: '강남ꡬ 역삼동',
title: 'κ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€λ‚˜λ‹€λΌλ§ˆκ°€',
dateTime: '2024-10-31T00:30',
currentCount: 8,
totalCount: 12,
imageUrl:
'https://images.unsplash.com/photo-1601758260892-a62c486ace97?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
isLiked: true,
},
];

return (
<div className="">
<div className="pl-4 md:pt-2">
<PopOverCalendar value={selectedDate} onChange={(d) => setSelectedDate(d)} />
</div>
<GatheringListWithDate gatheringList={creationGatheringList} />
</div>
);
}
function setState(arg0: Date) {
throw new Error('Function not implemented.');
}
Loading