fix(ceo-web): correct imports in LegislationPage (session-provider + apiFetch pattern)

This commit is contained in:
admin-valentin 2026-08-01 20:25:07 +00:00
parent 56ba4da17e
commit 5b734aa14b

View file

@ -1,26 +1,22 @@
'use client'; 'use client';
import { useState } from 'react'; import { useState } from 'react';
import { useSession } from '../../../lib/session'; import { useQuery } from '@tanstack/react-query';
import { apiFetch } from '../../../lib/api'; import { apiFetch } from '../../../lib/api';
import { useSession } from '../../../components/session-provider';
interface LegResult { interface LegResult {
country?: string; country?: string;
section?: string; section?: string;
text?: string; text?: string;
source_id?: string; source_id?: string;
[key: string]: unknown;
}
interface ApiSearchResponse {
scenario?: string;
country_filter?: string;
results?: LegResult[];
} }
type Mode = 'search' | 'ask'; type Mode = 'search' | 'ask';
export default function LegislationPage() { export default function LegislationPage() {
const { session } = useSession(); const { activeTenant } = useSession();
const tenantId = activeTenant?.tenantId ?? null;
const [mode, setMode] = useState<Mode>('ask'); const [mode, setMode] = useState<Mode>('ask');
const [input, setInput] = useState(''); const [input, setInput] = useState('');
const [country, setCountry] = useState('DE'); const [country, setCountry] = useState('DE');
@ -32,32 +28,29 @@ export default function LegislationPage() {
async function handleSubmit(e: React.FormEvent) { async function handleSubmit(e: React.FormEvent) {
e.preventDefault(); e.preventDefault();
if (!input.trim() || !session) return; if (!input.trim()) return;
setLoading(true); setError(null); setResults([]); setAiAnswer(null); setLoading(true); setError(null); setResults([]); setAiAnswer(null);
try { try {
const headers = {
Authorization: `Bearer ${session.access_token}`,
'x-tenant-id': session.tenant_id,
'Content-Type': 'application/json',
};
if (mode === 'search') { if (mode === 'search') {
const data: ApiSearchResponse = await apiFetch('/v1/external/legislation/search', { const data = await apiFetch<{ results?: LegResult[] }>('/v1/external/legislation/search', {
method: 'POST', headers, method: 'POST',
body: JSON.stringify({ scenario: input.trim(), country, topK: 10 }), body: { scenario: input.trim(), country, topK: 10 },
tenantId,
}); });
setResults(data.results ?? []); setResults(data.results ?? []);
} else { } else {
const data = await apiFetch('/v1/external/legislation/ask', { const data = await apiFetch<{ textResponse?: string; response?: string }>('/v1/external/legislation/ask', {
method: 'POST', headers, method: 'POST',
body: JSON.stringify({ body: {
message: `${input.trim()} (context juridic: ${country})`, message: `${input.trim()} (context juridic: ${country})`,
sessionId: 'ceo-legislation-' + Date.now(), country,
}), type: 'general',
}) as Record<string, unknown>; sessionId: `ceo-legislation-${Date.now()}`,
const text = (data?.textResponse ?? data?.response ?? data?.message ?? '') as string; },
setAiAnswer(text); tenantId,
});
setAiAnswer(data?.textResponse ?? data?.response ?? '');
} }
setSearched(true); setSearched(true);
} catch { } catch {
@ -79,7 +72,6 @@ export default function LegislationPage() {
</p> </p>
</div> </div>
{/* Mode toggle */}
<div className="flex gap-1 p-1 bg-muted rounded-lg w-fit"> <div className="flex gap-1 p-1 bg-muted rounded-lg w-fit">
{(['ask', 'search'] as Mode[]).map((m) => ( {(['ask', 'search'] as Mode[]).map((m) => (
<button key={m} onClick={() => setMode(m)} <button key={m} onClick={() => setMode(m)}
@ -88,7 +80,7 @@ export default function LegislationPage() {
? 'bg-background shadow-sm text-foreground' ? 'bg-background shadow-sm text-foreground'
: 'text-muted-foreground hover:text-foreground' : 'text-muted-foreground hover:text-foreground'
}`}> }`}>
{m === 'ask' ? '🤖 Întreabă agentul AI' : '📄 Caută în corpus'} {m === 'ask' ? 'Întreabă agentul AI' : 'Caută în corpus'}
</button> </button>
))} ))}
</div> </div>
@ -100,72 +92,52 @@ export default function LegislationPage() {
? 'ex: Am o firmă GmbH în Germania și vreau să angajez remote din România. Ce obligații legale am?' ? 'ex: Am o firmă GmbH în Germania și vreau să angajez remote din România. Ce obligații legale am?'
: 'Descrie situația ta complet pentru a obține secțiunile de lege relevante...' : 'Descrie situația ta complet pentru a obține secțiunile de lege relevante...'
} }
className="w-full rounded-lg border bg-background px-4 py-3 text-sm className="w-full rounded-lg border bg-background px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring resize-none"
focus:outline-none focus:ring-2 focus:ring-ring resize-none"
/> />
<div className="flex gap-3 flex-wrap"> <div className="flex gap-3 flex-wrap">
<select value={country} onChange={(e) => setCountry(e.target.value)} <select value={country} onChange={(e) => setCountry(e.target.value)}
className="rounded-lg border bg-background px-3 py-2 text-sm className="rounded-lg border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring">
focus:outline-none focus:ring-2 focus:ring-ring">
<option value="DE">Germania (DE)</option> <option value="DE">Germania (DE)</option>
<option value="RO">România (RO)</option> <option value="RO">România (RO)</option>
<option value="EU">UE (EU)</option> <option value="EU">UE (EU)</option>
<option value="AT">Austria (AT)</option> <option value="FR">Franța (FR)</option>
<option value="UK">UK (UK)</option>
</select> </select>
<button type="submit" disabled={loading || !input.trim()} <button type="submit" disabled={loading || !input.trim()}
className="rounded-lg bg-primary px-6 py-2 text-sm font-medium className="rounded-lg bg-primary px-6 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50">
text-primary-foreground hover:bg-primary/90 disabled:opacity-50">
{loading ? (mode === 'ask' ? 'Agent răspunde...' : 'Se caută...') : (mode === 'ask' ? 'Întreabă' : 'Caută')} {loading ? (mode === 'ask' ? 'Agent răspunde...' : 'Se caută...') : (mode === 'ask' ? 'Întreabă' : 'Caută')}
</button> </button>
</div> </div>
</form> </form>
{error && ( {error && (
<div className="rounded-lg border border-destructive/40 bg-destructive/10 px-4 py-3 <div className="rounded-lg border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive">
text-sm text-destructive">
{error} {error}
</div> </div>
)} )}
{/* AI Answer */}
{aiAnswer && ( {aiAnswer && (
<div className="rounded-xl border bg-card p-5 space-y-3"> <div className="rounded-xl border bg-card p-5 space-y-3">
<div className="flex items-center gap-2 text-sm font-medium"> <p className="text-sm font-medium">Răspuns agent legislație</p>
<span>🤖</span> <div className="text-sm leading-relaxed whitespace-pre-wrap text-foreground">{aiAnswer}</div>
<span>Răspuns agent legislație</span>
</div>
<div className="text-sm leading-relaxed whitespace-pre-wrap text-foreground">
{aiAnswer}
</div>
<p className="text-xs text-muted-foreground border-t pt-2"> <p className="text-xs text-muted-foreground border-t pt-2">
Generat de agentul AnythingLLM · Nu constituie consultanță juridică Generat de agentul AnythingLLM · Nu constituie consultanță juridică
</p> </p>
</div> </div>
)} )}
{/* Vector search results */}
{results.length > 0 && ( {results.length > 0 && (
<div className="space-y-3"> <div className="space-y-3">
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">{results.length} secțiuni relevante găsite</p>
{results.length} secțiuni relevante găsite
</p>
{results.map((r, i) => ( {results.map((r, i) => (
<div key={i} className="rounded-xl border bg-card p-4 space-y-2"> <div key={i} className="rounded-xl border bg-card p-4 space-y-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{r.country && ( {r.country && (
<span className="text-xs bg-primary/10 text-primary px-2 py-0.5 rounded font-mono font-medium"> <span className="text-xs bg-primary/10 text-primary px-2 py-0.5 rounded font-mono font-medium">{r.country}</span>
{r.country}
</span>
)}
{r.section && (
<span className="text-sm font-medium">{r.section}</span>
)} )}
{r.section && <span className="text-sm font-medium">{r.section}</span>}
</div> </div>
{r.text && ( {r.text && <p className="text-xs text-muted-foreground leading-relaxed line-clamp-4">{r.text}</p>}
<p className="text-xs text-muted-foreground leading-relaxed line-clamp-4">
{r.text}
</p>
)}
<p className="text-xs text-muted-foreground/60">{r.source_id}</p> <p className="text-xs text-muted-foreground/60">{r.source_id}</p>
</div> </div>
))} ))}
@ -173,9 +145,7 @@ export default function LegislationPage() {
)} )}
{searched && !loading && results.length === 0 && !aiAnswer && !error && ( {searched && !loading && results.length === 0 && !aiAnswer && !error && (
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">Niciun rezultat pentru scenariul introdus.</p>
Niciun rezultat pentru scenariul introdus.
</p>
)} )}
</div> </div>
); );