edit.blade.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. @extends('layouts.app')
  2. @section('title', 'Редактировать пост')
  3. @section('content')
  4. <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
  5. <div class="mb-6">
  6. <a href="{{ route('posts.show', $post) }}" class="inline-flex items-center text-indigo-600 hover:text-indigo-800">
  7. <svg class="w-5 h-5 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
  8. <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
  9. </svg>
  10. Назад к посту
  11. </a>
  12. </div>
  13. <div class="bg-white rounded-lg shadow-lg p-8">
  14. <h1 class="text-3xl font-bold text-gray-900 mb-6">Редактировать пост</h1>
  15. <form action="{{ route('posts.update', $post) }}" method="POST" class="space-y-6">
  16. @csrf
  17. @method('PUT')
  18. {{-- Заголовок --}}
  19. <div>
  20. <label for="title" class="block text-sm font-medium text-gray-700 mb-2">
  21. Заголовок *
  22. </label>
  23. <input type="text"
  24. name="title"
  25. id="title"
  26. required
  27. value="{{ old('title', $post->title) }}"
  28. placeholder="Введите заголовок поста"
  29. class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent @error('title') border-red-500 @enderror">
  30. @error('title')
  31. <p class="mt-2 text-sm text-red-600">{{ $message }}</p>
  32. @enderror
  33. </div>
  34. {{-- Slug (только для информации) --}}
  35. <div class="bg-gray-50 p-4 rounded-lg">
  36. <p class="text-sm text-gray-600">
  37. <span class="font-medium">URL:</span>
  38. <span class="text-indigo-600">/posts/{{ $post->slug }}</span>
  39. </p>
  40. </div>
  41. {{-- Контент --}}
  42. <div>
  43. <label for="content" class="block text-sm font-medium text-gray-700 mb-2">
  44. Содержание *
  45. </label>
  46. <textarea name="content"
  47. id="content"
  48. rows="15"
  49. required
  50. placeholder="Напишите содержание поста..."
  51. class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent @error('content') border-red-500 @enderror">{{ old('content', $post->content) }}</textarea>
  52. @error('content')
  53. <p class="mt-2 text-sm text-red-600">{{ $message }}</p>
  54. @enderror
  55. </div>
  56. {{-- Статус публикации --}}
  57. <div>
  58. <label class="block text-sm font-medium text-gray-700 mb-2">
  59. Статус публикации *
  60. </label>
  61. <div class="space-y-3">
  62. <label class="flex items-center p-4 border border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50 transition {{ old('status', $post->status) == 'draft' ? 'bg-indigo-50 border-indigo-500' : '' }}">
  63. <input type="radio"
  64. name="status"
  65. value="draft"
  66. {{ old('status', $post->status) == 'draft' ? 'checked' : '' }}
  67. class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
  68. <div class="ml-3">
  69. <span class="block text-sm font-medium text-gray-900">Черновик</span>
  70. <span class="block text-sm text-gray-500">Сохранить пост без публикации</span>
  71. </div>
  72. </label>
  73. <label class="flex items-center p-4 border border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50 transition {{ old('status', $post->status) == 'published' ? 'bg-indigo-50 border-indigo-500' : '' }}">
  74. <input type="radio"
  75. name="status"
  76. value="published"
  77. {{ old('status', $post->status) == 'published' ? 'checked' : '' }}
  78. class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
  79. <div class="ml-3">
  80. <span class="block text-sm font-medium text-gray-900">Опубликован</span>
  81. <span class="block text-sm text-gray-500">
  82. @if($post->status == 'published' && $post->published_at)
  83. Опубликовано: {{ $post->published_at->format('d.m.Y H:i') }}
  84. @else
  85. Пост будет опубликован немедленно
  86. @endif
  87. </span>
  88. </div>
  89. </label>
  90. <label class="flex items-center p-4 border border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50 transition {{ old('status', $post->status) == 'scheduled' ? 'bg-indigo-50 border-indigo-500' : '' }}">
  91. <input type="radio"
  92. name="status"
  93. value="scheduled"
  94. {{ old('status', $post->status) == 'scheduled' ? 'checked' : '' }}
  95. id="status_scheduled"
  96. class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
  97. <div class="ml-3">
  98. <span class="block text-sm font-medium text-gray-900">Запланировать публикацию</span>
  99. <span class="block text-sm text-gray-500">
  100. @if($post->status == 'scheduled' && $post->scheduled_at)
  101. Запланировано на: {{ $post->scheduled_at->format('d.m.Y H:i') }}
  102. @else
  103. Выберите дату и время публикации
  104. @endif
  105. </span>
  106. </div>
  107. </label>
  108. </div>
  109. @error('status')
  110. <p class="mt-2 text-sm text-red-600">{{ $message }}</p>
  111. @enderror
  112. </div>
  113. {{-- Дата планирования --}}
  114. <div id="scheduled_date_field" class="{{ old('status', $post->status) == 'scheduled' ? '' : 'hidden' }}">
  115. <label for="scheduled_at" class="block text-sm font-medium text-gray-700 mb-2">
  116. Дата и время публикации
  117. </label>
  118. <input type="datetime-local"
  119. name="scheduled_at"
  120. id="scheduled_at"
  121. value="{{ old('scheduled_at', $post->scheduled_at ? $post->scheduled_at->format('Y-m-d\TH:i') : '') }}"
  122. min="{{ now()->format('Y-m-d\TH:i') }}"
  123. class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-transparent @error('scheduled_at') border-red-500 @enderror">
  124. @error('scheduled_at')
  125. <p class="mt-2 text-sm text-red-600">{{ $message }}</p>
  126. @enderror
  127. </div>
  128. {{-- Информация о комментариях --}}
  129. @if($post->comments()->count() > 0)
  130. <div class="bg-blue-50 border-l-4 border-blue-400 p-4 rounded">
  131. <div class="flex">
  132. <svg class="h-5 w-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20">
  133. <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/>
  134. </svg>
  135. <div class="ml-3">
  136. <p class="text-sm text-blue-700">
  137. У этого поста {{ $post->comments()->count() }} {{ Str::plural('комментарий', $post->comments()->count()) }}
  138. ({{ $post->comments()->approved()->count() }} одобрено,
  139. {{ $post->comments()->pending()->count() }} ожидает модерации)
  140. </p>
  141. </div>
  142. </div>
  143. </div>
  144. @endif
  145. {{-- Кнопки действий --}}
  146. <div class="flex items-center justify-between pt-6 border-t border-gray-200">
  147. <a href="{{ route('posts.show', $post) }}"
  148. class="px-6 py-3 border border-gray-300 rounded-lg text-gray-700 font-medium hover:bg-gray-50">
  149. Отмена
  150. </a>
  151. <button type="submit"
  152. class="px-6 py-3 bg-indigo-600 text-white font-medium rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
  153. Сохранить изменения
  154. </button>
  155. </div>
  156. </form>
  157. </div>
  158. </div>
  159. @push('scripts')
  160. <script>
  161. document.addEventListener('DOMContentLoaded', function() {
  162. const statusRadios = document.querySelectorAll('input[name="status"]');
  163. const scheduledDateField = document.getElementById('scheduled_date_field');
  164. const scheduledAtInput = document.getElementById('scheduled_at');
  165. function toggleScheduledField() {
  166. const selectedStatus = document.querySelector('input[name="status"]:checked').value;
  167. if (selectedStatus === 'scheduled') {
  168. scheduledDateField.classList.remove('hidden');
  169. scheduledAtInput.required = true;
  170. } else {
  171. scheduledDateField.classList.add('hidden');
  172. scheduledAtInput.required = false;
  173. }
  174. }
  175. statusRadios.forEach(radio => {
  176. radio.addEventListener('change', toggleScheduledField);
  177. });
  178. toggleScheduledField();
  179. });
  180. </script>
  181. @endpush
  182. @endsection