@growflowstudio/growflowbooking-admin-ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +208 -0
- package/dist/index.d.ts +208 -0
- package/dist/index.js +1569 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1550 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/pages/TenantsPage.tsx","../src/components/tenants/TenantsTable.tsx","../src/primitives/utils.ts","../src/components/shared/StatusBadge.tsx","../src/components/shared/SkeletonRows.tsx","../src/components/tenants/TenantFormDialog.tsx","../src/components/tenants/TenantDetailDialog.tsx","../src/components/shared/DeleteConfirmDialog.tsx","../src/components/shared/FilterBar.tsx","../src/components/shared/Pagination.tsx","../src/pages/CustomersPage.tsx","../src/components/customers/CustomersTable.tsx","../src/components/customers/CustomerFormDialog.tsx","../src/pages/SubscriptionPlansPage.tsx","../src/components/subscription-plans/SubscriptionPlansTable.tsx","../src/components/subscription-plans/SubscriptionPlanFormDialog.tsx","../src/pages/BillingPlansPage.tsx","../src/pages/BillingSubscriptionsPage.tsx","../src/pages/SettingsPage.tsx","../src/nav/bookingNavItems.ts"],"sourcesContent":["// Provider\nexport { BookingAdminProvider, useBookingAdminConfig, useEnabledModules } from './provider';\nexport type {\n BookingAdminConfig,\n BookingAdminProviderProps,\n BookingModulesConfig,\n} from './provider';\n\n// Pages\nexport { TenantsPage } from './pages/TenantsPage';\nexport type { TenantsPageProps } from './pages/TenantsPage';\nexport { CustomersPage } from './pages/CustomersPage';\nexport type { CustomersPageProps } from './pages/CustomersPage';\nexport { SubscriptionPlansPage } from './pages/SubscriptionPlansPage';\nexport type { SubscriptionPlansPageProps } from './pages/SubscriptionPlansPage';\nexport { BillingPlansPage } from './pages/BillingPlansPage';\nexport type { BillingPlansPageProps } from './pages/BillingPlansPage';\nexport { BillingSubscriptionsPage } from './pages/BillingSubscriptionsPage';\nexport type { BillingSubscriptionsPageProps } from './pages/BillingSubscriptionsPage';\nexport { SettingsPage } from './pages/SettingsPage';\nexport type { SettingsPageProps } from './pages/SettingsPage';\n\n// Tenant components\nexport { TenantsTable, TenantFormDialog, TenantDetailDialog } from './components/tenants';\n\n// Customer components\nexport { CustomersTable, CustomerFormDialog } from './components/customers';\n\n// Subscription Plan components\nexport { SubscriptionPlansTable, SubscriptionPlanFormDialog } from './components/subscription-plans';\n\n// Shared components\nexport { DeleteConfirmDialog, FilterBar, StatusBadge, SkeletonRows, Pagination } from './components/shared';\n\n// Navigation\nexport { getBookingNavItems } from './nav/bookingNavItems';\nexport type { BookingNavItem } from './nav/bookingNavItems';\n","import React, { useMemo } from 'react';\nimport {\n BookingAdminClientContext,\n createBookingAdminClient,\n type Fetcher,\n} from '@growflowstudio/growflowbooking-admin-core';\n\n/**\n * Configure which booking modules are enabled for this project.\n * By default, all modules are enabled.\n */\nexport interface BookingModulesConfig {\n tenants?: boolean;\n customers?: boolean;\n subscriptionPlans?: boolean;\n billingPlans?: boolean;\n billingSubscriptions?: boolean;\n settings?: boolean;\n}\n\nconst DEFAULT_MODULES: Required<BookingModulesConfig> = {\n tenants: true,\n customers: true,\n subscriptionPlans: true,\n billingPlans: true,\n billingSubscriptions: true,\n settings: true,\n};\n\nexport interface BookingAdminConfig {\n /** Base path for booking admin API (e.g., '/api/v1') */\n basePath: string;\n /** HTTP fetcher function from the host application (handles auth) */\n fetcher: Fetcher;\n /** Locale for number/date formatting (default: 'it-IT') */\n locale?: string;\n /** Default currency (default: 'EUR') */\n currency?: string;\n /** Enable/disable booking modules. All enabled by default. */\n modules?: BookingModulesConfig;\n}\n\nconst BookingAdminConfigContext = React.createContext<BookingAdminConfig | null>(null);\n\nexport function useBookingAdminConfig(): BookingAdminConfig {\n const config = React.useContext(BookingAdminConfigContext);\n if (!config) {\n throw new Error(\n 'useBookingAdminConfig must be used within a BookingAdminProvider.'\n );\n }\n return config;\n}\n\n/** Returns the resolved modules config (with defaults applied) */\nexport function useEnabledModules(): Required<BookingModulesConfig> {\n const config = useBookingAdminConfig();\n return { ...DEFAULT_MODULES, ...config.modules };\n}\n\nexport interface BookingAdminProviderProps {\n config: BookingAdminConfig;\n children: React.ReactNode;\n}\n\nexport function BookingAdminProvider({ config, children }: BookingAdminProviderProps) {\n const client = useMemo(\n () => createBookingAdminClient({\n basePath: config.basePath,\n fetcher: config.fetcher,\n }),\n [config.basePath, config.fetcher]\n );\n\n return (\n <BookingAdminConfigContext.Provider value={config}>\n <BookingAdminClientContext.Provider value={client}>\n {children}\n </BookingAdminClientContext.Provider>\n </BookingAdminConfigContext.Provider>\n );\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { Plus, Building2 } from 'lucide-react';\nimport {\n useAdminTenants,\n useAdminTenant,\n useCreateTenant,\n useUpdateTenant,\n useDeleteTenant,\n} from '@growflowstudio/growflowbooking-admin-core';\nimport type { AdminTenant, AdminTenantCreate, AdminTenantUpdate, TenantPlan } from '@growflowstudio/growflowbooking-admin-core';\nimport { TenantsTable } from '../components/tenants/TenantsTable';\nimport { TenantFormDialog } from '../components/tenants/TenantFormDialog';\nimport { TenantDetailDialog } from '../components/tenants/TenantDetailDialog';\nimport { DeleteConfirmDialog } from '../components/shared/DeleteConfirmDialog';\nimport { FilterBar } from '../components/shared/FilterBar';\nimport { Pagination } from '../components/shared/Pagination';\n\nexport interface TenantsPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function TenantsPage({ wrapper: Wrapper, header }: TenantsPageProps) {\n const [search, setSearch] = useState('');\n const [planFilter, setPlanFilter] = useState('all');\n const [page, setPage] = useState(1);\n const pageSize = 20;\n\n const [showForm, setShowForm] = useState(false);\n const [showDelete, setShowDelete] = useState(false);\n const [showDetail, setShowDetail] = useState(false);\n const [selectedTenant, setSelectedTenant] = useState<AdminTenant | null>(null);\n\n const { data, isLoading, refetch } = useAdminTenants({\n search: search || undefined,\n plan: planFilter !== 'all' ? planFilter as TenantPlan : undefined,\n page,\n page_size: pageSize,\n });\n\n const { data: tenantDetail, isLoading: isLoadingDetail } = useAdminTenant(\n showDetail && selectedTenant ? selectedTenant.id : ''\n );\n\n const createMutation = useCreateTenant();\n const updateMutation = useUpdateTenant();\n const deleteMutation = useDeleteTenant();\n\n const tenants = data?.items || [];\n const total = data?.total || 0;\n\n const handleSubmit = (formData: AdminTenantCreate | AdminTenantUpdate) => {\n if (selectedTenant) {\n updateMutation.mutate({ id: selectedTenant.id, data: formData as AdminTenantUpdate }, {\n onSuccess: () => { toast.success('Tenant aggiornato con successo'); setShowForm(false); setSelectedTenant(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n } else {\n createMutation.mutate(formData as AdminTenantCreate, {\n onSuccess: () => { toast.success('Tenant creato con successo'); setShowForm(false); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const handleDelete = () => {\n if (selectedTenant) {\n deleteMutation.mutate(selectedTenant.id, {\n onSuccess: () => { toast.success('Tenant eliminato con successo'); setShowDelete(false); setSelectedTenant(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const content = (\n <>\n {header}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Building2 className=\"w-4 h-4\" />\n <span>{total} tenant</span>\n </div>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90\" onClick={() => { setSelectedTenant(null); setShowForm(true); }}>\n <Plus className=\"w-4 h-4 mr-2\" />Nuovo Tenant\n </button>\n </div>\n\n <FilterBar\n searchPlaceholder=\"Cerca tenant...\"\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1); }}\n statusFilter={planFilter}\n onStatusFilterChange={(v) => { setPlanFilter(v); setPage(1); }}\n statusOptions={[\n { value: 'all', label: 'Tutti i piani' },\n { value: 'free', label: 'Free' },\n { value: 'starter', label: 'Starter' },\n { value: 'professional', label: 'Professional' },\n { value: 'enterprise', label: 'Enterprise' },\n ]}\n onRefresh={() => refetch()}\n />\n\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-0\">\n <TenantsTable\n tenants={tenants}\n isLoading={isLoading}\n onEdit={(t) => { setSelectedTenant(t); setShowForm(true); }}\n onDelete={(t) => { setSelectedTenant(t); setShowDelete(true); }}\n onView={(t) => { setSelectedTenant(t); setShowDetail(true); }}\n />\n </div>\n {total > pageSize && (\n <div className=\"p-4 border-t\">\n <Pagination page={page} pageSize={pageSize} total={total} onPageChange={setPage} />\n </div>\n )}\n </div>\n </div>\n\n <TenantFormDialog\n isOpen={showForm}\n onOpenChange={setShowForm}\n tenant={selectedTenant}\n onSubmit={handleSubmit}\n isPending={createMutation.isPending || updateMutation.isPending}\n />\n\n <TenantDetailDialog\n isOpen={showDetail}\n onOpenChange={setShowDetail}\n tenant={tenantDetail}\n isLoading={isLoadingDetail}\n />\n\n <DeleteConfirmDialog\n isOpen={showDelete}\n onOpenChange={setShowDelete}\n title=\"Eliminare Tenant?\"\n description={<>Stai per eliminare il tenant <strong>{selectedTenant?.name}</strong>. Questa azione non può essere annullata e rimuoverà tutti i dati associati.</>}\n onConfirm={handleDelete}\n isDeleting={deleteMutation.isPending}\n confirmLabel=\"Elimina Tenant\"\n />\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import { Pencil, Trash2, MoreHorizontal } from 'lucide-react';\nimport type { AdminTenant } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { SkeletonRows } from '../shared/SkeletonRows';\nimport {\n tenantStatusColors,\n tenantStatusLabels,\n tenantPlanColors,\n tenantPlanLabels,\n formatDate,\n truncateId,\n} from '@growflowstudio/growflowbooking-admin-core';\n\ninterface TenantsTableProps {\n tenants: AdminTenant[];\n isLoading: boolean;\n onEdit: (tenant: AdminTenant) => void;\n onDelete: (tenant: AdminTenant) => void;\n onView: (tenant: AdminTenant) => void;\n}\n\nexport function TenantsTable({ tenants, isLoading, onEdit, onDelete, onView }: TenantsTableProps) {\n return (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Nome</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Slug</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Piano</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Stato</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Email</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Creato</th>\n <th className=\"h-12 px-4 text-right align-middle font-medium text-muted-foreground\">Azioni</th>\n </tr>\n </thead>\n <tbody>\n {isLoading ? (\n <SkeletonRows rows={5} columns={7} />\n ) : tenants.length === 0 ? (\n <tr>\n <td colSpan={7} className=\"h-24 text-center text-muted-foreground\">\n Nessun tenant trovato.\n </td>\n </tr>\n ) : (\n tenants.map((tenant) => (\n <tr key={tenant.id} className=\"border-b hover:bg-muted/50 cursor-pointer\" onClick={() => onView(tenant)}>\n <td className=\"p-4 font-medium\">{tenant.name}</td>\n <td className=\"p-4\">\n <code className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">{tenant.slug}</code>\n </td>\n <td className=\"p-4\">\n <StatusBadge label={tenantPlanLabels[tenant.plan]} colorClass={tenantPlanColors[tenant.plan]} />\n </td>\n <td className=\"p-4\">\n <StatusBadge\n label={tenant.is_active ? tenantStatusLabels.active : tenantStatusLabels.inactive}\n colorClass={tenant.is_active ? tenantStatusColors.active : tenantStatusColors.inactive}\n />\n </td>\n <td className=\"p-4 text-sm text-muted-foreground\">{tenant.owner_email}</td>\n <td className=\"p-4 text-sm text-muted-foreground\">{formatDate(tenant.created_at)}</td>\n <td className=\"p-4 text-right\">\n <div className=\"flex justify-end gap-1\" onClick={(e) => e.stopPropagation()}>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent\" onClick={() => onEdit(tenant)}>\n <Pencil className=\"w-4 h-4\" />\n </button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent text-destructive\" onClick={() => onDelete(tenant)}>\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n );\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { cn } from '../../primitives/utils';\n\ninterface StatusBadgeProps {\n label: string;\n colorClass: string;\n className?: string;\n}\n\nexport function StatusBadge({ label, colorClass, className }: StatusBadgeProps) {\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors',\n colorClass,\n className,\n )}\n >\n {label}\n </span>\n );\n}\n","interface SkeletonRowsProps {\n rows?: number;\n columns?: number;\n}\n\nexport function SkeletonRows({ rows = 5, columns = 1 }: SkeletonRowsProps) {\n return (\n <>\n {Array.from({ length: rows }).map((_, i) => (\n <tr key={i}>\n <td colSpan={columns} className=\"p-4\">\n <div className=\"h-10 w-full animate-pulse rounded-md bg-muted\" />\n </td>\n </tr>\n ))}\n </>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport type { AdminTenant, AdminTenantCreate, AdminTenantUpdate, TenantPlan } from '@growflowstudio/growflowbooking-admin-core';\nimport { validateRequired, validateSlug, validateEmail } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface TenantFormDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n tenant: AdminTenant | null;\n onSubmit: (data: AdminTenantCreate | AdminTenantUpdate) => void;\n isPending: boolean;\n}\n\nexport function TenantFormDialog({ isOpen, onOpenChange, tenant, onSubmit, isPending }: TenantFormDialogProps) {\n const isEdit = !!tenant;\n const [name, setName] = useState('');\n const [slug, setSlug] = useState('');\n const [ownerEmail, setOwnerEmail] = useState('');\n const [plan, setPlan] = useState<TenantPlan>('free');\n const [domain, setDomain] = useState('');\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n useEffect(() => {\n if (isOpen) {\n if (tenant) {\n setName(tenant.name);\n setSlug(tenant.slug);\n setOwnerEmail(tenant.owner_email);\n setPlan(tenant.plan);\n setDomain(tenant.domain || '');\n } else {\n setName('');\n setSlug('');\n setOwnerEmail('');\n setPlan('free');\n setDomain('');\n }\n setErrors({});\n }\n }, [isOpen, tenant]);\n\n const handleSubmit = () => {\n const errs: Record<string, string> = {};\n const nameErr = validateRequired(name, 'Il nome');\n if (nameErr) errs.name = nameErr;\n if (!isEdit) {\n const slugErr = validateSlug(slug);\n if (slugErr) errs.slug = slugErr;\n }\n const emailErr = validateEmail(ownerEmail);\n if (emailErr) errs.ownerEmail = emailErr;\n setErrors(errs);\n if (Object.keys(errs).length > 0) return;\n\n if (isEdit) {\n onSubmit({ name, owner_email: ownerEmail, domain: domain || undefined } as AdminTenantUpdate);\n } else {\n onSubmit({ name, slug, owner_email: ownerEmail, plan, domain: domain || undefined } as AdminTenantCreate);\n }\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"fixed inset-0 bg-black/80\" onClick={() => onOpenChange(false)} />\n <div className=\"relative z-50 w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-lg border bg-background p-6 shadow-lg\">\n <div className=\"flex flex-col space-y-1.5 pb-4\">\n <h2 className=\"text-lg font-semibold\">{isEdit ? 'Modifica Tenant' : 'Nuovo Tenant'}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {isEdit ? 'Modifica i dati del tenant selezionato' : 'Crea un nuovo tenant per la piattaforma di booking'}\n </p>\n </div>\n <div className=\"grid gap-4 py-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Nome *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={name} onChange={(e) => setName(e.target.value)} placeholder=\"Acme Salon\" />\n {errors.name && <p className=\"text-xs text-destructive\">{errors.name}</p>}\n </div>\n {!isEdit && (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Slug *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={slug} onChange={(e) => setSlug(e.target.value)} placeholder=\"acme-salon\" />\n {errors.slug && <p className=\"text-xs text-destructive\">{errors.slug}</p>}\n </div>\n )}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Email Proprietario *</label>\n <input type=\"email\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={ownerEmail} onChange={(e) => setOwnerEmail(e.target.value)} placeholder=\"owner@example.com\" />\n {errors.ownerEmail && <p className=\"text-xs text-destructive\">{errors.ownerEmail}</p>}\n </div>\n {!isEdit && (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Piano</label>\n <select className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={plan} onChange={(e) => setPlan(e.target.value as TenantPlan)}>\n <option value=\"free\">Free</option>\n <option value=\"starter\">Starter</option>\n <option value=\"professional\">Professional</option>\n <option value=\"enterprise\">Enterprise</option>\n </select>\n </div>\n )}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Dominio</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={domain} onChange={(e) => setDomain(e.target.value)} placeholder=\"salon.example.com\" />\n </div>\n </div>\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-4\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-input bg-background hover:bg-accent mt-2 sm:mt-0\" onClick={() => onOpenChange(false)}>Annulla</button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50\" onClick={handleSubmit} disabled={isPending}>\n {isPending && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n {isEdit ? 'Salva Modifiche' : 'Crea Tenant'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { X } from 'lucide-react';\nimport type { AdminTenantDetail } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { tenantPlanColors, tenantPlanLabels, tenantStatusColors, tenantStatusLabels, formatDate } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface TenantDetailDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n tenant: AdminTenantDetail | undefined;\n isLoading: boolean;\n}\n\nexport function TenantDetailDialog({ isOpen, onOpenChange, tenant, isLoading }: TenantDetailDialogProps) {\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"fixed inset-0 bg-black/80\" onClick={() => onOpenChange(false)} />\n <div className=\"relative z-50 w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border bg-background p-6 shadow-lg\">\n <div className=\"flex items-center justify-between pb-4\">\n <h2 className=\"text-lg font-semibold\">Dettaglio Tenant</h2>\n <button className=\"rounded-md h-8 w-8 inline-flex items-center justify-center hover:bg-accent\" onClick={() => onOpenChange(false)}>\n <X className=\"w-4 h-4\" />\n </button>\n </div>\n {isLoading || !tenant ? (\n <div className=\"space-y-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-6 w-full animate-pulse rounded-md bg-muted\" />\n ))}\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <span className=\"text-sm text-muted-foreground\">Nome</span>\n <p className=\"font-medium\">{tenant.name}</p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Slug</span>\n <p><code className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">{tenant.slug}</code></p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Piano</span>\n <p><StatusBadge label={tenantPlanLabels[tenant.plan]} colorClass={tenantPlanColors[tenant.plan]} /></p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Stato</span>\n <p><StatusBadge label={tenant.is_active ? tenantStatusLabels.active : tenantStatusLabels.inactive} colorClass={tenant.is_active ? tenantStatusColors.active : tenantStatusColors.inactive} /></p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Email</span>\n <p className=\"text-sm\">{tenant.owner_email}</p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Dominio</span>\n <p className=\"text-sm\">{tenant.domain || '-'}</p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Creato</span>\n <p className=\"text-sm\">{formatDate(tenant.created_at)}</p>\n </div>\n <div>\n <span className=\"text-sm text-muted-foreground\">Aggiornato</span>\n <p className=\"text-sm\">{formatDate(tenant.updated_at)}</p>\n </div>\n </div>\n <div className=\"border-t pt-4\">\n <h3 className=\"font-medium mb-3\">Statistiche</h3>\n <div className=\"grid grid-cols-3 gap-4\">\n <div className=\"rounded-lg border p-3 text-center\">\n <p className=\"text-2xl font-bold\">{tenant.services_count}</p>\n <p className=\"text-xs text-muted-foreground\">Servizi</p>\n </div>\n <div className=\"rounded-lg border p-3 text-center\">\n <p className=\"text-2xl font-bold\">{tenant.staff_count}</p>\n <p className=\"text-xs text-muted-foreground\">Staff</p>\n </div>\n <div className=\"rounded-lg border p-3 text-center\">\n <p className=\"text-2xl font-bold\">{tenant.locations_count}</p>\n <p className=\"text-xs text-muted-foreground\">Sedi</p>\n </div>\n <div className=\"rounded-lg border p-3 text-center\">\n <p className=\"text-2xl font-bold\">{tenant.customers_count}</p>\n <p className=\"text-xs text-muted-foreground\">Clienti</p>\n </div>\n <div className=\"rounded-lg border p-3 text-center\">\n <p className=\"text-2xl font-bold\">{tenant.bookings_count}</p>\n <p className=\"text-xs text-muted-foreground\">Prenotazioni</p>\n </div>\n </div>\n </div>\n <div className=\"border-t pt-4\">\n <h3 className=\"font-medium mb-3\">Limiti</h3>\n <div className=\"grid grid-cols-3 gap-4 text-sm\">\n <div>\n <span className=\"text-muted-foreground\">Max Servizi:</span> {tenant.max_services === -1 ? 'Illimitati' : tenant.max_services}\n </div>\n <div>\n <span className=\"text-muted-foreground\">Max Staff:</span> {tenant.max_staff === -1 ? 'Illimitati' : tenant.max_staff}\n </div>\n <div>\n <span className=\"text-muted-foreground\">Max Sedi:</span> {tenant.max_locations === -1 ? 'Illimitate' : tenant.max_locations}\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { Loader2 } from 'lucide-react';\n\ninterface DeleteConfirmDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n title?: string;\n description: React.ReactNode;\n onConfirm: () => void;\n isDeleting: boolean;\n confirmLabel?: string;\n cancelLabel?: string;\n}\n\nexport function DeleteConfirmDialog({\n isOpen,\n onOpenChange,\n title = 'Sei sicuro?',\n description,\n onConfirm,\n isDeleting,\n confirmLabel = 'Elimina',\n cancelLabel = 'Annulla',\n}: DeleteConfirmDialogProps) {\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n className=\"fixed inset-0 bg-black/80\"\n onClick={() => onOpenChange(false)}\n />\n <div className=\"relative z-50 w-full max-w-lg rounded-lg border bg-background p-6 shadow-lg\">\n <div className=\"flex flex-col space-y-2 text-center sm:text-left\">\n <h2 className=\"text-lg font-semibold\">{title}</h2>\n <div className=\"text-sm text-muted-foreground\">{description}</div>\n </div>\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 mt-4\">\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-input bg-background hover:bg-accent hover:text-accent-foreground mt-2 sm:mt-0\"\n onClick={() => onOpenChange(false)}\n >\n {cancelLabel}\n </button>\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-destructive text-destructive-foreground hover:bg-destructive/90\"\n onClick={onConfirm}\n disabled={isDeleting}\n >\n {isDeleting && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { Search, RefreshCw } from 'lucide-react';\n\ninterface FilterOption {\n value: string;\n label: string;\n}\n\ninterface FilterBarProps {\n searchPlaceholder?: string;\n searchValue: string;\n onSearchChange: (value: string) => void;\n statusFilter?: string;\n onStatusFilterChange?: (value: string) => void;\n statusOptions?: FilterOption[];\n onRefresh: () => void;\n}\n\nexport function FilterBar({\n searchPlaceholder = 'Cerca...',\n searchValue,\n onSearchChange,\n statusFilter,\n onStatusFilterChange,\n statusOptions,\n onRefresh,\n}: FilterBarProps) {\n return (\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-6 pt-6\">\n <div className=\"flex flex-col sm:flex-row gap-4\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\n <input\n className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 pl-9\"\n placeholder={searchPlaceholder}\n value={searchValue}\n onChange={(e) => onSearchChange(e.target.value)}\n />\n </div>\n {statusOptions && onStatusFilterChange && (\n <select\n className=\"flex h-10 w-[180px] rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n value={statusFilter || 'all'}\n onChange={(e) => onStatusFilterChange(e.target.value)}\n >\n {statusOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n )}\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-input bg-background hover:bg-accent hover:text-accent-foreground\"\n onClick={onRefresh}\n >\n <RefreshCw className=\"w-4 h-4 mr-2\" />\n Aggiorna\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { ChevronLeft, ChevronRight } from 'lucide-react';\n\ninterface PaginationProps {\n page: number;\n pageSize: number;\n total: number;\n onPageChange: (page: number) => void;\n}\n\nexport function Pagination({ page, pageSize, total, onPageChange }: PaginationProps) {\n const totalPages = Math.ceil(total / pageSize);\n\n return (\n <div className=\"flex justify-between items-center\">\n <span className=\"text-sm text-muted-foreground\">\n {total > 0 ? `${(page - 1) * pageSize + 1}-${Math.min(page * pageSize, total)} di ${total}` : 'Nessun risultato'}\n </span>\n <div className=\"flex gap-2\">\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 border border-input bg-background hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:pointer-events-none\"\n onClick={() => onPageChange(page - 1)}\n disabled={page <= 1}\n >\n <ChevronLeft className=\"w-4 h-4 mr-1\" />\n Precedente\n </button>\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 border border-input bg-background hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:pointer-events-none\"\n onClick={() => onPageChange(page + 1)}\n disabled={page >= totalPages}\n >\n Successiva\n <ChevronRight className=\"w-4 h-4 ml-1\" />\n </button>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { Plus, Users } from 'lucide-react';\nimport {\n useAdminCustomers,\n useCreateCustomer,\n useUpdateCustomer,\n useDeleteCustomer,\n} from '@growflowstudio/growflowbooking-admin-core';\nimport type { CustomerWithTenant, AdminCustomerCreate, AdminCustomerUpdate } from '@growflowstudio/growflowbooking-admin-core';\nimport { CustomersTable } from '../components/customers/CustomersTable';\nimport { CustomerFormDialog } from '../components/customers/CustomerFormDialog';\nimport { DeleteConfirmDialog } from '../components/shared/DeleteConfirmDialog';\nimport { FilterBar } from '../components/shared/FilterBar';\nimport { Pagination } from '../components/shared/Pagination';\n\nexport interface CustomersPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function CustomersPage({ wrapper: Wrapper, header }: CustomersPageProps) {\n const [search, setSearch] = useState('');\n const [page, setPage] = useState(1);\n const pageSize = 20;\n\n const [showForm, setShowForm] = useState(false);\n const [showDelete, setShowDelete] = useState(false);\n const [selectedCustomer, setSelectedCustomer] = useState<CustomerWithTenant | null>(null);\n\n const { data, isLoading, refetch } = useAdminCustomers({\n search: search || undefined,\n page,\n page_size: pageSize,\n });\n\n const createMutation = useCreateCustomer();\n const updateMutation = useUpdateCustomer();\n const deleteMutation = useDeleteCustomer();\n\n const customers = data?.items || [];\n const total = data?.total || 0;\n\n const handleSubmit = (formData: AdminCustomerCreate | AdminCustomerUpdate) => {\n if (selectedCustomer) {\n updateMutation.mutate({ id: selectedCustomer.id, data: formData as AdminCustomerUpdate }, {\n onSuccess: () => { toast.success('Cliente aggiornato con successo'); setShowForm(false); setSelectedCustomer(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n } else {\n createMutation.mutate(formData as AdminCustomerCreate, {\n onSuccess: () => { toast.success('Cliente creato con successo'); setShowForm(false); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const handleDelete = () => {\n if (selectedCustomer) {\n deleteMutation.mutate(selectedCustomer.id, {\n onSuccess: () => { toast.success('Cliente eliminato con successo'); setShowDelete(false); setSelectedCustomer(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const content = (\n <>\n {header}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Users className=\"w-4 h-4\" />\n <span>{total} clienti</span>\n </div>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90\" onClick={() => { setSelectedCustomer(null); setShowForm(true); }}>\n <Plus className=\"w-4 h-4 mr-2\" />Nuovo Cliente\n </button>\n </div>\n\n <FilterBar\n searchPlaceholder=\"Cerca clienti...\"\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1); }}\n onRefresh={() => refetch()}\n />\n\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-0\">\n <CustomersTable\n customers={customers}\n isLoading={isLoading}\n onEdit={(c) => { setSelectedCustomer(c); setShowForm(true); }}\n onDelete={(c) => { setSelectedCustomer(c); setShowDelete(true); }}\n />\n </div>\n {total > pageSize && (\n <div className=\"p-4 border-t\">\n <Pagination page={page} pageSize={pageSize} total={total} onPageChange={setPage} />\n </div>\n )}\n </div>\n </div>\n\n <CustomerFormDialog\n isOpen={showForm}\n onOpenChange={setShowForm}\n customer={selectedCustomer}\n onSubmit={handleSubmit}\n isPending={createMutation.isPending || updateMutation.isPending}\n />\n\n <DeleteConfirmDialog\n isOpen={showDelete}\n onOpenChange={setShowDelete}\n title=\"Eliminare Cliente?\"\n description={<>Stai per eliminare il cliente <strong>{selectedCustomer?.first_name} {selectedCustomer?.last_name}</strong>. Questa azione non può essere annullata.</>}\n onConfirm={handleDelete}\n isDeleting={deleteMutation.isPending}\n confirmLabel=\"Elimina Cliente\"\n />\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import { Pencil, Trash2 } from 'lucide-react';\nimport type { CustomerWithTenant } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { SkeletonRows } from '../shared/SkeletonRows';\nimport { formatDate } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface CustomersTableProps {\n customers: CustomerWithTenant[];\n isLoading: boolean;\n onEdit: (customer: CustomerWithTenant) => void;\n onDelete: (customer: CustomerWithTenant) => void;\n}\n\nexport function CustomersTable({ customers, isLoading, onEdit, onDelete }: CustomersTableProps) {\n return (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Nome</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Email</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Tenant</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Stato</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Creato</th>\n <th className=\"h-12 px-4 text-right align-middle font-medium text-muted-foreground\">Azioni</th>\n </tr>\n </thead>\n <tbody>\n {isLoading ? (\n <SkeletonRows rows={5} columns={6} />\n ) : customers.length === 0 ? (\n <tr>\n <td colSpan={6} className=\"h-24 text-center text-muted-foreground\">\n Nessun cliente trovato.\n </td>\n </tr>\n ) : (\n customers.map((customer) => (\n <tr key={customer.id} className=\"border-b hover:bg-muted/50\">\n <td className=\"p-4 font-medium\">{customer.first_name} {customer.last_name}</td>\n <td className=\"p-4 text-sm\">{customer.email}</td>\n <td className=\"p-4 text-sm text-muted-foreground\">{customer.tenant_name}</td>\n <td className=\"p-4\">\n <StatusBadge\n label={customer.is_active ? 'Attivo' : 'Inattivo'}\n colorClass={customer.is_active ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' : 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400'}\n />\n </td>\n <td className=\"p-4 text-sm text-muted-foreground\">{formatDate(customer.created_at)}</td>\n <td className=\"p-4 text-right\">\n <div className=\"flex justify-end gap-1\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent\" onClick={() => onEdit(customer)}>\n <Pencil className=\"w-4 h-4\" />\n </button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent text-destructive\" onClick={() => onDelete(customer)}>\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport type { CustomerWithTenant, AdminCustomerCreate, AdminCustomerUpdate } from '@growflowstudio/growflowbooking-admin-core';\nimport { validateRequired, validateEmail } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface CustomerFormDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n customer: CustomerWithTenant | null;\n onSubmit: (data: AdminCustomerCreate | AdminCustomerUpdate) => void;\n isPending: boolean;\n tenantId?: string;\n}\n\nexport function CustomerFormDialog({ isOpen, onOpenChange, customer, onSubmit, isPending, tenantId }: CustomerFormDialogProps) {\n const isEdit = !!customer;\n const [firstName, setFirstName] = useState('');\n const [lastName, setLastName] = useState('');\n const [email, setEmail] = useState('');\n const [phone, setPhone] = useState('');\n const [notes, setNotes] = useState('');\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n useEffect(() => {\n if (isOpen) {\n if (customer) {\n setFirstName(customer.first_name);\n setLastName(customer.last_name);\n setEmail(customer.email);\n setPhone(customer.phone || '');\n setNotes(customer.notes || '');\n } else {\n setFirstName('');\n setLastName('');\n setEmail('');\n setPhone('');\n setNotes('');\n }\n setErrors({});\n }\n }, [isOpen, customer]);\n\n const handleSubmit = () => {\n const errs: Record<string, string> = {};\n const fnErr = validateRequired(firstName, 'Il nome');\n if (fnErr) errs.firstName = fnErr;\n const lnErr = validateRequired(lastName, 'Il cognome');\n if (lnErr) errs.lastName = lnErr;\n const emailErr = validateEmail(email);\n if (emailErr) errs.email = emailErr;\n setErrors(errs);\n if (Object.keys(errs).length > 0) return;\n\n if (isEdit) {\n onSubmit({ first_name: firstName, last_name: lastName, email, phone: phone || undefined, notes: notes || undefined } as AdminCustomerUpdate);\n } else {\n onSubmit({ tenant_id: tenantId || '', first_name: firstName, last_name: lastName, email, phone: phone || undefined, notes: notes || undefined } as AdminCustomerCreate);\n }\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"fixed inset-0 bg-black/80\" onClick={() => onOpenChange(false)} />\n <div className=\"relative z-50 w-full max-w-lg max-h-[90vh] overflow-y-auto rounded-lg border bg-background p-6 shadow-lg\">\n <div className=\"flex flex-col space-y-1.5 pb-4\">\n <h2 className=\"text-lg font-semibold\">{isEdit ? 'Modifica Cliente' : 'Nuovo Cliente'}</h2>\n </div>\n <div className=\"grid gap-4 py-4\">\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Nome *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={firstName} onChange={(e) => setFirstName(e.target.value)} placeholder=\"Mario\" />\n {errors.firstName && <p className=\"text-xs text-destructive\">{errors.firstName}</p>}\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Cognome *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={lastName} onChange={(e) => setLastName(e.target.value)} placeholder=\"Rossi\" />\n {errors.lastName && <p className=\"text-xs text-destructive\">{errors.lastName}</p>}\n </div>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Email *</label>\n <input type=\"email\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={email} onChange={(e) => setEmail(e.target.value)} placeholder=\"mario@example.com\" />\n {errors.email && <p className=\"text-xs text-destructive\">{errors.email}</p>}\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Telefono</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder=\"+39 123 456 7890\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Note</label>\n <textarea className=\"flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={notes} onChange={(e) => setNotes(e.target.value)} rows={2} />\n </div>\n </div>\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-4\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-input bg-background hover:bg-accent mt-2 sm:mt-0\" onClick={() => onOpenChange(false)}>Annulla</button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50\" onClick={handleSubmit} disabled={isPending}>\n {isPending && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n {isEdit ? 'Salva Modifiche' : 'Crea Cliente'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { Plus, LayoutGrid } from 'lucide-react';\nimport {\n useSubscriptionPlans,\n useCreateSubscriptionPlan,\n useUpdateSubscriptionPlan,\n useDeleteSubscriptionPlan,\n} from '@growflowstudio/growflowbooking-admin-core';\nimport type { SubscriptionPlan, SubscriptionPlanCreate, SubscriptionPlanUpdate } from '@growflowstudio/growflowbooking-admin-core';\nimport { SubscriptionPlansTable } from '../components/subscription-plans/SubscriptionPlansTable';\nimport { SubscriptionPlanFormDialog } from '../components/subscription-plans/SubscriptionPlanFormDialog';\nimport { DeleteConfirmDialog } from '../components/shared/DeleteConfirmDialog';\n\nexport interface SubscriptionPlansPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function SubscriptionPlansPage({ wrapper: Wrapper, header }: SubscriptionPlansPageProps) {\n const [showForm, setShowForm] = useState(false);\n const [showDelete, setShowDelete] = useState(false);\n const [selectedPlan, setSelectedPlan] = useState<SubscriptionPlan | null>(null);\n\n const { data, isLoading, refetch } = useSubscriptionPlans(true);\n const createMutation = useCreateSubscriptionPlan();\n const updateMutation = useUpdateSubscriptionPlan();\n const deleteMutation = useDeleteSubscriptionPlan();\n\n const plans = data?.items || [];\n\n const handleSubmit = (formData: SubscriptionPlanCreate | SubscriptionPlanUpdate) => {\n if (selectedPlan) {\n updateMutation.mutate({ id: selectedPlan.id, data: formData as SubscriptionPlanUpdate }, {\n onSuccess: () => { toast.success('Piano aggiornato con successo'); setShowForm(false); setSelectedPlan(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n } else {\n createMutation.mutate(formData as SubscriptionPlanCreate, {\n onSuccess: () => { toast.success('Piano creato con successo'); setShowForm(false); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const handleDelete = () => {\n if (selectedPlan) {\n deleteMutation.mutate(selectedPlan.id, {\n onSuccess: () => { toast.success('Piano eliminato con successo'); setShowDelete(false); setSelectedPlan(null); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n }\n };\n\n const content = (\n <>\n {header}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <LayoutGrid className=\"w-4 h-4\" />\n <span>{plans.length} piani configurati</span>\n </div>\n <div className=\"flex gap-2\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 border border-input bg-background hover:bg-accent\" onClick={() => refetch()}>\n Aggiorna\n </button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90\" onClick={() => { setSelectedPlan(null); setShowForm(true); }}>\n <Plus className=\"w-4 h-4 mr-2\" />Nuovo Piano\n </button>\n </div>\n </div>\n\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-0\">\n <SubscriptionPlansTable\n plans={plans}\n isLoading={isLoading}\n onEdit={(p) => { setSelectedPlan(p); setShowForm(true); }}\n onDelete={(p) => { setSelectedPlan(p); setShowDelete(true); }}\n />\n </div>\n </div>\n </div>\n\n <SubscriptionPlanFormDialog\n isOpen={showForm}\n onOpenChange={setShowForm}\n plan={selectedPlan}\n onSubmit={handleSubmit}\n isPending={createMutation.isPending || updateMutation.isPending}\n />\n\n <DeleteConfirmDialog\n isOpen={showDelete}\n onOpenChange={setShowDelete}\n title=\"Eliminare Piano?\"\n description={<>Stai per eliminare il piano <strong>{selectedPlan?.name}</strong> (<code>{selectedPlan?.slug}</code>). Questa azione non può essere annullata.</>}\n onConfirm={handleDelete}\n isDeleting={deleteMutation.isPending}\n confirmLabel=\"Elimina Piano\"\n />\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import { Pencil, Trash2 } from 'lucide-react';\nimport type { SubscriptionPlan } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../shared/StatusBadge';\nimport { SkeletonRows } from '../shared/SkeletonRows';\nimport { formatPrice } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface SubscriptionPlansTableProps {\n plans: SubscriptionPlan[];\n isLoading: boolean;\n onEdit: (plan: SubscriptionPlan) => void;\n onDelete: (plan: SubscriptionPlan) => void;\n}\n\nexport function SubscriptionPlansTable({ plans, isLoading, onEdit, onDelete }: SubscriptionPlansTableProps) {\n return (\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Nome</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Slug</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Prezzo Mensile</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Prezzo Annuale</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Stato</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Trial</th>\n <th className=\"h-12 px-4 text-right align-middle font-medium text-muted-foreground\">Azioni</th>\n </tr>\n </thead>\n <tbody>\n {isLoading ? (\n <SkeletonRows rows={5} columns={7} />\n ) : plans.length === 0 ? (\n <tr>\n <td colSpan={7} className=\"h-24 text-center text-muted-foreground\">\n Nessun piano trovato.\n </td>\n </tr>\n ) : (\n plans.map((plan) => (\n <tr key={plan.id} className=\"border-b hover:bg-muted/50\">\n <td className=\"p-4 font-medium\">{plan.name}</td>\n <td className=\"p-4\">\n <code className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">{plan.slug}</code>\n </td>\n <td className=\"p-4 text-sm\">{formatPrice(plan.price_monthly, plan.currency)}</td>\n <td className=\"p-4 text-sm\">{formatPrice(plan.price_yearly, plan.currency)}</td>\n <td className=\"p-4\">\n <StatusBadge\n label={plan.is_active ? 'Attivo' : 'Inattivo'}\n colorClass={plan.is_active ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' : 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400'}\n />\n </td>\n <td className=\"p-4 text-sm text-muted-foreground\">{plan.trial_days} giorni</td>\n <td className=\"p-4 text-right\">\n <div className=\"flex justify-end gap-1\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent\" onClick={() => onEdit(plan)}>\n <Pencil className=\"w-4 h-4\" />\n </button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm h-8 w-8 hover:bg-accent text-destructive\" onClick={() => onDelete(plan)}>\n <Trash2 className=\"w-4 h-4\" />\n </button>\n </div>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n );\n}\n","import { useState, useEffect } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport type { SubscriptionPlan, SubscriptionPlanCreate, SubscriptionPlanUpdate, PlanPricingModel } from '@growflowstudio/growflowbooking-admin-core';\nimport { validateRequired, validateSlug } from '@growflowstudio/growflowbooking-admin-core';\n\ninterface SubscriptionPlanFormDialogProps {\n isOpen: boolean;\n onOpenChange: (open: boolean) => void;\n plan: SubscriptionPlan | null;\n onSubmit: (data: SubscriptionPlanCreate | SubscriptionPlanUpdate) => void;\n isPending: boolean;\n}\n\nexport function SubscriptionPlanFormDialog({ isOpen, onOpenChange, plan, onSubmit, isPending }: SubscriptionPlanFormDialogProps) {\n const isEdit = !!plan;\n const [slug, setSlug] = useState('');\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [pricingModel, setPricingModel] = useState<PlanPricingModel>('flat');\n const [priceMonthly, setPriceMonthly] = useState('');\n const [priceYearly, setPriceYearly] = useState('');\n const [currency, setCurrency] = useState('eur');\n const [trialDays, setTrialDays] = useState(14);\n const [isActive, setIsActive] = useState(true);\n const [errors, setErrors] = useState<Record<string, string>>({});\n\n useEffect(() => {\n if (isOpen) {\n if (plan) {\n setSlug(plan.slug);\n setName(plan.name);\n setDescription(plan.description || '');\n setPricingModel(plan.pricing_model);\n setPriceMonthly(plan.price_monthly?.toString() || '');\n setPriceYearly(plan.price_yearly?.toString() || '');\n setCurrency(plan.currency);\n setTrialDays(plan.trial_days);\n setIsActive(plan.is_active);\n } else {\n setSlug('');\n setName('');\n setDescription('');\n setPricingModel('flat');\n setPriceMonthly('');\n setPriceYearly('');\n setCurrency('eur');\n setTrialDays(14);\n setIsActive(true);\n }\n setErrors({});\n }\n }, [isOpen, plan]);\n\n const handleSubmit = () => {\n const errs: Record<string, string> = {};\n if (!isEdit) {\n const slugErr = validateSlug(slug);\n if (slugErr) errs.slug = slugErr;\n }\n const nameErr = validateRequired(name, 'Il nome');\n if (nameErr) errs.name = nameErr;\n setErrors(errs);\n if (Object.keys(errs).length > 0) return;\n\n const data = {\n ...(isEdit ? {} : { slug }),\n name,\n description: description || undefined,\n pricing_model: pricingModel,\n price_monthly: priceMonthly ? parseFloat(priceMonthly) : undefined,\n price_yearly: priceYearly ? parseFloat(priceYearly) : undefined,\n currency,\n trial_days: trialDays,\n is_active: isActive,\n };\n onSubmit(data);\n };\n\n if (!isOpen) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"fixed inset-0 bg-black/80\" onClick={() => onOpenChange(false)} />\n <div className=\"relative z-50 w-full max-w-xl max-h-[90vh] overflow-y-auto rounded-lg border bg-background p-6 shadow-lg\">\n <div className=\"flex flex-col space-y-1.5 pb-4\">\n <h2 className=\"text-lg font-semibold\">{isEdit ? 'Modifica Piano' : 'Nuovo Piano'}</h2>\n </div>\n <div className=\"grid gap-4 py-4\">\n {!isEdit && (\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Slug *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={slug} onChange={(e) => setSlug(e.target.value)} placeholder=\"pro-monthly\" />\n {errors.slug && <p className=\"text-xs text-destructive\">{errors.slug}</p>}\n </div>\n )}\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Nome *</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={name} onChange={(e) => setName(e.target.value)} placeholder=\"Professional\" />\n {errors.name && <p className=\"text-xs text-destructive\">{errors.name}</p>}\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Descrizione</label>\n <textarea className=\"flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={description} onChange={(e) => setDescription(e.target.value)} rows={2} />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Prezzo Mensile</label>\n <input type=\"number\" step=\"0.01\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={priceMonthly} onChange={(e) => setPriceMonthly(e.target.value)} placeholder=\"29.00\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Prezzo Annuale</label>\n <input type=\"number\" step=\"0.01\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={priceYearly} onChange={(e) => setPriceYearly(e.target.value)} placeholder=\"290.00\" />\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Valuta</label>\n <select className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={currency} onChange={(e) => setCurrency(e.target.value)}>\n <option value=\"eur\">EUR</option>\n <option value=\"usd\">USD</option>\n <option value=\"gbp\">GBP</option>\n </select>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium leading-none\">Giorni Prova</label>\n <input type=\"number\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={trialDays} onChange={(e) => setTrialDays(parseInt(e.target.value) || 0)} />\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n <button type=\"button\" role=\"switch\" aria-checked={isActive} onClick={() => setIsActive(!isActive)}\n className={`inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors ${isActive ? 'bg-primary' : 'bg-input'}`}>\n <span className={`pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg transition-transform ${isActive ? 'translate-x-4' : 'translate-x-0'}`} />\n </button>\n <span className=\"text-sm font-medium leading-none\">Piano Attivo</span>\n </div>\n </div>\n <div className=\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2 pt-4\">\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 border border-input bg-background hover:bg-accent mt-2 sm:mt-0\" onClick={() => onOpenChange(false)}>Annulla</button>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50\" onClick={handleSubmit} disabled={isPending}>\n {isPending && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n {isEdit ? 'Salva Modifiche' : 'Crea Piano'}\n </button>\n </div>\n </div>\n </div>\n );\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { CreditCard, RefreshCw, CloudUpload } from 'lucide-react';\nimport {\n useBillingPlans,\n useSyncBillingPlanToStripe,\n formatPrice,\n billingSubscriptionStatusColors,\n} from '@growflowstudio/growflowbooking-admin-core';\nimport type { BillingPlan } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../components/shared/StatusBadge';\nimport { SkeletonRows } from '../components/shared/SkeletonRows';\n\nexport interface BillingPlansPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function BillingPlansPage({ wrapper: Wrapper, header }: BillingPlansPageProps) {\n const { data, isLoading, refetch } = useBillingPlans();\n const syncMutation = useSyncBillingPlanToStripe();\n const plans = data?.items || [];\n\n const content = (\n <>\n {header}\n <div className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <CreditCard className=\"w-4 h-4\" />\n <span>{plans.length} piani billing (GrowFlow)</span>\n </div>\n <button className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 border border-input bg-background hover:bg-accent\" onClick={() => refetch()}>\n <RefreshCw className=\"w-4 h-4 mr-2\" />Aggiorna\n </button>\n </div>\n\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-0\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Nome</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Slug</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Mensile</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Annuale</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Stato</th>\n <th className=\"h-12 px-4 text-right align-middle font-medium text-muted-foreground\">Azioni</th>\n </tr>\n </thead>\n <tbody>\n {isLoading ? (\n <SkeletonRows rows={5} columns={6} />\n ) : plans.length === 0 ? (\n <tr>\n <td colSpan={6} className=\"h-24 text-center text-muted-foreground\">\n Nessun piano billing configurato.\n </td>\n </tr>\n ) : (\n plans.map((plan) => (\n <tr key={plan.id} className=\"border-b hover:bg-muted/50\">\n <td className=\"p-4 font-medium\">{plan.name}</td>\n <td className=\"p-4\"><code className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">{plan.slug}</code></td>\n <td className=\"p-4 text-sm\">{formatPrice(plan.priceMonthly, plan.currency)}</td>\n <td className=\"p-4 text-sm\">{formatPrice(plan.priceYearly, plan.currency)}</td>\n <td className=\"p-4\">\n <StatusBadge\n label={plan.isActive ? 'Attivo' : 'Inattivo'}\n colorClass={plan.isActive ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' : 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400'}\n />\n </td>\n <td className=\"p-4 text-right\">\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm h-8 px-2 hover:bg-accent disabled:opacity-50\"\n onClick={() => syncMutation.mutate(plan.id, {\n onSuccess: () => toast.success('Piano sincronizzato con Stripe'),\n onError: (err) => toast.error(`Errore sync: ${err.message}`),\n })}\n disabled={syncMutation.isPending}\n >\n <CloudUpload className=\"w-4 h-4 mr-1\" />Sync\n </button>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { CreditCard, RefreshCw } from 'lucide-react';\nimport {\n useBillingSubscriptions,\n useCancelBillingSubscription,\n formatDate,\n billingSubscriptionStatusColors,\n billingSubscriptionStatusLabels,\n} from '@growflowstudio/growflowbooking-admin-core';\nimport type { BillingSubscriptionStatus } from '@growflowstudio/growflowbooking-admin-core';\nimport { StatusBadge } from '../components/shared/StatusBadge';\nimport { SkeletonRows } from '../components/shared/SkeletonRows';\nimport { FilterBar } from '../components/shared/FilterBar';\n\nexport interface BillingSubscriptionsPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function BillingSubscriptionsPage({ wrapper: Wrapper, header }: BillingSubscriptionsPageProps) {\n const [search, setSearch] = useState('');\n const [statusFilter, setStatusFilter] = useState('all');\n\n const { data, isLoading, refetch } = useBillingSubscriptions({\n search: search || undefined,\n status: statusFilter !== 'all' ? statusFilter : undefined,\n });\n\n const cancelMutation = useCancelBillingSubscription();\n const subscriptions = data?.items || [];\n\n const content = (\n <>\n {header}\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <CreditCard className=\"w-4 h-4\" />\n <span>{data?.total || 0} abbonamenti billing</span>\n </div>\n\n <FilterBar\n searchPlaceholder=\"Cerca abbonamenti...\"\n searchValue={search}\n onSearchChange={setSearch}\n statusFilter={statusFilter}\n onStatusFilterChange={setStatusFilter}\n statusOptions={[\n { value: 'all', label: 'Tutti gli stati' },\n { value: 'active', label: 'Attivi' },\n { value: 'trialing', label: 'In Prova' },\n { value: 'past_due', label: 'Scaduti' },\n { value: 'canceled', label: 'Cancellati' },\n ]}\n onRefresh={() => refetch()}\n />\n\n <div className=\"rounded-lg border bg-card text-card-foreground shadow-sm\">\n <div className=\"p-0\">\n <table className=\"w-full\">\n <thead>\n <tr className=\"border-b\">\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Subscriber</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Piano</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Ciclo</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Stato</th>\n <th className=\"h-12 px-4 text-left align-middle font-medium text-muted-foreground\">Periodo Corrente</th>\n <th className=\"h-12 px-4 text-right align-middle font-medium text-muted-foreground\">Azioni</th>\n </tr>\n </thead>\n <tbody>\n {isLoading ? (\n <SkeletonRows rows={5} columns={6} />\n ) : subscriptions.length === 0 ? (\n <tr>\n <td colSpan={6} className=\"h-24 text-center text-muted-foreground\">\n Nessun abbonamento trovato.\n </td>\n </tr>\n ) : (\n subscriptions.map((sub) => (\n <tr key={sub.id} className=\"border-b hover:bg-muted/50\">\n <td className=\"p-4\">\n <div className=\"font-medium\">{sub.subscriberName || sub.subscriberEmail}</div>\n <div className=\"text-xs text-muted-foreground\">{sub.subscriberEmail}</div>\n </td>\n <td className=\"p-4\"><code className=\"text-xs bg-muted px-1.5 py-0.5 rounded\">{sub.planSlug}</code></td>\n <td className=\"p-4 text-sm capitalize\">{sub.billingCycle}</td>\n <td className=\"p-4\">\n <StatusBadge\n label={billingSubscriptionStatusLabels[sub.status]}\n colorClass={billingSubscriptionStatusColors[sub.status]}\n />\n </td>\n <td className=\"p-4 text-sm text-muted-foreground\">\n {sub.currentPeriodStart && sub.currentPeriodEnd\n ? `${formatDate(sub.currentPeriodStart)} - ${formatDate(sub.currentPeriodEnd)}`\n : '-'}\n </td>\n <td className=\"p-4 text-right\">\n {sub.status === 'active' && (\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm h-8 px-2 hover:bg-accent text-destructive disabled:opacity-50\"\n onClick={() => cancelMutation.mutate({ id: sub.id, atPeriodEnd: true }, {\n onSuccess: () => toast.success('Abbonamento cancellato a fine periodo'),\n onError: (err) => toast.error(`Errore: ${err.message}`),\n })}\n disabled={cancelMutation.isPending}\n >\n Cancella\n </button>\n )}\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import { useState } from 'react';\nimport { toast } from 'sonner';\nimport { Settings, Loader2, CheckCircle2, XCircle } from 'lucide-react';\nimport {\n useBillingSettings,\n useUpdateBillingSettings,\n useTestBillingConnection,\n} from '@growflowstudio/growflowbooking-admin-core';\n\nexport interface SettingsPageProps {\n wrapper?: React.ComponentType<{ children: React.ReactNode }>;\n header?: React.ReactNode;\n}\n\nexport function SettingsPage({ wrapper: Wrapper, header }: SettingsPageProps) {\n const { data: settings, isLoading } = useBillingSettings();\n const updateMutation = useUpdateBillingSettings();\n const testMutation = useTestBillingConnection();\n\n const [apiKey, setApiKey] = useState('');\n const [webhookSecret, setWebhookSecret] = useState('');\n const [mode, setMode] = useState('test');\n const [billingUrlTest, setBillingUrlTest] = useState('');\n const [billingUrlProduction, setBillingUrlProduction] = useState('');\n\n const handleSave = () => {\n const data: Record<string, string> = {};\n if (apiKey) data.apiKey = apiKey;\n if (webhookSecret) data.webhookSecret = webhookSecret;\n if (mode) data.mode = mode;\n if (billingUrlTest) data.billingUrlTest = billingUrlTest;\n if (billingUrlProduction) data.billingUrlProduction = billingUrlProduction;\n\n updateMutation.mutate(data, {\n onSuccess: () => { toast.success('Impostazioni salvate'); setApiKey(''); setWebhookSecret(''); },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n };\n\n const handleTest = () => {\n testMutation.mutate(undefined, {\n onSuccess: (result) => {\n if (result.success) {\n toast.success(`Connessione OK — ${result.plansCount} piani trovati`);\n } else {\n toast.error(`Connessione fallita: ${result.message}`);\n }\n },\n onError: (err) => toast.error(`Errore: ${err.message}`),\n });\n };\n\n const content = (\n <>\n {header}\n <div className=\"space-y-6\">\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Settings className=\"w-4 h-4\" />\n <span>Impostazioni GrowFlow Billing</span>\n </div>\n\n {isLoading ? (\n <div className=\"space-y-4\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"h-12 w-full animate-pulse rounded-md bg-muted\" />\n ))}\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <h3 className=\"font-medium\">Stato Connessione</h3>\n <div className=\"grid grid-cols-2 gap-4 text-sm\">\n <div className=\"flex items-center gap-2\">\n {settings?.apiKeyConfigured ? <CheckCircle2 className=\"w-4 h-4 text-green-600\" /> : <XCircle className=\"w-4 h-4 text-red-500\" />}\n <span>API Key: {settings?.apiKeyMasked || 'Non configurata'}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n {settings?.webhookSecretConfigured ? <CheckCircle2 className=\"w-4 h-4 text-green-600\" /> : <XCircle className=\"w-4 h-4 text-red-500\" />}\n <span>Webhook: {settings?.webhookSecretMasked || 'Non configurato'}</span>\n </div>\n <div>\n <span className=\"text-muted-foreground\">Modalità:</span> {settings?.mode || '-'}\n </div>\n <div>\n <span className=\"text-muted-foreground\">Client ID:</span> {settings?.clientId || '-'}\n </div>\n </div>\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 border border-input bg-background hover:bg-accent disabled:opacity-50\"\n onClick={handleTest}\n disabled={testMutation.isPending}\n >\n {testMutation.isPending && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n Testa Connessione\n </button>\n </div>\n\n <div className=\"rounded-lg border bg-card p-6 space-y-4\">\n <h3 className=\"font-medium\">Aggiorna Impostazioni</h3>\n <div className=\"grid gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">API Key</label>\n <input type=\"password\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={apiKey} onChange={(e) => setApiKey(e.target.value)} placeholder=\"sk_live_...\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">Webhook Secret</label>\n <input type=\"password\" className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={webhookSecret} onChange={(e) => setWebhookSecret(e.target.value)} placeholder=\"whsec_...\" />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">URL Test</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={billingUrlTest} onChange={(e) => setBillingUrlTest(e.target.value)} placeholder=\"http://localhost:8008\" />\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">URL Produzione</label>\n <input className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={billingUrlProduction} onChange={(e) => setBillingUrlProduction(e.target.value)} placeholder=\"https://billing.growflow.studio\" />\n </div>\n </div>\n <div className=\"space-y-2\">\n <label className=\"text-sm font-medium\">Modalità</label>\n <select className=\"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\" value={mode} onChange={(e) => setMode(e.target.value)}>\n <option value=\"test\">Test</option>\n <option value=\"production\">Produzione</option>\n </select>\n </div>\n </div>\n <button\n className=\"inline-flex items-center justify-center rounded-md text-sm font-medium h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-50\"\n onClick={handleSave}\n disabled={updateMutation.isPending}\n >\n {updateMutation.isPending && <Loader2 className=\"w-4 h-4 animate-spin mr-2\" />}\n Salva Impostazioni\n </button>\n </div>\n </div>\n )}\n </div>\n </>\n );\n\n return Wrapper ? <Wrapper>{content}</Wrapper> : content;\n}\n","import type { BookingModulesConfig } from '../provider';\n\nexport interface BookingNavItem {\n key: string;\n label: string;\n /** Lucide icon name (consumer maps to actual icon component) */\n icon: string;\n /** Suggested href path (consumer can override) */\n href: string;\n}\n\nconst ALL_NAV_ITEMS: BookingNavItem[] = [\n { key: 'tenants', label: 'Tenant', icon: 'Building2', href: '/admin/tenants' },\n { key: 'customers', label: 'Clienti', icon: 'Users', href: '/admin/customers' },\n { key: 'subscriptionPlans', label: 'Piani', icon: 'LayoutGrid', href: '/admin/subscription-plans' },\n { key: 'billingPlans', label: 'Billing Piani', icon: 'CreditCard', href: '/admin/billing-plans' },\n { key: 'billingSubscriptions', label: 'Abbonamenti', icon: 'Receipt', href: '/admin/billing-subscriptions' },\n { key: 'settings', label: 'Impostazioni', icon: 'Settings', href: '/admin/settings' },\n];\n\n/**\n * Returns navigation items filtered by enabled modules.\n */\nexport function getBookingNavItems(\n modules?: BookingModulesConfig,\n basePath?: string,\n): BookingNavItem[] {\n const enabled = {\n tenants: true,\n customers: true,\n subscriptionPlans: true,\n billingPlans: true,\n billingSubscriptions: true,\n settings: true,\n ...modules,\n };\n\n return ALL_NAV_ITEMS\n .filter((item) => enabled[item.key as keyof typeof enabled] !== false)\n .map((item) => ({\n ...item,\n href: basePath ? `${basePath}${item.href}` : item.href,\n }));\n}\n"],"mappings":"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","names":["React","import_react","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_jsx_runtime","import_growflowbooking_admin_core","import_jsx_runtime","import_react","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_lucide_react","import_jsx_runtime","import_jsx_runtime","import_react","import_sonner","import_lucide_react","import_growflowbooking_admin_core","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_react","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_jsx_runtime","import_react","import_sonner","import_lucide_react","import_growflowbooking_admin_core","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_react","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_jsx_runtime","import_sonner","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_react","import_sonner","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime","import_react","import_sonner","import_lucide_react","import_growflowbooking_admin_core","import_jsx_runtime"]}
|