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
11 changes: 11 additions & 0 deletions backend/api/views/quiblet.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/page.tsx
Original file line number Diff line number Diff line change
@@ -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() {
Expand All @@ -9,6 +10,7 @@ export default function Home() {
<div>
<div className="scrollbar-track-rounded-full scrollbar-thin scrollbar-track-transparent scrollbar-thumb-accent scrollbar scrollbar-thumb-rounded-full sticky top-14 flex h-[calc(100vh-var(--spacing)*14)] w-75 flex-col gap-4 overflow-y-auto p-4 pl-2">
<RecentQuibs />
<PopularQuiblets />
<LegalLinks />
</div>
</div>
Expand Down
61 changes: 61 additions & 0 deletions frontend/components/popular-quiblets.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<aside className="flex flex-col gap-4">
<h4 className="font-medium text-secondary">Popular Quiblets</h4>
{isLoading ? (
<div className="flex flex-col gap-4">
{Array.from({ length: 5 }).map((_, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: skeleton
<div key={i} className="flex items-center gap-3">
<Skeleton className="size-8 shrink-0 rounded-full" />
<div className="flex flex-1 flex-col gap-1.5">
<Skeleton className="h-3 w-24" />
<Skeleton className="h-3 w-16" />
</div>
</div>
))}
</div>
) : popularQuiblets?.length === 0 ? (
<div className="text-muted-foreground text-sm">
No popular quiblets found.
</div>
) : (
<div className="flex flex-col gap-4">
{popularQuiblets?.map((quiblet) => (
<Link
key={quiblet.name}
href={`/q/${quiblet.name}`}
className="group flex items-center gap-3 transition-colors hover:text-primary"
>
<Avatar className="size-8 shrink-0">
<AvatarImage src={quiblet.avatar_url || undefined} />
<AvatarFallback seed={quiblet.name} />
</Avatar>
<div className="flex flex-col">
<span className="font-semibold text-sm group-hover:underline">
q/{quiblet.name}
</span>
<span className="text-secondary text-xs">
{quiblet.members_count} members
</span>
</div>
</Link>
))}
</div>
)}
</aside>
);
}
1 change: 1 addition & 0 deletions frontend/constants/api-endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
5 changes: 5 additions & 0 deletions frontend/services/quiblet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Array<QuibletBasic>>(API_ENDPOINTS.POPULAR_QUIBLETS);
return res.data;
}
Loading