109 lines
4.1 KiB
TypeScript
109 lines
4.1 KiB
TypeScript
import type { Nip95Config } from '@/lib/configStorageTypes'
|
||
import { Button } from '../ui'
|
||
import { t } from '@/lib/i18n'
|
||
import { Nip95ApiList } from './Nip95ApiList'
|
||
|
||
export function Nip95ConfigContent(params: {
|
||
apis: Nip95Config[]
|
||
error: string | null
|
||
editingId: string | null
|
||
newUrl: string
|
||
showAddForm: boolean
|
||
draggedId: string | null
|
||
dragOverId: string | null
|
||
onClearError: () => void
|
||
onToggleAddForm: () => void
|
||
onNewUrlChange: (value: string) => void
|
||
onCancelAdd: () => void
|
||
onAddApi: () => void
|
||
onStartEditing: (id: string) => void
|
||
onStopEditing: () => void
|
||
onUpdateUrl: (id: string, url: string) => void
|
||
onToggleEnabled: (id: string, enabled: boolean) => void
|
||
onRemoveApi: (id: string) => void
|
||
onDragStart: (e: React.DragEvent<HTMLDivElement>, id: string) => void
|
||
onDragOver: (e: React.DragEvent<HTMLDivElement>, id: string) => void
|
||
onDragLeave: () => void
|
||
onDrop: (e: React.DragEvent<HTMLDivElement>, targetId: string) => void
|
||
}): React.ReactElement {
|
||
return (
|
||
<div className="space-y-6">
|
||
{params.error ? <ErrorBanner error={params.error} onClear={params.onClearError} /> : null}
|
||
<Header showAddForm={params.showAddForm} onToggleAddForm={params.onToggleAddForm} />
|
||
{params.showAddForm ? <AddForm newUrl={params.newUrl} onNewUrlChange={params.onNewUrlChange} onAdd={params.onAddApi} onCancel={params.onCancelAdd} /> : null}
|
||
<Nip95ApiList apis={params.apis} editingId={params.editingId} draggedId={params.draggedId} dragOverId={params.dragOverId} onStartEditing={params.onStartEditing} onStopEditing={params.onStopEditing} onUpdateUrl={params.onUpdateUrl} onToggleEnabled={params.onToggleEnabled} onRemoveApi={params.onRemoveApi} onDragStart={params.onDragStart} onDragOver={params.onDragOver} onDragLeave={params.onDragLeave} onDrop={params.onDrop} />
|
||
<Notes />
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function ErrorBanner(params: { error: string; onClear: () => void }): React.ReactElement {
|
||
return (
|
||
<div className="bg-red-900/30 border border-red-500/50 rounded p-4 text-red-300">
|
||
{params.error}
|
||
<button type="button" onClick={params.onClear} className="ml-4 text-red-400 hover:text-red-200">
|
||
×
|
||
</button>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function Header(params: { showAddForm: boolean; onToggleAddForm: () => void }): React.ReactElement {
|
||
return (
|
||
<div className="flex justify-between items-center">
|
||
<h2 className="text-2xl font-bold text-neon-cyan">{t('settings.nip95.title')}</h2>
|
||
<Button
|
||
type="button"
|
||
variant="primary"
|
||
onClick={params.onToggleAddForm}
|
||
>
|
||
{params.showAddForm ? t('settings.nip95.add.cancel') : t('settings.nip95.addButton')}
|
||
</Button>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function AddForm(params: { newUrl: string; onNewUrlChange: (value: string) => void; onAdd: () => void; onCancel: () => void }): React.ReactElement {
|
||
return (
|
||
<div className="bg-cyber-dark border border-neon-cyan/30 rounded p-4 space-y-4">
|
||
<div>
|
||
<label className="block text-sm font-medium text-cyber-accent mb-2">{t('settings.nip95.add.url')}</label>
|
||
<input
|
||
type="url"
|
||
value={params.newUrl}
|
||
onChange={(e) => params.onNewUrlChange(e.target.value)}
|
||
placeholder={t('settings.nip95.add.placeholder')}
|
||
className="w-full px-4 py-2 bg-cyber-darker border border-cyber-accent/30 rounded text-cyber-light focus:border-neon-cyan focus:outline-none"
|
||
/>
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<Button
|
||
type="button"
|
||
variant="primary"
|
||
onClick={params.onAdd}
|
||
>
|
||
{t('settings.nip95.add.add')}
|
||
</Button>
|
||
<Button
|
||
type="button"
|
||
variant="ghost"
|
||
onClick={params.onCancel}
|
||
>
|
||
{t('settings.nip95.add.cancel')}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
function Notes(): React.ReactElement {
|
||
return (
|
||
<div className="text-sm text-cyber-accent space-y-2">
|
||
<p>
|
||
<strong>{t('settings.nip95.note.title')}</strong> {t('settings.nip95.note.priority')}
|
||
</p>
|
||
<p>{t('settings.nip95.note.fallback')}</p>
|
||
</div>
|
||
)
|
||
}
|