1import { type RepoStats, repoStats, type Save, timeline } from "../mirror/queries.ts";2import { publicRepoNames } from "../server/db.ts";3import { type Html, html } from "./html.ts";4import { openPublicRepo, type PageContext, type PublicRepo, plural } from "./layout.ts";5import { repoIntro } from "./repo.ts";678export type LibraryRepo = PublicRepo & { stats: RepoStats; description: string; saves: Save[] };910export type RecentSave = { repo: string; save: Save };111213export function publicLibrary(ctx: PageContext): LibraryRepo[] {14 return publicRepoNames(ctx.kepr).flatMap((name) => {15 const repo = openPublicRepo(ctx, name);16 if (!repo) return [];17 const description = repoIntro(repo)?.text ?? "";18 return [{ ...repo, stats: repoStats(repo.mirror), description, saves: timeline(repo.mirror) }];19 });20}212223export function recentSaves(library: LibraryRepo[], limit: number): RecentSave[] {24 return library25 .flatMap((repo) => repo.saves.slice(-limit).map((save) => ({ repo: repo.settings.name, save })))26 .sort((a, b) => b.save.created_at - a.save.created_at)27 .slice(0, limit);28}2930export function repoCards(library: LibraryRepo[]): Html {31 return html`<div class="card-grid">${library.map(repoCard)}</div>`;32}333435function repoCard(repo: LibraryRepo): Html {36 const { name, category } = repo.settings;37 return html`<a class="repo-card" href="/${name}">38<div class="repo-card-head"><span class="repo-card-name">${39 name40 }</span><span class="repo-card-saves mono">${plural(repo.stats.saves, "save")}</span></div>41${repo.description && html`<p class="repo-card-desc">${repo.description}</p>`}42${category && html`<p class="repo-card-cat">${category}</p>`}43</a>`;44}