b2in/packages/flux-cms/components/resources/views/livewire/backend/blog-manager.blade.php
2025-10-20 17:50:35 +02:00

366 lines
No EOL
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="space-y-6">
{{-- Header --}}
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-semibold text-gray-900">Blog Manager</h1>
<p class="text-sm text-gray-500 mt-1">
Create and manage blog posts
</p>
</div>
<div class="flex items-center space-x-3">
<flux:button wire:click="createPost" variant="primary">
New Post
</flux:button>
</div>
</div>
{{-- Stats Cards --}}
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
@foreach($this->getStats() as $stat)
<flux:card>
<div class="text-center p-4">
<div class="text-2xl font-bold text-gray-900">{{ $stat['value'] }}</div>
<div class="text-sm text-gray-500">{{ $stat['label'] }}</div>
</div>
</flux:card>
@endforeach
</div>
{{-- Filters --}}
<flux:card>
<div class="flex flex-wrap items-center gap-4">
<div class="flex-1 min-w-64">
<flux:input wire:model.live="search"
placeholder="Search posts..."
class="w-full" />
</div>
<flux:select wire:model.live="statusFilter" placeholder="All Status">
<flux:option value="">All Status</flux:option>
<flux:option value="published">Published</flux:option>
<flux:option value="draft">Draft</flux:option>
<flux:option value="featured">Featured</flux:option>
</flux:select>
<flux:select wire:model.live="categoryFilter" placeholder="All Categories">
<flux:option value="">All Categories</flux:option>
@foreach($this->getCategories() as $category)
<flux:option value="{{ $category }}">{{ $category }}</flux:option>
@endforeach
</flux:select>
<flux:select wire:model.live="sortBy">
<flux:option value="created_at">Created Date</flux:option>
<flux:option value="published_at">Published Date</flux:option>
<flux:option value="title">Title</flux:option>
</flux:select>
<flux:select wire:model.live="sortDirection">
<flux:option value="desc">Newest First</flux:option>
<flux:option value="asc">Oldest First</flux:option>
</flux:select>
</div>
</flux:card>
{{-- Posts Table --}}
<flux:card>
<flux:table>
<flux:columns>
<flux:column>Title</flux:column>
<flux:column>Status</flux:column>
<flux:column>Category</flux:column>
<flux:column>Author</flux:column>
<flux:column>Published</flux:column>
<flux:column>Actions</flux:column>
</flux:columns>
<flux:rows>
@forelse($posts as $post)
<flux:row wire:key="post-{{ $post->id }}">
<flux:cell>
<div>
<div class="font-medium text-gray-900">
{{ $post->title }}
</div>
@if($post->excerpt)
<div class="text-sm text-gray-500 mt-1">
{{ str_limit($post->excerpt, 60) }}
</div>
@endif
</div>
</flux:cell>
<flux:cell>
<div class="flex items-center space-x-2">
@if($post->is_published)
<flux:badge color="green" size="sm">Published</flux:badge>
@else
<flux:badge color="gray" size="sm">Draft</flux:badge>
@endif
@if($post->is_featured)
<flux:badge color="blue" size="sm">Featured</flux:badge>
@endif
</div>
</flux:cell>
<flux:cell>
{{ $post->category ?? '—' }}
</flux:cell>
<flux:cell>
{{ $post->author?->name ?? '—' }}
</flux:cell>
<flux:cell>
{{ $post->published_at?->format('M j, Y') ?? '—' }}
</flux:cell>
<flux:cell>
<div class="flex items-center space-x-2">
@if($post->is_published)
<flux:button href="{{ $post->getUrl() }}"
target="_blank"
size="sm"
variant="ghost">
View
</flux:button>
@endif
<flux:button wire:click="editPost({{ $post->id }})"
size="sm"
variant="ghost">
Edit
</flux:button>
<flux:button wire:click="duplicatePost({{ $post->id }})"
size="sm"
variant="ghost">
Duplicate
</flux:button>
<flux:button wire:click="deletePost({{ $post->id }})"
size="sm"
variant="danger">
Delete
</flux:button>
</div>
</flux:cell>
</flux:row>
@empty
<flux:row>
<flux:cell colspan="6">
<div class="text-center py-8 text-gray-500">
<flux:icon.document-text class="w-12 h-12 mx-auto mb-3 text-gray-300" />
<p>No blog posts found.</p>
<p class="text-sm">Create your first blog post to get started.</p>
</div>
</flux:cell>
</flux:row>
@endforelse
</flux:rows>
</flux:table>
{{-- Pagination --}}
@if($posts->hasPages())
<div class="px-6 py-4 border-t border-gray-200">
{{ $posts->links() }}
</div>
@endif
</flux:card>
{{-- Post Form Modal --}}
<flux:modal name="post-form" class="md:w-6xl max-h-screen overflow-y-auto">
<div class="space-y-6">
<div class="flex items-center justify-between">
<flux:heading size="lg">
{{ $editingPost ? 'Edit Post' : 'Create Post' }}
</flux:heading>
<div class="flex items-center space-x-3">
@if($editingPost)
<flux:button wire:click="saveAsDraft" variant="ghost">
Save as Draft
</flux:button>
<flux:button wire:click="publishPost" variant="primary">
{{ $editingPost->is_published ? 'Update' : 'Publish' }}
</flux:button>
@else
<flux:button wire:click="saveDraft" variant="ghost">
Save Draft
</flux:button>
<flux:button wire:click="saveAndPublish" variant="primary">
Publish
</flux:button>
@endif
</div>
</div>
{{-- Language Tabs --}}
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8">
@foreach($availableLocales as $locale)
<button wire:click="setActiveLocale('{{ $locale }}')"
class="py-2 px-1 border-b-2 font-medium text-sm {{ $activeLocale === $locale ? 'border-blue-500 text-blue-600' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300' }}">
{{ strtoupper($locale) }}
</button>
@endforeach
</nav>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
{{-- Main Content --}}
<div class="lg:col-span-2 space-y-6">
{{-- Title & Slug --}}
<div class="space-y-4">
<flux:field>
<flux:label>Title ({{ strtoupper($activeLocale) }})</flux:label>
<flux:input wire:model.live="postForm.title.{{ $activeLocale }}"
placeholder="Enter post title" />
<flux:error name="postForm.title.{{ $activeLocale }}" />
</flux:field>
<flux:field>
<flux:label>Slug ({{ strtoupper($activeLocale) }})</flux:label>
<flux:input wire:model.live="postForm.slug.{{ $activeLocale }}"
placeholder="post-url-slug" />
<flux:error name="postForm.slug.{{ $activeLocale }}" />
</flux:field>
</div>
{{-- Excerpt --}}
<flux:field>
<flux:label>Excerpt ({{ strtoupper($activeLocale) }})</flux:label>
<flux:textarea wire:model.live="postForm.excerpt.{{ $activeLocale }}"
rows="3"
placeholder="Brief description of the post" />
<flux:description>Optional excerpt for post listings and SEO</flux:description>
<flux:error name="postForm.excerpt.{{ $activeLocale }}" />
</flux:field>
{{-- Content --}}
<flux:field>
<flux:label>Content ({{ strtoupper($activeLocale) }})</flux:label>
<div wire:ignore>
<textarea wire:model.live="postForm.content.{{ $activeLocale }}"
class="wysiwyg-editor"
rows="15"
placeholder="Write your post content here..."></textarea>
</div>
<flux:error name="postForm.content.{{ $activeLocale }}" />
</flux:field>
</div>
{{-- Sidebar --}}
<div class="space-y-6">
{{-- Publishing Options --}}
<flux:card>
<flux:card.header>
<flux:heading size="sm">Publishing</flux:heading>
</flux:card.header>
<div class="space-y-4">
<flux:field>
<flux:label>Published Date</flux:label>
<flux:input wire:model.live="postForm.published_at"
type="datetime-local" />
</flux:field>
<flux:field>
<flux:checkbox wire:model.live="postForm.is_featured">
Featured Post
</flux:checkbox>
<flux:description>Featured posts appear prominently on the site</flux:description>
</flux:field>
</div>
</flux:card>
{{-- Categories & Tags --}}
<flux:card>
<flux:card.header>
<flux:heading size="sm">Organization</flux:heading>
</flux:card.header>
<div class="space-y-4">
<flux:field>
<flux:label>Category</flux:label>
<flux:input wire:model.live="postForm.category"
placeholder="e.g., Technology, News" />
</flux:field>
<flux:field>
<flux:label>Tags</flux:label>
<flux:input wire:model.live="tagsInput"
placeholder="Enter tags separated by commas" />
<flux:description>Separate multiple tags with commas</flux:description>
</flux:field>
</div>
</flux:card>
{{-- SEO Settings --}}
<flux:card>
<flux:card.header>
<flux:heading size="sm">SEO Settings</flux:heading>
</flux:card.header>
<div class="space-y-4">
<flux:field>
<flux:label>Meta Title ({{ strtoupper($activeLocale) }})</flux:label>
<flux:input wire:model.live="postForm.meta_title.{{ $activeLocale }}"
placeholder="SEO title (defaults to post title)" />
</flux:field>
<flux:field>
<flux:label>Meta Description ({{ strtoupper($activeLocale) }})</flux:label>
<flux:textarea wire:model.live="postForm.meta_description.{{ $activeLocale }}"
rows="3"
placeholder="SEO description (defaults to excerpt)" />
</flux:field>
</div>
</flux:card>
{{-- Featured Image --}}
<flux:card>
<flux:card.header>
<flux:heading size="sm">Featured Image</flux:heading>
</flux:card.header>
<div class="space-y-4">
@if($featuredImage)
<div class="relative">
<img src="{{ $featuredImage->getUrl('thumb') }}"
alt="Featured image"
class="w-full rounded">
<button wire:click="removeFeaturedImage"
class="absolute -top-2 -right-2 bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center text-xs">
×
</button>
</div>
@else
<flux:button wire:click="selectFeaturedImage" size="sm" class="w-full">
Select Featured Image
</flux:button>
@endif
</div>
</flux:card>
</div>
</div>
<div class="flex justify-end space-x-3 pt-6 border-t border-gray-200">
<flux:button wire:click="$dispatch('close-modal')" variant="ghost">
Cancel
</flux:button>
</div>
</div>
</flux:modal>
</div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize WYSIWYG editor for content
// You can integrate your preferred editor here (CKEditor, TinyMCE, Quill, etc.)
});
</script>
@endpush