Compare commits

7 Commits

Author SHA1 Message Date
DanielS
c386fa03d4 style(shop): resolve merge conflict in license lookup placeholder
Some checks failed
Staging Build / build (push) Failing after 43s
2026-07-22 15:10:56 +02:00
DanielS
086a893e19 docs(dashboard): clarify calendar popup info for workshops and partners
All checks were successful
Staging Build / build (push) Successful in 2m50s
Update calendar modal description to specify workshops (online/onsite),
trainings, and Blue Wednesday partner registrations.
2026-07-22 12:54:26 +02:00
DanielS
61adf76da5 feat(dashboard): align quick access buttons in 3 columns with calendar popup
All checks were successful
Staging Build / build (push) Successful in 2m59s
Convert quick access grid to 3 columns and open in-app dialog modal for calendar button.
2026-07-22 12:45:15 +02:00
DanielS
2497063e82 fix(dashboard): import Calendar icon in HomeClient
All checks were successful
Staging Build / build (push) Successful in 2m59s
Add missing Calendar import from lucide-react.
2026-07-22 12:39:53 +02:00
DanielS
0a60526800 feat(dashboard): mark calendar button as planned in quick access
Some checks failed
Staging Build / build (push) Failing after 31s
Add planned status badge to appointment calendar quick access button.
2026-07-22 12:33:04 +02:00
DanielS
fef1ccd0f5 style(wizard): rename CAS references to CASPOS
All checks were successful
Staging Build / build (push) Successful in 2m49s
Replace all occurrences of 'CAS-Lizenz' and related strings
with 'CASPOS' across license-lookup-panel, step-billing,
and order-wizard. Update mock key to 995502-00 (GASTRO edition).
2026-07-22 11:07:30 +02:00
DanielS
3200784c51 style(wizard): remove aligned spacing in license-lookup-panel
All checks were successful
Staging Build / build (push) Successful in 2m57s
Update mock license keys to CASPOS format and normalize
object property alignment to standard single-space style.
2026-07-22 09:13:31 +02:00
4 changed files with 150 additions and 23 deletions

View File

