Skip to content

Commit 0d52610

Browse files
committed
hotfeat: suspense
1 parent 7c1f838 commit 0d52610

2 files changed

Lines changed: 68 additions & 14 deletions

File tree

src/components/common/loading/LoadingComponents.jsx

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,56 @@ export function WeeklyScheduleSkeleton() {
9595
);
9696
}
9797

98-
// ProjectList용 Skeleton UI
98+
// ProjectCard용 Skeleton UI
99+
export function ProjectCardSkeleton({ count = 4 }) {
100+
return (
101+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
102+
{Array.from({ length: count }).map((_, index) => (
103+
<div key={index} className="bg-white/80 backdrop-blur-md border border-white/20 p-4 shadow-lg shadow-black/5 relative overflow-hidden">
104+
{/* 우선순위 배경 스켈레톤 */}
105+
<div className="absolute inset-0 bg-gray-200/30 backdrop-blur-sm animate-pulse"></div>
106+
107+
{/* 컨텐츠 스켈레톤 */}
108+
<div className="relative z-10">
109+
{/* 헤더 */}
110+
<div className="flex items-start justify-between mb-3">
111+
<div className="flex-1">
112+
<Skeleton variant="text" width="70%" height={20} className="mb-2" />
113+
<Skeleton variant="text" width="90%" height={16} className="mb-1" />
114+
<Skeleton variant="text" width="60%" height={16} className="mb-3" />
115+
</div>
116+
<Skeleton variant="circular" width={24} height={24} />
117+
</div>
118+
119+
{/* 상태 및 진행률 */}
120+
<div className="mb-3">
121+
<div className="flex items-center justify-between mb-2">
122+
<Skeleton variant="rounded" width={60} height={24} />
123+
<Skeleton variant="text" width={30} height={16} />
124+
</div>
125+
<Skeleton variant="rounded" width="100%" height={6} />
126+
</div>
127+
128+
{/* 하단 정보 */}
129+
<div className="flex items-center justify-between text-xs mb-3">
130+
<Skeleton variant="text" width={50} height={14} />
131+
<Skeleton variant="text" width={30} height={14} />
132+
<Skeleton variant="text" width={60} height={14} />
133+
</div>
134+
135+
{/* 담당자 */}
136+
<div className="flex justify-between">
137+
<Skeleton variant="text" width={80} height={14} />
138+
<Skeleton variant="text" width={100} height={14} />
139+
</div>
140+
</div>
141+
</div>
142+
))}
143+
</div>
144+
);
145+
}
146+
147+
99148
export function ProjectListSkeleton({ count = 4 }) {
100149
return (
101150
<div className="bg-white border border-gray-200 rounded-lg">

src/components/project/ProjectList.jsx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import React, {useContext} from 'react';
2-
import ProjectCard from './ProjectCard';
1+
import React, {useContext, Suspense} from 'react';
32
import ProjectTable from './ProjectTable';
43
// 1. 삭제 기능을 위해 useDeleteProject 훅을 import 합니다.
54
import { useDeleteProject } from '../../hooks/useProjectQueries';
65
import AuthContext from "../../contexts/AuthContext.jsx";
6+
import { ProjectCardSkeleton } from '../common/loading/LoadingComponents';
7+
8+
// Lazy load ProjectCard component
9+
const ProjectCard = React.lazy(() => import('./ProjectCard'));
710

811
function ProjectList({
912
projects,
@@ -47,17 +50,19 @@ function ProjectList({
4750
switch (viewType) {
4851
case 'card':
4952
return (
50-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
51-
{projects.map(project => (
52-
<ProjectCard
53-
key={project.id}
54-
project={project}
55-
onAction={handleProjectAction}
56-
isPm={project?.pmId === user?.id}
57-
user={user}
58-
/>
59-
))}
60-
</div>
53+
<Suspense fallback={<ProjectCardSkeleton count={projects.length} />}>
54+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
55+
{projects.map(project => (
56+
<ProjectCard
57+
key={project.id}
58+
project={project}
59+
onAction={handleProjectAction}
60+
isPm={project?.pmId === user?.id}
61+
user={user}
62+
/>
63+
))}
64+
</div>
65+
</Suspense>
6166
);
6267

6368
case 'table':

0 commit comments

Comments
 (0)