git commit "add flight image upload and update support"

This commit is contained in:
2026-08-18 17:58:02 +03:30
parent 0722cf3120
commit 62a95c411b
15 changed files with 896 additions and 26 deletions
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace App\Enums;
enum FlightStatus : int
{
case Draft=0;
case Active=1;
case Inactive=2;
case Finished=3;
case Cancelled=4;
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum FlightType : int
{
case internal=0;
case external=2;
case charter=3;
}
@@ -3,9 +3,61 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use App\Http\Requests\Admin\FlightStoreRequest;
use App\Models\Flight;
class FlightController extends Controller class FlightController extends Controller
{ {
// public function index()
{
$flights = Flight::latest()->paginate(4);
return view('admin.flights.index',compact('flights'));
}
public function create()
{
return view('admin.flights.create');
}
public function store(FlightStoreRequest $request)
{
$data = $request->validated();
$data['type'] = (int) $data['type'];
if ($request->hasFile('image')) {
$data['image'] = $request->file('image')->store('flights', 'public');
}
Flight::create($data);
return redirect()->route('admin.flights.index')
->with('success', 'پرواز با موفقیت ثبت شد');
}
public function edit(Flight $flight)
{
return view('admin.flights.edit',compact('flight'));
}
public function update(FlightStoreRequest $request, Flight $flight)
{
$data = $request->validated();
$data['type'] = (int) $data['type'];
if ($request->hasFile('image')) {
$data['image'] = $request->file('image')->store('flights', 'public');
}
$flight->update($data);
return redirect()->route('admin.flights.index')
->with('success', 'پرواز با موفقیت ویرایش شد');
}
public function destroy(Flight $flight)
{
$flight->delete();
return back()->with('پرواز با موفقیت حذف شد.');
}
} }
@@ -10,8 +10,9 @@ class ReservationController extends Controller
{ {
public function index() public function index()
{ {
$reservations = Reservation:: $reservations = Reservation::query()
where('user_id', Auth::id()) ->with('reservable')
->where('user_id', Auth::id())
->latest() ->latest()
->get(); ->get();
+63 -2
View File
@@ -12,7 +12,7 @@ class FlightStoreRequest extends FormRequest
*/ */
public function authorize(): bool public function authorize(): bool
{ {
return false; return true;
} }
/** /**
@@ -23,7 +23,68 @@ class FlightStoreRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
return [ return [
// 'airline'=>[
'required',
'string',
'max:100'
],
'flight_number'=>[
'required',
'string',
'max:50'
],
'origin'=>[
'required',
'string',
'max:100'
],
'destination'=>[
'required',
'string',
'max:100'
],
'departure_date'=>[
'required',
'date',
],
'departure_time'=>[
'required'
],
'arrival_time'=>[
'required'
],
'flight_class'=>[
'nullable',
'string',
'max:50'
],
'capacity'=>[
'required',
'integer',
'min:1'
],
'price'=>[
'required',
'numeric',
'min:0'
],
'image' => [
'nullable',
'image',
'mimes:jpg,jpeg,png,webp',
'max:2048'
],
'type'=>[
'required',
'integer',
'in:0,2,3'
],
'status'=>[
'required',
'in:0,1,2,3,4'
]
]; ];
} }
} }
+7 -4
View File
@@ -6,6 +6,8 @@
namespace App\Models; namespace App\Models;
use App\Enums\FlightStatus;
use App\Enums\FlightType;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Attributes\Scope; use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
@@ -27,6 +29,7 @@ use Illuminate\Database\Eloquent\Model;
* @property string $views * @property string $views
* @property int|null $capacity * @property int|null $capacity
* @property float|null $price * @property float|null $price
* @property int $type
* @property int|null $status * @property int|null $status
* @property Carbon|null $created_at * @property Carbon|null $created_at
* @property Carbon|null $updated_at * @property Carbon|null $updated_at
@@ -44,7 +47,8 @@ class Flight extends Model
'arrival_time' => 'datetime', 'arrival_time' => 'datetime',
'capacity' => 'int', 'capacity' => 'int',
'price' => 'float', 'price' => 'float',
'status' => 'int' 'type' => FlightType::class,
'status' => FlightStatus::class,
]; ];
protected $fillable = [ protected $fillable = [
@@ -60,6 +64,7 @@ class Flight extends Model
'price', 'price',
'image', 'image',
'views', 'views',
'type',
'status' 'status'
]; ];
@@ -79,9 +84,7 @@ class Flight extends Model
public function reservations() public function reservations()
{ {
return $this->morphMany( return $this->morphMany(
Reservation::class, Reservation::class, 'reservable');
'reservable'
);
} }
#[Scope] #[Scope]
-1
View File
@@ -56,5 +56,4 @@ class Reservation extends Model
{ {
return $this->morphTo(); return $this->morphTo();
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@@ -60,14 +60,15 @@
<h3> <h3>
{{ $reservation->reservable?->name ?? 'پرواز حذف شده' }} {{ $reservation->reservable?->airline ?? 'پرواز حذف شده' }}
</h3> </h3>
<p> <p>
پرواز {{ $reservation->reservable?->origin }}
-
{{ $reservation->reservable?->destination }}
</p> </p>
@endif @endif
+224 -3
View File
@@ -1,3 +1,224 @@
<div> @extends('admin.layouts.app')
<!-- Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi -->
</div> @section('content')
<div class="container">
<h4 class="mb-4">
ثبت پرواز جدید
</h4>
<form action="{{ route('admin.flights.store') }}"
method="POST"
enctype="multipart/form-data">
@csrf
<div class="row">
<div class="col-md-6 mb-3">
<label>
ایرلاین
</label>
<input type="text"
name="airline"
class="form-control"
value="{{ old('airline') }}">
@error('airline')
<small class="text-danger">
{{ $message }}
</small>
@enderror
</div>
<div class="col-md-6 mb-3">
<label>
شماره پرواز
</label>
<input type="text"
name="flight_number"
class="form-control"
value="{{ old('flight_number') }}">
@error('flight_number')
<small class="text-danger">
{{ $message }}
</small>
@enderror
</div>
<div class="col-md-6 mb-3">
<label>
مبدا
</label>
<input type="text"
name="origin"
class="form-control"
value="{{ old('origin') }}">
</div>
<div class="col-md-6 mb-3">
<label>
مقصد
</label>
<input type="text"
name="destination"
class="form-control"
value="{{ old('destination') }}">
</div>
<div class="col-md-4 mb-3">
<label>
نوع پرواز
</label>
<select name="type" class="form-control">
<option value="0">داخلی</option>
<option value="2">خارجی</option>
<option value="3">چارتر</option>
</select>
</div>
<div class="col-md-4 mb-3">
<label>
تاریخ حرکت
</label>
<input type="date"
name="departure_date"
class="form-control">
</div>
<div class="col-md-4 mb-3">
<label>
کلاس پرواز
</label>
<input type="text"
name="flight_class"
class="form-control">
</div>
<div class="col-md-4 mb-3">
<label>
ظرفیت
</label>
<input type="number"
name="capacity"
class="form-control">
</div>
<div class="col-md-4 mb-3">
<label>
قیمت
</label>
<input type="number"
name="price"
class="form-control">
</div>
<div class="col-md-4 mb-3">
<label>
عکس
</label>
<input type="file"
name="image"
class="form-control">
</div>
<div class="col-md-4 mb-3">
<label>
وضعیت
</label>
<select name="status"
class="form-control">
<option value="1">
فعال
</option>
<option value="0">
پیش نویس
</option>
<option value="2">
غیرفعال
</option>
<option value="3">
تمام شده
</option>
<option value="4">
لغو شده
</option>
</select>
</div>
</div>
<button class="btn btn-primary">
ذخیره
</button>
</form>
</div>
@endsection
+241 -3
View File
@@ -1,3 +1,241 @@
<div> @extends('admin.layouts.app')
<!-- Let all your things have their places; let each part of your business have its time. - Benjamin Franklin -->
</div> @section('content')
<div class="container">
<h4 class="mb-4">
ویرایش پرواز
</h4>
<form action="{{ route('admin.flights.update', $flight->id) }}"
method="POST"
enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-6 mb-3">
<label>نام ایرلاین</label>
<input type="text"
name="airline"
class="form-control"
value="{{ old('airline', $flight->airline) }}">
@error('airline')
<small class="text-danger">
{{ $message }}
</small>
@enderror
</div>
<div class="col-md-6 mb-3">
<label>شماره پرواز</label>
<input type="text"
name="flight_number"
class="form-control"
value="{{ old('flight_number', $flight->flight_number) }}">
</div>
<div class="col-md-6 mb-3">
<label>مبدا</label>
<input type="text"
name="origin"
class="form-control"
value="{{ old('origin', $flight->origin) }}">
</div>
<div class="col-md-6 mb-3">
<label>مقصد</label>
<input type="text"
name="destination"
class="form-control"
value="{{ old('destination', $flight->destination) }}">
</div>
<div class="col-md-4 mb-3">
<label>تاریخ حرکت</label>
<input type="date"
name="departure_date"
class="form-control"
value="{{ old('departure_date', $flight->departure_date) }}">
</div>
<div class="col-md-4 mb-3">
<label>ساعت حرکت</label>
<input type="time"
name="departure_time"
class="form-control"
value="{{ old('departure_time', $flight->departure_time) }}">
</div>
<div class="col-md-4 mb-3">
<label>ساعت رسیدن</label>
<input type="time"
name="arrival_time"
class="form-control"
value="{{ old('arrival_time', $flight->arrival_time) }}">
</div>
<div class="col-md-4 mb-3">
<label>کلاس پرواز</label>
<input type="text"
name="flight_class"
class="form-control"
value="{{ old('flight_class', $flight->flight_class) }}">
</div>
<div class="col-md-4 mb-3">
<label>ظرفیت</label>
<input type="number"
name="capacity"
class="form-control"
value="{{ old('capacity', $flight->capacity) }}">
</div>
<div class="col-md-4 mb-3">
<label>قیمت</label>
<input type="number"
name="price"
class="form-control"
value="{{ old('price', $flight->price) }}">
</div>
<div class="col-md-6 mb-3">
<label>وضعیت</label>
<select name="status" class="form-control">
<option value="0"
{{ $flight->status == 0 ? 'selected':'' }}>
پیش نویس
</option>
<option value="1"
{{ $flight->status == 1 ? 'selected':'' }}>
فعال
</option>
<option value="2"
{{ $flight->status == 2 ? 'selected':'' }}>
غیرفعال
</option>
<option value="3"
{{ $flight->status == 3 ? 'selected':'' }}>
تمام شده
</option>
<option value="4"
{{ $flight->status == 4 ? 'selected':'' }}>
لغو شده
</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label>تصویر</label>
<input type="file"
name="image"
class="form-control">
@if($flight->image)
<img src="{{ asset('storage/'.$flight->image) }}"
width="120"
class="mt-2">
@endif
</div>
</div>
<button class="btn btn-primary">
ذخیره تغییرات
</button>
<a href="{{ route('admin.flights.index') }}"
class="btn btn-secondary">
بازگشت
</a>
</form>
</div>
@endsection
+271 -3
View File
@@ -1,3 +1,271 @@
<div> @extends('admin.layouts.app')
<!-- Simplicity is the essence of happiness. - Cedric Bledsoe -->
</div> @section('content')
<div class="container">
<div class="d-flex justify-content-between mb-4">
<h4>
مدیریت پروازها
</h4>
<a href="{{ route('admin.flights.create') }}"
class="btn btn-primary">
ثبت پرواز جدید
</a>
</div>
<form method="GET"
action="{{ route('admin.flights.index') }}"
class="mb-3">
<div class="row">
<div class="col-md-4">
<input type="text"
name="search"
class="form-control"
placeholder="جستجو..."
value="{{ request('search') }}">
</div>
<div class="col-md-3">
<select name="type"
class="form-control">
<option value="">
همه انواع
</option>
<option value="internal"
@selected(request('type')=='internal')>
داخلی
</option>
<option value="external"
@selected(request('type')=='external')>
خارجی
</option>
<option value="charter"
@selected(request('type')=='charter')>
چارتر
</option>
</select>
</div>
<div class="col-md-3">
<select name="sort"
class="form-control">
<option value="newest">
جدیدترین
</option>
<option value="price_asc">
ارزان‌ترین
</option>
<option value="price_desc">
گران‌ترین
</option>
</select>
</div>
<div class="col-md-2">
<button class="btn btn-dark w-100">
اعمال
</button>
</div>
</div>
</form>
<table class="table table-bordered text-center">
<thead>
<tr>
<th>
#
</th>
<th>
ایرلاین
</th>
<th>
شماره پرواز
</th>
<th>
مسیر
</th>
<th>
نوع
</th>
<th>
قیمت
</th>
<th>
وضعیت
</th>
<th>
عملیات
</th>
</tr>
</thead>
<tbody>
@forelse($flights as $flight)
<tr>
<td>
{{ $loop->iteration }}
</td>
<td>
{{ $flight->airline }}
</td>
<td>
{{ $flight->flight_number }}
</td>
<td>
{{ $flight->origin }}
-
{{ $flight->destination }}
</td>
<td>
@switch($flight->type->value)
@case('internal')
داخلی
@break
@case('external')
خارجی
@break
@case('charter')
چارتر
@break
@endswitch
</td>
<td>
{{ number_format($flight->price) }}
</td>
<td>
{{ $flight->status }}
</td>
<td>
<a href="{{ route('admin.flights.edit',$flight) }}"
class="btn btn-warning btn-sm">
ویرایش
</a>
<form action="{{ route('admin.flights.destroy',$flight) }}"
method="POST"
class="d-inline">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm"
onclick="return confirm('حذف شود؟')">
حذف
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="8">
موردی یافت نشد
</td>
</tr>
@endforelse
</tbody>
</table>
{{ $flights->links() }}
</div>
@endsection
+5 -3
View File
@@ -5,7 +5,7 @@ use App\Http\Controllers\Admin\AdminController;
use App\Http\Controllers\Admin\Auth\AuthController; use App\Http\Controllers\Admin\Auth\AuthController;
use App\Http\Controllers\Admin\Auth\DashboardController; use App\Http\Controllers\Admin\Auth\DashboardController;
use App\Http\Controllers\Admin\UserController; use App\Http\Controllers\Admin\UserController;
use App\Http\Controllers\FlightController; use App\Http\Controllers\Admin\FlightController;
use App\Http\Controllers\RoleController; use App\Http\Controllers\RoleController;
use App\Http\Controllers\TourController; use App\Http\Controllers\TourController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@@ -45,8 +45,10 @@ Route::prefix('admin')->name('admin.')->group(function (){
Route::prefix('flights')->name('flights.')->controller(FlightController::class)->group(function (){ Route::prefix('flights')->name('flights.')->controller(FlightController::class)->group(function (){
Route::get('/','index')->name('index'); Route::get('/','index')->name('index');
Route::prefix('{flight}')->group(function (){ Route::get('create','create')->name('create');
Route::get('show','show')->name('show'); Route::post('store','store')->name('store');
Route::prefix('{flight}')->group(function (){
Route::get('edit','edit')->name('edit'); Route::get('edit','edit')->name('edit');
Route::put('update','update')->name('update'); Route::put('update','update')->name('update');