@@ -18,9 +18,18 @@ import {
Zap,
ArrowUpRight,
ShieldCheck,
Calendar,
Sparkles,
Activity
} from 'lucide-react'
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from '@/components/ui/dialog'
interface HomeClientProps {
initialUser: User | null
@@ -29,6 +38,7 @@ interface HomeClientProps {
export function HomeClient({ initialUser }: HomeClientProps) {
const [user, setUser] = useState<User | null>(initialUser)
const [mounted, setMounted] = useState(false)
const [calendarOpen, setCalendarOpen] = useState(false)
useEffect(() => {
setMounted(true)
@@ -125,23 +135,23 @@ export function HomeClient({ initialUser }: HomeClientProps) {
Mein Dashboard Schnellzugriff
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Link href="/my-customers" className="group">
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200"
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-4">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors">
<Users className="w-5.5 h-5.5" />
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<Users className="w-5 h-5" />
</div>
<div className="text-left">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Kundenliste</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Kunden & Lizenzen verwalten</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Verwalten</span>
</div>
</div>
<ArrowUpRight className="w-4.5 h-4.5 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all" />
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</Link>
@@ -149,20 +159,42 @@ export function HomeClient({ initialUser }: HomeClientProps) {
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200"
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-4">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors">
<ClipboardList className="w-5.5 h-5.5" />
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<ClipboardList className="w-5 h-5" />
</div>
<div className="text-left">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Bestellungen</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Aufträge & Status einsehen</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Status einsehen</span>
</div>
</div>
<ArrowUpRight className="w-4.5 h-4.5 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all" />
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</Link>
<button type="button" onClick={() => setCalendarOpen(true)} className="group text-left w-full">
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<Calendar className="w-5 h-5" />
</div>
<div className="text-left">
<div className="flex items-center gap-1.5">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Termine</span>
<span className="px-1.5 py-0.5 text-[10px] font-medium bg-amber-500/10 text-amber-400 border border-amber-500/20 rounded-md">Geplant</span>
</div>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Terminkalender</span>
</div>
</div>
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</button>
</div>
</div>
</motion.div>
@@ -171,6 +203,52 @@ export function HomeClient({ initialUser }: HomeClientProps) {
</motion.div>
</section>
{/* Dialog / Popup für Termin-Kalender (Geplant) */}
<Dialog open={calendarOpen} onOpenChange={setCalendarOpen}>
<DialogContent className="bg-slate-900 border-slate-800 text-slate-100 max-w-md">
<DialogHeader>
<div className="flex items-center gap-3 mb-2">
<div className="p-2.5 rounded-xl bg-blue-500/10 text-blue-400 border border-blue-500/20">
<Calendar className="w-6 h-6" />
</div>
<div>
<DialogTitle className="text-xl font-bold text-white flex items-center gap-2">
Termin-Kalender
<span className="px-2 py-0.5 text-xs font-semibold bg-amber-500/10 text-amber-400 border border-amber-500/20 rounded-full">
In Planung
</span>
</DialogTitle>
</div>
</div>
<DialogDescription className="text-slate-400 text-sm leading-relaxed pt-2">
Der Termin-Kalender bietet in Kürze eine Übersicht für anstehende Schulungen, Online- & Vor-Ort-Workshops sowie Termine für Blauer-Mittwoch-Partner zur direkten Anmeldung.
</DialogDescription>
</DialogHeader>
<div className="p-4 my-2 rounded-xl bg-slate-950 border border-slate-800 text-xs text-slate-400 space-y-2">
<div className="flex items-center justify-between text-slate-300 font-medium">
<span>Geplante Features & Angebote:</span>
</div>
<ul className="list-disc list-inside space-y-1 text-slate-400">
<li>Anmeldung zu Online- & Vor-Ort-Workshops</li>
<li>Anstehende Schulungstermine auf einen Blick</li>
<li>Spezielle Schulungen für Blauer-Mittwoch-Partner</li>
<li>Kalender-Export (.ics / Google / Outlook)</li>
</ul>
</div>
<DialogFooter>
<Button
variant="outline"
onClick={() => setCalendarOpen(false)}
className="w-full sm:w-auto border-slate-700 bg-slate-800 text-slate-200 hover:bg-slate-700 hover:text-white"
>
Schließen
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
{/* Grid of modules */}
<section className="w-full py-16 md:py-24 border-t border-slate-900 bg-slate-950/50 relative">
<div className="container max-w-6xl mx-auto px-4 relative">

View File

@@ -179,7 +179,7 @@ export function OrderWizard({
return 'one_time'
})
// Falls "one_time" (Kauf) gewählt: optionales Datum der letzten CAS-Lizenzierung
// Falls "one_time" (Kauf) gewählt: optionales Datum der letzten CASPOS-Lizenzierung
const [lastLicenseDate, setLastLicenseDate] = useState<string>(
initialOrder?.order_data?.last_license_date || ''
)
@@ -608,7 +608,7 @@ export function OrderWizard({
setEditingIdx(null)
setModuleQuantities({})
setDeviceName('')
const resetSels: Record<string, CategorySelection> = {}
categories.forEach(cat => {
const isVisible = selectedBillingInterval === 'one_time' ? cat.show_in_kauf !== false : cat.show_in_abo !== false

View File

@@ -25,12 +25,21 @@ import { lookupLicenseFromLicServer } from '@/lib/actions/licserver-config'
// ─── MOCK DATA (until real LicServer API is wired up) ───────────────────────
const MOCK_LICENSES: Record<string, LicenseInfo> = {
<<<<<<< HEAD
'995500-0005': {
licenseKey: '995500-0005',
status: 'active',
product: 'CASPOS DEMO',
edition: 'Professional',
version: '14.1.2',
=======
'995502-00': {
licenseKey: '995502-00',
status: 'active',
product: 'CASPOS',
edition: 'GASTRO',
version: '4.8.6',
>>>>>>> 086a893e19593863f6b2044374187220cc3e392d
seats: 10,
customer: 'Mustermann GmbH',
contact: 'Max Mustermann',
@@ -39,6 +48,7 @@ const MOCK_LICENSES: Record<string, LicenseInfo> = {
maintenanceUntil: '2025-03-31',
modules: ['CRM', 'ERP-Link', 'Mobile Client', 'Web Client'],
},
<<<<<<< HEAD
'CAS-2020-STD-00456': {
licenseKey: 'CAS-2020-STD-00456',
status: 'expired',
@@ -66,6 +76,35 @@ const MOCK_LICENSES: Record<string, LicenseInfo> = {
expiresAt: '2026-12-31',
maintenanceUntil: '2026-12-31',
modules: ['CRM', 'ERP-Link', 'Mobile Client', 'Web Client', 'AI Assistant', 'Analytics Pro'],
=======
'995501-00': {
licenseKey: '995501-00',
status: 'expired',
product: 'CASPOS Handel',
edition: 'Standard',
version: '3.12.1',
seats: 1,
customer: 'Beispiel AG',
contact: 'Erika Muster',
issuedAt: '2016-03-14',
expiresAt: '2017-03-14',
maintenanceUntil: '2017-03-14',
modules: ['CASPOS Handel'],
},
'995500-00': {
licenseKey: '995500-00',
status: 'active',
product: 'CASPOS Handel',
edition: 'Standard',
version: '4.11.2',
seats: 2,
customer: 'Tech Solutions GmbH & Co. KG',
contact: 'Julia Schneider',
issuedAt: '2026-01-01',
expiresAt: '2027-12-31',
maintenanceUntil: '2027-12-31',
modules: ['CASPOS Handel'],
>>>>>>> 086a893e19593863f6b2044374187220cc3e392d
},
}
@@ -224,7 +263,7 @@ export function LicenseLookupPanel({ onLicenseResolved }: LicenseLookupPanelProp
{/* ── Input + Search Button ──────────────────────────────── */}
<div className="pt-4">
<p className="text-xs text-slate-400 mb-2 leading-relaxed">
Geben Sie Ihre bisherige CAS-Lizenznummer ein,
Geben Sie Ihre bisherige CASPOS-Lizenznummer ein,
um Lizenzinformationen automatisch abzurufen.
</p>
@@ -278,16 +317,28 @@ export function LicenseLookupPanel({ onLicenseResolved }: LicenseLookupPanelProp
Demo:&nbsp;
<span
className="font-mono text-violet-400/80 cursor-pointer hover:text-violet-400 transition-colors"
<<<<<<< HEAD
onClick={() => setLicenseKey('995500-00')}
>
995500-00
=======
onClick={() => setLicenseKey('995502-00')}
>
995502-00
>>>>>>> 086a893e19593863f6b2044374187220cc3e392d
</span>
{' · '}
<span
className="font-mono text-amber-400/80 cursor-pointer hover:text-amber-400 transition-colors"
<<<<<<< HEAD
onClick={() => setLicenseKey('995500-01')}
>
995500-01
=======
onClick={() => setLicenseKey('995501-00')}
>
995500-00
>>>>>>> 086a893e19593863f6b2044374187220cc3e392d
</span>
</p>
</div>

View File

@@ -44,11 +44,10 @@ export function StepBilling({
{/* Option 1: Kauf */}
<div
onClick={() => handleBillingIntervalChange('one_time')}
className={`relative p-6 rounded-2xl border-2 cursor-pointer transition-all duration-300 flex flex-col justify-between h-48 hover:shadow-[0_0_20px_rgba(255,255,255,0.05)] ${
selectedBillingInterval === 'one_time'
className={`relative p-6 rounded-2xl border-2 cursor-pointer transition-all duration-300 flex flex-col justify-between h-48 hover:shadow-[0_0_20px_rgba(255,255,255,0.05)] ${selectedBillingInterval === 'one_time'
? 'border-primary bg-primary/10 shadow-[0_0_25px_rgba(59,130,246,0.2)]'
: 'border-white/5 bg-white/5 hover:border-white/20'
}`}
}`}
>
<div>
<div className="flex items-center gap-3 mb-3">
@@ -71,11 +70,10 @@ export function StepBilling({
{/* Option 2: Abo */}
<div
onClick={() => handleBillingIntervalChange('monthly')}
className={`relative p-6 rounded-2xl border-2 cursor-pointer transition-all duration-300 flex flex-col justify-between h-48 hover:shadow-[0_0_20px_rgba(255,255,255,0.05)] ${
selectedBillingInterval === 'monthly'
className={`relative p-6 rounded-2xl border-2 cursor-pointer transition-all duration-300 flex flex-col justify-between h-48 hover:shadow-[0_0_20px_rgba(255,255,255,0.05)] ${selectedBillingInterval === 'monthly'
? 'border-primary bg-primary/10 shadow-[0_0_25px_rgba(59,130,246,0.2)]'
: 'border-white/5 bg-white/5 hover:border-white/20'
}`}
}`}
>
<div>
<div className="flex items-center gap-3 mb-3">
@@ -99,7 +97,7 @@ export function StepBilling({
<div className="p-4 rounded-xl bg-white/5 border border-white/10 space-y-3 mt-6 max-w-md animate-in fade-in slide-in-from-top-2 duration-300">
<Label htmlFor="last-license-date" className="text-white font-medium flex items-center gap-2">
<Calendar className="w-4 h-4 text-primary" />
Datum der letzten CAS-Lizenz (falls vorhanden)
Datum der letzten CASPOS-Lizenz (falls vorhanden)
</Label>
<Input
id="last-license-date"