Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const nextConfig = {
//로컬 이미지 테스트 하기 위해 localhost를 넣었습니다.
domains: ["sprint-fe-project.s3.ap-northeast-2.amazonaws.com", "localhost"],
},
reactStrictMode: false,

Choose a reason for hiding this comment

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

로컬에서 작업하시면서 strict껐으면 git으로는 추적 안하는게 좋을것 같아요

Copy link
Owner Author

Choose a reason for hiding this comment

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

안 그래도 이 부분 지우는 걸 잊고 있었는데, 우선 다음 작업까지 하고 다시 true로 해놓겠습니다!

};

export default nextConfig;
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client";

import { useModalStore } from "@/lib/store/useModalStore";
import Button from "@/components/common/button/Button";
import Image from "next/image";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,79 @@
"use client";

import { useEffect, useState, useRef } from "react";
import { DashboardColumn, TaskCardList } from "@/lib/types";
import { fetchTaskCardList } from "@/lib/apis/cardsApi";
import { TOKEN_1 } from "@/lib/constants/tokens";
import EditColumnButton from "./EditColumnButton";
import AddTaskButton from "./AddTaskButton";
import TaskCard from "./TaskCard";

export default async function Column({ id, title }: DashboardColumn) {
const { cards, totalCount, cursorId } = await fetchTaskCardList({
token: TOKEN_1,
id: id,
});
const items: TaskCardList[] = cards;
const PAGE_SIZE = 3;

export default function Column({ id, title }: DashboardColumn) {
const [items, setItems] = useState<TaskCardList[]>([]);
const [cursorId, setCursorId] = useState<number | null>(null);
const [totalCount, setTotalCount] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const [isLast, setIsLast] = useState(false);
const observerRef = useRef<HTMLDivElement | null>(null);

const handleLoad = async () => {
if (isLoading || isLast) return;
setIsLoading(true);

try {
const {
cards: newCards,
cursorId: nextCursorId,
totalCount,
} = await fetchTaskCardList({
token: TOKEN_1,
size: PAGE_SIZE,
cursorId,
columnId: id,
});

setItems((prev) => [...prev, ...newCards]);
setCursorId(nextCursorId);
setTotalCount(totalCount);

if (newCards.length < PAGE_SIZE || nextCursorId === null) {
setIsLast(true);
}
} finally {
setIsLoading(false);
}
};

useEffect(() => {
handleLoad();
}, []);

// 해당 값 사용하게 되면(페이지네이션) 지울 테스트 코드
console.log(cursorId);
useEffect(() => {
if (isLast) return;

const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
handleLoad();
}
},
{ threshold: 0.5 }
);

const current = observerRef.current;
if (current) observer.observe(current);

return () => {
if (current) observer.unobserve(current);
observer.disconnect();
};
}, [cursorId, isLoading, isLast]);
Comment on lines +53 to +72

Choose a reason for hiding this comment

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

observer하는거는 재사용의 목적 + 이 페이지에서는 비즈니스로직일 필요가 없어보여서 추상화해보면 좋겠네요.
useIntersection같은 커스텀훅으로요

Copy link
Owner Author

@hyeonjiroh hyeonjiroh Mar 29, 2025

Choose a reason for hiding this comment

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

다른 곳에서도 무한 스크롤을 사용해서 추상화해보면 좋겠네요. 의견 감사합니다!


return (
<div className="py-4 border-b border-gray-300 tablet:px-5 tablet:pt-[22px] tablet:pb-5 pc:border-b-0 pc:border-r">
<div className="flex flex-col gap-6 tablet:gap-[25px]">
<div className="h-full py-4 border-b border-gray-300 tablet:px-5 tablet:pt-[22px] tablet:pb-5 pc:border-b-0 pc:border-r">
<div className="flex flex-col gap-6 h-full tablet:gap-[25px]">
<div className="flex justify-between">
<div className="flex gap-3 items-center">
<div className="flex gap-2 items-center">
Expand All @@ -32,11 +88,20 @@ export default async function Column({ id, title }: DashboardColumn) {
</div>
<EditColumnButton columnId={id} columnTitle={title} />
</div>
<div className="flex flex-col gap-[10px] tablet:gap-4">
<AddTaskButton />
{items.map((item) => (
<TaskCard key={item.id} {...item} columnTitle={title} />
))}
<div className="flex flex-col gap-[10px] flex-grow min-h-0 tablet:gap-4">
<div>
<AddTaskButton />
</div>
<div className="flex flex-col gap-[10px] flex-grow min-h-0 overflow-y-auto whitespace-nowrap scrollbar-hide tablet:gap-4">
{items.map((item, index) => (
<div
key={item.id}
ref={index === items.length - 1 ? observerRef : null}
>
<TaskCard {...item} columnTitle={title} />
</div>
))}
</div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client";

import { useModalStore } from "@/lib/store/useModalStore";
import { useColumnStore } from "@/lib/store/useColumnStore";
import Image from "next/image";
Expand Down
15 changes: 12 additions & 3 deletions src/lib/apis/cardsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@ import { BASE_URL } from "@/lib/constants/urls";

export async function fetchTaskCardList({
token,
id,
size,
cursorId,
columnId,
}: {
token: string;
id: number;
size: number;
cursorId: number | null;
columnId: number;
}) {
const res = await fetch(`${BASE_URL}/cards?size=10&columnId=${id}`, {
let query = `size=${size}&columnId=${columnId}`;
if (cursorId !== null) {
query += `&cursorId=${cursorId}`;
}
Comment on lines +14 to +17

Choose a reason for hiding this comment

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

여기도 다른분들 생산성을 위해서 query로 붙여주는 함수로 한번 분리해보는것도 좋겠네요.
저는 exceptEmptyValue라는 함수를 만들어서 값이 없는 인자는 쿼리를 안붙이도록 만들어서 쓰고 있어요.

Copy link
Owner Author

Choose a reason for hiding this comment

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

감사합니다 고려해보고 해보도록 하겠습니다!


const res = await fetch(`${BASE_URL}/cards?${query}`, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${token}`,
Expand Down