0ca22831-efa9-41b6-87bd-e5ee6c344547
This commit is contained in:
1 parent
468e7ad123
commit
09ca75d36e
9 files changed
+294
-1
No files matched your search
@@ -0,0 +1,173 @@
|
||||
'use client'
|
||||
|
||||
import { useAos } from '@/store/aos'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
Rocket,
|
||||
Radar,
|
||||
FolderKanban,
|
||||
Receipt,
|
||||
BookOpen,
|
||||
Webhook,
|
||||
Check,
|
||||
X,
|
||||
ChevronRight,
|
||||
ChevronLeft,
|
||||
Sparkles,
|
||||
ShieldCheck,
|
||||
CalendarDays,
|
||||
} from 'lucide-react'
|
||||
|
||||
const STEPS = [
|
||||
{
|
||||
icon: Rocket,
|
||||
title: 'Willkommen bei AOS',
|
||||
description: 'Die selbstgehostete Plattform, die deine Agentur end-to-end betreibt: von der Lead-Suche bis zur Rechnung und Lizenzverwaltung.',
|
||||
highlight: '20 Module · 21 API-Endpunkte · MCP-Server · Client-Portal',
|
||||
},
|
||||
{
|
||||
icon: Radar,
|
||||
title: 'Leads Finder',
|
||||
description: 'Evidenzbasierte Website-Audits statt geratener KI-Vorschläge. Jeder Score beruht auf gespeicherten Prüfungen — die AI liefert nur die Erklärung.',
|
||||
highlight: 'Approve → Convert → CRM Company + Deal',
|
||||
},
|
||||
{
|
||||
icon: FolderKanban,
|
||||
title: 'Projekte & Support',
|
||||
description: 'Aufgaben, Zeitverfolgung, Budgets. Support-Tickets mit AI-Zusammenfassung und Antwort-Vorschlägen (z-ai-web-dev-sdk, server-side).',
|
||||
highlight: 'SLA-Timer · AI Ticket Summary · Billable Time → Invoice',
|
||||
},
|
||||
{
|
||||
icon: Receipt,
|
||||
title: 'Finanzen & Buchhaltung',
|
||||
description: 'Rechnungen mit E-Rechnung (ZUGFeRD/XRechnung), Umsatzsteuer-Voranmeldung (UStVA-XML, ELSTER), Bankabgleich (CAMT.053), EÜR, Mahnwesen.',
|
||||
highlight: 'GoBD-konform · DATEV-Export · Hash-Kette Audit',
|
||||
},
|
||||
{
|
||||
icon: BookOpen,
|
||||
title: 'Buchhaltung & Fristen',
|
||||
description: 'USt-Voranmeldung mit Kennzahlen (81/86/66/83/37), EÜR, Bankabgleich. Fristen-Kalender aggregiert alle Deadlines aller Module.',
|
||||
highlight: 'Real CAMT.053 Parser · ELSTER XML · SLA-Tracking',
|
||||
},
|
||||
{
|
||||
icon: Webhook,
|
||||
title: 'API & MCP Server',
|
||||
description: 'Public REST API mit Scoped Tokens (SHA-256 gehasht). MCP Server (JSON-RPC) für externe Agenten wie Claude Desktop oder ZeroClaw.',
|
||||
highlight: '8 MCP Tools · HMAC-signed Webhooks · OpenAPI 3.0',
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: 'Compliance & DSGVO',
|
||||
description: 'GoBD (Unveränderlichkeit, Hash-Kette), DSGVO (Konsens-Protokoll, Art. 15 Auskunft), BFSG (Barrierefreiheit), UWG § 7 (Cold-Outreach-Gate).',
|
||||
highlight: 'Self-hosted · Daten bleiben im Server',
|
||||
},
|
||||
{
|
||||
icon: CalendarDays,
|
||||
title: 'Client-Portal & i18n',
|
||||
description: 'Kunden sehen nur ihre eigenen Daten (projekt-isoliert). Meilenstein-Freigaben mit IP-Evidenz. UI in DE/EN/TR umschaltbar.',
|
||||
highlight: 'AdES Signatur · Real IP Evidence · 3 Sprachen',
|
||||
},
|
||||
]
|
||||
|
||||
export function OnboardingOverlay() {
|
||||
const { onboardingSeen, onboardingStep, setOnboardingSeen, setOnboardingStep } = useAos()
|
||||
|
||||
if (onboardingSeen) return null
|
||||
|
||||
const step = STEPS[onboardingStep]
|
||||
const Icon = step.icon
|
||||
const isLast = onboardingStep === STEPS.length - 1
|
||||
|
||||
const next = () => {
|
||||
if (isLast) {
|
||||
setOnboardingSeen(true)
|
||||
} else {
|
||||
setOnboardingStep(onboardingStep + 1)
|
||||
}
|
||||
}
|
||||
|
||||
const prev = () => onboardingStep > 0 && setOnboardingStep(onboardingStep - 1)
|
||||
const skip = () => setOnboardingSeen(true)
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-background/80 backdrop-blur-sm">
|
||||
<div className="mx-4 w-full max-w-lg rounded-xl border border-border bg-card shadow-2xl">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between border-b border-border px-6 py-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="outline" className="text-[10px]">
|
||||
{onboardingStep + 1} / {STEPS.length}
|
||||
</Badge>
|
||||
<span className="text-[10px] uppercase tracking-wide text-muted-foreground">Onboarding</span>
|
||||
</div>
|
||||
<Button variant="ghost" size="icon" className="size-7" onClick={skip} aria-label="Überspringen">
|
||||
<X className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Progress bar */}
|
||||
<div className="h-1 w-full bg-muted">
|
||||
<div
|
||||
className="h-full bg-foreground transition-all duration-300"
|
||||
style={{ width: `${((onboardingStep + 1) / STEPS.length) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="space-y-4 p-6">
|
||||
<div className="flex size-14 items-center justify-center rounded-xl bg-foreground text-background">
|
||||
<Icon className="size-7" />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<h2 className="text-xl font-semibold tracking-tight">{step.title}</h2>
|
||||
<p className="text-sm leading-relaxed text-muted-foreground">{step.description}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 rounded-md border border-dashed border-border bg-muted/30 p-2.5">
|
||||
<Sparkles className="size-3.5 shrink-0 text-muted-foreground" />
|
||||
<code className="text-[11px] text-muted-foreground">{step.highlight}</code>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Step dots */}
|
||||
<div className="flex items-center justify-center gap-1.5 pb-2">
|
||||
{STEPS.map((_, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setOnboardingStep(i)}
|
||||
className={cn(
|
||||
'h-1.5 rounded-full transition-all',
|
||||
i === onboardingStep ? 'w-6 bg-foreground' : i < onboardingStep ? 'w-1.5 bg-foreground/50' : 'w-1.5 bg-muted-foreground/30'
|
||||
)}
|
||||
aria-label={`Schritt ${i + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div className="flex items-center justify-between border-t border-border px-6 py-3">
|
||||
<Button variant="ghost" size="sm" onClick={prev} disabled={onboardingStep === 0} className="gap-1">
|
||||
<ChevronLeft className="size-4" />Zurück
|
||||
</Button>
|
||||
<div className="flex gap-2">
|
||||
<Button variant="ghost" size="sm" onClick={skip}>
|
||||
Überspringen
|
||||
</Button>
|
||||
<Button size="sm" onClick={next} className="gap-1.5">
|
||||
{isLast ? (
|
||||
<>
|
||||
Los geht's<Check className="size-4" />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Weiter<ChevronRight className="size-4" />
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user