| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- {{--
- Вьюха: Форма создания и редактирования автомобиля (единая для create и edit)
- Создана: 2026-05-06
- Контроллер: Admin\CarController::create() / edit() / store() / update()
- Переменные: $car (Car|null — null при создании), $dictSections (коллекция, индексирована по code)
- Partials (в admin/cars/partials/): _section_main, _section_tech, _section_price,
- _section_desc_opts, _section_photos
- JS (в @push('js')): модели грузятся динамически из $makeModels JSON, select Модель
- заблокирован до выбора Марки; обновление label у custom-file-input
- Плагин: Select2 для полей "Марка" и "Модель"
- --}}
- @extends('admin.layout')
- @section('title', isset($car) ? 'Редактировать автомобиль' : 'Добавить автомобиль')
- @section('content_header')
- <div class="d-flex justify-content-between align-items-center">
- <h1 class="m-0">{{ isset($car) ? 'Редактировать автомобиль #' . $car->id : 'Добавить автомобиль' }}</h1>
- <a href="{{ route('admin.cars.index') }}" class="btn btn-default btn-sm">
- <i class="fas fa-arrow-left"></i> Назад
- </a>
- </div>
- @stop
- @section('breadcrumb')
- <li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Главная</a></li>
- <li class="breadcrumb-item"><a href="{{ route('admin.cars.index') }}">Автомобили</a></li>
- <li class="breadcrumb-item active">{{ isset($car) ? 'Редактировать #' . $car->id : 'Добавить' }}</li>
- @stop
- @section('content')
- @php
- $car = $car ?? null;
- $v = fn($field, $default = null) => old($field, $car?->$field ?? $default);
- $makesList = $dictSections->get('makes');
- $bodyTypes = $dictSections->get('body_types')?->values ?? collect();
- $countries = $dictSections->get('countries')?->values ?? collect();
- $cities = $dictSections->get('cities')?->values ?? collect();
- $colorsExt = $dictSections->get('colors_ext')?->values ?? collect();
- $colorsInt = $dictSections->get('colors_int')?->values ?? collect();
- $engineVols = $dictSections->get('engine_volumes')?->values ?? collect();
- $optionsList = $dictSections->get('options')?->values ?? collect();
- $makes = $makesList?->allValues()->whereNull('parent_id')->with('children')->get() ?? collect();
- // Данные для JS: { "Toyota": ["Camry","RAV4",...], "BMW": [...], ... }
- // Передаём в @push('js') чтобы не гонять модели через data-атрибуты тысячи option-тегов
- $makeModels = $makes->mapWithKeys(fn($m) => [
- $m->value => $m->children->pluck('value')->all(),
- ])->all();
- $platforms = $dictSections->get('platforms')?->values ?? collect();
- $carOptions = is_array($car?->options) ? $car->options : (json_decode($car?->options ?? '[]', true) ?? []);
- @endphp
- <form action="{{ $car ? route('admin.cars.update', $car) : route('admin.cars.store') }}"
- method="POST" enctype="multipart/form-data">
- @csrf
- @if($car) @method('PUT') @endif
- @if($errors->any())
- <div class="alert alert-danger">
- <ul class="mb-0">
- @foreach($errors->all() as $e) <li>{{ $e }}</li> @endforeach
- </ul>
- </div>
- @endif
- @include('admin.cars.partials._section_main')
- @include('admin.cars.partials._section_tech')
- @include('admin.cars.partials._section_price')
- @include('admin.cars.partials._section_desc_opts')
- @include('admin.cars.partials._section_photos')
- <div class="mb-4">
- <button type="submit" class="btn btn-primary">
- <i class="fas fa-save"></i> {{ $car ? 'Сохранить изменения' : 'Добавить автомобиль' }}
- </button>
- <a href="{{ route('admin.cars.index') }}" class="btn btn-default ml-2">Отмена</a>
- </div>
- </form>
- @stop
- @section('plugins.Select2', true)
- @push('js')
- <script>
- (function () {
- // Все модели сгруппированы по марке: { "Toyota": ["Camry","RAV4",...], ... }
- var MODELS_BY_MAKE = @json($makeModels);
- // Значения для восстановления при редактировании (old() или $car->*)
- var initialMake = @json($v('make', ''));
- var initialModel = @json($v('model', ''));
- var $selMake = $('#sel-make');
- var $selModel = $('#sel-model');
- /**
- * Перестраивает #sel-model под выбранную марку.
- * make — строка, пустая = марка не выбрана
- * selectModel — какую модель выбрать после перестройки (для edit-формы)
- */
- function populateModels(make, selectModel) {
- // Уничтожаем Select2 если уже инициализирован
- if ($selModel.data('select2')) {
- $selModel.select2('destroy');
- }
- var sel = $selModel[0];
- if (!make) {
- // Марка не выбрана — блокируем и показываем подсказку
- sel.innerHTML = '<option value="">— сначала выберите марку —</option>';
- sel.disabled = true;
- } else {
- // Марка выбрана — строим список моделей только для неё
- sel.disabled = false;
- sel.innerHTML = '<option value="">— выберите модель —</option>';
- var models = MODELS_BY_MAKE[make] || [];
- models.forEach(function (model) {
- var opt = document.createElement('option');
- opt.value = model;
- opt.textContent = model;
- if (model === selectModel) opt.selected = true;
- sel.appendChild(opt);
- });
- }
- // Инициализируем Select2 обратно
- $selModel.select2({ theme: 'bootstrap4', width: '100%' });
- }
- // При смене марки — сбрасываем выбор модели и перестраиваем список
- $selMake.on('change', function () {
- populateModels(this.value, '');
- });
- // Инициализация при загрузке страницы:
- // для create — марка пуста, select заблокирован;
- // для edit — восстанавливаем марку и модель
- $(function () {
- populateModels(initialMake, initialModel);
- // Обновление подписи file input при выборе файла
- document.querySelectorAll('.custom-file-input').forEach(function (input) {
- input.addEventListener('change', function () {
- var label = this.nextElementSibling;
- label.textContent = this.files.length > 1
- ? this.files.length + ' файлов выбрано'
- : (this.files[0] ? this.files[0].name : 'Выберите файл...');
- });
- });
- });
- })();
- </script>
- @endpush
|