Skip to content

Commit 1033252

Browse files
author
Rajat Saxena
committed
empty states; communities pagination sort desending; common skeleton card
1 parent d41af16 commit 1033252

File tree

15 files changed

+230
-116
lines changed

15 files changed

+230
-116
lines changed

apps/web/app/(with-contexts)/(with-layout)/communities/communities-list.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,60 @@
11
"use client";
22

3-
import { useState } from "react";
43
import { useCommunities } from "@/hooks/use-communities";
5-
import { SkeletonCard } from "./skeleton-card";
64
import { ContentCard } from "./content-card";
75
import { PaginationControls } from "@components/public/pagination";
86
import { Community } from "@courselit/common-models";
7+
import { Users } from "lucide-react";
8+
import { Button } from "@components/ui/button";
9+
import { SkeletonCard } from "@components/skeleton-card";
910

1011
const ITEMS_PER_PAGE = 9;
1112

1213
export function CommunitiesList({
1314
itemsPerPage = ITEMS_PER_PAGE,
14-
publicLink = true,
15+
publicView = true,
16+
page,
17+
onPageChange,
1518
}: {
1619
itemsPerPage?: number;
17-
publicLink?: boolean;
20+
publicView?: boolean;
21+
page: number;
22+
onPageChange: (page: number) => void;
1823
}) {
19-
const [currentPage, setCurrentPage] = useState(1);
2024
const { communities, loading, totalPages } = useCommunities(
21-
currentPage,
25+
page,
2226
itemsPerPage,
2327
);
2428

29+
if (!loading && totalPages === 0) {
30+
return (
31+
<div className="flex flex-col items-center justify-center py-12 text-center">
32+
<Users className="w-12 h-12 text-muted-foreground mb-4" />
33+
<h3 className="text-lg font-semibold mb-2">
34+
No Communities Found
35+
</h3>
36+
<p className="text-muted-foreground">
37+
{publicView ? "The team " : "You have "} not added any
38+
communities yet.
39+
</p>
40+
</div>
41+
);
42+
}
43+
44+
if (!loading && totalPages && communities.length === 0) {
45+
return (
46+
<div className="flex flex-col items-center justify-center py-12 text-center">
47+
<Users className="w-12 h-12 text-muted-foreground mb-4" />
48+
<p className="text-muted-foreground mb-4">
49+
This page is empty.
50+
</p>
51+
<Button variant="outline" onClick={() => onPageChange(1)}>
52+
Go to first page
53+
</Button>
54+
</div>
55+
);
56+
}
57+
2558
return (
2659
<div className="space-y-8">
2760
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -33,14 +66,14 @@ export function CommunitiesList({
3366
<ContentCard
3467
key={community.communityId}
3568
community={community}
36-
publicLink={publicLink}
69+
publicView={publicView}
3770
/>
3871
))}
3972
</div>
4073
<PaginationControls
41-
currentPage={currentPage}
74+
currentPage={page}
4275
totalPages={Math.ceil(totalPages / itemsPerPage)}
43-
onPageChange={setCurrentPage}
76+
onPageChange={onPageChange}
4477
/>
4578
</div>
4679
);

