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

+12 -4
View File
@@ -28,6 +28,7 @@ import {
} from '@/components/ui/dialog'
import { PageHeader } from '../primitives'
import { formatEuro, formatDate, formatDateTime, daysUntil } from '@/lib/format'
import { HoldToConfirm } from '../hold-to-confirm'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'
@@ -312,10 +313,17 @@ export function ContractsView() {
<DialogFooter className="gap-2">
<Button variant="outline" onClick={() => setSelected(null)}>Schließen</Button>
{canSign && (
<Button onClick={() => sign(selected)} disabled={signing} className="gap-1.5">
{signing ? <Loader2 className="size-3.5 animate-spin" /> : <PenLine className="size-3.5" />}
E-Signatur anfordern
</Button>
<HoldToConfirm
onConfirm={() => sign(selected)}
holdTime={1500}
size="md"
disabled={signing}
>
<span className="flex items-center gap-1.5">
<PenLine className="size-3.5" />
E-Signatur anfordern
</span>
</HoldToConfirm>
)}
</DialogFooter>
</>
+8 -4
View File
@@ -6,6 +6,7 @@ import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Skeleton } from '@/components/ui/skeleton'
import { PageHeader } from '../primitives'
import { FuseCTA } from '../fuse-cta'
import { formatEuro, formatEuroCompact, formatDate } from '@/lib/format'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'
@@ -76,10 +77,13 @@ export function RecurringView() {
title="Wiederkehrende Rechnungen"
description="Automatische Generierung von wiederkehrenden Rechnungen (Wartung/SLA-Verträge). Bei Mahnstufe 3: automatische Lizenz-Suspendierung (PRD §6.4)."
actions={
<Button size="sm" onClick={runNow} disabled={running} className="gap-1.5">
{running ? <Loader2 className="size-4 animate-spin" /> : <Play className="size-4" />}
Jetzt ausführen
</Button>
<FuseCTA
label="Jetzt ausführen"
doneLabel="Ausgeführt"
onCommit={runNow}
disabled={running}
size="sm"
/>
}
/>
+2 -4
View File
@@ -11,6 +11,7 @@ import { formatMinutes } from '@/lib/format'
import { cn } from '@/lib/utils'
import { toast } from 'sonner'
import { ChevronLeft, ChevronRight, Lock, Clock, TrendingUp, CheckCircle2, Calendar } from 'lucide-react'
import { SlideToLock } from '../slide-to-lock'
interface DayData {
date: string
@@ -83,10 +84,7 @@ export function TimesheetView() {
description="Wochen-basierte Zeiterfassung mit PM-Freigabe (Lock). Nach Freigabe können Einträge nicht mehr geändert werden — GoBD-konform."
actions={
!stats.allLocked && stats.totalEntries > 0 ? (
<Button size="sm" onClick={lockWeek} disabled={locking} className="gap-1.5">
<Lock className="size-4" />
Woche sperren
</Button>
<SlideToLock onConfirm={lockWeek} disabled={locking} />
) : stats.allLocked ? (
<Badge variant="outline" className="gap-1">
<CheckCircle2 className="size-3" />Gesperrt