feat: add skipped/failed packages tab to STL files page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 16:36:39 +01:00
parent ad3d42a997
commit 5a3550fa10
2 changed files with 95 additions and 35 deletions

View File

@@ -8,6 +8,7 @@ import { useDataTable } from "@/hooks/use-data-table";
import { getPackageColumns, type PackageRow } from "./package-columns";
import { PackageFilesDrawer } from "./package-files-drawer";
import { IngestionStatus } from "./ingestion-status";
import { SkippedPackagesTab } from "./skipped-packages-tab";
import { DataTable } from "@/components/shared/data-table";
import { DataTablePagination } from "@/components/shared/data-table-pagination";
import { DataTableViewOptions } from "@/components/shared/data-table-view-options";
@@ -20,7 +21,10 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Badge } from "@/components/ui/badge";
import type { IngestionAccountStatus } from "@/lib/telegram/types";
import type { SkippedRow } from "./skipped-columns";
import { updatePackageCreator, updatePackageTags } from "../actions";
interface StlTableProps {
@@ -30,6 +34,9 @@ interface StlTableProps {
ingestionStatus: IngestionAccountStatus[];
availableTags: string[];
searchTerm: string;
skippedData: SkippedRow[];
skippedPageCount: number;
skippedTotalCount: number;
}
export function StlTable({
@@ -39,6 +46,9 @@ export function StlTable({
ingestionStatus,
availableTags,
searchTerm,
skippedData,
skippedPageCount,
skippedTotalCount,
}: StlTableProps) {
const router = useRouter();
const pathname = usePathname();
@@ -77,6 +87,22 @@ export function StlTable({
[router, pathname, searchParams]
);
const activeTab = searchParams.get("tab") ?? "packages";
const updateTab = useCallback(
(value: string) => {
const params = new URLSearchParams(searchParams.toString());
if (value === "packages") {
params.delete("tab");
} else {
params.set("tab", value);
}
params.set("page", "1");
router.push(`${pathname}?${params.toString()}`, { scroll: false });
},
[router, pathname, searchParams]
);
const columns = getPackageColumns({
onViewFiles: (pkg) => setViewPkg(pkg),
searchTerm,
@@ -125,6 +151,20 @@ export function StlTable({
<IngestionStatus initialStatus={ingestionStatus} />
</PageHeader>
<Tabs value={activeTab} onValueChange={updateTab}>
<TabsList>
<TabsTrigger value="packages">Packages</TabsTrigger>
<TabsTrigger value="skipped" className="gap-1.5">
Skipped / Failed
{skippedTotalCount > 0 && (
<Badge variant="secondary" className="text-[10px] ml-1">
{skippedTotalCount}
</Badge>
)}
</TabsTrigger>
</TabsList>
<TabsContent value="packages" className="space-y-4">
<div className="flex flex-wrap items-center gap-2">
<div className="relative flex-1 min-w-[200px] max-w-sm">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
@@ -158,6 +198,16 @@ export function StlTable({
emptyMessage="No packages found. Archives will appear here after ingestion."
/>
<DataTablePagination table={table} totalCount={totalCount} />
</TabsContent>
<TabsContent value="skipped">
<SkippedPackagesTab
data={skippedData}
pageCount={skippedPageCount}
totalCount={skippedTotalCount}
/>
</TabsContent>
</Tabs>
<PackageFilesDrawer
pkg={viewPkg}

View File

@@ -1,6 +1,6 @@
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
import { listPackages, searchPackages, getIngestionStatus, getAllPackageTags } from "@/lib/telegram/queries";
import { listPackages, searchPackages, getIngestionStatus, getAllPackageTags, listSkippedPackages, countSkippedPackages } from "@/lib/telegram/queries";
import { StlTable } from "./_components/stl-table";
interface Props {
@@ -20,9 +20,10 @@ export default async function StlFilesPage({ searchParams }: Props) {
const search = (params.search as string) ?? "";
const creator = (params.creator as string) || undefined;
const tag = (params.tag as string) || undefined;
const tab = (params.tab as string) ?? "packages";
// Fetch packages, ingestion status, and available tags in parallel
const [result, ingestionStatus, availableTags] = await Promise.all([
// Fetch packages, ingestion status, tags, and skipped count in parallel
const [result, ingestionStatus, availableTags, skippedCount] = await Promise.all([
search
? searchPackages({
query: search,
@@ -40,8 +41,14 @@ export default async function StlFilesPage({ searchParams }: Props) {
}),
getIngestionStatus(),
getAllPackageTags(),
countSkippedPackages(),
]);
// Fetch skipped packages only if on that tab
const skippedResult = tab === "skipped"
? await listSkippedPackages({ page, limit: perPage })
: null;
return (
<StlTable
data={result.items}
@@ -50,6 +57,9 @@ export default async function StlFilesPage({ searchParams }: Props) {
ingestionStatus={ingestionStatus}
availableTags={availableTags}
searchTerm={search}
skippedData={skippedResult?.items ?? []}
skippedPageCount={skippedResult?.pagination.totalPages ?? 0}
skippedTotalCount={skippedCount}
/>
);
}