Compare commits

...

21 Commits

Author SHA1 Message Date
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
39 changed files with 4095 additions and 2576 deletions
@@ -0,0 +1,37 @@
<?php
namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller;
use App\Http\Requests\EditProfilePostRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class EditProfileController extends Controller
{
public function index()
{
$user = Auth::user();
return view('account.edit-profile.index', compact('user'));
}
public function post(EditProfilePostRequest $request)
{
$user = Auth::user();
$user->name = $request['name'];
$user->username = $request['username'];
$user->email = $request['email'];
if ($request->filled('password')) {
$user->password = Hash::make($request['password']);
}
$user->save();
return redirect()
->route('account.edit-profile.index')
->with('success', 'اطلاعات پروفایل با موفقیت ویرایش شد.');
}
}
@@ -0,0 +1,76 @@
<?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'));
}
/**
* افزودن/حذف به صورت toggle (اگر موجود بود حذف کن، اگر نبود بساز).
* این متد با پلیمورفیک بودن Favorite از هر دو مدل تور و پرواز پشتیبانی میکنه.
*/
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'];
// بررسی اینکه مدل درخواستی واقعاً وجود داره (مثلاً Tour یا Flight)
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,11 +8,8 @@ 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
{
@@ -26,9 +24,13 @@ class RegisterController extends Controller
}
/**
* ثبت نام کاربر
*/
public function post(RegisterPostRequest $request)
{
// $data = $request->validated();
$imagePath = null;
@@ -42,65 +44,59 @@ 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);
}
+20 -163
View File
@@ -9,44 +9,41 @@ 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') . '%'
);
}
@@ -65,18 +62,17 @@ 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 +80,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 +95,7 @@ class FlightController extends Controller
$query->where(
'flight_number',
'like',
'%' . $request->flight_number . '%'
'%' . $request->input('flight_number') . '%'
);
}
@@ -117,155 +113,16 @@ class FlightController extends Controller
*/
public function show(Flight $flight)
{
/*
|--------------------------------------------------------------------------
| فعلاً isActive را حذف کردیم
|--------------------------------------------------------------------------
| چون اگر متد isActive در مدل اشتباه باشد یا status متفاوت باشد
| باعث 404 شدن صفحه می‌شود.
*/
// // فقط پرواز فعال قابل مشاهده باشد
// if (!$flight->isActive()) {
// abort(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')
// );
// }
//}
+6 -3
View File
@@ -11,14 +11,17 @@ class IndexController extends Controller
{
$tours = Tour::query()
->where('status', 1)
->latest()
->orderByDesc('created_at')
->paginate(6, ['*'], 'tours_page');
$flights = Flight::query()
->where('status', 1)
->latest()
->orderByDesc('created_at')
->paginate(6, ['*'], 'flights_page');
return view('index', compact('tours', 'flights'));
return view('index', [
'tours' => $tours,
'flights' => $flights,
]);
}
}
+12 -1
View File
@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Models\Favorite;
use App\Models\Tour;
use App\Models\TravelType;
use Illuminate\Http\Request;
@@ -113,9 +114,19 @@ class TourController extends Controller
->limit(4)
->get();
$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')
compact('tour', 'relatedTours', 'isFav')
);
}
+20 -13
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,8 +64,11 @@ class AdminController extends Controller
);
}
public function update(AdminUpdateRequest $request, Admin $admin)
{
public function update(
AdminUpdateRequest $request,
Admin $admin
) {
$data = $request->validated();
$permissions = $data['permissions'] ?? [];
@@ -76,9 +76,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,9 +93,10 @@ class AdminController extends Controller
return redirect()
->route('admin.admins.index')
->with('success', 'اطلاعات مدیر با موفقیت ویرایش شد.');
->with('success', 'مدیر با موفقیت ویرایش شد.');
}
public function destroy(Admin $admin)
{
$admin->permissions()->detach();
+193 -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,37 @@ 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 +52,238 @@ class TourController extends Controller
try {
$data = $request->validated();
// ساخت slug اگر خالی بود
// ساخت slug در صورت خالی بودن
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
/*
* وضعیت تور
*
* 1 = در انتظار
* 2 = تایید شده
*
* اگر می‌خواهی تور بلافاصله در لیست نمایش داده شود،
* مقدار 2 قرار می‌دهیم.
*/
$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']);
}
/*
* اگر status از فرم ارسال نشده باشد،
* وضعیت فعلی تور حفظ شود.
*/
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' =>
'حذف تور با خطا مواجه شد.'
]);
}
}
}
+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' => [
+11 -6
View File
@@ -27,22 +27,26 @@ class RegisterPostRequest extends FormRequest
'first_name' => [
'required',
'persian_alpha',
'string',
'min:3',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'last_name' => [
'required',
'persian_alpha',
'string',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'national_code' => [
'required',
// 'ir_national_id',
'digits:10',
'unique:users,national_code',
],
@@ -67,14 +71,15 @@ class RegisterPostRequest extends FormRequest
'string',
'max:200',
'required_if:marital_status,2',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'mobile' => [
'required',
'digits:11',
'regex:/^09\d{9}$/',
'ir_mobile:zero',
// 'regex:/^09\d{9}$/',
'unique:users,mobile',
],
@@ -89,10 +94,11 @@ class RegisterPostRequest extends FormRequest
'username' => [
'required',
'persian_not_accept',
'string',
'min:3',
'max:50',
'regex:/^[A-Za-z0-9]+$/',
// 'regex:/^[A-Za-z0-9]+$/',
'unique:users,username',
],
@@ -125,7 +131,6 @@ class RegisterPostRequest extends FormRequest
],
];
}
}
@@ -0,0 +1,57 @@
<?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
{
return [
'name' =>
[
'required',
'string',
'max:255'
],
'username' =>
[
'required',
'string',
'max:255',
'unique:users,username,' . $user->id,
],
'email' => [
'required',
'email',
'max:255',
'unique:users,email,' . $user->id,
],
'password' =>
[
'nullable',
'string',
'min:8',
'confirmed'
],
];
}
}
+99 -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;
@@ -91,3 +86,96 @@ class Admin extends User
return $this->status == 1;
}
}
//
///**
// * Created by Reliese Model.
// */
//
//namespace App\Models;
//
//use App\Enums\AdminStatus;
//use Carbon\Carbon;
//use Illuminate\Auth\Middleware\Authenticate;
//use Illuminate\Database\Eloquent\Factories\HasFactory;
//use Illuminate\Database\Eloquent\Model;
//
////use Illuminate\Foundation\Auth\Admin as User;
////use Illuminate\Foundation\Auth\Admin as Authenticate;
//
//
///**
// * Class Admin
// *
// * @property int $id
// * @property string $full_name
// * @property string $username
// * @property string $email
// * @property string $mobile
// * @property string $password
// * @property int $status
// * @property Carbon $created_at
// * @property Carbon $updated_at
// *
// * @package App\Models
// */
//class Admin extends Authenticate
//{
// protected $table = 'admins';
//
// public static $snakeAttributes = false;
//
// protected $casts = [
// 'status' => 'int',
// ];
//
// protected $hidden = [
// 'password',
// ];
//
// protected $fillable = [
// 'full_name',
// 'username',
// 'email',
// 'mobile',
// 'password',
// 'status',
// ];
//
// public function permissions()
// {
// return $this->belongsToMany(
// Permission::class,
// 'admin_permission',
// 'admin_id',
// 'permission_id'
// );
// }
//
//
// /**
// * بررسی دسترسی مدیر به ماژول مدیریت کاربران
// *
// * @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;
// }
//
// public function canManageFlights(string $action): bool
// {
// return $this->status == 1;
// }
//
// public function canManageTours(string $action): bool
// {
// return $this->status == 1;
// }
//}
+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();
// }
//}
+12
View File
@@ -75,4 +75,16 @@ class Tour extends Model
->withPivot('id')
->withTimestamps();
}
protected static function booted()
{
static::creating(function ($tour) {
// اگر مقداری تعیین نشده بود، پیش‌فرض‌ها را اعمال کن
if (is_null($tour->views_count)) {
$tour->views_count = 0;
}
if (is_null($tour->status)) {
$tour->status = 0; // فرض بر اینکه 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 */;
+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;
}
}
+53 -3
View File
@@ -1,3 +1,53 @@
<div>
<!-- Very little is needed to make a happy life. - Marcus Aurelius -->
</div>
@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">
<a href="{{route('tours.index')}}" class="btn btn-sm btn-primary">مشاهده</a>
<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 class="btn btn-sm btn-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
+119 -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>
@@ -364,6 +345,99 @@
</div>
{{-- <div class="col-xl-4">--}}
{{-- <div class="card custom-card">--}}
{{-- <div class="card-header">--}}
{{-- <div>--}}
{{-- <div class="card-title mb-1">--}}
{{-- سطح دسترسی--}}
{{-- </div>--}}
{{-- <small class="text-muted">--}}
{{-- دسترسی‌های مدیر را مدیریت کنید.--}}
{{-- </small>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="card-body">--}}
{{-- @php--}}
{{-- $selectedPermissions = old(--}}
{{-- 'permissions',--}}
{{-- $admin->permissions->pluck('id')->toArray()--}}
{{-- );--}}
{{-- @endphp--}}
{{-- @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"--}}
{{-- type="checkbox"--}}
{{-- name="permissions[]"--}}
{{-- value="{{ $permission->id }}"--}}
{{-- id="permission_{{ $permission->id }}"--}}
{{-- @checked(in_array(--}}
{{-- $permission->id,--}}
{{-- $selectedPermissions--}}
{{-- ))>--}}
{{-- <label class="form-check-label"--}}
{{-- for="permission_{{ $permission->id }}">--}}
{{-- <span class="fw-semibold">--}}
{{-- {{ $permission->name }}--}}
{{-- </span>--}}
{{-- @if($permission->description)--}}
{{-- <small class="text-muted d-block mt-1">--}}
{{-- {{ $permission->description }}--}}
{{-- </small>--}}
{{-- @endif--}}
{{-- </label>--}}
{{-- </div>--}}
{{-- @empty--}}
{{-- <div class="text-center text-muted py-4">--}}
{{-- <i class="ri-shield-keyhole-line fs-2 d-block mb-2"></i>--}}
{{-- هنوز دسترسی‌ای تعریف نشده است.--}}
{{-- </div>--}}
{{-- @endforelse--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
</div>
@@ -380,17 +454,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>
+31 -6
View File
@@ -101,13 +101,38 @@
</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>
{{-- <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>--}}
{{-- وضعیت --}}
<td>
+381 -39
View File
@@ -1,61 +1,403 @@
@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>
{{-- ============================= --}}
{{-- Pagination --}}
{{-- ============================= --}}
@if($tours->hasPages())
<div class="card-footer">
<div class="d-flex justify-content-center">
{{ $tours->links() }}
</div>
</div>
@endif
</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
+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>
+65 -14
View File
@@ -1,19 +1,70 @@
@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 }}">
</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
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="banner-caption _pt-120 banner-caption-bottom banner-caption-grad">
<h5 class="banner-title">
{{ $tour->title }}
</h5>
</div>
</div>
{{--<div class="banner _h-33vh _br-3 banner-animate banner-animate-mask-in">--}}
{{-- <div--}}
{{-- class="banner-bg"--}}
{{-- style="background-image:url('{{ asset($image) }}');">--}}
{{-- </div>--}}
{{-- <div class="banner-mask"></div>--}}
{{-- <a--}}
{{-- class="banner-link"--}}
{{-- href="#">--}}
{{-- </a>--}}
{{-- <div class="banner-caption _pt-120 banner-caption-bottom banner-caption-grad">--}}
{{-- <h5 class="banner-title">--}}
{{-- {{ $title }}--}}
{{-- </h5>--}}
{{-- <p class="banner-subtitle">--}}
{{-- {{ $country }}--}}
{{-- </p>--}}
{{-- </div>--}}
{{--</div>--}}
{{--@props(['tour'])--}}
{{--<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 }}">--}}
{{-- </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>--}}
+273
View File
@@ -0,0 +1,273 @@
<div class="col-md-4 col-sm-6">
<div class="theme-search-results-item">
<div class="theme-search-results-item-header">
<div>
<strong>
{{ $flight->airline_name }}
</strong>
</div>
<div>
<strong>
{{ $flight->flight_number }}
</strong>
</div>
</div>
<div class="theme-search-results-item-body">
{{-- مسیر پرواز --}}
<div class="text-center">
<div>
<strong>
{{ $flight->origin }}
</strong>
<span>
→
</span>
<strong>
{{ $flight->destination }}
</strong>
</div>
</div>
<hr>
{{-- ساعت پرواز --}}
<div class="row">
<div class="col-xs-6 text-center">
<small>
حرکت
</small>
<div>
<strong>
{{ $flight->departure_time }}
</strong>
</div>
</div>
<div class="col-xs-6 text-center">
<small>
رسیدن
</small>
<div>
<strong>
{{ $flight->arrival_time }}
</strong>
</div>
</div>
</div>
<hr>
{{-- مدت --}}
<div class="text-center">
<small>
مدت پرواز
</small>
<div>
{{ $flight->duration }}
</div>
</div>
<hr>
{{-- قیمت --}}
<div class="text-center">
<small>
قیمت
</small>
<div>
<strong>
{{ number_format($flight->price) }}
</strong>
تومان
</div>
</div>
<div style="margin-top: 15px;">
<a
href="{{ route('flights.show', ['flight' => $flight->id]) }}"
class="btn btn-primary btn-block"
>
مشاهده جزئیات
</a>
</div>
</div>
</div>
</div>
{{--@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>--}}
{{-- <p>--}}
{{-- پرواز مورد نظر خود را انتخاب کنید.--}}
{{-- </p>--}}
{{-- </div>--}}
{{-- --}}{{-- Search --}}
{{-- <div class="theme-search-area theme-search-area-stacked theme-search-area-white">--}}
{{-- <div class="theme-search-area-form">--}}
{{-- <div class="row">--}}
{{-- <div class="col-md-3">--}}
{{-- <input--}}
{{-- class="form-control"--}}
{{-- type="text"--}}
{{-- placeholder="مبدا">--}}
{{-- </div>--}}
{{-- <div class="col-md-3">--}}
{{-- <input--}}
{{-- class="form-control"--}}
{{-- type="text"--}}
{{-- placeholder="مقصد">--}}
{{-- </div>--}}
{{-- <div class="col-md-2">--}}
{{-- <input--}}
{{-- class="form-control"--}}
{{-- type="text"--}}
{{-- placeholder="تاریخ">--}}
{{-- </div>--}}
{{-- <div class="col-md-2">--}}
{{-- <select class="form-control">--}}
{{-- <option>اقتصادی</option>--}}
{{-- <option>بیزینس</option>--}}
{{-- <option>فرست کلاس</option>--}}
{{-- </select>--}}
{{-- </div>--}}
{{-- <div class="col-md-2">--}}
{{-- <button class="btn btn-primary btn-block">--}}
{{-- جستجو--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- --}}
{{-- --}}{{-- Flights --}}
{{-- <div class="row row-col-gap">--}}
{{-- @forelse($flights as $flight)--}}
{{-- @include('components.flight', [--}}
{{-- 'flight' => $flight--}}
{{-- ])--}}
{{-- @empty--}}
{{-- <div class="col-12">--}}
{{-- <div class="alert alert-info text-center">--}}
{{-- در حال حاضر پرواز فعالی برای نمایش وجود ندارد.--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- @endforelse--}}
{{-- </div>--}}
{{-- <div class="row row-col-gap">--}}
{{-- @include('components.flight', [--}}
{{-- 'airline' => 'ایران ایر',--}}
{{-- 'from' => 'تهران',--}}
{{-- 'to' => 'استانبول',--}}
{{-- 'departure' => '09:30',--}}
{{-- 'arrival' => '12:00',--}}
{{-- 'price' => '25,000,000'--}}
{{-- ])--}}
{{-- @include('components.flight', [--}}
{{-- 'airline' => 'ماهان',--}}
{{-- 'from' => 'تهران',--}}
{{-- 'to' => 'دبی',--}}
{{-- 'departure' => '14:00',--}}
{{-- 'arrival' => '17:00',--}}
{{-- 'price' => '18,500,000'--}}
{{-- ])--}}
{{-- @include('components.flight', [--}}
{{-- 'airline' => 'ترکیش ایرلاینز',--}}
{{-- 'from' => 'تهران',--}}
{{-- 'to' => 'استانبول',--}}
{{-- 'departure' => '20:30',--}}
{{-- 'arrival' => '23:30',--}}
{{-- 'price' => '22,000,000'--}}
{{-- ])--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
+207 -3
View File
@@ -1,3 +1,207 @@
<div>
<!-- Simplicity is an acquired taste. - Katharine Gerould -->
</div>
@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
{{--@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>--}}
{{-- تهران → استانبول--}}
{{-- </h3>--}}
{{-- <hr>--}}
{{-- <p>--}}
{{-- شرکت هواپیمایی: ایران ایر--}}
{{-- </p>--}}
{{-- <p>--}}
{{-- تاریخ: 1405/05/30--}}
{{-- </p>--}}
{{-- <p>--}}
{{-- ساعت حرکت: 09:30--}}
{{-- </p>--}}
{{-- <p>--}}
{{-- ساعت رسیدن: 12:00--}}
{{-- </p>--}}
{{-- <p>--}}
{{-- مدت پرواز: 3 ساعت و 30 دقیقه--}}
{{-- </p>--}}
{{-- <p>--}}
{{-- کلاس: اقتصادی--}}
{{-- </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>--}}
{{-- 25,000,000 تومان--}}
{{-- </h2>--}}
{{-- <a--}}
{{-- href="{{ route('booking.flight', $flight) }}"--}}
{{-- class="btn btn-primary"--}}
{{-- >--}}
{{-- رزرو پرواز--}}
{{-- </a>--}}
{{-- <button class="btn btn-primary btn-block">--}}
{{-- رزرو پرواز--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
File diff suppressed because it is too large Load Diff
+2
View File
@@ -17,6 +17,8 @@
<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/plugins/bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/auth.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">
+224 -30
View File
@@ -107,52 +107,191 @@
</nav>
{{-- @auth--}}
{{-- <!-- Account Btn -->--}}
{{-- <button class="group relative flex-center py-2 px-4 app-border rounded-full app-hover delay-75">--}}
{{-- <a href="{{ route('account.edit-profile.index') }}" class="flex items-center gap-x-1">--}}
{{-- <svg class="size-5">--}}
{{-- <use href="#user"/>--}}
{{-- </svg>--}}
{{-- <p>حساب کاربری</p>--}}
{{-- </a>--}}
{{-- <div--}}
{{-- class="absolute dark:border-none border border-gray-100 w-52 p-2 bg-white text-gray-900 dark:text-gray-100 flex flex-col gap-y-3 opacity-0 invisible group-hover:opacity-100 group-hover:visible group-hover:top-12 transition-all delay-100 dark:bg-gray-700 top-20 rounded-lg text-base shadow child:transition-all duration-300 child:py-1.5 child:px-2 z-30 child:rounded-lg child:w-full">--}}
{{-- <a href="{{ route('account.orders')}}"--}}
{{-- class="flex items-center gap-x-2 hover:bg-blue-500 hover:text-gray-100">--}}
{{-- <svg class="h-5 w-5">--}}
{{-- <use href="#user"></use>--}}
{{-- </svg>--}}
{{-- سفارشات من--}}
{{-- </a>--}}
{{-- <a href="{{ route('account.edit-profile.index') }}"--}}
{{-- class="flex items-center gap-x-2 hover:bg-blue-500 hover:text-gray-100">--}}
{{-- <svg class="h-5 w-5">--}}
{{-- <use href="#cog"></use>--}}
{{-- </svg>--}}
{{-- اطلاعات کاربری--}}
{{-- </a>--}}
{{-- <a href="{{ route('auth.logout') }}"--}}
{{-- class="flex items-center gap-x-2 hover:bg-red-500 dark:hover:bg-red-500 hover:text-gray-100">--}}
{{-- <svg class="h-5 w-5">--}}
{{-- <use href="#arrow-left-end"></use>--}}
{{-- </svg>--}}
{{-- خروج از حساب--}}
{{-- </a>--}}
{{-- </div>--}}
{{-- </button>--}}
{{-- @else--}}
<!-- LOGIN -->
{{-- <button class="flex-center py-2 px-4 app-border rounded-full app-hover">--}}
{{-- <a href="{{route('auth.login.index')}}" class="flex items-center gap-x-2">--}}
{{-- <p>ورود | ثبت‌نام</p>--}}
{{-- <svg class="size-5">--}}
{{-- <use href="#arrow-left-end"/>--}}
{{-- </svg>--}}
{{-- </a>--}}
{{-- </button>--}}
{{-- @endauth--}}
{{-- =========================================
سمت چپ Navbar
========================================= --}}
{{-- سمت چپ --}}
<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>
{{-- نظرات قبلی --}}
{{-- فعلاً اگر route نظرات را ساخته‌ای فعالش کن --}}
@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 +303,82 @@
</button>
</div>
{{-- <div class="travel-navbar-actions">--}}
{{-- <div class="travel-navbar-actions">--}}
{{-- <a href="{{ route('auth') }}" class="travel-login">--}}
{{-- @auth()--}}
{{-- <i class="fa fa-user"></i>--}}
{{-- --}}{{----}}{{-- کاربر وارد نشده --}}
{{-- ورود / ثبت‌نام--}}
{{-- <a href="{{ route('auth.login.index') }}" class="travel-login">--}}
{{-- </a>--}}
{{-- <i class="fa fa-sign-in"></i>--}}
{{-- ورود--}}
{{-- </a>--}}
{{-- <a href="{{ route('auth.register.index') }}" class="travel-register">--}}
{{-- <i class="fa fa-user-plus"></i>--}}
{{-- ثبت‌نام--}}
{{-- </a>--}}
{{-- @else--}}
{{-- --}}{{-- کاربر وارد شده --}}
{{-- <a href="{{ route('account.index') }}" class="travel-login">--}}
{{-- <i class="fa fa-user"></i>--}}
{{-- حساب کاربری--}}
{{-- </a>--}}
{{-- <a href="{{ route('auth.logout') }}" class="travel-logout">--}}
{{-- <i class="fa fa-sign-out"></i>--}}
{{-- خروج--}}
{{-- </a>--}}
{{-- @endguest--}}
{{-- <button--}}
{{-- type="button"--}}
{{-- class="travel-mobile-toggle"--}}
{{-- aria-label="منو">--}}
{{-- <button--}}
{{-- type="button"--}}
{{-- class="travel-mobile-toggle"--}}
{{-- aria-label="منو">--}}
{{-- <i class="fa fa-bars"></i>--}}
{{-- <i class="fa fa-bars"></i>--}}
{{-- </button>--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- </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>
+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>
+77 -1
View File
@@ -3,11 +3,65 @@
@section('title', 'لیست تورها')
@section('content')
{{-- استایل دکمه علاقهمندی (مناسب برای کارتها) --}}
<style>
.travel-favorite-form {
position: absolute;
top: 10px;
left: 10px;
z-index: 3;
margin: 0;
}
.travel-favorite-btn {
width: 42px;
height: 42px;
border-radius: 50%;
border: 1px solid #e0245e;
background: rgba(255, 255, 255, .95);
color: #e0245e;
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
transition: all .2s ease;
}
.travel-favorite-btn:hover,
.travel-favorite-btn.active {
background: #e0245e;
color: #fff;
}
</style>
<h1>تورهای ما</h1>
<div class="row">
@forelse($tours as $tour)
<div class="col-md-4">
@php
$isFavTour = in_array($tour->id, $favoriteTourIds ?? []);
@endphp
<div class="col-md-4 position-relative">
<x-tour :tour="$tour"/>
{{-- دکمه علاقهمندی --}}
@auth
<form action="{{ route('favorites.toggle') }}" method="POST" class="travel-favorite-form">
@csrf
<input type="hidden" name="favoritable_type" value="{{ \App\Models\Tour::class }}">
<input type="hidden" name="favoritable_id" value="{{ $tour->id }}">
<button type="submit" class="travel-favorite-btn {{ $isFavTour ? 'active' : '' }}">
<i class="fa {{ $isFavTour ? 'fa-heart' : 'far fa-heart' }}"></i>
</button>
</form>
@else
<a href="{{ route('login') }}" class="travel-favorite-btn">
<i class="far fa-heart"></i>
</a>
@endauth
</div>
@empty
<p>تور فعالی یافت نشد.</p>
@@ -15,4 +69,26 @@
</div>
{{ $tours->links() }}
@endsection
{{--@extends('layouts.app')--}}
{{--@section('title', 'لیست تورها')--}}
{{--@section('content')--}}
{{-- <h1>تورهای ما</h1>--}}
{{-- <div class="row">--}}
{{-- @forelse($tours as $tour)--}}
{{-- <div class="col-md-4">--}}
{{-- <x-tour :tour="$tour"/>--}}
{{-- </div>--}}
{{-- @empty--}}
{{-- <p>تور فعالی یافت نشد.</p>--}}
{{-- @endforelse--}}
{{-- </div>--}}
{{-- {{ $tours->links() }}--}}
{{--@endsection--}}
+346 -6
View File
@@ -1,7 +1,31 @@
@extends('layouts.app')
@section('title', $tour->title)
@section('content')
<style>
.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: .9rem;
cursor: pointer;
transition: all .2s ease;
}
.travel-favorite-btn:hover,
.travel-favorite-btn.active {
background: #e0245e;
color: #fff;
}
</style>
<div class="tour-details-page">
<div class="container">
@@ -37,6 +61,25 @@
{{ $tour->title }}
</h1>
{{-- دکمه علاقهمندی --}}
@auth
<form action="{{ route('favorites.toggle') }}" method="POST" class="mb-3">
@csrf
<input type="hidden" name="favoritable_type" value="{{ \App\Models\Tour::class }}">
<input type="hidden" name="favoritable_id" value="{{ $tour->id }}">
<button type="submit" class="travel-favorite-btn {{ $isFav ? 'active' : '' }}">
<i class="fa {{ $isFav ? 'fa-heart' : 'far fa-heart' }}"></i>
<span>{{ $isFav ? 'در علاقهمندیها' : 'افزودن به علاقهمندی' }}</span>
</button>
</form>
@else
<a href="{{ route('login') }}" class="travel-favorite-btn">
<i class="far fa-heart"></i>
<span>افزودن به علاقهمندی</span>
</a>
@endauth
{{-- اطلاعات اصلی --}}
<div class="tour-details-info">
@@ -293,6 +336,303 @@
@endsection
{{--@extends('layouts.app')--}}
{{--@section('content')--}}
{{-- <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">--}}
{{-- تصویر برای این تور ثبت نشده است--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- </div>--}}
{{-- --}}{{-- محتوای تور --}}
{{-- <div class="tour-details-content">--}}
{{-- --}}{{-- عنوان --}}
{{-- <h1 class="tour-details-title">--}}
{{-- {{ $tour->title }}--}}
{{-- </h1>--}}
{{-- --}}{{-- اطلاعات اصلی --}}
{{-- <div class="tour-details-info">--}}
{{-- --}}{{-- نوع سفر --}}
{{-- <div class="tour-info-box">--}}
{{-- <span class="tour-info-label">--}}
{{-- نوع سفر--}}
{{-- </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>--}}
{{-- </div>--}}
{{-- </a>--}}
{{-- @endforeach--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- دکمه بازگشت --}}
{{-- <div class="tour-back">--}}
{{-- <a--}}
{{-- href="{{ route('tours.index') }}"--}}
{{-- class="tour-back-button"--}}
{{-- >--}}
{{-- بازگشت به لیست تورها--}}
{{-- </a>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}
{{-- resources/views/tours/show.blade.php --}}
{{--@extends('layouts.app')--}}
@@ -301,7 +641,7 @@
{{--@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>--}}
@@ -325,7 +665,7 @@
{{-- </div>--}}
{{-- </section>--}}
{{-- --}}{{-- ===== فرم رزرو تور ===== --}}
{{-- --}}{{----}}{{-- ===== فرم رزرو تور ===== --}}
{{-- @auth--}}
{{-- <section class="pb-5">--}}
{{-- <div class="container">--}}
@@ -351,7 +691,7 @@
{{-- </div>--}}
{{-- </section>--}}
{{-- @else--}}
{{-- --}}{{-- کاربر لاگین نیست => دکمه ورود به روت login --}}
{{-- --}}{{----}}{{-- کاربر لاگین نیست => دکمه ورود به روت login --}}
{{-- <div class="alert alert-warning text-center">--}}
{{-- برای رزرو تور ابتدا <a href="{{ route('login') }}">وارد شوید</a>.--}}
{{-- </div>--}}
@@ -365,7 +705,7 @@
{{--@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">--}}
@@ -377,13 +717,13 @@
{{-- <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"/>--}}
+62 -6
View File
@@ -8,8 +8,15 @@ 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.')
@@ -19,11 +26,13 @@ Route::prefix('auth')->name('auth.')->group(function () {
Route::post('/', 'post')->name('post');
Route::get('cities/{province}', 'cities')
->name('cities');
// دریافت شهرستان‌های یک استان
Route::get('provinces/{province}/cities', 'cities')
->name('provinces.cities');
});
// Login
Route::controller(LoginController::class)
->prefix('login')
->name('login.')
@@ -36,28 +45,75 @@ Route::prefix('auth')->name('auth.')->group(function () {
});
/*
|--------------------------------------------------------------------------
| Logout
|--------------------------------------------------------------------------
*/
Route::get('logout', [LogoutController::class, 'index'])
->middleware('auth:web')
->name('logout');
});
//
//
//use App\Http\Controllers\Auth\LoginController;
//use App\Http\Controllers\Auth\LogoutController;
//use App\Http\Controllers\Auth\RegisterController;
//use Illuminate\Support\Facades\Route;
//
//Route::prefix('auth')->name('auth.')->group(function () {
//
// Route::middleware('guest:web')->group(function () {
//
// 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('cities/{province}', 'cities')
// ->name('cities');
// });
//
//
// 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');
// });
// });
//
//
// Route::get('logout', [LogoutController::class, 'index'])
// ->middleware('auth:web')->name('logout');
// ->middleware('auth:web')
// ->name('logout');
//});
//
////Route::prefix('auth')->name('auth.')->group(function () {
////
//// Route::middleware('guest:web')->group(function () {
////
//// Route::controller(RegisterController::class)
//// ->prefix('register')->name('register.')->group(function () {
//// Route::get('/', 'index')->name('index');
//// Route::post('/', 'post')->name('post');
//// });
////
//// Route::controller(LoginController::class)
//// ->prefix('login')->name('login.')->group(function () {
//// Route::get('/', 'index')->name('index');
//// Route::post('/', 'post')->name('post');
//// });
//// });
////
//// Route::get('logout', [LogoutController::class, 'index'])
//// ->middleware('auth:web')->name('logout');
////});
+121 -36
View File
@@ -1,28 +1,15 @@
<?php
use App\Http\Controllers\Account\BookingController;
use App\Http\Controllers\Account\EditProfileController;
use App\Http\Controllers\Account\FavoriteController;
use App\Http\Controllers\Account\HomeController;
use App\Http\Controllers\BookingController as SiteBookingController;
//use App\Http\Controllers\CommentController;
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');
@@ -44,10 +31,6 @@ Route::prefix('flights')->name('flights.')->controller(FlightController::class)
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)
@@ -58,28 +41,19 @@ Route::prefix('favorites')->name('favorites.')
});
// ------------------------------ رزرو (مرحله اول: بدون پرداخت) ------------------------------
Route::prefix('booking')
->name('booking.')
->middleware('auth')
->controller(SiteBookingController::class)
->group(function () {
// صفحه رزرو
Route::get('/', 'index')->name('index');
Route::get('/', 'index')->name('index'); // صفحه رزرو
// رزرو تور
Route::post('tours/{tour}', 'store')
->name('store');
Route::post('tours/{tour}', 'store')->name('store'); // رزرو تور
// صفحه فرم رزرو پرواز
Route::get('flights/{flight}', 'flight')
->name('flight');
// ثبت نهایی رزرو پرواز
Route::post('flights/{flight}', 'storeFlight')
->name('flight.store');
Route::get('flights/{flight}', 'flight')->name('flight'); // فرم رزرو پرواز
Route::post('flights/{flight}', 'storeFlight')->name('flight.store'); // ثبت نهایی پرواز
});
// ------------------------------ پنل شخصی کاربر ------------------------------
@@ -87,7 +61,8 @@ Route::prefix('account')->name('account.')
->middleware('auth')
->group(function () {
Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
// 🔥 تغییر اینجا: به‌جای HomeController از IndexController
Route::get('/', [IndexController::class, 'index'])->name('index'); // داشبورد
Route::controller(BookingController::class)->group(function () {
Route::get('bookings', 'index')->name('bookings'); // رزروها
@@ -97,10 +72,6 @@ Route::prefix('account')->name('account.')
Route::get('favorites', 'index')->name('favorites');
});
// 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::get('/', 'index')->name('index');
@@ -113,6 +84,120 @@ 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;
//use App\Http\Controllers\Account\EditProfileController;
//use App\Http\Controllers\Account\FavoriteController;
//use App\Http\Controllers\Account\HomeController;
//use App\Http\Controllers\BookingController as SiteBookingController;
////use App\Http\Controllers\CommentController;
//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)
// ->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('{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(FavoriteController::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('flights/{flight}', 'flight')
// ->name('flight');
//
// // ثبت نهایی رزرو پرواز
// Route::post('flights/{flight}', 'storeFlight')
// ->name('flight.store');
//
// });
//
//// ------------------------------ پنل شخصی کاربر ------------------------------
//Route::prefix('account')->name('account.')
// ->middleware('auth')
// ->group(function () {
//
// Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
//
// Route::controller(BookingController::class)->group(function () {
// Route::get('bookings', 'index')->name('bookings'); // رزروها
// });
//
// Route::controller(FavoriteController::class)->group(function () {
// Route::get('favorites', 'index')->name('favorites');
// });
//
//// 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::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;