diff --git a/src/app/(crew)/my-crew/hosted/page.tsx b/src/app/(crew)/my-crew/hosted/page.tsx
index 4f0f330c..6e388ca6 100644
--- a/src/app/(crew)/my-crew/hosted/page.tsx
+++ b/src/app/(crew)/my-crew/hosted/page.tsx
@@ -4,6 +4,7 @@ import { Loader } from '@mantine/core';
import { useGetMyCrewHostedQuery } from '@/src/_queries/crew/my-crew-hosted-list-query';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import CrewCardList from '@/src/components/common/crew-list/crew-card-list';
+import CrewSkeletonList from '@/src/components/common/skeleton/crew-skeleton-list';
export default function MyCrewHostedPage() {
const { data, isLoading, error, ref, isFetchingNextPage } = useInfiniteScroll(
@@ -15,9 +16,7 @@ export default function MyCrewHostedPage() {
{isLoading || isFetchingNextPage ? (
-
-
-
+
) : (
)}
diff --git a/src/app/(crew)/my-crew/joined/page.tsx b/src/app/(crew)/my-crew/joined/page.tsx
index e016ecae..23c47f14 100644
--- a/src/app/(crew)/my-crew/joined/page.tsx
+++ b/src/app/(crew)/my-crew/joined/page.tsx
@@ -4,6 +4,7 @@ import { Loader } from '@mantine/core';
import { useGetMyCrewJoinedQuery } from '@/src/_queries/crew/my-crew-joined-list-query';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
import CrewCardList from '@/src/components/common/crew-list/crew-card-list';
+import CrewSkeletonList from '@/src/components/common/skeleton/crew-skeleton-list';
export default function MyCrewJoinedPage() {
const { data, isLoading, error, ref, isFetchingNextPage } = useInfiniteScroll(
@@ -15,9 +16,7 @@ export default function MyCrewJoinedPage() {
{isLoading || isFetchingNextPage ? (
-
-
-
+
) : (
)}
diff --git a/src/app/(crew)/my-gathering/hosted/page.tsx b/src/app/(crew)/my-gathering/hosted/page.tsx
index 8fd6fd23..8a122dee 100644
--- a/src/app/(crew)/my-gathering/hosted/page.tsx
+++ b/src/app/(crew)/my-gathering/hosted/page.tsx
@@ -6,13 +6,14 @@ import { useGetHostedGatheringListQuery } from '@/src/_queries/my-gathering/host
import { formatDateToRequest } from '@/src/utils/format-date';
import GatheringListWithDate from '@/src/app/(crew)/my-gathering/_component/gathering-list-with-date';
import PopOverCalendar from '@/src/components/common/input/pop-over-calendar';
+import MyGatheringSkeletonList from '@/src/components/common/skeleton/my-gathering-skeleton-list';
import { GatheringCardProps } from '@/src/types/gathering-data';
export default function MyGatheringHostedPage() {
const [selectedDate, setSelectedDate] = useState(new Date());
const [hostedGatheringList, setHostedGatheringList] = useState
();
- const { data, refetch } = useQuery(
+ const { data, isLoading, refetch } = useQuery(
useGetHostedGatheringListQuery(formatDateToRequest(selectedDate)),
);
@@ -29,6 +30,7 @@ export default function MyGatheringHostedPage() {
+ {isLoading && }
{hostedGatheringList && }
);
diff --git a/src/app/(crew)/my-gathering/joined/page.tsx b/src/app/(crew)/my-gathering/joined/page.tsx
index 9ba850a4..d4233a58 100644
--- a/src/app/(crew)/my-gathering/joined/page.tsx
+++ b/src/app/(crew)/my-gathering/joined/page.tsx
@@ -6,13 +6,14 @@ import { useGetJoinedGatheringListQuery } from '@/src/_queries/my-gathering/join
import { formatDateToRequest } from '@/src/utils/format-date';
import GatheringListWithDate from '@/src/app/(crew)/my-gathering/_component/gathering-list-with-date';
import PopOverCalendar from '@/src/components/common/input/pop-over-calendar';
+import MyGatheringSkeletonList from '@/src/components/common/skeleton/my-gathering-skeleton-list';
import { GatheringCardProps } from '@/src/types/gathering-data';
export default function MyGatheringJoinedPage() {
const [selectedDate, setSelectedDate] = useState(new Date());
const [joinedGatheringList, setJoinedGatheringList] = useState
();
- const { data, refetch } = useQuery(
+ const { data, isLoading, refetch } = useQuery(
useGetJoinedGatheringListQuery(formatDateToRequest(selectedDate)),
);
@@ -29,6 +30,7 @@ export default function MyGatheringJoinedPage() {
+ {isLoading && }
{joinedGatheringList && }
);
diff --git a/src/app/(crew)/my-page/_components/profile-card/container.tsx b/src/app/(crew)/my-page/_components/profile-card/container.tsx
index 2f548646..a5ffb981 100644
--- a/src/app/(crew)/my-page/_components/profile-card/container.tsx
+++ b/src/app/(crew)/my-page/_components/profile-card/container.tsx
@@ -10,6 +10,7 @@ import {
} from '@/src/_apis/auth/user-apis';
import { useUser } from '@/src/_queries/auth/user-queries';
import { useAuth } from '@/src/hooks/use-auth';
+import ProfileSkeleton from '@/src/components/common/skeleton/profile-skeleton';
import ProfileCardPresenter from './presenter';
export default function ProfileCard() {
@@ -38,7 +39,7 @@ export default function ProfileCard() {
}
}, [user]);
- if (userLoading || !isAuthChecked) return 로딩 중...
;
+ if (userLoading || !isAuthChecked) return ;
if (!user) return null;
const handleEdit = () => {
diff --git a/src/app/(crew)/page.tsx b/src/app/(crew)/page.tsx
index f7bdca76..76ed33d2 100644
--- a/src/app/(crew)/page.tsx
+++ b/src/app/(crew)/page.tsx
@@ -2,7 +2,7 @@
import { useRef, useState } from 'react';
import Image from 'next/image';
-import { Divider, Loader, TextInput } from '@mantine/core';
+import { Divider, Loader, Skeleton, TextInput } from '@mantine/core';
import { useGetCrewListQuery } from '@/src/_queries/crew/crew-list-queries';
import regionData from '@/src/data/region.json';
import { useInfiniteScroll } from '@/src/hooks/use-infinite-scroll';
@@ -11,6 +11,7 @@ import HeroCrew from '@/src/app/(crew)/_components/hero/hero-crew';
import CrewCardList from '@/src/components/common/crew-list/crew-card-list';
import Button from '@/src/components/common/input/button';
import DropDown from '@/src/components/common/input/drop-down';
+import CrewSkeletonList from '@/src/components/common/skeleton/crew-skeleton-list';
import IcoSearch from '@/public/assets/icons/ic-search.svg';
export default function HomePage() {
@@ -133,9 +134,7 @@ export default function HomePage() {
{data &&
}
{isLoading || isFetchingNextPage ? (
-
-
-
+
) : (
)}
diff --git a/src/components/common/crew-list/crew-card-list.tsx b/src/components/common/crew-list/crew-card-list.tsx
index 26bd3a53..c6482646 100644
--- a/src/components/common/crew-list/crew-card-list.tsx
+++ b/src/components/common/crew-list/crew-card-list.tsx
@@ -33,7 +33,7 @@ export default function CrewCardList({ data, inWhere }: CrewCardListProps) {
);
return (
-
+
{crewDataList.map((inform) => (
-
router.push(CREWPAGE)}
- className="relative mx-auto flex h-[430px] w-full animate-fade cursor-pointer flex-col overflow-hidden rounded-[14px] bg-white shadow-bg md:h-[203px] md:flex-row"
+ className="relative mx-auto flex w-full animate-fade cursor-pointer flex-col overflow-hidden rounded-[14px] bg-white transition-shadow hover:shadow-card md:h-[203px] md:flex-row"
>
{/* 썸네일 */}
-
+
@@ -66,7 +66,7 @@ export default function CrewCard({
{`현재 ${totalGatheringCount}개의 약속이 개설되어 있습니다.`}
-
+
diff --git a/src/components/common/input/date-time-picker/index.tsx b/src/components/common/input/date-time-picker/index.tsx
index a20ecec7..e959f59d 100644
--- a/src/components/common/input/date-time-picker/index.tsx
+++ b/src/components/common/input/date-time-picker/index.tsx
@@ -18,10 +18,18 @@ export default function DateTimePicker({ fullDate, onChange }: DateTimePickerPro
const [minute, setMinute] = useState
('분');
const handleSelect = (date: Date) => {
+ const newDate = new Date(selected);
const isSelected = selected;
+ newDate.setFullYear(Number(date.getFullYear()));
+ newDate.setMonth(Number(date.getMonth()));
+ newDate.setDate(Number(date.getDate()));
+
+ const kstDate = new Date(newDate.getTime() - newDate.getTimezoneOffset() * 60000).toISOString();
+
if (isSelected) {
- setSelected(date);
+ setSelected(newDate);
+ onChange(kstDate);
}
};
@@ -53,7 +61,7 @@ export default function DateTimePicker({ fullDate, onChange }: DateTimePickerPro
})}
firstDayOfWeek={0}
classNames={{
- day: 'w-full aspect-square text-gray-800 data-[selected=true]:text-white flex',
+ day: 'w-full aspect-square text-gray-800 data-[selected=true]:text-white data-[selected=true]:rounded-xl flex',
monthCell: 'w-[calc(14.285vw-5.714px)] aspect-square md:w-[85px]',
monthsListCell:
'w-[calc(33.333vw-13.333px)] h-[10vw] md:w-[200px] md:h-[80px] text-gray-800',
diff --git a/src/components/common/skeleton/crew-skeleton-list/index.tsx b/src/components/common/skeleton/crew-skeleton-list/index.tsx
new file mode 100644
index 00000000..a5ff327f
--- /dev/null
+++ b/src/components/common/skeleton/crew-skeleton-list/index.tsx
@@ -0,0 +1,18 @@
+import CrewSkeleton from '../crew-skeleton';
+
+interface CrewSkeletonListProps {
+ num: number;
+ column?: number;
+}
+
+export default function CrewSkeletonList({ num, column }: CrewSkeletonListProps) {
+ const columnStyle = column === 2 ? 'lg:grid-cols-2' : 'lg:grid-cols-1';
+ return (
+
+ {[...Array(num)].map((_, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ ))}
+
+ );
+}
diff --git a/src/components/common/skeleton/crew-skeleton/index.tsx b/src/components/common/skeleton/crew-skeleton/index.tsx
new file mode 100644
index 00000000..f434225f
--- /dev/null
+++ b/src/components/common/skeleton/crew-skeleton/index.tsx
@@ -0,0 +1,15 @@
+import { Skeleton } from '@mantine/core';
+
+export default function CrewSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/common/skeleton/gathering-skeleton-list/index.tsx b/src/components/common/skeleton/gathering-skeleton-list/index.tsx
new file mode 100644
index 00000000..23a18a66
--- /dev/null
+++ b/src/components/common/skeleton/gathering-skeleton-list/index.tsx
@@ -0,0 +1,19 @@
+import GatheringSkeleton from '../gathering-skeleton';
+
+interface GatheringSkeletonListProps {
+ num: number;
+}
+
+export default function GatheringSkeletonList({ num }: GatheringSkeletonListProps) {
+ return (
+
+ {[...Array(num)].map((_, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ ))}
+
+ );
+}
diff --git a/src/components/common/skeleton/gathering-skeleton/index.tsx b/src/components/common/skeleton/gathering-skeleton/index.tsx
new file mode 100644
index 00000000..ec23a40d
--- /dev/null
+++ b/src/components/common/skeleton/gathering-skeleton/index.tsx
@@ -0,0 +1,16 @@
+import { Skeleton } from '@mantine/core';
+
+export default function GatheringSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/common/skeleton/my-gathering-skeleton-list/index.tsx b/src/components/common/skeleton/my-gathering-skeleton-list/index.tsx
new file mode 100644
index 00000000..d6934600
--- /dev/null
+++ b/src/components/common/skeleton/my-gathering-skeleton-list/index.tsx
@@ -0,0 +1,30 @@
+import { Skeleton } from '@mantine/core';
+import MyGatheringSkeleton from '../my-gathering-skeleton';
+
+interface MyGatheringSkeletonListProps {
+ num: number;
+}
+
+export default function MyGatheringSkeletonList({ num }: MyGatheringSkeletonListProps) {
+ return (
+
+ {[...Array(num)].map((_, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ ))}
+
+ );
+}
diff --git a/src/components/common/skeleton/my-gathering-skeleton/index.tsx b/src/components/common/skeleton/my-gathering-skeleton/index.tsx
new file mode 100644
index 00000000..8ff661b6
--- /dev/null
+++ b/src/components/common/skeleton/my-gathering-skeleton/index.tsx
@@ -0,0 +1,17 @@
+import { Skeleton } from '@mantine/core';
+
+export default function MyGatheringSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/common/skeleton/my-review-skeleton-list/index.tsx b/src/components/common/skeleton/my-review-skeleton-list/index.tsx
new file mode 100644
index 00000000..e27836fd
--- /dev/null
+++ b/src/components/common/skeleton/my-review-skeleton-list/index.tsx
@@ -0,0 +1,16 @@
+import MyReviewSkeleton from '../my-review-skeleton';
+
+interface MyReviewSkeletonListProps {
+ num: number;
+}
+
+export default function MyReviewSkeletonList({ num }: MyReviewSkeletonListProps) {
+ return (
+
+ {[...Array(num)].map((_, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ ))}
+
+ );
+}
diff --git a/src/components/common/skeleton/my-review-skeleton/index.tsx b/src/components/common/skeleton/my-review-skeleton/index.tsx
new file mode 100644
index 00000000..057ededf
--- /dev/null
+++ b/src/components/common/skeleton/my-review-skeleton/index.tsx
@@ -0,0 +1,16 @@
+import { Skeleton } from '@mantine/core';
+
+export default function MyReviewSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/common/skeleton/profile-skeleton/index.tsx b/src/components/common/skeleton/profile-skeleton/index.tsx
new file mode 100644
index 00000000..ef523718
--- /dev/null
+++ b/src/components/common/skeleton/profile-skeleton/index.tsx
@@ -0,0 +1,13 @@
+import { Skeleton } from '@mantine/core';
+
+export default function ProfileSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx b/src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx
new file mode 100644
index 00000000..3a749f9f
--- /dev/null
+++ b/src/components/common/skeleton/reviewable-review-skeleton-list/index.tsx
@@ -0,0 +1,16 @@
+import ReviewableReviewSkeleton from '../reviewable-review-skeleton';
+
+interface ReviewableReviewSkeletonListProps {
+ num: number;
+}
+
+export default function ReviewableReviewSkeletonList({ num }: ReviewableReviewSkeletonListProps) {
+ return (
+
+ {[...Array(num)].map((_, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ ))}
+
+ );
+}
diff --git a/src/components/common/skeleton/reviewable-review-skeleton/index.tsx b/src/components/common/skeleton/reviewable-review-skeleton/index.tsx
new file mode 100644
index 00000000..d8660d94
--- /dev/null
+++ b/src/components/common/skeleton/reviewable-review-skeleton/index.tsx
@@ -0,0 +1,15 @@
+import { Skeleton } from '@mantine/core';
+
+export default function ReviewableReviewSkeleton() {
+ return (
+
+ );
+}
diff --git a/src/components/gathering-list/liked-list-container.tsx b/src/components/gathering-list/liked-list-container.tsx
index a800d8a6..6cb1a3b9 100644
--- a/src/components/gathering-list/liked-list-container.tsx
+++ b/src/components/gathering-list/liked-list-container.tsx
@@ -5,6 +5,7 @@ import { toast } from 'react-toastify';
import { addLike, removeLike } from '@/src/_apis/liked/liked-apis';
import { useGetLikedListQuery } from '@/src/_queries/liked/liked-queries';
import { ApiError } from '@/src/utils/api';
+import GatheringSkeletonList from '../common/skeleton/gathering-skeleton-list';
import LikedListPresenter from './liked-list-presenter';
export default function LikedList() {
@@ -37,7 +38,12 @@ export default function LikedList() {
setPage(newPage);
};
- if (isLoading) return 로딩중...
;
+ if (isLoading)
+ return (
+
+
+
+ );
// 에러 처리: error 또는 gatheringData가 undefined일 경우
if (error || gatheringData === undefined) {
diff --git a/tailwind.config.ts b/tailwind.config.ts
index dda96831..a90479ca 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -121,6 +121,7 @@ const config: Config = {
boxShadow: {
xl: '0 4px 4px 0 rgba(0,0,0,0.25)',
bg: '0 4px 30px 1px rgba(0,122,255,0.04)',
+ card: '0 4px 15px 1px rgba(0,122,255,0.1)',
xs: '0px 2px 4px 0px rgba(0, 0, 0, 0.02)',
},
keyframes: {