140 lines
6 KiB
TypeScript
140 lines
6 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { apiFetch } from '../../../../lib/api';
|
|
import { useSession } from '../../../../components/session-provider';
|
|
|
|
interface CompanyResult {
|
|
cui?: string; companyId?: string; name?: string; companyName?: string;
|
|
industry?: string; county?: string; city?: string; country?: string;
|
|
employees?: number; revenue?: number; registrationDate?: string;
|
|
isActive?: boolean; caenCode?: string; caenLabel?: string;
|
|
}
|
|
|
|
export default function CompaniesIntelligencePage() {
|
|
const { activeTenant } = useSession();
|
|
const tenantId = activeTenant?.tenantId ?? '';
|
|
|
|
const [q, setQ] = useState('');
|
|
const [submitted, setSubmitted] = useState('');
|
|
|
|
const { data, isLoading, error } = useQuery({
|
|
queryKey: ['intel-companies', tenantId, submitted],
|
|
queryFn: () => apiFetch<{ results?: CompanyResult[]; total?: number } | CompanyResult[]>(
|
|
`/v1/intelligence/companies/search?q=${encodeURIComponent(submitted)}&limit=20`,
|
|
{ tenantId }
|
|
),
|
|
enabled: Boolean(tenantId) && submitted.length >= 2,
|
|
staleTime: 300_000,
|
|
});
|
|
|
|
const results: CompanyResult[] = Array.isArray(data) ? data : (data as any)?.results ?? [];
|
|
|
|
return (
|
|
<div className="max-w-3xl space-y-6 p-6">
|
|
<div>
|
|
<h1 className="font-display text-2xl font-semibold text-ink">Baza de date Companii</h1>
|
|
<p className="text-sm text-ink-faint mt-1">
|
|
Caută companii din registrul de business — nume, CUI, domeniu de activitate.
|
|
</p>
|
|
</div>
|
|
|
|
{/* Search box */}
|
|
<form onSubmit={(e) => { e.preventDefault(); if (q.trim().length >= 2) setSubmitted(q.trim()); }}
|
|
className="flex gap-2">
|
|
<input
|
|
placeholder="Caută companie (minim 2 caractere)…"
|
|
value={q} onChange={(e) => setQ(e.target.value)}
|
|
className="flex-1 rounded-lg border bg-card px-4 py-2.5 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring"
|
|
/>
|
|
<button type="submit" disabled={q.trim().length < 2}
|
|
className="btn btn-primary px-5 py-2.5 text-sm rounded-lg disabled:opacity-50">
|
|
Caută
|
|
</button>
|
|
</form>
|
|
|
|
{/* Results */}
|
|
{isLoading && (
|
|
<div className="text-center text-sm text-ink-faint py-8">Se caută…</div>
|
|
)}
|
|
|
|
{error && (
|
|
<div className="card p-4 bg-signal-danger/5 border-signal-danger/20">
|
|
<p className="text-sm text-signal-danger">Eroare la căutare. Verifică conexiunea la baza de date.</p>
|
|
</div>
|
|
)}
|
|
|
|
{!isLoading && submitted && results.length === 0 && !error && (
|
|
<div className="card p-8 text-center space-y-2">
|
|
<p className="text-2xl">🔍</p>
|
|
<p className="text-sm text-ink-faint">Niciun rezultat pentru "{submitted}"</p>
|
|
</div>
|
|
)}
|
|
|
|
{results.length > 0 && (
|
|
<div className="space-y-3">
|
|
<p className="text-xs text-ink-faint">{results.length} rezultate pentru "{submitted}"</p>
|
|
<div className="card divide-y divide-border/50">
|
|
{results.map((company, i) => {
|
|
const name = company.name ?? company.companyName ?? '—';
|
|
const id = company.cui ?? company.companyId ?? String(i);
|
|
return (
|
|
<div key={id} className="p-4 space-y-1">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-semibold text-ink">{name}</p>
|
|
{(company.cui || company.companyId) && (
|
|
<p className="text-[10px] text-ink-faint font-mono mt-0.5">
|
|
CUI: {company.cui ?? company.companyId}
|
|
</p>
|
|
)}
|
|
</div>
|
|
{company.isActive !== undefined && (
|
|
<span className={`shrink-0 rounded-full px-2 py-0.5 text-[10px] font-medium ${
|
|
company.isActive ? 'bg-signal-ok/10 text-signal-ok' : 'bg-muted text-ink-faint'
|
|
}`}>
|
|
{company.isActive ? 'Activ' : 'Inactiv'}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-wrap gap-3">
|
|
{company.industry && (
|
|
<span className="text-[10px] text-ink-faint">🏭 {company.industry}</span>
|
|
)}
|
|
{(company.caenCode || company.caenLabel) && (
|
|
<span className="text-[10px] text-ink-faint">📋 {company.caenCode}{company.caenLabel ? ` — ${company.caenLabel}` : ''}</span>
|
|
)}
|
|
{(company.city || company.county) && (
|
|
<span className="text-[10px] text-ink-faint">📍 {[company.city, company.county].filter(Boolean).join(', ')}</span>
|
|
)}
|
|
{company.employees && (
|
|
<span className="text-[10px] text-ink-faint">👥 {company.employees.toLocaleString('ro-RO')} angajați</span>
|
|
)}
|
|
{company.registrationDate && (
|
|
<span className="text-[10px] text-ink-faint">📅 {company.registrationDate.slice(0, 10)}</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{!submitted && (
|
|
<div className="card p-6 space-y-3">
|
|
<p className="text-xs font-semibold text-ink-faint uppercase tracking-wider">Cum funcționează</p>
|
|
<div className="space-y-2">
|
|
{[
|
|
'🔍 Caută după denumire completă sau parțială',
|
|
'🔢 Caută după CUI (cod unic de identificare)',
|
|
'📊 Rezultatele includ date ONRC: CAEN, angajați, locație',
|
|
'⚡ Rezultatele sunt live din baza de date de intelligence',
|
|
].map((s) => <p key={s} className="text-xs text-ink-faint">{s}</p>)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|