Files
fn_registry/frontend/functions/ui/settings_page.tsx
T
egutierrez 953f598b9b feat: funciones frontend React/TS — componentes UI, hooks Wails, charts y tipos
Componentes React reutilizables: card, dialog, tabs, select, alert, badge, button, input, label,
skeleton, tooltip, progress_bar, page_header, form_field, settings_page, crud_page, analytics_page,
dashboard_layout. Charts: area, bar, line, sparkline, kpi_card, chart_container.
Hooks Wails: use_wails_query, use_wails_mutation, use_wails_stream, use_wails_event, use_animated_canvas.
Funciones core: cn, format_compact, chart_colors, get_series_color, wails_cache, theme_config_to_colors.
Tipos: chart_series, wails_ipc, theme_config, component_variants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 20:55:34 +02:00

113 lines
4.4 KiB
TypeScript

import * as React from 'react'
import { cn } from '../core/cn'
interface SettingField {
key: string
label: string
description?: string
type: 'text' | 'number' | 'toggle' | 'select' | 'textarea'
value?: unknown
options?: Array<{ label: string; value: string }>
placeholder?: string
}
interface SettingSection {
id: string
title: string
description?: string
fields: SettingField[]
}
interface SettingsPageProps {
title?: string
subtitle?: string
sections: SettingSection[]
onSave?: (values: Record<string, unknown>) => void
className?: string
}
export function settingsPage({
title = 'Settings',
subtitle,
sections,
onSave,
className,
}: SettingsPageProps): React.ReactElement {
return (
<div className={cn('space-y-6', className)}>
{/* Header */}
<div className="border-b pb-4">
<h1 className="text-2xl font-semibold tracking-tight">{title}</h1>
{subtitle && <p className="text-sm text-muted-foreground">{subtitle}</p>}
</div>
{/* Tabs navigation */}
<div className="flex gap-6">
<nav className="hidden w-48 shrink-0 md:block">
<div className="space-y-1">
{sections.map((section) => (
<a
key={section.id}
href={`#${section.id}`}
className="block rounded-md px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-muted hover:text-foreground"
>
{section.title}
</a>
))}
</div>
</nav>
{/* Sections */}
<div className="flex-1 space-y-8">
{sections.map((section) => (
<div key={section.id} id={section.id} className="space-y-4">
<div>
<h2 className="text-lg font-medium">{section.title}</h2>
{section.description && <p className="text-sm text-muted-foreground">{section.description}</p>}
</div>
<div className="space-y-4 rounded-lg border p-4">
{section.fields.map((field) => (
<div key={field.key} className="flex flex-col gap-1.5 sm:flex-row sm:items-center sm:justify-between">
<div className="space-y-0.5">
<label className="text-sm font-medium">{field.label}</label>
{field.description && <p className="text-xs text-muted-foreground">{field.description}</p>}
</div>
<div className="w-full sm:w-64">
{field.type === 'toggle' ? (
<button className={cn(
'relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors',
field.value ? 'bg-primary' : 'bg-input'
)}>
<span className={cn('pointer-events-none block size-4 rounded-full bg-background shadow-lg ring-0 transition-transform', field.value ? 'translate-x-4' : 'translate-x-0')} />
</button>
) : field.type === 'select' ? (
<select className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm">
{field.options?.map((opt) => <option key={opt.value} value={opt.value}>{opt.label}</option>)}
</select>
) : field.type === 'textarea' ? (
<textarea className="w-full rounded-lg border border-input bg-transparent px-2.5 py-1.5 text-sm" rows={3} placeholder={field.placeholder} defaultValue={String(field.value ?? '')} />
) : (
<input type={field.type} className="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 text-sm" placeholder={field.placeholder} defaultValue={String(field.value ?? '')} />
)}
</div>
</div>
))}
</div>
</div>
))}
{onSave && (
<div className="flex justify-end border-t pt-4">
<button className="inline-flex h-8 items-center rounded-lg bg-primary px-4 text-sm font-medium text-primary-foreground hover:bg-primary/80">
Save changes
</button>
</div>
)}
</div>
</div>
</div>
)
}
export type { SettingsPageProps, SettingSection, SettingField }