feat: final updates

This commit is contained in:
2026-08-22 11:11:28 -07:00
parent 618a3d4cd9
commit d4bb1b9414
43 changed files with 1136 additions and 375 deletions
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\EditProfilePostRequest; use App\Http\Requests\EditProfilePostRequest;
use App\Models\Province;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
@@ -11,10 +12,13 @@ class EditProfileController extends Controller
{ {
public function index() public function index()
{ {
$user = Auth::user(); $user = Auth::user();
return view('account.setting', compact('user')); $user->load(['province', 'city']);
$provinces = Province::all();
return view('account.setting', compact('user', 'provinces'));
} }
public function post(EditProfilePostRequest $request) public function post(EditProfilePostRequest $request)
@@ -8,6 +8,7 @@ use Illuminate\Http\Request;
class ActivityLogController extends Controller class ActivityLogController extends Controller
{ {
public function index(Request $request) public function index(Request $request)
{ {
$logs = ActivityLog::query() $logs = ActivityLog::query()
@@ -207,12 +207,11 @@ class AdminController extends Controller
public function destroy(Admin $admin) public function destroy(Admin $admin)
{ {
AdminPermission::where('admin_id', $admin->id)->delete();
$admin->delete(); $admin->delete();
return redirect() return redirect()->route('admin.admins.index')
->route('admin.admins.index') ->with('success', 'ادمین با موفقیت حذف شد.');
->withErrors([
'success' => 'عملیات با موفقیت انجام شد'
]);
} }
} }
@@ -0,0 +1,88 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\City;
use App\Models\Province;
use Illuminate\Http\Request;
class CityController extends Controller
{
public function index(Request $request)
{
$cities = City::query()
->with('province')
->when($request->filled('search'), function ($query) use ($request) {
$query->where('name', 'LIKE', '%' . $request->input('search') . '%');
})
->orderByDesc('created_at')
->paginate();
return view('admin.cities.index', compact('cities'));
}
public function create()
{
$provinces = Province::all();
return view('admin.cities.create', compact('provinces'));
}
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'max:255'],
'province_id' => ['required', 'exists:provinces,id'],
]);
City::create([
'name' => $request->input('name'),
'province_id' => $request->input('province_id'),
]);
return redirect()
->route('admin.cities.index')
->with('success', 'شهرستان با موفقیت ایجاد شد');
}
public function edit(City $city)
{
$provinces = Province::all();
return view('admin.cities.edit', compact('city', 'provinces'));
}
public function update(Request $request, City $city)
{
$request->validate([
'name' => ['required', 'max:255'],
'province_id' => ['required', 'exists:provinces,id'],
]);
$city->update([
'name' => $request->input('name'),
'province_id' => $request->input('province_id'),
]);
return redirect()
->route('admin.cities.index')
->with('success', 'شهرستان با موفقیت ویرایش شد');
}
public function destroy(City $city)
{
if ($city->airports()->exists()) {
return back()->withErrors([
'error' => 'این شهرستان دارای فرودگاه است و قابل حذف نیست.'
]);
}
$city->delete();
return redirect()->route('admin.cities.index')->withErrors([
'success', 'شهرستان با موفقیت حذف شد'
]);
}
}
@@ -110,6 +110,12 @@ class FlightController extends Controller
'after_or_equal:today', 'after_or_equal:today',
], ],
'return_time' => [
'nullable',
'date',
'after:departure_time',
],
'departure_airport_id' => [ 'departure_airport_id' => [
'required', 'required',
'exists:airports,id', 'exists:airports,id',
@@ -175,6 +181,7 @@ class FlightController extends Controller
'airline_id' => $request->input('airline_id'), 'airline_id' => $request->input('airline_id'),
'flight_type' => $request->input('flight_type'), 'flight_type' => $request->input('flight_type'),
'departure_time' => $request->input('departure_time'), 'departure_time' => $request->input('departure_time'),
'return_time' => $request->input('return_time'),
'departure_airport_id' => $request->input('departure_airport_id'), 'departure_airport_id' => $request->input('departure_airport_id'),
'arrival_airport_id' => $request->input('arrival_airport_id'), 'arrival_airport_id' => $request->input('arrival_airport_id'),
'price' => $request->input('price'), 'price' => $request->input('price'),
@@ -232,7 +239,7 @@ class FlightController extends Controller
public function update(Request $request, Flight $flight) public function update(Request $request, Flight $flight)
{ {
$before = $flight->only([ $before = $flight->only([
'title', 'airline_id', 'flight_type', 'departure_time', 'title', 'airline_id', 'flight_type', 'departure_time', 'return_time',
'departure_airport_id', 'arrival_airport_id', 'price', 'departure_airport_id', 'arrival_airport_id', 'price',
'summary', 'capacity', 'description', 'status', 'summary', 'capacity', 'description', 'status',
]); ]);
@@ -266,6 +273,12 @@ class FlightController extends Controller
'after_or_equal:today', 'after_or_equal:today',
], ],
'return_time' => [
'nullable',
'date',
'after:departure_time',
],
'departure_airport_id' => [ 'departure_airport_id' => [
'required', 'required',
'exists:airports,id', 'exists:airports,id',
@@ -330,6 +343,7 @@ class FlightController extends Controller
'airline_id' => $request->input('airline_id'), 'airline_id' => $request->input('airline_id'),
'flight_type' => $request->input('flight_type'), 'flight_type' => $request->input('flight_type'),
'departure_time' => $request->input('departure_time'), 'departure_time' => $request->input('departure_time'),
'return_time' => $request->input('return_time'),
'departure_airport_id' => $request->input('departure_airport_id'), 'departure_airport_id' => $request->input('departure_airport_id'),
'arrival_airport_id' => $request->input('arrival_airport_id'), 'arrival_airport_id' => $request->input('arrival_airport_id'),
'price' => $request->input('price'), 'price' => $request->input('price'),
@@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Province;
use Illuminate\Http\Request;
class ProvinceController extends Controller
{
public function index(Request $request)
{
$provinces = Province::query()
->when($request->filled('search'), function ($query) use ($request) {
$query->where('name', 'LIKE', '%' . $request->input('search') . '%');
})
->withCount('cities')
->orderByDesc('created_at')
->paginate();
return view('admin.provinces.index', compact('provinces'));
}
public function create()
{
return view('admin.provinces.create');
}
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'max:255', 'unique:provinces,name'],
]);
Province::create([
'name' => $request->input('name'),
]);
return redirect()
->route('admin.provinces.index')
->with('success', 'استان با موفقیت ایجاد شد');
}
public function edit(Province $province)
{
return view('admin.provinces.edit', compact('province'));
}
public function update(Request $request, Province $province)
{
$request->validate([
'name' => ['required', 'max:255', 'unique:provinces,name,' . $province->id],
]);
$province->update([
'name' => $request->input('name'),
]);
return redirect()
->route('admin.provinces.index')
->with('success', 'استان با موفقیت ویرایش شد');
}
public function destroy(Province $province)
{
if ($province->cities()->exists()) {
return back()->withErrors([
'error' => 'این استان دارای شهرستان است و قابل حذف نیست.'
]);
}
$province->delete();
return redirect()->route('admin.provinces.index')->withErrors([
'success' => 'استان با موفقیت حذف شد'
]);
}
}
+19 -3
View File
@@ -7,6 +7,7 @@ use App\Http\Requests\Admin\Users\UserEditRequest;
use App\Http\Requests\EditProfilePostRequest; use App\Http\Requests\EditProfilePostRequest;
use App\Models\Booking; use App\Models\Booking;
use App\Models\Order; use App\Models\Order;
use App\Models\Province;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -20,6 +21,7 @@ class UserController extends Controller
{ {
$users = User::query() $users = User::query()
->with(['province', 'city', 'file'])
->when($request->filled('search'), function (Builder $query) use ($request){ ->when($request->filled('search'), function (Builder $query) use ($request){
$search = $request->input('search'); $search = $request->input('search');
@@ -61,7 +63,11 @@ class UserController extends Controller
public function edit(User $user) public function edit(User $user)
{ {
return view('admin.users.edit', compact('user')); $user->load(['province', 'city', 'file']);
$provinces = Province::all();
return view('admin.users.edit', compact('user', 'provinces'));
} }
public function update(User $user, UserEditRequest $request) public function update(User $user, UserEditRequest $request)
@@ -71,7 +77,9 @@ class UserController extends Controller
'first_name', 'first_name',
'last_name', 'last_name',
'mobile', 'mobile',
'email' 'email',
'province_id',
'city_id',
]); ]);
if ($request->filled('password')){ if ($request->filled('password')){
@@ -86,9 +94,17 @@ class UserController extends Controller
public function destroy(User $user) public function destroy(User $user)
{ {
if ($user->bookings()->exists()) {
return back()->withErrors([
'error' => 'این کاربر دارای رزرو است و قابل حذف نیست.'
]);
}
$user->delete(); $user->delete();
return redirect()->route('admin.users.index'); return redirect()->route('admin.users.index')->withErrors([
'success'=> 'کاربر با موفقیت حذف شد'
]);
} }
} }
@@ -6,6 +6,7 @@ use App\Enums\UserStatus;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\RegisterPostRequest; use App\Http\Requests\Auth\RegisterPostRequest;
use App\Models\File; use App\Models\File;
use App\Models\Province;
use App\Models\User; use App\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@@ -19,7 +20,9 @@ class RegisterController extends Controller
$withoutHeader = true; $withoutHeader = true;
$withoutFooter = true; $withoutFooter = true;
return view('auth.register', compact('withoutHeader', 'withoutFooter')); $provinces = Province::all();
return view('auth.register', compact('withoutHeader', 'withoutFooter', 'provinces'));
} }
@@ -79,14 +79,14 @@ class RegisterPostRequest extends FormRequest
'max:800', 'max:800',
], ],
'province' => [ 'province_id' => [
'nullable', 'nullable',
'string', 'exists:provinces,id',
], ],
'city' => [ 'city_id' => [
'nullable', 'nullable',
'string', 'exists:cities,id',
], ],
'password' => [ 'password' => [
@@ -105,7 +105,8 @@ class RegisterPostRequest extends FormRequest
'required', 'required',
'max:150', 'max:150',
'email', 'email',
'unique:users,mobile', ] 'unique:users,email',
]
]; ];
} }
} }
+1 -1
View File
@@ -48,7 +48,7 @@ class EditProfilePostRequest extends FormRequest
'max:100', 'max:100',
], ],
'city' => [ 'cities' => [
'nullable', 'nullable',
'string', 'string',
'max:100', 'max:100',
+1 -1
View File
@@ -18,7 +18,7 @@ use Illuminate\Database\Eloquent\Model;
* @property string $country * @property string $country
* @property string $code * @property string $code
* *
* @property City $city * @property City $cities
* @property Collection|Flight[] $flights * @property Collection|Flight[] $flights
* *
* @package App\Models * @package App\Models
+5 -1
View File
@@ -24,7 +24,6 @@ use Illuminate\Database\Eloquent\Model;
class City extends Model class City extends Model
{ {
protected $table = 'cities'; protected $table = 'cities';
public $timestamps = false;
public static $snakeAttributes = false; public static $snakeAttributes = false;
protected $casts = [ protected $casts = [
@@ -45,4 +44,9 @@ class City extends Model
{ {
return $this->hasMany(User::class); return $this->hasMany(User::class);
} }
public function airports()
{
return $this->hasMany(Airport::class);
}
} }
+4 -2
View File
@@ -31,7 +31,6 @@ use Illuminate\Database\Eloquent\Model;
* @property int $status * @property int $status
* @property Carbon $created_at * @property Carbon $created_at
* @property Carbon $updated_at * @property Carbon $updated_at
*
* @property Airline $airline * @property Airline $airline
* @property File|null $file * @property File|null $file
* @property Airport $airport * @property Airport $airport
@@ -53,7 +52,8 @@ class Flight extends Model
'price' => 'float', 'price' => 'float',
'capacity' => 'int', 'capacity' => 'int',
'views' => 'int', 'views' => 'int',
'status' => FlightStatus::class 'status' => FlightStatus::class,
'return_time' => 'datetime',
]; ];
protected $fillable = [ protected $fillable = [
@@ -72,6 +72,8 @@ class Flight extends Model
'status', 'status',
'created_by', 'created_by',
'updated_by', 'updated_by',
'return_time',
]; ];
protected $hidden = [ protected $hidden = [
-1
View File
@@ -23,7 +23,6 @@ use Illuminate\Database\Eloquent\Model;
class Province extends Model class Province extends Model
{ {
protected $table = 'provinces'; protected $table = 'provinces';
public $timestamps = false;
public static $snakeAttributes = false; public static $snakeAttributes = false;
protected $fillable = [ protected $fillable = [
+13 -4
View File
@@ -30,7 +30,7 @@ use Illuminate\Foundation\Auth\User as Authenticated;
* @property string $username * @property string $username
* @property string $password * @property string $password
* @property string $province * @property string $province
* @property string $city * @property string $cities
* @property int $status * @property int $status
* @property Carbon $created_at * @property Carbon $created_at
* @property Carbon $updated_at * @property Carbon $updated_at
@@ -70,12 +70,11 @@ class User extends Authenticated
'file_id', 'file_id',
'username', 'username',
'password', 'password',
'province', 'province_id',
'city', 'city_id',
'status', 'status',
'deleted' 'deleted'
]; ];
public function file() public function file()
{ {
return $this->belongsTo(File::class); return $this->belongsTo(File::class);
@@ -95,4 +94,14 @@ class User extends Authenticated
{ {
return $this->hasMany(Wishlist::class); return $this->hasMany(Wishlist::class);
} }
public function province()
{
return $this->belongsTo(Province::class);
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
} }
+1 -1
View File
@@ -22,7 +22,7 @@ return [
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may configure all of the mailers used by your application plus | Here you may configure all of the mailers used by your application plus
| their respective settings. Several examples have been configured for | their respective activity-logs. Several examples have been configured for
| you and you are free to add your own as your application requires. | you and you are free to add your own as your application requires.
| |
| Laravel supports a variety of mail "transport" drivers that can be used | Laravel supports a variety of mail "transport" drivers that can be used
+1 -1
View File
@@ -197,7 +197,7 @@ return [
'last_name' => 'نام خانوادگی', 'last_name' => 'نام خانوادگی',
'password' => 'گذرواژه', 'password' => 'گذرواژه',
'password_confirmation' => 'تاییدیه گذرواژه', 'password_confirmation' => 'تاییدیه گذرواژه',
'city' => 'شهر', 'cities' => 'شهر',
'state' => 'استان', 'state' => 'استان',
'country' => 'کشور', 'country' => 'کشور',
'address' => 'آدرس', 'address' => 'آدرس',
+1 -1
View File
@@ -422,7 +422,7 @@ Version : 1.1
$('.flights-search .search-form-return').show(); $('.flights-search .search-form-return').show();
$('.have-to-clone').hide(); $('.have-to-clone').hide();
$('.another-item').remove(); $('.another-item').remove();
} else if (ft === "multi-city") { } else if (ft === "multi-cities") {
$('.flights-search .search-form-return').hide(); $('.flights-search .search-form-return').hide();
$('.have-to-clone').show(); $('.have-to-clone').show();
$('.another-item').remove(); $('.another-item').remove();
+49 -6
View File
@@ -65,9 +65,18 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label>استان</label> <label>استان</label>
<input type="text" name="province_id" class="form-control" <select name="province_id" id="province_id" class="form-control">
value="{{ old('province', $user->province) }}" placeholder="استان"> <option value="">استان را انتخاب کنید</option>
@error('province') @foreach($provinces as $province)
<option
value="{{ $province->id }}"
@selected(old('province_id', $user->province_id) == $province->id)
>
{{ $province->name }}
</option>
@endforeach
</select>
@error('province_id')
<span class="text-danger">{{ $message }}</span> <span class="text-danger">{{ $message }}</span>
@enderror @enderror
</div> </div>
@@ -75,9 +84,16 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label>شهر</label> <label>شهر</label>
<input type="text" name="city" class="form-control" <select name="city_id" id="city_id" class="form-control">
value="{{ old('city', $user->city) }}" placeholder="شهر"> @if($user->city)
@error('city') <option value="{{ $user->city->id }}" selected>
{{ $user->city->name }}
</option>
@else
<option value="">ابتدا استان را انتخاب کنید</option>
@endif
</select>
@error('city_id')
<span class="text-danger">{{ $message }}</span> <span class="text-danger">{{ $message }}</span>
@enderror @enderror
</div> </div>
@@ -115,4 +131,31 @@
</div> </div>
</div> </div>
<script>
document.getElementById('province_id').addEventListener('change', function () {
const provinceId = this.value;
const citySelect = document.getElementById('city_id');
citySelect.innerHTML = '<option value="">در حال بارگذاری...</option>';
if (!provinceId) {
citySelect.innerHTML = '<option value="">ابتدا استان را انتخاب کنید</option>';
return;
}
fetch(`{{ route('account.cities-by-province', ':province') }}`.replace(':province', provinceId))
.then(response => response.json())
.then(cities => {
citySelect.innerHTML = '<option value="">شهرستان خود را انتخاب کنید</option>';
cities.forEach(city => {
const option = document.createElement('option');
option.value = city.id;
option.textContent = city.name;
citySelect.appendChild(option);
});
});
});
</script>
@endsection @endsection
@@ -61,26 +61,110 @@
<td> <td>
@if($log->event === 'updated' && $log->changes) @if($log->event === 'updated' && $log->changes)
<ul class="mb-0 ps-3"> <ul class="mb-0 ps-3">
@foreach($log->changes['after'] as $field => $newValue) @foreach($log->changes['after'] as $field => $newValue)
@if(($log->changes['before'][$field] ?? null) != $newValue) @if(($log->changes['before'][$field] ?? null) != $newValue)
@php
$oldValue = $log->changes['before'][$field] ?? null;
@endphp
<li> <li>
{{ $field }}: @switch($field)
«{{ $log->changes['before'][$field] ?? '—' }}»
@case('title')
عنوان:
«{{ $oldValue }}»
&larr; &larr;
«{{ $newValue }}» «{{ $newValue }}»
@break
@case('status')
وضعیت:
«{{ $oldValue == 1 ? 'فعال' : 'غیرفعال' }}»
&larr;
«{{ $newValue == 1 ? 'فعال' : 'غیرفعال' }}»
@break
@case('price')
قیمت:
«{{ number_format($oldValue) }}»
&larr;
«{{ number_format($newValue) }}»
@break
@case('capacity')
ظرفیت:
«{{ $oldValue }} نفر»
&larr;
«{{ $newValue }} نفر»
@break
@case('summary')
خلاصه:
«{{ $oldValue }}»
&larr;
«{{ $newValue }}»
@break
@case('description')
توضیحات:
«{{ $oldValue }}»
&larr;
«{{ $newValue }}»
@break
@case('flight_type')
نوع پرواز:
«{{ $oldValue == 1 ? 'یک‌طرفه' : 'رفت و برگشت' }}
»
&larr;
«{{ $newValue == 1 ? 'یک‌طرفه' : 'رفت و برگشت' }}
»
@break
@case('departure_time')
زمان رفت:
«{{ $oldValue ? \Carbon\Carbon::parse($oldValue)->format('Y/m/d H:i') : '—' }}
»
به
«{{ $newValue ? \Carbon\Carbon::parse($newValue)->format('Y/m/d H:i') : '—' }}
»
@break
@case('return_time')
زمان برگشت:
«{{ $oldValue ? \Carbon\Carbon::parse($oldValue)->format('Y/m/d H:i') : '—' }}
»
به
«{{ $newValue ? \Carbon\Carbon::parse($newValue)->format('Y/m/d H:i') : '—' }}
»
@break
@default
{{ $field }}:
«{{ $oldValue ?? '—' }}»
&larr;
«{{ $newValue }}»
@endswitch
</li> </li>
@endif @endif
@endforeach @endforeach
</ul> </ul>
@elseif($log->event === 'created') @elseif($log->event === 'created')
ایجاد رکورد جدید ایجاد رکورد جدید
@else @else
حذف رکورد حذف رکورد
@endif @endif
</td> </td>
<td> <td>
{{ verta($log->created_at)->format('Y/m/d H:i') }} {{ $log->created_at->toJalali()->format('Y/m/d H:i') }}
</td> </td>
</tr> </tr>
@empty @empty
@@ -124,8 +124,6 @@
</div> </div>
</div> </div>
{{-- مدیریت تور --}}
<div class="col-xl-6"> <div class="col-xl-6">
<label class="form-label fw-semibold">مدیریت تور</label> <label class="form-label fw-semibold">مدیریت تور</label>
@@ -168,50 +166,6 @@
</div> </div>
{{-- مدیریت رزرو --}}
<div class="col-xl-6">
<label class="form-label fw-semibold">مدیریت رزرو</label>
<div class="d-flex gap-4 flex-wrap">
<div class="form-check">
<input class="form-check-input"
type="checkbox"
name="permissions[booking_view]"
value="1"
id="booking_view">
<label class="form-check-label" for="booking_view">
مشاهده رزرو
</label>
</div>
<div class="form-check">
<input class="form-check-input"
type="checkbox"
name="permissions[booking_edit]"
value="1"
id="booking_edit">
<label class="form-check-label" for="booking_edit">
ویرایش رزرو
</label>
</div>
<div class="form-check">
<input class="form-check-input"
type="checkbox"
name="permissions[booking_delete]"
value="1"
id="booking_delete">
<label class="form-check-label" for="booking_delete">
حذف رزرو
</label>
</div>
</div>
</div>
{{-- مدیریت کاربران --}}
<div class="col-xl-6"> <div class="col-xl-6">
<label class="form-label fw-semibold">مدیریت کاربران</label> <label class="form-label fw-semibold">مدیریت کاربران</label>
@@ -254,7 +208,6 @@
</div> </div>
{{-- مدیریت مدیران --}}
<div class="col-xl-6"> <div class="col-xl-6">
<label class="form-label fw-semibold">مدیریت مدیران</label> <label class="form-label fw-semibold">مدیریت مدیران</label>
@@ -124,7 +124,6 @@
<div class="card-body"> <div class="card-body">
<div class="row gy-4"> <div class="row gy-4">
{{-- مدیریت پروازها --}}
<div class="col-xl-3 col-lg-6"> <div class="col-xl-3 col-lg-6">
<h6 class="fw-semibold mb-3">مدیریت پروازها</h6> <h6 class="fw-semibold mb-3">مدیریت پروازها</h6>
@@ -169,7 +168,6 @@
</div> </div>
{{-- مدیریت تورها --}}
<div class="col-xl-3 col-lg-6"> <div class="col-xl-3 col-lg-6">
<h6 class="fw-semibold mb-3">مدیریت تورها</h6> <h6 class="fw-semibold mb-3">مدیریت تورها</h6>
@@ -214,52 +212,6 @@
</div> </div>
{{-- مدیریت رزروها --}}
<div class="col-xl-3 col-lg-6">
<h6 class="fw-semibold mb-3">مدیریت رزروها</h6>
<div class="form-check mb-2">
<input
class="form-check-input"
type="checkbox"
name="permissions[booking_view]"
value="1"
@checked($admin->permission?->booking_view)
>
<label class="form-check-label">
مشاهده رزروها
</label>
</div>
<div class="form-check mb-2">
<input
class="form-check-input"
type="checkbox"
name="permissions[booking_edit]"
value="1"
@checked($admin->permission?->booking_edit)
>
<label class="form-check-label">
ویرایش رزرو
</label>
</div>
<div class="form-check mb-2">
<input
class="form-check-input"
type="checkbox"
name="permissions[booking_delete]"
value="1"
@checked($admin->permission?->booking_delete)
>
<label class="form-check-label">
حذف رزرو
</label>
</div>
</div>
{{-- مدیریت کاربران --}}
<div class="col-xl-3 col-lg-6"> <div class="col-xl-3 col-lg-6">
<h6 class="fw-semibold mb-3">مدیریت کاربران</h6> <h6 class="fw-semibold mb-3">مدیریت کاربران</h6>
@@ -304,7 +256,6 @@
</div> </div>
{{-- مدیریت مدیران --}}
<div class="col-xl-3 col-lg-6"> <div class="col-xl-3 col-lg-6">
<h6 class="fw-semibold mb-3">مدیریت مدیران</h6> <h6 class="fw-semibold mb-3">مدیریت مدیران</h6>
@@ -0,0 +1,46 @@
@extends('admin.layouts.app')
@section('content')
<div class="container-fluid pt-4">
<form action="{{ route('admin.cities.store') }}" method="POST">
@csrf
<div class="card custom-card">
<div class="card-header">
<div class="card-title">افزودن شهرستان</div>
</div>
<div class="card-body row gy-3">
<div class="col-xl-6">
<label class="form-label">نام شهرستان</label>
<input type="text" class="form-control" name="name" value="{{ old('name') }}">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">استان</label>
<select class="form-control" name="province_id">
<option value="">یک استان انتخاب کنید</option>
@foreach($provinces as $province)
<option value="{{ $province->id }}" @selected(old('province_id') == $province->id)>
{{ $province->name }}
</option>
@endforeach
</select>
@error('province_id')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ثبت</button>
</div>
</div>
</form>
</div>
@endsection
@@ -0,0 +1,47 @@
@extends('admin.layouts.app')
@section('content')
<div class="container-fluid pt-4">
<form action="{{ route('admin.cities.update', $city) }}" method="POST">
@csrf
@method('put')
<div class="card custom-card">
<div class="card-header">
<div class="card-title">ویرایش شهرستان</div>
</div>
<div class="card-body row gy-3">
<div class="col-xl-6">
<label class="form-label">نام شهرستان</label>
<input type="text" class="form-control" name="name" value="{{ old('name', $city->name) }}">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">استان</label>
<select class="form-control" name="province_id">
<option value="">یک استان انتخاب کنید</option>
@foreach($provinces as $province)
<option value="{{ $province->id }}" @selected(old('province_id', $city->province_id) == $province->id)>
{{ $province->name }}
</option>
@endforeach
</select>
@error('province_id')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</div>
</form>
</div>
@endsection
+57 -2
View File
@@ -1,3 +1,58 @@
@extends('admin.layouts.app') @extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت شهرها</h1></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-5"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجوی شهر"></div><div class="col-md-3"><select class="form-control" name="province_id"><option value="">همه استان‌ها</option>@foreach(($provinces ?? []) as $province)<option value="{{ $province->id }}" @selected((string)request('province_id')===(string)$province->id)>{{ $province->name }}</option>@endforeach</select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.cities.create') }}" class="btn btn-primary w-100">شهر جدید</a></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table"><thead><tr><th>#</th><th>شهر</th><th>استان</th><th>عملیات</th></tr></thead><tbody>@forelse(($cities ?? []) as $city)<tr><td>{{ $city->id }}</td><td>{{ $city->name }}</td><td>{{ $city->province->name ?? '-' }}</td><td><a href="{{ route('admin.cities.edit',$city) }}" class="btn btn-secondary-light btn-sm">ویرایش</a><form class="d-inline" method="POST" action="{{ route('admin.cities.destroy',$city) }}" onsubmit="return confirm('حذف شهر؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="4" class="text-center text-muted py-5">شهری ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($cities ?? collect())->links() }}</div>@endsection @section('content')
<div class="container-fluid pt-4">
<div class="card custom-card">
<div class="card-header d-flex align-items-center justify-content-between">
<div class="card-title">مدیریت شهرستان‌ها</div>
<a href="{{ route('admin.cities.create') }}" class="btn btn-primary btn-sm">
افزودن شهرستان
</a>
</div>
<div class="card-body pt-0">
<div class="table-responsive">
<table class="table text-nowrap">
<thead>
<tr>
<th>#</th>
<th>نام شهرستان</th>
<th>استان</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@forelse($cities as $city)
<tr>
<td>{{ $city->id }}</td>
<td>{{ $city->name }}</td>
<td>{{ optional($city->province)->name ?? '—' }}</td>
<td>
<a href="{{ route('admin.cities.edit', $city) }}" class="btn btn-sm btn-warning">
ویرایش
</a>
<form action="{{ route('admin.cities.destroy', $city) }}" method="POST" class="d-inline">
@csrf
@method('delete')
<button type="submit" class="btn btn-sm btn-danger"
onclick="return confirm('آیا مطمئن هستید؟')">
حذف
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center">شهرستانی ثبت نشده است</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{ $cities->links() }}
</div>
</div>
</div>
@endsection
+2 -2
View File
@@ -231,8 +231,8 @@
<tbody> <tbody>
@forelse($recentVisits as $visit) @forelse($recentVisits as $visit)
<tr> <tr>
<td>{{ verta($visit->created_at)->format('Y/m/d') }}</td> <td>{{ $visit->created_at->toJalali()->format('Y/m/d') }}</td>
<td>{{ verta($visit->created_at)->format('H:i') }}</td> <td>{{ $visit->created_at->toJalali()->format('H:i') }}</td>
<td>{{ $visit->ip_address ?? '—' }}</td> <td>{{ $visit->ip_address ?? '—' }}</td>
</tr> </tr>
@empty @empty
@@ -203,6 +203,35 @@
@enderror @enderror
</div> </div>
<!-- Return Time -->
<div class="col-xl-6">
<label class="form-label">زمان برگشت (اختیاری)</label>
<input
type="text"
class="form-control"
name="return_time_jalali"
id="return_time_jalali"
data-jdp
data-jdp-target-value-input="#return_time_gregorian"
data-jdp-target-value-type="gregorian"
autocomplete="off"
placeholder="مثلاً 1403/06/02 18:00"
value="{{ old('return_time_jalali') }}"
>
<input
type="hidden"
name="return_time"
id="return_time_gregorian"
value="{{ old('return_time') }}"
>
@error('return_time')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Price --> <!-- Price -->
<div class="col-xl-6"> <div class="col-xl-6">
+30 -1
View File
@@ -172,7 +172,7 @@
data-jdp-target-value-type="gregorian" data-jdp-target-value-type="gregorian"
autocomplete="off" autocomplete="off"
placeholder="مثلاً 1403/05/29 14:30" placeholder="مثلاً 1403/05/29 14:30"
value="{{ old('departure_time_jalali', $flight->departure_time ? verta($flight->departure_time)->format('Y/m/d H:i') : '') }}" value="{{ old('departure_time_jalali', $flight->departure_time->toJalali()->format('Y/m/d H:i')) }}"
> >
<input <input
@@ -187,6 +187,35 @@
@enderror @enderror
</div> </div>
<!-- Return Time -->
<div class="col-xl-6">
<label class="form-label">زمان برگشت (اختیاری)</label>
<input
type="text"
class="form-control"
name="return_time_jalali"
id="return_time_jalali"
data-jdp
data-jdp-target-value-input="#return_time_gregorian"
data-jdp-target-value-type="gregorian"
autocomplete="off"
placeholder="مثلاً 1403/06/02 18:00"
value="{{ old('return_time_jalali', $flight->return_time ? $flight->return_time->toJalali()->format('Y/m/d H:i') : '') }}"
>
<input
type="hidden"
name="return_time"
id="return_time_gregorian"
value="{{ old('return_time', optional($flight->return_time)->format('Y-m-d H:i:s')) }}"
>
@error('return_time')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Price --> <!-- Price -->
<div class="col-xl-6"> <div class="col-xl-6">
<label class="form-label">قیمت</label> <label class="form-label">قیمت</label>
@@ -138,6 +138,7 @@
<th>ایرلاین</th> <th>ایرلاین</th>
<th>نوع پرواز</th> <th>نوع پرواز</th>
<th>زمان حرکت</th> <th>زمان حرکت</th>
<th>زمان برگشت</th>
<th>مبدا</th> <th>مبدا</th>
<th>مقصد</th> <th>مقصد</th>
<th>قیمت</th> <th>قیمت</th>
@@ -214,7 +215,11 @@
</td> </td>
<td> <td>
{{ $flight->departure_time->toJalali()->format('H:i Y-m-d') }} {{ $flight->departure_time->toJalali()->format('H:i Y-m-d') ?? '—' }}
</td>
<td>
{{ $flight->return_time ? $flight->return_time->toJalali()->format('H:i Y-m-d') : '—' }}
</td> </td>
<td> <td>
@@ -31,7 +31,7 @@
</div> </div>
<ul class="main-menu mx-0"> <ul class="main-menu mx-0">
<!-- Start::slide --> <!-- Start::slide -->
<!-- داشبورد -->
<li class="slide"> <li class="slide">
<a href="{{route('admin.dashboard.index')}}" <a href="{{route('admin.dashboard.index')}}"
class="side-menu__item {{activeAdminSidebar('admin.dashboard.index')}}"> class="side-menu__item {{activeAdminSidebar('admin.dashboard.index')}}">
@@ -40,7 +40,6 @@
</a> </a>
</li> </li>
<!-- مدیریت کاربران -->
@if(auth('admin')->user()->permission?->admin_view) @if(auth('admin')->user()->permission?->admin_view)
<li class="slide"> <li class="slide">
<a href="{{ route('admin.users.index') }}" <a href="{{ route('admin.users.index') }}"
@@ -51,7 +50,6 @@
</li> </li>
@endif @endif
<!-- مدیریت تورها -->
@if(auth('admin')->user()->permission?->admin_view) @if(auth('admin')->user()->permission?->admin_view)
<li class="slide"> <li class="slide">
<a href="{{ route('admin.tours.index') }}" <a href="{{ route('admin.tours.index') }}"
@@ -62,7 +60,6 @@
</li> </li>
@endif @endif
<!-- مدیریت پروازها -->
@if(auth('admin')->user()->permission?->admin_view) @if(auth('admin')->user()->permission?->admin_view)
<li class="slide"> <li class="slide">
<a href="{{ route('admin.flights.index') }}" <a href="{{ route('admin.flights.index') }}"
@@ -74,7 +71,6 @@
@endif @endif
<!-- مدیریت مدیران -->
@if(auth('admin')->user()->permission?->admin_view) @if(auth('admin')->user()->permission?->admin_view)
<li class="slide active"> <li class="slide active">
<a href="{{route('admin.admins.index')}}" <a href="{{route('admin.admins.index')}}"
@@ -85,7 +81,23 @@
</li> </li>
@endif @endif
<!-- مدیریت اطلاعات -->
<li class="slide">
<a href="{{ route('admin.provinces.index') }}"
class="side-menu__item {{activeAdminSidebar(['admin.provinces.index', 'admin.provinces.create', 'admin.provinces.edit'])}}">
<i class="ri-map-pin-line side-menu__icon"></i>
<span class="side-menu__label">مدیریت استان‌ها</span>
</a>
</li>
<li class="slide">
<a href="{{ route('admin.cities.index') }}"
class="side-menu__item {{activeAdminSidebar(['admin.cities.index', 'admin.cities.create', 'admin.cities.edit'])}}">
<i class="ri-building-line side-menu__icon"></i>
<span class="side-menu__label">مدیریت شهرستان‌ها</span>
</a>
</li>
<li class="slide"> <li class="slide">
<a href="{{ route('admin.activity-logs.index') }}" <a href="{{ route('admin.activity-logs.index') }}"
class="side-menu__item {{activeAdminSidebar('admin.activity-logs.index')}}"> class="side-menu__item {{activeAdminSidebar('admin.activity-logs.index')}}">
@@ -0,0 +1,28 @@
@extends('admin.layouts.app')
@section('content')
<div class="container-fluid pt-4">
<form action="{{ route('admin.provinces.store') }}" method="POST">
@csrf
<div class="card custom-card">
<div class="card-header">
<div class="card-title">افزودن استان</div>
</div>
<div class="card-body">
<label class="form-label">نام استان</label>
<input type="text" class="form-control" name="name" value="{{ old('name') }}">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ثبت</button>
</div>
</div>
</form>
</div>
@endsection
@@ -0,0 +1,31 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<form action="{{ route('admin.provinces.update', $province) }}" method="POST">
@csrf
@method('put')
<div class="card custom-card">
<div class="card-header">
<div class="card-title">ویرایش استان</div>
</div>
<div class="card-body">
<label class="form-label">نام استان</label>
<input type="text" class="form-control" name="name" value="{{ old('name', $province->name) }}">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</div>
</form>
</div>
</div>
@endsection
@@ -1,3 +1,58 @@
@extends('admin.layouts.app') @extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت استان‌ها</h1></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-8"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجوی استان"></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.provinces.create') }}" class="btn btn-primary w-100">استان جدید</a></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table"><thead><tr><th>#</th><th>استان</th><th>عملیات</th></tr></thead><tbody>@forelse(($provinces ?? []) as $province)<tr><td>{{ $province->id }}</td><td>{{ $province->name }}</td><td><a href="{{ route('admin.provinces.edit',$province) }}" class="btn btn-secondary-light btn-sm">ویرایش</a><form class="d-inline" method="POST" action="{{ route('admin.provinces.destroy',$province) }}" onsubmit="return confirm('حذف استان؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="3" class="text-center text-muted py-5">استانی ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($provinces ?? collect())->links() }}</div>@endsection @section('content')
<div class="container-fluid pt-4">
<div class="card custom-card">
<div class="card-header d-flex align-items-center justify-content-between">
<div class="card-title">مدیریت استان‌ها</div>
<a href="{{ route('admin.provinces.create') }}" class="btn btn-primary btn-sm">
افزودن استان
</a>
</div>
<div class="card-body pt-0">
<div class="table-responsive">
<table class="table text-nowrap">
<thead>
<tr>
<th>#</th>
<th>نام استان</th>
<th>تعداد شهرستان</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@forelse($provinces as $province)
<tr>
<td>{{ $province->id }}</td>
<td>{{ $province->name }}</td>
<td>{{ $province->cities_count }}</td>
<td>
<a href="{{ route('admin.provinces.edit', $province) }}" class="btn btn-sm btn-warning">
ویرایش
</a>
<form action="{{ route('admin.provinces.destroy', $province) }}" method="POST" class="d-inline">
@csrf
@method('delete')
<button type="submit" class="btn btn-sm btn-danger"
onclick="return confirm('آیا مطمئن هستید؟')">
حذف
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center">استانی ثبت نشده است</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{ $provinces->links() }}
</div>
</div>
</div>
@endsection
+62 -1
View File
@@ -63,6 +63,41 @@
<span style="color: red">{{ $message }}</span> <span style="color: red">{{ $message }}</span>
@enderror @enderror
</div> </div>
<div class="col-xl-6">
<label class="form-label">استان</label>
<select name="province_id" id="province_id" class="form-control">
<option value="">استان را انتخاب کنید</option>
@foreach($provinces as $province)
<option
value="{{ $province->id }}"
@selected(old('province_id', $user->province_id) == $province->id)
>
{{ $province->name }}
</option>
@endforeach
</select>
@error('province_id')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">شهرستان</label>
<select name="city_id" id="city_id" class="form-control">
@if($user->city)
<option value="{{ $user->city->id }}" selected>
{{ $user->city->name }}
</option>
@else
<option value="">ابتدا استان را انتخاب کنید</option>
@endif
</select>
@error('city_id')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6"> <div class="col-xl-6">
<label class="form-label">رمز عبور (در صورت تغییر)</label> <label class="form-label">رمز عبور (در صورت تغییر)</label>
<input type="text" class="form-control" name="password" <input type="text" class="form-control" name="password"
@@ -84,5 +119,31 @@
</div> </div>
</div> </div>
@endsection
<script>
document.getElementById('province_id').addEventListener('change', function () {
const provinceId = this.value;
const citySelect = document.getElementById('city_id');
citySelect.innerHTML = '<option value="">در حال بارگذاری...</option>';
if (!provinceId) {
citySelect.innerHTML = '<option value="">ابتدا استان را انتخاب کنید</option>';
return;
}
fetch(`/admin/users/cities-by-province/${provinceId}`)
.then(response => response.json())
.then(cities => {
citySelect.innerHTML = '<option value="">شهرستان خود را انتخاب کنید</option>';
cities.forEach(city => {
const option = document.createElement('option');
option.value = city.id;
option.textContent = city.name;
citySelect.appendChild(option);
});
});
});
</script>
@endsection
+2 -2
View File
@@ -191,10 +191,10 @@
{{ $user->email }} {{ $user->email }}
</td> </td>
<td> <td>
{{$user->province}} {{ $user->province?->name ?? '-' }}
</td> </td>
<td> <td>
{{$user->city}} {{ $user->city?->name ?? '-' }}
</td> </td>
<td> <td>
{{ $user->mobile }} {{ $user->mobile }}
+48 -22
View File
@@ -119,7 +119,7 @@
<label>جنسیت</label> <label>جنسیت</label>
<div class="form-group-icon"> <div class="form-group-icon">
<select name="gender" class="form-control"> <select name="gender" class="form-control">
<option value="">جنسیت را انتخاب کنید</option> <option value="" selected>جنسیت را انتخاب کنید</option>
<option value="{{ \App\Enums\UserGenderStatus::MALE->value }}" <option value="{{ \App\Enums\UserGenderStatus::MALE->value }}"
{{ old('gender') == \App\Enums\UserGenderStatus::MALE->value ? 'selected' : '' }}> {{ old('gender') == \App\Enums\UserGenderStatus::MALE->value ? 'selected' : '' }}>
مرد مرد
@@ -149,20 +149,20 @@
<div class="form-group-icon"> <div class="form-group-icon">
<select name="marital_status" class="form-control"> <select name="marital_status" class="form-control">
<option value="">وضعیت تأهل را انتخاب کنید</option> <option value="" selected>وضعیت تأهل را انتخاب کنید</option>
<option value="{{ \App\Enums\UserMaritalStatus::SINGLE->value }}" <option value="{{ \App\Enums\UserMaritalStatus::SINGLE }}"
{{ old('marital_status') == \App\Enums\UserMaritalStatus::SINGLE->value ? 'selected' : '' }}> {{ old('marital_status') == \App\Enums\UserMaritalStatus::SINGLE ? 'selected' : '' }}>
مجرد مجرد
</option> </option>
<option value="{{ \App\Enums\UserMaritalStatus::MARRIED->value }}" <option value="{{ \App\Enums\UserMaritalStatus::MARRIED }}"
{{ old('marital_status') == \App\Enums\UserMaritalStatus::MARRIED->value ? 'selected' : '' }}> {{ old('marital_status') == \App\Enums\UserMaritalStatus::MARRIED ? 'selected' : '' }}>
متأهل متأهل
</option> </option>
<option value="{{ \App\Enums\UserMaritalStatus::SEPARATED->value }}" <option value="{{ \App\Enums\UserMaritalStatus::SEPARATED }}"
{{ old('marital_status') == \App\Enums\UserMaritalStatus::SEPARATED->value ? 'selected' : '' }}> {{ old('marital_status') == \App\Enums\UserMaritalStatus::SEPARATED ? 'selected' : '' }}>
متارکه متارکه
</option> </option>
@@ -204,15 +204,17 @@
<small class="text-muted">(اختیاری)</small> <small class="text-muted">(اختیاری)</small>
</label> </label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" <select name="province_id" id="province_id" class="form-control">
id="province" <option value="">استان خود را انتخاب کنید</option>
name="province" @foreach($provinces as $province)
class="form-control" <option value="{{ $province->id }}" @selected(old('province_id') == $province->id)>
placeholder="استان خود را وارد کنید" {{ $province->name }}
value="{{ old('province') }}"> </option>
@endforeach
</select>
<i class="far fa-map-marker-alt"></i> <i class="far fa-map-marker-alt"></i>
</div> </div>
@error('province') @error('province_id')
<span class="text-danger">{{ $message }}</span> <span class="text-danger">{{ $message }}</span>
@enderror @enderror
</div> </div>
@@ -224,15 +226,12 @@
<small class="text-muted">(اختیاری)</small> <small class="text-muted">(اختیاری)</small>
</label> </label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" <select name="city_id" id="city_id" class="form-control">
id="city" <option value="">ابتدا استان را انتخاب کنید</option>
name="city" </select>
class="form-control"
placeholder="شهرستان خود را وارد کنید"
value="{{ old('city') }}">
<i class="far fa-map-marker-alt"></i> <i class="far fa-map-marker-alt"></i>
</div> </div>
@error('city') @error('city_id')
<span class="text-danger">{{ $message }}</span> <span class="text-danger">{{ $message }}</span>
@enderror @enderror
</div> </div>
@@ -329,4 +328,31 @@
</div> </div>
</main> </main>
<script>
document.getElementById('province_id').addEventListener('change', function () {
const provinceId = this.value;
const citySelect = document.getElementById('city_id');
citySelect.innerHTML = '<option value="">در حال بارگذاری...</option>';
if (!provinceId) {
citySelect.innerHTML = '<option value="">ابتدا استان را انتخاب کنید</option>';
return;
}
fetch(`/auth/cities-by-province/${provinceId}`)
.then(response => response.json())
.then(cities => {
citySelect.innerHTML = '<option value="">شهرستان خود را انتخاب کنید</option>';
cities.forEach(city => {
const option = document.createElement('option');
option.value = city.id;
option.textContent = city.name;
citySelect.appendChild(option);
});
});
});
</script>
@endsection @endsection
@@ -4,31 +4,36 @@
<div class="search-box flight-search"> <div class="search-box flight-search">
<div class="search-form"> <div class="search-form">
<form action="{{ route('flights.index') }}" method="GET">
<form action="{{ route('flights.index') }}" method="GET">
<div class="flight-search-wrapper"> <div class="flight-search-wrapper">
<div class="flight-search-content"> <div class="flight-search-content">
{{-- مبدا --}}
<div class="flight-search-item"> <div class="flight-search-item">
<div class="row"> <div class="row">
<div class="col-lg-3"> <div class="col-lg-4">
<div class="form-group"> <div class="form-group">
<label>از</label> <label>از</label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" <input type="text"
name="from-destination" name="from-destination"
class="form-control swap-from" class="form-control swap-from"
value="{{ request('from-destination') }}"> value="{{ request('from-destination') }}">
<i class="fal fa-plane-departure"></i> <i class="fal fa-plane-departure"></i>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3"> {{-- مقصد --}}
<div class="col-lg-4">
<div class="form-group"> <div class="form-group">
<div class="search-form-swap"> <div class="search-form-swap">
<i class="far fa-repeat"></i> <i class="far fa-repeat"></i>
</div> </div>
@@ -40,13 +45,16 @@
name="to-destination" name="to-destination"
class="form-control swap-to" class="form-control swap-to"
value="{{ request('to-destination') }}"> value="{{ request('to-destination') }}">
<i class="fal fa-plane-arrival"></i> <i class="fal fa-plane-arrival"></i>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-3">
{{-- مسافر --}}
<div class="col-lg-4">
<div class="form-group dropdown passenger-box"> <div class="form-group dropdown passenger-box">
<div class="passenger-class" <div class="passenger-class"
@@ -54,103 +62,111 @@
data-bs-toggle="dropdown" data-bs-toggle="dropdown"
aria-expanded="false"> aria-expanded="false">
<label>مسافر، کلاس</label> <label>مسافر</label>
<div class="form-group-icon"> <div class="form-group-icon">
<div class="passenger-total"> <div class="passenger-total">
<span class="passenger-total-amount"> <span class="passenger-total-amount">
{{ request('adult', 2) + request('children', 0) + request('infant', 0) }} {{ request('adult', 2) + request('children', 0) + request('infant', 0) }}
</span> </span>
Passenger
مسافر
</div> </div>
<i class="fal fa-user-plus"></i> <i class="fal fa-user-plus"></i>
</div>
</div>
</div> </div>
{{-- dropdown مسافران --}}
<div class="dropdown-menu dropdown-menu-end"> <div class="dropdown-menu dropdown-menu-end">
<div class="dropdown-item"> <div class="dropdown-item">
<div class="passenger-item">
<div class="passenger-info"> {{-- بزرگسال --}}
<h6>بزرگسالان</h6> <div
<p>12+ سال</p> class="passenger-item d-flex justify-content-between align-items-center">
<div>
<strong>بزرگسال</strong>
<small class="d-block text-muted">
بالای ۱۲ سال
</small>
</div> </div>
<div class="passenger-qty"> <input type="number"
<button type="button" class="minus-btn">
<i class="far fa-minus"></i>
</button>
<input type="text"
name="adult" name="adult"
class="qty-amount passenger-adult" class="form-control"
value="{{ request('adult', 2) }}" value="{{ request('adult', 2) }}"
readonly> min="1">
<button type="button" class="plus-btn">
<i class="far fa-plus"></i>
</button>
</div>
</div>
</div> </div>
<div class="dropdown-item"> {{-- کودک --}}
<div class="passenger-item"> <div
class="passenger-item d-flex justify-content-between align-items-center mt-2">
<div class="passenger-info"> <div>
<h6>بچه ها</h6> <strong>کودک</strong>
<p>2-12 سال</p> <small class="d-block text-muted">
۲ تا ۱۲ سال
</small>
</div> </div>
<div class="passenger-qty"> <input type="number"
<button type="button" class="minus-btn">
<i class="far fa-minus"></i>
</button>
<input type="text"
name="children" name="children"
class="qty-amount passenger-children" class="form-control"
value="{{ request('children', 0) }}" value="{{ request('children', 0) }}"
readonly> min="0">
</div>
<button type="button" class="plus-btn">
<i class="far fa-plus"></i> {{-- نوزاد --}}
</button> <div
class="passenger-item d-flex justify-content-between align-items-center mt-2">
<div>
<strong>نوزاد</strong>
<small class="d-block text-muted">
زیر ۲ سال
</small>
</div>
<input type="number"
name="infant"
class="form-control"
value="{{ request('infant', 0) }}"
min="0">
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="search-btn mt-3">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="search-btn">
<button type="submit" class="theme-btn"> <button type="submit" class="theme-btn">
<span class="far fa-search"></span> <span class="far fa-search"></span>
جستجو کردن جستجو کردن
</button> </button>
</div>
</div>
</div> </div>
</div> </div>
</div>
</form> </form>
</div> </div>
</div> </div>
+18 -7
View File
@@ -17,9 +17,17 @@
<div class="listing-content"> <div class="listing-content">
<div class="listing-slider owl-carousel owl-theme" dir="ltr"> <div class="listing-slider owl-carousel owl-theme" dir="ltr">
@if($flight?->file_id)
<img <img
src="{{ $flight->file ? asset('storage/'.$flight->file->path) : asset('assets/img/flight/single-1.jpg') }}" src="{{ getFileUrl($flight->file_id) }}"
alt> alt="{{ $flight->title }}"
>
@else
<img
src="{{ asset('assets/img/flight/01.jpg') }}"
alt="{{ $flight->title }}"
>
@endif
</div> </div>
<div class="listing-header"> <div class="listing-header">
@@ -96,20 +104,23 @@
</div> </div>
</div> </div>
</div> </div>
@if($flight->return_time)
<div class="col-md-6 col-lg-3"> <div class="col-md-6 col-lg-3">
<div class="listing-feature"> <div class="listing-feature">
<div class="listing-feature-icon"> <div class="listing-feature-icon">
<i class="far fa-eye"></i> <i class="far fa-calendar-check"></i>
</div> </div>
<div class="listing-feature-content"> <div class="listing-feature-content">
<h6>بازدید این پرواز</h6> <h6>تاریخ برگشت</h6>
<span>{{ number_format($flight->views) }} بازدید</span> <span>{{ $flight->return_time->toJalali()->format('Y/m/d') }}</span>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@endif
</div>
</div>
@if($flight->summary) @if($flight->summary)
<div class="listing-item"> <div class="listing-item">
<h4 class="mb-3">درباره این پرواز</h4> <h4 class="mb-3">درباره این پرواز</h4>
+7 -5
View File
@@ -23,14 +23,16 @@
{{-- Slider --}} {{-- Slider --}}
<div class="listing-slider owl-carousel owl-theme" dir="ltr"> <div class="listing-slider owl-carousel owl-theme" dir="ltr">
@if(getFileUrl($tour?->file?->id))
<img <img
src="{{ $tour->file src="{{ getFileUrl($tour?->file?->id) }}"
? asset('storage/' . $tour->file->path)
: asset('assets/img/tour/01.jpg') }}"
alt="{{ $tour->title }}" alt="{{ $tour->title }}"
style=""
> >
@else
<img src="{{ asset('assets/img/tour/02.jpg') }}" alt
style="">
@endif
</div> </div>
+51 -3
View File
@@ -4,8 +4,10 @@
use App\Http\Controllers\Admin\ActivityLogController; use App\Http\Controllers\Admin\ActivityLogController;
use App\Http\Controllers\Admin\AdminController; use App\Http\Controllers\Admin\AdminController;
use App\Http\Controllers\Admin\AuthController; use App\Http\Controllers\Admin\AuthController;
use App\Http\Controllers\Admin\CityController;
use App\Http\Controllers\Admin\DashboardController; use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\FlightController; use App\Http\Controllers\Admin\FlightController;
use App\Http\Controllers\Admin\ProvinceController;
use App\Http\Controllers\Admin\UserController; use App\Http\Controllers\Admin\UserController;
use App\Http\Controllers\Admin\TourController; use App\Http\Controllers\Admin\TourController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@@ -47,7 +49,7 @@ Route::prefix('admin')->name('admin.')->group(function () {
Route::put('update', 'update')->name('update')->middleware('admin.permission:admin_edit'); Route::put('update', 'update')->name('update')->middleware('admin.permission:admin_edit');
Route::delete('destroy', 'destroy')->name('destroy')->middleware('admin.permission:admin_edit'); Route::delete('destroy', 'destroy')->name('destroy')->middleware('admin.permission:admin_delete');
}); });
}); });
@@ -55,12 +57,17 @@ Route::prefix('admin')->name('admin.')->group(function () {
Route::get('/', 'index')->name('index')->middleware('admin.permission:user_view'); Route::get('/', 'index')->name('index')->middleware('admin.permission:user_view');
Route::get('cities-by-province/{province}', function (\App\Models\Province $province) {
return $province->cities()->orderBy('name')->get(['id', 'name']);
})->name('cities-by-province');
Route::prefix('{user}')->group(function () { Route::prefix('{user}')->group(function () {
Route::get('edit', 'edit')->name('edit')->middleware('admin.permission:admin_edit'); Route::get('edit', 'edit')->name('edit')->middleware('admin.permission:user_edit');
Route::put('update', 'update')->name('update')->middleware('admin.permission:user_edit'); Route::put('update', 'update')->name('update')->middleware('admin.permission:user_edit');
Route::delete('destroy', 'destroy')->name('destroy')->middleware('admin.permission:user_destroy'); Route::delete('destroy', 'destroy')->name('destroy')->middleware('admin.permission:user_delete');
}); });
}); });
@@ -106,5 +113,46 @@ Route::prefix('admin')->name('admin.')->group(function () {
}); });
Route::get('activity-logs', [ActivityLogController::class, 'index'])->name('activity-logs.index'); Route::get('activity-logs', [ActivityLogController::class, 'index'])->name('activity-logs.index');
Route::prefix('provinces')->name('provinces.')->controller(ProvinceController::class)->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{province}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
Route::delete('destroy', 'destroy')->name('destroy');
});
});
Route::prefix('cities')->name('cities.')->controller(CityController::class)->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{cities}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
Route::delete('destroy', 'destroy')->name('destroy');
});
});
}); });
}); });
+7
View File
@@ -23,6 +23,13 @@ Route::prefix('auth')->name('auth.')->group(function (){
Route::post('/','post')->name('post'); Route::post('/','post')->name('post');
}); });
Route::get('cities-by-province/{province}', function (\App\Models\Province $province) {
return $province->cities()->orderBy('name')->get(['id', 'name']);
})->name('cities-by-province');
}); });
Route::get('logout',[LogoutController::class,'index'])->middleware('auth')->name('logout'); Route::get('logout',[LogoutController::class,'index'])->middleware('auth')->name('logout');
}); });
+4
View File
@@ -37,6 +37,10 @@ Route::prefix('account')->name('account.')->middleware('auth')->group(function (
Route::post('profile/image', [ProfileController::class, 'updateImage']) ->name('profile.image.update'); Route::post('profile/image', [ProfileController::class, 'updateImage']) ->name('profile.image.update');
Route::get('cities-by-province/{province}', function (\App\Models\Province $province) {
return $province->cities()->orderBy('name')->get(['id', 'name']);
})->name('cities-by-province');
Route::prefix('edit-profile')->name('edit-profile.')->controller(EditProfileController::class)->group(function () { Route::prefix('edit-profile')->name('edit-profile.')->controller(EditProfileController::class)->group(function () {
Route::get('/', 'index')->name('index'); Route::get('/', 'index')->name('index');