Skip to content
7 changes: 4 additions & 3 deletions src/app/(route)/completes/[completeId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PageContainer } from '@/components/common/PageContainer';
import { CompleteComments } from '@/components/Complete/Comments';
import { CompleteHeader } from '@/components/Complete/CompleteHeader';
import { CompletePost } from '@/components/Complete/Post';
Expand All @@ -12,15 +13,15 @@ export default async function CompletePage({
params: Promise<CompletePageProps>;
}) {
const { completeId } = await params;

return (
<div className="flex min-h-screen w-screen flex-col gap-16 bg-custom-white-100 py-16 md:px-200 xl:px-400 2xl:px-650">
<PageContainer className="!px-0">
<CompleteHeader />

<CompletePost completeId={completeId} />

<div className="h-6 bg-custom-white-200" />

<CompleteComments completeId={completeId} />
</div>
</PageContainer>
);
}
6 changes: 4 additions & 2 deletions src/components/Complete/Comments/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use client';

import { useRouter } from 'next/navigation';

import { FollowsSkeleton } from '@/components/Skeletons/FollowsSkeleton';
import { useGetCompleteDetailQuery } from '@/hooks/apis/Complete/useGetCompleteDetailQuery';
import { CommentList } from './CommentList';

import { CommentInput } from './CommentInput';
import { CommentList } from './CommentList';

