Du lịch
  • 22/03/2026
  • 8 lượt xem

ffifiefiif ènnienen hay nha

ffifiefiif ènnienen hay nha

@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

Chuyên mục: Du lịch
Trợ lý GoViet
Xin chào! 👋 Mình là trợ lý ảo của GoViet. Mình có thể giúp gì cho bạn?
Trợ lý đang xử lý...