From 42e8a513abc7b1769f1da76949a3c62353dc8b07 Mon Sep 17 00:00:00 2001
From: stabldev <114811070+stabldev@users.noreply.github.com>
Date: Fri, 20 Mar 2026 11:54:14 +0530
Subject: [PATCH] feat: setup popular quiblets section
---
backend/api/views/quiblet.py | 11 +++++
frontend/app/page.tsx | 2 +
frontend/components/popular-quiblets.tsx | 61 ++++++++++++++++++++++++
frontend/constants/api-endpoints.ts | 1 +
frontend/services/quiblet.ts | 5 ++
5 files changed, 80 insertions(+)
create mode 100644 frontend/components/popular-quiblets.tsx
diff --git a/backend/api/views/quiblet.py b/backend/api/views/quiblet.py
index 012128e9..f98bc328 100644
--- a/backend/api/views/quiblet.py
+++ b/backend/api/views/quiblet.py
@@ -46,6 +46,17 @@ def search_quiblets(request: HttpRequest, q: str): # pyright: ignore[reportUnus
)[:10]
+@router.get("/popular", response=list[QuibletBasicSchema])
+def get_popular_quiblets(request: HttpRequest):
+ def fetch():
+ return Quiblet.objects.filter(type="PUBLIC").annotate(
+ members_count=Count("members")
+ ).order_by("-members_count")[:5]
+
+ cache_key = "quiblets:popular"
+ return cache_response(cache_key, fetch)
+
+
@router.get(
"/{name}",
response=QuibletSchema,
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index ea885515..b7e03613 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -1,5 +1,6 @@
import Feed from "@/components/feed";
import LegalLinks from "@/components/legal-links";
+import PopularQuiblets from "@/components/popular-quiblets";
import RecentQuibs from "@/components/recent-quibs";
export default function Home() {
@@ -9,6 +10,7 @@ export default function Home() {
diff --git a/frontend/components/popular-quiblets.tsx b/frontend/components/popular-quiblets.tsx
new file mode 100644
index 00000000..2519ebf3
--- /dev/null
+++ b/frontend/components/popular-quiblets.tsx
@@ -0,0 +1,61 @@
+"use client";
+
+import { useQuery } from "@tanstack/react-query";
+import Link from "next/link";
+import { getPopularQuiblets } from "@/services/quiblet";
+import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
+import { Skeleton } from "./ui/skeleton";
+
+export default function PopularQuiblets() {
+ const { data: popularQuiblets, isLoading } = useQuery({
+ queryKey: ["popular-quiblets"],
+ queryFn: getPopularQuiblets,
+ });
+
+ return (
+
+ );
+}
diff --git a/frontend/constants/api-endpoints.ts b/frontend/constants/api-endpoints.ts
index 314c8176..43bf291f 100644
--- a/frontend/constants/api-endpoints.ts
+++ b/frontend/constants/api-endpoints.ts
@@ -16,6 +16,7 @@ export const API_ENDPOINTS = {
SEARCH: (query: string) => `api/v1/search?q=${query}`,
// quiblet
QUIBLET_SEARCH: (query: string) => `api/v1/quiblet/search?q=${query}`,
+ POPULAR_QUIBLETS: "api/v1/quiblet/popular",
QUIBLET: (name?: string) => `api/v1/quiblet/${name || ""}`,
QUIBLET_IS_UNIQUE_NAME: (name: string) =>
`api/v1/quiblet/is-unique?name=${name}`,
diff --git a/frontend/services/quiblet.ts b/frontend/services/quiblet.ts
index 5c750e3a..8e5e9695 100644
--- a/frontend/services/quiblet.ts
+++ b/frontend/services/quiblet.ts
@@ -66,3 +66,8 @@ export async function getUserQuibs(userId: string) {
export async function toggleQuibletFavorite(name: string) {
await api.post(API_ENDPOINTS.TOGGLE_FAVORITE(name));
}
+
+export async function getPopularQuiblets() {
+ const res = await api.get>(API_ENDPOINTS.POPULAR_QUIBLETS);
+ return res.data;
+}