OwnGPT.v2 / client /src /components /UI /ModelDialog.jsx
parthib07's picture
Upload 199 files
212c959 verified
import { useEffect, useMemo, useState } from 'react'
import { Check } from 'lucide-react'
import Modal from './Modal'
import Button from './Button'
export default function ModelDialog({
open,
onOpenChange,
registry,
currentProvider,
currentModel,
onSelect,
}) {
const providerIds = useMemo(() => Object.keys(registry || {}), [registry])
const [activeProvider, setActiveProvider] = useState(currentProvider || providerIds[0] || 'groq')
const provider = registry?.[activeProvider]
const models = provider?.models || []
const providerEnabled = provider?.enabled !== false
useEffect(() => {
if (!open || !providerIds.length) return
setActiveProvider(currentProvider || providerIds[0])
}, [open, currentProvider, providerIds])
return (
<Modal
open={open}
onOpenChange={onOpenChange}
size="lg"
title="Models"
>
<div className="grid gap-4 lg:grid-cols-[200px_minmax(0,1fr)]">
<div className="space-y-2">
{providerIds.map((providerId) => (
<button
key={providerId}
type="button"
onClick={() => setActiveProvider(providerId)}
className={`w-full rounded-lg border px-3 py-2.5 text-left text-sm transition ${
activeProvider === providerId
? 'border-border bg-secondary text-foreground'
: 'border-border bg-panel text-muted-foreground hover:bg-secondary hover:text-foreground'
}`}
>
<div className="flex items-center justify-between gap-2">
<p className="truncate font-medium">{registry[providerId].label}</p>
<span
className={`h-2 w-2 rounded-full ${
registry[providerId].enabled !== false
? 'bg-accent'
: 'bg-danger'
}`}
aria-label={registry[providerId].enabled !== false ? 'Connected' : 'Setup needed'}
/>
</div>
</button>
))}
</div>
<div className="space-y-3">
{providerEnabled ? null : (
<div className="rounded-lg border border-danger/25 bg-danger/5 px-4 py-3 text-sm text-muted-foreground">
{provider?.reason || 'This provider is not configured for the current deployment.'}
</div>
)}
{models.map((model) => {
const active = currentProvider === activeProvider && currentModel === model.id
return (
<button
key={model.id}
type="button"
disabled={!providerEnabled}
onClick={() => {
if (!providerEnabled) return
onSelect(activeProvider, model.id)
onOpenChange(false)
}}
className={`w-full rounded-lg border px-4 py-3 text-left transition disabled:cursor-not-allowed disabled:opacity-60 ${
active
? 'border-border bg-secondary'
: 'border-border bg-panel hover:bg-secondary'
}`}
>
<div className="flex items-center justify-between gap-3">
<div className="min-w-0">
<p className="truncate font-medium text-foreground">{model.name}</p>
<p className="truncate text-sm text-muted-foreground">{model.id}</p>
</div>
{active ? (
<div className="rounded-lg bg-accent p-2 text-accent-foreground">
<Check className="h-4 w-4" />
</div>
) : null}
</div>
</button>
)
})}
{!models.length ? (
<div className="rounded-lg border border-border bg-panel px-4 py-10 text-center text-sm text-muted-foreground">
No models available for this provider.
</div>
) : null}
</div>
</div>
<div className="mt-5 flex justify-end">
<Button variant="ghost" onClick={() => onOpenChange(false)}>
Close
</Button>
</div>
</Modal>
)
}