Skip to content

Commit 3493e98

Browse files
committed
feat: skeleton for apps.
1 parent 6b6b7ef commit 3493e98

File tree

1 file changed

+64
-38
lines changed

1 file changed

+64
-38
lines changed

src/pages/AppPage.js

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ function AppPage() {
2222

2323
const [groupedApps, setGroupedApps] = useState({});
2424
const [collapsedCategories, setCollapsedCategories] = useState({});
25+
const [isLoading, setIsLoading] = useState(true); // New loading state
2526

2627
useEffect(() => {
28+
setIsLoading(true); // Set loading to true when fetch starts
2729
fetch('/apps/apps.json')
2830
.then((response) => response.json())
2931
.then((data) => {
@@ -34,7 +36,10 @@ function AppPage() {
3436
}, {});
3537
setCollapsedCategories(initialCollapsedState);
3638
})
37-
.catch((error) => console.error('Error fetching apps:', error));
39+
.catch((error) => console.error('Error fetching apps:', error))
40+
.finally(() => {
41+
setIsLoading(false); // Set loading to false when fetch completes
42+
});
3843
}, []);
3944

4045
const toggleCategoryCollapse = (categoryKey) => {
@@ -64,44 +69,65 @@ function AppPage() {
6469
<span className="apps-color">apps</span>
6570
</h1>
6671
<hr className="border-gray-700" />
67-
{Object.keys(groupedApps)
68-
.sort((a, b) => groupedApps[a].order - groupedApps[b].order)
69-
.map(categoryKey => {
70-
const category = groupedApps[categoryKey];
71-
const CategoryIcon = appIcons[category.icon];
72-
return (
73-
<div key={categoryKey} className="mt-8">
74-
<h2
75-
className="text-3xl font-arvo font-normal tracking-tight text-gray-200 mb-2 flex items-center cursor-pointer"
76-
onClick={() => toggleCategoryCollapse(categoryKey)}
77-
>
78-
{collapsedCategories[categoryKey] ? <CaretRight size={24} className="mr-2" /> : <CaretDown size={24} className="mr-2" />}
79-
{CategoryIcon && <CategoryIcon size={28} className="mr-2" />}
80-
{category.name} ({category.apps.length})
81-
</h2>
82-
<p className="text-gray-400 mb-4 ml-10">{category.description}</p>
83-
<AnimatePresence initial={false}>
84-
{!collapsedCategories[categoryKey] && (
85-
<motion.div
86-
key="content"
87-
initial="collapsed"
88-
animate="open"
89-
exit="collapsed"
90-
variants={variants}
91-
transition={{ duration: 0.3, ease: "easeInOut" }}
92-
style={{ overflow: "hidden" }}
93-
>
94-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
95-
{category.apps.map((app, index) => (
96-
<AppCard key={index} app={app} />
97-
))}
98-
</div>
99-
</motion.div>
100-
)}
101-
</AnimatePresence>
72+
{isLoading ? (
73+
// Skeleton Loading State
74+
<div className="mt-8">
75+
{[...Array(3)].map((_, categoryIndex) => ( // Simulate 3 categories
76+
<div key={categoryIndex} className="mb-8">
77+
<div className="h-8 bg-gray-700 rounded w-1/3 mb-4 animate-pulse"></div> {/* Category Title */}
78+
<div className="h-4 bg-gray-800 rounded w-1/2 mb-6 animate-pulse"></div> {/* Category Description */}
79+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
80+
{[...Array(3)].map((_, appIndex) => ( // Simulate 3 app cards per category
81+
<div key={appIndex} className="bg-gray-800 rounded-lg shadow-lg p-6 h-40 animate-pulse">
82+
<div className="h-6 bg-gray-700 rounded w-3/4 mb-2"></div>
83+
<div className="h-4 bg-gray-700 rounded w-1/2"></div>
84+
</div>
85+
))}
86+
</div>
10287
</div>
103-
);
104-
})}
88+
))}
89+
</div>
90+
) : (
91+
// Actual Content
92+
Object.keys(groupedApps)
93+
.sort((a, b) => groupedApps[a].order - groupedApps[b].order)
94+
.map(categoryKey => {
95+
const category = groupedApps[categoryKey];
96+
const CategoryIcon = appIcons[category.icon];
97+
return (
98+
<div key={categoryKey} className="mt-8">
99+
<h2
100+
className="text-3xl font-arvo font-normal tracking-tight text-gray-200 mb-2 flex items-center cursor-pointer"
101+
onClick={() => toggleCategoryCollapse(categoryKey)}
102+
>
103+
{collapsedCategories[categoryKey] ? <CaretRight size={24} className="mr-2" /> : <CaretDown size={24} className="mr-2" />}
104+
{CategoryIcon && <CategoryIcon size={28} className="mr-2" />}
105+
{category.name} ({category.apps.length})
106+
</h2>
107+
<p className="text-gray-400 mb-4 ml-10">{category.description}</p>
108+
<AnimatePresence initial={false}>
109+
{!collapsedCategories[categoryKey] && (
110+
<motion.div
111+
key="content"
112+
initial="collapsed"
113+
animate="open"
114+
exit="collapsed"
115+
variants={variants}
116+
transition={{ duration: 0.3, ease: "easeInOut" }}
117+
style={{ overflow: "hidden" }}
118+
>
119+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
120+
{category.apps.map((app, index) => (
121+
<AppCard key={index} app={app} />
122+
))}
123+
</div>
124+
</motion.div>
125+
)}
126+
</AnimatePresence>
127+
</div>
128+
);
129+
})
130+
)}
105131
</div>
106132
</div>
107133
);

0 commit comments

Comments
 (0)