# Admin Package The Admin package provides a complete admin panel with Livewire modals, form components, global search, and an extensible menu system. ## Installation ```bash composer require host-uk/core-admin ``` ## Features ### Admin Menu System Extensible navigation menu with automatic discovery: ```php icon('newspaper') ->priority(30) ->children([ MenuItemBuilder::make('Posts') ->route('admin.blog.posts.index') ->icon('document-text'), MenuItemBuilder::make('Categories') ->route('admin.blog.categories.index') ->icon('folder'), ]) ->build(), ]; } } ``` Register in your module's Boot.php: ```php public function onAdmin(AdminPanelBooting $event): void { $event->menu(new BlogMenuProvider()); } ``` [Learn more about Admin Menus →](/patterns-guide/admin-menus) ### Livewire Modals Full-page modal system for admin interfaces: ```php post = $post; $this->title = $post?->title; $this->content = $post?->content; } public function save(): void { $validated = $this->validate([ 'title' => 'required|max:255', 'content' => 'required', ]); if ($this->post) { $this->post->update($validated); } else { Post::create($validated); } $this->dispatch('post-saved'); $this->closeModal(); } public function render() { return view('blog::admin.post-editor'); } } ``` Open modals from any admin page: ```blade New Post Edit Post ``` ### Form Components Pre-built form components with validation: ```blade
Save Post Cancel
``` ### Global Search Search across all admin content: ```php orWhere('content', 'like', "%{$query}%") ->limit(5) ->get() ->map(fn ($post) => new SearchResult( title: $post->title, description: $post->excerpt, url: route('admin.blog.posts.edit', $post), icon: 'document-text', type: 'Post', )) ->toArray(); } public function getSearchableTypes(): array { return ['posts']; } } ``` Register provider: ```php // config/core-admin.php 'search' => [ 'providers' => [ \Mod\Blog\Search\PostSearchProvider::class, ], ], ``` ### Dashboard Widgets Add widgets to the admin dashboard: ```php Post::count(), 'publishedPosts' => Post::published()->count(), 'draftPosts' => Post::draft()->count(), ]); } } ``` Register widget: ```php public function onAdmin(AdminPanelBooting $event): void { $event->widget(new PostStatsWidget(), priority: 10); } ``` ### Settings Pages Add custom settings pages: ```php postsPerPage = config('blog.posts_per_page', 10); $this->enableComments = config('blog.comments_enabled', true); } public function save(): void { ConfigService::set('blog.posts_per_page', $this->postsPerPage); ConfigService::set('blog.comments_enabled', $this->enableComments); $this->dispatch('settings-saved'); } public function render() { return view('blog::admin.settings'); } } ``` Register settings page: ```php public function onAdmin(AdminPanelBooting $event): void { $event->settings('blog', BlogSettings::class); } ``` ## Components Reference ### Input ```blade ``` ### Textarea ```blade ``` ### Select ```blade ``` ### Checkbox ```blade ``` ### Toggle ```blade ``` ### Button ```blade Save Changes ``` ### Form Group ```blade ``` ## Layouts ### Admin App Layout ```blade

Page Title

{{-- Main content --}}
Content here
``` ### HLCRF Layout ```blade Page Header with Actions Sidebar Navigation Main Content Area Contextual Help & Widgets ``` [Learn more about HLCRF →](/patterns-guide/hlcrf) ## Configuration ```php // config/core-admin.php return [ 'menu' => [ 'cache_enabled' => true, 'cache_ttl' => 3600, 'show_icons' => true, ], 'search' => [ 'enabled' => true, 'providers' => [ // Register search providers ], 'max_results' => 10, ], 'livewire' => [ 'modal_max_width' => '7xl', 'modal_close_on_escape' => true, ], 'form' => [ 'validation_real_time' => true, 'show_required_indicator' => true, ], ]; ``` ## Styling Admin package uses Tailwind CSS. Customize theme: ```js // tailwind.config.js module.exports = { theme: { extend: { colors: { admin: { primary: '#3b82f6', secondary: '#64748b', success: '#22c55e', danger: '#ef4444', }, }, }, }, }; ``` ## JavaScript Admin package includes Alpine.js for interactivity: ```blade
Content
``` ## Testing ### Feature Tests ```php public function test_can_access_admin_dashboard(): void { $user = User::factory()->admin()->create(); $response = $this->actingAs($user) ->get('/admin'); $response->assertStatus(200); } public function test_admin_menu_displays_blog_items(): void { $user = User::factory()->admin()->create(); $response = $this->actingAs($user) ->get('/admin'); $response->assertSee('Blog'); $response->assertSee('Posts'); $response->assertSee('Categories'); } ``` ### Livewire Component Tests ```php public function test_can_create_post_via_modal(): void { Livewire::actingAs($admin) ->test(PostEditor::class) ->set('title', 'Test Post') ->set('content', 'Test content') ->call('save') ->assertDispatched('post-saved'); $this->assertDatabaseHas('posts', [ 'title' => 'Test Post', ]); } ``` ## Best Practices ### 1. Use Livewire Modals for CRUD ```php // ✅ Good - modal UX New Post // ❌ Bad - full page redirect New Post ``` ### 2. Organize Menu Items by Domain ```php MenuItemBuilder::make('Content') ->children([ MenuItemBuilder::make('Posts')->route('admin.posts.index'), MenuItemBuilder::make('Pages')->route('admin.pages.index'), ]); ``` ### 3. Use Form Components ```blade {{-- ✅ Good - consistent styling --}} {{-- ❌ Bad - custom HTML --}}
``` ## Changelog See [CHANGELOG.md](https://github.com/host-uk/core-php/blob/main/packages/core-admin/changelog/2026/jan/features.md) ## License EUPL-1.2 ## Learn More - [HLCRF Layout System →](/patterns-guide/hlcrf) - [Livewire Documentation](https://livewire.laravel.com) - [Alpine.js Documentation](https://alpinejs.dev)