stats
This commit is contained in:
parent
6fb3d2bdbe
commit
0779aa6199
8 changed files with 192 additions and 8 deletions
|
@ -12,7 +12,7 @@ export default function GlobalError({
|
|||
error: Error & { digest?: string }
|
||||
}) {
|
||||
return (
|
||||
<CardGrid>
|
||||
<CardGrid max_rows={1}>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-center text-2xl text-red-400">Error</CardTitle>
|
||||
|
|
|
@ -12,7 +12,7 @@ export default function GlobalError({
|
|||
error: Error & { digest?: string }
|
||||
}) {
|
||||
return (
|
||||
<CardGrid>
|
||||
<CardGrid max_rows={1}>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-center text-2xl text-red-400">404 - Not Found</CardTitle>
|
||||
|
|
30
src/app/stats/columns.tsx
Normal file
30
src/app/stats/columns.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
"use client";
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
|
||||
export type UrlTable = {
|
||||
clicks: number;
|
||||
date_accessed: Date;
|
||||
date_added: Date;
|
||||
id: string;
|
||||
long_url: string;
|
||||
};
|
||||
|
||||
export const columns: ColumnDef<UrlTable>[] = [
|
||||
{
|
||||
accessorKey: "clicks",
|
||||
header: "Clicks",
|
||||
},
|
||||
{
|
||||
accessorKey: "long_url",
|
||||
header: "URL",
|
||||
},
|
||||
{ accessorKey: "id", header: "ID" },
|
||||
{
|
||||
accessorKey: "date_accessed",
|
||||
header: "Date Accessed",
|
||||
},
|
||||
{
|
||||
accessorKey: "date_added",
|
||||
header: "Date Added",
|
||||
},
|
||||
];
|
79
src/app/stats/data-table.tsx
Normal file
79
src/app/stats/data-table.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
"use client";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import {
|
||||
ColumnDef,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable
|
||||
} from "@tanstack/react-table";
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
data: TData[];
|
||||
slug: string[];
|
||||
}
|
||||
|
||||
export function DataTable<TData, TValue>({
|
||||
columns,
|
||||
data,
|
||||
}: DataTableProps<TData, TValue>) {
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
)
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</>
|
||||
);
|
||||
}
|
19
src/app/stats/db.tsx
Normal file
19
src/app/stats/db.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
"use server";
|
||||
import { initConnection } from "@/components/db-utils";
|
||||
|
||||
export async function querydb() {
|
||||
try {
|
||||
let db = await initConnection();
|
||||
let stats = await db.query(`
|
||||
select * from url
|
||||
order by clicks desc
|
||||
limit 50;
|
||||
`);
|
||||
|
||||
// @ts-ignore
|
||||
console.log(stats);
|
||||
return stats;
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
}
|
23
src/app/stats/loading.tsx
Normal file
23
src/app/stats/loading.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
"use client";
|
||||
import CardGrid from "@/components/card-grid";
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle
|
||||
} from "@/components/ui/card";
|
||||
|
||||
export default function GlobalError({
|
||||
error,
|
||||
}: {
|
||||
error: Error & { digest?: string }
|
||||
}) {
|
||||
return (
|
||||
<CardGrid max_rows={1}>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-1xl text-amber-400">Loading...</CardTitle>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</CardGrid>
|
||||
);
|
||||
}
|
|
@ -1,8 +1,16 @@
|
|||
import CardGrid from "@/components/card-grid";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { columns } from "./columns";
|
||||
import { DataTable } from "./data-table";
|
||||
import { querydb } from "./db";
|
||||
|
||||
export default function StatsPage() {
|
||||
export default async function StatsPage() {
|
||||
let data = await querydb();
|
||||
return (
|
||||
<div>
|
||||
<h1>Stats</h1>
|
||||
</div>
|
||||
<CardGrid max_rows={1}>
|
||||
<Card>
|
||||
<DataTable columns={columns} data={data[0]} />
|
||||
</Card>
|
||||
</CardGrid>
|
||||
);
|
||||
}
|
|
@ -1,15 +1,40 @@
|
|||
export default function CardGrid({
|
||||
max_rows = 4,
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: {
|
||||
max_rows?: number;
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
}) {
|
||||
let baseClassName = `hidden items-start justify-center gap-6 rounded-lg p-8 md:grid`;
|
||||
|
||||
switch (max_rows) {
|
||||
case 1:
|
||||
baseClassName += " md:grid-cols-1 ";
|
||||
break;
|
||||
case 2:
|
||||
baseClassName += " md:grid-cols-1 lg:grid-cols-2 ";
|
||||
break;
|
||||
case 3:
|
||||
baseClassName += " md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 ";
|
||||
break;
|
||||
case 4:
|
||||
baseClassName += " md:grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 ";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
if (className == undefined) {
|
||||
className = baseClassName;
|
||||
} else {
|
||||
className = baseClassName + className;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={`hidden items-start justify-center gap-6 rounded-lg p-8 md:grid lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4" ${className}`}
|
||||
className={`hidden items-start justify-center gap-6 rounded-lg p-8 md:grid " ${className}`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue