boban
28fbcba227
fix: bugs 1,4,5,7,8,9 — sidebar icon, theme button, copy-link, UTM computed, workspace context, theme sync
...
Bug 1: sidebar toggle — single rotating SVG → two x-show SVGs (chevron-left / chevron-right)
Bug 4: theme button — template x-if → svg x-show x-cloak; apply() now resolves 'system'
to dark/light before setting data-theme (was setting data-theme="system" → CSS ignored it)
Bug 5: x-ui.copy-button added to links, bio, qr-codes rows and api-tokens new-token display
Bug 7: UtmBuilder::getFullUrlProperty() (Livewire v2 magic) → #[Computed] fullUrl()
(Livewire v3 dropped getXProperty magic — $fullUrl was undefined in blade)
Bug 8: require_workspace() moved from render() to mount() in Overview, Links/Index, Settings/Index
(Livewire update requests hit /livewire/update — ResolveWorkspace middleware never ran → threw)
Bug 9: Preferences::save() dispatches theme-changed-server → layout listener calls
Alpine.store('theme').apply(theme) so DOM updates immediately without reload
Bugs 2, 3, 6 already correct in codebase (layout had transition/ml-60 binding,
mobile sidebar used $store.sidebar.open, routes used ULID via model route key).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 17:30:44 +02:00
boban
43ff6d6407
fix(FIX-10): 6 bugs — route ULID, QR modal, bio unique, nav active, copy btn, analytics context
...
- Workspace.getRouteKeyName()='ulid' so route() generates ULID URLs not ID
- QR modal 4xl→5xl; import QRCode in @script→window.QRCode (no ESM in @script)
- Bio slug unique rule scoped to (workspace_id, domain_id) not global
- updateActiveNav uses URL.pathname not raw getAttribute('href') (absolute URL fix)
- Add resources/views/components/ui/copy-button.blade.php Alpine component
- Analytics Index.render/baseQuery use $workspaceId not require_workspace() — prevents RuntimeException on Livewire action calls without middleware
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 17:01:16 +02:00
boban
2d231fe6b8
fix: bio public /b/{slug} route + QR types + code cleanup
...
- Add GET /b/{slug} route alias (nimu.li shorthand for bio pages)
- QR wizard: extend type enum to include email, phone, sms, location
- Modals: replace FQCN references with imported class aliases (Pint clean)
- Analytics: add missing Carbon/Builder imports, improve return types
- Octane config: add ResetCurrentWorkspace import
- scripts/crawl-all.sh: curl+PHPUnit based crawler (replaces Playwright)
All 158 tests pass, PHPStan clean, Pint clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 16:41:05 +02:00
boban
248c5100d1
fix(sidebar+types): mobile slide animation, close-on-navigate, PHPStan clean
...
- sidebar: transition-[width,transform] so mobile open/close animates
- sidebar: pure :class binding replaces mixed class+:style for translate
- layout: livewire:navigated closes mobile sidebar via Alpine store
- tests: RouteSmokeTest covers all 17 workspace/profile/AI routes
- scripts: crawl-all-routes.mjs + console-check.mjs (Playwright)
- phpstan: add @property-read, @var, @return generics across 15 modal/component files → 0 errors
- pint: auto-fix style violations in 9 files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:47:17 +02:00
boban
257d1b94f1
feat: QR wizard, UTM Builder, A/B variants, AI features, analytics URL filters
...
- QR Code: split-pane wizard with type tabs, live preview canvas, style/frame/advanced options
- UTM Builder modal: generate URL with UTM params, copy + create short link
- A/B Test: LinkVariants modal with auto-balance weights (min 2, max 5 variants)
- AI: SlugSuggester service (3 suggestions via claude-haiku), AI-slug button in CreateLink
- AI pages: /ai/insights, /ai/anomalies, /ai/ab-generator with sidebar entry
- Analytics: #[Url] attributes for range/country/device/linkId, 24h/7d/30d/90d buttons
- QR enum migration (MySQL-only guard) to add email/phone/sms/location types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:14:19 +02:00
boban
2510620f67
fix(modals): make create/edit/delete modals actually save + auto-refresh lists
...
- All create modals now validate→create→dispatch(kebab-case event)→toast→close
- All edit/delete modals dispatch kebab-case events to Index classes
- Index components listen via #[On] and call resetPage() to refresh
- QR Code save() validates url field conditionally per type
- Tests updated to assert kebab-case event names
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:13:44 +02:00
boban
c67bde8fc5
feat: Toaster, button-component, 10 new modals, links-page fix, vite-tuning
...
- Toaster Livewire component (toast event, dismiss, auto-hide, 6 tests)
- <x-ui.button> Blade component with wire:loading indicator + variants
- QR modals: CreateQrCode, EditQrCode, DeleteQrCode (TDD, 8 tests)
- Bio modals: CreateBioPage, EditBioPage, DeleteBioPage (TDD, 7 tests)
- Domain modals: AddDomain, VerifyDomain, DeleteDomain (TDD, 7 tests)
- Profile modal: DeleteAccount with password confirm (TDD, 4 tests)
- Links page: fix openModal event name, wire up Edit/Delete to modals, toast on all CRUD
- vite.config.js: add chart.js/auto + optimizeDeps.force
- QrCode model: add newFactory() + QrCodeFactory
- Layout: Toaster embedded before </body>
- 141 tests / 296 assertions all green, verify 29/29
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 13:55:25 +02:00
boban
5748dd3443
style: apply Pint formatting to modal files and tests
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:42:16 +02:00
boban
fa9985cc33
feat: modal infrastructure + 11 modals (links, team, settings, workspace)
...
wire-elements/modal v3 integration:
- Replace custom Alpine modal-container with <livewire:livewire-ui-modal />
- Customize vendor modal view with design tokens (bg-s1, dark overlay, smooth transitions)
- All modals extend ModalComponent, use $this->closeModal()
Modals built (PHP + Blade view + tests):
- ConfirmAction — reusable danger confirm with custom event dispatch
- CreateLink, EditLink, DeleteLink — full CRUD with workspace isolation
- InviteMember, EditMemberRole, RemoveMember — team management
- CreateApiToken, RevokeApiToken — Sanctum token lifecycle
- CreateWebhook, DeleteWebhook — webhook CRUD
- CreateWorkspace (uses CreateWorkspaceAction), DeleteWorkspace (confirmation input)
Fixes:
- Remove SoftDeletes from Webhook model (table has no deleted_at column)
- Auto-generate webhook secret when user leaves field empty
- Use correct role enum: owner/admin/editor/viewer (not member)
- Protected Livewire model properties replaced with re-query pattern
- Sidebar "New Workspace" button now dispatches openModal
Tests: 105/105 passing, 211 assertions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:41:14 +02:00
boban
30989523cd
feat: vollständiges Nimuli-Frontend Phase 1
...
Layouts:
- nimuli-app: Sidebar + Topbar + Mobile-Drawer (Alpine.js stores)
- guest: Nimuli-Brand, bg-bg, Inter/JetBrains Mono
- sidebar: Workspace-Switcher, Nav mit SVG-Icons, Plan-Usage-Box
- topbar: Theme-Toggle, Notifications-Bell, User-Dropdown
Auth (Breeze-Restyle mit Design-Tokens):
- Login: "Sign in" + dark-theme-native (text-t1, bg-s2, text-blue)
- Register: "Create account"
- Forgot Password: restyled
- Alle Input-Komponenten (text-input, label, button, errors) auf Tokens
Dashboard:
- Hero-Metrics (Today/7d/30d/Total Links)
- 30-Tage Chart.js Line-Chart
- Top-5-Links-Tabelle
- Quick-Actions
Links:
- Tabelle: nimu.li/-Prefix, font-mono slug, Tag-Badges, Status-Badges
- Create-Link Modal (Alpine.js + Livewire, auto-slug)
- Modal-Container-System
Stub-Pages (alle mit nimuli-app layout):
- QR Codes: Empty-State + CTA
- Link-in-Bio: Empty-State + CTA
- Analytics: Metrics + Top-Countries + By-Device
- Domains: Empty-State + CTA
- Settings: Workspace-Name + Danger-Zone
- Billing: Current-Plan + 3-Tier-Pricing-Cards
Demo-Daten:
- DemoDataSeeder: 20 Links + 957 Clicks (30 Tage)
- Workspace "Demo Agency" für nexxo@nimuli.com
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 10:52:52 +02:00