Files
portal-api/resources/views/components/image-picker.blade.php
T
2026-02-06 16:18:15 +07:00

204 lines
8.6 KiB
PHP

@props([
'name' => 'thumbnail',
'label' => 'Thumbnail',
'value' => null,
'placeholder' => 'Chọn File',
'required' => false,
'horizontal' => true,
'labelClass' => 'col-md-3 text-right',
'inputClass' => 'col-md-9',
])
@php
$uniqueId = 'image-picker-' . uniqid();
$currentValue = old($name) ?? $value;
@endphp
@if ($horizontal)
<div class="row form-group align-items-center mb-0">
<label for="{{ $name }}" class="{{ $labelClass }}">
{{ $label }}
@if ($required)
<span class="text-danger">*</span>
@endif
</label>
<div class="{{ $inputClass }} p-1">
@else
<div class="form-group mb-3">
<label for="{{ $name }}" class="mb-2">
{{ $label }}
@if ($required)
<span class="text-danger">*</span>
@endif
</label>
<div>
@endif
<div class="row">
<div class="col-md-8 bg-customer">
<input type="text" id="{{ $uniqueId }}-input" name="{{ $name }}" value="{{ $currentValue }}"
class="form-control image-picker-input" placeholder="{{ $placeholder }}"
data-picker-id="{{ $uniqueId }}" @if ($required) required @endif>
</div>
<div class="col-md-4">
<button type="button" class="btn btn-outline-secondary btn-open-image-picker"
data-picker-id="{{ $uniqueId }}">
<i data-lucide="folder-open" class="w-14px h-14px me-1"></i> Chọn hình ảnh
</button>
</div>
</div>
{{-- Image Preview --}}
<div class="mt-2" id="{{ $uniqueId }}-preview-wrapper" style="display: {{ $currentValue ? 'block' : 'none' }};">
<div class="position-relative d-inline-block">
<div id="{{ $uniqueId }}-preview-container"
class="img-thumbnail bg-light d-flex align-items-center justify-content-center"
style="max-width: 200px; max-height: 150px; min-width: 100px; min-height: 80px; cursor: pointer; overflow: hidden;"
data-bs-toggle="modal" data-bs-target="#{{ $uniqueId }}-modal">
@if ($currentValue)
@if (str_ends_with(strtolower($currentValue), '.svg'))
<object data="{{ $currentValue }}" type="image/svg+xml"
style="max-width: 100%; max-height: 150px; width: auto; height: auto;">
<img src="{{ $currentValue }}" alt="Preview" style="max-width: 100%; max-height: 150px;">
</object>
@else
<img src="{{ $currentValue }}" alt="Preview"
style="max-width: 100%; max-height: 150px; object-fit: contain;">
@endif
@endif
</div>
<button type="button" class="btn btn-sm btn-danger position-absolute btn-remove-image end-0 top-0"
data-picker-id="{{ $uniqueId }}" style="transform: translate(50%, -50%);">
<i data-lucide="x" class="w-12px h-12px"></i>
</button>
</div>
<small class="text-muted d-block mt-1">Click vào ảnh để xem phóng to</small>
</div>
</div>
</div>
{{-- Image Preview Modal --}}
<div class="modal fade" id="{{ $uniqueId }}-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i data-lucide="image" class="w-18px h-18px me-2"></i>
Preview Image
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body bg-light p-3 text-center">
<div id="{{ $uniqueId }}-modal-container" class="d-flex align-items-center justify-content-center"
style="min-height: 300px;">
@if ($currentValue)
@if (str_ends_with(strtolower($currentValue), '.svg'))
<object data="{{ $currentValue }}" type="image/svg+xml"
style="max-width: 100%; max-height: 70vh; width: auto; height: auto;">
<img src="{{ $currentValue }}" alt="Full Preview"
style="max-width: 100%; max-height: 70vh;">
</object>
@else
<img src="{{ $currentValue }}" alt="Full Preview" class="img-fluid"
style="max-height: 70vh;">
@endif
@endif
</div>
</div>
</div>
</div>
</div>
@pushOnce('custom-scripts')
<script>
$(document).ready(function() {
// Prevent multiple initializations
if (window.imagePickerInitialized) return;
window.imagePickerInitialized = true;
// Function to check if file is SVG
function isSvg(url) {
return url && url.toLowerCase().endsWith('.svg');
}
// Function to update preview
function updateImagePreview(pickerId, url) {
const $wrapper = $(`#${pickerId}-preview-wrapper`);
const $container = $(`#${pickerId}-preview-container`);
const $modalContainer = $(`#${pickerId}-modal-container`);
if (url && url.trim() !== '') {
if (isSvg(url)) {
$container.html(`
<object data="${url}" type="image/svg+xml"
style="max-width: 100%; max-height: 150px; width: auto; height: auto;">
<img src="${url}" alt="Preview" style="max-width: 100%; max-height: 150px;">
</object>
`);
$modalContainer.html(`
<object data="${url}" type="image/svg+xml"
style="max-width: 100%; max-height: 70vh; width: auto; height: auto;">
<img src="${url}" alt="Full Preview" style="max-width: 100%; max-height: 70vh;">
</object>
`);
} else {
$container.html(`
<img src="${url}" alt="Preview" style="max-width: 100%; max-height: 150px; object-fit: contain;">
`);
$modalContainer.html(`
<img src="${url}" alt="Full Preview" class="img-fluid" style="max-height: 70vh;">
`);
}
$wrapper.slideDown(200);
// Reinitialize Lucide icons
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
} else {
$wrapper.slideUp(200);
}
}
// Listen for input changes
$(document).on('input change', '.image-picker-input', function() {
const pickerId = $(this).data('picker-id');
updateImagePreview(pickerId, $(this).val());
});
// Remove image button
$(document).on('click', '.btn-remove-image', function(e) {
e.preventDefault();
e.stopPropagation();
const pickerId = $(this).data('picker-id');
const $input = $(`#${pickerId}-input`);
$input.val('');
$(`#${pickerId}-preview-wrapper`).slideUp(200);
});
// Open CKFinder popup
$(document).on('click', '.btn-open-image-picker', function() {
const pickerId = $(this).data('picker-id');
const $input = $(`#${pickerId}-input`);
if (typeof CKFinder !== 'undefined') {
CKFinder.popup({
connectorPath: '{{ route('ckfinder_connector') }}',
chooseFiles: true,
width: 800,
height: 600,
onInit: function(finder) {
finder.on('files:choose', function(evt) {
const fileUrl = evt.data.files.first().getUrl();
$input.val(fileUrl).trigger('input');
});
}
});
} else {
console.error('CKFinder is not loaded');
alert('CKFinder chưa được tải. Vui lòng thử lại.');
}
});
});
</script>
@endPushOnce