apps/web/app/(with-contexts)/(with-layout)/communities/content-card.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import {
1212

1313
export function ContentCard({
1414
community,
15-
publicLink = true,
15+
publicView = true,
1616
}: {
1717
community: Community;
18-
publicLink?: boolean;
18+
publicView?: boolean;
1919
}) {
2020
return (
2121
<Link
2222
href={
23-
publicLink
23+
publicView
2424
? `/p/${community.pageId}`
2525
: `/dashboard/community/${community.communityId}`
2626
}
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
1-
import { Suspense } from "react";
1+
"use client";
2+
3+
import { useCallback } from "react";
24
import { CommunitiesList } from "./communities-list";
5+
import { useRouter, useSearchParams } from "next/navigation";
36

47
export default function CommunitiesPage() {
8+
const searchParams = useSearchParams();
9+
const page = parseInt(searchParams?.get("page") || "1");
10+
const router = useRouter();
11+
12+
const handlePageChange = useCallback(
13+
(value: number) => {
14+
router.push(`/communities?page=${value}`);
15+
},
16+
[router],
17+
);
18+
519
return (
620
<div className="container mx-auto px-4 py-8">
721
<h1 className="text-3xl font-bold mb-8">Communities</h1>
8-
<Suspense fallback={<div>Loading...</div>}>
9-
<CommunitiesList />
10-
</Suspense>
22+
<CommunitiesList
23+
page={page}
24+
onPageChange={handlePageChange}
25+
itemsPerPage={1}
26+
/>
1127
</div>
1228
);
1329
}

apps/web/app/(with-contexts)/(with-layout)/communities/skeleton-card.tsx

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { BookOpen } from "lucide-react";
2+
3+
export function EmptyState({ publicView = true }: { publicView?: boolean }) {
4+
return (
5+
<div className="flex flex-col items-center justify-center py-12 text-center">
6+
<BookOpen className="w-12 h-12 text-muted-foreground mb-4" />
7+
<h3 className="text-lg font-semibold mb-2">No Products Found</h3>
8+
<p className="text-muted-foreground">
9+
{publicView ? "The team has " : "You have "} not added any
10+
products yet.
11+
</p>
12+
</div>
13+
);
14+
}
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
import { Suspense } from "react";
1+
"use client";
2+
3+
import { useCallback } from "react";
24
import { ProductsList } from "./products-list";
5+
import { useRouter, useSearchParams } from "next/navigation";
36

47
export default function CoursesPage() {
8+
const searchParams = useSearchParams();
9+
const page = parseInt(searchParams?.get("page") || "1");
10+
const router = useRouter();
11+
12+
const handlePageChange = useCallback(
13+
(value: number) => {
14+
router.push(`/products?page=${value}`);
15+
},
16+
[router],
17+
);
18+
519
return (
620
<div className="container mx-auto px-4 py-8">
721
<h1 className="text-3xl font-bold mb-8">Products</h1>
8-
<Suspense fallback={<div>Loading...</div>}>
9-
<ProductsList />
10-
</Suspense>
22+
<ProductsList page={page} onPageChange={handlePageChange} />
1123
</div>
1224
);
1325
}

apps/web/app/(with-contexts)/(with-layout)/products/products-list.tsx

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,56 @@
11
"use client";
22

3-
import { useMemo, useState } from "react";
4-
import { SkeletonCard } from "./skeleton-card";
3+
import { useMemo } from "react";
4+
import { SkeletonCard } from "@components/skeleton-card";
55
import { ContentCard } from "./content-card";
66
import { PaginationControls } from "@components/public/pagination";
77
import { Constants, Course } from "@courselit/common-models";
88
import { useProducts } from "@/hooks/use-products";
9+
import { BookOpen } from "lucide-react";
10+
import { EmptyState } from "./empty-state";
11+
import { Button } from "@components/ui/button";
912

1013
const ITEMS_PER_PAGE = 9;
1114

1215
export function ProductsList({
16+
page,
1317
itemsPerPage = ITEMS_PER_PAGE,
18+
onPageChange,
1419
}: {
20+
page: number;
1521
itemsPerPage?: number;
22+
onPageChange: (page: number) => void;
1623
}) {
17-
const [currentPage, setCurrentPage] = useState(1);
1824
const filters = useMemo(
1925
() => [Constants.CourseType.COURSE.toUpperCase()],
2026
[],
2127
);
28+
2229
const { products, loading, totalPages } = useProducts(
23-
currentPage,
30+
page,
2431
itemsPerPage,
2532
filters,
2633
true,
2734
);
2835

36+
if (!loading && totalPages === 0) {
37+
return <EmptyState />;
38+
}
39+
40+
if (!loading && totalPages && products.length === 0) {
41+
return (
42+
<div className="flex flex-col items-center justify-center py-12 text-center">
43+
<BookOpen className="w-12 h-12 text-muted-foreground mb-4" />
44+
<p className="text-muted-foreground mb-4">
45+
This page is empty.
46+
</p>
47+
<Button variant="outline" onClick={() => onPageChange(1)}>
48+
Go to first page
49+
</Button>
50+
</div>
51+
);
52+
}
53+
2954
return (
3055
<div className="space-y-8">
3156
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@@ -41,9 +66,9 @@ export function ProductsList({
4166
))}
4267
</div>
4368
<PaginationControls
44-
currentPage={currentPage}
69+
currentPage={page}
4570
totalPages={Math.ceil(totalPages / itemsPerPage)}
46-
onPageChange={setCurrentPage}
71+
onPageChange={onPageChange}
4772
/>
4873
</div>
4974
);

apps/web/app/(with-contexts)/dashboard/(sidebar)/communities/page.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,25 @@ import {
99
} from "@ui-config/strings";
1010
import Link from "next/link";
1111
import { Button } from "@components/ui/button";
12+
import { useRouter, useSearchParams } from "next/navigation";
13+
import { useCallback } from "react";
14+
import Resources from "@components/resources";
1215
const { permissions } = UIConstants;
1316

1417
const breadcrumbs = [{ label: MANAGE_COMMUNITIES_PAGE_HEADING, href: "#" }];
1518

1619
export default function Page() {
20+
const searchParams = useSearchParams();
21+
const router = useRouter();
22+
const page = parseInt(searchParams?.get("page") || "1");
23+
24+
const handlePageChange = useCallback(
25+
(value: number) => {
26+
router.push(`/dashboard/communities?page=${value}`);
27+
},
28+
[router],
29+
);
30+
1731
return (
1832
<DashboardContent
1933
breadcrumbs={breadcrumbs}
@@ -29,7 +43,20 @@ export default function Page() {
2943
</Link>
3044
</div>
3145
</div>
32-
<CommunitiesList itemsPerPage={9} publicLink={false} />
46+
<CommunitiesList
47+
page={page}
48+
itemsPerPage={9}
49+
publicView={false}
50+
onPageChange={handlePageChange}
51+
/>
52+
<Resources
53+
links={[
54+
{
55+
href: "https://docs.courselit.app/en/communities/introduction/",
56+
text: "Create a community",
57+
},
58+
]}
59+
/>
3360
</DashboardContent>
3461
);
3562
}

apps/web/app/(with-contexts)/dashboard/(sidebar)/my-content/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useState, useEffect, useContext } from "react";
44
// import { ContentCard } from "@/components/admin/my-content/content-card";
5-
import { SkeletonCard } from "@/components/admin/my-content/skeleton-card";
5+
// import { SkeletonCard } from "@/components/admin/my-content/skeleton-card";
66
import type { ContentItem } from "@/components/admin/my-content/content";
77
import { AddressContext, ProfileContext } from "@components/contexts";
88
import { MY_CONTENT_HEADER } from "@ui-config/strings";
@@ -13,6 +13,7 @@ import { MyContentCard } from "@components/admin/my-content/content-card";
1313
import { BookOpen, Users } from "lucide-react";
1414
import Link from "next/link";
1515
import { Button } from "@components/ui/button";
16+
import { SkeletonCard } from "@components/skeleton-card";
1617

1718
function ContentGrid({
1819
items,

0 commit comments

Comments
 (0)