@extends('adminlte::page')
@section('title', 'Soạn thảo bài viết | CMS Modern')
@section('content_header')
<div class="row mb-2">
<div class="col-sm-6">
<h1 class="m-0 text-dark font-weight-bold">
<i class="fas fa-feather-alt text-primary mr-2"></i>TRÌNH SOẠN THẢO BÀI VIẾT
</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="#"><i class="fas fa-home"></i> Admin</a></li>
<li class="breadcrumb-item active">Viết bài</li>
</ol>
</div>
</div>
@stop
@section('content')
<form action="{{ route('admin.blogs.store') }}" method="POST" enctype="multipart/form-data" id="form-blog">
@csrf

{{-- STICKY ACTION BAR: Thanh công cụ dính khi cuộn --}}
<div class="sticky-action-bar shadow-sm">
<div class="container-fluid d-flex justify-content-between align-items-center">
<div class="text-muted small d-none d-md-block">
<i class="fas fa-info-circle mr-1"></i> Đang soạn thảo: <span id="header-title-preview" class="font-weight-bold text-dark">Chưa có tiêu đề</span>
</div>
<div class="actions">
<a href="{{ route('admin.blogs.index') }}" class="btn btn-outline-secondary mr-2 btn-sm-flat">
<i class="fas fa-chevron-left mr-1"></i> Thoát
</a>
<button type="submit" class="btn btn-primary shadow-sm btn-sm-flat">
<i class="fas fa-cloud-upload-alt mr-1"></i> XUẤT BẢN NGAY
</button>
</div>
</div>
</div>
<div class="row mt-3">
{{-- ================= CỘT TRÁI: NỘI DUNG & SEO ================= --}}
<div class="col-lg-8 col-md-12">
{{-- CARD 1: NỘI DUNG CHÍNH --}}
<div class="card card-outline card-primary shadow-lg border-0">
<div class="card-body">
<div class="form-group mb-4">
<label class="h5 font-weight-bold">Tiêu đề bài viết <span class="text-danger">*</span></label>
<input type="text" name="title" id="title" class="form-control form-control-lg border-0 shadow-none bg-light"
value="{{ old('title') }}" placeholder="Ví dụ: 10 địa điểm du lịch không thể bỏ qua..." required style="font-size: 1.5rem; font-weight: 700;">
@error('title') <span class="text-danger small">{{ $message }}</span> @enderror
</div>
<div class="form-group mb-4 bg-light p-2 rounded border-left border-primary">
<div class="d-flex justify-content-between">
<label class="small font-weight-bold text-uppercase text-muted">Đường dẫn tĩnh (URL Slug)</label>
<button type="button" class="btn btn-xs btn-link" id="btn-edit-slug"><i class="fas fa-lock" id="slug-lock-icon"></i> Chỉnh sửa</button>
</div>
<div class="d-flex align-items-center">
<span class="text-muted mr-1">{{ url('/blog') }}/</span>
<input type="text" name="slug" id="slug" value="{{ old('slug') }}" class="form-control form-control-sm border-0 bg-transparent p-0 font-weight-bold text-primary" readonly required>
</div>
</div>
<div class="form-group">
<label class="h6 font-weight-bold"><i class="fas fa-edit mr-1"></i> Nội dung chi tiết</label>
<div class="editor-stats mb-2">
<span class="badge badge-light border"><i class="fas fa-font mr-1"></i> <span id="word-count">0</span> chữ</span>
<span class="badge badge-light border"><i class="fas fa-clock mr-1"></i> <span id="reading-time">0</span> phút đọc</span>
</div>
<textarea name="content" id="editor">{{ old('content') }}</textarea>
</div>
</div>
</div>
{{-- CARD 2: SEO GOOGLE PREVIEW (Hiện đại) --}}
<div class="card shadow-lg border-0">
<div class="card-header bg-white">
<h3 class="card-title font-weight-bold text-muted"><i class="fab fa-google text-success mr-2"></i>Xem trước kết quả tìm kiếm (SEO)</h3>
</div>
<div class="card-body">
<div class="google-preview-box">
<div class="google-url">{{ url('/blog') }}/<span id="google-slug">...</span></div>
<div class="google-title" id="google-title">Tiêu đề bài viết sẽ hiển thị tại đây</div>
<div class="google-desc" id="google-desc">Hãy nhập mô tả ngắn để xem trước cách Google hiển thị bài viết của bạn cho người dùng.</div>
</div>
<hr>
<div class="form-group">
<label class="small font-weight-bold text-uppercase">Mô tả Meta (SEO Description)</label>
<textarea name="description" id="description" class="form-control border-0 bg-light" rows="3" placeholder="Nhập mô tả chuẩn SEO...">{{ old('description') }}</textarea>
<div class="progress progress-xxs mt-2">
<div id="desc-progress" class="progress-bar bg-success" style="width: 0%"></div>
</div>
</div>
</div>
</div>
</div>
{{-- ================= CỘT PHẢI: TÙY CHỌN ================= --}}
<div class="col-lg-4 col-md-12">
<div class="card shadow-lg border-0 card-primary card-outline">
<div class="card-header"><h3 class="card-title font-weight-bold">Cấu hình & Xuất bản</h3></div>
<div class="card-body">
<div class="form-group">
<label>Trạng thái</label>
<select name="is_active" class="form-control select2bs4 shadow-none border-0 bg-light">
<option value="1">🟢 Công khai ngay</option>
<option value="0">🟡 Lưu bản nháp</option>
</select>
</div>
<div class="form-group mt-4">
<label>Danh mục <span class="text-danger">*</span></label>
<select name="category_name" class="form-control select2bs4 shadow-none border-0 bg-light" required>
<option value="Du lịch">Du lịch</option>
<option value="Ẩm thực">Ẩm thực</option>
</select>
</div>
</div>
</div>
<div class="card shadow-lg border-0">
<div class="card-header bg-white"><h3 class="card-title font-weight-bold">Ảnh đại diện</h3></div>
<div class="card-body">
<div class="image-upload-wrapper text-center" onclick="document.getElementById('customFile').click()">
<img id="imagePreview" src="" style="display:none; width:100%; border-radius:8px;">
<div id="imagePlaceholder">
<i class="fas fa-image fa-4x text-muted mb-2"></i>
<p class="text-muted small">Nhấp để tải lên ảnh đại diện bài viết</p>
</div>
</div>
<input type="file" name="image" id="customFile" class="d-none" accept="image/*" onchange="previewImage(event)">
<button type="button" id="btn-remove-img" class="btn btn-xs btn-danger btn-block mt-2" style="display:none;" onclick="removeImage()">Xóa ảnh</button>
</div>
</div>
</div>
</div>
</form>
@stop
@section('css')
<style>
/* Sticky Action Bar */
.sticky-action-bar {
position: sticky; top: 0; z-index: 1030; background: rgba(255,255,255,0.9);
backdrop-filter: blur(5px); padding: 10px 15px; margin: -15px -7.5px 15px -7.5px;
border-bottom: 1px solid #dee2e6; transition: all 0.3s;
}
/* CKEditor Custom */
.ck-editor__editable_inline { min-height: 500px; border: none !important; }
.ck.ck-editor__main>.ck-editor__editable { background: #fff !important; }
/* Google Preview */
.google-preview-box { max-width: 600px; padding: 15px; border: 1px solid #f2f2f2; border-radius: 8px; font-family: arial, sans-serif; }
.google-url { color: #202124; font-size: 14px; margin-bottom: 3px; }
.google-title { color: #1a0dab; font-size: 20px; cursor: pointer; line-height: 1.3; margin-bottom: 3px; }
.google-title:hover { text-decoration: underline; }
.google-desc { color: #4d5156; font-size: 14px; line-height: 1.58; word-wrap: break-word; }
/* Image Wrapper */
.image-upload-wrapper { border: 2px dashed #eee; padding: 40px; border-radius: 12px; transition: 0.3s; cursor: pointer; background: #fafafa; }
.image-upload-wrapper:hover { border-color: #3c8dbc; background: #f0f7ff; }
</style>
@stop
@section('js')
<script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.js"></script>
<script>
$(document).ready(function() {
// CKEditor 5
ClassicEditor.create(document.querySelector('#editor'), {
ckfinder: { uploadUrl: '{{ route("admin.blogs.upload", ["_token" => csrf_token()]) }}' }
}).then(editor => {
// Đếm chữ & Thời gian đọc
editor.model.document.on('change:data', () => {
const text = editor.getData().replace(/<[^>]*>/g, '');
const words = text.split(/\s+/).filter(a => a.length > 0).length;
$('#word-count').text(words);
$('#reading-time').text(Math.ceil(words / 200));
});
});
// Sync Title with Google Preview & Header
$('#title').on('input', function() {
let val = $(this).val();
$('#header-title-preview').text(val || 'Chưa có tiêu đề');
$('#google-title').text(val || 'Tiêu đề bài viết sẽ hiển thị tại đây');
// Auto Slug (nếu không bị khóa)
if ($('#slug-lock-icon').hasClass('fa-lock')) {
let slug = generateSlug(val);
$('#slug').val(slug);
$('#google-slug, #slug-preview').text(slug);
}
});
// SEO Desc Preview
$('#description').on('input', function() {
let val = $(this).val();
$('#google-desc').text(val || 'Hãy nhập mô tả ngắn...');
let progress = Math.min((val.length / 160) * 100, 100);
$('#desc-progress').css('width', progress + '%');
});
// Toggle Slug Lock
$('#btn-edit-slug').click(function() {
let icon = $('#slug-lock-icon');
let input = $('#slug');
if (icon.hasClass('fa-lock')) {
icon.removeClass('fa-lock').addClass('fa-unlock text-warning');
input.removeAttr('readonly').focus();
} else {
icon.removeClass('fa-unlock text-warning').addClass('fa-lock');
input.attr('readonly', true);
}
});
});
function generateSlug(title) {
return title.toLowerCase().replace(/á|à|ả|ạ|ã|ă|ắ|ằ|ẳ|ẵ|ặ|â|ấ|ầ|ẩ|ẫ|ậ/gi, 'a').replace(/é|è|ẻ|ẽ|ẹ|ê|ế|ề|ể|ễ|ệ/gi, 'e').replace(/i|í|ì|ỉ|ĩ|ị/gi, 'i').replace(/ó|ò|ỏ|õ|ọ|ô|ố|ồ|ổ|ỗ|ộ|ơ|ớ|ờ|ở|ỡ|ợ/gi, 'o').replace(/ú|ù|ủ|ũ|ụ|ư|ứ|ừ|ử|ữ|ự/gi, 'u').replace(/ý|ỳ|ỷ|ỹ|ỵ/gi, 'y').replace(/đ/gi, 'd').replace(/\s+/g, '-').replace(/[^a-z0-9\-]/g, '').replace(/\-\-+/g, '-');
}
function previewImage(event) {
let reader = new FileReader();
reader.onload = function() {
$('#imagePreview').attr('src', reader.result).show();
$('#imagePlaceholder').hide();
$('#btn-remove-img').show();
}
reader.readAsDataURL(event.target.files[0]);
}
function removeImage() {
$('#customFile').val("");
$('#imagePreview').hide();
$('#imagePlaceholder').show();
$('#btn-remove-img').hide();
}
</script>
@stop