Commit Graph

10 Commits (0a08d0f268bee037086374ac98a523fa82921232)

Author SHA1 Message Date
boban 0a08d0f268 fix(bug-2): sidebar width via CSS attribute — bypasses @persist Alpine reactivity issue
@persist disconnects Alpine :class bindings from store reactivity on re-render.
Solution: drive sidebar width via html[data-sidebar-collapsed] CSS attribute
(same mechanism as skeleton) instead of Alpine :class.

- _syncDataset() now uses isCollapsed (respects mobile: never narrow on <768px)
- Blocking script checks window.innerWidth >= 768 before setting attribute
- Resize handler calls _syncDataset() to update attribute on viewport change
- aside gets sidebar-aside class; CSS sets 15rem/4rem at md+ via attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:52:57 +02:00
boban fe257ef75b fix(bug-2): isCollapsed as plain reactive property — getters unreliable in Alpine stores 2026-05-17 12:50:11 +02:00
boban d3ad4b4740 fix(bug-2): isCollapsed getter — sidebar auto-expands on mobile viewport
Add isMobile reactive property + resize listener to sidebar store.
isCollapsed getter returns collapsed && !isMobile, so:
- Desktop: collapse works as normal
- Mobile: isCollapsed always false → sidebar always shows expanded state
  regardless of desktop-set collapsed value

Replace all visual $store.sidebar.collapsed → isCollapsed in sidebar + layout.
toggle() / _syncDataset() remain on raw `collapsed` (persisted to localStorage).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:47:38 +02:00
boban 436d80a097 fix(FIX-13): 8 bugs — sidebar flash, mobile hamburger, AI insights, button overlay, QR modal collapse, dashboard always-active, bio themes
- BUG 1: blocking script in <head> reads localStorage before first paint; CSS rule html[data-sidebar-collapsed] .skel-sidebar{width:64px} eliminates width flash
- BUG 2: sidebar store gains mobileOpen/toggleMobile()/closeMobile(); hamburger calls toggleMobile(); backdrop and sidebar :style use mobileOpen; SPA navigated handler calls closeMobile()
- BUG 3: text-purple → text-accent in AI Insights view (text-purple is undefined)
- BUG 4: ui/button.blade.php — spinner is now absolute inset-0 overlay; content fades to opacity-40 via wire:loading.class instead of hiding
- BUG 5: insights generate button and QR modal save/cancel migrated to x-ui.button component
- BUG 6: QR modal Styling/Frame/Advanced sections replaced from <details> (destroyed by Livewire re-render) to Alpine x-data{open:false} divs with x-show — state survives wire:model.live updates
- BUG 7: updateActiveNav() now checks el.dataset.navExact; Dashboard <a> gets data-nav-exact="1" so it only activates on exact pathname match
- BUG 8: bio_pages.theme JSON applied in public show.blade.php via inline CSS vars (4 presets: dark/light/purple/blue); EditBioPage gains theme property with preset selector in modal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 18:28:27 +02:00
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 1ff4114674 feat(sidebar+profile+buttons): sidebar active state, 3-tab profile, consistent button variants
- Sidebar JS: DOMContentLoaded + livewire:navigated updateActiveNav, data-nav-link on links
- Profile: exactly 3 tabs (Personal Info, Preferences, Security) with wire:navigate
- Buttons: all primary actions use bg-accent-gradient text-white
- UTM Builder + copy-to-clipboard Livewire event handler in app layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:14:04 +02:00
boban 502a777afd fix: Chart.js global, Vite 504, test DB isolation, verify script green
- bootstrap.js: Chart.js registered components + window.Chart; Alpine stores moved here
- app.js: minimal (CSS + bootstrap import only)
- vite.config.js: optimizeDeps pre-bundle axios/laravel-echo/pusher-js/chart.js
- nginx: proxy_connect_timeout + proxy_buffering off for Vite asset location
- nimuli-app.blade.php: swap @livewire(wire-elements-modal) before @livewireScripts (rule #7)
- PlanLimitsServiceTest: add RefreshDatabase (SQLite unit test had no migrations)
- verify-modals.sh: fix grep pattern, add Chart.js/optimizeDeps checks, set -e safe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 13:36:40 +02:00
boban 6c81dd1d48 fix: eliminate FOUC, Echo, modal duplicate, icons, test DB isolation
- FIX 1: Remove duplicate modal container (keep @livewire directive, drop <x-modal-container>)
- FIX 2: Add Laravel Echo + Pusher to bootstrap.js with Reverb config
- FIX 3: Cookie-based theme — exclude nimuli_theme from encryption, write cookie in Alpine store, read server-side in layout
- FIX 4: Generate missing PNG favicons (16/32/180/192/512px) via GD
- FIX 5: Create scripts/verify-modals.sh (27 checks, all green)
- BUG: Docker OS env DB_CONNECTION=mysql was overriding phpunit.xml sqlite config, causing RefreshDatabase to migrate:fresh production MySQL — fixed by forcing DB vars in tests/bootstrap.php alongside existing APP_ENV fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 13:23:44 +02:00
boban 25dddf5293 feat: initial Nimuli scaffold with Laravel 12, Livewire 3, Octane, Reverb, Docker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 23:51:57 +02:00