Files
erp-system/app/search/page.tsx
T
2026-05-20 18:58:23 +00:00

95 lines
3.8 KiB
TypeScript

// /opt/erp-system/app/search/page.tsx
'use client';
import { useSearchParams } from 'next/navigation';
import { useEffect, useState, Suspense } from 'react';
import Link from 'next/link';
import { Search, Ticket, Users } from 'lucide-react';
import { getStatusBadge } from '../components/AppShell';
function SearchResults() {
const searchParams = useSearchParams();
const q = searchParams.get('q');
const [results, setResults] = useState({ tickets: [], customers: [] });
const [loading, setLoading] = useState(false);
useEffect(() => {
if (q) {
setLoading(true);
fetch(`/api/search?q=${encodeURIComponent(q)}`)
.then(res => res.json())
.then(data => {
setResults(data);
setLoading(false);
});
}
}, [q]);
if (!q) return <div className="text-slate-500 font-medium">Bitte gib einen Suchbegriff ein.</div>;
return (
<div className="max-w-5xl mx-auto space-y-6">
<h1 className="text-2xl font-bold text-slate-900 flex items-center gap-2">
<Search className="w-6 h-6 text-indigo-600" /> Suchergebnisse für "{q}"
</h1>
{loading ? (
<div className="text-slate-500 font-medium animate-pulse">Suche läuft...</div>
) : (
<div className="space-y-8">
<div className="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
<div className="p-4 border-b border-slate-200 bg-slate-50 flex items-center gap-2 font-semibold text-slate-800">
<Users className="w-5 h-5 text-slate-500" /> Kunden ({results.customers?.length || 0})
</div>
<div className="divide-y divide-slate-100">
{results.customers?.length > 0 ? results.customers.map((c: any) => (
<Link key={c.id} href={`/customers/${c.id}`} className="block p-4 hover:bg-slate-50 transition">
<p className="font-semibold text-indigo-600">{c.companyName || `${c.firstName} ${c.lastName}`}</p>
<p className="text-sm text-slate-500">{c.email}</p>
</Link>
)) : (
<div className="p-4 text-sm text-slate-500">Keine Kunden gefunden.</div>
)}
</div>
</div>
<div className="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
<div className="p-4 border-b border-slate-200 bg-slate-50 flex items-center gap-2 font-semibold text-slate-800">
<Ticket className="w-5 h-5 text-slate-500" /> Tickets ({results.tickets?.length || 0})
</div>
<div className="divide-y divide-slate-100">
{results.tickets?.length > 0 ? results.tickets.map((t: any) => (
<Link key={t.id} href={`/tickets/${t.id}`} className="block p-4 hover:bg-slate-50 transition flex justify-between items-start">
<div>
<p className="font-semibold text-indigo-600">#{t.id} - {t.title}</p>
<p className="text-sm text-slate-500 mt-1 line-clamp-1">{t.description}</p>
<p className="text-xs text-slate-400 mt-1">
Kunde: {t.customer.companyName || `${t.customer.firstName} ${t.customer.lastName}`}
</p>
</div>
<div className="ml-4 shrink-0">
{getStatusBadge(t.status)}
</div>
</Link>
)) : (
<div className="p-4 text-sm text-slate-500">Keine Tickets gefunden.</div>
)}
</div>
</div>
</div>
)}
</div>
);
}
export default function SearchPage() {
return (
<Suspense fallback={<div className="text-slate-500">Lade Suche...</div>}>
<SearchResults />
</Suspense>
);
}