feat: complete create and edit views and customize Persian validation messages
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('breadcrumb')
|
||||
<div>
|
||||
<div>
|
||||
<h1 class="page-title fw-medium fs-18 mb-2">ویرایش تور</h1>
|
||||
<div>
|
||||
<nav>
|
||||
<ol class="breadcrumb mb-0">
|
||||
<li class="breadcrumb-item"><a href="{{ route('admin.tours.index') }}">مدیریت تورها</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">ویرایش تور</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid pt-4">
|
||||
|
||||
@if(session('success'))
|
||||
<span style="color: green">{{ session('success') }}</span>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<span style="color: red">{{ session('error') }}</span>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xl-12">
|
||||
<form action="{{ route('admin.tours.update', $tour->id) }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="card custom-card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">مشخصات اصلی تور</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pt-0">
|
||||
<div class="row gy-3">
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">عنوان تور <span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" name="title"
|
||||
value="{{ old('title', $tour->title) }}">
|
||||
@error('title')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">گستره تور <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="tour_scope" id="tourScopeSelect">
|
||||
<option value="">یک مورد را انتخاب کنید</option>
|
||||
@foreach(\App\Enums\Admin\Tour\TourScope::cases() as $scope)
|
||||
<option value="{{ $scope->value }}"
|
||||
{{ old('tour_scope', $tour->tour_scope?->value) == $scope->value ? 'selected' : '' }}>
|
||||
{{ $scope->label() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('tour_scope')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">نوع حمل و نقل / سفر <span
|
||||
class="text-danger">*</span></label>
|
||||
<select class="form-control" name="tour_mode">
|
||||
<option value="">یک مورد را انتخاب کنید</option>
|
||||
@foreach(\App\Enums\Admin\Tour\TourMode::cases() as $mode)
|
||||
<option value="{{ $mode->value }}"
|
||||
{{ old('tour_mode', $tour->tour_mode?->value) == $mode->value ? 'selected' : '' }}>
|
||||
{{ $mode->label() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('tour_mode')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">سبک تور <span class="text-danger">*</span></label>
|
||||
<select class="form-control" name="tour_type">
|
||||
<option value="">یک مورد را انتخاب کنید</option>
|
||||
@foreach(\App\Enums\Admin\Tour\TourType::cases() as $type)
|
||||
<option value="{{ $type->value }}"
|
||||
{{ old('tour_type', $tour->tour_type?->value) == $type->value ? 'selected' : '' }}>
|
||||
{{ $type->label() }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('tour_type')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">شهر مبدا <span class="text-danger">*</span></label>
|
||||
<select class="form-control select2" name="origin_city_id">
|
||||
<option value="">شهر مبدا را انتخاب کنید</option>
|
||||
@foreach($cities as $city)
|
||||
<option value="{{ $city->id }}"
|
||||
{{ old('origin_city_id', $tour->origin_city_id) == $city->id ? 'selected' : '' }}>
|
||||
{{ $city->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('origin_city_id')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6" id="countryWrapper"
|
||||
style="{{ $tour->tour_scope === \App\Enums\Admin\Tour\TourScope::INTERNATIONAL ? '' : 'display:none;' }}">
|
||||
<label class="form-label">کشور مقصد</label>
|
||||
<select class="form-control" id="country_id"
|
||||
{{ $tour->tour_scope === \App\Enums\Admin\Tour\TourScope::INTERNATIONAL ? '' : 'disabled' }}>
|
||||
<option value="">یک مورد را انتخاب کنید</option>
|
||||
@foreach($countries as $country)
|
||||
<option value="{{ $country->id }}"
|
||||
{{ $selectedCountryId == $country->id ? 'selected' : '' }}>
|
||||
{{ $country->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-6">
|
||||
<label class="form-label">شهر مقصد <span class="text-danger">*</span></label>
|
||||
<select class="form-control select2" name="destination_city_id">
|
||||
<option value="">شهر مقصد را انتخاب کنید</option>
|
||||
@foreach($destinationCities as $city)
|
||||
<option value="{{ $city->id }}"
|
||||
{{ old('destination_city_id', $tour->destination_city_id) == $city->id ? 'selected' : '' }}>
|
||||
{{ $city->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('destination_city_id')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-12">
|
||||
<label class="form-label">خلاصه تور</label>
|
||||
<textarea class="form-control" name="summary"
|
||||
rows="2">{{ old('summary', $tour->summary) }}</textarea>
|
||||
@error('summary')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-12">
|
||||
<label class="form-label">توضیحات کامل و برنامه سفر</label>
|
||||
<textarea class="form-control" name="description"
|
||||
rows="5">{{ old('description', $tour->description) }}</textarea>
|
||||
@error('description')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="fw-bold mb-3">اطلاعات ظرفیت / زمانبندی حرکت</h6>
|
||||
<div class="row gy-3">
|
||||
<div class="col-xl-3">
|
||||
<label class="form-label">تاریخ رفت (شروع)</label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
id="startDateInput"
|
||||
class="form-control"
|
||||
name="start_date"
|
||||
value="{{ old(
|
||||
'start_date',$departure?->start_date ? Verta::instance($departure->start_date)->format('Y/m/d H:i') : '' ) }}">
|
||||
@error('start_date')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3">
|
||||
<label class="form-label">تاریخ برگشت (پایان)</label>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
id="endDateInput"
|
||||
class="form-control"
|
||||
name="end_date"
|
||||
value="{{ old('end_date',$departure?->end_date ? Verta::instance($departure->end_date)->format('Y/m/d H:i') : '') }}">
|
||||
@error('end_date')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3">
|
||||
<label class="form-label">قیمت (تومان)</label>
|
||||
<input type="text" class="form-control" name="price"
|
||||
value="{{ old('price', $departure?->price) }}">
|
||||
@error('price')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3">
|
||||
<label class="form-label">ظرفیت مسافر</label>
|
||||
<input type="number" class="form-control" name="capacity"
|
||||
value="{{ old('capacity', $departure?->capacity) }}">
|
||||
@error('capacity')
|
||||
<span class="text-danger small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
<h6 class="fw-bold mb-2">گالری تصاویر فعلی</h6>
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
@forelse($tour->images as $image)
|
||||
<div class="position-relative" style="width:120px;height:120px;">
|
||||
<img src="{{ getFileUrl($image->file_id) }}"
|
||||
class="w-100 h-100 rounded"
|
||||
style="object-fit:cover;"
|
||||
alt="{{ $tour->title }}">
|
||||
@if($image->is_default)
|
||||
<span
|
||||
class="badge bg-primary position-absolute top-0 start-0 m-1">اصلی</span>
|
||||
@endif
|
||||
</div>
|
||||
@empty
|
||||
<span class="text-muted">هیچ تصویری ثبت نشده است.</span>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<h6 class="fw-bold mb-2">افزودن تصاویر جدید</h6>
|
||||
<div class="image-upload-wrapper d-flex flex-wrap gap-2 px-0 pt-0 mt-2"
|
||||
id="imagePreviewContainer" style="border-radius: 8px; padding: 10px;">
|
||||
<label id="uploadPlaceholder" class="upload-placeholder" for="imageInput"
|
||||
style="cursor: pointer; width:150px; height:150px; display: flex; justify-content: center; align-items: center; border: 2px dashed #ccc; border-radius: 8px; padding: 20px; text-align: center;">
|
||||
<div>📷<br><strong>آپلود تصاویر</strong></div>
|
||||
<small style="color:#999;">JPG / PNG / WEBP</small>
|
||||
</label>
|
||||
<input id="imageInput" name="images[]" type="file"
|
||||
accept=".jpg,.png,.jpeg,.webp" multiple style="display:none">
|
||||
</div>
|
||||
@error('images')
|
||||
<span class="text-danger small d-block">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="card-footer text-end">
|
||||
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
|
||||
$('#startDateInput').persianDatepicker({
|
||||
format: 'YYYY/MM/DD HH:mm',
|
||||
timePicker: {
|
||||
enabled: true,
|
||||
meridiem: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
autoClose: false,
|
||||
initialValue: false,
|
||||
initialValueType: 'persian',
|
||||
toolbox: {
|
||||
calendarSwitch: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#endDateInput').persianDatepicker({
|
||||
format: 'YYYY/MM/DD HH:mm',
|
||||
timePicker: {
|
||||
enabled: true,
|
||||
meridiem: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
autoClose: false,
|
||||
initialValue: false,
|
||||
initialValueType: 'persian',
|
||||
toolbox: {
|
||||
calendarSwitch: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function toggleScopeUI() {
|
||||
const scope = $('#tourScopeSelect').val();
|
||||
|
||||
if (scope === '1') {
|
||||
$('#countryWrapper').show();
|
||||
$('#country_id').prop('disabled', false);
|
||||
} else {
|
||||
$('#countryWrapper').hide();
|
||||
$('#country_id').prop('disabled', true).val('');
|
||||
}
|
||||
}
|
||||
|
||||
$('#tourScopeSelect').on('change', toggleScopeUI);
|
||||
|
||||
$('#country_id').on('change', function () {
|
||||
const countryId = $(this).val();
|
||||
|
||||
if (!countryId) return;
|
||||
|
||||
$.get(`/admin/tours/cities-by-country/${countryId}`, function (cities) {
|
||||
let options = '<option value="">شهر را انتخاب کنید</option>';
|
||||
cities.forEach(function (city) {
|
||||
options += `<option value="${city.id}">${city.name}</option>`;
|
||||
});
|
||||
|
||||
$('select[name="destination_city_id"]').html(options).trigger('change');
|
||||
}).fail(function () {
|
||||
alert('خطا در دریافت لیست شهرهای این کشور');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@endsection
|
||||
Reference in New Issue
Block a user