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

253 lines
No EOL
14 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">
{{ $componentData ? 'Edit Component' : 'Add Component' }}
</h1>
@if($componentType)
<p class="text-sm text-gray-500 mt-1">
Component Type: {{ class_basename($componentType) }}
</p>
@endif
</div>
<div class="flex items-center space-x-3">
<flux:button wire:click="$dispatch('close-modal')" variant="ghost">
Cancel
</flux:button>
<flux:button wire:click="save" variant="primary">
{{ $componentData ? 'Update' : 'Add' }} Component
</flux:button>
</div>
</div>
{{-- Component Settings --}}
@if($componentType && $fields)
<flux:card>
<flux:card.header>
<flux:heading size="lg">Component Settings</flux:heading>
</flux:card.header>
<div class="space-y-6">
{{-- Language Tabs for Translatable Fields --}}
@if($hasTranslatableFields)
<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>
@endif
{{-- Dynamic Fields --}}
@foreach($fields as $field)
<div class="space-y-2">
@if($field->isTranslatable() && $hasTranslatableFields)
{{-- Translatable Field --}}
<flux:field>
<flux:label>{{ $field->getLabel() }}</flux:label>
@if($field->getHelpText())
<flux:description>{{ $field->getHelpText() }}</flux:description>
@endif
@php
$fieldKey = $field->getKey();
$wireModel = "content.{$fieldKey}.{$activeLocale}";
@endphp
@switch($field->getType())
@case('text')
<flux:input wire:model.live="{{ $wireModel }}"
placeholder="{{ $field->getPlaceholder() }}" />
@break
@case('textarea')
<flux:textarea wire:model.live="{{ $wireModel }}"
placeholder="{{ $field->getPlaceholder() }}"
rows="4" />
@break
@case('wysiwyg')
<div wire:ignore>
<textarea wire:model.live="{{ $wireModel }}"
class="wysiwyg-editor"
rows="10"></textarea>
</div>
@break
@case('select')
<flux:select wire:model.live="{{ $wireModel }}">
@if($field->getEmptyOption())
<flux:option value="">{{ $field->getEmptyOption() }}</flux:option>
@endif
@foreach($field->getOptions() as $value => $label)
<flux:option value="{{ $value }}">{{ $label }}</flux:option>
@endforeach
</flux:select>
@break
@endswitch
<flux:error name="{{ $wireModel }}" />
</flux:field>
@else
{{-- Non-translatable Field --}}
<flux:field>
<flux:label>{{ $field->getLabel() }}</flux:label>
@if($field->getHelpText())
<flux:description>{{ $field->getHelpText() }}</flux:description>
@endif
@php
$fieldKey = $field->getKey();
$wireModel = "content.{$fieldKey}";
@endphp
@switch($field->getType())
@case('text')
<flux:input wire:model.live="{{ $wireModel }}"
placeholder="{{ $field->getPlaceholder() }}" />
@break
@case('number')
<flux:input wire:model.live="{{ $wireModel }}"
type="number"
step="{{ $field->getStep() }}"
@if($field->getMin() !== null) min="{{ $field->getMin() }}" @endif
@if($field->getMax() !== null) max="{{ $field->getMax() }}" @endif
placeholder="{{ $field->getPlaceholder() }}" />
@break
@case('boolean')
@if($field->getDisplayType() === 'toggle')
<flux:switch wire:model.live="{{ $wireModel }}">
{{ $field->getTrueLabel() }}
</flux:switch>
@else
<flux:checkbox wire:model.live="{{ $wireModel }}">
{{ $field->getTrueLabel() }}
</flux:checkbox>
@endif
@break
@case('select')
@if($field->isMultiple())
<flux:select wire:model.live="{{ $wireModel }}" multiple>
@foreach($field->getOptions() as $value => $label)
<flux:option value="{{ $value }}">{{ $label }}</flux:option>
@endforeach
</flux:select>
@else
<flux:select wire:model.live="{{ $wireModel }}">
@if($field->getEmptyOption())
<flux:option value="">{{ $field->getEmptyOption() }}</flux:option>
@endif
@foreach($field->getOptions() as $value => $label)
<flux:option value="{{ $value }}">{{ $label }}</flux:option>
@endforeach
</flux:select>
@endif
@break
@case('media')
<div class="space-y-3">
<flux:button wire:click="openMediaPicker('{{ $fieldKey }}')" size="sm">
Select {{ $field->acceptsImages() ? 'Image' : 'File' }}
</flux:button>
@if(!empty($content[$fieldKey]))
<div class="grid grid-cols-3 gap-3">
@if($field->isMultiple())
@foreach($content[$fieldKey] as $index => $mediaId)
<div class="relative">
<img src="{{ $this->getMediaUrl($mediaId) }}"
alt="Selected media"
class="w-full h-24 object-cover rounded">
<button wire:click="removeMedia('{{ $fieldKey }}', {{ $index }})"
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>
@endforeach
@else
<div class="relative">
<img src="{{ $this->getMediaUrl($content[$fieldKey]) }}"
alt="Selected media"
class="w-full h-24 object-cover rounded">
<button wire:click="removeMedia('{{ $fieldKey }}')"
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>
@endif
</div>
@endif
</div>
@break
@endswitch
<flux:error name="{{ $wireModel }}" />
</flux:field>
@endif
</div>
@endforeach
</div>
</flux:card>
{{-- Component Visibility Settings --}}
<flux:card>
<flux:card.header>
<flux:heading size="lg">Visibility Settings</flux:heading>
</flux:card.header>
<div class="space-y-4">
<flux:field>
<flux:checkbox wire:model.live="settings.is_active">
Component is active
</flux:checkbox>
<flux:description>Inactive components will not be displayed on the frontend</flux:description>
</flux:field>
<flux:field>
<flux:label>CSS Classes</flux:label>
<flux:input wire:model.live="settings.css_classes"
placeholder="Additional CSS classes" />
<flux:description>Custom CSS classes to apply to this component</flux:description>
</flux:field>
</div>
</flux:card>
@else
<div class="text-center py-8">
<flux:icon.exclamation-triangle class="w-12 h-12 mx-auto text-gray-400 mb-4" />
<p class="text-gray-500">No component type selected or fields defined.</p>
</div>
@endif
{{-- Media Picker Modal --}}
<flux:modal name="media-picker" class="md:w-4xl">
<div class="space-y-6">
<flux:heading size="lg">Select Media</flux:heading>
<div class="grid grid-cols-4 gap-4 max-h-96 overflow-y-auto">
{{-- Media items would be loaded here --}}
<div class="text-center py-8 col-span-4 text-gray-500">
Media picker implementation needed
</div>
</div>
</div>
</flux:modal>
</div>
@push('scripts')
<script>
// Initialize WYSIWYG editors
document.addEventListener('DOMContentLoaded', function() {
// Initialize your preferred WYSIWYG editor here
// Example: CKEditor, TinyMCE, Quill, etc.
});
</script>
@endpush