Compare commits

...

42 Commits

Author SHA1 Message Date
shahrzad 5e3924d929 feat: add charts to admin dashboard 2026-08-22 11:47:39 +03:30
shahrzad 691290c340 chore: finalize project updates 2026-08-22 11:42:16 +03:30
shahrzad 7719d750e9 feat: add favorites management 2026-08-22 11:27:55 +03:30
shahrzad 6addcf73bb chore: add latest database backup 2026-08-22 11:27:28 +03:30
shahrzad 9e38c63614 feat: add user password update validation 2026-08-22 11:27:09 +03:30
shahrzad f73800fa50 feat: add public comment management 2026-08-22 11:26:32 +03:30
shahrzad e322ddda8f feat: add province and city management 2026-08-22 11:26:01 +03:30
shahrzad 64bfa2b94f feat: add province and city management 2026-08-22 11:25:31 +03:30
shahrzad 07e6dc7f5d feat: add comment status view 2026-08-22 07:57:24 +03:30
shahrzad 1544aed64d feat: add archive page styles 2026-08-22 07:56:53 +03:30
shahrzad 17090d0666 feat: add account page styles 2026-08-22 07:56:40 +03:30
shahrzad 4462237c44 chore: add latest database backup 2026-08-22 07:56:20 +03:30
shahrzad fad359f1c5 fix: update tour functionality 2026-08-22 07:55:56 +03:30
shahrzad 2195f10016 fix: update homepage data 2026-08-22 07:55:32 +03:30
shahrzad 178219b699 fix: update admin user management 2026-08-22 07:54:50 +03:30
shahrzad 281b82fc5b fix: update admin dashboard 2026-08-22 07:54:26 +03:30
shahrzad 65c4863f30 fix: update profile editing 2026-08-22 07:53:15 +03:30
shahrzad cb494a933e fix: update account comment handling 2026-08-22 07:52:16 +03:30
shahrzad 7c0bc5b08b fix: update authentication flow 2026-08-20 08:28:45 +03:30
shahrzad 2a980ecc55 fix: update public tour functionality 2026-08-20 08:27:53 +03:30
shahrzad 9b7934c0ba fix: update flight functionality 2026-08-20 08:27:00 +03:30
shahrzad f9dd90f1ac fix: update admin management 2026-08-20 08:25:43 +03:30
shahrzad ecb2e9ff08 chore: update composer dependencies 2026-08-20 08:24:37 +03:30
shahrzad ea2333cc68 fix: update web routes 2026-08-20 08:24:19 +03:30
shahrzad 6f99b8fb1c fix: update frontend styles 2026-08-20 08:24:00 +03:30
shahrzad f23ce338b3 fix: update frontend layout 2026-08-20 08:23:41 +03:30
shahrzad 409b8bb7f9 fix: update account favorites view 2026-08-20 08:22:54 +03:30
shahrzad c770921377 fix: update admin model 2026-08-20 08:22:19 +03:30
shahrzad d4e96f614a fix: update user model 2026-08-20 08:21:55 +03:30
shahrzad 2d9b56a83e fix: update homepage 2026-08-20 08:21:27 +03:30
shahrzad 854324813e fix: update public tour functionality 2026-08-20 08:20:29 +03:30
shahrzad 99e7d4ee95 fix: update flight functionality 2026-08-20 08:19:33 +03:30
shahrzad 39386b8155 fix: update authentication flow 2026-08-20 08:18:39 +03:30
shahrzad 66cc0d64ad fix: update admin tour management 2026-08-20 08:17:05 +03:30
shahrzad ccee91fdc4 feat: add user favorites management 2026-08-20 08:15:42 +03:30
shahrzad 52a8633787 feat: add profile editing 2026-08-20 08:15:20 +03:30
shahrzad 9e4baaa08d feat: add flight controller 2026-08-20 08:12:35 +03:30
shahrzad 793a3dc06e feat: add user authentication 2026-08-20 08:10:51 +03:30
shahrzad bbdfb48812 chore: add latest database backup 2026-08-20 08:06:32 +03:30
shahrzad a6d0cc2d41 fix: update application routes 2026-08-19 08:30:30 +03:30
shahrzad 2a69d676e1 fix: update airport management 2026-08-19 08:29:08 +03:30
shahrzad 157efd8df0 fix: update dashboard functionality 2026-08-19 08:28:03 +03:30
95 changed files with 6997 additions and 7402 deletions
@@ -1,13 +1,47 @@
<?php
namespace App\Http\Controllers\Account;
use App\Http\Requests\CommentStoreRequest;
use App\Http\Controllers\Controller;
use App\Models\Flight;
use App\Models\Tour;
class CommentController extends Controller
{
public function index()
//ثبت نظر برای تور
public function storeTour(CommentStoreRequest $request, Tour $tour)
{
return view('account.comments');
$tour->comments()->create([
'user_id' => auth()->id(),
'body' => $request->validated('body'),
'status' => 1,
]);
return back()->with('success', 'نظر شما با موفقیت ثبت شد.');
}
//ثبت نظر برای پرواز
public function storeFlight(CommentStoreRequest $request, Flight $flight)
{
$flight->comments()->create([
'user_id' => auth()->id(),
'body' => $request->validated('body'),
'status' => 1,
]);
return back()->with('success', 'نظر شما با موفقیت ثبت شد.');
}
public function myComments()
{
$comments = auth()->user()->comments()
->with('commentable')
->latest()
->paginate(10);
return view('account.comments', compact('comments'));
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller;
use App\Http\Requests\EditProfilePostRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class EditProfileController extends Controller
{
public function index()
{
$user = Auth::user()->load(['comments.commentable', 'favorites.favoritable']);
return view('account.edit-profile.index', compact('user'));
}
public function post(EditProfilePostRequest $request)
{
$user = Auth::user();
// به‌روزرسانی فیلدها
$user->first_name = $request->first_name;
$user->last_name = $request->last_name;
$user->email = $request->email;
$user->username = $request->username;
if ($request->filled('password')) {
$user->password = Hash::make($request->password);
}
if ($request->hasFile('image')) {
if ($user->image) {
Storage::disk('public')->delete($user->image);
}
$path = $request->file('image')->store('avatars', 'public');
$user->image = $path;
}
$user->save();
return redirect()
->route('account.edit-profile.index')
->with('success', 'اطلاعات پروفایل با موفقیت ویرایش شد.');
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller;
use App\Models\Favorite;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class FavoriteController extends Controller
{
public function index()
{
// dd(Auth::id(), Favorite::with('favoritable')->where('user_id', Auth::id())->get());
$user = Auth::user();
$favorites = Favorite::with('favoritable')
->where('user_id', $user->id)
->orderByDesc('id')
->paginate(9);
return view('account.favorites', compact('favorites'));
}
public function toggle(Request $request)
{
// چک اینکه کاربر ورود شدهست
if (!Auth::check()) {
return back()->with('error', 'برای افزودن به علاقهمندی باید ورود شوی');
}
$data = $request->validate([
'favoritable_type' => 'required|string',
'favoritable_id' => 'required|integer',
]);
$type = $data['favoritable_type'];
$id = $data['favoritable_id'];
if (!class_exists($type)) {
return back()->with('error', 'مدل معتبر نیست');
}
$model = $type::find($id);
if (!$model) {
return back()->with('error', 'مورد یافت نشد');
}
// یافتن علاقهمندی موجود
$favorite = Favorite::where('user_id', Auth::id())
->where('favoritable_type', $type)
->where('favoritable_id', $id)
->first();
if ($favorite) {
$favorite->delete(); // حذف از علاقهمندیها
$message = 'از علاقهمندیها حذف شد';
} else {
Favorite::create([
'user_id' => Auth::id(),
'favoritable_type' => $type,
'favoritable_id' => $id,
]);
$message = 'به علاقهمندیها افزوده شد';
}
return back()->with('success', $message);
}
}
+18 -32
View File
@@ -3,57 +3,43 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Requests\Auth\LoginPostRequest;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* نمایش صفحه ورود
*/
public function index()
{
return view('auth.login');
}
/**
* ورود کاربر
*/
public function post(Request $request)
public function post(LoginPostRequest $request)
{
// $credentials = $request->validate([
// 'email' => [
// 'required',
// 'email',
// ],
//
// 'password' => [
// 'required',
// 'string',
// ],
// ],
//
// [
// 'email.required' => 'ایمیل را وارد کنید.',
// 'email.email' => 'فرمت ایمیل صحیح نیست.',
// 'password.required' => 'رمز عبور را وارد کنید.',
// ]);
$login = $request->validated();
$field = filter_var($login['username'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
$credentials = [
$field => $login['username'],
'password' => $login['password'],
];
$remember = $request->boolean('remember');
if (Auth::guard('web')->attempt($credentials, $remember)) {
if (Auth::attempt($credentials, $remember)) {
$request->session()->regenerate();
return redirect()->intended(
route('index')
);
return redirect()
->intended(route('account.index'))
->with('success', 'با موفقیت وارد حساب کاربری شدید.');
}
return back()
->withInput($request->only('email', 'remember'))
->withInput($request->only('username'))
->withErrors([
'email' => 'ایمیل یا رمز عبور اشتباه است.',
'username' => 'نام کاربری، ایمیل یا رمز عبور اشتباه است.',
]);
}
}
+10 -1
View File
@@ -4,8 +4,17 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LogoutController extends Controller
{
//
public function index(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('auth.login.index')->with('success', 'با موفقیت از حساب کاربری خارج شدید.');
}
}
@@ -1,5 +1,6 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
@@ -7,17 +8,12 @@ use App\Http\Requests\Auth\RegisterPostRequest;
use App\Models\City;
use App\Models\Province;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
class RegisterController extends Controller
{
/**
* نمایش فرم ثبت نام
*/
public function index()
{
$provinces = Province::orderBy('name')->get();
@@ -26,9 +22,11 @@ class RegisterController extends Controller
}
public function post(RegisterPostRequest $request)
{
// $data = $request->validated();
$imagePath = null;
@@ -42,65 +40,56 @@ class RegisterController extends Controller
$user = User::create([
'first_name' => $request->input('first_name'),
'first_name' => $request['first_name'],
'last_name' => $request->input('last_name'),
'last_name' => $request['last_name'],
'national_code' => $request->input('national_code'),
'national_code' => $request['national_code'],
'gender' => $request->input('gender'),
'gender' => $request['gender'],
'marital_status' => $request->input('marital_status'),
'marital_status' => $request['marital_status'],
'spouse_name' => $request->input('marital_status') == 2
? $request->input('spouse_name')
'spouse_name' => $request['marital_status'] == 2
? ($data['spouse_name'] ?? null)
: null,
'mobile' => $request->input('mobile'),
'mobile' => $request['mobile'],
'email' => $request->input('email'),
'email' => $request['email'],
'username' => $request->input('username'),
'username' => $request['username'],
'password' => Hash::make($request->input('password')),
'password' => Hash::make($request['password']),
'image' => $imagePath,
'province_id' => $request->input('province_id'),
'province_id' => $data['province_id'] ?? null,
'city_id' => $request->input('city_id'),
'city_id' => $request['city_id'] ?? null,
'status' => 1,
]);
/*
|--------------------------------------------------------------------------
| ورود خودکار بعد از ثبت نام
|--------------------------------------------------------------------------
*/
Auth::guard('web')->login($user);
$request->session()->regenerate();
/*
|--------------------------------------------------------------------------
| انتقال به پنل کاربری
|--------------------------------------------------------------------------
*/
// $request->session()->regenerate();
return redirect()
->route('account.index')
->with('success', 'ثبت‌نام شما با موفقیت انجام شد.');
}
public function cities(Province $province)
{
$cities = City::where('province_id', $province->id)
->orderBy('name')
->get(['id', 'name']);
->get([
'id',
'name'
]);
return response()->json($cities);
}
@@ -0,0 +1,10 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CommentController extends Controller
{
//
}
@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers;
use App\Models\Tour;
use Illuminate\Http\Request;
class FavoriteController extends Controller
{
public function toggle(Request $request)
{
$type = $request->input('favoritable_type');
$id = $request->input('favoritable_id');
// چک کنید اگر null بود، متوقف شود
if (!$type || !$id) {
return back()->withErrors('اطلاعات ارسالی ناقص است!');
}
$user = auth()->user();
$exists = $user->favorites()
->where('favoritable_type', $type)
->where('favoritable_id', $id)
->first();
if ($exists) {
// اگر وجود داشت، حذفش کن
$exists->delete();
$message = 'از علاقه‌مندی‌ها حذف شد.';
} else {
// اگر وجود نداشت، یک رکورد جدید بساز
$user->favorites()->create([
'favoritable_type' => $type,
'favoritable_id' => $id,
]);
$message = 'به علاقه‌مندی‌ها اضافه شد.';
}
return back()->with('success', $message);
}
}
+18 -171
View File
@@ -8,45 +8,40 @@ use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* لیست پروازها
*/
public function index(Request $request)
{
$query = Flight::query()
->active()
->with([
'travelType',
'origin',
'destination',
'tours',
]);
// فقط پروازهای فعال
$query->where('status', 1);
// جستجو بر اساس شماره پرواز
// شماره پرواز
if ($request->filled('flight_number')) {
$query->where(
'flight_number',
'like',
'%' . $request->flight_number . '%'
'%' . $request->input('flight_number') . '%'
);
}
// جستجو بر اساس مبدا
// مبدا
if ($request->filled('origin')) {
$query->where(
'origin',
'like',
'%' . $request->origin . '%'
'%' . $request->input('origin') . '%'
);
}
// جستجو بر اساس مقصد
// مقصد
if ($request->filled('destination')) {
$query->where(
'destination',
'like',
'%' . $request->destination . '%'
'%' . $request->input('destination') . '%'
);
}
@@ -59,24 +54,21 @@ class FlightController extends Controller
}
/**
* جستجوی پروازها
*/
public function search(Request $request)
{
$query = Flight::query()
->where('status', 1)
->active()
->with([
'travelType',
'origin',
'destination',
'tours',
]);
if ($request->filled('origin')) {
$query->where(
'origin',
'like',
'%' . $request->origin . '%'
'%' . $request->input('origin') . '%'
);
}
@@ -84,14 +76,14 @@ class FlightController extends Controller
$query->where(
'destination',
'like',
'%' . $request->destination . '%'
'%' . $request->input('destination') . '%'
);
}
if ($request->filled('departure_date')) {
$query->where(
$query->whereDate(
'departure_date',
$request->departure_date
$request->input('departure_date')
);
}
@@ -99,7 +91,7 @@ class FlightController extends Controller
$query->where(
'flight_number',
'like',
'%' . $request->flight_number . '%'
'%' . $request->input('flight_number') . '%'
);
}
@@ -112,160 +104,15 @@ class FlightController extends Controller
}
/**
* جزئیات پرواز
*/
public function show(Flight $flight)
{
/*
|--------------------------------------------------------------------------
| فعلاً isActive را حذف کردیم
|--------------------------------------------------------------------------
| چون اگر متد isActive در مدل اشتباه باشد یا status متفاوت باشد
| باعث 404 شدن صفحه می‌شود.
*/
$flight->load([
'travelType',
'origin',
'destination',
'tours',
]);
return view('flights.show', compact('flight'));
}
}
//
//namespace App\Http\Controllers;
//
//use App\Models\Flight;
//use Illuminate\Http\Request;
//
//class FlightController extends Controller
//{
// /**
// * لیست پروازها
// */
// public function index(Request $request)
// {
// $query = Flight::query()
// ->where('status', 1)
// ->with([
// 'travelType',
// 'origin',
// 'destination',
// ]);
//
// // جستجو بر اساس شماره پرواز
// if ($request->filled('flight_number')) {
// $query->where(
// 'flight_number',
// 'like',
// '%' . $request->input('flight_number') . '%'
// );
// }
//
// // جستجو بر اساس مبدا
// if ($request->filled('origin')) {
// $query->where(
// 'origin',
// 'like',
// '%' . $request->input('origin') . '%'
// );
// }
//
// // جستجو بر اساس مقصد
// if ($request->filled('destination')) {
// $query->where(
// 'destination',
// 'like',
// '%' . $request->input('destination') . '%'
// );
// }
//
// // مرتب‌سازی
// $flights = $query
// ->latest()
// ->paginate(12)
// ->withQueryString();
//
// return view(
// 'flights.index',
// compact('flights')
// );
// }
//
//
// /**
// * جستجوی پروازها
// */
// public function search(Request $request)
// {
// $query = Flight::query()
// ->where('status', 1)
// ->with([
// 'travelType',
// 'origin',
// 'destination',
// ]);
//
// if ($request->filled('origin')) {
// $query->where(
// 'origin',
// 'like',
// '%' . $request->input('origin') . '%'
// );
// }
//
// if ($request->filled('destination')) {
// $query->where(
// 'destination',
// 'like',
// '%' . $request->input('destination') . '%'
// );
// }
//
// if ($request->filled('departure_date')) {
// $query->where(
// 'departure_date',
// $request->input('departure_date')
// );
// }
//
// $flights = $query
// ->latest()
// ->paginate(12)
// ->withQueryString();
//
// return view(
// 'flights.index',
// compact('flights')
// );
// }
//
//
// /**
// * جزئیات پرواز
// */
// public function show(Flight $flight)
// {
// // فقط پروازهای فعال قابل مشاهده باشند
// if (!$flight->isActive()) {
// abort(404);
// }
//
// // اطلاعات مورد نیاز پرواز
// $flight->load([
// 'travelType',
// 'origin',
// 'destination',
// 'tours',
// ]);
//
// return view(
// 'flights.show',
// compact('flight')
// );
// }
//}
+13 -5
View File
@@ -9,16 +9,24 @@ class IndexController extends Controller
{
public function index()
{
$tours = Tour::query()
->where('status', 1)
->latest()
->paginate(6, ['*'], 'tours_page');
->orderByDesc('created_at')
->paginate(3, ['*'], 'tours_page');
$flights = Flight::query()
->where('status', 1)
->latest()
->paginate(6, ['*'], 'flights_page');
->orderByDesc('created_at')
->paginate(3, ['*'], 'flights_page');
return view('index', compact('tours', 'flights'));
$latestTours= Tour::latest()->limit(6)->get();
$latestFlights = Flight::latest()->limit(6)->get();
return view('index', [
'tours' => $tours,
'flights' => $flights,
compact('latestTours', 'latestFlights')
]);
}
}
+57 -81
View File
@@ -1,146 +1,122 @@
<?php
namespace App\Http\Controllers;
use App\Models\Favorite;
use App\Models\Tour;
use App\Models\Comment;
// اضافه شد
use App\Models\TravelType;
use Illuminate\Http\Request;
class TourController extends Controller
{
/**
* لیست / آرشیو تورها با قابلیت فیلتر
*/
public function index(Request $request)
{
$query = Tour::query()
->where('status', 1)
->with(['travelType', 'flights']);
// فیلتر بر اساس نوع سفر
if ($request->filled('travel_type')) {
$query->where(
'travel_type_id',
$request->input('travel_type')
);
$query->where('travel_type_id', $request->input('travel_type'));
}
// جستجو بر اساس عنوان
if ($request->filled('q')) {
$query->where(
'title',
'like',
'%' . $request->input('q') . '%'
);
$query->where('title', 'like', '%' . $request->input('q') . '%');
}
// حداقل قیمت
if ($request->filled('price_min')) {
$query->where(
'price',
'>=',
$request->input('price_min')
);
$query->where('price', '>=', $request->input('price_min'));
}
// حداکثر قیمت
if ($request->filled('price_max')) {
$query->where(
'price',
'<=',
$request->input('price_max')
);
$query->where('price', '<=', $request->input('price_max'));
}
// مرتب‌سازی
if ($request->filled('sort')) {
$query->orderBy(
'price',
$request->input('sort') === 'desc'
? 'desc'
: 'asc'
);
$query->orderBy('price', $request->input('sort') === 'desc' ? 'desc' : 'asc');
} else {
$query->latest();
}
// صفحه‌بندی
$tours = $query->paginate(12)->withQueryString();
if ($request->routeIs('index')) {
// انواع سفر
$tours = $query->latest()->limit(4)->get();
return view('index', compact('tours'));
} else {
$tours = $query->latest()->paginate(2);
$travelTypes = TravelType::where('status', 1)->get();
return view(
'tours.index',
compact('tours', 'travelTypes')
);
return view('tours.index', compact('tours', 'travelTypes'));
}
}
/**
* حذف فیلترها
*/
public function removeFilters()
{
return redirect()->route('tours.index');
}
/**
* نمایش جزئیات یک تور
*/
public function show(Tour $tour)
{
// فقط تورهای فعال قابل مشاهده باشند
if ($tour->status != 1) {
abort(404);
}
// افزایش تعداد بازدید
$tour->increment('views_count');
// بارگذاری اطلاعات مورد نیاز
// بارگذاری اطلاعات مورد نیاز + نظرات تایید شده
$tour->load([
'flights',
'travelType',
'comments' => function ($query) {
$query->where('status', 1)->latest();
},
'comments.user' // برای نمایش نام کاربری در نظرات
]);
// تورهای مرتبط
$relatedTours = Tour::where('status', 1)
->where('travel_type_id', $tour->travel_type_id)
->where('id', '!=', $tour->id)
->latest()
->limit(4)
->limit(3)
->get();
return view(
'tours.show',
compact('tour', 'relatedTours')
);
$isFav = false;
if (auth()->check()) {
$isFav = Favorite::where('user_id', auth()->id())
->where('favoritable_type', Tour::class)
->where('favoritable_id', $tour->id)
->exists();
}
return view('tours.show', compact('tour', 'relatedTours', 'isFav'));
}
/**
* جستجوی پیشنهادی
*/
//ثبت نظر جدید برای تور
public function storeComment(Request $request, Tour $tour)
{
$request->validate([
'body' => 'required|string|min:5|max:1000',
]);
$tour->comments()->create([
'user_id' => auth()->id(),
'body' => $request->body,
'status' => 0, // در انتظار تایید
]);
return back()->with('success', 'نظر شما ثبت شد و پس از تایید مدیریت نمایش داده می‌شود.');
}
//جستجوی پیشنهادی
public function searchSuggestion(Request $request)
{
$q = $request->input('q', '');
$tours = Tour::where('status', 1)
->where(
'title',
'like',
'%' . $q . '%'
)
return response()->json(
Tour::where('status', 1)
->where('title', 'like', '%' . $q . '%')
->limit(8)
->get([
'id',
'title',
'slug',
'price'
]);
return response()->json($tours);
->get(['id', 'title', 'slug', 'price'])
);
}
}
+19 -12
View File
@@ -1,6 +1,5 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
@@ -14,19 +13,17 @@ class AdminController extends Controller
{
public function index()
{
$admins = Admin::query()
->with('permissions')
$admins = Admin::with('permissions')
->latest()
->paginate(10);
return view('admin.admins.index', compact('admins'));
}
public function create()
{
$permissions = Permission::query()
->orderBy('name')
->get();
$permissions = Permission::orderBy('id')->get();
return view(
'admin.admins.create',
@@ -34,6 +31,7 @@ class AdminController extends Controller
);
}
public function store(AdminStoreRequest $request)
{
$data = $request->validated();
@@ -53,11 +51,10 @@ class AdminController extends Controller
->with('success', 'مدیر با موفقیت ایجاد شد.');
}
public function edit(Admin $admin)
{
$permissions = Permission::query()
->orderBy('name')
->get();
$permissions = Permission::orderBy('id')->get();
$admin->load('permissions');
@@ -67,7 +64,11 @@ class AdminController extends Controller
);
}
public function update(AdminUpdateRequest $request, Admin $admin)
public function update(
AdminUpdateRequest $request,
Admin $admin
)
{
$data = $request->validated();
@@ -76,9 +77,15 @@ class AdminController extends Controller
unset($data['permissions']);
if (!empty($data['password'])) {
$data['password'] = Hash::make($data['password']);
$data['password'] = Hash::make(
$data['password']
);
} else {
unset($data['password']);
}
$admin->update($data);
@@ -87,7 +94,7 @@ class AdminController extends Controller
return redirect()
->route('admin.admins.index')
->with('success', 'اطلاعات مدیر با موفقیت ویرایش شد.');
->with('success', 'مدیر با موفقیت ویرایش شد.');
}
public function destroy(Admin $admin)
@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\CityStoreRequest;
use App\Http\Requests\CityUpdateRequest;
use App\Models\City;
use App\Models\Province;
use Illuminate\Http\Request;
class CityController extends Controller
{
public function index(Request $request)
{
$query = City::with('province');
if ($request->filled('province_id')) {
$query->where('province_id', $request->province_id);
}
$cities = $query->paginate(20);
$provinces = Province::all();
return view('admin.cities.index', compact('cities', 'provinces'));
}
public function create()
{
$provinces = Province::all();
return view('admin.cities.create', compact('provinces'));
}
// استفاده از CityRequest به جای Request
public function store(CityStoreRequest $request)
{
City::create($request->validated());
return redirect()->route('admin.locations.cities.index')->with('success', 'شهر با موفقیت ایجاد شد.');
}
public function edit(City $city)
{
$provinces = Province::all();
return view('admin.cities.edit', compact('city', 'provinces'));
}
public function update(CityUpdateRequest $request, City $city)
{
$city->update($request->validated());
return redirect()->route('admin.locations.cities.index')->with('success', 'شهر ویرایش شد.');
}
public function destroy(City $city)
{
$city->delete();
return back()->with('success', 'شهر حذف شد.');
}
}
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\CommentUpdateRequest;
use App\Http\Requests\UpdateCommentRequest;
use App\Models\Comment;
class CommentController extends Controller
@@ -23,10 +22,6 @@ class CommentController extends Controller
return view('admin.comments.show', compact('comment'));
}
// public function edit(Comment $comment)
// {
// return view('admin.comments.edit', compact('comment'));
// }
public function update(CommentUpdateRequest $request, Comment $comment)
{
@@ -7,12 +7,10 @@ use App\Models\Airport;
use App\Models\Comment;
use App\Models\Favorite;
use App\Models\Flight;
use App\Models\Payment;
use App\Models\Tour;
use App\Models\User;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\VisitsExport;
use App\Models\VisitStatistic;
use Illuminate\Support\Carbon;
use Hekmatinasser\Verta\Verta;
@@ -21,18 +19,32 @@ class DashboardController extends Controller
public function index()
{
$usersCount = User::count();
$toursCount = Tour::count();
$flightsCount = Flight::count();
$airportsCount = Airport::count();
$commentsCount = Comment::count();
$favoritesCount = Favorite::count();
$paymentsCount = Payment::count();
/*
|--------------------------------------------------------------------------
| داده‌های نمودار
|--------------------------------------------------------------------------
*/
$chartLabels = [];
$chartValues = [];
for ($i = 9; $i >= 0; $i--) {
$date = Carbon::now()
->subDays($i);
$chartLabels[] = Verta::instance($date)
->format('Y/m/d');
// فعلاً برای تست
$chartValues[] = rand(5, 100);
}
return view('admin.dashboard', compact(
'usersCount',
@@ -41,28 +53,36 @@ class DashboardController extends Controller
'airportsCount',
'commentsCount',
'favoritesCount',
'paymentsCount'
'chartLabels',
'chartValues'
));
}
public function exportExcel()
{
// ۱. لیست کاربران با فیلدهایی که واقعاً در جدول users داری
$users = User::select('id', 'first_name', 'last_name', 'email', 'mobile', 'created_at')->get();
$users = User::select(
'id',
'first_name',
'last_name',
'email',
'mobile',
'created_at'
)->get();
// ۲. تبدیل به آرایه برای اکسل
$rows = $users->map(fn ($user) => [
$user->id,
$user->first_name,
$user->last_name,
$user->email,
$user->mobile,
$user->created_at ? Verta::instance($user->created_at)->format('Y/m/d') : '-',
$user->created_at
? Verta::instance($user->created_at)->format('Y/m/d')
: '-',
])->toArray();
// ۳. تغییر کلاس اکسل و اسم فایل
return Excel::download(new VisitsExport($rows), 'users-report-' . now()->format('Y-m-d') . '.xlsx');
return Excel::download(
new VisitsExport($rows),
'users-report-' . now()->format('Y-m-d') . '.xlsx'
);
}
}
@@ -78,9 +78,7 @@ class FlightController extends Controller
return view('admin.flights.show', compact('flight'));
}
/**
* نمایش فرم ویرایش پرواز
*/
public function edit(Flight $flight)
{
abort_unless(auth('admin')->user()?->canManageFlights('update'), 403);
@@ -90,9 +88,7 @@ class FlightController extends Controller
return view('admin.flights.edit', compact('flight', 'travelTypes'));
}
/**
* بروزرسانی پرواز
*/
public function update(FlightUpdateRequest $request, Flight $flight)
{
abort_unless(auth('admin')->user()?->canManageFlights('update'), 403);
@@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\ProvinceUpdateRequest;
use App\Models\Province;
class ProvinceController extends Controller
{
public function index()
{
$provinces = Province::paginate(20);
return view('admin.provinces.index', compact('provinces'));
}
public function create()
{
return view('admin.provinces.create');
}
public function store(ProvinceUpdateRequest $request)
{
Province::create($request->validated());
return redirect()->route('admin.locations.provinces.index')->with('success', 'استان با موفقیت ایجاد شد.');
}
public function edit(Province $province)
{
return view('admin.provinces.edit', compact('province'));
}
public function update(ProvinceUpdateRequest $request, Province $province)
{
$province->update($request->validated());
return redirect()->route('admin.locations.provinces.index')->with('success', 'استان ویرایش شد.');
}
public function destroy(Province $province)
{
$province->delete();
return back()->with('success', 'استان حذف شد.');
}
}
+165 -25
View File
@@ -4,9 +4,9 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\TourStoreRequest;
use App\Models\Flight;
use App\Models\Tour;
use App\Models\TravelType;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
@@ -14,18 +14,33 @@ use Illuminate\Support\Str;
class TourController extends Controller
{
public function index()
{
$tours = Tour::latest()->paginate(10);
return view('admin.tours.index', compact('tours'));
// ->where('status', 2)
$tours = Tour::latest()->paginate(20);
// آخرین پروازهای تایید شده
$flights = Flight::where('status', 2)
->latest()
->paginate(3);
return view('admin.tours.index', compact('tours', 'flights'));
}
/**
* فرم ایجاد تور
*/
public function create()
{
$travelTypes = TravelType::all();
return view('admin.tours.create', compact('travelTypes'));
}
/**
* ذخیره تور جدید
*/
public function store(TourStoreRequest $request)
{
DB::beginTransaction();
@@ -33,89 +48,214 @@ class TourController extends Controller
try {
$data = $request->validated();
// ساخت slug اگر خالی بود
// ساخت slug در صورت خالی بودن
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
$data['status'] = 2;
// ایجاد تور
$tour = Tour::create($data);
// آپلود تصویر
if ($request->hasFile('image')) {
$image = $request->file('image');
$newFileName = time() . '.tour-image' . rand(11111, 99999) . '.' . $image->extension();
$path = $image->storeAs('tours', $newFileName, 'public');
$tour->update(['image' => $path]);
$image = $request->file('image');
$newFileName =
time()
. '.tour-image'
. rand(11111, 99999)
. '.'
. $image->extension();
$path = $image->storeAs(
'tours',
$newFileName,
'public'
);
$tour->update([
'image' => $path
]);
}
DB::commit();
return redirect()->route('admin.tours.index')->with('success', 'تور با موفقیت ایجاد شد.');
return redirect()
->route('admin.tours.index')
->with('success', 'تور با موفقیت ایجاد شد.');
} catch (\Exception $exception) {
Log::error($exception);
DB::rollBack();
return back()->withInput()->withErrors(['general' => 'خطایی در ثبت رخ داد.']);
Log::error($exception);
return back()
->withInput()
->withErrors([
'general' => 'خطایی در ثبت تور رخ داد.'
]);
}
}
public function show(Tour $tour)
{
return view('admin.tours.show', compact('tour'));
}
public function edit(Tour $tour)
{
$travelTypes = TravelType::all();
return view('admin.tours.edit', compact('tour', 'travelTypes'));
return view(
'admin.tours.edit',
compact('tour', 'travelTypes')
);
}
public function update(TourStoreRequest $request, Tour $tour)
{
public function update(
TourStoreRequest $request,
Tour $tour
) {
DB::beginTransaction();
try {
$data = $request->validated();
// ساخت slug
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
if (!isset($data['status'])) {
$data['status'] = $tour->status ?? 2;
}
// اگر تصویر جدید آپلود شده
if ($request->hasFile('image')) {
// حذف عکس قبلی از حافظه
if ($tour->image && Storage::disk('public')->exists($tour->image)) {
// حذف تصویر قبلی
if (
$tour->image &&
Storage::disk('public')->exists($tour->image)
) {
Storage::disk('public')->delete($tour->image);
}
$image = $request->file('image');
$newFileName = time() . '.tour-image' . rand(11111, 99999) . '.' . $image->extension();
$path = $image->storeAs('tours', $newFileName, 'public');
$newFileName =
time()
. '.tour-image'
. rand(11111, 99999)
. '.'
. $image->extension();
$path = $image->storeAs(
'tours',
$newFileName,
'public'
);
$data['image'] = $path;
}
// بروزرسانی
$tour->update($data);
DB::commit();
return redirect()->route('admin.tours.index')->with('success', 'تور با موفقیت به‌روزرسانی شد.');
return redirect()
->route('admin.tours.index')
->with(
'success',
'تور با موفقیت به‌روزرسانی شد.'
);
} catch (\Exception $exception) {
Log::error($exception);
DB::rollBack();
return back()->withInput()->withErrors(['general' => 'خطایی در به‌روزرسانی رخ داد.']);
Log::error($exception);
return back()
->withInput()
->withErrors([
'general' =>
'خطایی در به‌روزرسانی تور رخ داد.'
]);
}
}
public function removeImage(Tour $tour)
{
// حذف تصویر تکی (اختیاری — می‌توانی منطق دلخواه بگذاری)
return back()->with('success', 'عملیات حذف تصویر انجام شد.');
try {
if (
$tour->image &&
Storage::disk('public')->exists($tour->image)
) {
Storage::disk('public')->delete($tour->image);
}
$tour->update([
'image' => null
]);
return back()->with(
'success',
'تصویر تور با موفقیت حذف شد.'
);
} catch (\Exception $exception) {
Log::error($exception);
return back()->withErrors([
'general' =>
'حذف تصویر با خطا مواجه شد.'
]);
}
}
public function destroy(Tour $tour)
{
try {
// حذف تصویر
if (
$tour->image &&
Storage::disk('public')->exists($tour->image)
) {
Storage::disk('public')->delete($tour->image);
}
// حذف تور
$tour->delete();
return redirect()->route('admin.tours.index')
->with('success', 'تور با موفقیت حذف شد.');
return redirect()
->route('admin.tours.index')
->with(
'success',
'تور با موفقیت حذف شد.'
);
} catch (\Exception $exception) {
Log::error($exception);
return back()->withErrors([
'general' =>
'حذف تور با خطا مواجه شد.'
]);
}
}
}
@@ -10,9 +10,7 @@ use Illuminate\Http\Request;
class TravelTypeController extends Controller
{
/**
* لیست + جستجو + صفحه‌بندی انواع سفر
*/
public function index(Request $request)
{
abort_unless(auth('admin')->user()->canManageTravelTypes('view'), 403);
@@ -27,7 +25,7 @@ class TravelTypeController extends Controller
});
}
// فیلتر وضعیت (1=فعال، 0=غیرفعال)
// فیلتر وضعیت
if ($request->filled('status')) {
$query->where('status', $request->status);
}
+6 -156
View File
@@ -12,20 +12,18 @@ use Illuminate\Support\Facades\Hash;
class UserController extends Controller
{
/**
* لیست + جستجوی چندپارامتری
*/
public function index(Request $request)
{
// چک دسترسی: فقط مدیرانی که مجوز «مشاهده کاربران» دارند
abort_unless(auth('admin')->user()->canManageUsers('view'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('view'), 403);
$query = User::query();
// جستجوی کلی: نام / ایمیل / موبایل
if ($request->filled('search')) {
$query->where(function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%')
$q->where('first_name', 'like', '%' . $request->search . '%')
->orWhere('email', 'like', '%' . $request->search . '%')
->orWhere('mobile', 'like', '%' . $request->search . '%');
});
@@ -59,7 +57,7 @@ class UserController extends Controller
public function update(UserUpdateRequest $request, User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('edit'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('edit'), 403);
$data = $request->validated();
@@ -84,14 +82,14 @@ class UserController extends Controller
public function changePassword(User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
return view('admin.users.change-password', compact('user'));
}
public function updatePassword(UserPasswordUpdateRequest $request, User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
$user->update([
'password' => Hash::make($request->password),
@@ -101,151 +99,3 @@ class UserController extends Controller
->with('success', 'رمز عبور کاربر با موفقیت تغییر کرد.');
}
}
//
//
//namespace App\Http\Controllers\Admin;
//
//use App\Http\Controllers\Controller;
//use App\Http\Requests\UserPasswordUpdateRequest;
//use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
//use App\Http\Requests\UserUpdateRequest;
//use App\Models\User;
//use Illuminate\Http\Request;
//use Illuminate\Support\Facades\Hash;
//
//class UserController extends Controller
//{
//
// /**
// * لیست + جستجوی چندپارامتری
// */
// public function index(Request $request)
// {
// // چک دسترسی: فقط مدیرانی که مجوز «مشاهده کاربران» دارند
// $this->authorize('users.view');
//
// $query = User::query();
//
// // جستجوی کلی: نام / ایمیل / موبایل
// if ($request->filled('search')) {
// $query->where(function ($q) use ($request) {
// $q->where('name', 'like', '%' . $request->search . '%')
// ->orWhere('email', 'like', '%' . $request->search . '%')
// ->orWhere('mobile', 'like', '%' . $request->search . '%');
// });
// }
//
// // فیلتر وضعیت
// if ($request->filled('status')) {
// $query->where('status', $request->status);
// }
//
// // فیلتر تاریخ عضویت
// if ($request->filled('from_date')) {
// $query->whereDate('created_at', '>=', $request->from_date);
// }
// if ($request->filled('to_date')) {
// $query->whereDate('created_at', '<=', $request->to_date);
// }
//
// // withQueryString => فیلترها هنگام صفحه‌بندی حفظ می‌شوند
// $users = $query->latest()->paginate(10)->withQueryString();
//
// return view('admin.users.index', compact('users'));
// }
//
//
// public function edit(User $user)
// {
// $this->authorize('users.edit');
//
// return view('admin.users.edit', compact('user'));
// }
//
// public function update(UserUpdateRequest $request, User $user)
// {
// $data = $request->validated();
//
// // اگر رمز خالی بود تغییرش نده (گزینه‌ای)
// unset($data['password']);
//
// $user->update($data);
//
// return redirect()->route('admin.users.index')
// ->with('success', 'اطلاعات کاربر با موفقیت ویرایش شد.');
// }
//
//
// public function destroy(User $user)
// {
// $this->authorize('users.delete');
//
// $user->delete();
//
// return redirect()->route('admin.users.index')
// ->with('success', 'کاربر با موفقیت حذف شد.');
// }
//
// public function changePassword(User $user)
// {
// $this->authorize('users.change-password');
//
// return view('admin.users.change-password', compact('user'));
// }
//
// public function updatePassword(UserPasswordUpdateRequest $request, User $user)
// {
// $user->update([
// 'password' => Hash::make($request->password),
// ]);
//
// return redirect()->route('admin.users.index')
// ->with('success', 'رمز عبور کاربر با موفقیت تغییر کرد.');
// }
//}
//
////
////namespace App\Http\Controllers\Admin;
////
////use App\Http\Controllers\Controller;
////use App\Http\Requests\UserStoreRequest;
////use App\Models\User;
////
////class UserController extends Controller
////{
//// public function index()
//// {
//// $users = User::latest()->paginate(15);
////
//// return view('admin.users.index', compact('users'));
//// }
////
//// public function show(User $user)
//// {
//// return view('admin.users.show', compact('user'));
//// }
////
//// public function edit(User $user)
//// {
//// return view('admin.users.edit', compact('user'));
//// }
////
//// public function update(UserStoreRequest $request, User $user)
//// {
//// $user->update($request->validated());
////
//// return redirect()
//// ->route('admin.users.index')
//// ->with('success', 'کاربر با موفقیت بروزرسانی شد.');
//// }
////
//// public function destroy(User $user)
//// {
//// $user->delete();
////
//// return redirect()
//// ->route('admin.users.index')
//// ->with('success', 'کاربر با موفقیت حذف شد.');
//// }
////}
+1 -14
View File
@@ -14,6 +14,7 @@ class AirportStoreRequest extends FormRequest
{
return true;
}
protected function prepareForValidation(): void
{
// کد فرودگاه همیشه با حروف بزرگ ذخیره شود (IATA)
@@ -68,18 +69,4 @@ class AirportStoreRequest extends FormRequest
'code' => 'کد فرودگاه',
];
}
// public function messages(): array
// {
// return [
// 'name.required' => 'نام فرودگاه الزامی است.',
// 'name.max' => 'نام فرودگاه حداکثر ۱۵۰ کاراکتر باشد.',
// 'city.required' => 'نام شهر الزامی است.',
// 'city.max' => 'نام شهر حداکثر ۱۰۰ کاراکتر باشد.',
// 'country.required' => 'نام کشور الزامی است.',
// 'country.max' => 'نام کشور حداکثر ۱۰۰ کاراکتر باشد.',
// 'code.required' => 'کد فرودگاه (IATA) الزامی است.',
// 'code.max' => 'کد فرودگاه حداکثر ۱۰ کاراکتر باشد.',
// ];
// }
}
+7 -2
View File
@@ -23,9 +23,14 @@ class LoginPostRequest extends FormRequest
public function rules(): array
{
return [
'email' => [
// 'email' => [
// 'required',
// 'email',
// ],
'username' => [
'required',
'email',
'string',
],
'password' => [
@@ -27,22 +27,24 @@ class RegisterPostRequest extends FormRequest
'first_name' => [
'required',
'persian_alpha',
'string',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'min:3',
'max:100'
],
'last_name' => [
'required',
'persian_alpha',
'string',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'max:100'
],
'national_code' => [
'required',
// 'ir_national_id',
'digits:10',
'unique:users,national_code',
],
@@ -66,15 +68,14 @@ class RegisterPostRequest extends FormRequest
'nullable',
'string',
'max:200',
'required_if:marital_status,2',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'required_if:marital_status,2'
],
'mobile' => [
'required',
'digits:11',
'regex:/^09\d{9}$/',
'ir_mobile:zero',
'unique:users,mobile',
],
@@ -89,10 +90,10 @@ class RegisterPostRequest extends FormRequest
'username' => [
'required',
'persian_not_accept',
'string',
'min:3',
'max:50',
'regex:/^[A-Za-z0-9]+$/',
'unique:users,username',
],
@@ -125,7 +126,6 @@ class RegisterPostRequest extends FormRequest
],
];
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
class CityStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' =>
[
'required',
'string',
'max:100'
],
'province_id' =>
[
'required',
'exists:provinces,id'
],
];
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace App\Http\Requests;
use App\Enums\PaymentStatus;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class CityUpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' =>
[
'required',
'string',
'max:100'
],
'province_id' =>
[
'required',
'exists:provinces,id'
],
];
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
class CommentStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'body' =>
[
'required',
'string',
'min:3',
'max:1000'
],
];
}
}
@@ -0,0 +1,66 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
class EditProfilePostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
// دریافت آیدی کاربر از طریق سشن لاگین
$userId = auth()->id();
return [
'first_name' =>
[
'required',
'string',
'max:100'
],
'last_name' =>
[
'required',
'string',
'max:100'
],
'username' =>
[
'required',
'string',
'max:50',
'unique:users,username,' . $userId,
],
'email' => [
'required',
'email',
'max:150',
'unique:users,email,' . $userId,
],
'password' =>
[
'nullable',
'string',
'min:8',
'confirmed'
],
];
}
}
@@ -0,0 +1,37 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class ProvinceUpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' =>
[
'required',
'string',
'max:100'
],
];
}
}
+1 -3
View File
@@ -29,9 +29,7 @@ class SettingUpdateRequest extends FormRequest
$this->merge($filtered);
}
/**
* قوانین اعتبارسنجی.
*/
public function rules(): array
{
$codes = Setting::pluck('code')->all();
@@ -12,8 +12,7 @@ class UserPasswordUpdateRequest extends FormRequest
*/
public function authorize(): bool
{
// return true;
return auth('admin')->user()->can('users.change-password');
return true;
}
/**
@@ -24,6 +23,12 @@ class UserPasswordUpdateRequest extends FormRequest
public function rules(): array
{
return [
// چک کردن رمز فعلی کاربر
'current_password' =>
[
'nullable',
'current_password'
],
'password' =>
[
'required',
@@ -31,10 +36,6 @@ class UserPasswordUpdateRequest extends FormRequest
'min:8',
'confirmed'
],
'password_confirmation' =>
[
'required'
],
];
}
}
-11
View File
@@ -47,15 +47,4 @@ class UserStoreRequest extends FormRequest
],
];
}
// public function messages(): array
// {
// return [
// 'name.required' => 'نام و نام خانوادگی الزامی است.',
// 'email.required' => 'ایمیل الزامی است.',
// 'email.email' => 'فرمت ایمیل معتبر نیست.',
// 'email.unique' => 'این ایمیل قبلاً ثبت شده است.',
// 'password.required' => 'رمز عبور الزامی است.',
// 'password.confirmed' => 'تکرار رمز عبور مطابقت ندارد.',
// ];
// }
}
+10 -5
View File
@@ -23,19 +23,24 @@ class UserUpdateRequest extends FormRequest
public function rules(): array
{
return [
'name' =>
'first_name' =>
[
'required',
'string',
'max:255'
'max:100'
],
'last_name' =>
[
'required',
'string',
'max:100'
],
'email' =>
[
'required',
'nullable',
'email',
'max:255',
'unique:users',
'email,' . $this->user->id
'unique:users,email,' . $this->user->id,
],
'mobile' =>
+6 -11
View File
@@ -1,5 +1,6 @@
<?php
/**
* Created by Reliese Model.
*/
@@ -8,12 +9,8 @@ namespace App\Models;
use App\Enums\AdminStatus;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
//use Illuminate\Foundation\Auth\Admin as Authenticate;
//use Illuminate\Foundation\Auth\Admin as Authenticate;
/**
* Class Admin
@@ -30,8 +27,10 @@ use Illuminate\Database\Eloquent\Model;
*
* @package App\Models
*/
class Admin extends User
class Admin extends Authenticatable
{
use HasFactory;
protected $table = 'admins';
public static $snakeAttributes = false;
@@ -42,6 +41,7 @@ class Admin extends User
protected $hidden = [
'password',
'remember_token',
];
protected $fillable = [
@@ -63,19 +63,14 @@ class Admin extends User
);
}
/**
* بررسی دسترسی مدیر به ماژول مدیریت کاربران
*
* @param string $action view|edit|delete|password
*/
public function canManageUsers(string $action): bool
{
// مدیریت کاربران فقط برای مدیر فعال مجاز است
return $this->status == 1;
}
public function canManageTravelTypes(string $action): bool
{
return $this->status == 1;
+1 -11
View File
@@ -53,19 +53,9 @@ class Comment extends Model
return $this->belongsTo(User::class);
}
// ✅ رابطه پلیمورفیک: نظر میتونه متعلق به محصول، خبر، پست و... باشه
// رابطه پلیمورفیک
public function commentable(): MorphTo
{
return $this->morphTo();
}
// public function comment()
// {
// return $this->belongsTo(Comment::class, 'commentable_id');
// }
//
// public function comments()
// {
// return $this->hasMany(Comment::class, 'commentable_id');
// }
}
+1 -1
View File
@@ -47,7 +47,7 @@ class Favorite extends Model
return $this->belongsTo(User::class);
}
// رابطه پلیمورفیک: علاقهمندی میتونه به محصول، خبر، پست و... وصل باشه
// رابطه پلیمورفیک
public function favoritable(): MorphTo
{
return $this->morphTo();
+25 -112
View File
@@ -1,32 +1,27 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Model;
/**
* Class Flight
*/
class Flight extends Model
{
protected $table = 'flights';
protected $casts = [
'travel_type_id' => 'int',
'travel_type_id' => 'integer',
'departure_date' => 'date',
'arrival_date' => 'date',
'departure_time' => 'datetime',
'arrival_time' => 'datetime',
'price' => 'decimal:2',
'capacity' => 'int',
'status' => 'int',
'capacity' => 'integer',
'status' => 'integer',
];
protected $fillable = [
@@ -45,135 +40,53 @@ class Flight extends Model
'status',
];
// مبدا پرواز
public function origin()
{
return $this->belongsTo(Airport::class, 'origin_airport_id');
}
// مقصد پرواز
public function destination()
{
return $this->belongsTo(Airport::class, 'destination_airport_id');
}
/* ------------------------- روابط (Relations) ------------------------- */
/**
* نوع سفر (داخلی/خارجی/چارتر) مرتبط با این پرواز
*/
public function travelType()
{
return $this->belongsTo(TravelType::class);
return $this->belongsTo(
TravelType::class,
'travel_type_id'
);
}
/**
* تورهای مرتبط با این پرواز
*/
public function tours()
{
return $this->belongsToMany(Tour::class, 'tour_flights')
return $this->belongsToMany(
Tour::class,
'tour_flights'
)
->withPivot('id')
->withTimestamps();
}
/* --------------------------- Helper ها ------------------------------ */
public function statusLabel(): string
{
return $this->status == 1 ? 'فعال' : 'غیرفعال';
return (int)$this->status === 1
? 'فعال'
: 'غیرفعال';
}
public function isActive(): bool
{
return (int)$this->status === 1;
}
/**
* اسکوپ برای پروازهای فعال
*/
#[Scope]
public function scopeActive($query)
{
return $query->where('status', 1);
}
public function getRouteKeyName(): string
{
return 'id';
}
}
//
///**
// * Created by Reliese Model.
// */
//
//namespace App\Models;
//
//use Carbon\Carbon;
//use Illuminate\Database\Eloquent\Collection;
//use Illuminate\Database\Eloquent\Model;
//
///**
// * Class Flight
// *
// * @property int $id
// * @property int $travel_type_id
// * @property string $flight_number
// * @property string $airline_name
// * @property string $origin
// * @property string $destination
// * @property Carbon $departure_date
// * @property Carbon $departure_time
// * @property Carbon $arrival_date
// * @property Carbon $arrival_time
// * @property string $duration
// * @property float $price
// * @property int $capacity
// * @property int $status
// * @property Carbon $created_at
// * @property Carbon $updated_at
// *
// * @property Collection|Tour[] $tours
// *
// * @package App\Models
// */
//class Flight extends Model
//{
// protected $table = 'flights';
// public static $snakeAttributes = false;
//
// protected $casts = [
// 'travel_type_id' => 'int',
// 'departure_date' => 'datetime',
// 'departure_time' => 'datetime',
// 'arrival_date' => 'datetime',
// 'arrival_time' => 'datetime',
// 'price' => 'float',
// 'capacity' => 'int',
// 'status' => 'int'
// ];
//
// protected $fillable = [
// 'travel_type_id',
// 'flight_number',
// 'airline_name',
// 'origin',
// 'destination',
// 'departure_date',
// 'departure_time',
// 'arrival_date',
// 'arrival_time',
// 'duration',
// 'price',
// 'capacity',
// 'status'
// ];
//
// public function tours()
// {
// return $this->belongsToMany(Tour::class, 'tour_flights')
// ->withPivot('id')
// ->withTimestamps();
// }
//}
+40
View File
@@ -75,4 +75,44 @@ class Tour extends Model
->withPivot('id')
->withTimestamps();
}
// در فایل App\Models\Tour.php و App\Models\Flight.php
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function favorites()
{
return $this->morphMany(\App\Models\Favorite::class, 'favoritable');
}
public function isFavoritedBy($user)
{
if (!$user) return false;
// استفاده از فیلدهای پلی‌مورفیک به جای tour_id
return $this->favorites()
->where('user_id', $user->id)
->where('favoritable_id', $this->id)
->where('favoritable_type', Tour::class)
->exists();
}
protected static function booted()
{
static::creating(function ($tour) {
// اگر مقداری تعیین نشده بود، پیش‌فرض‌ها را اعمال کن
if (is_null($tour->views_count)) {
$tour->views_count = 0;
}
if (is_null($tour->status)) {
// فرض بر اینکه 0 یعنی غیرفعال یا پیش‌نویس
$tour->status = 0;
}
});
}
}
+2 -1
View File
@@ -7,6 +7,7 @@
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
@@ -38,7 +39,7 @@ use Illuminate\Database\Eloquent\Model;
*
* @package App\Models
*/
class User extends Model
class User extends Authenticatable
{
protected $table = 'users';
public static $snakeAttributes = false;
+2 -1
View File
@@ -13,7 +13,8 @@
"hekmatinasser/verta": "^9.0",
"laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1",
"maatwebsite/excel": "^4.0"
"maatwebsite/excel": "^4.0",
"sadegh19b/laravel-persian-validation": "^2.1"
},
"require-dev": {
"fakerphp/faker": "^1.23",
Generated
+64 -1
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5b89eabef4196cd293b2611199f21233",
"content-hash": "338165288c07f7469e57955c0c1ad7c3",
"packages": [
{
"name": "brick/math",
@@ -4018,6 +4018,69 @@
},
"time": "2026-06-18T03:57:49+00:00"
},
{
"name": "sadegh19b/laravel-persian-validation",
"version": "v2.1.0",
"source": {
"type": "git",
"url": "https://github.com/sadegh19b/laravel-persian-validation.git",
"reference": "827b446c54121d9fcb0e06415788645c62f7dcd0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sadegh19b/laravel-persian-validation/zipball/827b446c54121d9fcb0e06415788645c62f7dcd0",
"reference": "827b446c54121d9fcb0e06415788645c62f7dcd0",
"shasum": ""
},
"require": {
"illuminate/support": "^11.0|^12.0|^13.0",
"php": ">=8.2"
},
"require-dev": {
"orchestra/testbench": "^9.0",
"phpunit/phpunit": "^11.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Sadegh19b\\LaravelPersianValidation\\PersianValidationServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Sadegh19b\\LaravelPersianValidation\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sadegh Barzegar",
"email": "sadegh19b@gmail.com",
"homepage": "https://github.com/sadegh19b",
"role": "Developer"
}
],
"description": "A comprehensive Laravel validation package for Persian text, numbers, dates, and Iranian national identifiers",
"homepage": "https://github.com/sadegh19b/laravel-persian-validation",
"keywords": [
"farsi",
"laravel",
"persian",
"validate",
"validation",
"validator"
],
"support": {
"issues": "https://github.com/sadegh19b/laravel-persian-validation/issues",
"source": "https://github.com/sadegh19b/laravel-persian-validation/tree/v2.1.0"
},
"time": "2026-04-25T07:43:18+00:00"
},
{
"name": "symfony/clock",
"version": "v8.1.0",
+526
View File
@@ -0,0 +1,526 @@
-- phpMyAdmin SQL Dump
-- version 5.2.3
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3308
-- Generation Time: Aug 20, 2026 at 04:33 AM
-- Server version: 8.4.7
-- PHP Version: 8.3.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `airline_agency`
--
-- --------------------------------------------------------
--
-- Table structure for table `admins`
--
DROP TABLE IF EXISTS `admins`;
CREATE TABLE IF NOT EXISTS `admins` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`full_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:disable 1:enable',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `admins`
--
INSERT INTO `admins` (`id`, `full_name`, `username`, `email`, `mobile`, `password`, `status`, `created_at`, `updated_at`) VALUES
(2, 'شهرزاد زندی', 'shahrzad', 'shahrzad.zandi@gmail.com', '09359359350', '$2y$12$KpHLJK1kIz/TxVUOn4FV7udVA3xGLLDtEknPZyfh13Z2WPkRmHwni', 1, '2026-08-17 07:24:19', '2026-08-17 07:24:19'),
(3, 'مدیر سیستم', 'admin', 'admin@gmail.com', '09123456789', '$2y$12$ElsUA1CqyK6euG6adWhXRuayR/Jzcq1zH28eoN3ypfeVrmTIr/zAe', 1, '2026-08-17 07:44:25', '2026-08-17 09:12:14');
-- --------------------------------------------------------
--
-- Table structure for table `admin_permission`
--
DROP TABLE IF EXISTS `admin_permission`;
CREATE TABLE IF NOT EXISTS `admin_permission` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`admin_id` bigint UNSIGNED NOT NULL,
`permission_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk1_admin_permission` (`permission_id`),
KEY `fk2_admin_permission` (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `airports`
--
DROP TABLE IF EXISTS `airports`;
CREATE TABLE IF NOT EXISTS `airports` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`city` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `airports`
--
INSERT INTO `airports` (`id`, `name`, `city`, `province`, `code`, `created_at`, `updated_at`) VALUES
(1, 'فرودگاه بین‌المللی اهواز', 'اهواز', 'خوزستان', 'AWZ', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
-- --------------------------------------------------------
--
-- Table structure for table `bookings`
--
DROP TABLE IF EXISTS `bookings`;
CREATE TABLE IF NOT EXISTS `bookings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`tour_id` bigint UNSIGNED DEFAULT NULL,
`flight_id` bigint UNSIGNED DEFAULT NULL,
`booking_code` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`passengers` int UNSIGNED NOT NULL DEFAULT '1',
`price` decimal(15,2) NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`payment_status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_bookings` (`user_id`),
KEY `fk2_bookings` (`tour_id`),
KEY `fk3_bookings` (`flight_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `cities`
--
DROP TABLE IF EXISTS `cities`;
CREATE TABLE IF NOT EXISTS `cities` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`province_id` bigint UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk1_cities` (`province_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `cities`
--
INSERT INTO `cities` (`id`, `province_id`, `name`, `created_at`, `updated_at`) VALUES
(7, 2, 'ساری', NULL, NULL),
(8, 1, 'تهران', NULL, NULL),
(9, 5, 'شیراز', NULL, NULL),
(10, 4, 'اصفهان', NULL, NULL),
(11, 1, 'ری', NULL, NULL),
(12, 2, 'آمل', NULL, NULL);
-- --------------------------------------------------------
--
-- Table structure for table `comments`
--
DROP TABLE IF EXISTS `comments`;
CREATE TABLE IF NOT EXISTS `comments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`commentable_id` bigint UNSIGNED NOT NULL,
`commentable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`body` text COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_ comments` (`user_id`),
KEY `fk2_ comments` (`commentable_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `favorites`
--
DROP TABLE IF EXISTS `favorites`;
CREATE TABLE IF NOT EXISTS `favorites` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`favoritable_id` bigint UNSIGNED NOT NULL,
`favoritable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_favorites` (`user_id`),
KEY `fk2_favorites` (`favoritable_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `favorites`
--
INSERT INTO `favorites` (`id`, `user_id`, `favoritable_id`, `favoritable_type`, `created_at`, `updated_at`) VALUES
(3, 1, 3, 'App\\Models\\Tour', '2026-08-19 16:05:52', '2026-08-19 16:05:52'),
(4, 1, 4, 'App\\Models\\Tour', '2026-08-19 16:11:50', '2026-08-19 16:11:50');
-- --------------------------------------------------------
--
-- Table structure for table `files`
--
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`fileable_id` bigint DEFAULT NULL,
`fileable_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`extension` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`size` bigint UNSIGNED NOT NULL,
`original_name` varchar(350) COLLATE utf8mb4_unicode_ci NOT NULL,
`path` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `flights`
--
DROP TABLE IF EXISTS `flights`;
CREATE TABLE IF NOT EXISTS `flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED NOT NULL,
`flight_number` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`airline_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`origin` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`destination` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`departure_date` date NOT NULL,
`departure_time` time NOT NULL,
`arrival_date` date NOT NULL,
`arrival_time` time NOT NULL,
`duration` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED NOT NULL,
`status` tinyint NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `flights`
--
INSERT INTO `flights` (`id`, `travel_type_id`, `flight_number`, `airline_name`, `origin`, `destination`, `departure_date`, `departure_time`, `arrival_date`, `arrival_time`, `duration`, `price`, `capacity`, `status`, `created_at`, `updated_at`) VALUES
(1, 2, 'IR-725', 'ایران ایر', 'تهران', 'مشهد', '1405-06-03', '14:30:00', '1405-06-03', '16:00:00', '1 ساعت و 30 دقیقه', 2500000.00, 180, 0, '2026-08-17 13:52:44', '2026-08-17 13:56:00'),
(2, 3, 'TK-182', 'ترکیش ایرلاینز', 'تهران', 'استانبول', '2026-08-28', '20:00:00', '2026-08-29', '07:31:00', '11 ساعت و 31', 18500000.00, 220, 1, '2026-08-17 14:01:19', '2026-08-17 14:01:19'),
(3, 4, 'CH-401', 'وارش', 'تهران', 'کیش', '2026-09-01', '10:30:00', '2026-09-01', '20:33:00', '10 ساعت و3 دقیقه', 4200000.00, 160, 1, '2026-08-17 14:04:34', '2026-08-17 14:04:34'),
(4, 2, 'ia33', 'test', 'test', 'test', '1405-05-06', '20:12:00', '1405-05-06', '22:06:00', '2', 850000.00, 2, 1, '2026-08-19 13:38:25', '2026-08-19 13:38:25');
-- --------------------------------------------------------
--
-- Table structure for table `payments`
--
DROP TABLE IF EXISTS `payments`;
CREATE TABLE IF NOT EXISTS `payments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`payable_id` bigint UNSIGNED NOT NULL,
`amount` decimal(12,2) NOT NULL,
`authority` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`transaction_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint NOT NULL COMMENT 'pending:0 | success:1| failed:2 | canceled:3',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `permissions`
--
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE IF NOT EXISTS `permissions` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `provinces`
--
DROP TABLE IF EXISTS `provinces`;
CREATE TABLE IF NOT EXISTS `provinces` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `provinces`
--
INSERT INTO `provinces` (`id`, `name`, `created_at`, `updated_at`) VALUES
(1, 'تهران', NULL, NULL),
(2, 'مازندران', NULL, NULL),
(3, 'گیلان', NULL, NULL),
(4, 'اصفهان', NULL, NULL),
(5, 'فارس', NULL, NULL),
(6, 'یزد', NULL, NULL),
(7, 'آذربایجان غربی', NULL, NULL),
(8, 'آذربایجان شرقی', NULL, NULL);
-- --------------------------------------------------------
--
-- Table structure for table `settings`
--
DROP TABLE IF EXISTS `settings`;
CREATE TABLE IF NOT EXISTS `settings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`code` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `tours`
--
DROP TABLE IF EXISTS `tours`;
CREATE TABLE IF NOT EXISTS `tours` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED DEFAULT NULL,
`title` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`duration` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED DEFAULT NULL,
`views_count` int NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tours` (`travel_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `tours`
--
INSERT INTO `tours` (`id`, `travel_type_id`, `title`, `slug`, `image`, `description`, `duration`, `start_date`, `end_date`, `price`, `capacity`, `views_count`, `status`, `created_at`, `updated_at`) VALUES
(3, NULL, 'تور سه‌روزه اصفهان با راهنمای تخصصی', 'tor-shrozh-asfhan-ba-rahnmay-tkhssy', 'tours/1787037667.tour-image56011.jpg', NULL, NULL, NULL, NULL, 2850000.00, NULL, 28, 1, '2026-08-18 07:21:07', '2026-08-20 01:19:33'),
(4, NULL, 'تور لوکس پنج‌روزه کیش با پرواز مستقیم', 'tor-loks-pngrozh-kysh-ba-proaz-mstkym', 'tours/1787037718.tour-image49479.jpg', NULL, NULL, NULL, NULL, 12500000.00, NULL, 31, 1, '2026-08-18 07:21:58', '2026-08-20 01:20:50'),
(5, NULL, 'تور خانوادگی پنج‌روزه قشم و هرمز', 'tor-khanoadgy-pngrozh-kshm-o-hrmz', 'tours/1787138709.tour-image35820.jpg', NULL, NULL, NULL, NULL, 9750000.00, NULL, 0, 0, '2026-08-19 11:25:09', '2026-08-19 11:25:11'),
(6, NULL, 'تور شش‌روزه رم و فلورانس', 'tor-shshrozh-rm-o-florans', 'tours/1787138776.tour-image35964.jpg', NULL, NULL, NULL, NULL, 76500000.00, NULL, 0, 0, '2026-08-19 11:26:16', '2026-08-19 11:26:16'),
(7, NULL, 'تور لوکس هفت‌روزه پاریس', 'tor-loks-hftrozh-parys', 'tours/1787138834.tour-image66216.jpg', NULL, NULL, NULL, NULL, 89000000.00, NULL, 0, 0, '2026-08-19 11:27:14', '2026-08-19 11:27:14'),
(8, NULL, 'تور اقتصادی چهارروزه باکو', 'tor-aktsady-chharrozh-bako', 'tours/1787138868.tour-image42665.jpg', NULL, NULL, NULL, NULL, 15800000.00, NULL, 0, 0, '2026-08-19 11:27:48', '2026-08-19 11:27:48'),
(9, NULL, 'test', 'test', 'tours/1787146812.tour-image88373.jpg', NULL, NULL, NULL, NULL, 2000000.00, NULL, 0, 0, '2026-08-19 13:40:12', '2026-08-19 13:40:14');
-- --------------------------------------------------------
--
-- Table structure for table `tour_flights`
--
DROP TABLE IF EXISTS `tour_flights`;
CREATE TABLE IF NOT EXISTS `tour_flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`tour_id` bigint UNSIGNED NOT NULL,
`flight_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tour_flights` (`flight_id`),
KEY `fk2_tour_flights` (`tour_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `travel_types`
--
DROP TABLE IF EXISTS `travel_types`;
CREATE TABLE IF NOT EXISTS `travel_types` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `travel_types`
--
INSERT INTO `travel_types` (`id`, `title`, `slug`, `status`, `created_at`, `updated_at`) VALUES
(2, 'تور داخلی', 'domestic-tour', 1, '2026-08-17 11:36:22', '2026-08-17 11:36:22'),
(3, 'تور خارجی', 'international-tour', 1, '2026-08-17 11:46:33', '2026-08-17 11:46:33'),
(4, 'تور چارتر', 'charter-tour', 1, '2026-08-17 11:46:59', '2026-08-17 11:46:59'),
(5, 'تور ترکیبی', 'combined-tour', 1, '2026-08-17 11:47:41', '2026-08-17 11:47:41'),
(6, 'پرواز خارجی', 'international-flight', 1, '2026-08-17 11:48:19', '2026-08-17 11:48:19'),
(7, 'پرواز داخلی', 'domestic-flight', 1, '2026-08-17 11:48:44', '2026-08-17 11:48:44'),
(8, 'تور لحظه آخری', 'last-minute', 1, '2026-08-17 11:49:11', '2026-08-17 11:49:11'),
(9, 'پیشنویس نمونه', 'draft-sample', 0, '2026-08-17 11:49:33', '2026-08-17 11:56:13');
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth_date` date DEFAULT NULL,
`gender` tinyint(1) NOT NULL COMMENT '1:Male | 2:Female',
`marital_status` tinyint(1) NOT NULL COMMENT '1:Single | 2:Married | 3:Divorced/Separated',
`spouse_name` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`username` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`province_id` bigint UNSIGNED NOT NULL,
`city_id` bigint UNSIGNED DEFAULT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `first_name`, `last_name`, `email`, `mobile`, `password`, `national_code`, `birth_date`, `gender`, `marital_status`, `spouse_name`, `image`, `username`, `province_id`, `city_id`, `status`, `created_at`, `updated_at`) VALUES
(1, 'شهرزاد', 'زندی', 'shahrzad.zandi011@gmail.com', '09118909120', '$2y$12$LzDaglfvgypwHT20MAffJOnjpIePJbwJjIcbnoRW8tLy53wNbfFqa', '2080706640', NULL, 2, 1, NULL, 'users/zCDeIumAUhjqbKYwlu8wsDiKgl462J48eiBrF7wN.jpg', 'shahrzad011', 2, NULL, 1, '2026-08-19 01:09:30', '2026-08-19 01:09:30'),
(2, 'حاتمه', 'اندرزا', 'hatame19@gmail.com', '09119533286', '$2y$12$6AxXNTIpJAK0czNU78PeAObgC.Nl0dTbqKyyMHSGTUrr0GynKyfhq', '2081391693', NULL, 2, 1, NULL, 'users/MU5t6XmUmS558EO4EPQUdO2kDL7XSeDEtoeP83LD.jpg', 'hatame19', 2, NULL, 1, '2026-08-19 06:23:09', '2026-08-19 06:23:09');
--
-- Constraints for dumped tables
--
--
-- Constraints for table `admin_permission`
--
ALTER TABLE `admin_permission`
ADD CONSTRAINT `fk1_admin_permission` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_admin_permission` FOREIGN KEY (`admin_id`) REFERENCES `admins` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `bookings`
--
ALTER TABLE `bookings`
ADD CONSTRAINT `fk1_bookings` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_bookings` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk3_bookings` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `cities`
--
ALTER TABLE `cities`
ADD CONSTRAINT `fk1_cities` FOREIGN KEY (`province_id`) REFERENCES `provinces` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `comments`
--
ALTER TABLE `comments`
ADD CONSTRAINT `fk1_ comments` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_ comments` FOREIGN KEY (`commentable_id`) REFERENCES `comments` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `favorites`
--
ALTER TABLE `favorites`
ADD CONSTRAINT `fk1_favorites` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_favorites` FOREIGN KEY (`favoritable_id`) REFERENCES `favorites` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tours`
--
ALTER TABLE `tours`
ADD CONSTRAINT `fk1_tours` FOREIGN KEY (`travel_type_id`) REFERENCES `travel_types` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tour_flights`
--
ALTER TABLE `tour_flights`
ADD CONSTRAINT `fk1_tour_flights` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_tour_flights` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+532
View File
@@ -0,0 +1,532 @@
-- phpMyAdmin SQL Dump
-- version 5.2.3
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3308
-- Generation Time: Aug 20, 2026 at 01:33 PM
-- Server version: 8.4.7
-- PHP Version: 8.3.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `airline_agency`
--
-- --------------------------------------------------------
--
-- Table structure for table `admins`
--
DROP TABLE IF EXISTS `admins`;
CREATE TABLE IF NOT EXISTS `admins` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`full_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:disable 1:enable',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `admins`
--
INSERT INTO `admins` (`id`, `full_name`, `username`, `email`, `mobile`, `password`, `status`, `created_at`, `updated_at`) VALUES
(2, 'شهرزاد زندی', 'shahrzad', 'shahrzad.zandi@gmail.com', '09359359350', '$2y$12$KpHLJK1kIz/TxVUOn4FV7udVA3xGLLDtEknPZyfh13Z2WPkRmHwni', 1, '2026-08-17 07:24:19', '2026-08-17 07:24:19'),
(3, 'مدیر سیستم', 'admin', 'admin@gmail.com', '09123456789', '$2y$12$ElsUA1CqyK6euG6adWhXRuayR/Jzcq1zH28eoN3ypfeVrmTIr/zAe', 1, '2026-08-17 07:44:25', '2026-08-17 09:12:14');
-- --------------------------------------------------------
--
-- Table structure for table `admin_permission`
--
DROP TABLE IF EXISTS `admin_permission`;
CREATE TABLE IF NOT EXISTS `admin_permission` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`admin_id` bigint UNSIGNED NOT NULL,
`permission_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk1_admin_permission` (`permission_id`),
KEY `fk2_admin_permission` (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `airports`
--
DROP TABLE IF EXISTS `airports`;
CREATE TABLE IF NOT EXISTS `airports` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`city` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `airports`
--
INSERT INTO `airports` (`id`, `name`, `city`, `province`, `code`, `created_at`, `updated_at`) VALUES
(1, 'فرودگاه بین‌المللی اهواز', 'اهواز', 'خوزستان', 'AWZ', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
-- --------------------------------------------------------
--
-- Table structure for table `bookings`
--
DROP TABLE IF EXISTS `bookings`;
CREATE TABLE IF NOT EXISTS `bookings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`tour_id` bigint UNSIGNED DEFAULT NULL,
`flight_id` bigint UNSIGNED DEFAULT NULL,
`booking_code` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`passengers` int UNSIGNED NOT NULL DEFAULT '1',
`price` decimal(15,2) NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`payment_status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_bookings` (`user_id`),
KEY `fk2_bookings` (`tour_id`),
KEY `fk3_bookings` (`flight_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `cities`
--
DROP TABLE IF EXISTS `cities`;
CREATE TABLE IF NOT EXISTS `cities` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`province_id` bigint UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk1_cities` (`province_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `cities`
--
INSERT INTO `cities` (`id`, `province_id`, `name`, `created_at`, `updated_at`) VALUES
(7, 2, 'ساری', NULL, NULL),
(8, 1, 'تهران', NULL, NULL),
(9, 5, 'شیراز', NULL, NULL),
(10, 4, 'اصفهان', NULL, NULL),
(11, 1, 'ری', NULL, NULL),
(12, 2, 'آمل', NULL, NULL);
-- --------------------------------------------------------
--
-- Table structure for table `comments`
--
DROP TABLE IF EXISTS `comments`;
CREATE TABLE IF NOT EXISTS `comments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`commentable_id` bigint UNSIGNED NOT NULL,
`commentable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`body` text COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_ comments` (`user_id`),
KEY `fk2_ comments` (`commentable_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `comments`
--
INSERT INTO `comments` (`id`, `user_id`, `commentable_id`, `commentable_type`, `body`, `status`, `created_at`, `updated_at`) VALUES
(2, 1, 3, 'App\\Models\\Tour', 'بسیار خوب بود', 1, '2026-08-20 10:15:43', '2026-08-20 10:15:43'),
(3, 1, 3, 'App\\Models\\Tour', 'خیلی هم عالی', 1, '2026-08-20 10:17:07', '2026-08-20 10:17:07'),
(4, 1, 3, 'App\\Models\\Tour', 'من این تور را پسندیدم.', 1, '2026-08-20 13:15:04', '2026-08-20 13:15:04');
-- --------------------------------------------------------
--
-- Table structure for table `favorites`
--
DROP TABLE IF EXISTS `favorites`;
CREATE TABLE IF NOT EXISTS `favorites` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`favoritable_id` bigint UNSIGNED NOT NULL,
`favoritable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_favorites` (`user_id`),
KEY `fk2_favorites` (`favoritable_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `favorites`
--
INSERT INTO `favorites` (`id`, `user_id`, `favoritable_id`, `favoritable_type`, `created_at`, `updated_at`) VALUES
(3, 1, 3, 'App\\Models\\Tour', '2026-08-19 16:05:52', '2026-08-19 16:05:52');
-- --------------------------------------------------------
--
-- Table structure for table `files`
--
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`fileable_id` bigint DEFAULT NULL,
`fileable_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`extension` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`size` bigint UNSIGNED NOT NULL,
`original_name` varchar(350) COLLATE utf8mb4_unicode_ci NOT NULL,
`path` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `flights`
--
DROP TABLE IF EXISTS `flights`;
CREATE TABLE IF NOT EXISTS `flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED NOT NULL,
`flight_number` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`airline_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`origin` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`destination` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`departure_date` date NOT NULL,
`departure_time` time NOT NULL,
`arrival_date` date NOT NULL,
`arrival_time` time NOT NULL,
`duration` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED NOT NULL,
`status` tinyint NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `flights`
--
INSERT INTO `flights` (`id`, `travel_type_id`, `flight_number`, `airline_name`, `origin`, `destination`, `departure_date`, `departure_time`, `arrival_date`, `arrival_time`, `duration`, `price`, `capacity`, `status`, `created_at`, `updated_at`) VALUES
(1, 2, 'IR-725', 'ایران ایر', 'تهران', 'مشهد', '1405-06-03', '14:30:00', '1405-06-03', '16:00:00', '1 ساعت و 30 دقیقه', 2500000.00, 180, 0, '2026-08-17 13:52:44', '2026-08-17 13:56:00'),
(2, 3, 'TK-182', 'ترکیش ایرلاینز', 'تهران', 'استانبول', '2026-08-28', '20:00:00', '2026-08-29', '07:31:00', '11 ساعت و 31', 18500000.00, 220, 1, '2026-08-17 14:01:19', '2026-08-17 14:01:19'),
(3, 4, 'CH-401', 'وارش', 'تهران', 'کیش', '2026-09-01', '10:30:00', '2026-09-01', '20:33:00', '10 ساعت و3 دقیقه', 4200000.00, 160, 1, '2026-08-17 14:04:34', '2026-08-17 14:04:34'),
(4, 2, 'ia33', 'test', 'test', 'test', '1405-05-06', '20:12:00', '1405-05-06', '22:06:00', '2', 850000.00, 2, 1, '2026-08-19 13:38:25', '2026-08-19 13:38:25');
-- --------------------------------------------------------
--
-- Table structure for table `payments`
--
DROP TABLE IF EXISTS `payments`;
CREATE TABLE IF NOT EXISTS `payments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`payable_id` bigint UNSIGNED NOT NULL,
`amount` decimal(12,2) NOT NULL,
`authority` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`transaction_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint NOT NULL COMMENT 'pending:0 | success:1| failed:2 | canceled:3',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `permissions`
--
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE IF NOT EXISTS `permissions` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `provinces`
--
DROP TABLE IF EXISTS `provinces`;
CREATE TABLE IF NOT EXISTS `provinces` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `provinces`
--
INSERT INTO `provinces` (`id`, `name`, `created_at`, `updated_at`) VALUES
(1, 'تهران', NULL, NULL),
(2, 'مازندران', NULL, NULL),
(3, 'گیلان', NULL, NULL),
(4, 'اصفهان', NULL, NULL),
(5, 'فارس', NULL, NULL),
(6, 'یزد', NULL, NULL),
(7, 'آذربایجان غربی', NULL, NULL),
(8, 'آذربایجان شرقی', NULL, NULL);
-- --------------------------------------------------------
--
-- Table structure for table `settings`
--
DROP TABLE IF EXISTS `settings`;
CREATE TABLE IF NOT EXISTS `settings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`code` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `tours`
--
DROP TABLE IF EXISTS `tours`;
CREATE TABLE IF NOT EXISTS `tours` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED DEFAULT NULL,
`title` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`duration` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED DEFAULT NULL,
`views_count` int NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tours` (`travel_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `tours`
--
INSERT INTO `tours` (`id`, `travel_type_id`, `title`, `slug`, `image`, `description`, `duration`, `start_date`, `end_date`, `price`, `capacity`, `views_count`, `status`, `created_at`, `updated_at`) VALUES
(3, NULL, 'تور سه‌روزه اصفهان با راهنمای تخصصی', 'tor-shrozh-asfhan-ba-rahnmay-tkhssy', 'tours/1787037667.tour-image56011.jpg', NULL, NULL, NULL, NULL, 2850000.00, NULL, 63, 1, '2026-08-18 07:21:07', '2026-08-20 13:15:04'),
(4, NULL, 'تور لوکس پنج‌روزه کیش با پرواز مستقیم', 'tor-loks-pngrozh-kysh-ba-proaz-mstkym', 'tours/1787037718.tour-image49479.jpg', NULL, NULL, NULL, NULL, 12500000.00, NULL, 36, 1, '2026-08-18 07:21:58', '2026-08-20 08:02:13'),
(5, NULL, 'تور خانوادگی پنج‌روزه قشم و هرمز', 'tor-khanoadgy-pngrozh-kshm-o-hrmz', 'tours/1787138709.tour-image35820.jpg', NULL, NULL, NULL, NULL, 9750000.00, NULL, 0, 0, '2026-08-19 11:25:09', '2026-08-19 11:25:11'),
(6, NULL, 'تور شش‌روزه رم و فلورانس', 'tor-shshrozh-rm-o-florans', 'tours/1787138776.tour-image35964.jpg', NULL, NULL, NULL, NULL, 76500000.00, NULL, 0, 0, '2026-08-19 11:26:16', '2026-08-19 11:26:16'),
(7, NULL, 'تور لوکس هفت‌روزه پاریس', 'tor-loks-hftrozh-parys', 'tours/1787138834.tour-image66216.jpg', NULL, NULL, NULL, NULL, 89000000.00, NULL, 0, 0, '2026-08-19 11:27:14', '2026-08-19 11:27:14'),
(8, NULL, 'تور اقتصادی چهارروزه باکو', 'tor-aktsady-chharrozh-bako', 'tours/1787138868.tour-image42665.jpg', NULL, NULL, NULL, NULL, 15800000.00, NULL, 0, 0, '2026-08-19 11:27:48', '2026-08-19 11:27:48'),
(9, NULL, 'test', 'test', 'tours/1787146812.tour-image88373.jpg', NULL, NULL, NULL, NULL, 2000000.00, NULL, 0, 0, '2026-08-19 13:40:12', '2026-08-19 13:40:14');
-- --------------------------------------------------------
--
-- Table structure for table `tour_flights`
--
DROP TABLE IF EXISTS `tour_flights`;
CREATE TABLE IF NOT EXISTS `tour_flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`tour_id` bigint UNSIGNED NOT NULL,
`flight_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tour_flights` (`flight_id`),
KEY `fk2_tour_flights` (`tour_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `travel_types`
--
DROP TABLE IF EXISTS `travel_types`;
CREATE TABLE IF NOT EXISTS `travel_types` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `travel_types`
--
INSERT INTO `travel_types` (`id`, `title`, `slug`, `status`, `created_at`, `updated_at`) VALUES
(2, 'تور داخلی', 'domestic-tour', 1, '2026-08-17 11:36:22', '2026-08-17 11:36:22'),
(3, 'تور خارجی', 'international-tour', 1, '2026-08-17 11:46:33', '2026-08-17 11:46:33'),
(4, 'تور چارتر', 'charter-tour', 1, '2026-08-17 11:46:59', '2026-08-17 11:46:59'),
(5, 'تور ترکیبی', 'combined-tour', 1, '2026-08-17 11:47:41', '2026-08-17 11:47:41'),
(6, 'پرواز خارجی', 'international-flight', 1, '2026-08-17 11:48:19', '2026-08-17 11:48:19'),
(7, 'پرواز داخلی', 'domestic-flight', 1, '2026-08-17 11:48:44', '2026-08-17 11:48:44'),
(8, 'تور لحظه آخری', 'last-minute', 1, '2026-08-17 11:49:11', '2026-08-17 11:49:11'),
(9, 'پیشنویس نمونه', 'draft-sample', 0, '2026-08-17 11:49:33', '2026-08-17 11:56:13');
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth_date` date DEFAULT NULL,
`gender` tinyint(1) NOT NULL COMMENT '1:Male | 2:Female',
`marital_status` tinyint(1) NOT NULL COMMENT '1:Single | 2:Married | 3:Divorced/Separated',
`spouse_name` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`username` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`province_id` bigint UNSIGNED NOT NULL,
`city_id` bigint UNSIGNED DEFAULT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `first_name`, `last_name`, `email`, `mobile`, `password`, `national_code`, `birth_date`, `gender`, `marital_status`, `spouse_name`, `image`, `username`, `province_id`, `city_id`, `status`, `created_at`, `updated_at`) VALUES
(1, 'شهرزاد', 'زندی', 'shahrzad2020@gmail.com', '09118909120', '$2y$12$LzDaglfvgypwHT20MAffJOnjpIePJbwJjIcbnoRW8tLy53wNbfFqa', '2080706640', NULL, 2, 1, NULL, 'avatars/FevHjQ0JjviBzlNOGXiI0k1JmshmUIxrDXF3xBAC.jpg', 'shahrzad011', 2, NULL, 1, '2026-08-19 01:09:30', '2026-08-20 13:16:51'),
(2, 'حاتمه', 'اندرزا', 'hatame19@gmail.com', '09119533286', '$2y$12$6AxXNTIpJAK0czNU78PeAObgC.Nl0dTbqKyyMHSGTUrr0GynKyfhq', '2081391693', NULL, 2, 1, NULL, 'users/MU5t6XmUmS558EO4EPQUdO2kDL7XSeDEtoeP83LD.jpg', 'hatame19', 2, NULL, 1, '2026-08-19 06:23:09', '2026-08-19 06:23:09');
--
-- Constraints for dumped tables
--
--
-- Constraints for table `admin_permission`
--
ALTER TABLE `admin_permission`
ADD CONSTRAINT `fk1_admin_permission` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_admin_permission` FOREIGN KEY (`admin_id`) REFERENCES `admins` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `bookings`
--
ALTER TABLE `bookings`
ADD CONSTRAINT `fk1_bookings` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_bookings` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk3_bookings` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `cities`
--
ALTER TABLE `cities`
ADD CONSTRAINT `fk1_cities` FOREIGN KEY (`province_id`) REFERENCES `provinces` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `comments`
--
ALTER TABLE `comments`
ADD CONSTRAINT `fk1_ comments` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `favorites`
--
ALTER TABLE `favorites`
ADD CONSTRAINT `fk1_favorites` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tours`
--
ALTER TABLE `tours`
ADD CONSTRAINT `fk1_tours` FOREIGN KEY (`travel_type_id`) REFERENCES `travel_types` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tour_flights`
--
ALTER TABLE `tour_flights`
ADD CONSTRAINT `fk1_tour_flights` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_tour_flights` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+538
View File
@@ -0,0 +1,538 @@
-- phpMyAdmin SQL Dump
-- version 5.2.3
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3308
-- Generation Time: Aug 22, 2026 at 07:47 AM
-- Server version: 8.4.7
-- PHP Version: 8.3.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `airline_agency`
--
-- --------------------------------------------------------
--
-- Table structure for table `admins`
--
DROP TABLE IF EXISTS `admins`;
CREATE TABLE IF NOT EXISTS `admins` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`full_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:disable 1:enable',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `admins`
--
INSERT INTO `admins` (`id`, `full_name`, `username`, `email`, `mobile`, `password`, `status`, `created_at`, `updated_at`) VALUES
(2, 'شهرزاد زندی', 'shahrzad', 'shahrzad.zandi@gmail.com', '09359359350', '$2y$12$KpHLJK1kIz/TxVUOn4FV7udVA3xGLLDtEknPZyfh13Z2WPkRmHwni', 1, '2026-08-17 07:24:19', '2026-08-17 07:24:19'),
(3, 'مدیر سیستم', 'admin', 'admin@gmail.com', '09123456789', '$2y$12$ElsUA1CqyK6euG6adWhXRuayR/Jzcq1zH28eoN3ypfeVrmTIr/zAe', 1, '2026-08-17 07:44:25', '2026-08-17 09:12:14');
-- --------------------------------------------------------
--
-- Table structure for table `admin_permission`
--
DROP TABLE IF EXISTS `admin_permission`;
CREATE TABLE IF NOT EXISTS `admin_permission` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`admin_id` bigint UNSIGNED NOT NULL,
`permission_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk1_admin_permission` (`permission_id`),
KEY `fk2_admin_permission` (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `airports`
--
DROP TABLE IF EXISTS `airports`;
CREATE TABLE IF NOT EXISTS `airports` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`city` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `airports`
--
INSERT INTO `airports` (`id`, `name`, `city`, `province`, `code`, `created_at`, `updated_at`) VALUES
(1, 'فرودگاه بین‌المللی اهواز', 'اهواز', 'خوزستان', 'AWZ', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
-- --------------------------------------------------------
--
-- Table structure for table `bookings`
--
DROP TABLE IF EXISTS `bookings`;
CREATE TABLE IF NOT EXISTS `bookings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`tour_id` bigint UNSIGNED DEFAULT NULL,
`flight_id` bigint UNSIGNED DEFAULT NULL,
`booking_code` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`passengers` int UNSIGNED NOT NULL DEFAULT '1',
`price` decimal(15,2) NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`payment_status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_bookings` (`user_id`),
KEY `fk2_bookings` (`tour_id`),
KEY `fk3_bookings` (`flight_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `cities`
--
DROP TABLE IF EXISTS `cities`;
CREATE TABLE IF NOT EXISTS `cities` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`province_id` bigint UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk1_cities` (`province_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `cities`
--
INSERT INTO `cities` (`id`, `province_id`, `name`, `created_at`, `updated_at`) VALUES
(7, 2, 'ساری', NULL, NULL),
(8, 1, 'تهران', NULL, NULL),
(9, 5, 'شیراز', NULL, NULL),
(10, 4, 'اصفهان', NULL, NULL),
(11, 1, 'ری', NULL, NULL),
(12, 2, 'آمل', NULL, NULL),
(13, 9, 'کرمان', '2026-08-22 04:57:54', '2026-08-22 04:57:54');
-- --------------------------------------------------------
--
-- Table structure for table `comments`
--
DROP TABLE IF EXISTS `comments`;
CREATE TABLE IF NOT EXISTS `comments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`commentable_id` bigint UNSIGNED NOT NULL,
`commentable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`body` text COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_ comments` (`user_id`),
KEY `fk2_ comments` (`commentable_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `comments`
--
INSERT INTO `comments` (`id`, `user_id`, `commentable_id`, `commentable_type`, `body`, `status`, `created_at`, `updated_at`) VALUES
(2, 1, 3, 'App\\Models\\Tour', 'بسیار خوب بود', 1, '2026-08-20 10:15:43', '2026-08-20 10:15:43'),
(3, 1, 3, 'App\\Models\\Tour', 'خیلی هم عالی', 1, '2026-08-20 10:17:07', '2026-08-20 10:17:07'),
(4, 1, 3, 'App\\Models\\Tour', 'من این تور را پسندیدم.', 1, '2026-08-20 13:15:04', '2026-08-20 13:15:04'),
(5, 1, 6, 'App\\Models\\Tour', 'بسیار سفر خوبی بود با این تور', 1, '2026-08-22 06:47:37', '2026-08-22 06:47:37');
-- --------------------------------------------------------
--
-- Table structure for table `favorites`
--
DROP TABLE IF EXISTS `favorites`;
CREATE TABLE IF NOT EXISTS `favorites` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`favoritable_id` bigint UNSIGNED NOT NULL,
`favoritable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_favorites` (`user_id`),
KEY `fk2_favorites` (`favoritable_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `favorites`
--
INSERT INTO `favorites` (`id`, `user_id`, `favoritable_id`, `favoritable_type`, `created_at`, `updated_at`) VALUES
(3, 1, 3, 'App\\Models\\Tour', '2026-08-19 16:05:52', '2026-08-19 16:05:52'),
(6, 1, 6, 'App\\Models\\Tour', '2026-08-22 06:39:47', '2026-08-22 06:39:47'),
(7, 1, 8, 'App\\Models\\Tour', '2026-08-22 06:48:01', '2026-08-22 06:48:01'),
(8, 1, 5, 'App\\Models\\Tour', '2026-08-22 07:37:20', '2026-08-22 07:37:20');
-- --------------------------------------------------------
--
-- Table structure for table `files`
--
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`fileable_id` bigint DEFAULT NULL,
`fileable_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`extension` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`size` bigint UNSIGNED NOT NULL,
`original_name` varchar(350) COLLATE utf8mb4_unicode_ci NOT NULL,
`path` varchar(300) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `flights`
--
DROP TABLE IF EXISTS `flights`;
CREATE TABLE IF NOT EXISTS `flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED NOT NULL,
`flight_number` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`airline_name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`origin` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`destination` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`departure_date` date NOT NULL,
`departure_time` time NOT NULL,
`arrival_date` date NOT NULL,
`arrival_time` time NOT NULL,
`duration` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED NOT NULL,
`status` tinyint NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `flights`
--
INSERT INTO `flights` (`id`, `travel_type_id`, `flight_number`, `airline_name`, `origin`, `destination`, `departure_date`, `departure_time`, `arrival_date`, `arrival_time`, `duration`, `price`, `capacity`, `status`, `created_at`, `updated_at`) VALUES
(1, 2, 'IR-725', 'ایران ایر', 'تهران', 'مشهد', '1405-06-03', '14:30:00', '1405-06-03', '16:00:00', '1 ساعت و 30 دقیقه', 2500000.00, 180, 0, '2026-08-17 13:52:44', '2026-08-17 13:56:00'),
(2, 3, 'TK-182', 'ترکیش ایرلاینز', 'تهران', 'استانبول', '2026-08-28', '20:00:00', '2026-08-29', '07:31:00', '11 ساعت و 31', 18500000.00, 220, 1, '2026-08-17 14:01:19', '2026-08-17 14:01:19'),
(3, 4, 'CH-401', 'وارش', 'تهران', 'کیش', '2026-09-01', '10:30:00', '2026-09-01', '20:33:00', '10 ساعت و3 دقیقه', 4200000.00, 160, 1, '2026-08-17 14:04:34', '2026-08-17 14:04:34'),
(4, 2, 'ia33', 'test', 'test', 'test', '1405-05-06', '20:12:00', '1405-05-06', '22:06:00', '2', 850000.00, 2, 1, '2026-08-19 13:38:25', '2026-08-19 13:38:25');
-- --------------------------------------------------------
--
-- Table structure for table `payments`
--
DROP TABLE IF EXISTS `payments`;
CREATE TABLE IF NOT EXISTS `payments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`payable_id` bigint UNSIGNED NOT NULL,
`amount` decimal(12,2) NOT NULL,
`authority` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`transaction_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint NOT NULL COMMENT 'pending:0 | success:1| failed:2 | canceled:3',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `permissions`
--
DROP TABLE IF EXISTS `permissions`;
CREATE TABLE IF NOT EXISTS `permissions` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `provinces`
--
DROP TABLE IF EXISTS `provinces`;
CREATE TABLE IF NOT EXISTS `provinces` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `provinces`
--
INSERT INTO `provinces` (`id`, `name`, `created_at`, `updated_at`) VALUES
(1, 'تهران', NULL, NULL),
(2, 'مازندران', NULL, NULL),
(3, 'گیلان', NULL, NULL),
(4, 'اصفهان', NULL, NULL),
(5, 'فارس', NULL, NULL),
(6, 'یزد', NULL, NULL),
(7, 'آذربایجان غربی', NULL, NULL),
(8, 'آذربایجان شرقی', NULL, NULL),
(9, 'کرمان', '2026-08-22 04:57:33', '2026-08-22 04:57:33');
-- --------------------------------------------------------
--
-- Table structure for table `settings`
--
DROP TABLE IF EXISTS `settings`;
CREATE TABLE IF NOT EXISTS `settings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`code` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `tours`
--
DROP TABLE IF EXISTS `tours`;
CREATE TABLE IF NOT EXISTS `tours` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`travel_type_id` bigint UNSIGNED DEFAULT NULL,
`title` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
`duration` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
`price` decimal(12,2) NOT NULL,
`capacity` int UNSIGNED DEFAULT NULL,
`views_count` int NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tours` (`travel_type_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `tours`
--
INSERT INTO `tours` (`id`, `travel_type_id`, `title`, `slug`, `image`, `description`, `duration`, `start_date`, `end_date`, `price`, `capacity`, `views_count`, `status`, `created_at`, `updated_at`) VALUES
(3, NULL, 'تور سه‌روزه اصفهان با راهنمای تخصصی', 'tor-shrozh-asfhan-ba-rahnmay-tkhssy', 'tours/1787037667.tour-image56011.jpg', NULL, NULL, NULL, NULL, 2850000.00, NULL, 80, 1, '2026-08-18 07:21:07', '2026-08-22 06:35:20'),
(4, NULL, 'تور لوکس پنج‌روزه کیش با پرواز مستقیم', 'tor-loks-pngrozh-kysh-ba-proaz-mstkym', 'tours/1787037718.tour-image49479.jpg', NULL, NULL, NULL, NULL, 12500000.00, NULL, 41, 1, '2026-08-18 07:21:58', '2026-08-21 15:21:22'),
(5, NULL, 'تور خانوادگی پنج‌روزه قشم و هرمز', 'tor-khanoadgy-pngrozh-kshm-o-hrmz', 'tours/1787138709.tour-image35820.jpg', NULL, NULL, NULL, NULL, 9750000.00, NULL, 4, 1, '2026-08-19 11:25:09', '2026-08-22 07:37:20'),
(6, NULL, 'تور شش‌روزه رم و فلورانس', 'tor-shshrozh-rm-o-florans', 'tours/1787138776.tour-image35964.jpg', NULL, NULL, NULL, NULL, 76500000.00, NULL, 5, 1, '2026-08-19 11:26:16', '2026-08-22 06:47:38'),
(7, NULL, 'تور لوکس هفت‌روزه پاریس', 'tor-loks-hftrozh-parys', 'tours/1787138834.tour-image66216.jpg', NULL, NULL, NULL, NULL, 89000000.00, NULL, 0, 0, '2026-08-19 11:27:14', '2026-08-22 05:54:45'),
(8, NULL, 'تور اقتصادی چهارروزه باکو', 'tor-aktsady-chharrozh-bako', 'tours/1787138868.tour-image42665.jpg', NULL, NULL, NULL, NULL, 15800000.00, NULL, 2, 1, '2026-08-19 11:27:48', '2026-08-22 06:48:01'),
(9, NULL, 'test', 'test', 'tours/1787146812.tour-image88373.jpg', NULL, NULL, NULL, NULL, 2000000.00, NULL, 0, 0, '2026-08-19 13:40:12', '2026-08-22 05:55:01');
-- --------------------------------------------------------
--
-- Table structure for table `tour_flights`
--
DROP TABLE IF EXISTS `tour_flights`;
CREATE TABLE IF NOT EXISTS `tour_flights` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`tour_id` bigint UNSIGNED NOT NULL,
`flight_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_tour_flights` (`flight_id`),
KEY `fk2_tour_flights` (`tour_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `travel_types`
--
DROP TABLE IF EXISTS `travel_types`;
CREATE TABLE IF NOT EXISTS `travel_types` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`slug` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `travel_types`
--
INSERT INTO `travel_types` (`id`, `title`, `slug`, `status`, `created_at`, `updated_at`) VALUES
(2, 'تور داخلی', 'domestic-tour', 1, '2026-08-17 11:36:22', '2026-08-17 11:36:22'),
(3, 'تور خارجی', 'international-tour', 1, '2026-08-17 11:46:33', '2026-08-17 11:46:33'),
(4, 'تور چارتر', 'charter-tour', 1, '2026-08-17 11:46:59', '2026-08-17 11:46:59'),
(5, 'تور ترکیبی', 'combined-tour', 1, '2026-08-17 11:47:41', '2026-08-17 11:47:41'),
(6, 'پرواز خارجی', 'international-flight', 1, '2026-08-17 11:48:19', '2026-08-17 11:48:19'),
(7, 'پرواز داخلی', 'domestic-flight', 1, '2026-08-17 11:48:44', '2026-08-17 11:48:44'),
(8, 'تور لحظه آخری', 'last-minute', 1, '2026-08-17 11:49:11', '2026-08-17 11:49:11'),
(9, 'پیشنویس نمونه', 'draft-sample', 0, '2026-08-17 11:49:33', '2026-08-17 11:56:13');
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth_date` date DEFAULT NULL,
`gender` tinyint(1) NOT NULL COMMENT '1:Male | 2:Female',
`marital_status` tinyint(1) NOT NULL COMMENT '1:Single | 2:Married | 3:Divorced/Separated',
`spouse_name` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`image` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`username` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`province_id` bigint UNSIGNED NOT NULL,
`city_id` bigint UNSIGNED DEFAULT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `first_name`, `last_name`, `email`, `mobile`, `password`, `national_code`, `birth_date`, `gender`, `marital_status`, `spouse_name`, `image`, `username`, `province_id`, `city_id`, `status`, `created_at`, `updated_at`) VALUES
(1, 'شهرزاد', 'زندی', 'shahrzad2020@gmail.com', '09118909120', '$2y$12$exJ7bGMeL8lsMJvdJXYhl.pDRg2tT7tRr.cVstjx0rbQuw04dWgNC', '2080706640', NULL, 2, 1, NULL, 'avatars/FevHjQ0JjviBzlNOGXiI0k1JmshmUIxrDXF3xBAC.jpg', 'shahrzad011', 2, NULL, 1, '2026-08-19 01:09:30', '2026-08-22 06:48:45'),
(2, 'حاتمه', 'اندرزا', 'hatame19@gmail.com', '09119533286', '$2y$12$6AxXNTIpJAK0czNU78PeAObgC.Nl0dTbqKyyMHSGTUrr0GynKyfhq', '2081391693', NULL, 2, 1, NULL, 'users/MU5t6XmUmS558EO4EPQUdO2kDL7XSeDEtoeP83LD.jpg', 'hatame19', 2, NULL, 1, '2026-08-19 06:23:09', '2026-08-19 06:23:09');
--
-- Constraints for dumped tables
--
--
-- Constraints for table `admin_permission`
--
ALTER TABLE `admin_permission`
ADD CONSTRAINT `fk1_admin_permission` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_admin_permission` FOREIGN KEY (`admin_id`) REFERENCES `admins` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `bookings`
--
ALTER TABLE `bookings`
ADD CONSTRAINT `fk1_bookings` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_bookings` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk3_bookings` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `cities`
--
ALTER TABLE `cities`
ADD CONSTRAINT `fk1_cities` FOREIGN KEY (`province_id`) REFERENCES `provinces` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `comments`
--
ALTER TABLE `comments`
ADD CONSTRAINT `fk1_ comments` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `favorites`
--
ALTER TABLE `favorites`
ADD CONSTRAINT `fk1_favorites` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tours`
--
ALTER TABLE `tours`
ADD CONSTRAINT `fk1_tours` FOREIGN KEY (`travel_type_id`) REFERENCES `travel_types` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
--
-- Constraints for table `tour_flights`
--
ALTER TABLE `tour_flights`
ADD CONSTRAINT `fk1_tour_flights` FOREIGN KEY (`flight_id`) REFERENCES `flights` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `fk2_tour_flights` FOREIGN KEY (`tour_id`) REFERENCES `tours` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+122
View File
@@ -0,0 +1,122 @@
/* ================================================
استایل‌های صفحه حساب کاربری (account pages)
================================================ */
/* ---------- کارت پروفایل (سایدبار) ---------- */
.profile-sidebar {
background: linear-gradient(145deg, #ffffff, #f8fbff);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 20px;
box-shadow: 0 12px 35px rgba(0, 82, 165, 0.10);
padding: 30px 20px;
transition: transform .3s ease;
}
.profile-sidebar:hover {
transform: translateY(-4px);
}
.profile-avatar {
width: 120px;
height: 120px;
border-radius: 50%;
object-fit: cover;
border: 4px solid #e8f0fe;
box-shadow: 0 6px 18px rgba(0, 123, 255, .25);
}
.profile-name {
font-weight: 700;
color: #1f2d3d;
margin-bottom: 0;
}
.profile-username {
color: #6c757d;
font-size: .85rem;
}
/* ---------- تب‌ها ---------- */
.nav-tabs .nav-link {
color: #6c757d;
font-weight: 600;
border-radius: 12px 12px 0 0;
padding: 10px 18px;
}
.nav-tabs .nav-link.active {
color: #007bff;
border-color: #dee2e6 #dee2e6 #fff;
background: #f8fbff;
}
/* ---------- فرم‌ها ---------- */
.form-card {
background: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.05);
border-radius: 20px;
box-shadow: 0 5px 22px rgba(0, 0, 0, 0.05);
padding: 25px;
}
.form-card .form-control {
border-radius: 12px;
border: 2px solid #e9ecef;
padding: 11px 15px;
transition: all .3s;
}
.form-card .form-control:focus {
border-color: #007bff;
box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .15);
}
.form-label {
font-weight: 600;
color: #495057;
font-size: .9rem;
}
/* ---------- علاقه‌مندی‌ها ---------- */
.favorite-item {
background: #fff3f5;
color: #d63384;
border: 1.5px solid #f7c8d4;
border-radius: 50px;
padding: 9px 18px;
margin: 4px;
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 600;
font-size: .9rem;
transition: all .25s;
}
.favorite-item i { font-size: .95rem; }
.favorite-item:hover {
background: #d63384;
color: #fff;
cursor: pointer;
}
/* ---------- کامنت‌ها ---------- */
.comment-box {
background: #f8f9fa;
border-right: 4px solid #17a2b8;
border-radius: 12px;
padding: 14px 16px;
color: #495057;
}
.comment-box small {
color: #17a2b8;
font-weight: 600;
}
/* ---------- دکمه ذخیره ---------- */
.btn-save {
background: linear-gradient(135deg, #007bff, #0d6efd);
border: none;
border-radius: 12px;
padding: 12px 28px;
color: #fff;
font-weight: 600;
box-shadow: 0 6px 15px rgba(0, 123, 255, .3);
transition: all .3s;
}
.btn-save:hover {
transform: translateY(-2px);
box-shadow: 0 9px 20px rgba(0, 123, 255, .4);
color: #fff;
}
+277
View File
@@ -0,0 +1,277 @@
/* ==========================================
استایل صفحات آرشیو تورها و پروازها
========================================== */
.archive-page {
background: #f6f8fb;
min-height: 60vh;
padding: 50px 0;
}
/* هدر صفحه آرشیو */
.archive-header {
background: linear-gradient(135deg, #1e3a8a, #3b82f6);
border-radius: 16px;
padding: 28px 30px;
margin-bottom: 35px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 15px;
box-shadow: 0 8px 24px rgba(30, 58, 138, 0.25);
}
.archive-header h4 {
color: #fff;
font-weight: 700;
margin: 0;
font-size: 1.4rem;
}
.archive-header .btn-back {
background: rgba(255, 255, 255, 0.15);
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.4);
border-radius: 50px;
padding: 7px 22px;
font-size: 0.9rem;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 6px;
}
.archive-header .btn-back:hover {
background: #fff;
color: #1e3a8a;
}
/* کارت تور */
.tour-card {
background: #fff;
border-radius: 14px;
overflow: hidden;
border: none;
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease, box-shadow 0.3s ease;
height: 100%;
}
.tour-card:hover {
transform: translateY(-6px);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.14);
}
.tour-card .tour-image-wrap {
position: relative;
height: 200px;
overflow: hidden;
}
.tour-card .tour-image-wrap img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.tour-card:hover .tour-image-wrap img {
transform: scale(1.08);
}
.tour-card .tour-body {
padding: 20px;
}
.tour-card .tour-title {
font-size: 1.1rem;
font-weight: 700;
margin-bottom: 10px;
}
.tour-card .tour-title a {
color: #1e3a8a;
text-decoration: none;
transition: color 0.3s;
}
.tour-card .tour-title a:hover {
color: #3b82f6;
}
.tour-card .tour-desc {
color: #6c757d;
font-size: 0.88rem;
line-height: 1.8;
margin-bottom: 15px;
min-height: 48px;
}
.tour-card .tour-footer {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px dashed #e5e7eb;
padding-top: 14px;
}
.tour-card .tour-price {
background: #eef2ff;
color: #4338ca;
border-radius: 50px;
padding: 5px 16px;
font-size: 0.85rem;
font-weight: 600;
}
/* کارت پرواز */
.flight-card {
background: #fff;
border-radius: 14px;
border: none;
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease, box-shadow 0.3s ease;
height: 100%;
}
.flight-card:hover {
transform: translateY(-6px);
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.14);
}
.flight-card .flight-body {
padding: 22px 20px;
}
.flight-card .flight-route {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 18px;
}
.flight-card .flight-city {
text-align: center;
flex: 1;
}
.flight-card .flight-city span {
display: block;
font-size: 0.75rem;
color: #9ca3af;
margin-bottom: 4px;
}
.flight-card .flight-city strong {
font-size: 1.05rem;
color: #1e293b;
}
.flight-card .flight-line {
flex: 0 0 auto;
display: flex;
align-items: center;
color: #3b82f6;
font-size: 1.1rem;
padding: 0 12px;
}
.flight-card .flight-line .plane-icon {
margin: 0 6px;
font-size: 1.2rem;
}
.flight-card .flight-info {
background: #f8fafc;
border-radius: 10px;
padding: 12px 15px;
margin-bottom: 15px;
font-size: 0.85rem;
color: #475569;
}
.flight-card .flight-info p {
margin-bottom: 5px;
display: flex;
align-items: center;
gap: 6px;
}
.flight-card .flight-info p:last-child {
margin-bottom: 0;
}
.flight-card .flight-price {
background: #eef2ff;
color: #4338ca;
border-radius: 50px;
padding: 5px 16px;
font-size: 0.85rem;
font-weight: 600;
display: inline-block;
}
/* صفحه‌بندی */
.archive-pagination {
margin-top: 40px;
}
.archive-pagination .pagination {
justify-content: center;
gap: 5px;
}
.archive-pagination .page-item .page-link {
border-radius: 8px;
border: 1px solid #e5e7eb;
color: #475569;
padding: 8px 15px;
min-width: 42px;
text-align: center;
transition: all 0.3s;
background: #fff;
}
.archive-pagination .page-item .page-link:hover {
background: #eef2ff;
color: #4338ca;
border-color: #c7d2fe;
}
.archive-pagination .page-item.active .page-link {
background: #1e3a8a;
border-color: #1e3a8a;
color: #fff;
box-shadow: 0 4px 12px rgba(30, 58, 138, 0.3);
}
/* پیام خالی */
.archive-empty {
background: #fff;
border: 2px dashed #d1d5db;
border-radius: 14px;
padding: 60px 20px;
text-align: center;
color: #9ca3af;
}
.archive-empty i {
font-size: 3rem;
display: block;
margin-bottom: 15px;
color: #cbd5e1;
}
/* ریسپانسیو */
@media (max-width: 575.98px) {
.archive-header {
flex-direction: column;
text-align: center;
}
.tour-card .tour-image-wrap {
height: 180px;
}
}
+127 -555
View File
@@ -1,606 +1,178 @@
/* =========================================================
Travel Agency - Home Page
تایپوگرافی و تنظیمات پایه (یکپارچه)
========================================================= */
.travel-page {
background: #f6f8fb;
min-height: 100vh;
padding: 60px 0;
direction: rtl;
body, html {
font-family: 'Tahoma', 'Arial', sans-serif !important;
/*font-size: 13px !important; !* متن اصلی خواناتر *!*/
line-height: 1.8 !important;
color: #374151 !important;
/*background: #f5f7fa;*/
}
.travel-page .section-heading {
text-align: center;
margin-bottom: 35px;
h1, h2, h3, h4, h5 {
font-family: 'Tahoma', sans-serif !important;
color: #1f2937 !important;
}
.travel-page .section-heading h2 {
font-size: 28px;
font-weight: 700;
color: #1f2937;
margin-bottom: 10px;
/* اصلاح فرم‌ها */
.form-control, input, select, textarea {
font-size: 12px !important;
padding: 10px 14px !important;
}
.travel-page .section-heading p {
color: #7b8494;
font-size: 14px;
margin: 0;
}
/* =========================================================
Tour Cards
استایل‌های کارت‌ها (مشترک بین همه صفحات)
========================================================= */
.travel-page .travel-card {
background: #fff;
border-radius: 14px;
overflow: hidden;
border: 1px solid #edf0f4;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
transition: all .25s ease;
height: 100%;
}
.travel-page .travel-card:hover {
transform: translateY(-6px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.10);
}
/* تصویر کارت */
.travel-page .travel-card-image {
width: 100%;
height: 210px;
overflow: hidden;
background: #eef1f5;
}
.travel-page .travel-card-image img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
transition: transform .35s ease;
}
.travel-page .travel-card:hover .travel-card-image img {
transform: scale(1.05);
}
/* بدنه کارت */
.travel-page .travel-card-body {
padding: 20px;
}
.travel-page .travel-card-title {
font-size: 19px;
font-weight: 700;
color: #202936;
margin: 0 0 12px;
}
.travel-page .travel-card-summary {
color: #737d8d;
font-size: 14px;
line-height: 1.9;
min-height: 52px;
margin-bottom: 15px;
}
.travel-page .travel-date {
color: #555f70;
font-size: 13px;
margin-bottom: 18px;
}
.travel-page .travel-date i {
margin-left: 6px;
color: #1687d9;
}
/* =========================================================
Buttons
========================================================= */
.travel-page .travel-btn {
display: block;
text-align: center;
text-decoration: none !important;
background: #1687d9;
color: #fff !important;
border-radius: 8px;
padding: 10px 15px;
font-size: 14px;
transition: .2s;
}
.travel-page .travel-btn:hover {
background: #0d6fae;
}
/* =========================================================
Empty State
========================================================= */
.travel-page .empty-box {
background: #fff;
border: 1px dashed #d9dee7;
border-radius: 12px;
padding: 35px;
text-align: center;
color: #8a93a1;
}
/* =========================================================
Pagination
========================================================= */
.travel-page .pagination-wrapper {
display: flex;
justify-content: center;
margin-top: 30px;
direction: rtl;
}
.travel-page .pagination-wrapper nav {
margin: 0;
}
/* =========================================================
Flights
========================================================= */
.travel-page .flights-section {
margin-top: 80px;
}
.travel-page .flight-card {
background: #fff;
border-radius: 14px;
border: 1px solid #edf0f4;
padding: 22px;
height: 100%;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
transition: all .25s ease;
}
.travel-page .flight-card:hover {
transform: translateY(-5px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.09);
}
.travel-page .flight-icon {
width: 50px;
height: 50px;
border-radius: 50%;
background: #e9f5ff;
color: #1687d9;
display: flex;
align-items: center;
justify-content: center;
font-size: 21px;
margin-bottom: 17px;
}
.travel-page .flight-title {
font-size: 19px;
font-weight: 700;
color: #202936;
margin-bottom: 12px;
}
.travel-page .flight-summary {
color: #737d8d;
font-size: 14px;
line-height: 1.9;
min-height: 52px;
margin-bottom: 14px;
}
.travel-page .flight-date {
color: #555f70;
font-size: 13px;
margin-bottom: 18px;
}
/* =========================================================
Responsive
========================================================= */
@media (max-width: 767px) {
.travel-page {
padding: 35px 15px;
}
.travel-page .section-heading h2 {
font-size: 23px;
}
.travel-page .travel-card-image {
height: 190px;
}
.travel-page .flights-section {
margin-top: 55px;
}
}
.tour-details-page {
direction: rtl;
padding: 50px 0;
background: #f7f8fa;
}
.tour-details-card {
max-width: 1050px;
margin: auto;
.travel-card, .flight-card, .tour-card, .tour-details-card {
background: #fff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
border: 1px solid #eef0f5;
transition: all .3s ease;
}
.travel-card:hover, .flight-card:hover, .tour-details-card:hover {
box-shadow: 0 10px 25px rgba(20, 50, 90, .10);
}
/* دکمه‌های اصلی */
.travel-btn {
display: inline-block;
background: #1687d9;
color: #fff !important;
font-size: 12px;
font-weight: 400;
padding: 10px 20px;
border-radius: 8px;
text-decoration: none;
}
.travel-btn:hover { background: #0e6bb0; }
/* دکمه علاقه‌مندی */
.travel-favorite-btn {
display: inline-flex;
align-items: center;
gap: 8px;
background: transparent;
border: 1px solid #e0245e;
color: #e0245e;
border-radius: 25px;
padding: 8px 20px;
font-size: 12px;
cursor: pointer;
transition: all .2s ease;
}
.travel-favorite-btn:hover, .travel-favorite-btn.active {
background: #e0245e;
color: #fff;
}
/* =========================================================
بخش اختصاصی جزئیات تور (tour-details-page)
========================================================= */
.tour-details-page { padding: 30px 0; }
.tour-details-card { padding: 30px; margin-bottom: 30px; }
.tour-details-image {
width: 100%;
height: 400px;
height: 350px;
overflow: hidden;
border-radius: 12px;
margin-bottom: 20px;
}
.tour-details-image img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.tour-no-image {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #eeeeee;
color: #777;
}
.tour-details-content {
padding: 35px;
}
.tour-details-title {
margin: 0 0 25px;
font-size: 32px;
font-weight: 700;
color: #222;
}
.tour-details-image img { width: 100%; height: 100%; object-fit: cover; }
.tour-details-info {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 15px;
margin-bottom: 35px;
margin: 25px 0;
}
.tour-info-box {
padding: 20px;
background: #f7f8fa;
border-radius: 12px;
background: #f8fafc;
padding: 15px;
border-radius: 10px;
text-align: center;
border: 1px solid #eef0f5;
}
.tour-info-label {
display: block;
color: #888;
font-size: 13px;
margin-bottom: 8px;
}
.tour-info-box strong {
color: #222;
font-size: 15px;
}
.tour-description {
border-top: 1px solid #eee;
padding-top: 30px;
}
.tour-description h2,
.tour-flights h2,
.related-tours h2 {
margin-bottom: 20px;
font-size: 22px;
}
.tour-description p {
color: #555;
line-height: 2.2;
font-size: 15px;
}
.tour-flights {
margin-top: 35px;
padding-top: 30px;
border-top: 1px solid #eee;
}
.flight-item {
display: flex;
justify-content: space-between;
gap: 20px;
padding: 18px;
margin-bottom: 10px;
background: #f7f8fa;
border-radius: 10px;
}
.flight-item span {
display: block;
color: #888;
font-size: 13px;
font-size: 12px;
color: #8a93a3;
margin-bottom: 5px;
}
.related-tours {
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid #eee;
}
.related-tours-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
}
.related-tour-card {
.tour-info-box strong {
font-size: 13px;
color: #1f2937;
display: block;
overflow: hidden;
background: #f7f8fa;
}
.tour-flights .flight-item {
background: #f8fafc;
padding: 15px;
border-radius: 10px;
color: inherit;
text-decoration: none;
}
.related-tour-card img {
width: 100%;
height: 130px;
object-fit: cover;
display: block;
}
.related-tour-card div {
padding: 12px;
}
.related-tour-card h3 {
margin: 0 0 8px;
font-size: 15px;
}
.related-tour-card span {
color: #888;
font-size: 12px;
}
.tour-back {
margin-top: 35px;
}
.tour-back-button {
display: inline-block;
padding: 12px 25px;
background: #222;
color: #fff;
border-radius: 8px;
text-decoration: none;
}
.tour-back-button:hover {
color: #fff;
text-decoration: none;
opacity: .9;
}
@media (max-width: 768px) {
.tour-details-page {
padding: 20px 10px;
}
.tour-details-image {
height: 250px;
}
.tour-details-content {
padding: 20px;
}
.tour-details-title {
font-size: 25px;
}
.tour-details-info {
grid-template-columns: 1fr 1fr;
}
.related-tours-grid {
grid-template-columns: 1fr 1fr;
}
.flight-item {
flex-direction: column;
}
margin-bottom: 10px;
display: flex;
justify-content: space-between;
}
/* =========================================================
Main Navbar - RTL Fix
عنوان بخش‌ها (Global Header Style)
========================================================= */
h2 {
font-size: 15px !important;
font-weight: 500 !important;
padding-right: 15px;
position: relative;
margin-bottom: 20px !important;
}
h2::before {
content: "";
position: absolute;
right: 0;
top: 2px;
width: 5px;
height: 24px;
/*background: #1687d9;*/
border-radius: 4px;
}
/* =========================================================
حفظ رنگ سفید در هیرو (travel-hero)
این قانون باید بعد از قانون سراسری h1 قرار بگیرد
========================================================= */
#main-nav {
direction: rtl;
width: 100%;
position: relative;
z-index: 1000;
.travel-hero-content h1,
.travel-hero-content h1 span {
color: #ffffff !important;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
#main-nav .container {
width: 100%;
/* متن‌های دیگر هیرو هم سفید و خوانا */
.travel-hero-label,
.travel-hero-content p {
color: #ffffff !important;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
#main-nav .navbar-inner {
.travel-card {
display: flex;
align-items: center;
min-height: 80px;
flex-direction: column;
border-radius: 8px;
overflow: hidden;
background: #fff;
transition: transform 0.3s ease;
}
/* لوگو */
#main-nav .navbar-header {
float: none;
flex-shrink: 0;
}
#main-nav .navbar-brand {
display: flex;
align-items: center;
height: 80px;
padding: 10px 0 10px 30px;
}
#main-nav .navbar-brand img {
max-height: 55px;
width: auto;
}
/* بخش منو */
#main-nav .navbar-collapse {
display: flex !important;
align-items: center;
justify-content: space-between;
flex: 1;
border: 0;
box-shadow: none;
}
/* منوی اصلی */
#main-nav .navbar-nav {
float: none !important;
display: flex;
align-items: center;
margin: 0;
}
#main-nav .navbar-nav > li {
float: none;
}
#main-nav .navbar-nav > li > a {
display: flex;
align-items: center;
min-height: 80px;
padding: 0 16px;
white-space: nowrap;
}
/* منوی سمت راست */
#main-nav .navbar-nav.navbar-right {
margin-right: auto;
margin-left: 0;
}
/* آیکون حساب */
#main-nav .navbar-nav-item-user-icon {
margin-left: 7px;
font-size: 18px;
}
/* Dropdown */
#main-nav .dropdown-menu {
right: 0;
left: auto;
min-width: 180px;
text-align: right;
}
#main-nav .navbar-right .dropdown-menu {
right: auto;
left: 0;
}
/* موبایل */
@media (max-width: 767px) {
#main-nav .navbar-inner {
display: block;
min-height: auto;
}
#main-nav .navbar-header {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 70px;
}
#main-nav .navbar-brand {
height: 70px;
padding: 8px 0;
}
#main-nav .navbar-toggle {
float: left;
margin-left: 0;
margin-right: 15px;
}
#main-nav .navbar-collapse {
display: block !important;
.travel-card-image img {
width: 100%;
padding: 0;
height: 200px;
object-fit: cover;
}
#main-nav .navbar-nav {
display: block;
width: 100%;
}
#main-nav .navbar-nav > li {
display: block;
width: 100%;
}
#main-nav .navbar-nav > li > a {
min-height: 45px;
padding: 12px 15px;
display: block;
}
#main-nav .navbar-nav.navbar-right {
margin: 0;
}
#main-nav .dropdown-menu {
position: static;
float: none;
width: 100%;
box-shadow: none;
}
.travel-card-body {
padding: 15px;
flex-grow: 1;
}
+272
View File
@@ -15211,3 +15211,275 @@ jdp-container .jdp-btn-today, jdp-container .jdp-btn-empty {
}
}
/* =========================================
User Menu
========================================= */
.travel-user-menu {
position: relative;
display: inline-block;
}
/* دکمه حساب کاربری */
.travel-user-button {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
border: 1px solid rgba(255, 255, 255, 0.35);
border-radius: 30px;
background: rgba(255, 255, 255, 0.12);
color: #fff;
cursor: pointer;
font-family: inherit;
font-size: 14px;
transition: all 0.25s ease;
backdrop-filter: blur(8px);
}
.travel-user-button:hover {
background: rgba(255, 255, 255, 0.22);
}
.travel-user-button > i:first-child {
font-size: 20px;
}
.travel-user-arrow {
font-size: 12px;
transition: transform 0.25s ease;
}
/* =========================================
Dropdown
========================================= */
.travel-user-dropdown {
position: absolute;
top: calc(100% + 12px);
left: 0;
width: 220px;
padding: 8px;
background: #fff;
border-radius: 12px;
box-shadow:
0 10px 30px rgba(0, 0, 0, 0.15),
0 3px 10px rgba(0, 0, 0, 0.08);
opacity: 0;
visibility: hidden;
transform: translateY(-8px);
transition:
opacity 0.25s ease,
visibility 0.25s ease,
transform 0.25s ease;
z-index: 999;
}
/* باز شدن منو */
.travel-user-menu:hover .travel-user-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
/* فلش */
.travel-user-menu:hover .travel-user-arrow {
transform: rotate(180deg);
}
/* =========================================
Dropdown Items
========================================= */
.travel-user-dropdown a {
display: flex;
align-items: center;
gap: 10px;
padding: 11px 12px;
border-radius: 8px;
color: #333;
text-decoration: none;
font-size: 14px;
transition: all 0.2s ease;
}
.travel-user-dropdown a i {
width: 20px;
text-align: center;
font-size: 16px;
}
.travel-user-dropdown a:hover {
background: #f1f5f9;
color: #2563eb;
transform: translateX(-3px);
}
/* =========================================
Divider
========================================= */
.travel-dropdown-divider {
height: 1px;
margin: 6px 4px;
background: #e5e7eb;
}
/* =========================================
Logout
========================================= */
.travel-user-dropdown .travel-logout-link {
color: #dc2626;
}
.travel-user-dropdown .travel-logout-link:hover {
background: #fef2f2;
color: #dc2626;
}
/* =========================================
Login / Register
========================================= */
.travel-navbar-actions {
display: flex;
align-items: center;
gap: 10px;
}
.travel-login,
.travel-register {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 9px 15px;
border-radius: 25px;
text-decoration: none;
font-size: 14px;
transition: all 0.25s ease;
}
.travel-login {
color: #fff;
border: 1px solid rgba(255, 255, 255, 0.4);
background: rgba(255, 255, 255, 0.1);
}
.travel-login:hover {
background: rgba(255, 255, 255, 0.2);
color: #fff;
}
.travel-register {
color: #fff;
background: #2563eb;
border: 1px solid #2563eb;
box-shadow: 0 5px 15px rgba(37, 99, 235, 0.25);
}
.travel-register:hover {
background: #1d4ed8;
color: #fff;
transform: translateY(-2px);
}
/* =========================================
Mobile
========================================= */
@media (max-width: 768px) {
.travel-user-button span {
display: none;
}
.travel-user-button {
padding: 9px 12px;
}
.travel-user-dropdown {
left: auto;
right: 0;
}
.travel-login span,
.travel-register span {
display: none;
}
}
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
<div>
<!-- Simplicity is the ultimate sophistication. - Leonardo da Vinci -->
</div>
+137 -1
View File
@@ -1,3 +1,139 @@
@extends('layouts.app')
@section('title', 'نظرات من')
@section('content')
{{-- =====================
سربرگ صفحه (Page Header)
===================== --}}
<div class="account-page-header mb-4 d-flex justify-content-between align-items-center flex-wrap gap-3">
<div>
<!-- An unexamined life is not worth living. - Socrates -->
<h4 class="mb-1 fw-bold">
<i class="fa fa-comments text-primary me-1"></i>
نظرات من
</h4>
<p class="text-muted small mb-0">
دیدگاه‌هایی که برای تورها و پروازها ثبت کرده‌اید
</p>
</div>
<div>
<a href="{{ route('tours.index') }}" class="btn btn-sm btn-outline-primary">
<i class="fa fa-suitcase me-1"></i>
مشاهده تورها
</a>
</div>
</div>
{{-- نمایش پیام موفقیت --}}
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="بستن"></button>
</div>
@endif
{{-- =====================
لیست نظرات
===================== --}}
@forelse ($comments as $comment)
<div class="card shadow-sm app-comment-card mb-3 border-0 rounded-4">
<div class="card-body">
{{-- بالای کارت: عنوان تور/پرواز + وضعیت --}}
<div class="d-flex justify-content-between align-items-start flex-wrap gap-2 mb-2">
<div class="d-flex align-items-center gap-2">
{{-- آیکون تور یا پرواز بر اساس نوع محتوا --}}
@if ($comment->commentable instanceof \App\Models\Tour)
<span class="app-icon-circle bg-primary-subtle text-primary">
<i class="fa fa-suitcase"></i>
</span>
@else
<span class="app-icon-circle bg-info-subtle text-info">
<i class="fa fa-plane"></i>
</span>
@endif
<div>
<h6 class="mb-0 fw-bold">
{{ $comment->commentable?->title ?? 'مورد حذف‌شده' }}
</h6>
<small class="text-muted">
{{ class_basename($comment->commentable_type) }}
</small>
</div>
</div>
{{-- وضعیت نظر --}}
@include('admin.comments.status', ['status' => $comment->status])
</div>
{{-- متن نظر --}}
<p class="card-text text-muted mb-0">
{{ $comment->body }}
</p>
{{-- تاریخ ثبت --}}
<div class="d-flex justify-content-between align-items-center mt-3 pt-3 border-top small text-muted">
<span>
<i class="fa fa-calendar me-1"></i>
{{ $comment->created_at->format('Y/m/d H:i') }}
</span>
{{-- دکمه حذف نظر --}}
@if (Route::has('account.comments.destroy'))
<form action="{{ route('account.comments.destroy', $comment) }}" method="POST"
onsubmit="return confirm('نظر شما حذف شود؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-link btn-sm text-danger p-0">
<i class="fa fa-trash me-1"></i>
حذف
</button>
</form>
@endif
</div>
</div>
</div>
@empty
<div class="card border-0 shadow-sm rounded-4">
<div class="card-body text-center py-5">
<div class="app-empty-icon mx-auto mb-3">
<i class="fa fa-comment-slash"></i>
</div>
<h5 class="fw-bold mb-1">هنوز نظری ثبت نکرده‌اید</h5>
<p class="text-muted mb-3">
بعد از خرید یا رزرو تور و پرواز، می‌توانید نظر خود را ثبت کنید.
</p>
<a href="{{ route('tours.index') }}" class="btn btn-primary">
<i class="fa fa-suitcase me-1"></i>
مشاهده تورها
</a>
</div>
</div>
@endforelse
{{-- =====================
صفحه‌بندی
===================== --}}
<div class="mt-4">
{{ $comments->links() }}
</div>
@endsection
@@ -1,3 +1,120 @@
<div>
<!-- If you do not have a consistent goal in life, you can not live it in a consistent way. - Marcus Aurelius -->
@extends('layouts.app')
@section('content')
<div class="container py-5">
<div class="row g-4">
<!-- ====== سایدبار پروفایل ====== -->
<div class="col-lg-3 col-md-4">
<div class="profile-sidebar text-center">
<img src="{{ $user->image ? asset('storage/'.$user->image) : asset('assets/img/default.png') }}"
class="profile-avatar mb-3" alt="تصویر پروفایل">
<h5 class="profile-name">{{ $user->first_name }} {{ $user->last_name }}</h5>
<p class="profile-username">@ {{ $user->username }}</p>
<hr class="my-3">
<div class="d-flex justify-content-around small">
<div><strong>{{ $user->favorites->count() }}</strong><br><span style="color:#6c757d;">علاقه‌مندی</span></div>
<div><strong>{{ $user->comments->count() }}</strong><br><span style="color:#6c757d;">کامنت</span></div>
</div>
</div>
</div>
<!-- ====== محتوای اصلی ====== -->
<div class="col-lg-9 col-md-8">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#edit">ویرایش پروفایل</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#comments">کامنت‌های من</a></li>
<li class="nav-item"><a class="nav-link" data-toggle="tab" href="#favorites">علاقه‌مندی‌ها</a></li>
</ul>
<div class="tab-content pt-4">
<!-- تب ویرایش پروفایل -->
<div class="tab-pane active" id="edit">
<div class="form-card">
<form action="{{ route('account.edit-profile.post') }}" method="POST"
enctype="multipart/form-data">
@csrf
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">نام</label>
<input type="text" name="first_name" class="form-control"
value="{{ old('first_name', $user->first_name) }}">
@error('first_name') <small class="text-danger">{{ $message }}</small> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="form-label">نام خانوادگی</label>
<input type="text" name="last_name" class="form-control"
value="{{ old('last_name', $user->last_name) }}">
@error('last_name') <small class="text-danger">{{ $message }}</small> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="form-label">نام کاربری</label>
<input type="text" name="username" class="form-control"
value="{{ old('username', $user->username) }}">
@error('username') <small class="text-danger">{{ $message }}</small> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="form-label">ایمیل</label>
<input type="email" name="email" class="form-control"
value="{{ old('email', $user->email) }}">
@error('email') <small class="text-danger">{{ $message }}</small> @enderror
</div>
<div class="col-md-12 mb-3">
<label class="form-label">تصویر پروفایل</label>
<input type="file" name="image" class="form-control">
</div>
<div class="col-md-12 mb-4">
<label class="form-label">رمز عبور جدید <small class="text-muted">(اختیاری)</small></label>
<input type="password" name="password" class="form-control">
@error('password') <small class="text-danger">{{ $message }}</small> @enderror
</div>
</div>
<button type="submit" class="btn btn-save">ذخیره تغییرات</button>
</form>
</div>
</div>
<!-- تب کامنت‌ها -->
<div class="tab-pane" id="comments">
@forelse($user->comments as $comment)
<div class="comment-box mb-3">
<div>{{ $comment->content }}</div>
<small>{{ $comment->created_at ? $comment->created_at->format('Y/m/d') : '' }}</small>
</div>
@empty
<p class="text-muted">هنوز کامنتی ثبت نکرده‌اید.</p>
@endforelse
</div>
<!-- تب علاقه‌مندی‌ها -->
<div class="tab-pane" id="favorites">
@forelse($user->favorites as $fav)
<span class="favorite-item">
<i class="fa fa-heart"></i>
{{ $fav->favoritable->title ?? 'مورد علاقه‌مند' }}
</span>
@empty
<p class="text-muted">هنوز موردی به علاقه‌مندی‌ها اضافه نکرده‌اید.</p>
@endforelse
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.nav-tabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
});
});
</script>
@endsection
+60 -2
View File
@@ -1,3 +1,61 @@
<div>
<!-- Very little is needed to make a happy life. - Marcus Aurelius -->
@extends('layouts.app')
@section('content')
<div class="container py-4">
<h1 class="mb-4">علاقه‌مندی‌های من</h1>
@if($favorites->count())
<div class="row g-3">
@foreach($favorites as $favorite)
@php $item = $favorite->favoritable; @endphp
<div class="col-md-4">
<div class="card h-100">
<div class="card-body">
@if($favorite->favoritable_type === \App\Models\Tour::class)
<h5 class="card-title">{{ $item?->title ?? 'تور' }}</h5>
<p class="card-text">
{{ $item?->summary ?? '' }}
</p>
@elseif($favorite->favoritable_type === \App\Models\Flight::class)
<h5 class="card-title">
{{ $item?->origin ?? '-' }} → {{ $item?->destination ?? '-' }}
</h5>
@else
<h5 class="card-title">مورد ناشناخته</h5>
@endif
</div>
<div
class="card-footer bg-transparent border-0 d-flex justify-content-between align-items-center">
@if($favorite->favoritable_type === \App\Models\Tour::class)
<a href="{{ route('tours.show', $item->id) }}" class="btn btn-sm btn-primary">مشاهده
تور</a>
@endif
<form action="{{ route('favorites.toggle') }}" method="POST">
@csrf
<input type="hidden" name="favoritable_type"
value="{{ $favorite->favoritable_type }}">
<input type="hidden" name="favoritable_id" value="{{ $favorite->favoritable_id }}">
<button type="submit" class="btn btn-sm btn-outline-danger">
از علاقه‌مندی‌ها حذف شود
</button>
</form>
</div>
</div>
</div>
@endforeach
</div>
<div class="mt-4">
{{ $favorites->links() }}
</div>
@else
<div class="alert alert-info">
هنوز هیچ موردی به علاقه‌مندی‌ها اضافه نکرده‌اید.
</div>
@endif
</div>
@endsection
+26 -45
View File
@@ -270,13 +270,14 @@
{{-- دسترسی‌ها --}}
<div class="col-xl-4">
<div class="card custom-card">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="card-title mb-1">
@@ -291,62 +292,42 @@
</div>
</div>
<div class="card-body">
@php
@if($permissions->count())
$selectedPermissions = old(
'permissions',
$admin->permissions->pluck('id')->toArray()
);
<div class="d-flex flex-column gap-3">
@endphp
@foreach($permissions as $permission)
<div class="form-check">
@error('permissions')
<div class="alert alert-danger py-2">
{{ $message }}
</div>
@enderror
@forelse($permissions as $permission)
<div class="form-check form-check-lg mb-3">
<input class="form-check-input"
<input
type="checkbox"
class="form-check-input"
name="permissions[]"
value="{{ $permission->id }}"
id="permission_{{ $permission->id }}"
@checked(in_array(
$permission->id,
$selectedPermissions
))>
{{ $admin->permissions->contains($permission->id) ? 'checked' : '' }}
>
<label class="form-check-label"
for="permission_{{ $permission->id }}">
<span class="fw-semibold">
<label
class="form-check-label"
for="permission_{{ $permission->id }}"
>
{{ $permission->name }}
</span>
@if($permission->description)
<small class="text-muted d-block mt-1">
{{ $permission->description }}
</small>
@endif
</label>
</div>
@empty
@endforeach
</div>
@else
<div class="text-center text-muted py-4">
@@ -356,7 +337,7 @@
</div>
@endforelse
@endif
</div>
@@ -380,17 +361,17 @@
<i class="ri-information-line me-1"></i>
آخرین ویرایش:
@if($admin->updated_at)
<td>
{{ $admin->updated_at->toJalali()->format('Y/m/d H:i') }}
</td>
<td>{{ $type->updated_at ? $type->updated_at->toJalali()->format('Y/m/d H:i') : '-' }}</td>
@else
-
<td>-</td>
@endif
</div>
+24 -723
View File
@@ -101,12 +101,30 @@
</td>
{{-- دسترسی‌ها --}}
<td style="min-width: 200px; max-width: 280px; white-space: normal;">
@forelse($admin->permissions as $permission)
<span class="badge bg-primary-subtle text-primary mb-1">{{ $permission->name }}</span>
@empty
<span class="text-muted fs-12">بدون دسترسی</span>
@endforelse
<td>
@if($admin->permissions->count())
<div class="d-flex flex-wrap gap-1">
@foreach($admin->permissions as $permission)
<span class="badge bg-light text-dark border">
{{ $permission->name }}
</span>
@endforeach
</div>
@else
<span class="text-muted">
بدون دسترسی
</span>
@endif
</td>
{{-- وضعیت --}}
@@ -179,720 +197,3 @@
</div>
@endsection
{{--@extends('admin.layouts.app')--}}
{{--@section('title', 'مدیریت مدیران')--}}
{{--@section('breadcrumb')--}}
{{-- <div>--}}
{{-- <h1 class="page-title fw-medium fs-18 mb-2">--}}
{{-- مدیریت مدیران--}}
{{-- </h1>--}}
{{-- <nav>--}}
{{-- <ol class="breadcrumb mb-0">--}}
{{-- <li class="breadcrumb-item">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}">--}}
{{-- داشبورد--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- <li class="breadcrumb-item active">--}}
{{-- مدیریت مدیران--}}
{{-- </li>--}}
{{-- </ol>--}}
{{-- </nav>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@section('content')--}}
{{-- <div class="container-fluid pt-4">--}}
{{-- --}}{{-- پیام موفقیت --}}
{{-- @if(session('success'))--}}
{{-- <div class="alert alert-success alert-dismissible fade show" role="alert">--}}
{{-- <i class="ri-checkbox-circle-line me-1"></i>--}}
{{-- {{ session('success') }}--}}
{{-- <button type="button"--}}
{{-- class="btn-close"--}}
{{-- data-bs-dismiss="alert"--}}
{{-- aria-label="Close">--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- خطاهای عمومی --}}
{{-- @if(session('error'))--}}
{{-- <div class="alert alert-danger alert-dismissible fade show" role="alert">--}}
{{-- <i class="ri-error-warning-line me-1"></i>--}}
{{-- {{ session('error') }}--}}
{{-- <button type="button"--}}
{{-- class="btn-close"--}}
{{-- data-bs-dismiss="alert"--}}
{{-- aria-label="Close">--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- عنوان و عملیات --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3">--}}
{{-- <div class="d-flex align-items-center justify-content-between flex-wrap gap-3">--}}
{{-- <div>--}}
{{-- <h5 class="mb-1">--}}
{{-- لیست مدیران--}}
{{-- </h5>--}}
{{-- <p class="text-muted mb-0 fs-12">--}}
{{-- مدیریت مدیران و سطح دسترسی پنل--}}
{{-- </p>--}}
{{-- </div>--}}
{{-- <div>--}}
{{-- <a href="{{ route('admin.admins.create') }}"--}}
{{-- class="btn btn-primary">--}}
{{-- <i class="ri-add-line me-1"></i>--}}
{{-- ایجاد مدیر جدید--}}
{{-- </a>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- --}}{{-- جدول مدیران --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="table-responsive">--}}
{{-- <table class="table text-nowrap table-hover table-bordered mb-0">--}}
{{-- <thead>--}}
{{-- <tr>--}}
{{-- <th>--}}
{{-- #--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- مدیر--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- نام کاربری--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- اطلاعات تماس--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- دسترسی‌ها--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- وضعیت--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- تاریخ ایجاد--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- عملیات--}}
{{-- </th>--}}
{{-- </tr>--}}
{{-- </thead>--}}
{{-- <tbody>--}}
{{-- @forelse($admins as $admin)--}}
{{-- <tr>--}}
{{-- --}}{{-- ID --}}
{{-- <td>--}}
{{-- {{ $admin->id }}--}}
{{-- </td>--}}
{{-- --}}{{-- نام مدیر --}}
{{-- <td>--}}
{{-- <div class="d-flex align-items-center">--}}
{{-- <div class="avatar avatar-sm bg-primary-transparent me-2">--}}
{{-- <i class="ri-user-settings-line"></i>--}}
{{-- </div>--}}
{{-- <div>--}}
{{-- <div class="fw-semibold">--}}
{{-- {{ $admin->full_name }}--}}
{{-- </div>--}}
{{-- <small class="text-muted">--}}
{{-- مدیر پنل--}}
{{-- </small>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- --}}{{-- username --}}
{{-- <td>--}}
{{-- <span class="badge bg-light text-dark">--}}
{{-- <i class="ri-user-line me-1"></i>--}}
{{-- {{ $admin->username }}--}}
{{-- </span>--}}
{{-- </td>--}}
{{-- --}}{{-- اطلاعات تماس --}}
{{-- <td>--}}
{{-- <div>--}}
{{-- <i class="ri-mail-line text-muted me-1"></i>--}}
{{-- {{ $admin->email }}--}}
{{-- </div>--}}
{{-- <div class="mt-1">--}}
{{-- <i class="ri-smartphone-line text-muted me-1"></i>--}}
{{-- {{ $admin->mobile }}--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- --}}{{-- Permissionها --}}
{{-- <td style="min-width: 220px; max-width: 300px; white-space: normal;">--}}
{{-- @forelse($admin->permissions as $permission)--}}
{{-- <span class="badge bg-primary-transparent mb-1">--}}
{{-- {{ $permission->name }}--}}
{{-- </span>--}}
{{-- @empty--}}
{{-- <span class="text-muted fs-12">--}}
{{-- بدون دسترسی--}}
{{-- </span>--}}
{{-- @endforelse--}}
{{-- </td>--}}
{{-- --}}{{-- وضعیت --}}
{{-- <td>--}}
{{-- @if((int) $admin->status === 1)--}}
{{-- <span class="badge bg-success-transparent">--}}
{{-- <i class="ri-checkbox-circle-line me-1"></i>--}}
{{-- فعال--}}
{{-- </span>--}}
{{-- @else--}}
{{-- <span class="badge bg-danger-transparent">--}}
{{-- <i class="ri-close-circle-line me-1"></i>--}}
{{-- غیرفعال--}}
{{-- </span>--}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{-- تاریخ ایجاد --}}
{{-- <td>--}}
{{-- @if($admin->created_at)--}}
{{-- <span class="badge bg-info-transparent">--}}
{{-- {{ $admin->created_at->toJalali()->format('H:i Y/m/d') }}--}}
{{-- </span>--}}
{{-- @else--}}
{{-- ---}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{-- عملیات --}}
{{-- <td>--}}
{{-- <div class="hstack gap-2 fs-15">--}}
{{-- --}}{{-- ویرایش --}}
{{-- <a href="{{ route('admin.admins.edit', $admin) }}"--}}
{{-- class="btn btn-secondary-light btn-icon btn-sm"--}}
{{-- title="ویرایش">--}}
{{-- <i class="ri-pencil-line"></i>--}}
{{-- </a>--}}
{{-- --}}{{-- حذف --}}
{{-- <form action="{{ route('admin.admins.destroy', $admin) }}"--}}
{{-- method="POST"--}}
{{-- onsubmit="return confirm('آیا از حذف این مدیر مطمئن هستید؟')">--}}
{{-- @csrf--}}
{{-- @method('DELETE')--}}
{{-- <button type="submit"--}}
{{-- class="btn btn-danger-light btn-icon btn-sm"--}}
{{-- title="حذف">--}}
{{-- <i class="ri-delete-bin-line"></i>--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @empty--}}
{{-- <tr>--}}
{{-- <td colspan="8" class="text-center py-5">--}}
{{-- <div class="text-muted">--}}
{{-- <i class="ri-user-settings-line fs-1 d-block mb-2"></i>--}}
{{-- مدیری برای نمایش وجود ندارد.--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @endforelse--}}
{{-- </tbody>--}}
{{-- </table>--}}
{{-- </div>--}}
{{-- --}}{{-- Pagination --}}
{{-- @if($admins->hasPages())--}}
{{-- <div class="card-footer">--}}
{{-- {{ $admins->links() }}--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@extends('admin.layouts.app')--}}
{{--@section('title', 'مدیریت مدیران')--}}
{{--@section('breadcrumb')--}}
{{-- <div>--}}
{{-- <h1 class="page-title fw-medium fs-18 mb-2">--}}
{{-- مدیریت مدیران--}}
{{-- </h1>--}}
{{-- <nav>--}}
{{-- <ol class="breadcrumb mb-0">--}}
{{-- <li class="breadcrumb-item">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}">--}}
{{-- داشبورد--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- <li class="breadcrumb-item active">--}}
{{-- مدیریت مدیران--}}
{{-- </li>--}}
{{-- </ol>--}}
{{-- </nav>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@section('content')--}}
{{-- <div class="container-fluid pt-4">--}}
{{-- --}}{{-- عنوان و عملیات --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3">--}}
{{-- <div class="d-flex align-items-center justify-content-between flex-wrap gap-3">--}}
{{-- <div>--}}
{{-- <h5 class="mb-1">--}}
{{-- لیست مدیران--}}
{{-- </h5>--}}
{{-- <p class="text-muted mb-0 fs-12">--}}
{{-- مدیریت مدیران پنل آژانس هواپیمایی--}}
{{-- </p>--}}
{{-- </div>--}}
{{-- <div>--}}
{{-- <a href="{{ route('admin.admins.create') }}"--}}
{{-- class="btn btn-primary">--}}
{{-- <i class="ri-add-line me-1"></i>--}}
{{-- ایجاد مدیر جدید--}}
{{-- </a>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- --}}{{-- جدول مدیران --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="table-responsive">--}}
{{-- <table class="table text-nowrap table-bordered">--}}
{{-- <thead>--}}
{{-- <tr>--}}
{{-- <th>--}}
{{-- #--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- نام و نام خانوادگی--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- نام کاربری--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- ایمیل--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- موبایل--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- وضعیت--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- تاریخ ایجاد--}}
{{-- </th>--}}
{{-- <th>--}}
{{-- عملیات--}}
{{-- </th>--}}
{{-- </tr>--}}
{{-- </thead>--}}
{{-- <tbody>--}}
{{-- @forelse($admins as $admin)--}}
{{-- <tr>--}}
{{-- <td>--}}
{{-- {{ $admin->id }}--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- <span class="fw-semibold">--}}
{{-- {{ $admin->full_name }}--}}
{{-- </span>--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- <span class="text-muted">--}}
{{-- {{ $admin->username }}--}}
{{-- </span>--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- {{ $admin->email }}--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- {{ $admin->mobile }}--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- @if((int) $admin->status === 1)--}}
{{-- <span class="badge bg-success-transparent">--}}
{{-- فعال--}}
{{-- </span>--}}
{{-- @else--}}
{{-- <span class="badge bg-danger-transparent">--}}
{{-- غیرفعال--}}
{{-- </span>--}}
{{-- @endif--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- {{ optional($admin->created_at)->format('Y/m/d') }}--}}
{{-- </td>--}}
{{-- <td>--}}
{{-- <div class="hstack gap-2 fs-15">--}}
{{-- <a href="{{ route('admin.admins.edit', $admin) }}"--}}
{{-- class="btn btn-secondary-light btn-icon btn-sm">--}}
{{-- <i class="ti ti-pencil"></i>--}}
{{-- </a>--}}
{{-- <form action="{{ route('admin.admins.destroy', $admin) }}"--}}
{{-- method="POST"--}}
{{-- onsubmit="return confirm('آیا از حذف این مدیر مطمئن هستید؟')">--}}
{{-- @csrf--}}
{{-- @method('DELETE')--}}
{{-- <button type="submit"--}}
{{-- class="btn btn-danger-light btn-icon btn-sm">--}}
{{-- <i class="ri-delete-bin-line"></i>--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @empty--}}
{{-- <tr>--}}
{{-- <td colspan="8" class="text-center py-4">--}}
{{-- <div class="text-muted">--}}
{{-- مدیری برای نمایش وجود ندارد.--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @endforelse--}}
{{-- </tbody>--}}
{{-- </table>--}}
{{-- </div>--}}
{{-- <div class="card-footer">--}}
{{-- {{ $admins->links() }}--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
+177 -1
View File
@@ -1,3 +1,179 @@
@extends('admin.layouts.app')
@section('title', 'افزودن فرودگاه')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<!-- Be present above all else. - Naval Ravikant -->
<h4 class="mb-1">افزودن فرودگاه جدید</h4>
<small class="text-muted">
ثبت اطلاعات فرودگاه
</small>
</div>
<a href="{{ route('admin.airports.index') }}"
class="btn btn-outline-secondary btn-sm">
بازگشت
</a>
</div>
<div class="card custom-card">
<div class="card-body">
<form action="{{ route('admin.airports.store') }}"
method="POST">
@csrf
{{-- نام فرودگاه --}}
<div class="mb-3">
<label class="form-label">
نام فرودگاه
</label>
<input type="text"
name="name"
value="{{ old('name') }}"
class="form-control @error('name') is-invalid @enderror"
placeholder="مثلاً فرودگاه امام خمینی">
@error('name')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- کد فرودگاه --}}
<div class="mb-3">
<label class="form-label">
کد فرودگاه
</label>
<input type="text"
name="code"
value="{{ old('code') }}"
class="form-control @error('code') is-invalid @enderror"
placeholder="مثلاً IKA">
@error('code')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- استان --}}
<div class="mb-3">
<label class="form-label">
استان
</label>
<input type="text"
name="province"
value="{{ old('province') }}"
class="form-control @error('province') is-invalid @enderror">
@error('province')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- شهر --}}
<div class="mb-3">
<label class="form-label">
شهر
</label>
<input type="text"
name="city"
value="{{ old('city') }}"
class="form-control @error('city') is-invalid @enderror">
@error('city')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- وضعیت --}}
<div class="mb-3">
<label class="form-label">
وضعیت
</label>
<select name="status"
class="form-select">
<option value="1"
{{ old('status', 1) == 1 ? 'selected' : '' }}>
فعال
</option>
<option value="0"
{{ old('status') == 0 ? 'selected' : '' }}>
غیرفعال
</option>
</select>
</div>
<div class="d-flex gap-2 mt-4">
<button type="submit"
class="btn btn-primary">
ثبت فرودگاه
</button>
<a href="{{ route('admin.airports.index') }}"
class="btn btn-light">
انصراف
</a>
</div>
</form>
</div>
</div>
</div>
@endsection
+272 -1
View File
@@ -1,3 +1,274 @@
@extends('admin.layouts.app')
@section('title', 'ویرایش فرودگاه')
@section('breadcrumb')
<div>
<!-- Because you are alive, everything is possible. - Thich Nhat Hanh -->
<h1 class="page-title fw-medium fs-18 mb-2">
ویرایش فرودگاه
</h1>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item">
<a href="{{ route('admin.dashboard.index') }}">
داشبورد
</a>
</li>
<li class="breadcrumb-item">
<a href="{{ route('admin.airports.index') }}">
مدیریت فرودگاه‌ها
</a>
</li>
<li class="breadcrumb-item active">
ویرایش فرودگاه
</li>
</ol>
</nav>
</div>
@endsection
@section('content')
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-8 col-lg-10 mx-auto">
<div class="card custom-card">
<div class="card-header">
<div>
<h5 class="mb-1">
ویرایش فرودگاه
</h5>
<small class="text-muted">
ویرایش اطلاعات {{ $airport->name }}
</small>
</div>
</div>
<div class="card-body">
<form action="{{ route('admin.airports.update', $airport) }}"
method="POST">
@csrf
@method('PUT')
{{-- نام فرودگاه --}}
<div class="mb-3">
<label for="name"
class="form-label">
نام فرودگاه
<span class="text-danger">*</span>
</label>
<input type="text"
id="name"
name="name"
value="{{ old('name', $airport->name) }}"
class="form-control @error('name') is-invalid @enderror"
placeholder="نام فرودگاه">
@error('name')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- کد فرودگاه --}}
<div class="mb-3">
<label for="code"
class="form-label">
کد فرودگاه
<span class="text-danger">*</span>
</label>
<input type="text"
id="code"
name="code"
value="{{ old('code', $airport->code) }}"
class="form-control @error('code') is-invalid @enderror"
placeholder="مثلاً IKA">
@error('code')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- استان --}}
<div class="mb-3">
<label for="province"
class="form-label">
استان
</label>
<input type="text"
id="province"
name="province"
value="{{ old('province', $airport->province) }}"
class="form-control @error('province') is-invalid @enderror"
placeholder="نام استان">
@error('province')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- شهر --}}
<div class="mb-3">
<label for="city"
class="form-label">
شهر
</label>
<input type="text"
id="city"
name="city"
value="{{ old('city', $airport->city) }}"
class="form-control @error('city') is-invalid @enderror"
placeholder="نام شهر">
@error('city')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- وضعیت --}}
<div class="mb-3">
<label for="status"
class="form-label">
وضعیت
</label>
<select id="status"
name="status"
class="form-select @error('status') is-invalid @enderror">
<option value="1"
{{ old('status', $airport->status) == 1 ? 'selected' : '' }}>
فعال
</option>
<option value="0"
{{ old('status', $airport->status) == 0 ? 'selected' : '' }}>
غیرفعال
</option>
</select>
@error('status')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
{{-- دکمه‌ها --}}
<div class="d-flex gap-2 mt-4">
<button type="submit"
class="btn btn-primary">
<i class="fa fa-save me-1"></i>
بروزرسانی فرودگاه
</button>
<a href="{{ route('admin.airports.index') }}"
class="btn btn-light">
انصراف
</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
+74 -1
View File
@@ -1,3 +1,76 @@
@extends('admin.layouts.app')
@section('title', 'مدیریت فرودگاه‌ها')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<!-- We must ship. - Taylor Otwell -->
<h4 class="mb-0">مدیریت فرودگاه‌ها</h4>
<span class="text-muted small">تعداد کل: {{ $airports->total() }} فرودگاه</span>
</div>
<a href="{{ route('admin.airports.create') }}" class="btn btn-primary">
<i class="bi bi-plus-lg"></i> افزودن فرودگاه
</a>
</div>
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="بستن"></button>
</div>
@endif
<div class="card shadow-sm">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>#</th>
<th>نام فرودگاه</th>
<th>کد</th>
<th>استان</th>
<th>شهر</th>
<th class="text-center">عملیات</th>
</tr>
</thead>
<tbody>
@forelse ($airports as $airport)
<tr>
<td>{{ $airport->id }}</td>
<td class="fw-semibold">{{ $airport->name }}</td>
<td>{{ $airport->code }}</td>
<td>{{ $airport->province }}</td>
<td>{{ $airport->city }}</td>
<td class="text-center">
<div class="d-inline-flex gap-2">
<a href="{{ route('admin.airports.edit', $airport) }}"
class="btn btn-sm btn-outline-primary">ویرایش</a>
<form action="{{ route('admin.airports.destroy', $airport) }}"
method="POST"
onsubmit="return confirm('آیا از حذف فرودگاه {{ $airport->name }} مطمئن هستید؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger">حذف</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center text-muted py-5">
هنوز فرودگاهی ثبت نشده است.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="mt-3">
{{ $airports->links() }}
</div>
</div>
@endsection
@@ -0,0 +1,34 @@
@extends('admin.layouts.app')
@section('title', 'افزودن شهر')
@section('content')
<div class="admin-card p-4">
<h5 class="mb-4">افزودن شهر جدید</h5>
<form action="{{ route('admin.locations.cities.store') }}" method="POST">
@csrf
<div class="mb-3">
<label class="form-label">نام شهر</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror"
value="{{ old('name') }}">
@error('name')
<div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="mb-3">
<label class="form-label">استان</label>
<select name="province_id" class="form-control @error('province_id') is-invalid @enderror">
<option value="">انتخاب استان...</option>
@foreach($provinces as $province)
<option
value="{{ $province->id }}" {{ old('province_id') == $province->id ? 'selected' : '' }}>{{ $province->name }}</option>
@endforeach
</select>
@error('province_id')
<div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<button type="submit" class="btn btn-success">ذخیره اطلاعات</button>
<a href="{{ route('admin.locations.cities.index') }}" class="btn btn-secondary">انصراف</a>
</form>
</div>
@endsection
@@ -0,0 +1,31 @@
@extends('admin.layouts.app')
@section('content')
<div class="card">
<div class="card-header"><h5>ویرایش شهر: {{ $city->name }}</h5></div>
<div class="card-body">
<form action="{{ route('admin.locations.cities.update', $city->id) }}" method="POST">
@csrf @method('PUT')
<div class="form-group">
<label>نام شهر</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror"
value="{{ old('name', $city->name) }}">
@error('name') <span class="text-danger">{{ $message }}</span> @enderror
</div>
<div class="form-group">
<label>استان مربوطه</label>
<select name="province_id" class="form-control @error('province_id') is-invalid @enderror">
@foreach($provinces as $province)
<option
value="{{ $province->id }}" {{ old('province_id', $city->province_id) == $province->id ? 'selected' : '' }}>
{{ $province->name }}
</option>
@endforeach
</select>
@error('province_id') <span class="text-danger">{{ $message }}</span> @enderror
</div>
<button type="submit" class="btn btn-primary">بروزرسانی</button>
</form>
</div>
</div>
@endsection
@@ -0,0 +1,69 @@
@extends('admin.layouts.app')
@section('title', 'مدیریت شهرها')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">مدیریت شهرها</h1>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard.index') }}">داشبورد</a></li>
<li class="breadcrumb-item active">مدیریت مناطق / شهرها</li>
</ol>
</nav>
</div>
@endsection
@section('content')
<div class="container-fluid pt-4">
<div class="card custom-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">لیست شهرها</h5>
<a href="{{ route('admin.locations.cities.create') }}" class="btn btn-primary">افزودن شهر جدید</a>
</div>
<div class="card-body">
<form action="{{ route('admin.locations.cities.index') }}" method="GET" class="mb-4">
<select name="province_id" class="form-control w-25" onchange="this.form.submit()">
<option value="">همه استان‌ها</option>
@foreach($provinces as $province)
<option
value="{{ $province->id }}" {{ request('province_id') == $province->id ? 'selected' : '' }}>{{ $province->name }}</option>
@endforeach
</select>
</form>
<div class="table-responsive">
<table class="table table-bordered table-hover mb-0">
<thead>
<tr>
<th>نام شهر</th>
<th>استان</th>
<th class="text-center">عملیات</th>
</tr>
</thead>
<tbody>
@foreach($cities as $city)
<tr>
<td>{{ $city->name }}</td>
<td>{{ $city->province->name ?? '-' }}</td>
<td class="text-center">
<a href="{{ route('admin.locations.cities.edit', $city->id) }}"
class="btn btn-sm btn-info text-white">ویرایش</a>
<form action="{{ route('admin.locations.cities.destroy', $city->id) }}"
method="POST" class="d-inline">
@csrf @method('DELETE')
<button class="btn btn-sm btn-danger" onclick="return confirm('آیا مطمئنید؟')">
حذف
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-3">{{ $cities->links() }}</div>
</div>
</div>
</div>
@endsection
+1 -10
View File
@@ -51,16 +51,7 @@
<div class="btn-group btn-group-sm" role="group">
<a href="{{ route('admin.comments.show', $comment) }}"
class="btn btn-outline-secondary" title="نمایش">نمایش</a>
<a href="{{ route('admin.comments.edit', $comment) }}"
class="btn btn-outline-primary" title="ویرایش">ویرایش</a>
<form action="{{ route('admin.comments.destroy', $comment) }}" method="POST"
class="d-inline"
onsubmit="return confirm('نظر حذف شود؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-outline-danger" title="حذف">حذف</button>
</form>
</div>
</td>
</tr>
@empty
@@ -36,15 +36,7 @@
</dd>
</dl>
</div>
<div class="card-footer bg-white">
<a href="{{ route('admin.comments.edit', $comment) }}" class="btn btn-primary btn-sm">ویرایش</a>
<form action="{{ route('admin.comments.destroy', $comment) }}" method="POST" class="d-inline"
onsubmit="return confirm('نظر حذف شود؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">حذف</button>
</form>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,10 @@
@switch($status)
@case(1)
<span class="badge bg-success text-white">تایید شده</span>
@break
@case(2)
<span class="badge bg-warning text-dark">در انتظار بررسی</span>
@break
@default
<span class="badge bg-secondary">نامشخص</span>
@endswitch
File diff suppressed because it is too large Load Diff
@@ -507,7 +507,6 @@
</div>
{{-- Pagination --}}
@if($flights->hasPages())
<div class="card-footer">
+1 -133
View File
@@ -221,142 +221,10 @@
<script src="{{ asset('assets/js/countdown.js') }}"></script>
<script src="{{ asset('assets/js/ion-range-slider.js') }}"></script>
<script src="{{ asset('assets/js/chart.js') }}"></script>
@stack('scripts')
</body>
</html>
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport"--}}
{{-- content="width=device-width, initial-scale=1.0">--}}
{{-- <title>--}}
{{-- @yield('title', 'پنل مدیریت')--}}
{{-- </title>--}}
{{-- --}}{{-- CSS اصلی پروژه --}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/bootstrap.min.css') }}">--}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/icons.css') }}">--}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/style.css') }}">--}}
{{-- @stack('styles')--}}
{{--</head>--}}
{{--<body>--}}
{{--<div class="page">--}}
{{-- --}}{{-- Sidebar --}}
{{-- @include('admin.layouts.sidebar')--}}
{{-- <div class="main-content app-content">--}}
{{-- --}}{{-- Header --}}
{{-- @include('admin.layouts.header')--}}
{{-- <main>--}}
{{-- --}}{{-- Breadcrumb --}}
{{-- @hasSection('breadcrumb')--}}
{{-- <div class="page-header-breadcrumb">--}}
{{-- @yield('breadcrumb')--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- Content --}}
{{-- @yield('content')--}}
{{-- </main>--}}
{{-- --}}{{-- Footer --}}
{{-- @include('admin.layouts.footer')--}}
{{-- </div>--}}
{{--</div>--}}
{{--<script src="{{ asset('assets/admin/js/bootstrap.bundle.min.js') }}"></script>--}}
{{--@stack('scripts')--}}
{{--</body>--}}
{{--</html>--}}
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport"--}}
{{-- content="width=device-width, initial-scale=1.0">--}}
{{-- <title>--}}
{{-- @yield('title', 'پنل مدیریت')--}}
{{-- </title>--}}
{{-- --}}{{----}}{{-- CSS اصلی پروژه --}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/bootstrap.min.css') }}">--}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/icons.css') }}">--}}
{{-- <link rel="stylesheet"--}}
{{-- href="{{ asset('assets/admin/css/style.css') }}">--}}
{{-- @stack('styles')--}}
{{--</head>--}}
{{--<body>--}}
{{--<div class="page">--}}
{{-- --}}{{----}}{{-- Sidebar --}}
{{-- @include('admin.layouts.sidebar')--}}
{{-- <div class="main-content app-content">--}}
{{-- --}}{{----}}{{-- Header --}}
{{-- @include('admin.layouts.header')--}}
{{-- <main>--}}
{{-- --}}{{----}}{{-- Breadcrumb --}}
{{-- @hasSection('breadcrumb')--}}
{{-- <div class="page-header-breadcrumb">--}}
{{-- @yield('breadcrumb')--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{----}}{{-- Content --}}
{{-- @yield('content')--}}
{{-- </main>--}}
{{-- --}}{{----}}{{-- Footer --}}
{{-- @include('admin.layouts.footer')--}}
{{-- </div>--}}
{{--</div>--}}
{{--<script src="{{ asset('assets/admin/js/bootstrap.bundle.min.js') }}"></script>--}}
{{--@stack('scripts')--}}
{{--</body>--}}
{{--</html>--}}
@@ -41,132 +41,3 @@
</div>
</header>
{{--<header class="app-header">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="d-flex align-items-center justify-content-between">--}}
{{-- <div class="d-flex align-items-center gap-3">--}}
{{-- <button type="button"--}}
{{-- class="btn btn-light"--}}
{{-- id="sidebarToggle">--}}
{{-- <i class="ri-menu-line"></i>--}}
{{-- </button>--}}
{{-- <span class="fw-semibold">--}}
{{-- پنل مدیریت--}}
{{-- </span>--}}
{{-- </div>--}}
{{-- <div class="d-flex align-items-center gap-3">--}}
{{-- @auth('admin')--}}
{{-- <div class="dropdown">--}}
{{-- <button class="btn btn-light dropdown-toggle"--}}
{{-- data-bs-toggle="dropdown">--}}
{{-- <i class="ri-user-line me-1"></i>--}}
{{-- {{ auth('admin')->user()->full_name }}--}}
{{-- </button>--}}
{{-- <ul class="dropdown-menu">--}}
{{-- <li>--}}
{{-- <a class="dropdown-item"--}}
{{-- href="{{ route('admin.auth.logout') }}">--}}
{{-- <i class="ri-logout-box-line me-2"></i>--}}
{{-- خروج--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- @endauth--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</header>--}}
{{--<header class="app-header">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="d-flex align-items-center justify-content-between">--}}
{{-- <div class="d-flex align-items-center gap-3">--}}
{{-- <button type="button"--}}
{{-- class="btn btn-light"--}}
{{-- id="sidebarToggle">--}}
{{-- <i class="ri-menu-line"></i>--}}
{{-- </button>--}}
{{-- <span class="fw-semibold">--}}
{{-- پنل مدیریت--}}
{{-- </span>--}}
{{-- </div>--}}
{{-- <div class="d-flex align-items-center gap-3">--}}
{{-- @auth('admin')--}}
{{-- <div class="dropdown">--}}
{{-- <button class="btn btn-light dropdown-toggle"--}}
{{-- data-bs-toggle="dropdown">--}}
{{-- <i class="ri-user-line me-1"></i>--}}
{{-- {{ auth('admin')->user()->full_name }}--}}
{{-- </button>--}}
{{-- <ul class="dropdown-menu">--}}
{{-- <li>--}}
{{-- <a class="dropdown-item"--}}
{{-- href="{{ route('admin.auth.logout') }}">--}}
{{-- <i class="ri-logout-box-line me-2"></i>--}}
{{-- خروج--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- @endauth--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</header>--}}
+27 -118
View File
@@ -1,18 +1,12 @@
<aside class="admin-sidebar">
<div class="admin-logo">
<a href="{{ route('admin.dashboard.index') }}">
✈️
آژانس هواپیمایی
</a>
</div>
<nav class="admin-menu">
<div class="admin-menu-title">
@@ -21,186 +15,101 @@
<a href="{{ route('admin.dashboard.index') }}"
class="{{ request()->routeIs('admin.dashboard.*') ? 'active' : '' }}">
<i class="fa fa-dashboard"></i>
<span>
داشبورد
</span>
<span>داشبورد</span>
</a>
<div class="admin-menu-title">
مدیریت سفر
</div>
<a href="{{ route('admin.flights.index') }}"
class="{{ request()->routeIs('admin.flights.*') ? 'active' : '' }}">
<i class="fa fa-plane"></i>
<span>
مدیریت پروازها
</span>
<span>مدیریت پروازها</span>
</a>
<a href="{{ route('admin.tours.index') }}"
class="{{ request()->routeIs('admin.tours.*') ? 'active' : '' }}">
<i class="fa fa-map-marker"></i>
<span>
مدیریت تورها
</span>
<span>مدیریت تورها</span>
</a>
<a href="{{ route('admin.travelTypes.index') }}"
class="{{ request()->routeIs('admin.travelTypes.*') ? 'active' : '' }}">
<i class="fa fa-suitcase"></i>
<span>
انواع سفر
</span>
<span>انواع سفر</span>
</a>
<a href="{{ route('admin.airports.index') }}"
class="{{ request()->routeIs('admin.airports.*') ? 'active' : '' }}">
<i class="fa fa-building"></i>
<span>
فرودگاه‌ها
</span>
<span>فرودگاه‌ها</span>
</a>
<div class="admin-menu-title">
مدیریت مناطق
</div>
<a href="{{ route('admin.locations.provinces.index') }}"
class="{{ request()->routeIs('admin.locations.provinces.*') ? 'active' : '' }}">
<i class="fa fa-map"></i>
<span>مدیریت استان‌ها</span>
</a>
<a href="{{ route('admin.locations.cities.index') }}"
class="{{ request()->routeIs('admin.locations.cities.*') ? 'active' : '' }}">
<i class="fa fa-map-signs"></i>
<span>مدیریت شهرها</span>
</a>
<div class="admin-menu-title">
کاربران و تعاملات
</div>
<a href="{{ route('admin.users.index') }}"
class="{{ request()->routeIs('admin.users.*') ? 'active' : '' }}">
<i class="fa fa-users"></i>
<span>
کاربران
</span>
<span>کاربران</span>
</a>
<a href="{{ route('admin.comments.index') }}"
class="{{ request()->routeIs('admin.comments.*') ? 'active' : '' }}">
<i class="fa fa-comments"></i>
<span>
نظرات
</span>
<span>نظرات</span>
</a>
<a href="{{ route('admin.favorites.index') }}"
class="{{ request()->routeIs('admin.favorites.*') ? 'active' : '' }}">
<i class="fa fa-heart"></i>
<span>
علاقه‌مندی‌ها
</span>
<span>علاقه‌مندی‌ها</span>
</a>
<div class="admin-menu-title">
مالی
</div>
{{-- <a href="{{ route('admin.payments.index') }}"--}}
{{-- class="{{ request()->routeIs('admin.payments.*') ? 'active' : '' }}">--}}
{{-- <i class="fa fa-credit-card"></i>--}}
{{-- <span>--}}
{{-- پرداخت‌ها--}}
{{-- </span>--}}
{{-- </a>--}}
<div class="admin-menu-title">
تنظیمات سایت
</div>
{{-- <a href="{{ route('admin.sliders.index') }}"--}}
{{-- class="{{ request()->routeIs('admin.sliders.*') ? 'active' : '' }}">--}}
{{-- <i class="fa fa-picture-o"></i>--}}
{{-- <span>--}}
{{-- اسلایدرها--}}
{{-- </span>--}}
{{-- </a>--}}
<a href="{{ route('admin.settings.index') }}"
class="{{ request()->routeIs('admin.settings.*') ? 'active' : '' }}">
<i class="fa fa-cog"></i>
<span>
تنظیمات
</span>
<span>تنظیمات</span>
</a>
<div class="admin-menu-title">
مدیریت مدیران
</div>
<a href="{{ route('admin.admins.index') }}"
class="{{ request()->routeIs('admin.admins.*') ? 'active' : '' }}">
<i class="fa fa-user-secret"></i>
<span>
مدیران سیستم
</span>
<span>مدیران سیستم</span>
</a>
<div class="admin-menu-title">
حساب کاربری
</div>
<a href="{{ route('admin.auth.logout') }}">
<i class="fa fa-sign-out"></i>
<span>
خروج
</span>
<span>خروج</span>
</a>
</nav>
@@ -0,0 +1,20 @@
@extends('admin.layouts.app')
@section('content')
<div class="card">
<div class="card-header"><h5>افزودن استان جدید</h5></div>
<div class="card-body">
<form action="{{ route('admin.locations.provinces.store') }}" method="POST">
@csrf
<div class="form-group">
<label>نام استان</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror"
value="{{ old('name') }}">
@error('name') <span class="text-danger">{{ $message }}</span> @enderror
</div>
<button type="submit" class="btn btn-success">ذخیره</button>
</form>
</div>
</div>
@endsection
@@ -0,0 +1,19 @@
@extends('admin.layouts.app')
@section('content')
<div class="card">
<div class="card-header"><h5>ویرایش استان: {{ $province->name }}</h5></div>
<div class="card-body">
<form action="{{ route('admin.locations.provinces.update', $province->id) }}" method="POST">
@csrf @method('PUT')
<div class="form-group">
<label>نام استان</label>
<input type="text" name="name" class="form-control @error('name') is-invalid @enderror"
value="{{ old('name', $province->name) }}">
@error('name') <span class="text-danger">{{ $message }}</span> @enderror
</div>
<button type="submit" class="btn btn-primary">بروزرسانی</button>
</form>
</div>
</div>
@endsection
@@ -0,0 +1,59 @@
@extends('admin.layouts.app')
@section('title', 'مدیریت استان‌ها')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">مدیریت استان‌ها</h1>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard.index') }}">داشبورد</a></li>
<li class="breadcrumb-item active">مدیریت مناطق / استان‌ها</li>
</ol>
</nav>
</div>
@endsection
@section('content')
<div class="container-fluid pt-4">
<div class="card custom-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">لیست استان‌ها</h5>
<a href="{{ route('admin.locations.provinces.create') }}" class="btn btn-primary">افزودن استان جدید</a>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-hover mb-0">
<thead>
<tr>
<th>شناسه</th>
<th>نام استان</th>
<th class="text-center">عملیات</th>
</tr>
</thead>
<tbody>
@foreach($provinces as $province)
<tr>
<td>{{ $province->id }}</td>
<td>{{ $province->name }}</td>
<td class="text-center">
<a href="{{ route('admin.locations.provinces.edit', $province->id) }}"
class="btn btn-sm btn-info text-white">ویرایش</a>
<form action="{{ route('admin.locations.provinces.destroy', $province->id) }}"
method="POST" class="d-inline">
@csrf @method('DELETE')
<button class="btn btn-sm btn-danger" onclick="return confirm('آیا مطمئنید؟')">
حذف
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-3">{{ $provinces->links() }}</div>
</div>
</div>
</div>
@endsection
+1 -1
View File
@@ -24,7 +24,7 @@
@method('PUT')
<div class="row">
<!-- عنوان -->
<div class="col-md-6 mb-3">
<label class="form-label">عنوان تور</label>
<input type="text" name="title" class="form-control"
+377 -39
View File
@@ -1,61 +1,399 @@
@extends('admin.layouts.app') {{-- فرض بر وجود لایوت ادمین --}}
@extends('admin.layouts.app')
@section('content')
<div class="container mt-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h2>مدیریت تورها</h2>
<a href="{{ route('admin.tours.create') }}" class="btn btn-primary">افزودن تور جدید</a>
{{-- ============================= --}}
{{-- هدر صفحه --}}
{{-- ============================= --}}
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h2 class="mb-1">
مدیریت تورها
</h2>
<p class="text-muted mb-0">
لیست تورهای ثبت شده در سیستم
</p>
</div>
<a
href="{{ route('admin.tours.create') }}"
class="btn btn-primary"
>
<i class="fa fa-plus"></i>
افزودن تور جدید
</a>
</div>
{{-- ============================= --}}
{{-- پیام موفقیت --}}
{{-- ============================= --}}
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
<div class="alert alert-success alert-dismissible fade show">
{{ session('success') }}
<button
type="button"
class="close"
data-dismiss="alert"
aria-label="Close"
>
<span>&times;</span>
</button>
</div>
@endif
<div class="card shadow">
<div class="card-body">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>تصویر</th>
<th>عنوان تور</th>
<th>قیمت (تومان)</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@forelse($tours as $tour)
<tr>
<td>
<img src="{{ asset('storage/' . ($tour->image ?? 'default.jpg')) }}" width="60" class="rounded">
</td>
<td>{{ $tour->title }}</td>
<td>{{ number_format($tour->price) }}</td>
<td>
<div class="btn-group" role="group">
<a href="{{ route('admin.tours.show', $tour->id) }}" class="btn btn-sm btn-info text-white">مشاهده</a>
<a href="{{ route('admin.tours.edit', $tour->id) }}" class="btn btn-sm btn-warning text-white">ویرایش</a>
<form action="{{ route('admin.tours.destroy', $tour->id) }}" method="POST" onsubmit="return confirm('آیا مطمئن هستید؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger">حذف</button>
</form>
{{-- ============================= --}}
{{-- خطاهای عمومی --}}
{{-- ============================= --}}
@if($errors->has('general'))
<div class="alert alert-danger">
{{ $errors->first('general') }}
</div>
</td>
</tr>
@empty
@endif
{{-- ============================= --}}
{{-- جدول تورها --}}
{{-- ============================= --}}
<div class="card shadow-sm">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<strong>
لیست تورها
</strong>
<span class="badge badge-primary">
{{ $tours->total() }}
تور
</span>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover table-bordered mb-0">
<thead class="thead-light">
<tr>
<td colspan="4" class="text-center">هیچ توری یافت نشد.</td>
<th style="width: 80px;">
#
</th>
<th style="width: 100px;">
تصویر
</th>
<th>
عنوان تور
</th>
<th>
قیمت
</th>
<th>
تاریخ حرکت
</th>
<th>
وضعیت
</th>
<th style="width: 230px;">
عملیات
</th>
</tr>
</thead>
<tbody>
@forelse($tours as $tour)
<tr>
{{-- شماره --}}
<td>
{{ $tours->firstItem() + $loop->index }}
</td>
{{-- تصویر --}}
<td>
@if($tour->image)
<img
src="{{ asset('storage/' . $tour->image) }}"
alt="{{ $tour->title }}"
width="70"
height="60"
class="rounded"
style="object-fit: cover;"
>
@else
<img
src="{{ asset('images/no-image.jpg') }}"
alt="بدون تصویر"
width="70"
height="60"
class="rounded"
style="object-fit: cover;"
>
@endif
</td>
{{-- عنوان --}}
<td>
<strong>
{{ $tour->title }}
</strong>
@if($tour->slug)
<small class="d-block text-muted">
{{ $tour->slug }}
</small>
@endif
</td>
{{-- قیمت --}}
<td>
@if($tour->price)
<strong>
{{ number_format($tour->price) }}
</strong>
تومان
@else
<span class="text-muted">
تعیین نشده
</span>
@endif
</td>
{{-- تاریخ حرکت --}}
<td>
@if($tour->start_date)
{{ $tour->start_date }}
@else
<span class="text-muted">
—
</span>
@endif
</td>
{{-- وضعیت --}}
<td>
@if($tour->status == 2)
<span class="badge badge-success">
تایید شده
</span>
@elseif($tour->status == 1)
<span class="badge badge-warning">
در انتظار تایید
</span>
@elseif($tour->status == 3)
<span class="badge badge-danger">
رد شده
</span>
@else
<span class="badge badge-secondary">
نامشخص
</span>
@endif
</td>
{{-- عملیات --}}
<td>
<div class="btn-group">
{{-- مشاهده --}}
<a
href="{{ route('admin.tours.show', $tour->id) }}"
class="btn btn-sm btn-info text-white"
>
<i class="fa fa-eye"></i>
مشاهده
</a>
{{-- ویرایش --}}
<a
href="{{ route('admin.tours.edit', $tour->id) }}"
class="btn btn-sm btn-warning text-white"
>
<i class="fa fa-edit"></i>
ویرایش
</a>
{{-- حذف --}}
<form
action="{{ route('admin.tours.destroy', $tour->id) }}"
method="POST"
onsubmit="return confirm('آیا از حذف این تور مطمئن هستید؟')"
style="display: inline;"
>
@csrf
@method('DELETE')
<button
type="submit"
class="btn btn-sm btn-danger"
>
<i class="fa fa-trash"></i>
حذف
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td
colspan="7"
class="text-center py-5"
>
<div class="text-muted">
<i
class="fa fa-plane"
style="font-size: 40px;"
></i>
<p class="mt-3 mb-0">
هیچ توری یافت نشد.
</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
{{-- بخش بسیار مهم برای آزمون: نمایش لینک‌های صفحه‌بندی --}}
<div class="d-flex justify-content-center mt-3">
</div>
</div>
@if($tours->hasPages())
<div class="card-footer">
<div class="d-flex justify-content-center">
{{ $tours->links() }}
</div>
</div>
@endif
</div>
</div>
@endsection
@@ -25,11 +25,7 @@
<div class="invalid-feedback">{{ $message }}</div>@enderror
</div>
{{-- <div class="mb-3 form-check">--}}
{{-- <input type="checkbox" name="status" value="1" class="form-check-input"--}}
{{-- id="status" @checked(old('status', true))>--}}
{{-- <label class="form-check-label" for="status">فعال باشد</label>--}}
{{-- </div>--}}
<input type="hidden" name="status" value="0">
<div class="form-check">
@@ -1,3 +0,0 @@
<div>
<!-- Well begun is half done. - Aristotle -->
</div>
@@ -1,10 +1,30 @@
@extends('admin.layouts.app')
@section('title', 'تغییر رمز کاربر')
@section('title', 'تغییر رمز عبور')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">تغییر رمز عبور کاربر</h1>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard.index') }}">داشبورد</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.users.index') }}">ثبت‌نامی‌ها</a></li>
<li class="breadcrumb-item active">تغییر رمز عبور</li>
</ol>
</nav>
</div>
@endsection
@section('content')
<div class="container-fluid pt-4">
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@@ -19,15 +39,17 @@
<div class="col-xl-6">
<div class="card custom-card">
<div class="card-header">
<h5 class="mb-0">تغییر رمز عبور — {{ $user->full_name ?? $user->name }}</h5>
<h5 class="mb-0">
تغییر رمز عبور برای: {{ $user->first_name }} {{ $user->last_name }}
</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('admin.users.update-password', $user) }}">
<form action="{{ route('admin.users.update-password', $user) }}" method="POST">
@csrf
@method('PUT')
<div class="mb-3">
<label class="form-label">رمز عبور جدید</label>
<label class="form-label">رمز عبور جدید <span class="text-danger">*</span></label>
<input type="password" name="password"
class="form-control @error('password') is-invalid @enderror">
@error('password')
@@ -36,14 +58,14 @@
</div>
<div class="mb-3">
<label class="form-label">تکرار رمز جدید</label>
<label class="form-label">تکرار رمز عبور <span class="text-danger">*</span></label>
<input type="password" name="password_confirmation"
class="form-control">
class="form-control @error('password') is-invalid @enderror">
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-success">ذخیره رمز</button>
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary">انصراف</a>
<button type="submit" class="btn btn-warning">بروزرسانی رمز</button>
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary">بازگشت</a>
</div>
</form>
</div>
@@ -53,4 +75,3 @@
</div>
@endsection
+53 -59
View File
@@ -7,12 +7,8 @@
<h1 class="page-title fw-medium fs-18 mb-2">ویرایش کاربر</h1>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item">
<a href="{{ route('admin.dashboard.index') }}">داشبورد</a>
</li>
<li class="breadcrumb-item">
<a href="{{ route('admin.users.index') }}">مدیریت کاربران</a>
</li>
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard.index') }}">داشبورد</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.users.index') }}">ثبت‌نامی‌ها</a></li>
<li class="breadcrumb-item active">ویرایش کاربر</li>
</ol>
</nav>
@@ -22,100 +18,98 @@
@section('content')
<div class="container-fluid pt-4">
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if($errors->any())
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<div class="alert alert-danger">
<ul class="mb-0">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<div class="row justify-content-center">
<div class="col-xl-8 col-lg-10">
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">ویرایش کاربر</h5>
<a href="{{ route('admin.users.index') }}" class="btn btn-sm btn-secondary">بازگشت</a>
<div class="card-header">
<h5 class="mb-0">ویرایش اطلاعات کاربر</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('admin.users.update', $user) }}">
<form action="{{ route('admin.users.update', $user) }}" method="POST">
@csrf
@method('PUT')
{{-- نام کامل --}}
<div class="mb-3">
<label class="form-label">نام کامل <span class="text-danger">*</span></label>
<input type="text"
name="full_name"
value="{{ old('full_name', $user->full_name ?? $user->name) }}"
class="form-control @error('full_name') is-invalid @enderror">
@error('full_name')
<small class="text-danger">{{ $message }}</small>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">نام <span class="text-danger">*</span></label>
<input type="text" name="first_name"
value="{{ old('first_name', $user->first_name) }}"
class="form-control @error('first_name') is-invalid @enderror">
@error('first_name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
{{-- ایمیل --}}
<div class="mb-3">
<div class="col-md-6">
<label class="form-label">نام خانوادگی <span class="text-danger">*</span></label>
<input type="text" name="last_name"
value="{{ old('last_name', $user->last_name) }}"
class="form-control @error('last_name') is-invalid @enderror">
@error('last_name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label class="form-label">ایمیل <span class="text-danger">*</span></label>
<input type="email"
name="email"
<input type="email" name="email"
value="{{ old('email', $user->email) }}"
class="form-control @error('email') is-invalid @enderror">
@error('email')
<small class="text-danger">{{ $message }}</small>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
{{-- موبایل --}}
<div class="mb-3">
<div class="col-md-6">
<label class="form-label">موبایل</label>
<input type="text"
name="mobile"
value="{{ old('mobile', $user->mobile ?? '') }}"
<input type="text" name="mobile"
value="{{ old('mobile', $user->mobile) }}"
class="form-control @error('mobile') is-invalid @enderror">
@error('mobile')
<small class="text-danger">{{ $message }}</small>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
{{-- وضعیت --}}
<div class="mb-3">
<label class="form-label">وضعیت حساب</label>
<div class="form-check form-switch">
<input type="checkbox"
name="status"
value="1"
class="form-check-input"
id="status"
{{ (int) old('status', $user->status) === 1 ? 'checked' : '' }}>
<label class="form-check-label" for="status">حساب فعال باشد</label>
</div>
<div class="col-md-6">
<label class="form-label">وضعیت</label>
<select name="status" class="form-select @error('status') is-invalid @enderror">
<option value="1" @selected(old('status', $user->status) == 1)>فعال</option>
<option value="0" @selected(old('status', $user->status) == 0)>غیرفعال</option>
</select>
@error('status')
<small class="text-danger">{{ $message }}</small>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mt-4 d-flex gap-2">
<button type="submit" class="btn btn-primary">
ذخیره تغییرات
</button>
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary">
انصراف
</a>
</div>
<div class="d-flex gap-2 mt-4">
<button type="submit" class="btn btn-success">ذخیره تغییرات</button>
<a href="{{ route('admin.users.change-password', $user) }}"
class="btn btn-warning">تغییر رمز عبور</a>
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary">بازگشت به لیست</a>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
+3 -364
View File
@@ -41,7 +41,7 @@
<form method="GET" action="{{ route('admin.users.index') }}" class="row g-3 align-items-end">
<div class="col-md-4">
<label class="form-label">کلمه کلیدی (نام / ایمیل / موبایل)</label>
<label class="form-label">کلمه کلیدی (نام / نام خانوادگی / ایمیل / موبایل)</label>
<input type="text" name="search" value="{{ request('search') }}"
class="form-control" placeholder="جستجو...">
</div>
@@ -110,7 +110,7 @@
<tr>
<td>{{ $user->id }}</td>
<td>
<div class="fw-semibold">{{ $user->full_name ?? $user->name }}</div>
<div class="fw-semibold">{{ $user->first_name }} {{ $user->last_name }}</div>
<small class="text-muted">کاربر سایت</small>
</td>
<td>{{ $user->email }}</td>
@@ -126,21 +126,16 @@
{{ $user->created_at?->toJalali()->format('Y/m/d') ?? '-' }}
</td>
{{-- عملیات (بر اساس دسترسی) --}}
{{-- عملیات --}}
<td class="text-center">
<div class="d-flex justify-content-center gap-2">
@can('users.edit')
<a href="{{ route('admin.users.edit', $user) }}"
class="btn btn-sm btn-primary fw-semibold">ویرایش</a>
@endcan
@can('users.change-password')
<a href="{{ route('admin.users.change-password', $user) }}"
class="btn btn-sm btn-warning fw-semibold">تغییر رمز</a>
@endcan
@can('users.delete')
<form action="{{ route('admin.users.destroy', $user) }}"
method="POST" class="d-inline"
onsubmit="return confirm('آیا از حذف این کاربر مطمئن هستید؟')">
@@ -150,7 +145,6 @@
حذف
</button>
</form>
@endcan
</div>
</td>
@@ -177,358 +171,3 @@
</div>
@endsection
{{--@extends('admin.layouts.app')--}}
{{--@section('title', 'مدیریت کاربران')--}}
{{--@section('breadcrumb')--}}
{{-- <div>--}}
{{-- <h1 class="page-title fw-medium fs-18 mb-2">مدیریت کاربران</h1>--}}
{{-- <nav>--}}
{{-- <ol class="breadcrumb mb-0">--}}
{{-- <li class="breadcrumb-item">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}">داشبورد</a>--}}
{{-- </li>--}}
{{-- <li class="breadcrumb-item active">مدیریت کاربران</li>--}}
{{-- </ol>--}}
{{-- </nav>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@section('content')--}}
{{-- <div class="container-fluid pt-4">--}}
{{-- @if(session('success'))--}}
{{-- <div class="alert alert-success alert-dismissible fade show" role="alert">--}}
{{-- {{ session('success') }}--}}
{{-- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- @if(session('error'))--}}
{{-- <div class="alert alert-danger alert-dismissible fade show" role="alert">--}}
{{-- {{ session('error') }}--}}
{{-- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- جستجو --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3">--}}
{{-- <form method="GET" action="{{ route('admin.users.index') }}"--}}
{{-- class="d-flex flex-wrap gap-2 align-items-center">--}}
{{-- <div class="flex-grow-1" style="min-width: 200px;">--}}
{{-- <input type="text"--}}
{{-- name="search"--}}
{{-- value="{{ request('search') }}"--}}
{{-- class="form-control"--}}
{{-- placeholder="جستجو بر اساس نام، ایمیل یا موبایل...">--}}
{{-- </div>--}}
{{-- <button type="submit" class="btn btn-primary">جستجو</button>--}}
{{-- @if(request('search'))--}}
{{-- <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">پاک‌کردن</a>--}}
{{-- @endif--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- --}}{{-- جدول کاربران --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3 d-flex justify-content-between align-items-center">--}}
{{-- <h5 class="mb-0">لیست کاربران</h5>--}}
{{-- <span class="badge bg-primary-transparent">{{ $users->total() }} کاربر</span>--}}
{{-- </div>--}}
{{-- <div class="table-responsive">--}}
{{-- <table class="table text-nowrap table-hover table-bordered mb-0">--}}
{{-- <thead>--}}
{{-- <tr>--}}
{{-- <th>#</th>--}}
{{-- <th>نام کاربر</th>--}}
{{-- <th>ایمیل</th>--}}
{{-- <th>موبایل</th>--}}
{{-- <th>وضعیت</th>--}}
{{-- <th>تاریخ عضویت</th>--}}
{{-- <th class="text-center">عملیات</th>--}}
{{-- </tr>--}}
{{-- </thead>--}}
{{-- <tbody>--}}
{{-- @forelse($users as $user)--}}
{{-- <tr>--}}
{{-- <td>{{ $user->id }}</td>--}}
{{-- --}}{{-- نام --}}
{{-- <td>--}}
{{-- <div class="d-flex align-items-center">--}}
{{-- <div class="avatar avatar-sm bg-primary-transparent me-2 fw-semibold">--}}
{{-- {{ mb_substr($user->full_name ?? $user->name, 0, 1) }}--}}
{{-- </div>--}}
{{-- <div>--}}
{{-- <div class="fw-semibold">{{ $user->full_name ?? $user->name }}</div>--}}
{{-- <small class="text-muted">کاربر سایت</small>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- --}}{{-- ایمیل --}}
{{-- <td>{{ $user->email }}</td>--}}
{{-- --}}{{-- موبایل --}}
{{-- <td>{{ $user->mobile ?? '-' }}</td>--}}
{{-- --}}{{-- وضعیت --}}
{{-- <td>--}}
{{-- @if((int) $user->status === 1)--}}
{{-- <span class="badge bg-success-subtle text-success">فعال</span>--}}
{{-- @else--}}
{{-- <span class="badge bg-danger-subtle text-danger">غیرفعال</span>--}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{-- تاریخ عضویت --}}
{{-- <td>--}}
{{-- @if($user->created_at)--}}
{{-- {{ $user->created_at->toJalali()->format('Y/m/d H:i') }}--}}
{{-- @else--}}
{{-- ---}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{-- عملیات --}}
{{-- <td class="text-center">--}}
{{-- <div class="d-flex justify-content-center gap-2">--}}
{{-- --}}{{-- ویرایش --}}
{{-- <a href="{{ route('admin.users.edit', $user) }}"--}}
{{-- class="btn btn-sm btn-primary fw-semibold">--}}
{{-- ویرایش--}}
{{-- </a>--}}
{{-- --}}{{-- حذف --}}
{{-- <form action="{{ route('admin.users.destroy', $user) }}"--}}
{{-- method="POST"--}}
{{-- class="d-inline"--}}
{{-- onsubmit="return confirm('آیا از حذف این کاربر مطمئن هستید؟')">--}}
{{-- @csrf--}}
{{-- @method('DELETE')--}}
{{-- <button type="submit" class="btn btn-sm btn-danger fw-semibold">--}}
{{-- حذف--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @empty--}}
{{-- <tr>--}}
{{-- <td colspan="7" class="text-center py-5 text-muted">--}}
{{-- کاربری برای نمایش وجود ندارد.--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @endforelse--}}
{{-- </tbody>--}}
{{-- </table>--}}
{{-- </div>--}}
{{-- --}}{{-- صفحه‌بندی --}}
{{-- @if($users->hasPages())--}}
{{-- <div class="card-footer">--}}
{{-- {{ $users->links() }}--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@extends('admin.layouts.app')--}}
{{--@section('title', 'مدیریت کاربران')--}}
{{--@section('breadcrumb')--}}
{{-- <div>--}}
{{-- <h1 class="page-title fw-medium fs-18 mb-2">مدیریت کاربران</h1>--}}
{{-- <nav>--}}
{{-- <ol class="breadcrumb mb-0">--}}
{{-- <li class="breadcrumb-item">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}">داشبورد</a>--}}
{{-- </li>--}}
{{-- <li class="breadcrumb-item active">مدیریت کاربران</li>--}}
{{-- </ol>--}}
{{-- </nav>--}}
{{-- </div>--}}
{{--@endsection--}}
{{--@section('content')--}}
{{-- <div class="container-fluid pt-4">--}}
{{-- @if(session('success'))--}}
{{-- <div class="alert alert-success alert-dismissible fade show" role="alert">--}}
{{-- {{ session('success') }}--}}
{{-- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- @if(session('error'))--}}
{{-- <div class="alert alert-danger alert-dismissible fade show" role="alert">--}}
{{-- {{ session('error') }}--}}
{{-- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{----}}{{-- جستجو --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3">--}}
{{-- <form method="GET" action="{{ route('admin.users.index') }}"--}}
{{-- class="d-flex flex-wrap gap-2 align-items-center">--}}
{{-- <div class="flex-grow-1" style="min-width: 200px;">--}}
{{-- <input type="text"--}}
{{-- name="search"--}}
{{-- value="{{ request('search') }}"--}}
{{-- class="form-control"--}}
{{-- placeholder="جستجو بر اساس نام، ایمیل یا موبایل...">--}}
{{-- </div>--}}
{{-- <button type="submit" class="btn btn-primary">جستجو</button>--}}
{{-- @if(request('search'))--}}
{{-- <a href="{{ route('admin.users.index') }}" class="btn btn-secondary">پاک‌کردن</a>--}}
{{-- @endif--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- --}}{{----}}{{-- جدول کاربران --}}
{{-- <div class="row">--}}
{{-- <div class="col-xl-12">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-body p-3 d-flex justify-content-between align-items-center">--}}
{{-- <h5 class="mb-0">لیست کاربران</h5>--}}
{{-- <span class="badge bg-primary-transparent">{{ $users->total() }} کاربر</span>--}}
{{-- </div>--}}
{{-- <div class="table-responsive">--}}
{{-- <table class="table text-nowrap table-hover table-bordered mb-0">--}}
{{-- <thead>--}}
{{-- <tr>--}}
{{-- <th>#</th>--}}
{{-- <th>نام کاربر</th>--}}
{{-- <th>ایمیل</th>--}}
{{-- <th>موبایل</th>--}}
{{-- <th>وضعیت</th>--}}
{{-- <th>تاریخ عضویت</th>--}}
{{-- <th class="text-center">عملیات</th>--}}
{{-- </tr>--}}
{{-- </thead>--}}
{{-- <tbody>--}}
{{-- @forelse($users as $user)--}}
{{-- <tr>--}}
{{-- <td>{{ $user->id }}</td>--}}
{{-- --}}{{----}}{{-- نام --}}
{{-- <td>--}}
{{-- <div class="d-flex align-items-center">--}}
{{-- <div class="avatar avatar-sm bg-primary-transparent me-2 fw-semibold">--}}
{{-- {{ mb_substr($user->full_name ?? $user->name, 0, 1) }}--}}
{{-- </div>--}}
{{-- <div>--}}
{{-- <div class="fw-semibold">{{ $user->full_name ?? $user->name }}</div>--}}
{{-- <small class="text-muted">کاربر سایت</small>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- --}}{{----}}{{-- ایمیل --}}
{{-- <td>{{ $user->email }}</td>--}}
{{-- --}}{{----}}{{-- موبایل --}}
{{-- <td>{{ $user->mobile ?? '-' }}</td>--}}
{{-- --}}{{----}}{{-- وضعیت --}}
{{-- <td>--}}
{{-- @if((int) $user->status === 1)--}}
{{-- <span class="badge bg-success-subtle text-success">فعال</span>--}}
{{-- @else--}}
{{-- <span class="badge bg-danger-subtle text-danger">غیرفعال</span>--}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{----}}{{-- تاریخ عضویت --}}
{{-- <td>--}}
{{-- @if($user->created_at)--}}
{{-- {{ $user->created_at->toJalali()->format('Y/m/d H:i') }}--}}
{{-- @else--}}
{{-- ---}}
{{-- @endif--}}
{{-- </td>--}}
{{-- --}}{{----}}{{-- عملیات --}}
{{-- <td class="text-center">--}}
{{-- <div class="d-flex justify-content-center gap-2">--}}
{{-- --}}{{----}}{{-- نمایش --}}
{{-- <a href="{{ route('admin.users.show', $user) }}"--}}
{{-- class="btn btn-sm btn-secondary fw-semibold">--}}
{{-- نمایش--}}
{{-- </a>--}}
{{-- --}}{{----}}{{-- ویرایش --}}
{{-- <a href="{{ route('admin.users.edit', $user) }}"--}}
{{-- class="btn btn-sm btn-primary fw-semibold">--}}
{{-- ویرایش--}}
{{-- </a>--}}
{{-- --}}{{----}}{{-- حذف --}}
{{-- <form action="{{ route('admin.users.destroy', $user) }}"--}}
{{-- method="POST"--}}
{{-- class="d-inline"--}}
{{-- onsubmit="return confirm('آیا از حذف این کاربر مطمئن هستید؟')">--}}
{{-- @csrf--}}
{{-- @method('DELETE')--}}
{{-- <button type="submit" class="btn btn-sm btn-danger fw-semibold">--}}
{{-- حذف--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @empty--}}
{{-- <tr>--}}
{{-- <td colspan="7" class="text-center py-5 text-muted">--}}
{{-- کاربری برای نمایش وجود ندارد.--}}
{{-- </td>--}}
{{-- </tr>--}}
{{-- @endforelse--}}
{{-- </tbody>--}}
{{-- </table>--}}
{{-- </div>--}}
{{-- --}}{{----}}{{-- صفحه‌بندی --}}
{{-- @if($users->hasPages())--}}
{{-- <div class="card-footer">--}}
{{-- {{ $users->links() }}--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
+2 -2
View File
@@ -98,8 +98,8 @@
<input
type="text"
id="login"
name="login"
id="username"
name="username"
value="{{ old('login') }}"
class="form-control"
placeholder="ایمیل یا نام کاربری"
+119 -6
View File
@@ -118,9 +118,12 @@
maxlength="100"
required
>
@error('first_name')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -144,9 +147,12 @@
maxlength="100"
required
>
@error('last_name')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -171,9 +177,12 @@
inputmode="numeric"
required
>
@error('national_code')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -286,9 +295,12 @@
placeholder="در صورت تأهل وارد کنید"
maxlength="200"
>
@error('spouse_name')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -336,9 +348,12 @@
inputmode="numeric"
required
>
@error('mobile')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -363,9 +378,12 @@
dir="ltr"
required
>
@error('email')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
@@ -414,6 +432,9 @@
pattern="[A-Za-z0-9]+"
required
>
@error('username')
<span style="color: red">{{ $message }}</span>
@enderror
<small class="form-help">
فقط حروف انگلیسی و اعداد مجاز است.
@@ -421,6 +442,7 @@
</div>
</div>
@@ -595,6 +617,9 @@
class="form-control"
accept="image/jpeg,image/png,image/jpg"
>
@error('image')
<span style="color: red">{{ $message }}</span>
@enderror
<small class="form-help">
@@ -610,6 +635,7 @@
</div>
</div>
@@ -657,3 +683,90 @@
</div>
@endsection
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function () {
const provinceSelect = document.getElementById('province_id');
const citySelect = document.getElementById('city_id');
provinceSelect.addEventListener('change', function () {
const provinceId = this.value;
// پاک کردن شهرستان‌ها
citySelect.innerHTML = `
<option value="">
در حال دریافت شهرستان‌ها...
</option>
`;
if (!provinceId) {
citySelect.innerHTML = `
<option value="">
ابتدا استان را انتخاب کنید
</option>
`;
return;
}
fetch(`/auth/register/provinces/${provinceId}/cities`)
.then(response => {
if (!response.ok) {
throw new Error('خطا در دریافت شهرستان‌ها');
}
return response.json();
})
.then(cities => {
citySelect.innerHTML = `
<option value="">
انتخاب شهرستان
</option>
`;
if (cities.length === 0) {
citySelect.innerHTML = `
<option value="">
شهرستانی برای این استان پیدا نشد
</option>
`;
return;
}
cities.forEach(city => {
const option = document.createElement('option');
option.value = city.id;
option.textContent = city.name;
citySelect.appendChild(option);
});
})
.catch(error => {
console.error(error);
citySelect.innerHTML = `
<option value="">
خطا در دریافت شهرستان‌ها
</option>
`;
});
});
});
</script>
@endpush
+77 -2
View File
@@ -1,3 +1,78 @@
<div>
<!-- No surplus words or unnecessary actions. - Marcus Aurelius -->
@extends('layouts.app')
@section('content')
<div class="container py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>نظرات من</h2>
<a href="{{ route('account.index') }}" class="btn btn-outline-secondary btn-sm">بازگشت به پنل</a>
</div>
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
@if($comments->isEmpty())
<div class="alert alert-info">
هنوز نظری ثبت نکردهای.
<a href="{{ route('tours.index') }}" class="alert-link">مشاهده تورها</a>
</div>
@else
<div class="card">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>مربوط به</th>
<th>متن نظر</th>
<th>تاریخ</th>
<th>وضعیت</th>
</tr>
</thead>
<tbody>
@foreach($comments as $comment)
<tr>
{{-- آیتم مرتبط (تور یا پرواز) --}}
<td>
@if($comment->commentable)
@if($comment->commentable instanceof \App\Models\Tour)
<a href="{{ route('tours.show', $comment->commentable) }}">
<i class="fa fa-plane"></i> {{ $comment->commentable->title }}
</a>
@else
<a href="{{ route('flights.show', $comment->commentable) }}">
<i class="fa fa-plane"></i>
{{ $comment->commentable->title ?? $comment->commentable->flight_number ?? 'پرواز' }}
</a>
@endif
@else
<span class="text-muted">حذف شده</span>
@endif
</td>
<td class="text-muted">{{ Str::limit($comment->body, 80) }}</td>
<td>{{ $comment->created_at->format('Y/m/d') }}</td>
<td>
@if($comment->status == 2)
<span class="badge bg-success">تایید شده</span>
@elseif($comment->status == 1)
<span class="badge bg-warning text-dark">در انتظار تایید</span>
@else
<span class="badge bg-danger">رد شده</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<div class="mt-3 d-flex justify-content-center">
{{ $comments->links() }}
</div>
@endif
</div>
@endsection
+93 -2
View File
@@ -1,3 +1,94 @@
<div>
<!-- We must ship. - Taylor Otwell -->
<div class="col-md-12">
<div class="theme-search-results-item">
<div class="theme-search-results-item-preview">
<div class="row">
<div class="col-md-2">
<div class="theme-search-results-item-flight-logo">
<i class="fa fa-plane fa-2x"></i>
<h5>
{{ $airline }}
</h5>
</div>
</div>
<div class="col-md-2">
<h4>
{{ $departure }}
</h4>
<p>
{{ $from }}
</p>
</div>
<div class="col-md-2 text-center">
<i class="fa fa-long-arrow-right"></i>
<p>
پرواز مستقیم
</p>
</div>
<div class="col-md-2">
<h4>
{{ $arrival }}
</h4>
<p>
{{ $to }}
</p>
</div>
<div class="col-md-2">
<strong>
{{ $price }}
</strong>
<small>
تومان
</small>
</div>
<div class="col-md-2">
<a
href="{{ url('/flights/1') }}"
class="btn btn-primary btn-block">
جزئیات
</a>
</div>
</div>
</div>
</div>
</div>
+19 -16
View File
@@ -1,19 +1,22 @@
@props(['tour'])
<div class="banner _h-33vh _br-3 banner-animate banner-animate-mask-in">
<div class="card tour-card">
<a href="{{ route('tours.show', $tour) }}">
<img src="{{ $tour->images->first()->path ?? asset('images/placeholder.jpg') }}" class="card-img-top"
alt="{{ $tour->title }}">
<div
class="banner-bg"
style="background-image:url('{{ asset($tour->image) }}');">
</div>
<div class="banner-mask"></div>
<a
class="banner-link"
href="{{ route('tours.show', $tour) }}">
</a>
<div class="card-body">
<h5 class="card-title">
<a href="{{ route('tours.show', $tour) }}">{{ $tour->title }}</a>
</h5>
<p class="card-text">{{ Str::limit($tour->description, 80) }}</p>
<div class="d-flex justify-content-between">
<span>{{ $tour->travelType->title ?? '—' }}</span>
<strong>{{ number_format($tour->price) }} تومان</strong>
</div>
</div>
</div>
<div class="banner-caption _pt-120 banner-caption-bottom banner-caption-grad">
<h5 class="banner-title">
{{ $tour->title }}
</h5>
</div>
</div>
+72
View File
@@ -0,0 +1,72 @@
@extends('layouts.app')
@section('title', 'آرشیو پروازها')
@push('styles')
<link rel="stylesheet" href="{{ asset('assets/css/archive.css') }}">
@endpush
@section('content')
<div class="archive-page">
<div class="container">
{{-- هدر آرشیو --}}
<div class="archive-header">
<h4><i class="fa fa-plane mr-2"></i> آرشیو پروازها</h4>
<a href="{{ route('index') }}" class="btn-back">
<i class="fa fa-home"></i> بازگشت به صفحه اصلی
</a>
</div>
<div class="row">
@forelse($flights as $flight)
<div class="col-md-4 col-sm-6 mb-4">
<div class="flight-card">
<div class="flight-body">
{{-- مسیر پرواز --}}
<div class="flight-route">
<div class="flight-city">
<span>مبدأ</span>
<strong>{{ $flight->origin }}</strong>
</div>
<div class="flight-line">
<span class="plane-icon">✈</span>
</div>
<div class="flight-city">
<span>مقصد</span>
<strong>{{ $flight->destination }}</strong>
</div>
</div>
{{-- زمان‌ها --}}
<div class="flight-info">
<p>🛫 حرکت: {{ $flight->departure_time?->toJalali()->format('Y/m/d H:i') }}</p>
<p>🛬 ورود: {{ $flight->arrival_time?->toJalali()->format('Y/m/d H:i') }}</p>
</div>
{{-- قیمت --}}
<span class="flight-price">{{ number_format($flight->price) }} تومان</span>
<a href="{{ route('flights.show', $flight->id) }}" class="btn btn-sm btn-primary btn-block mt-3">
مشاهده جزئیات <i class="fa fa-arrow-left"></i>
</a>
</div>
</div>
</div>
@empty
<div class="col-12">
<div class="archive-empty">
<i class="fa fa-plane"></i>
<p>هنوز پروازی ثبت نشده است.</p>
</div>
</div>
@endforelse
</div>
<div class="archive-pagination">
{{ $flights->links('pagination::bootstrap-4') }}
</div>
</div>
</div>
@endsection
+101 -2
View File
@@ -1,3 +1,102 @@
<div>
<!-- Simplicity is an acquired taste. - Katharine Gerould -->
@extends('layouts.app')
@section('title', 'جزئیات پرواز')
@section('content')
<div class="theme-page-section theme-page-section-gray">
<div class="container">
<div class="theme-page-section-header">
<h1 class="theme-page-section-title">
جزئیات پرواز
</h1>
</div>
<div class="row">
<div class="col-md-8">
<div class="theme-search-results-item">
<div class="theme-search-results-item-preview">
<h3>
{{ $flight->origin }} → {{ $flight->destination }}
</h3>
<hr>
<p>
<strong>شماره پرواز:</strong> {{ $flight->flight_number }}
</p>
<p>
<strong>شرکت هواپیمایی:</strong> {{ $flight->airline_name }}
</p>
<p>
<strong>تاریخ حرکت:</strong> {{ $flight->departure_date }}
</p>
<p>
<strong>ساعت حرکت:</strong> {{ $flight->departure_time }}
</p>
<p>
<strong>تاریخ رسیدن:</strong> {{ $flight->arrival_date }}
</p>
<p>
<strong>ساعت رسیدن:</strong> {{ $flight->arrival_time }}
</p>
<p>
<strong>مدت پرواز:</strong> {{ $flight->duration }}
</p>
<p>
<strong>ظرفیت:</strong> {{ $flight->capacity }} نفر
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="theme-search-results-item">
<div class="theme-search-results-item-preview">
<h4>قیمت بلیت</h4>
<h2>
{{ number_format($flight->price) }} تومان
</h2>
<a
href="{{ route('booking.flight', $flight) }}"
class="btn btn-primary"
>
رزرو پرواز
</a>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
File diff suppressed because it is too large Load Diff
+8 -153
View File
@@ -17,9 +17,13 @@
<link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
<link rel="stylesheet" href="{{ asset('assets/plugins/bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/account.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/archive.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/auth.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
{{-- صفحه‌هایی که CSS اختصاصی دارند --}}
@stack('styles')
@@ -31,9 +35,9 @@
@include('layouts.header')
{{-- Navbar --}}
@include('layouts.navbar')
{{--@include('layouts.navbar')--}}
{{-- محتوای اصلی هر صفحه --}}
@yield('content')
{{-- Footer --}}
@@ -62,158 +66,9 @@
<script src="{{ asset('assets/js/fitvid.js') }}"></script>
<script src="{{ asset('assets/js/youtube-bg.js') }}"></script>
<script src="{{ asset('assets/js/custom.js') }}"></script>
<script src="{{ asset('assets/js/chart.js') }}"></script>
@stack('scripts')
</body>
</html>
{{-- resources/views/layouts/app.blade.php --}}
{{-- <!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{-- <meta name="csrf-token" content="{{ csrf_token() }}">--}}
{{-- <title>@yield('title', 'آژانس مسافرتی')</title>--}}
{{-- @vite(['resources/css/app.css', 'resources/js/app.js'])--}}
{{-- @stack('styles')--}}
{{--</head>--}}
{{--<body>--}}
{{-- ===== ناوبری بالا ===== --}}
{{--<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">--}}
{{-- <div class="container">--}}
{{-- <a class="navbar-brand" href="{{ route('home') }}">آژانس پرواز</a>--}}
{{-- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav">--}}
{{-- <span class="navbar-toggler-icon"></span>--}}
{{-- </button>--}}
{{-- <div class="collapse navbar-collapse" id="mainNav">--}}
{{-- <ul class="navbar-nav ms-auto">--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('tours.index') }}">تورها</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('flights.index') }}">پروازها</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('about') }}">درباره ما</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('contact') }}">تماس با ما</a></li>--}}
{{-- </ul>--}}
{{-- --}}{{-- منوی کاربر --}}
{{-- <ul class="navbar-nav ms-auto">--}}
{{-- @auth--}}
{{-- <li class="nav-item dropdown">--}}
{{-- <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">--}}
{{-- {{ Auth::user()->name }}--}}
{{-- </a>--}}
{{-- <ul class="dropdown-menu dropdown-menu-end">--}}
{{-- <li><a class="dropdown-item" href="{{ route('dashboard') }}">پیشخوان</a></li>--}}
{{-- <li><a class="dropdown-item" href="{{ route('account.bookings') }}">رزروهای من</a></li>--}}
{{-- <li><a class="dropdown-item" href="{{ route('account.favorites') }}">علاقه‌مندی‌ها</a></li>--}}
{{-- <li><hr class="dropdown-divider"></li>--}}
{{-- <li>--}}
{{-- <form method="POST" action="{{ route('logout') }}">--}}
{{-- @csrf--}}
{{-- <button class="dropdown-item" type="submit">خروج</button>--}}
{{-- </form>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- @else--}}
{{-- <a href="{{ route('login') }}" class="btn btn-outline-light me-2">ورود</a>--}}
{{-- <a href="{{ route('register') }}" class="btn btn-primary">ثبت‌نام</a>--}}
{{-- @endauth--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</nav>--}}
{{-- ===== محتوای صفحه ===== --}}
{{--<main class="py-5 mt-5">--}}
{{-- @yield('content')--}}
{{--</main>--}}
{{-- ===== فوتر ===== --}}
{{--<footer class="bg-dark text-light py-4 mt-5">--}}
{{-- <div class="container text-center">--}}
{{-- <p class="mb-0">© {{ date('Y') }} — آژانس مسافرتی | تمامی حقوق محفوظ است</p>--}}
{{-- </div>--}}
{{--</footer>--}}
{{--@stack('scripts')--}}
{{--</body>--}}
{{--</html>--}}
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{-- <title>قالب رزرواسیون</title>--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">--}}
{{--</head>--}}
{{--<body>--}}
{{--@include('layouts.header')--}}
{{--@include('layouts.navbar')--}}
{{--@yield('content')--}}
{{--@include('layouts.footer')--}}
{{--<script src="{{ asset('assets/js/jquery.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/moment.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/bootstrap.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/owl-carousel.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/blur-area.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/icheck.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/gmap.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/magnific-popup.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/ion-range-slider.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/sticky-kit.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/smooth-scroll.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/fotorama.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/bs-datepicker.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/typeahead.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/quantity-selector.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/countdown.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/window-scroll-action.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/fitvid.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/youtube-bg.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/custom.js') }}"></script>--}}
{{--</body>--}}
{{--</html>--}}
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{-- <title>@yield('title', 'آژانس هواپیمایی')</title>--}}
{{-- @include('layouts.icon')--}}
{{-- <link rel="stylesheet" href="{{ asset('css/app.css') }}">--}}
{{-- @stack('styles')--}}
{{--</head>--}}
{{--<body>--}}
{{--@include('layouts.header')--}}
{{--@include('layouts.navbar')--}}
{{--<main>--}}
{{-- @yield('content')--}}
{{--</main>--}}
{{--@include('layouts.footer')--}}
{{--@stack('scripts')--}}
{{--</body>--}}
{{--</html>--}}
-200
View File
@@ -149,53 +149,6 @@
</div>
{{-- Newsletter --}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-section-subscribe bg-grad">--}}
{{-- <div--}}
{{-- class="theme-footer-section-subscribe-bg"--}}
{{-- style="background-image:url('{{ asset('img/footer/footer_subscribe_bg.png') }}');">--}}
{{-- </div>--}}
{{-- <div class="theme-footer-section-subscribe-content">--}}
{{-- <h5 class="theme-footer-section-title">--}}
{{-- از پیشنهادهای ویژه باخبر شوید--}}
{{-- </h5>--}}
{{-- <p class="text-muted">--}}
{{-- ایمیل خود را وارد کنید تا پیشنهادهای ویژه را دریافت کنید.--}}
{{-- </p>--}}
{{-- <form>--}}
{{-- <div class="form-group">--}}
{{-- <input--}}
{{-- class="form-control theme-footer-subscribe-form-control"--}}
{{-- type="email"--}}
{{-- placeholder="ایمیل شما">--}}
{{-- </div>--}}
{{-- <button--}}
{{-- class="btn btn-primary-invert btn-shadow text-upcase theme-footer-subscribe-btn"--}}
{{-- type="submit">--}}
{{-- عضویت--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
</div>
</div>
@@ -256,156 +209,3 @@
</div>
</div>
{{--<footer class="theme-footer">--}}
{{-- <div class="theme-footer-area theme-footer-area-dark">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="row row-col-gap">--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-">--}}
{{-- <h5 class="theme-footer-section-title">سفر کنید</h5>--}}
{{-- <ul class="theme-footer-section-list">--}}
{{-- <li>--}}
{{-- <a href="#">کشورها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مناطق</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">شهرها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">نواحی</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">فرودگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">هتل</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مکان های مورد علاقه</a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-">--}}
{{-- <h5 class="theme-footer-section-title">کتاب</h5>--}}
{{-- <ul class="theme-footer-section-list">--}}
{{-- <li>--}}
{{-- <a href="#">آپارتمان ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">استراحتگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">ویلاها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">خوابگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">رستوران</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مهمانخانه</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">هتل های زنجیره ای</a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-section-subscribe bg-grad _mt-mob-30">--}}
{{-- <div class="theme-footer-section-subscribe-bg"--}}
{{-- style="background-image:url('{{ asset('assets/img/footer/footer_subscribe_bg.png') }}');">--}}
{{-- </div>--}}
{{-- <div class="theme-footer-section-subscribe-content">--}}
{{-- <h5 class="theme-footer-section-title">--}}
{{-- تا 50 درصد از سفر بعدی خود صرفه جویی کنید--}}
{{-- </h5>--}}
{{-- <p class="text-muted">--}}
{{-- برای باز کردن قفل معاملات مخفی ما مشترک شوید--}}
{{-- </p>--}}
{{-- <form>--}}
{{-- <div class="form-group">--}}
{{-- <input--}}
{{-- class="form-control theme-footer-subscribe-form-control"--}}
{{-- type="email"--}}
{{-- placeholder="ایمیل خود را اینجا تایپ کنید">--}}
{{-- </div>--}}
{{-- <button--}}
{{-- class="btn btn-primary-invert btn-shadow text-upcase theme-footer-subscribe-btn"--}}
{{-- type="submit">--}}
{{-- معاملات دریافت کنید--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="theme-copyright">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="row">--}}
{{-- <div class="col-md-6">--}}
{{-- <p class="theme-copyright-text">--}}
{{-- حق چاپ © 1400--}}
{{-- <a href="#">Bookify</a>--}}
{{-- . تمامی حقوق محفوظ است.--}}
{{-- </p>--}}
{{-- </div>--}}
{{-- <div class="col-md-6">--}}
{{-- <ul class="theme-copyright-social">--}}
{{-- <li>--}}
{{-- <a class="fa fa-facebook" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-google" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-twitter" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-youtube-play" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-instagram" href="#"></a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</footer>--}}
+105 -50
View File
@@ -108,51 +108,138 @@
</nav>
{{-- سمت چپ --}}
<div class="travel-navbar-actions">
@guest
@auth
{{-- کاربر وارد نشده --}}
{{-- =====================================
کاربر وارد شده
====================================== --}}
<a href="{{ route('auth.login.index') }}" class="travel-login">
<div class="travel-user-menu">
<i class="fa fa-sign-in"></i>
{{-- دکمه حساب کاربری --}}
<button
type="button"
class="travel-user-button">
ورود
<i class="fa fa-user-circle"></i>
</a>
<span>
{{ auth()->user()->first_name }}
{{ auth()->user()->last_name }}
</span>
<a href="{{ route('auth.register.index') }}" class="travel-register">
<i class="fa fa-angle-down travel-user-arrow"></i>
<i class="fa fa-user-plus"></i>
</button>
ثبت‌نام
</a>
{{-- =================================
زیرمنوی حساب کاربری
================================== --}}
@else
<div class="travel-user-dropdown">
{{-- کاربر وارد شده --}}
<a href="{{ route('account.index') }}" class="travel-login">
{{-- پروفایل --}}
<a href="{{ route('account.edit-profile.index') }}">
<i class="fa fa-user"></i>
حساب کاربری
<span>
پروفایل
</span>
</a>
<a href="{{ route('auth.logout') }}" class="travel-logout">
{{-- علاقه‌مندی‌ها --}}
<a href="{{ route('account.favorites') }}">
<i class="fa fa-heart"></i>
<span>
علاقه‌مندی‌ها
</span>
</a>
{{-- نظرات قبلی --}}
@if(Route::has('account.comments'))
<a href="{{ route('account.comments') }}">
<i class="fa fa-comments"></i>
<span>
نظرات قبلی
</span>
</a>
@endif
{{-- جداکننده --}}
<div class="travel-dropdown-divider"></div>
{{-- خروج --}}
<a
href="{{ route('auth.logout') }}"
class="travel-logout-link">
<i class="fa fa-sign-out"></i>
<span>
خروج
</span>
</a>
@endguest
</div>
</div>
@else
{{-- =====================================
کاربر وارد نشده
====================================== --}}
<a
href="{{ route('auth.login.index') }}"
class="travel-login">
<i class="fa fa-sign-in"></i>
<span>
ورود
</span>
</a>
<a
href="{{ route('auth.register.index') }}"
class="travel-register">
<i class="fa fa-user-plus"></i>
<span>
ثبت‌نام
</span>
</a>
@endauth
{{-- =========================================
دکمه منوی موبایل
========================================== --}}
<button
type="button"
@@ -164,27 +251,6 @@
</button>
</div>
{{-- <div class="travel-navbar-actions">--}}
{{-- <a href="{{ route('auth') }}" class="travel-login">--}}
{{-- <i class="fa fa-user"></i>--}}
{{-- ورود / ثبت‌نام--}}
{{-- </a>--}}
{{-- <button--}}
{{-- type="button"--}}
{{-- class="travel-mobile-toggle"--}}
{{-- aria-label="منو">--}}
{{-- <i class="fa fa-bars"></i>--}}
{{-- </button>--}}
{{-- </div>--}}
</div>
@@ -301,14 +367,3 @@
</div>
</header>
{{--<meta charset="UTF-8">--}}
{{--<meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{--<title>@yield('title', 'Dornica')</title>--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">--}}
+123 -123
View File
@@ -2,177 +2,177 @@
class="navbar navbar-default navbar-inverse navbar-theme navbar-theme-abs navbar-theme-transparent navbar-theme-border"
id="main-nav">
<div class="container">
{{-- <div class="container">--}}
<div class="navbar-inner nav">
{{-- <div class="navbar-inner nav">--}}
{{-- Logo --}}
<div class="navbar-header">
{{-- --}}{{-- Logo --}}
{{-- <div class="navbar-header">--}}
<button
class="navbar-toggle collapsed"
data-target="#navbar-main"
data-toggle="collapse"
type="button"
aria-expanded="false">
{{-- <button--}}
{{-- class="navbar-toggle collapsed"--}}
{{-- data-target="#navbar-main"--}}
{{-- data-toggle="collapse"--}}
{{-- type="button"--}}
{{-- aria-expanded="false">--}}
<span class="sr-only">باز کردن منو</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
{{-- <span class="sr-only">باز کردن منو</span>--}}
{{-- <span class="icon-bar"></span>--}}
{{-- <span class="icon-bar"></span>--}}
{{-- <span class="icon-bar"></span>--}}
</button>
{{-- </button>--}}
<a class="navbar-brand" href="{{ url('/') }}">
<img
src="{{ asset('img/logo.png') }}"
alt="آژانس مسافرتی">
</a>
{{-- <a class="navbar-brand" href="{{ url('/') }}">--}}
{{-- <img--}}
{{-- src="{{ asset('img/logo.png') }}"--}}
{{-- alt="آژانس مسافرتی">--}}
{{-- </a>--}}
</div>
{{-- </div>--}}
{{-- Main Menu --}}
<div class="collapse navbar-collapse" id="navbar-main">
{{-- --}}{{-- Main Menu --}}
{{-- <div class="collapse navbar-collapse" id="navbar-main">--}}
<ul class="nav navbar-nav">
{{-- <ul class="nav navbar-nav">--}}
<li>
<a href="{{ url('/') }}">
صفحه اصلی
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/') }}">--}}
{{-- صفحه اصلی--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/flights') }}">
پروازها
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/flights') }}">--}}
{{-- پروازها--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/offers') }}">
پیشنهادهای ویژه
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/offers') }}">--}}
{{-- پیشنهادهای ویژه--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/about') }}">
درباره ما
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/about') }}">--}}
{{-- درباره ما--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/faq') }}">
سوالات متداول
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/faq') }}">--}}
{{-- سوالات متداول--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/contact') }}">
تماس با ما
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/contact') }}">--}}
{{-- تماس با ما--}}
{{-- </a>--}}
{{-- </li>--}}
</ul>
{{-- </ul>--}}
{{-- Right Menu --}}
<ul class="nav navbar-nav navbar-right">
{{-- --}}{{-- Right Menu --}}
{{-- <ul class="nav navbar-nav navbar-right">--}}
{{-- Currency --}}
<li class="dropdown">
{{-- --}}{{-- Currency --}}
{{-- <li class="dropdown">--}}
<a
class="dropdown-toggle"
href="#"
data-toggle="dropdown"
role="button">
{{-- <a--}}
{{-- class="dropdown-toggle"--}}
{{-- href="#"--}}
{{-- data-toggle="dropdown"--}}
{{-- role="button">--}}
<span class="_desk-h">
واحد پول
</span>
{{-- <span class="_desk-h">--}}
{{-- واحد پول--}}
{{-- </span>--}}
<b>تومان</b>
{{-- <b>تومان</b>--}}
</a>
{{-- </a>--}}
<ul class="dropdown-menu">
{{-- <ul class="dropdown-menu">--}}
<li>
<a href="#">تومان</a>
</li>
{{-- <li>--}}
{{-- <a href="#">تومان</a>--}}
{{-- </li>--}}
<li>
<a href="#">دلار</a>
</li>
{{-- <li>--}}
{{-- <a href="#">دلار</a>--}}
{{-- </li>--}}
<li>
<a href="#">یورو</a>
</li>
{{-- <li>--}}
{{-- <a href="#">یورو</a>--}}
{{-- </li>--}}
</ul>
{{-- </ul>--}}
</li>
{{-- </li>--}}
{{-- User --}}
<li class="navbar-nav-item-user dropdown">
{{-- --}}{{-- User --}}
{{-- <li class="navbar-nav-item-user dropdown">--}}
<a
class="dropdown-toggle"
href="#"
data-toggle="dropdown"
role="button">
{{-- <a--}}
{{-- class="dropdown-toggle"--}}
{{-- href="#"--}}
{{-- data-toggle="dropdown"--}}
{{-- role="button">--}}
<i class="fa fa-user-circle-o navbar-nav-item-user-icon"></i>
{{-- <i class="fa fa-user-circle-o navbar-nav-item-user-icon"></i>--}}
حساب من
{{-- حساب من--}}
</a>
{{-- </a>--}}
<ul class="dropdown-menu">
{{-- <ul class="dropdown-menu">--}}
<li>
<a href="{{ url('/account') }}">
داشبورد
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/account') }}">--}}
{{-- داشبورد--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/account/bookings') }}">
رزروهای من
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/account/bookings') }}">--}}
{{-- رزروهای من--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/account/favorites') }}">
علاقه‌مندی‌ها
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/account/favorites') }}">--}}
{{-- علاقه‌مندی‌ها--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/account/comments') }}">
نظرات من
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/account/comments') }}">--}}
{{-- نظرات من--}}
{{-- </a>--}}
{{-- </li>--}}
<li>
<a href="{{ url('/account/edit-profile') }}">
ویرایش پروفایل
</a>
</li>
{{-- <li>--}}
{{-- <a href="{{ url('/account/edit-profile') }}">--}}
{{-- ویرایش پروفایل--}}
{{-- </a>--}}
{{-- </li>--}}
</ul>
{{-- </ul>--}}
</li>
{{-- </li>--}}
</ul>
{{-- </ul>--}}
</div>
{{-- </div>--}}
</div>
{{-- </div>--}}
</div>
{{-- </div>--}}
</nav>
+60 -6
View File
@@ -1,18 +1,72 @@
@extends('layouts.app')
@section('title', 'لیست تورها')
@section('title', 'آرشیو تورها')
@push('styles')
<link rel="stylesheet" href="{{ asset('assets/css/archive.css') }}">
@endpush
@section('content')
<h1>تورهای ما</h1>
<div class="archive-page">
<div class="container">
{{-- هدر آرشیو --}}
<div class="archive-header">
<h4><i class="fa fa-plane mr-2"></i> آرشیو تورها</h4>
<a href="{{ route('index') }}" class="btn-back">
<i class="fa fa-home"></i> بازگشت به صفحه اصلی
</a>
</div>
<div class="row">
@forelse($tours as $tour)
<div class="col-md-4">
<x-tour :tour="$tour"/>
<div class="col-md-4 col-sm-6 mb-4">
<div class="tour-card">
<div class="tour-image-wrap">
{{-- دکمه علاقه‌مندی (در صورت لاگین بودن کاربر) --}}
@auth
<form action="{{ route('favorites.toggle', $tour->id) }}" method="POST" style="position: absolute; top: 10px; right: 10px; z-index: 10;">
@csrf
<button type="submit" class="btn btn-sm" style="background: rgba(255,255,255,0.8); border-radius: 50%; border:none; padding: 5px 10px;">
<i class="fa {{ $tour->isFavoritedBy(auth()->user()) ? 'fa-heart text-danger' : 'fa-heart-o' }}"></i>
</button>
</form>
@endauth
@if($tour->image)
<img src="{{ asset('storage/' . $tour->image) }}" alt="{{ $tour->title }}">
@else
<img src="{{ asset('assets/img/exp-page/slider/2.jpg') }}" alt="بدون تصویر">
@endif
</div>
<div class="tour-body">
<h5 class="tour-title">
<a href="{{ route('tours.show', $tour->id) }}">{{ $tour->title }}</a>
</h5>
<p class="tour-desc">{{ Str::limit(strip_tags($tour->description), 80) }}</p>
<div class="tour-footer">
<span class="tour-price">{{ number_format($tour->price) }} تومان</span>
<a href="{{ route('tours.show', $tour->id) }}" class="text-primary">
جزئیات <i class="fa fa-arrow-left"></i>
</a>
</div>
</div>
</div>
</div>
@empty
<p>تور فعالی یافت نشد.</p>
<div class="col-12">
<div class="archive-empty">
<i class="fa fa-map-marker"></i>
<p>هنوز توری ثبت نشده است.</p>
</div>
</div>
@endforelse
</div>
{{ $tours->links() }}
<div class="archive-pagination">
{{ $tours->links('pagination::bootstrap-4') }}
</div>
</div>
</div>
@endsection
+120 -374
View File
@@ -1,400 +1,146 @@
@extends('layouts.app')
@section('content')
<div class="container py-5">
<div class="tour-details-page">
<div class="container">
<div class="tour-details-card">
{{-- تصویر تور --}}
<div class="tour-details-image">
@if($tour->image)
<img
src="{{ asset('storage/' . $tour->image) }}"
alt="{{ $tour->title }}"
>
@else
<div class="tour-no-image">
تصویر برای این تور ثبت نشده است
{{-- پیام موفقیت--}}
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show d-flex align-items-center shadow-sm"
role="alert">
<i class="bi bi-check-circle-fill me-2"></i>
{{ session('success') }}
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
</div>
{{-- محتوای تور --}}
<div class="tour-details-content">
{{-- عنوان --}}
<h1 class="tour-details-title">
{{-- کارت اطلاعات تور --}}
<div class="card shadow-lg border-0 rounded-4 mb-4">
<div class="card-body p-4 p-md-5">
{{-- ردیف عنوان و دکمه علاقه‌مندی --}}
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="card-title h3 fw-bold mb-0 d-flex align-items-center">
<span class="badge bg-info bg-opacity-10 text-info p-2 me-2 rounded">
<i class="bi bi-airplane"></i>
</span>
{{ $tour->title }}
</h1>
{{-- دکمه علاقه‌مندی --}}
@auth
<form action="{{ route('favorites.toggle') }}" method="POST" class="m-0">
@csrf
<input type="hidden" name="favoritable_type" value="App\Models\Tour">
<input type="hidden" name="favoritable_id" value="{{ $tour->id }}">
{{-- اطلاعات اصلی --}}
<div class="tour-details-info">
<button type="submit"
class="btn {{ $tour->isFavoritedBy(auth()->user()) ? 'btn-outline-danger' : 'btn-outline-primary' }} rounded-pill px-4">
<i class="bi {{ $tour->isFavoritedBy(auth()->user()) ? 'bi-heart-fill' : 'bi-heart' }} me-1"></i>
{{ $tour->isFavoritedBy(auth()->user()) ? 'پسندیدم' : 'افزودن به علاقه‌مندی' }}
</button>
</form>
@endauth
</div>
{{-- نوع سفر --}}
<div class="tour-info-box">
<p class="card-text text-muted fs-5 mb-4 line-h-8">{{ $tour->description }}</p>
<div
class="d-inline-flex align-items-center gap-2 bg-primary bg-opacity-10 text-primary fw-bold px-4 py-2 rounded-3">
<i class="bi bi-tag-fill"></i>
<span>{{ number_format($tour->price) }} تومان</span>
</div>
</div>
</div>
<span class="tour-info-label">
نوع سفر
{{-- نظرات کاربران --}}
<div class="card shadow-lg border-0 rounded-4 mb-4">
<div class="card-body p-4 p-md-5">
<div class="d-flex justify-content-between align-items-center border-bottom pb-3 mb-4">
<h3 class="h5 fw-bold mb-0 d-flex align-items-center">
<span class="bg-purple bg-opacity-10 text-purple p-2 me-2 rounded-3">
<i class="bi bi-people-fill"></i>
</span>
<strong>
{{ $tour->travelType->title ?? 'نامشخص' }}
</strong>
</div>
{{-- تاریخ شروع --}}
<div class="tour-info-box">
<span class="tour-info-label">
تاریخ حرکت
</span>
<strong>
{{ $tour->start_date
? \Carbon\Carbon::parse($tour->start_date)->format('Y/m/d')
: 'نامشخص'
}}
</strong>
</div>
{{-- تاریخ پایان --}}
<div class="tour-info-box">
<span class="tour-info-label">
تاریخ پایان
</span>
<strong>
{{ $tour->end_date
? \Carbon\Carbon::parse($tour->end_date)->format('Y/m/d')
: 'نامشخص'
}}
</strong>
</div>
{{-- مدت سفر --}}
<div class="tour-info-box">
<span class="tour-info-label">
مدت سفر
</span>
<strong>
{{ $tour->duration ?? 'نامشخص' }}
</strong>
</div>
{{-- قیمت --}}
<div class="tour-info-box">
<span class="tour-info-label">
قیمت
</span>
<strong>
{{ number_format($tour->price) }}
تومان
</strong>
</div>
{{-- ظرفیت --}}
<div class="tour-info-box">
<span class="tour-info-label">
ظرفیت
</span>
<strong>
{{ $tour->capacity ?? 'نامحدود' }}
</strong>
</div>
{{-- تعداد بازدید --}}
<div class="tour-info-box">
<span class="tour-info-label">
تعداد بازدید
</span>
<strong>
{{ number_format($tour->views_count) }}
</strong>
</div>
</div>
{{-- توضیحات --}}
<div class="tour-description">
<h2>
توضیحات سفر
</h2>
@if($tour->description)
<p>
{{ $tour->description }}
</p>
@else
<p>
توضیحی برای این تور ثبت نشده است.
</p>
@endif
</div>
{{-- پروازهای تور --}}
@if($tour->flights && $tour->flights->count())
<div class="tour-flights">
<h2>
پروازهای این تور
</h2>
@foreach($tour->flights as $flight)
<div class="flight-item">
<div>
<span>
مبدأ
</span>
<strong>
{{ $flight->origin ?? '-' }}
</strong>
</div>
<div>
<span>
مقصد
</span>
<strong>
{{ $flight->destination ?? '-' }}
</strong>
</div>
</div>
@endforeach
</div>
@endif
{{-- تورهای مرتبط --}}
@if($relatedTours->count())
<div class="related-tours">
<h2>
تورهای مرتبط
</h2>
<div class="related-tours-grid">
@foreach($relatedTours as $relatedTour)
<a
href="{{ route('tours.show', $relatedTour) }}"
class="related-tour-card"
>
@if($relatedTour->image)
<img
src="{{ asset('storage/' . $relatedTour->image) }}"
alt="{{ $relatedTour->title }}"
>
@endif
<div>
<h3>
{{ $relatedTour->title }}
نظرات کاربران
</h3>
<span>
@if($relatedTour->start_date)
{{ \Carbon\Carbon::parse($relatedTour->start_date)->format('Y/m/d') }}
@endif
<span class="badge bg-purple bg-opacity-10 text-purple rounded-pill">
{{ $tour->comments_count ?? $tour->comments->count() }} نظر
</span>
</div>
</a>
<div class="d-flex flex-column gap-3">
@forelse($tour->comments as $comment)
<div class="p-3 rounded-4 bg-light border">
<div class="d-flex justify-content-between align-items-center mb-2 flex-wrap gap-2">
<div class="d-flex align-items-center gap-2">
<div
class="rounded-circle bg-gradient-primary d-flex align-items-center justify-content-center text-white fw-bold"
style="width:40px;height:40px;">
{{ mb_strtoupper(mb_substr($comment->user?->first_name ?? 'م', 0, 1)) }}
</div>
<strong
class="text-dark">{{ $comment->user?->first_name }} {{ $comment->user?->last_name }}</strong>
</div>
<small class="text-muted">
<i class="bi bi-clock me-1"></i>{{ $comment->created_at->diffForHumans() }}
</small>
</div>
<p class="mb-0 text-muted">{{ $comment->body }}</p>
</div>
@empty
<div class="text-center py-5">
<div
class="bg-light rounded-circle d-flex align-items-center justify-content-center mx-auto mb-3"
style="width:60px;height:60px;">
<i class="bi bi-chat-dots fs-2 text-muted"></i>
</div>
<p class="text-muted mb-0">هنوز نظری ثبت نشده است — اولین نفر باش! 🎉</p>
</div>
@endforelse
</div>
</div>
</div>
{{-- فرم ثبت نظر --}}
@auth
<div class="card shadow-lg border-0 rounded-4 mb-4">
<div class="card-body p-4 p-md-5">
<h2 class="card-title h4 fw-bold mb-4 d-flex align-items-center">
<span class="bg-primary bg-opacity-10 text-primary p-2 me-2 rounded-3">
<i class="bi bi-chat-left-text-fill"></i>
</span>
ثبت نظر شما
</h2>
@if($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
@endif
{{-- دکمه بازگشت --}}
<div class="tour-back">
<a
href="{{ route('tours.index') }}"
class="tour-back-button"
>
بازگشت به لیست تورها
</a>
<form action="{{ route('comments.tour.store', $tour->id) }}" method="POST">
@csrf
<div class="mb-3">
<textarea name="body" class="form-control" rows="4"
placeholder="نظر خود را درباره این تور بنویسید..." required></textarea>
@error('body')
<span class="text-danger small mt-1 d-block">{{ $message }}</span>
@enderror
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary px-4 rounded-pill">
<i class="bi bi-send-fill me-1"></i> ثبت نظر
</button>
</div>
</form>
</div>
</div>
@else
<div class="alert alert-warning text-center">
برای ثبت نظر لطفاً <a href="{{ route('auth.login.index') }}" class="alert-link">وارد شوید</a>.
</div>
@endauth
</div>
</div>
</div>
</div>
</div>
@endsection
{{-- resources/views/tours/show.blade.php --}}
{{--@extends('layouts.app')--}}
{{--@section('title', $tour->name)--}}
{{--@section('content')--}}
{{-- <div class="container py-5 mt-4">--}}
{{-- --}}{{-- اطلاعات تور --}}
{{-- <div class="card mb-4 shadow-sm">--}}
{{-- <div class="card-body">--}}
{{-- <h2 class="card-title">{{ $tour->name }}</h2>--}}
{{-- <p class="text-muted">{{ $tour->description }}</p>--}}
{{-- <hr>--}}
{{-- <div class="row">--}}
{{-- <div class="col-md-3"><strong>مبدأ:</strong> {{ $tour->origin->name ?? '—' }}</div>--}}
{{-- <div class="col-md-3"><strong>مقصد:</strong> {{ $tour->destination->name ?? '—' }}</div>--}}
{{-- <div class="col-md-3"><strong>تاریخ رفت:</strong> {{ $tour->start_date }}</div>--}}
{{-- <div class="col-md-3"><strong>بازگشت:</strong> {{ $tour->end_date }}</div>--}}
{{-- </div>--}}
{{-- <div class="row mt-3">--}}
{{-- <div class="col-md-4"><strong>قیمت:</strong> {{ number_format($tour->price) }} تومان</div>--}}
{{-- <div class="col-md-4"><strong>ظرفیت:</strong> {{ $tour->capacity }} نفر</div>--}}
{{-- <div class="col-md-4"><strong>موجودی:</strong> {{ $tour->available_seats ?? $tour->capacity }} نفر--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <hr>--}}
{{-- <p>{{ $tour->description }}</p>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </section>--}}
{{-- --}}{{-- ===== فرم رزرو تور ===== --}}
{{-- @auth--}}
{{-- <section class="pb-5">--}}
{{-- <div class="container">--}}
{{-- <div class="card shadow-sm">--}}
{{-- <div class="card-header bg-success text-white">--}}
{{-- رزرو تور {{ $tour->name }}--}}
{{-- </div>--}}
{{-- <div class="card-body">--}}
{{-- <form action="{{ route('booking.store', $tour) }}" method="POST">--}}
{{-- @csrf--}}
{{-- <div class="mb-3">--}}
{{-- <label class="form-label">تعداد نفرات</label>--}}
{{-- <input type="number" name="seats" min="1" max="{{ $tour->capacity }}" value="1"--}}
{{-- class="form-control @error('seats') is-invalid @enderror" required>--}}
{{-- @error('seats')--}}
{{-- <span class="invalid-feedback">{{ $message }}</span>--}}
{{-- @enderror--}}
{{-- </div>--}}
{{-- <button type="submit" class="btn btn-success w-100">رزرو تور</button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </section>--}}
{{-- @else--}}
{{-- --}}{{-- کاربر لاگین نیست => دکمه ورود به روت login --}}
{{-- <div class="alert alert-warning text-center">--}}
{{-- برای رزرو تور ابتدا <a href="{{ route('login') }}">وارد شوید</a>.--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- @endauth--}}
{{--@endsection--}}
{{--@extends('layouts.app')--}}
{{--@section('content')--}}
{{-- <h1>{{ $tour->title }}</h1>--}}
{{-- --}}{{----}}{{-- گالری تصاویر (اسلایدر) --}}
{{-- <div id="tourGallery" class="carousel slide" data-bs-ride="carousel">--}}
{{-- @foreach ($tour->images as $image)--}}
{{-- <div class="carousel-item @if($loop->first) active @endif">--}}
{{-- <img src="{{ $image->path }}" class="d-block w-100" alt="">--}}
{{-- </div>--}}
{{-- @endforeach--}}
{{-- </div>--}}
{{-- <p>{{ $tour->description }}</p>--}}
{{-- <p>تاریخ شروع: {{ $tour->start_date?->format('Y/m/d') }}</p>--}}
{{-- --}}{{----}}{{-- پروازهای این تور --}}
{{-- <h3>پروازهای همراه</h3>--}}
{{-- @foreach ($tour->flights as $flight)--}}
{{-- <x-flight :flight="$flight"/>--}}
{{-- @endforeach--}}
{{-- --}}{{----}}{{-- نظرات --}}
{{-- <h3>نظرات ({{ $tour->comments->count() }})</h3>--}}
{{-- @foreach ($tour->comments as $comment)--}}
{{-- <x-comment :comment="$comment"/>--}}
{{-- @endforeach--}}
{{-- @auth--}}
{{-- <form method="POST" action="{{ route('comments.store', $tour) }}">--}}
{{-- @csrf--}}
{{-- <textarea name="body" required></textarea>--}}
{{-- <button type="submit">ثبت نظر</button>--}}
{{-- </form>--}}
{{-- @endauth--}}
{{--@endsection--}}
+141 -47
View File
@@ -4,13 +4,13 @@
use App\Http\Controllers\Admin\AdminController;
use App\Http\Controllers\Admin\AirportController;
use App\Http\Controllers\Admin\AuthController;
use App\Http\Controllers\Admin\CityController;
use App\Http\Controllers\Admin\CommentController;
use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\FavoriteController;
use App\Http\Controllers\Admin\FlightController;
use App\Http\Controllers\Admin\PaymentController;
use App\Http\Controllers\Admin\ProvinceController;
use App\Http\Controllers\Admin\SettingController;
use App\Http\Controllers\Admin\SliderController;
use App\Http\Controllers\Admin\TourController;
use App\Http\Controllers\Admin\TravelTypeController;
use App\Http\Controllers\Admin\UserController;
@@ -18,11 +18,13 @@ use Illuminate\Support\Facades\Route;
Route::prefix('admin')->name('admin.')->group(function () {
// صفحه اصلی پنل ادمین
Route::get('/', function () {
return redirect()->route('admin.dashboard.index');
})->name('index');
// ------------------------------ احراز هویت ادمین ------------------------------
Route::prefix('auth')->name('auth.')->controller(AuthController::class)->group(function () {
Route::prefix('login')->name('login.')->middleware('guest:admin')->group(function () {
@@ -30,35 +32,58 @@ Route::prefix('admin')->name('admin.')->group(function () {
Route::post('/', 'loginPost')->name('post');
});
Route::get('logout', 'logout')->middleware('auth:admin')->name('logout');
Route::get('logout', 'logout')
->middleware('auth:admin')
->name('logout');
});
// ------------------------------ بخش‌های محافظت‌شده ------------------------------
Route::middleware('auth:admin')->group(function () {
Route::get('dashboard', [DashboardController::class, 'index'])->name('dashboard.index');
// ---------- dashboard ----------
Route::get('dashboard', [DashboardController::class, 'index'])
->name('dashboard.index');
Route::get('dashboard/export', [DashboardController::class, 'exportExcel'])
->name('dashboard.export');
// گزارش خروجی اکسل
Route::get('dashboard/export', [DashboardController::class, 'exportExcel'])->name('dashboard.export');
// ---------- users ----------
Route::prefix('users')->name('users.')->group(function () {
Route::get('/', [UserController::class, 'index'])->name('index');
Route::get('{user}/edit', [UserController::class, 'edit'])->name('edit');
Route::put('{user}', [UserController::class, 'update'])->name('update');
Route::delete('{user}', [UserController::class, 'destroy'])->name('destroy');
// تغییر رمز (دو روت مجزا برای فرم و ذخیره)
Route::get('{user}/change-password', [UserController::class, 'changePassword'])->name('change-password');
Route::put('{user}/change-password', [UserController::class, 'updatePassword'])->name('update-password');
Route::prefix('users')->name('users.')->group(function () {
Route::get('/', [UserController::class, 'index'])
->name('index');
Route::get('{user}/edit', [UserController::class, 'edit'])
->name('edit');
Route::put('{user}', [UserController::class, 'update'])
->name('update');
Route::delete('{user}', [UserController::class, 'destroy'])
->name('destroy');
Route::get('{user}/change-password', [UserController::class, 'changePassword'])
->name('change-password');
Route::put('{user}/change-password', [UserController::class, 'updatePassword'])
->name('update-password');
});
// ---------- admins ----------
Route::prefix('admins')->name('admins.')->controller(AdminController::class)->group(function () {
Route::prefix('admins')
->name('admins.')
->controller(AdminController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{admin}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
@@ -66,26 +91,41 @@ Route::prefix('admin')->name('admin.')->group(function () {
});
});
// ---------- tours ----------
Route::prefix('tours')->name('tours.')->controller(TourController::class)->group(function () {
Route::prefix('tours')
->name('tours.')
->controller(TourController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{tour}')->group(function () {
Route::get('show', 'show')->name('show');
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
Route::delete('destroy', 'destroy')->name('destroy');
// حذف تصویر تور
Route::delete('images/{image}', 'removeImage')->name('removeImage');
Route::delete('images/{image}', 'removeImage')
->name('removeImage');
});
});
// ---------- travel types (نوع سفر) ----------
Route::prefix('travel-types')->name('travelTypes.')->controller(TravelTypeController::class)->group(function () {
// ---------- travel types ----------
Route::prefix('travel-types')
->name('travelTypes.')
->controller(TravelTypeController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{travelType}')->group(function () {
Route::get('show', 'show')->name('show');
Route::get('edit', 'edit')->name('edit');
@@ -94,11 +134,18 @@ Route::prefix('admin')->name('admin.')->group(function () {
});
});
// ---------- flights ----------
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('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{flight}')->group(function () {
Route::get('show', 'show')->name('show');
Route::get('edit', 'edit')->name('edit');
@@ -109,10 +156,16 @@ Route::prefix('admin')->name('admin.')->group(function () {
// ---------- airports ----------
Route::prefix('airports')->name('airports.')->controller(AirportController::class)->group(function () {
Route::prefix('airports')
->name('airports.')
->controller(AirportController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{airport}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
@@ -120,45 +173,86 @@ Route::prefix('admin')->name('admin.')->group(function () {
});
});
// ---------- comments ----------
Route::prefix('comments')->name('comments.')->controller(CommentController::class)->group(function () {
// ---------- provinces and cities ----------
Route::prefix('locations')->name('locations.')->group(function () {
// مدیریت استان‌ها
Route::prefix('provinces')
->name('provinces.')
->controller(ProvinceController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::prefix('{comment}')->group(function () {
Route::get('show', 'show')->name('show');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::prefix('{province}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::patch('update', 'update')->name('update'); // تأیید/رد نظر
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('{city}')->group(function () {
Route::get('edit', 'edit')->name('edit');
Route::put('update', 'update')->name('update');
Route::delete('destroy', 'destroy')->name('destroy');
});
});
});
// ---------- comments ----------
Route::prefix('comments')
->name('comments.')
->controller(CommentController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::prefix('{comment}')->group(function () {
Route::get('show', 'show')->name('show');
Route::get('edit', 'edit')->name('edit');
Route::patch('update', 'update')->name('update');
Route::delete('destroy', 'destroy')->name('destroy');
});
});
// ---------- favorites ----------
Route::prefix('favorites')->name('favorites.')->controller(FavoriteController::class)->group(function () {
Route::prefix('favorites')
->name('favorites.')
->controller(FavoriteController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('{favorite}', 'show')->name('show');
Route::delete('{favorite}/destroy', 'destroy')->name('destroy');
});
// ---------- payments ----------
Route::prefix('payments')->name('payments.')->controller(PaymentController::class)->group(function () {
Route::get('/', 'index')->name('index');
Route::get('{payment}', 'show')->name('show');
});
// ---------- sliders ----------
// Route::prefix('sliders')->name('sliders.')->controller(SliderController::class)->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('create', 'create')->name('create');
// Route::post('store', 'store')->name('store');
// Route::prefix('{slider}')->group(function () {
// Route::get('show', 'show')->name('show');
// Route::get('edit', 'edit')->name('edit');
// Route::put('update', 'update')->name('update');
// Route::delete('destroy', 'destroy')->name('destroy');
// });
// });
// ---------- settings ----------
Route::prefix('settings')->name('settings.')->controller(SettingController::class)->group(function () {
Route::prefix('settings')
->name('settings.')
->controller(SettingController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::put('update', 'update')->name('update');
});
+23 -3
View File
@@ -8,21 +8,41 @@ use Illuminate\Support\Facades\Route;
Route::prefix('auth')->name('auth.')->group(function () {
//Guest
Route::middleware('guest:web')->group(function () {
// Register
Route::controller(RegisterController::class)
->prefix('register')->name('register.')->group(function () {
->prefix('register')
->name('register.')
->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'post')->name('post');
// دریافت شهرستان‌های یک استان
Route::get('provinces/{province}/cities', 'cities')
->name('provinces.cities');
});
// Login
Route::controller(LoginController::class)
->prefix('login')->name('login.')->group(function () {
->prefix('login')
->name('login.')
->group(function () {
Route::get('/', 'index')->name('index');
Route::post('/', 'post')->name('post');
});
});
// Logout
Route::get('logout', [LogoutController::class, 'index'])
->middleware('auth:web')->name('logout');
->middleware('auth:web')
->name('logout');
});
+44 -247
View File
@@ -1,292 +1,89 @@
<?php
use App\Http\Controllers\Account\BookingController;
use App\Http\Controllers\Account\CommentController as AccountCommentController;
use App\Http\Controllers\Account\EditProfileController;
use App\Http\Controllers\Account\FavoriteController;
use App\Http\Controllers\Account\HomeController;
use App\Http\Controllers\Account\FavoriteController as AccountFavoriteController;
use App\Http\Controllers\BookingController as SiteBookingController;
//use App\Http\Controllers\CommentController;
use App\Http\Controllers\CommentController;
use App\Http\Controllers\FavoriteController;
use App\Http\Controllers\FlightController;
use App\Http\Controllers\IndexController;
use App\Http\Controllers\PageController;
use App\Http\Controllers\TourController;
use Illuminate\Support\Facades\Route;
//use App\Http\Controllers\BookingController;
//use App\Http\Controllers\CommentController;
//use App\Http\Controllers\EditProfileController;
//use App\Http\Controllers\FavoriteController;
//use App\Http\Controllers\HomeController;
//use App\Http\Controllers\BookingController as SiteBookingController;
//use App\Http\Controllers\FlightController;
//use App\Http\Controllers\IndexController;
//use App\Http\Controllers\PageController;
//use App\Http\Controllers\TourController;
//use Illuminate\Support\Facades\Route;
// ------------------------------ index ------------------------------
// ------------------------------ صفحه اصلی ------------------------------
Route::get('/', [IndexController::class, 'index'])->name('index');
// ------------------------------ tours (مثل products) ------------------------------
Route::prefix('tours')->name('tours.')->controller(TourController::class)
// ------------------------------ تورها ------------------------------
Route::prefix('tours')
->name('tours.')
->controller(TourController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('remove-filters', 'removeFilters')->name('remove-filters');
Route::get('search/suggestion', 'searchSuggestion')->name('searchSuggestion'); // قبل از {tour}
Route::get('search/suggestion', 'searchSuggestion')->name('searchSuggestion');
Route::get('{tour}', 'show')->name('show');
});
// ------------------------------ flights ------------------------------
Route::prefix('flights')->name('flights.')->controller(FlightController::class)
// ------------------------------ پروازها ------------------------------
Route::prefix('flights')
->name('flights.')
->controller(FlightController::class)
->group(function () {
Route::get('/', 'index')->name('index');
Route::get('search', 'search')->name('search');
Route::get('{flight}', 'show')->name('show');
});
// ------------------------------ نظرات (مهمان یا عضو) ------------------------------
//Route::post('tours/{tour}/comments', [CommentController::class, 'store'])
// ->middleware('auth')->name('comments.store');
// ------------------------------ علاقه‌مندی‌ها ------------------------------
Route::prefix('favorites')->name('favorites.')
->middleware('auth')->controller(FavoriteController::class)
// ------------------------------ نظرات (پلی‌مورفیک) ------------------------------
Route::prefix('comments')
->name('comments.')
->middleware('auth')
->controller(AccountCommentController::class) // اصلاح شد: استفاده از کنترلر صحیح
->group(function () {
Route::get('/', 'index')->name('index');
Route::post('toggle', 'toggle')->name('toggle'); // افزودن/حذف با ajax
Route::get('clear', 'clear')->name('clear');
Route::post('tour/{tour}', 'storeTour')->name('tour.store');
Route::post('flight/{flight}', 'storeFlight')->name('flight.store');
});
// ------------------------------ رزرو (مرحله اول: بدون پرداخت) ------------------------------
// ------------------------------ علاقه‌مندی‌ها (عمومی) ------------------------------
Route::prefix('favorites')->name('favorites.')->middleware('auth')->controller(FavoriteController::class)->group(function () {
Route::post('toggle', 'toggle')->name('toggle');
});
// ------------------------------ رزرو ------------------------------
Route::prefix('booking')
->name('booking.')
->middleware('auth')
->controller(SiteBookingController::class)
->group(function () {
// صفحه رزرو
Route::get('/', 'index')->name('index');
// رزرو تور
Route::post('tours/{tour}', 'store')
->name('store');
// صفحه فرم رزرو پرواز
Route::get('flights/{flight}', 'flight')
->name('flight');
// ثبت نهایی رزرو پرواز
Route::post('flights/{flight}', 'storeFlight')
->name('flight.store');
Route::post('tours/{tour}', 'store')->name('store');
Route::get('flights/{flight}', 'flight')->name('flight');
Route::post('flights/{flight}', 'storeFlight')->name('flight.store');
});
// ------------------------------ پنل شخصی کاربر ------------------------------
Route::prefix('account')->name('account.')
// ------------------------------ پنل کاربری ------------------------------
Route::prefix('account')
->name('account.')
->middleware('auth')
->group(function () {
Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
Route::get('/', [IndexController::class, 'index'])->name('index');
Route::controller(BookingController::class)->group(function () {
Route::get('bookings', 'index')->name('bookings'); // رزروها
});
// علاقه‌مندی‌ها
Route::get('favorites', [AccountFavoriteController::class, 'index'])->name('favorites');
Route::controller(FavoriteController::class)->group(function () {
Route::get('favorites', 'index')->name('favorites');
});
// نظرات
Route::get('comments', [AccountCommentController::class, 'myComments'])->name('comments');
// Route::controller(CommentController::class)->group(function () {
// Route::get('comments', 'index')->name('comments');
// });
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::post('/', 'post')->name('post');
});
});
// ------------------------------ صفحات ثابت ------------------------------
Route::get('/about', [PageController::class, 'about'])->name('about');
Route::get('/contact', [PageController::class, 'contact'])->name('contact');
Route::get('/faq', [PageController::class, 'faq'])->name('faq');
//
//
//use App\Http\Controllers\Account\BookingController as AccountBookingController;
//use App\Http\Controllers\Account\EditProfileController;
//use App\Http\Controllers\Account\FavoriteController as AccountFavoriteController;
//use App\Http\Controllers\Account\HomeController;
//use App\Http\Controllers\Account\CommentController as AccountCommentController;
//use App\Http\Controllers\BookingController as SiteBookingController;
//use App\Http\Controllers\CommentController;
//use App\Http\Controllers\FavoriteController as SiteFavoriteController;
//use App\Http\Controllers\FlightController;
//use App\Http\Controllers\IndexController;
//use App\Http\Controllers\PageController;
//use App\Http\Controllers\TourController;
//use Illuminate\Support\Facades\Route;
//
//// ------------------------------ index ------------------------------
//Route::get('/', [IndexController::class, 'index'])->name('index');
//
//// ------------------------------ json-suggestion-search (جستجوی پیشنهادی تورها) ------------------------------
//// قبل از گروه tours تعریف شد تا با روت {tour} تداخل پیدا نکند
//Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'])
// ->name('tours.searchSuggestion');
//
//// ------------------------------ tours ------------------------------
//Route::prefix('tours')
// ->name('tours.')
// ->controller(TourController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('remove-filters', 'removeFilters')->name('remove-filters');
// Route::get('{tour}', 'show')->name('show');
// });
//
//// ------------------------------ flights ------------------------------
//Route::prefix('flights')
// ->name('flights.')
// ->controller(FlightController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('search', 'search')->name('search');
// Route::get('{flight}', 'show')->name('show');
// });
//
//// ------------------------------ نظرات (فقط کاربر واردشده) ------------------------------
//Route::post('tours/{tour}/comments', [CommentController::class, 'store'])
// ->middleware('auth')
// ->name('comments.store');
//
//// ------------------------------ علاقهمندیها ------------------------------
//Route::prefix('favorites')
// ->name('favorites.')
// ->middleware('auth')
// ->controller(SiteFavoriteController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('toggle', 'toggle')->name('toggle'); // افزودن/حذف با ajax
// Route::get('clear', 'clear')->name('clear');
// });
//
//// ------------------------------ رزرو (بدون پرداخت) ------------------------------
//Route::prefix('booking')
// ->name('booking.')
// ->middleware('auth')
// ->controller(SiteBookingController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index'); // فرم رزرو تور
// Route::post('tours/{tour}', 'store')->name('store'); // ثبت رزرو
// });
//
//// ------------------------------ پنل شخصی کاربر ------------------------------
//Route::prefix('account')
// ->name('account.')
// ->middleware('auth')
// ->group(function () {
//
// Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
//
// Route::get('bookings', [AccountBookingController::class, 'index'])->name('bookings');
// Route::get('favorites', [AccountFavoriteController::class, 'index'])->name('favorites');
// Route::get('comments', [AccountCommentController::class, 'index'])->name('comments');
//
// Route::prefix('edit-profile')
// ->name('edit-profile.')
// ->controller(EditProfileController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('/', 'post')->name('post');
// });
// });
//
//// ------------------------------ صفحات ثابت ------------------------------
//Route::get('/about', [PageController::class, 'about'])->name('about');
//Route::get('/contact', [PageController::class, 'contact'])->name('contact');
//Route::get('/faq', [PageController::class, 'faq'])->name('faq');
//
//
////use App\Http\Controllers\Account\EditProfileController;
////use App\Http\Controllers\Account\BookingController;
////use App\Http\Controllers\Account\FavoriteController;
////use App\Http\Controllers\BookingController as SiteBookingController;
////use App\Http\Controllers\CommentController;
////use App\Http\Controllers\FavoriteController as SiteFavoriteController;
////use App\Http\Controllers\FlightController;
//use App\Http\Controllers\IndexController;
////use App\Http\Controllers\PageController;
////use App\Http\Controllers\PaymentController;
//use App\Http\Controllers\TourController;
//use Illuminate\Support\Facades\Route;
//
//// ------------------------------ index ------------------------------
//Route::get('/', [IndexController::class, 'index'])->name('index');
//
//// ------------------------------ tours (مثل products) ------------------------------
//Route::prefix('tours')->name('tours.')->controller(TourController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('remove-filters', 'removeFilters')->name('remove-filters');
// Route::get('{tour}', 'show')->name('show');
// });
//
//// json-suggestion-search (جستجوی پیشنهادی تورها)
//Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'])
// ->name('tours.searchSuggestion');
//
//// ------------------------------ flights ------------------------------
//Route::prefix('flights')->name('flights.')->controller(FlightController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('search', 'search')->name('search');
// Route::get('{flight}', 'show')->name('show');
// });
//
//// ------------------------------ نظرات (مهمان یا عضو) ------------------------------
//Route::post('tours/{tour}/comments', [CommentController::class, 'store'])
// ->middleware('auth')->name('comments.store');
//
//// ------------------------------ علاقه‌مندی‌ها ------------------------------
//Route::prefix('favorites')->name('favorites.')
// ->middleware('auth')->controller(SiteFavoriteController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('toggle', 'toggle')->name('toggle'); // افزودن/حذف با ajax
// Route::get('clear', 'clear')->name('clear');
// });
//
//// ------------------------------ رزرو و پرداخت ------------------------------
//Route::prefix('booking')->name('booking.')
// ->middleware('auth')->controller(SiteBookingController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index'); // فرم رزرو تور
// Route::post('tours/{tour}', 'store')->name('store'); // ثبت رزرو
// });
//
//Route::get('payment/{booking}/pay', [PaymentController::class, 'pay'])
// ->middleware('auth')->name('payment.pay');
//
//// ------------------------------ پنل شخصی کاربر ------------------------------
//Route::prefix('account')->name('account.')->middleware('auth')->group(function () {
//
// Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
// Route::get('bookings', [BookingController::class, 'index'])->name('bookings'); // رزروها
// Route::get('favorites', [FavoriteController::class, 'index'])->name('favorites');
// Route::get('comments', [CommentController::class, 'index'])->name('comments');
//
// Route::prefix('edit-profile')->name('edit-profile.')
// ->controller(EditProfileController::class)->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('/', 'post')->name('post');
// });
//});
//
//// ------------------------------ صفحات ثابت ------------------------------
//Route::get('/about', [PageController::class, 'about'])->name('about');
//Route::get('/contact', [PageController::class, 'contact'])->name('contact');
//Route::get('/faq', [PageController::class, 'faq'])->name('faq');