'use client'; import { useEffect, useState } from 'react'; export interface AiModelInfo { id: string; name: string; description: string; model: string; path: string; trigger: string; access: string; } const STORAGE_KEY = 'mistral_api_key_meta'; interface KeyMeta { createdAt: string; validityMonths: string; } interface Props { keyHint: string; hasKey: boolean; aiFunctions: AiModelInfo[]; } export default function AiAdminClient({ keyHint, hasKey, aiFunctions }: Props) { const [meta, setMeta] = useState({ createdAt: '', validityMonths: '' }); useEffect(() => { try { const stored = localStorage.getItem(STORAGE_KEY); if (stored) setMeta(JSON.parse(stored)); } catch { // ignore } }, []); const saveMeta = (patch: Partial) => { const updated = { ...meta, ...patch }; setMeta(updated); try { localStorage.setItem(STORAGE_KEY, JSON.stringify(updated)); } catch { // ignore } }; const { daysLeft, expiryDate } = computeExpiry(meta.createdAt, meta.validityMonths); const modelChip = (model: string) => { const color = model.includes('tiny') ? '#6366f1' : '#0ea5e9'; return ( {model} ); }; const accessChip = (access: string) => { const isAdmin = access === 'Admin'; const isPremium = access.includes('Premium'); const bg = isAdmin ? '#7c3aed' : isPremium ? '#f59e0b' : '#10b981'; return ( {access} ); }; return (
{/* API-nyckel */}

🔑 Mistral API-nyckel

{!hasKey && (
⚠️ MISTRAL_API_KEY är inte konfigurerad — alla AI-funktioner är inaktiva tills nyckeln sätts i miljövariablerna.
)} {hasKey && (
ℹ️ Status Konfigurerad innebär att API-nyckeln är satt. Om Mistral svarar med 503 är det ett tillfälligt serverfel hos Mistral — inte ett konfigurationsproblem.
)}
Status {hasKey ? âś“ Konfigurerad : âś— Saknas (MISTRAL_API_KEY ej satt)} Nyckel (sista 4) ****{keyHint}
{expiryDate && daysLeft !== null ? (
Förfaller {expiryDate}
{daysLeft <= 0 ? '⚠️ Nyckel har förfallit!' : `${daysLeft} dagar kvar`}
) : (
Fyll i datum och giltighet för att se återstående tid
)}
{/* AI-funktioner */}

✨ Implementerade AI-funktioner

{aiFunctions.map((fn, i) => ( ))}
Status Funktion Modell Åtkomst Utlösare Sida
{hasKey ? ( âś“ Konfigurerad ) : ( âś— Inaktiv )}
{fn.name}
{fn.description}
{modelChip(fn.model)} {accessChip(fn.access)} {fn.trigger} {fn.path}
tiny Snabb och kostnadseffektiv — text- och bildtolkning
small Bättre resoneringsförmåga — kategorisering och matchning
); } function computeExpiry(createdAt: string, validityMonths: string): { daysLeft: number | null; expiryDate: string | null } { if (!createdAt || !validityMonths) return { daysLeft: null, expiryDate: null }; const months = parseInt(validityMonths, 10); if (isNaN(months) || months <= 0) return { daysLeft: null, expiryDate: null }; const created = new Date(createdAt); if (isNaN(created.getTime())) return { daysLeft: null, expiryDate: null }; const expiry = new Date(created); expiry.setMonth(expiry.getMonth() + months); const today = new Date(); today.setHours(0, 0, 0, 0); expiry.setHours(0, 0, 0, 0); const daysLeft = Math.round((expiry.getTime() - today.getTime()) / (1000 * 60 * 60 * 24)); const expiryDate = expiry.toLocaleDateString('sv-SE'); return { daysLeft, expiryDate }; }