TypeScript 97.5%
SQL 1.4%
Python 0.8%
1import Link from "next/link";2import { ListTree } from "lucide-react";3import { getWorkspace } from "@/lib/session";4import { API_PUBLIC_URL } from "@/lib/utils";5import { parseRequestFilters, requestsHref, REQUESTS_PAGE_SIZE, type SearchParams } from "@/lib/requests-filters";6import { listRequests, projectHasRequests, type Scope } from "@/lib/queries/dashboard";7import { PageHeader } from "@/components/ui/page-header";8import { Card } from "@/components/ui/card";9import { Button } from "@/components/ui/button";10import { EmptyState } from "@/components/ui/empty-state";11import { CodeBlock } from "@/components/ui/code-block";12import { RequestsTable } from "@/components/dashboard/requests/requests-table";13import { ActiveFilterChips, RequestsFilterForm } from "@/components/dashboard/requests/requests-filters";14import { Pagination } from "@/components/dashboard/requests/pagination";1516export const dynamic = "force-dynamic";1718const CURL_SNIPPET = `curl -X POST ${API_PUBLIC_URL}/v1/fetch \\19 -H "Authorization: Bearer fch_live_YOUR_KEY" \\20 -H "Content-Type: application/json" \\21 -d '{ "url": "https://example.com", "country": "CA", "format": "text" }'`;2223export default async function RequestsPage({ searchParams }: { searchParams: Promise<SearchParams> }) {24 const [ws, sp] = await Promise.all([getWorkspace(), searchParams]);25 const scope: Scope = { organizationId: ws.organization.id, projectId: ws.project.id };26 const filters = parseRequestFilters(sp);27 const [hasAny, result] = await Promise.all([projectHasRequests(scope), listRequests(scope, filters, REQUESTS_PAGE_SIZE)]);2829 return (30 <div className="flex flex-col gap-5">31 <PageHeader32 title="Requests"33 description={`Every request routed for ${ws.project.name}, with its resolved network, latency, attempts and billed price. Logs are retained according to your plan.`}34 />3536 {!hasAny ? (37 <EmptyState38 icon={ListTree}39 title="No requests yet"40 description="Requests appear here the moment you send one. Start in the Playground, or call the API directly with a key from API Keys."41 action={42 <>43 <Button asChild variant="primary" size="sm">44 <Link href="/dashboard/playground">Open Playground</Link>45 </Button>46 <Button asChild variant="outline" size="sm">47 <Link href="/dashboard/api-keys">Create API key</Link>48 </Button>49 </>50 }51 className="pb-8"52 />53 ) : null}5455 {!hasAny ? (56 <div className="mx-auto w-full max-w-2xl">57 <CodeBlock code={CURL_SNIPPET} lang="bash" title="Your first request (replace the key)" />58 </div>59 ) : (60 <>61 <RequestsFilterForm filters={filters} exportCount={result.total} />62 <ActiveFilterChips filters={filters} />63 <Card className="overflow-hidden">64 <RequestsTable rows={result.rows} emptyMessage={<span>No requests match these filters. Widen the date range or <Link href="/dashboard/requests" className="text-accent underline-offset-4 hover:underline">clear the filters</Link>.</span>} />65 </Card>66 <Pagination page={result.page} pageCount={result.pageCount} total={result.total} pageSize={REQUESTS_PAGE_SIZE} hrefFor={(p) => requestsHref(filters, { page: p })} />67 </>68 )}69 </div>70 );71}72