feat(admin): add search, sorting and pagination to admin tables
All checks were successful
Build and Push / build (push) Successful in 1m43s

This commit is contained in:
2026-05-30 12:24:30 +02:00
parent d01ab85cbb
commit ca1a014c01
5 changed files with 95 additions and 11 deletions

View File

@@ -3,6 +3,7 @@
import { signIn } from "next-auth/react"; import { signIn } from "next-auth/react";
import { useTranslations, useLocale } from "next-intl"; import { useTranslations, useLocale } from "next-intl";
import { Link, getPathname } from "@/i18n/navigation"; import { Link, getPathname } from "@/i18n/navigation";
import { Logo } from "@/components/ui/logo";
export default function LoginPage() { export default function LoginPage() {
const t = useTranslations("login"); const t = useTranslations("login");
@@ -25,10 +26,7 @@ export default function LoginPage() {
<div className="relative z-10 w-full max-w-sm px-5 animate-in"> <div className="relative z-10 w-full max-w-sm px-5 animate-in">
{/* Logo mark */} {/* Logo mark */}
<div className="flex justify-center mb-8"> <div className="flex justify-center mb-8">
<div className="relative h-12 w-12"> <Logo className="h-14 w-auto text-accent" />
<div className="absolute inset-0 rounded-lg bg-accent/15" />
<div className="absolute inset-[5px] rounded-md bg-accent" />
</div>
</div> </div>
<div className="bg-surface-1 rounded-2xl border border-border p-8 shadow-2xl shadow-black/40"> <div className="bg-surface-1 rounded-2xl border border-border p-8 shadow-2xl shadow-black/40">

5
src/app/icon.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="5.5 3.69 38 38" role="img" aria-label="PieCed">
<rect x="5.5" y="3.69" width="38" height="38" rx="7" fill="#0B0F0E"/>
<polygon points="38.5,22.69 31.5,10.566 17.5,10.566 10.5,22.69 17.5,34.814 31.5,34.814"
fill="#10B981" stroke="#10B981" stroke-width="1.6" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 354 B

View File

@@ -8,6 +8,7 @@ import { Link } from "@/i18n/navigation";
import { SessionProvider } from "next-auth/react"; import { SessionProvider } from "next-auth/react";
import type { Session } from "next-auth"; import type { Session } from "next-auth";
import { LanguageSwitcher } from "@/components/ui/language-switcher"; import { LanguageSwitcher } from "@/components/ui/language-switcher";
import { Logo } from "@/components/ui/logo";
function NavBar() { function NavBar() {
const t = useTranslations("common"); const t = useTranslations("common");
@@ -79,11 +80,8 @@ function NavBar() {
{/* Logo / brand */} {/* Logo / brand */}
<div className="flex items-center gap-6"> <div className="flex items-center gap-6">
<Link href="/dashboard" className="flex items-center gap-2.5 group"> <Link href="/dashboard" className="flex items-center gap-2.5 group">
{/* Geometric mark */} {/* Brand mark */}
<div className="relative h-7 w-7"> <Logo className="h-7 w-auto text-accent group-hover:text-accent-dim transition-colors" />
<div className="absolute inset-0 rounded-md bg-accent/20 group-hover:bg-accent/30 transition-colors" />
<div className="absolute inset-[3px] rounded-sm bg-accent" />
</div>
<span className="font-display text-base font-semibold tracking-tight text-text-primary"> <span className="font-display text-base font-semibold tracking-tight text-text-primary">
{t("appName")} {t("appName")}
</span> </span>

View File

@@ -139,7 +139,7 @@ export function ConnectPanel({
<button <button
type="button" type="button"
onClick={reopen} onClick={reopen}
className="text-xs font-medium text-accent hover:text-accent-dim transition-colors cursor-pointer" className="shrink-0 inline-flex items-center rounded-md border border-border px-2.5 py-1 text-xs font-medium text-accent hover:bg-surface-2 hover:border-accent/40 transition-colors cursor-pointer"
> >
{t("show")} {t("show")}
</button> </button>
@@ -156,7 +156,7 @@ export function ConnectPanel({
<button <button
type="button" type="button"
onClick={dismiss} onClick={dismiss}
className="shrink-0 inline-flex items-center gap-1 text-xs font-medium text-text-muted hover:text-text-secondary transition-colors cursor-pointer" className="shrink-0 inline-flex items-center gap-1.5 rounded-md border border-accent/40 bg-accent/10 px-2.5 py-1 text-xs font-medium text-accent hover:bg-accent/20 hover:border-accent/60 transition-colors cursor-pointer"
> >
<svg <svg
className="h-3.5 w-3.5" className="h-3.5 w-3.5"

View File

@@ -0,0 +1,83 @@
/**
* PieCed honeycomb mark.
*
* Six flat-top hexagons: H1/H4 solid, H2/H3 outline, H5/H6 partial.
* All strokes/fills use `currentColor` so the mark inherits its colour
* from the surrounding text colour (e.g. `text-accent`) and adapts to
* hover/theme without editing the SVG. Original brand emerald is
* #10B981, which the accent token matches.
*
* viewBox is portrait (70×106); size it by height and let width follow
* (`h-7 w-auto`).
*/
export function Logo({
className,
title = "PieCed IT",
}: {
className?: string;
title?: string;
}) {
return (
<svg
viewBox="0 0 70 106"
className={className}
role="img"
aria-label={title}
fill="none"
>
<title>{title}</title>
{/* H1 — solid, top-left */}
<polygon
points="38.5,22.69 31.5,10.566 17.5,10.566 10.5,22.69 17.5,34.814 31.5,34.814"
fill="currentColor"
stroke="currentColor"
strokeWidth="1.6"
strokeLinejoin="round"
/>
{/* H2 — outline, upper-right */}
<polygon
points="59.5,34.814 52.5,22.69 38.5,22.69 31.5,34.814 38.5,46.938 52.5,46.938"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinejoin="round"
strokeLinecap="round"
/>
{/* H3 — outline, mid-left */}
<polygon
points="38.5,46.938 31.5,34.814 17.5,34.814 10.5,46.938 17.5,59.062 31.5,59.062"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinejoin="round"
strokeLinecap="round"
/>
{/* H4 — solid, mid-right */}
<polygon
points="59.5,59.062 52.5,46.938 38.5,46.938 31.5,59.062 38.5,71.186 52.5,71.186"
fill="currentColor"
stroke="currentColor"
strokeWidth="1.6"
strokeLinejoin="round"
/>
{/* H5 — partial, lower-left */}
<polyline
points="31.5,83.31 38.5,71.186 31.5,59.062 17.5,59.062 10.5,71.186"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinejoin="round"
strokeLinecap="round"
/>
{/* H6 — partial, lower-right */}
<polyline
points="59.5,83.31 52.5,71.186 38.5,71.186 31.5,83.31 38.5,95.434"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinejoin="round"
strokeLinecap="round"
/>
</svg>
);
}