interface CompleteCommentsProps {
completeId: number;
Expand All @@ -23,7 +25,7 @@ export const CompleteComments = (props: CompleteCommentsProps) => {
}

return (
<div className="relative pb-20">
<div className="relative">
{isLoading ? (
<FollowsSkeleton />
) : complete ? (
Expand Down
7 changes: 4 additions & 3 deletions src/components/Complete/Post/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use client';

import { useRouter } from 'next/navigation';
import { FollowsSkeleton } from '@/components/Skeletons/FollowsSkeleton';
import { useGetCompleteDetailQuery } from '@/hooks/apis/Complete/useGetCompleteDetailQuery';

import { PostContent } from '@/components/Follows/Post/PostContent';
import { PostImage } from '@/components/Follows/Post/PostImage';
import { PostLike } from '@/components/Follows/Post/PostLike';
import { PostProfile } from '@/components/Follows/Post/PostProfile';
import { FollowsSkeleton } from '@/components/Skeletons/FollowsSkeleton';
import { useGetCompleteDetailQuery } from '@/hooks/apis/Complete/useGetCompleteDetailQuery';
import { PostGoalAndTodo } from './PostGoalAndTodo';

interface CompletePostProps {
Expand All @@ -32,7 +33,7 @@ export const CompletePost = (props: CompletePostProps) => {
{isLoading ? (
<FollowsSkeleton />
) : complete ? (
<div className="w-screen flex-col">
<div className="w-full flex-col">
<div className="mr-16 flex justify-between">
<PostProfile
createdAt={complete.createdAt}
Expand Down
41 changes: 27 additions & 14 deletions src/components/Dashboard/Follower/FollowerStory/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
import { FaHeart } from 'react-icons/fa6';
import Image from 'next/image';
import { useRouter } from 'next/navigation';

import { FollowerTypes } from '@/mocks/followerData';
import { cn } from '@/utils/className';
import { ContentTypes } from '@/types/data';
import { formatDateToRelativeTime } from '@/utils/date';

interface FollowerStoryProps {
follower: FollowerTypes;
follower: ContentTypes;
}

export const FollowerStory = ({ follower }: FollowerStoryProps) => {
const heartClass = cn(
'absolute right-8 top-8 size-28 p-4',
follower.likeStatus ? 'text-error' : 'text-custom-gray-200',
);
const router = useRouter();
const pic = follower.completePic;

const handleClickImage = () => {
router.push(`/completes/${follower.completeId}`);
};

return (
<div className="shrink-0 snap-start">
<div className="relative size-120 rounded-20 bg-custom-white-300">
<FaHeart className={heartClass} />
</div>
<div className="pt-8">
<span className="mr-4 text-xs-medium">{follower.name}</span>
<div
onClick={handleClickImage}
className="shrink-0 cursor-pointer snap-start"
>
{pic ? (
<Image
src={pic}
width={120}
height={120}
alt="νŒ”λ‘œμ›Œ 인증 사진"
className="size-120 rounded-20 object-cover"
/>
) : (
<div className="size-120 rounded-20 bg-custom-gray-100" />
)}
<div className="ml-4 pt-8">
<span className="mr-4 text-xs-medium">{follower.username}</span>
<span className="text-xs-normal text-custom-gray-200">
{formatDateToRelativeTime(follower.createdAt)}
</span>
Expand Down
25 changes: 21 additions & 4 deletions src/components/Dashboard/Follower/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,42 @@
'use client';

import { Card } from '@/components/common/Card';
import { Spinner } from '@/components/common/Spinner';
import { DashboardItemContainer } from '@/components/Dashboard/DashboardItemContainer';
import { FOLLOWER_DATA } from '@/mocks/followerData';
import { FollowStorySkeleton } from '@/components/Skeletons/FollowStorySkeleton';
import { useGetFollowPosts } from '@/hooks/apis/Follows/useGetFollowPostsQuery';
import { useInfiniteScroll } from '@/hooks/useInfiniteScroll';
import { FollowerStory } from './FollowerStory';

export const Follwer = () => {
const { follows, isLoading, fetchNextPage, isFetchingNextPage } =
useGetFollowPosts();
const { observerRef } = useInfiniteScroll({ fetchNextPage, isLoading });

return (
<DashboardItemContainer
title="νŒ”λ‘œμ›Œ ν˜„ν™©"
className="relative mb-22 mt-16"
>
{FOLLOWER_DATA.length === 0 ? (
{isLoading ? (
<FollowStorySkeleton />
) : follows.length === 0 ? (
<Card>
<p className="text-sm-normal text-custom-gray-100">
찍찍이듀 νŒ”λ‘œμš° ν•˜κ³  인증 보기
</p>
</Card>
) : (
<div className="flex snap-x snap-mandatory items-center gap-8 overflow-x-scroll scrollbar-hide">
{FOLLOWER_DATA.map((follower) => (
<FollowerStory key={follower.id} follower={follower} />
{follows.map((follower) => (
<FollowerStory key={follower.completeId} follower={follower} />
))}
{isFetchingNextPage && (
<span className="flex w-full justify-center">
<Spinner className="size-18" />
</span>
)}
<div ref={observerRef} style={{ width: '1px' }} />
</div>
)}
<div className="absolute -bottom-22 -left-16 h-6 w-[calc(100%+32px)] bg-custom-white-200" />
Expand Down
8 changes: 4 additions & 4 deletions src/components/Follows/FollowsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useRouter } from 'next/navigation';

import { useGetFollowPosts } from '@/hooks/apis/Follows/useGetFollowPostsQuery';
import { useInfiniteScroll } from '@/hooks/useInfiniteScroll';
import { FollowsSkeleton } from '../Skeletons/FollowsSkeleton';
Expand All @@ -23,12 +24,11 @@ export const FollowsContainer = () => {
}

return (
<PageContainer className="!px-0">
<div>
<h1 className="fixed h-44 px-16 py-8 text-xl-semibold text-custom-gray-300">
<PageContainer className="!px-0 !pt-0">
<div className="relative pt-48 md:pt-0">
<h1 className="sticky right-0 top-48 h-44 w-full bg-custom-white-100 px-16 py-8 text-xl-semibold text-custom-gray-300 md:top-0">
νŒ”λ‘œμ›Œ
</h1>
<div className="mb-8 h-48" />
{isLoading ? (
<FollowsSkeleton />
) : follows.length > 0 ? (
Expand Down
3 changes: 1 addition & 2 deletions src/components/Follows/Post/PostImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function PostImage(props: PostImageProps) {
if (!completePic) {
return (
<div
className="my-8 aspect-square cursor-pointer bg-slate-600"
className="my-8 aspect-square cursor-pointer bg-slate-600"
onClick={handleClickImage}
/>
);
Expand All @@ -27,7 +27,6 @@ export function PostImage(props: PostImageProps) {
<Image
src={completePic}
alt="post-image"
sizes="100vw"
width={100}
height={100}
className="my-8 aspect-square w-full cursor-pointer"
Expand Down
8 changes: 4 additions & 4 deletions src/components/Follows/Post/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { ContentTypes } from '@/types/data';
import { PostProfile } from './PostProfile';
import { PostImage } from './PostImage';
import { PostLike } from './PostLike';
import { PostComments } from './PostComments';
import { PostContent } from './PostContent';
import { PostImage } from './PostImage';
import { PostLike } from './PostLike';
import { PostProfile } from './PostProfile';

interface PostProps {
post: ContentTypes;
Expand All @@ -13,7 +13,7 @@ export function Post(props: PostProps) {
const { post } = props;

return (
<div className="w-screen flex-col gap-16 pb-24">
<div className="w-full flex-col gap-16 pb-24">
<PostProfile
createdAt={post.createdAt}
username={post.username}
Expand Down
24 changes: 20 additions & 4 deletions src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {
FaFire,
FaFlag,
FaListUl,
FaMagnifyingGlass,
} from 'react-icons/fa6';

import { useRouter } from 'next/navigation';
import { usePathname, useRouter } from 'next/navigation';

import Link from 'next/link';
import LogoIcon from '@/assets/svg/svg-logo-icon.svg';
import LogoSide from '@/assets/svg/svg-logo-side.svg';
import { GoalList } from '@/components/Sidebar/GoalList';
Expand All @@ -29,6 +29,7 @@ import { cn } from '@/utils/className';

export const Sidebar = () => {
const router = useRouter();
const path = usePathname();

const { goals } = useGoalsQuery();

Expand Down Expand Up @@ -58,10 +59,17 @@ export const Sidebar = () => {
return (
<div className={sidebarClass}>
<div className={iconContainerClass}>
<Link href="/dashboard">{isOpen ? <LogoSide /> : <LogoIcon />}</Link>
<div
onClick={() => {
router.push('/dashboard');
close();
}}
>
{isOpen ? <LogoSide /> : <LogoIcon />}
</div>
{isOpen ? (
<FaAnglesLeft
className="size-28 cursor-pointer p-4 text-slate-400"
className="size-28 cursor-pointer p-4 text-custom-gray-200"
onClick={close}
/>
) : (
Expand All @@ -70,6 +78,14 @@ export const Sidebar = () => {
onClick={open}
/>
)}
{path === '/follows' && !isOpen && (
<FaMagnifyingGlass
className="size-28 cursor-pointer p-4 text-primary-100"
onClick={() => {
router.push('/search');
}}
/>
)}
</div>
{isOpen && (
<div className="flex w-full flex-col items-center">
Expand Down
17 changes: 17 additions & 0 deletions src/components/Skeletons/FollowStorySkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Skeleton } from '@/components/common/Skeleton';

export const FollowStorySkeleton = () => {
return (
<div className="flex items-center gap-8">
{Array.from({ length: 3 }).map((_, index) => (
<div key={index}>
<Skeleton className="size-120 rounded-20" />
<div className="ml-4 mt-15 flex items-center gap-8">
<Skeleton className="h-14 w-70 rounded-12" />
<Skeleton className="h-14 w-35 rounded-12" />
</div>
</div>
))}
</div>
);
};
5 changes: 3 additions & 2 deletions src/components/common/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import { FaBarsStaggered, FaBell, FaMagnifyingGlass } from 'react-icons/fa6';
import { useRouter } from 'next/navigation';
import { FaBars, FaBell, FaMagnifyingGlass } from 'react-icons/fa6';

import { useSidebarStore } from '@/store/useSidebarStore';

interface HeaderProps {
Expand All @@ -20,7 +21,7 @@ export const Header = ({ title = '', search = false }: HeaderProps) => {
return (
<div className="fixed left-0 top-0 z-10 flex h-48 w-full items-center justify-between bg-white px-16 md:hidden">
<div className="flex items-center">
<FaBarsStaggered
<FaBars
className="w-24 cursor-pointer text-primary-100"
onClick={open}
style={{ strokeWidth: 15 }}
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/apis/Dashboard/useTodosOfGoalsQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const todosOfGoalsOptions = (): UseInfiniteQueryOptions<
queryKey: [QUERY_KEYS.TODOS_OF_GOALS],
queryFn: ({ pageParam = 0 }) =>
GET<TodosOfGoalsResponse>(
`${API_ENDPOINTS.TODOS.GET_GOALS}?lastGoalId=${pageParam}&size=3`,
`${API_ENDPOINTS.TODOS.GET_GOALS}?lastGoalId=${pageParam}&size=5`,
),
getNextPageParam: (lastPage) => {
const nextCursor = lastPage.data.nextCursor;
Expand Down
Loading
Loading