Files
timebank-cc-public/resources/views/livewire/quill-editor.blade.php
Ronald Huynen 2547717edb Initial commit
2026-03-23 21:37:59 +01:00

106 lines
3.8 KiB
PHP

<div>
<style>
[x-cloak] { display: none !important; }
</style>
<div
x-data="quillEditorComponent()"
x-init="init()"
wire:ignore.self
class="mb-4">
<div wire:ignore>
<div x-ref="editor">{!! \App\Helpers\StringHelper::sanitizeHtml($content) !!}</div>
</div>
<!-- Word and Character Counter Display -->
<div class="mt-2 flex justify-between items-center text-sm text-theme-muted">
<div class="flex space-x-4">
<span x-text="wordCount + ' words'"></span>
<span x-text="characterCount + ' characters'"></span>
</div>
<div class="text-right">
<span
x-text="(maxCharacters - characterCount) + ' ' + charactersRemainingText"
:class="{
'text-red-500': characterCount > maxCharacters,
'text-orange-500': characterCount > maxCharacters * 0.75,
'text-theme-muted': characterCount <= maxCharacters * 0.75
}">
</span>
</div>
</div>
@error('content')
<div class="mt-1 text-sm text-red-500">
{{ $message }}
</div>
@enderror
</div>
<script>
function quillEditorComponent() {
return {
characterCount: 0,
wordCount: 0,
maxCharacters: {{ timebank_config('posts.content_max_input', 10000) }},
charactersRemainingText: '{{ __('characters remaining') }}',
quillInstance: null,
init() {
// Initialize counters with existing content
const existingContent = this.$refs.editor.innerHTML;
this.updateCounters(existingContent);
// Initialize Quill editor
this.$nextTick(() => {
this.initQuill();
});
// Listen to Livewire events for content updates
Livewire.on('postLoaded', () => {
this.$wire.get('content').then(content => {
if (this.quillInstance) {
this.quillInstance.root.innerHTML = content || '<p><br></p>';
this.updateCounters(content || '');
}
});
});
},
updateCounters(text) {
const plainText = text.replace(/<[^>]*>/g, '').trim();
this.characterCount = plainText.length;
this.wordCount = plainText === '' ? 0 : plainText.split(/\s+/).length;
},
initQuill() {
this.quillInstance = new Quill(this.$refs.editor, {
modules: {
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'],
[{'list': 'ordered' }, {'list': 'bullet' }],
[{ 'align': [] }],
['link', 'image', 'video'],
['clean']
]
},
theme: 'snow',
});
// Sync to Livewire on every change
this.quillInstance.on('text-change', () => {
const content = this.quillInstance.root.innerHTML;
this.$wire.set('content', content, false);
this.updateCounters(content);
});
// Update counters with current content
this.updateCounters(this.quillInstance.root.innerHTML);
}
};
}
</script>
</div>