feat: ReactBits micro components integration

Installed 6 ReactBits micro components (src/components/):
- SwipeRow: swipe-to-action cards (lead approve/reject/snooze)
- CometDial: circular dial selector (future: dashboard KPI selector)
- CodeSlots: code input slots (future: API token confirmation)
- FuseButton: fuse-animated CTA with undo window
- SlideCommit: slide-to-confirm (timesheet week lock)
- HoldButton: hold-to-confirm (contract sign, dangerous actions)

Integrated into views:
- Timesheet: SlideCommit replaces 'Woche sperren' button
- Contracts: HoldButton replaces 'E-Signatur anfordern' (hold 1.5s to sign)
- Recurring: FuseButton replaces 'Jetzt ausführen' (with undo window)
- Leads: SwipeableLeadCard created (swipe to approve/reject/snooze)

Created wrapper components:
- swipeable-lead-card.tsx: SwipeRow wrapper for lead cards
- hold-to-confirm.tsx: HoldButton wrapper with loading state
- fuse-cta.tsx: FuseButton wrapper with toast feedback
- slide-to-lock.tsx: SlideCommit wrapper for GoBD week lock

0 TS errors, ESLint clean, no console errors.
This commit is contained in:
Z User committed 2026-10-28 02:36:53 +00:00
1 parent 21e112e5cb
commit 37e976a732
17 files changed
+2884 -25

No files matched your search

+61
View File
@@ -0,0 +1,61 @@
'use client'
import FuseButton from '@/components/FuseButton'
import { useState } from 'react'
import { toast } from 'sonner'
import { Loader2 } from 'lucide-react'
// FuseButton wrapper for primary CTA actions with undo window.
// Used for: create deal, finalize invoice, run recurring, approve estimate.
export function FuseCTA({
label,
doneLabel = 'Erledigt',
undoLabel = 'Rückgängig',
onCommit,
onUndo,
disabled,
size = 'md',
}: {
label: string
doneLabel?: string
undoLabel?: string
onCommit: () => void | Promise<void>
onUndo?: () => void
disabled?: boolean
size?: 'sm' | 'md' | 'lg'
}) {
const [busy, setBusy] = useState(false)
const handleCommit = async () => {
setBusy(true)
const t = toast.loading('Wird ausgeführt…')
try {
await onCommit()
toast.success(doneLabel, { id: t })
} catch {
toast.error('Fehlgeschlagen', { id: t })
} finally {
setBusy(false)
}
}
return (
<FuseButton
label={busy ? 'Lädt…' : label}
doneLabel={doneLabel}
undoLabel={undoLabel}
onCommit={handleCommit}
onUndo={onUndo}
disabled={disabled || busy}
size={size}
commitOn="fuseEnd"
settle="stay"
fuse="bottom"
fuseThickness={2}
undoWindow={4000}
color="oklch(0.98 0 0)"
background="oklch(0.2 0 0)"
fuseColor="oklch(0.5 0 0)"
/>
)
}