feat(domain): centralize data definition

This commit is contained in:
2025-11-17 00:04:27 +02:00
parent e7585aa76c
commit f39635e04f
96 changed files with 3474 additions and 1167 deletions
@@ -1,22 +1,21 @@
import { Metadata } from "next";
import { ArticlesFeed } from "#dashboard/components/articles-feed";
import { PageLayout } from "#dashboard/components/shell/page-layout";
import { HydrateClient, batchPrefetch, trpc } from "#dashboard/trpc/server";
export const metadata: Metadata = {
title: "Articles | Basango Dashboard",
};
export default function Page() {
batchPrefetch([trpc.articles.list.infiniteQueryOptions({ limit: 12 })]);
return (
<PageLayout leading="Manage your articles" title="Articles">
<div className="flex flex-1 flex-col gap-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="bg-muted/50 aspect-video rounded-xl" />
<div className="bg-muted/50 aspect-video rounded-xl" />
<div className="bg-muted/50 aspect-video rounded-xl" />
</div>
<div className="bg-muted/50 min-h-screen flex-1 rounded-xl md:min-h-min" />
</div>
</PageLayout>
<HydrateClient>
<PageLayout leading="Track crawled content and trends" title="Articles">
<ArticlesFeed />
</PageLayout>
</HydrateClient>
);
}
@@ -0,0 +1,30 @@
import { Metadata } from "next";
import { PublicationGraphChart } from "#dashboard/components/charts/articles/publication-graph-chart";
import { SourceDistributionChart } from "#dashboard/components/charts/articles/source-distribution-chart";
import { PageLayout } from "#dashboard/components/shell/page-layout";
import { HydrateClient, batchPrefetch, trpc } from "#dashboard/trpc/server";
export const metadata: Metadata = {
title: "Dashboard | Basango",
};
export default async function Page() {
batchPrefetch([
trpc.articles.getPublicationGraph.queryOptions({}),
trpc.articles.getSourceDistribution.queryOptions({ limit: 8 }),
]);
return (
<HydrateClient>
<PageLayout leading="Keep track of article volume and source coverage" title="Dashboard">
<div className="grid grid-cols-1 gap-4 lg:grid-cols-4">
<div className="lg:col-span-3">
<PublicationGraphChart />
</div>
<SourceDistributionChart />
</div>
</PageLayout>
</HydrateClient>
);
}
@@ -1,9 +1,12 @@
import { Source } from "@basango/domain/models/sources";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@basango/ui/components/tabs";
import { Metadata } from "next";
import { SourceCategorySharesChart } from "#dashboard/components/charts/source-category-shares-chart";
import { SourcePublicationgGraphChart } from "#dashboard/components/charts/source-publication-graph-chart";
import { ArticlesFeed } from "#dashboard/components/articles-feed";
import { CategorySharesChart } from "#dashboard/components/charts/sources/category-shares-chart";
import { PublicationGraphChart } from "#dashboard/components/charts/sources/publication-graph-chart";
import { PageLayout } from "#dashboard/components/shell/page-layout";
import { SourceDetailsTab } from "#dashboard/components/source-details-tab";
import { HydrateClient, batchPrefetch, getQueryClient, trpc } from "#dashboard/trpc/server";
export const metadata: Metadata = {
@@ -16,11 +19,12 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
batchPrefetch([
trpc.sources.getById.queryOptions({ id }),
trpc.sources.getCategoryShares.queryOptions({ id }),
trpc.sources.getCategoryShares.queryOptions({ id, limit: 10 }),
trpc.sources.getPublicationGraph.queryOptions({ id }),
trpc.articles.list.infiniteQueryOptions({ limit: 12, sourceId: id }),
]);
const source = await queryClient.fetchQuery(trpc.sources.getById.queryOptions({ id }));
const source: Source = await queryClient.fetchQuery(trpc.sources.getById.queryOptions({ id }));
return (
<HydrateClient>
@@ -29,20 +33,17 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="articles">Articles</TabsTrigger>
<TabsTrigger value="details">Details</TabsTrigger>
</TabsList>
<TabsContent className="space-y-4" value="overview">
<SourceCategorySharesChart sourceId={source.id} />
<SourcePublicationgGraphChart sourceId={source.id} />
<CategorySharesChart sourceId={source.id} />
<PublicationGraphChart sourceId={source.id} />
</TabsContent>
<TabsContent value="articles">
<div className="flex flex-1 flex-col gap-4">
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
<div className="bg-muted/50 aspect-video rounded-xl" />
<div className="bg-muted/50 aspect-video rounded-xl" />
<div className="bg-muted/50 aspect-video rounded-xl" />
</div>
<div className="bg-muted/50 min-h-screen flex-1 rounded-xl md:min-h-min" />
</div>
<ArticlesFeed sourceId={source.id} />
</TabsContent>
<TabsContent value="details">
<SourceDetailsTab source={source} />
</TabsContent>
</Tabs>
</PageLayout>
@@ -1,33 +1,44 @@
import { RouterOutputs } from "@basango/api/trpc/routers/_app";
import { Source } from "@basango/domain/models/sources";
import { Button } from "@basango/ui/components/button";
import { PlusIcon } from "lucide-react";
import { Metadata } from "next";
import Link from "next/link";
import { SourceCreateModal } from "#dashboard/components/modals/source-create-modal";
import { PageLayout } from "#dashboard/components/shell/page-layout";
import { SourceCard } from "#dashboard/components/widgets/source-card";
import { SourceCard } from "#dashboard/components/source-card";
import { HydrateClient, getQueryClient, prefetch, trpc } from "#dashboard/trpc/server";
export const metadata: Metadata = {
title: "Sources | Basango Dashboard",
};
type SourceDetails = RouterOutputs["sources"]["get"][number];
export default async function Page() {
const queryClient = getQueryClient();
prefetch(trpc.sources.get.queryOptions());
const sources = await queryClient.fetchQuery(trpc.sources.get.queryOptions());
const sources: Source[] = await queryClient.fetchQuery(trpc.sources.get.queryOptions());
return (
<HydrateClient>
<PageLayout leading="Manage your news sources" title="Sources">
<div className="mb-6 flex justify-end">
<Link href="?createSource=true">
<Button type="button">
<PlusIcon className="mr-2 size-4" />
Add source
</Button>
</Link>
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
{sources.map((source: SourceDetails) => (
{sources.map((source: Source) => (
<Link href={`/sources/${source.id}`} key={source.id}>
<SourceCard source={source} />
</Link>
))}
</div>
<SourceCreateModal />
</PageLayout>
</HydrateClient>
);