b800dcd403
* style(ui): system-wide UX/UI polish pass — design-system conformance + copy cleanup Multi-agent scan of all 404 UI files against the locked design system, then 141 verified surgical fixes across 109 files (net -32 lines): - Remove forbidden elevation/motion: shadow-* and rounded-xl on cards, active:scale bounce, hover:shadow on list items, transition-all -> transition-colors. - Drop font-medium from single-weight Hedvig display headings/numerals. - Replace raw rainbow Tailwind status colors with Badge variants / brand tokens / neutral surfaces (achromatic chrome, semantic colors stay data-only). - Route raw dates through formatDate(), hand-rolled currency through formatCurrency(), add tabular-nums to financial figures; text-gray-* -> text-foreground tokens. - Swap hand-rolled skeletons for the Skeleton primitive; off-scale spacing -> token scale. - Fix copy: mislabeled "Leverantörsfakturor" -> "Utgifter" on bank-import outflow total, collapse no-op identical-branch ternaries, broken Swedish diacritics (mojibake), correct mismatch-password toast, correct supplier currency-field label. - Remove PII-leaking debug console.log on register, stray console.logs. Verified: tsc clean on all changed files, eslint clean, production build passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(auth): sanitize residual error logs in register flow Follow-up to PR review (compliance swarm V16 / GDPR Art.5(1)(f)): the remaining console.error calls in the register flow passed raw error objects, which Supabase may populate with PII (email) in nested fields. Log only sanitized message strings instead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
'use client'
|
|
|
|
import { Card, CardContent } from '@/components/ui/card'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Input } from '@/components/ui/input'
|
|
import { Label } from '@/components/ui/label'
|
|
import { Settings } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
|
|
interface SetupField {
|
|
key: string
|
|
label: string
|
|
type?: 'number' | 'text'
|
|
placeholder?: string
|
|
}
|
|
|
|
interface SetupPromptProps {
|
|
title: string
|
|
description: string
|
|
fields: SetupField[]
|
|
onSave: (values: Record<string, string>) => Promise<void>
|
|
}
|
|
|
|
export default function SetupPrompt({ title, description, fields, onSave }: SetupPromptProps) {
|
|
const [values, setValues] = useState<Record<string, string>>({})
|
|
const [isSaving, setIsSaving] = useState(false)
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault()
|
|
setIsSaving(true)
|
|
try {
|
|
await onSave(values)
|
|
} finally {
|
|
setIsSaving(false)
|
|
}
|
|
}
|
|
|
|
const allFilled = fields.every(f => values[f.key]?.trim())
|
|
|
|
return (
|
|
<div className="flex items-center justify-center py-12">
|
|
<Card className="w-full max-w-md">
|
|
<CardContent className="pt-6">
|
|
<div className="text-center mb-6">
|
|
<div className="inline-flex items-center justify-center w-12 h-12 rounded-full bg-muted mb-3">
|
|
<Settings className="h-6 w-6 text-muted-foreground" />
|
|
</div>
|
|
<h3 className="font-semibold">{title}</h3>
|
|
<p className="text-sm text-muted-foreground mt-1">{description}</p>
|
|
</div>
|
|
<form onSubmit={handleSubmit} className="space-y-4">
|
|
{fields.map(field => (
|
|
<div key={field.key} className="space-y-2">
|
|
<Label htmlFor={`setup-${field.key}`}>{field.label}</Label>
|
|
<Input
|
|
id={`setup-${field.key}`}
|
|
type={field.type ?? 'text'}
|
|
placeholder={field.placeholder}
|
|
value={values[field.key] ?? ''}
|
|
onChange={e => setValues(prev => ({ ...prev, [field.key]: e.target.value }))}
|
|
/>
|
|
</div>
|
|
))}
|
|
<Button type="submit" className="w-full" disabled={!allFilled || isSaving}>
|
|
{isSaving ? 'Sparar...' : 'Kom igång'}
|
|
</Button>
|
|
</form>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|