Compare commits

...

23 Commits

Author SHA1 Message Date
shahrzad e74e6c1377 fix: update application routes 2026-08-19 08:24:50 +03:30
shahrzad 771d4d4b00 fix: update frontend styles and scripts 2026-08-19 08:24:36 +03:30
shahrzad de190fb550 fix: update admin styles 2026-08-19 08:24:16 +03:30
shahrzad 82e48faf0f fix: update application service provider 2026-08-19 08:23:08 +03:30
shahrzad 761411e959 fix: update homepage 2026-08-19 08:22:05 +03:30
shahrzad 92daccd47a fix: update frontend layouts and components 2026-08-19 08:21:13 +03:30
shahrzad 6e46594233 fix: update admin layout 2026-08-19 08:20:39 +03:30
shahrzad 7d557bebff fix: update admin settings views 2026-08-19 08:19:31 +03:30
shahrzad 2bf9ba1577 fix: update admin favorites views 2026-08-19 08:18:41 +03:30
shahrzad 68d11dcbd5 fix: update airport management 2026-08-19 08:17:48 +03:30
shahrzad 97c01a17a3 fix: update comment management 2026-08-19 08:17:06 +03:30
shahrzad 552b23d5ff fix: update tour management 2026-08-19 08:14:34 +03:30
shahrzad 852ea9d105 fix: update tour management 2026-08-19 08:13:26 +03:30
shahrzad c790091131 fix: update user model 2026-08-19 08:11:50 +03:30
shahrzad a9d46fe64c fix: update travel models 2026-08-19 08:11:32 +03:30
shahrzad 4aa2e9fb65 chore: add latest database backup 2026-08-19 08:10:16 +03:30
shahrzad b4399e638f feat: add bootstrap assets 2026-08-19 08:09:56 +03:30
shahrzad ad58f114fd feat: add custom frontend styles 2026-08-19 08:08:34 +03:30
shahrzad c500bdd1b7 feat: add province and city models 2026-08-19 08:07:35 +03:30
shahrzad b01507ed7d feat: add flight controller 2026-08-19 08:07:01 +03:30
shahrzad f251fd800f feat: add booking management 2026-08-19 08:06:30 +03:30
shahrzad f27e676b87 feat: add booking management 2026-08-19 08:05:38 +03:30
shahrzad 84f095b00f feat: add user authentication 2026-08-19 08:04:02 +03:30
93 changed files with 68946 additions and 2756 deletions
@@ -0,0 +1,59 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* نمایش صفحه ورود
*/
public function index()
{
return view('auth.login');
}
/**
* ورود کاربر
*/
public function post(Request $request)
{
// $credentials = $request->validate([
// 'email' => [
// 'required',
// 'email',
// ],
//
// 'password' => [
// 'required',
// 'string',
// ],
// ],
//
// [
// 'email.required' => 'ایمیل را وارد کنید.',
// 'email.email' => 'فرمت ایمیل صحیح نیست.',
// 'password.required' => 'رمز عبور را وارد کنید.',
// ]);
$remember = $request->boolean('remember');
if (Auth::guard('web')->attempt($credentials, $remember)) {
$request->session()->regenerate();
return redirect()->intended(
route('index')
);
}
return back()
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => 'ایمیل یا رمز عبور اشتباه است.',
]);
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LogoutController extends Controller
{
//
}
@@ -0,0 +1,107 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\RegisterPostRequest;
use App\Models\City;
use App\Models\Province;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
class RegisterController extends Controller
{
/**
* نمایش فرم ثبت نام
*/
public function index()
{
$provinces = Province::orderBy('name')->get();
return view('auth.register', compact('provinces'));
}
public function post(RegisterPostRequest $request)
{
$imagePath = null;
if ($request->hasFile('image')) {
$imagePath = $request
->file('image')
->store('users', 'public');
}
$user = User::create([
'first_name' => $request->input('first_name'),
'last_name' => $request->input('last_name'),
'national_code' => $request->input('national_code'),
'gender' => $request->input('gender'),
'marital_status' => $request->input('marital_status'),
'spouse_name' => $request->input('marital_status') == 2
? $request->input('spouse_name')
: null,
'mobile' => $request->input('mobile'),
'email' => $request->input('email'),
'username' => $request->input('username'),
'password' => Hash::make($request->input('password')),
'image' => $imagePath,
'province_id' => $request->input('province_id'),
'city_id' => $request->input('city_id'),
'status' => 1,
]);
/*
|--------------------------------------------------------------------------
| ورود خودکار بعد از ثبت نام
|--------------------------------------------------------------------------
*/
Auth::guard('web')->login($user);
$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']);
return response()->json($cities);
}
}
@@ -0,0 +1,76 @@
<?php
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
class BookingController extends Controller
{
public function flight(Flight $flight)
{
// فقط پرواز فعال
if ((int)$flight->status !== 1) {
abort(404);
}
$flight->load([
'travelType',
'origin',
'destination',
]);
return view('account.bookings', compact('flight'));
}
public function storeFlight(Request $request, Flight $flight)
{
// بررسی فعال بودن پرواز
if ((int) $flight->status !== 1) {
abort(404);
}
// اعتبارسنجی
$validated = $request->validate([
'first_name' => [
'required',
'string',
'max:100',
],
'last_name' => [
'required',
'string',
'max:100',
],
'national_code' => [
'required',
'string',
'max:20',
],
'phone' => [
'required',
'string',
'max:20',
],
'passengers' => [
'required',
'integer',
'min:1',
'max:10',
],
]);
// فعلاً برای تست
return redirect()
->route('flights.show', $flight)
->with(
'success',
'درخواست رزرو پرواز با موفقیت ثبت شد.'
);
}
}
+271
View File
@@ -0,0 +1,271 @@
<?php
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* لیست پروازها
*/
public function index(Request $request)
{
$query = Flight::query()
->with([
'travelType',
'origin',
'destination',
]);
// فقط پروازهای فعال
$query->where('status', 1);
// جستجو بر اساس شماره پرواز
if ($request->filled('flight_number')) {
$query->where(
'flight_number',
'like',
'%' . $request->flight_number . '%'
);
}
// جستجو بر اساس مبدا
if ($request->filled('origin')) {
$query->where(
'origin',
'like',
'%' . $request->origin . '%'
);
}
// جستجو بر اساس مقصد
if ($request->filled('destination')) {
$query->where(
'destination',
'like',
'%' . $request->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->origin . '%'
);
}
if ($request->filled('destination')) {
$query->where(
'destination',
'like',
'%' . $request->destination . '%'
);
}
if ($request->filled('departure_date')) {
$query->where(
'departure_date',
$request->departure_date
);
}
if ($request->filled('flight_number')) {
$query->where(
'flight_number',
'like',
'%' . $request->flight_number . '%'
);
}
$flights = $query
->latest()
->paginate(12)
->withQueryString();
return view('flights.index', compact('flights'));
}
/**
* جزئیات پرواز
*/
public function show(Flight $flight)
{
/*
|--------------------------------------------------------------------------
| فعلاً isActive را حذف کردیم
|--------------------------------------------------------------------------
| چون اگر متد isActive در مدل اشتباه باشد یا status متفاوت باشد
| باعث 404 شدن صفحه می‌شود.
*/
$flight->load([
'travelType',
'origin',
'destination',
'tours',
]);
return view('flights.show', compact('flight'));
}
}
//
//namespace App\Http\Controllers;
//
//use App\Models\Flight;
//use Illuminate\Http\Request;
//
//class FlightController extends Controller
//{
// /**
// * لیست پروازها
// */
// public function index(Request $request)
// {
// $query = Flight::query()
// ->where('status', 1)
// ->with([
// 'travelType',
// 'origin',
// 'destination',
// ]);
//
// // جستجو بر اساس شماره پرواز
// if ($request->filled('flight_number')) {
// $query->where(
// 'flight_number',
// 'like',
// '%' . $request->input('flight_number') . '%'
// );
// }
//
// // جستجو بر اساس مبدا
// if ($request->filled('origin')) {
// $query->where(
// 'origin',
// 'like',
// '%' . $request->input('origin') . '%'
// );
// }
//
// // جستجو بر اساس مقصد
// if ($request->filled('destination')) {
// $query->where(
// 'destination',
// 'like',
// '%' . $request->input('destination') . '%'
// );
// }
//
// // مرتب‌سازی
// $flights = $query
// ->latest()
// ->paginate(12)
// ->withQueryString();
//
// return view(
// 'flights.index',
// compact('flights')
// );
// }
//
//
// /**
// * جستجوی پروازها
// */
// public function search(Request $request)
// {
// $query = Flight::query()
// ->where('status', 1)
// ->with([
// 'travelType',
// 'origin',
// 'destination',
// ]);
//
// if ($request->filled('origin')) {
// $query->where(
// 'origin',
// 'like',
// '%' . $request->input('origin') . '%'
// );
// }
//
// if ($request->filled('destination')) {
// $query->where(
// 'destination',
// 'like',
// '%' . $request->input('destination') . '%'
// );
// }
//
// if ($request->filled('departure_date')) {
// $query->where(
// 'departure_date',
// $request->input('departure_date')
// );
// }
//
// $flights = $query
// ->latest()
// ->paginate(12)
// ->withQueryString();
//
// return view(
// 'flights.index',
// compact('flights')
// );
// }
//
//
// /**
// * جزئیات پرواز
// */
// public function show(Flight $flight)
// {
// // فقط پروازهای فعال قابل مشاهده باشند
// if (!$flight->isActive()) {
// abort(404);
// }
//
// // اطلاعات مورد نیاز پرواز
// $flight->load([
// 'travelType',
// 'origin',
// 'destination',
// 'tours',
// ]);
//
// return view(
// 'flights.show',
// compact('flight')
// );
// }
//}
+13 -2
View File
@@ -2,12 +2,23 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Flight;
use App\Models\Tour;
class IndexController extends Controller
{
public function index()
{
return view('index');
$tours = Tour::query()
->where('status', 1)
->latest()
->paginate(6, ['*'], 'tours_page');
$flights = Flight::query()
->where('status', 1)
->latest()
->paginate(6, ['*'], 'flights_page');
return view('index', compact('tours', 'flights'));
}
}
+80 -33
View File
@@ -8,92 +8,139 @@ use Illuminate\Http\Request;
class TourController extends Controller
{
//لیست/آرشیو تورها با قابلیت فیلتر
/**
* لیست / آرشیو تورها با قابلیت فیلتر
*/
public function index(Request $request)
{
$query = Tour::query()
->where('status', 1) // فقط تورهای فعال
->with(['travelType', 'flights']); // بارگذاری زودهنگام برای جلوگیری از N+1
->where('status', 1)
->with(['travelType', 'flights']);
// فیلتر بر اساس نوع سفر (travel_type_id)
// فیلتر بر اساس نوع سفر
if ($request->filled('travel_type')) {
$query->where('travel_type_id', $request->input('travel_type'));
$query->where(
'travel_type_id',
$request->input('travel_type')
);
}
// فیلتر جستجوی متنی (عنوان)
// جستجو بر اساس عنوان
if ($request->filled('q')) {
$query->where('title', 'like', '%' . $request->input('q') . '%');
$query->where(
'title',
'like',
'%' . $request->input('q') . '%'
);
}
// فیلتر بازه قیمتی
// حداقل قیمت
if ($request->filled('price_min')) {
$query->where('price', '>=', $request->input('price_min'));
$query->where(
'price',
'>=',
$request->input('price_min')
);
}
// حداکثر قیمت
if ($request->filled('price_max')) {
$query->where('price', '<=', $request->input('price_max'));
$query->where(
'price',
'<=',
$request->input('price_max')
);
}
// مرتب‌سازی بر اساس قیمت (اگر خواستی)
// مرتب‌سازی
if ($request->filled('sort')) {
$query->orderBy('price', $request->input('sort') === 'desc' ? 'desc' : 'asc');
$query->orderBy(
'price',
$request->input('sort') === 'desc'
? 'desc'
: 'asc'
);
} else {
$query->latest(); // جدیدترین‌ها اول
$query->latest();
}
$tours = $query->paginate(12);
$travelTypes = TravelType::where('status', 1)->get(); // برای منوی فیلتر
// صفحه‌بندی
$tours = $query->paginate(12)->withQueryString();
return view('tours.index', compact('tours', 'travelTypes'));
// انواع سفر
$travelTypes = TravelType::where('status', 1)->get();
return view(
'tours.index',
compact('tours', 'travelTypes')
);
}
//حذف فیلترها و بازگشت به آرشیو کامل
/**
* حذف فیلترها
*/
public function removeFilters()
{
// ساده: فقط برگشت به آرشیو بدون هیچ پارامتری.
// (اگر از کوکی/سشن استفاده می‌کنی، اینجا آن‌ها را هم پاک کن)
return redirect()->route('tours.index');
}
//صفحه‌ی جزئیات یک تور
/**
* نمایش جزئیات یک تور
*/
public function show(Tour $tour)
{
// فقط اگر تور غیرفعال بود از دسترسی جلوگیری کن (مثلاً ریدایرکت)
if ($tour->status == 0) {
// فقط تورهای فعال قابل مشاهده باشند
if ($tour->status != 1) {
abort(404);
}
// بارگذاری پروازها + نوع سفر + نظرات تاییدشده
// افزایش تعداد بازدید
$tour->increment('views_count');
// بارگذاری اطلاعات مورد نیاز
$tour->load([
'flights',
'travelType',
// توجه: این رابطه را باید در مدل Tour تعریف کنی (morphMany)
'comments' => function ($q) {
$q->where('status', 1)->latest();
}
]);
// تورهای پیشنهادی مرتبط (هم‌دسته) برای نمایش کنار صفحه
// تورهای مرتبط
$relatedTours = Tour::where('status', 1)
->where('travel_type_id', $tour->travel_type_id)
->where('id', '!=', $tour->id)
->latest()
->limit(4)
->get();
return view('tours.show', compact('tour', 'relatedTours'));
return view(
'tours.show',
compact('tour', 'relatedTours')
);
}
//جستجوی پیشنهادی (Typeahead / AJAX) — خروجی JSON
/**
* جستجوی پیشنهادی
*/
public function searchSuggestion(Request $request)
{
$q = $request->input('q', '');
$tours = Tour::where('status', 1)
->where('title', 'like', '%' . $q . '%')
->where(
'title',
'like',
'%' . $q . '%'
)
->limit(8)
->get(['id', 'title', 'slug', 'price']);
->get([
'id',
'title',
'slug',
'price'
]);
return response()->json($tours);
}
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\CommentUpdateRequest;
use App\Http\Requests\UpdateCommentRequest;
use App\Models\Comment;
@@ -22,12 +23,12 @@ class CommentController extends Controller
return view('admin.comments.show', compact('comment'));
}
public function edit(Comment $comment)
{
return view('admin.comments.edit', compact('comment'));
}
// public function edit(Comment $comment)
// {
// return view('admin.comments.edit', compact('comment'));
// }
public function update(UpdateCommentRequest $request, Comment $comment)
public function update(CommentUpdateRequest $request, Comment $comment)
{
$comment->update($request->validated());
+62 -28
View File
@@ -7,6 +7,10 @@ use App\Http\Requests\TourStoreRequest;
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;
use Illuminate\Support\Str;
class TourController extends Controller
{
@@ -18,23 +22,40 @@ class TourController extends Controller
public function create()
{
return view('admin.tours.create');
$travelTypes = TravelType::all();
return view('admin.tours.create', compact('travelTypes'));
}
public function store(TourStoreRequest $request)
{
DB::beginTransaction();
// Tour::create($request->validated());
try {
$data = $request->validated();
// ساخت slug اگر خالی بود
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
$tour = Tour::create($request->only([
'travel_type_id', 'title', 'slug', 'description',
'start_date', 'end_date', 'price', 'capacity', 'status'
]));
$tour = Tour::create($data);
$this->uploadImages($tour, $request->file('images'));
return view('admin.tours.index')
->with('success', 'تور با موفقیت ایجاد شد.');
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]);
}
DB::commit();
return redirect()->route('admin.tours.index')->with('success', 'تور با موفقیت ایجاد شد.');
} catch (\Exception $exception) {
Log::error($exception);
DB::rollBack();
return back()->withInput()->withErrors(['general' => 'خطایی در ثبت رخ داد.']);
}
}
public function show(Tour $tour)
@@ -50,25 +71,44 @@ class TourController extends Controller
public function update(TourStoreRequest $request, Tour $tour)
{
$tour->update($request->validated());
DB::beginTransaction();
try {
$data = $request->validated();
// ذخیره فایل و گرفتن مسیر (بدون پسوند)
$path = $request->file('image')->store('photos', 'public');
if (empty($data['slug'])) {
$data['slug'] = Str::slug($data['title']);
}
$extension = $request->file('image')->getClientOriginalExtension();
if ($request->hasFile('image')) {
// حذف عکس قبلی از حافظه
if ($tour->image && Storage::disk('public')->exists($tour->image)) {
Storage::disk('public')->delete($tour->image);
}
// ایجاد رکورد
$tour->files()->create([
'name' => $path,
'extension' => $extension,
'size' => $request->file('image')->getSize(),
'original_name' => $request->file('image')->getClientOriginalName(),
]);
$image = $request->file('image');
$newFileName = time() . '.tour-image' . rand(11111, 99999) . '.' . $image->extension();
$path = $image->storeAs('tours', $newFileName, 'public');
$data['image'] = $path;
}
return redirect()->route('admin.tours.index')
->with('success', 'تور با موفقیت به‌روزرسانی شد.');
$tour->update($data);
DB::commit();
return redirect()->route('admin.tours.index')->with('success', 'تور با موفقیت به‌روزرسانی شد.');
} catch (\Exception $exception) {
Log::error($exception);
DB::rollBack();
return back()->withInput()->withErrors(['general' => 'خطایی در به‌روزرسانی رخ داد.']);
}
}
public function removeImage(Tour $tour)
{
// حذف تصویر تکی (اختیاری — می‌توانی منطق دلخواه بگذاری)
return back()->with('success', 'عملیات حذف تصویر انجام شد.');
}
public function destroy(Tour $tour)
@@ -78,10 +118,4 @@ class TourController extends Controller
return redirect()->route('admin.tours.index')
->with('success', 'تور با موفقیت حذف شد.');
}
public function removeImage(Tour $tour, $image)
{
// منطق حذف تصویر — بسته به جدول تصاویر
return back()->with('success', 'تصویر حذف شد.');
}
}
+20 -1
View File
@@ -14,6 +14,15 @@ class AirportStoreRequest extends FormRequest
{
return true;
}
protected function prepareForValidation(): void
{
// کد فرودگاه همیشه با حروف بزرگ ذخیره شود (IATA)
if ($this->has('code')) {
$this->merge([
'code' => strtoupper($this->input('code')),
]);
}
}
/**
* Get the validation rules that apply to the request.
@@ -35,7 +44,7 @@ class AirportStoreRequest extends FormRequest
'string',
'max:100'
],
'country' =>
'province' =>
[
'required',
'string',
@@ -50,6 +59,16 @@ class AirportStoreRequest extends FormRequest
];
}
public function attributes(): array
{
return [
'name' => 'نام فرودگاه',
'city' => 'شهر',
'country' => 'کشور',
'code' => 'کد فرودگاه',
];
}
// public function messages(): array
// {
// return [
@@ -1,13 +1,11 @@
<?php
namespace App\Http\Requests;
namespace App\Http\Requests\Auth;
use App\Enums\PaymentStatus;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class PaymentUpdateRequest extends FormRequest
class LoginPostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
@@ -25,12 +23,18 @@ class PaymentUpdateRequest extends FormRequest
public function rules(): array
{
return [
'status' => [
'email' => [
'required',
// مقدار باید یکی از مقادیر integer enum باشد (0,1,2,3)
Rule::enum(PaymentStatus::class),
'email',
],
'password' => [
'required',
'string',
],
];
}
}
@@ -0,0 +1,131 @@
<?php
namespace App\Http\Requests\Auth;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class RegisterPostRequest 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 [
'first_name' => [
'required',
'string',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'last_name' => [
'required',
'string',
'max:100',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'national_code' => [
'required',
'digits:10',
'unique:users,national_code',
],
'gender' => [
'required',
'integer',
Rule::in([1, 2]),
],
'marital_status' => [
'required',
'integer',
Rule::in([1, 2, 3]),
],
'spouse_name' => [
'nullable',
'string',
'max:200',
'required_if:marital_status,2',
'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
],
'mobile' => [
'required',
'digits:11',
'regex:/^09\d{9}$/',
'unique:users,mobile',
],
'email' => [
'required',
'email',
'max:150',
'unique:users,email',
],
'username' => [
'required',
'string',
'min:3',
'max:50',
'regex:/^[A-Za-z0-9]+$/',
'unique:users,username',
],
'password' => [
'required',
'string',
'min:8',
'confirmed',
],
'image' => [
'nullable',
'image',
'mimes:jpg,jpeg,png,webp',
'max:800',
],
'province_id' => [
'nullable',
'integer',
],
'city_id' => [
'nullable',
'integer',
],
];
}
}
+3 -1
View File
@@ -27,7 +27,9 @@ class CommentUpdateRequest extends FormRequest
'body' =>
[
'required',
'string'
'string',
'min:3',
'max:1000'
],
'status' =>
[
+39 -39
View File
@@ -23,60 +23,60 @@ class TourStoreRequest extends FormRequest
public function rules(): array
{
return [
'travel_type_id' =>
[
'required',
'exists:travel_types,id'
],
// 'travel_type_id' =>
// [
// 'nullable',
// 'exists:travel_types,id'
// ],
'title' =>
[
'required',
'string',
'max:200'
],
'slug' =>
['required', 'string',
'max:200',
'regex:/^[a-z0-9-]+$/',
'unique:tours,slug,' . $this->tour
],
// 'slug' =>
// ['nullable', 'string',
// 'max:200',
// 'regex:/^[a-z0-9-]+$/',
// 'unique:tours,slug,' . $this->tour
// ],
'description' =>
[
'required',
'string'
],
'duration' =>
[
'required',
'string',
'max:50'
],
'start_date' =>
[
'required',
'date'
],
'end_date' =>
[
'required',
'date',
'after_or_equal:start_date'
],
// 'description' =>
// [
// 'nullable',
// 'string'
// ],
// 'duration' =>
// [
// 'nullable',
// 'string',
// 'max:50'
// ],
// 'start_date' =>
// [
// 'nullable',
// 'date'
// ],
// 'end_date' =>
// [
// 'nullable',
// 'date',
// 'after_or_equal:start_date'
// ],
'price' =>
[
'required',
'numeric',
'min:0'
],
'capacity' =>
[
'required',
'integer',
'min:0'],
// 'capacity' =>
// [
// 'nullable',
// 'integer',
// 'min:0'],
'images' =>
[
'required',
'nullable',
'array'
],
'images.*' =>
+5 -3
View File
@@ -6,6 +6,7 @@
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
@@ -14,21 +15,22 @@ use Illuminate\Database\Eloquent\Model;
* @property int $id
* @property string $name
* @property string $city
* @property string $country
* @property string $province
* @property string $code
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @package App\Models
*/
class Airport extends Model
{
protected $table = 'airports';
public $timestamps = false;
public static $snakeAttributes = false;
protected $fillable = [
'name',
'city',
'country',
'province',
'code'
];
}
+84
View File
@@ -0,0 +1,84 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
* Class Booking
*
* @property int $id
* @property int $user_id
* @property int|null $tour_id
* @property int|null $flight_id
* @property string $booking_code
* @property string $first_name
* @property string $last_name
* @property string|null $national_code
* @property string $mobile
* @property string|null $email
* @property int $passengers
* @property float $price
* @property int $status
* @property string $payment_status
* @property string|null $notes
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @property User $user
* @property Tour|null $tour
* @property Flight|null $flight
*
* @package App\Models
*/
class Booking extends Model
{
protected $table = 'bookings';
public static $snakeAttributes = false;
protected $casts = [
'user_id' => 'int',
'tour_id' => 'int',
'flight_id' => 'int',
'passengers' => 'int',
'price' => 'float',
'status' => 'int'
];
protected $fillable = [
'user_id',
'tour_id',
'flight_id',
'booking_code',
'first_name',
'last_name',
'national_code',
'mobile',
'email',
'passengers',
'price',
'status',
'payment_status',
'notes'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function tour()
{
return $this->belongsTo(Tour::class);
}
public function flight()
{
return $this->belongsTo(Flight::class);
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
/**
* Class City
*
* @property int $id
* @property int $province_id
* @property string $name
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Province $province
*
* @package App\Models
*/
class City extends Model
{
protected $table = 'cities';
public static $snakeAttributes = false;
protected $casts = [
'province_id' => 'int'
];
protected $fillable = [
'province_id',
'name'
];
public function province()
{
return $this->belongsTo(Province::class);
}
}
+12
View File
@@ -45,6 +45,18 @@ 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) ------------------------- */
/**
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* Created by Reliese Model.
*/
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
/**
* Class Province
*
* @property int $id
* @property string $name
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @property Collection|City[] $cities
*
* @package App\Models
*/
class Province extends Model
{
protected $table = 'provinces';
public static $snakeAttributes = false;
protected $fillable = [
'name'
];
public function cities()
{
return $this->hasMany(City::class);
}
}
+20 -50
View File
@@ -14,20 +14,22 @@ use Illuminate\Database\Eloquent\Model;
* Class Tour
*
* @property int $id
* @property int $travel_type_id
* @property int|null $travel_type_id
* @property string $title
* @property string $slug
* @property string $description
* @property string $duration
* @property Carbon $start_date
* @property Carbon $end_date
* @property string|null $slug
* @property string|null $image
* @property string|null $description
* @property string|null $duration
* @property Carbon|null $start_date
* @property Carbon|null $end_date
* @property float $price
* @property int $capacity
* @property int|null $capacity
* @property int $views_count
* @property int $status
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @property TravelType $travelType
* @property TravelType|null $travelType
* @property Collection|Flight[] $flights
*
* @package App\Models
@@ -38,31 +40,28 @@ class Tour extends Model
public static $snakeAttributes = false;
protected $casts = [
'start_date' => 'date',
'end_date' => 'date',
'price' => 'decimal:2',
'status' => 'integer',
// 'travel_type_id' => 'int',
// 'start_date' => 'datetime',
// 'end_date' => 'datetime',
// 'price' => 'float',
// 'capacity' => 'int',
// 'status' => 'int'
'travel_type_id' => 'int',
'start_date' => 'datetime',
'end_date' => 'datetime',
'price' => 'float',
'capacity' => 'int',
'views_count' => 'int',
'status' => 'int'
];
protected $fillable = [
'travel_type_id',
'title',
'slug',
'image',
'description',
'duration',
'start_date',
'end_date',
'price',
'capacity',
'status',
'image',
'views_count',
'status'
];
public function travelType()
@@ -76,33 +75,4 @@ class Tour extends Model
->withPivot('id')
->withTimestamps();
}
//اضافه شده (بعدا بررسی بشه)
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function favorites()
{
return $this->morphMany(Favorite::class, 'favoritable');
}
public function files()
{
return $this->morphMany(File::class, 'fileable');
}
public function getRouteKeyName()
{
return 'slug';
}
public function getStatusLabelAttribute()
{
return $this->status == 1 ? 'فعال' : 'پیش‌نویس';
}
}
+26 -2
View File
@@ -8,7 +8,7 @@ namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Auth\User as Authenticate;
use Illuminate\Database\Eloquent\Model;
/**
* Class User
@@ -21,22 +21,34 @@ use Illuminate\Foundation\Auth\User as Authenticate;
* @property string $password
* @property string|null $national_code
* @property Carbon|null $birth_date
* @property bool $gender
* @property bool $marital_status
* @property string|null $spouse_name
* @property string|null $image
* @property string $username
* @property int $province_id
* @property int|null $city_id
* @property int $status
* @property Carbon $created_at
* @property Carbon $updated_at
*
* @property Collection|Booking[] $bookings
* @property Collection|Comment[] $comments
* @property Collection|Favorite[] $favorites
*
* @package App\Models
*/
class User extends Authenticate
class User extends Model
{
protected $table = 'users';
public static $snakeAttributes = false;
protected $casts = [
'birth_date' => 'datetime',
'gender' => 'bool',
'marital_status' => 'bool',
'province_id' => 'int',
'city_id' => 'int',
'status' => 'int'
];
@@ -52,9 +64,21 @@ class User extends Authenticate
'password',
'national_code',
'birth_date',
'gender',
'marital_status',
'spouse_name',
'image',
'username',
'province_id',
'city_id',
'status'
];
public function bookings()
{
return $this->hasMany(Booking::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
+2 -1
View File
@@ -2,6 +2,7 @@
namespace App\Providers;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@@ -19,6 +20,6 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot(): void
{
//
Paginator::useBootstrapFive();
}
}
+504
View File
@@ -0,0 +1,504 @@
-- phpMyAdmin SQL Dump
-- version 5.2.3
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1:3308
-- Generation Time: Aug 18, 2026 at 04:23 PM
-- Server version: 8.4.7
-- PHP Version: 8.3.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `airline_agency`
--
-- --------------------------------------------------------
--
-- Table structure for table `admins`
--
DROP TABLE IF EXISTS `admins`;
CREATE TABLE IF NOT EXISTS `admins` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`full_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '1' COMMENT '0:disable 1:enable',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `admins`
--
INSERT INTO `admins` (`id`, `full_name`, `username`, `email`, `mobile`, `password`, `status`, `created_at`, `updated_at`) VALUES
(2, 'شهرزاد زندی', 'shahrzad', 'shahrzad.zandi@gmail.com', '09359359350', '$2y$12$KpHLJK1kIz/TxVUOn4FV7udVA3xGLLDtEknPZyfh13Z2WPkRmHwni', 1, '2026-08-17 07:24:19', '2026-08-17 07:24:19'),
(3, 'مدیر سیستم', 'admin', 'admin@gmail.com', '09123456789', '$2y$12$ElsUA1CqyK6euG6adWhXRuayR/Jzcq1zH28eoN3ypfeVrmTIr/zAe', 1, '2026-08-17 07:44:25', '2026-08-17 09:12:14');
-- --------------------------------------------------------
--
-- Table structure for table `admin_permission`
--
DROP TABLE IF EXISTS `admin_permission`;
CREATE TABLE IF NOT EXISTS `admin_permission` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`admin_id` bigint UNSIGNED NOT NULL,
`permission_id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk1_admin_permission` (`permission_id`),
KEY `fk2_admin_permission` (`admin_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `airports`
--
DROP TABLE IF EXISTS `airports`;
CREATE TABLE IF NOT EXISTS `airports` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`name` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`city` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`code` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `airports`
--
INSERT INTO `airports` (`id`, `name`, `city`, `province`, `code`, `created_at`, `updated_at`) VALUES
(1, 'فرودگاه بین‌المللی اهواز', 'اهواز', 'خوزستان', 'AWZ', '0000-00-00 00:00:00', '0000-00-00 00:00:00');
-- --------------------------------------------------------
--
-- Table structure for table `bookings`
--
DROP TABLE IF EXISTS `bookings`;
CREATE TABLE IF NOT EXISTS `bookings` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`tour_id` bigint UNSIGNED DEFAULT NULL,
`flight_id` bigint UNSIGNED DEFAULT NULL,
`booking_code` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`national_code` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`mobile` varchar(11) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`passengers` int UNSIGNED NOT NULL DEFAULT '1',
`price` decimal(15,2) NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`payment_status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_bookings` (`user_id`),
KEY `fk2_bookings` (`tour_id`),
KEY `fk3_bookings` (`flight_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- Table structure for table `cities`
--
DROP TABLE IF EXISTS `cities`;
CREATE TABLE IF NOT EXISTS `cities` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`province_id` bigint UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk1_cities` (`province_id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- Dumping data for table `cities`
--
INSERT INTO `cities` (`id`, `province_id`, `name`, `created_at`, `updated_at`) VALUES
(7, 2, 'ساری', NULL, NULL),
(8, 1, 'تهران', NULL, NULL),
(9, 5, 'شیراز', NULL, NULL),
(10, 4, 'اصفهان', NULL, NULL),
(11, 1, 'ری', NULL, NULL),
(12, 2, 'آمل', NULL, NULL);
-- --------------------------------------------------------
--
-- Table structure for table `comments`
--
DROP TABLE IF EXISTS `comments`;
CREATE TABLE IF NOT EXISTS `comments` (
`id` bigint UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint UNSIGNED NOT NULL,
`commentable_id` bigint UNSIGNED NOT NULL,
`commentable_type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`body` text COLLATE utf8mb4_unicode_ci NOT NULL,
`status` tinyint UNSIGNED NOT NULL DEFAULT '0',
`created_at` timestamp NOT NULL,
`updated_at` timestamp NOT NULL,
PRIMARY KEY (`id`),
KEY `fk1_ comments` (`user_id`),
KEY `fk2_ comments` (`commentable_id`)
) ENGINE=InnoDB 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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
--
-- 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=4 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');
-- --------------------------------------------------------
--
-- 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=5 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, 5, 1, '2026-08-18 07:21:07', '2026-08-18 12:12:55'),
(4, NULL, 'تور لوکس پنج‌روزه کیش با پرواز مستقیم', 'tor-loks-pngrozh-kysh-ba-proaz-mstkym', 'tours/1787037718.tour-image49479.jpg', NULL, NULL, NULL, NULL, 12500000.00, NULL, 4, 1, '2026-08-18 07:21:58', '2026-08-18 12:13:45');
-- --------------------------------------------------------
--
-- 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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
--
-- 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 */;
+126
View File
@@ -117,4 +117,130 @@ body {
padding: 16px;
}
}
body {
background: #f5f7fa;
}
.admin-wrapper {
min-height: 100vh;
}
.admin-sidebar {
width: 260px;
min-height: 100vh;
background: #fff;
border-left: 1px solid #e5e7eb;
position: fixed;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
overflow-y: auto;
}
.admin-main {
margin-right: 260px;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.admin-header {
height: 70px;
background: #fff;
border-bottom: 1px solid #e5e7eb;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 25px;
}
.admin-content {
padding: 25px;
flex: 1;
}
.admin-logo {
height: 70px;
display: flex;
align-items: center;
padding: 0 20px;
border-bottom: 1px solid #eee;
}
.admin-logo a {
text-decoration: none;
font-size: 18px;
font-weight: bold;
color: #0d6efd;
}
.admin-menu {
padding: 15px 10px;
}
.admin-menu-title {
font-size: 11px;
color: #9ca3af;
padding: 10px;
margin-top: 10px;
}
.admin-menu a {
display: flex;
align-items: center;
gap: 10px;
padding: 11px 12px;
margin-bottom: 4px;
border-radius: 8px;
color: #4b5563;
text-decoration: none;
transition: .2s;
}
.admin-menu a:hover,
.admin-menu a.active {
background: #eef5ff;
color: #0d6efd;
}
.admin-menu i {
width: 22px;
text-align: center;
font-size: 16px;
}
.admin-user {
display: flex;
align-items: center;
gap: 10px;
}
.admin-user-avatar {
width: 38px;
height: 38px;
border-radius: 50%;
background: #eef5ff;
display: flex;
align-items: center;
justify-content: center;
color: #0d6efd;
}
.admin-card {
background: #fff;
border: 1px solid #e5e7eb;
border-radius: 12px;
}
@media (max-width: 991px) {
.admin-sidebar {
transform: translateX(100%);
}
}
+379
View File
@@ -0,0 +1,379 @@
/* =========================================
AUTH PAGE
========================================= */
.auth-page {
min-height: 80vh;
padding: 70px 0;
background: #f5f7fb;
direction: rtl;
}
/* =========================================
CARD
========================================= */
.auth-card {
width: 100%;
max-width: 900px;
margin: 0 auto;
background: #fff;
border-radius: 18px;
padding: 40px;
box-shadow:
0 15px 45px rgba(0, 0, 0, 0.10);
}
.login-card {
max-width: 500px;
}
/* =========================================
HEADER
========================================= */
.auth-header {
text-align: center;
margin-bottom: 35px;
}
.auth-icon {
width: 70px;
height: 70px;
margin: 0 auto 18px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #eef5ff;
color: #1473e6;
font-size: 28px;
}
.auth-header h1 {
margin: 0 0 10px;
font-size: 27px;
font-weight: 700;
color: #222;
}
.auth-header p {
margin: 0;
color: #777;
font-size: 14px;
line-height: 1.8;
}
/* =========================================
FORM SECTION
========================================= */
.form-section {
margin-bottom: 30px;
padding-bottom: 25px;
border-bottom: 1px solid #eee;
}
.form-section:last-of-type {
border-bottom: none;
}
.form-section-title {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 22px;
font-size: 17px;
font-weight: 700;
color: #333;
}
.form-section-title i {
color: #1473e6;
font-size: 19px;
}
/* =========================================
FORM
========================================= */
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-size: 14px;
font-weight: 600;
color: #333;
}
.form-group label span {
color: #e53935;
}
.form-control {
width: 100%;
height: 48px;
border: 1px solid #ddd;
border-radius: 9px;
padding: 0 14px;
background: #fff;
color: #333;
font-size: 14px;
transition: all 0.2s ease;
box-shadow: none;
}
.form-control:focus {
border-color: #1473e6;
outline: none;
box-shadow:
0 0 0 3px rgba(20, 115, 230, 0.10);
}
textarea.form-control {
height: auto;
padding-top: 12px;
}
select.form-control {
cursor: pointer;
}
.form-help {
display: block;
margin-top: 6px;
color: #888;
font-size: 12px;
line-height: 1.7;
}
/* =========================================
ALERT
========================================= */
.auth-alert {
display: flex;
gap: 12px;
padding: 15px;
margin-bottom: 25px;
border-radius: 10px;
font-size: 14px;
line-height: 1.8;
}
.auth-alert-danger {
background: #fff1f1;
color: #b42318;
border: 1px solid #ffd5d5;
}
.auth-alert-success {
background: #effbf3;
color: #16733a;
border: 1px solid #ccefd9;
}
.auth-alert i {
margin-top: 4px;
}
.auth-alert ul {
margin: 7px 0 0;
padding-right: 18px;
}
/* =========================================
LOGIN OPTIONS
========================================= */
.login-options {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.remember-me {
display: flex;
align-items: center;
gap: 7px;
cursor: pointer;
font-size: 13px;
color: #666;
}
.remember-me input {
cursor: pointer;
}
/* =========================================
BUTTON
========================================= */
.auth-btn {
width: 100%;
height: 52px;
border: none;
border-radius: 10px;
background: #1473e6;
color: #fff;
font-size: 15px;
font-weight: 700;
cursor: pointer;
transition: all 0.25s ease;
}
.auth-btn:hover {
background: #0d5fc5;
transform: translateY(-1px);
box-shadow:
0 8px 20px rgba(20, 115, 230, 0.22);
}
.auth-btn i {
margin-left: 7px;
}
/* =========================================
FOOTER
========================================= */
.auth-footer {
margin-top: 25px;
padding-top: 22px;
border-top: 1px solid #eee;
text-align: center;
color: #777;
font-size: 14px;
}
.auth-footer a {
color: #1473e6;
font-weight: 700;
text-decoration: none;
margin-right: 5px;
}
.auth-footer a:hover {
text-decoration: underline;
}
/* =========================================
RESPONSIVE
========================================= */
@media (max-width: 767px) {
.auth-page {
padding: 30px 15px;
}
.auth-card {
padding: 25px 18px;
border-radius: 14px;
}
.auth-header h1 {
font-size: 23px;
}
.form-section-title {
font-size: 16px;
}
}
+606
View File
@@ -0,0 +1,606 @@
/* =========================================================
Travel Agency - Home Page
========================================================= */
.travel-page {
background: #f6f8fb;
min-height: 100vh;
padding: 60px 0;
direction: rtl;
}
.travel-page .section-heading {
text-align: center;
margin-bottom: 35px;
}
.travel-page .section-heading h2 {
font-size: 28px;
font-weight: 700;
color: #1f2937;
margin-bottom: 10px;
}
.travel-page .section-heading p {
color: #7b8494;
font-size: 14px;
margin: 0;
}
/* =========================================================
Tour Cards
========================================================= */
.travel-page .travel-card {
background: #fff;
border-radius: 14px;
overflow: hidden;
border: 1px solid #edf0f4;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
transition: all .25s ease;
height: 100%;
}
.travel-page .travel-card:hover {
transform: translateY(-6px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.10);
}
/* تصویر کارت */
.travel-page .travel-card-image {
width: 100%;
height: 210px;
overflow: hidden;
background: #eef1f5;
}
.travel-page .travel-card-image img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
transition: transform .35s ease;
}
.travel-page .travel-card:hover .travel-card-image img {
transform: scale(1.05);
}
/* بدنه کارت */
.travel-page .travel-card-body {
padding: 20px;
}
.travel-page .travel-card-title {
font-size: 19px;
font-weight: 700;
color: #202936;
margin: 0 0 12px;
}
.travel-page .travel-card-summary {
color: #737d8d;
font-size: 14px;
line-height: 1.9;
min-height: 52px;
margin-bottom: 15px;
}
.travel-page .travel-date {
color: #555f70;
font-size: 13px;
margin-bottom: 18px;
}
.travel-page .travel-date i {
margin-left: 6px;
color: #1687d9;
}
/* =========================================================
Buttons
========================================================= */
.travel-page .travel-btn {
display: block;
text-align: center;
text-decoration: none !important;
background: #1687d9;
color: #fff !important;
border-radius: 8px;
padding: 10px 15px;
font-size: 14px;
transition: .2s;
}
.travel-page .travel-btn:hover {
background: #0d6fae;
}
/* =========================================================
Empty State
========================================================= */
.travel-page .empty-box {
background: #fff;
border: 1px dashed #d9dee7;
border-radius: 12px;
padding: 35px;
text-align: center;
color: #8a93a1;
}
/* =========================================================
Pagination
========================================================= */
.travel-page .pagination-wrapper {
display: flex;
justify-content: center;
margin-top: 30px;
direction: rtl;
}
.travel-page .pagination-wrapper nav {
margin: 0;
}
/* =========================================================
Flights
========================================================= */
.travel-page .flights-section {
margin-top: 80px;
}
.travel-page .flight-card {
background: #fff;
border-radius: 14px;
border: 1px solid #edf0f4;
padding: 22px;
height: 100%;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.05);
transition: all .25s ease;
}
.travel-page .flight-card:hover {
transform: translateY(-5px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.09);
}
.travel-page .flight-icon {
width: 50px;
height: 50px;
border-radius: 50%;
background: #e9f5ff;
color: #1687d9;
display: flex;
align-items: center;
justify-content: center;
font-size: 21px;
margin-bottom: 17px;
}
.travel-page .flight-title {
font-size: 19px;
font-weight: 700;
color: #202936;
margin-bottom: 12px;
}
.travel-page .flight-summary {
color: #737d8d;
font-size: 14px;
line-height: 1.9;
min-height: 52px;
margin-bottom: 14px;
}
.travel-page .flight-date {
color: #555f70;
font-size: 13px;
margin-bottom: 18px;
}
/* =========================================================
Responsive
========================================================= */
@media (max-width: 767px) {
.travel-page {
padding: 35px 15px;
}
.travel-page .section-heading h2 {
font-size: 23px;
}
.travel-page .travel-card-image {
height: 190px;
}
.travel-page .flights-section {
margin-top: 55px;
}
}
.tour-details-page {
direction: rtl;
padding: 50px 0;
background: #f7f8fa;
}
.tour-details-card {
max-width: 1050px;
margin: auto;
background: #fff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
}
.tour-details-image {
width: 100%;
height: 400px;
overflow: hidden;
}
.tour-details-image img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.tour-no-image {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #eeeeee;
color: #777;
}
.tour-details-content {
padding: 35px;
}
.tour-details-title {
margin: 0 0 25px;
font-size: 32px;
font-weight: 700;
color: #222;
}
.tour-details-info {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
margin-bottom: 35px;
}
.tour-info-box {
padding: 20px;
background: #f7f8fa;
border-radius: 12px;
text-align: center;
}
.tour-info-label {
display: block;
color: #888;
font-size: 13px;
margin-bottom: 8px;
}
.tour-info-box strong {
color: #222;
font-size: 15px;
}
.tour-description {
border-top: 1px solid #eee;
padding-top: 30px;
}
.tour-description h2,
.tour-flights h2,
.related-tours h2 {
margin-bottom: 20px;
font-size: 22px;
}
.tour-description p {
color: #555;
line-height: 2.2;
font-size: 15px;
}
.tour-flights {
margin-top: 35px;
padding-top: 30px;
border-top: 1px solid #eee;
}
.flight-item {
display: flex;
justify-content: space-between;
gap: 20px;
padding: 18px;
margin-bottom: 10px;
background: #f7f8fa;
border-radius: 10px;
}
.flight-item span {
display: block;
color: #888;
font-size: 13px;
margin-bottom: 5px;
}
.related-tours {
margin-top: 40px;
padding-top: 30px;
border-top: 1px solid #eee;
}
.related-tours-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
}
.related-tour-card {
display: block;
overflow: hidden;
background: #f7f8fa;
border-radius: 10px;
color: inherit;
text-decoration: none;
}
.related-tour-card img {
width: 100%;
height: 130px;
object-fit: cover;
display: block;
}
.related-tour-card div {
padding: 12px;
}
.related-tour-card h3 {
margin: 0 0 8px;
font-size: 15px;
}
.related-tour-card span {
color: #888;
font-size: 12px;
}
.tour-back {
margin-top: 35px;
}
.tour-back-button {
display: inline-block;
padding: 12px 25px;
background: #222;
color: #fff;
border-radius: 8px;
text-decoration: none;
}
.tour-back-button:hover {
color: #fff;
text-decoration: none;
opacity: .9;
}
@media (max-width: 768px) {
.tour-details-page {
padding: 20px 10px;
}
.tour-details-image {
height: 250px;
}
.tour-details-content {
padding: 20px;
}
.tour-details-title {
font-size: 25px;
}
.tour-details-info {
grid-template-columns: 1fr 1fr;
}
.related-tours-grid {
grid-template-columns: 1fr 1fr;
}
.flight-item {
flex-direction: column;
}
}
/* =========================================================
Main Navbar - RTL Fix
========================================================= */
#main-nav {
direction: rtl;
width: 100%;
position: relative;
z-index: 1000;
}
#main-nav .container {
width: 100%;
}
#main-nav .navbar-inner {
display: flex;
align-items: center;
min-height: 80px;
}
/* لوگو */
#main-nav .navbar-header {
float: none;
flex-shrink: 0;
}
#main-nav .navbar-brand {
display: flex;
align-items: center;
height: 80px;
padding: 10px 0 10px 30px;
}
#main-nav .navbar-brand img {
max-height: 55px;
width: auto;
}
/* بخش منو */
#main-nav .navbar-collapse {
display: flex !important;
align-items: center;
justify-content: space-between;
flex: 1;
border: 0;
box-shadow: none;
}
/* منوی اصلی */
#main-nav .navbar-nav {
float: none !important;
display: flex;
align-items: center;
margin: 0;
}
#main-nav .navbar-nav > li {
float: none;
}
#main-nav .navbar-nav > li > a {
display: flex;
align-items: center;
min-height: 80px;
padding: 0 16px;
white-space: nowrap;
}
/* منوی سمت راست */
#main-nav .navbar-nav.navbar-right {
margin-right: auto;
margin-left: 0;
}
/* آیکون حساب */
#main-nav .navbar-nav-item-user-icon {
margin-left: 7px;
font-size: 18px;
}
/* Dropdown */
#main-nav .dropdown-menu {
right: 0;
left: auto;
min-width: 180px;
text-align: right;
}
#main-nav .navbar-right .dropdown-menu {
right: auto;
left: 0;
}
/* موبایل */
@media (max-width: 767px) {
#main-nav .navbar-inner {
display: block;
min-height: auto;
}
#main-nav .navbar-header {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 70px;
}
#main-nav .navbar-brand {
height: 70px;
padding: 8px 0;
}
#main-nav .navbar-toggle {
float: left;
margin-left: 0;
margin-right: 15px;
}
#main-nav .navbar-collapse {
display: block !important;
width: 100%;
padding: 0;
}
#main-nav .navbar-nav {
display: block;
width: 100%;
}
#main-nav .navbar-nav > li {
display: block;
width: 100%;
}
#main-nav .navbar-nav > li > a {
min-height: 45px;
padding: 12px 15px;
display: block;
}
#main-nav .navbar-nav.navbar-right {
margin: 0;
}
#main-nav .dropdown-menu {
position: static;
float: none;
width: 100%;
box-shadow: none;
}
}
+467 -3
View File
@@ -14569,9 +14569,7 @@ jdp-container .jdp-icon-plus.not-in-range svg, jdp-container .jdp-icon-minus.not
opacity: 0.3;
}
jdp-container .jdp-years, jdp-container .jdp-months {
display: -webkit-inline-box;
display: -webkit-flex;
display: -ms-inline-flexbox;
/*display: -webkit-flex;*/
display: inline-flex;
margin: 0 2.5%;
font-size: 120%;
@@ -14747,3 +14745,469 @@ jdp-container .jdp-btn-today, jdp-container .jdp-btn-empty {
.datepic:focus {
outline: none;
}
/* =========================================================
TRAVEL HERO HEADER
========================================================= */
.travel-header {
position: relative;
min-height: 560px;
overflow: hidden;
direction: rtl;
color: #fff;
}
/* Background */
.travel-header-bg {
position: absolute;
inset: 0;
z-index: 0;
}
.travel-header-bg-image {
position: absolute;
inset: 0;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
transform: scale(1.02);
}
.travel-header-overlay {
position: absolute;
inset: 0;
background:
linear-gradient(
180deg,
rgba(5, 20, 40, .78) 0%,
rgba(5, 20, 40, .48) 45%,
rgba(5, 20, 40, .72) 100%
);
}
/* Content */
.travel-header-content {
position: relative;
z-index: 2;
}
/* =========================================================
NAVBAR
========================================================= */
.travel-navbar {
min-height: 90px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(255,255,255,.18);
position: relative;
}
/* Logo */
.travel-logo a {
display: flex;
align-items: center;
gap: 12px;
text-decoration: none !important;
color: #fff;
}
.travel-logo-icon {
width: 48px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 14px;
background: rgba(255,255,255,.15);
border: 1px solid rgba(255,255,255,.28);
backdrop-filter: blur(8px);
font-size: 21px;
}
.travel-logo-content {
display: flex;
flex-direction: column;
line-height: 1.5;
}
.travel-logo-content strong {
font-size: 17px;
font-weight: 800;
}
.travel-logo-content small {
font-size: 11px;
opacity: .75;
}
/* =========================================================
MENU
========================================================= */
.travel-menu ul {
display: flex;
align-items: center;
margin: 0;
padding: 0;
list-style: none;
gap: 4px;
}
.travel-menu li {
position: relative;
}
.travel-menu a {
display: block;
padding: 12px 17px;
color: rgba(255,255,255,.88);
text-decoration: none !important;
font-size: 14px;
font-weight: 600;
border-radius: 9px;
transition: all .25s ease;
}
.travel-menu a:hover {
color: #fff;
background: rgba(255,255,255,.12);
}
.travel-menu li.active a {
color: #fff;
background: rgba(255,255,255,.15);
}
/* خط زیر آیتم فعال */
.travel-menu li.active::after {
content: "";
position: absolute;
bottom: -1px;
left: 17px;
right: 17px;
height: 3px;
background: #fff;
border-radius: 10px 10px 0 0;
}
/* =========================================================
ACTION
========================================================= */
.travel-navbar-actions {
display: flex;
align-items: center;
gap: 10px;
}
.travel-login {
display: flex;
align-items: center;
gap: 8px;
padding: 11px 18px;
color: #fff !important;
text-decoration: none !important;
border-radius: 10px;
background: rgba(255,255,255,.14);
border: 1px solid rgba(255,255,255,.25);
backdrop-filter: blur(8px);
font-size: 13px;
font-weight: 700;
transition: all .25s ease;
}
.travel-login:hover {
background: rgba(255,255,255,.23);
transform: translateY(-2px);
}
/* =========================================================
HERO CONTENT
========================================================= */
.travel-hero {
min-height: 465px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.travel-hero-content {
max-width: 800px;
margin: auto;
padding: 70px 20px 80px;
}
.travel-hero-label {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
border-radius: 50px;
background: rgba(255,255,255,.13);
border: 1px solid rgba(255,255,255,.2);
backdrop-filter: blur(8px);
font-size: 13px;
}
.travel-hero h1 {
margin: 20px 0 15px;
color: #fff;
font-size: 48px;
line-height: 1.45;
font-weight: 800;
text-shadow: 0 4px 20px rgba(0,0,0,.25);
}
.travel-hero h1 span {
color: #fff;
}
.travel-hero p {
max-width: 620px;
margin: 0 auto;
color: rgba(255,255,255,.88);
font-size: 16px;
line-height: 2;
}
/* =========================================================
HERO BUTTONS
========================================================= */
.travel-hero-buttons {
margin-top: 30px;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.hero-btn {
min-width: 160px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 13px 22px;
border-radius: 11px;
text-decoration: none !important;
font-size: 14px;
font-weight: 700;
transition: all .25s ease;
}
.hero-btn-primary {
color: #1268d8 !important;
background: #fff;
box-shadow: 0 10px 30px rgba(0,0,0,.18);
}
.hero-btn-primary:hover {
transform: translateY(-3px);
box-shadow: 0 14px 35px rgba(0,0,0,.25);
}
.hero-btn-outline {
color: #fff !important;
border: 1px solid rgba(255,255,255,.45);
background: rgba(255,255,255,.08);
backdrop-filter: blur(8px);
}
.hero-btn-outline:hover {
color: #1268d8 !important;
background: #fff;
transform: translateY(-3px);
}
/* =========================================================
MOBILE
========================================================= */
.travel-mobile-toggle {
display: none;
width: 42px;
height: 42px;
border: 1px solid rgba(255,255,255,.25);
border-radius: 10px;
background: rgba(255,255,255,.12);
color: #fff;
cursor: pointer;
}
.travel-mobile-menu {
display: none;
}
/* =========================================================
RESPONSIVE
========================================================= */
@media (max-width: 991px) {
.travel-menu {
display: none;
}
.travel-mobile-toggle {
display: flex;
align-items: center;
justify-content: center;
}
.travel-header {
min-height: 500px;
}
.travel-hero h1 {
font-size: 38px;
}
}
@media (max-width: 576px) {
.travel-navbar {
min-height: 72px;
}
.travel-logo-icon {
width: 42px;
height: 42px;
}
.travel-logo-content strong {
font-size: 14px;
}
.travel-logo-content small {
display: none;
}
.travel-login {
padding: 9px 11px;
font-size: 12px;
}
.travel-login i {
display: none;
}
.travel-hero {
min-height: 420px;
}
.travel-hero-content {
padding: 50px 15px;
}
.travel-hero h1 {
font-size: 30px;
line-height: 1.6;
}
.travel-hero p {
font-size: 13px;
}
.travel-hero-buttons {
flex-direction: column;
}
.hero-btn {
width: 100%;
max-width: 260px;
}
}
+28
View File
@@ -359,3 +359,31 @@ $('.mobile-picker').each(function(i, item){
});
}
});
document.addEventListener('DOMContentLoaded', function () {
const menuButton = document.querySelector('.mobile-menu-toggle');
const mobileNavigation = document.querySelector('.mobile-navigation');
if (!menuButton || !mobileNavigation) {
return;
}
menuButton.addEventListener('click', function () {
const isOpen = mobileNavigation.style.display === 'block';
mobileNavigation.style.display = isOpen ? 'none' : 'block';
const icon = menuButton.querySelector('i');
if (icon) {
icon.className = isOpen
? 'fa fa-bars'
: 'fa fa-times';
}
});
});
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+601
View File
@@ -0,0 +1,601 @@
/*!
* Bootstrap Reboot v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
line-height: inherit;
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type=search]::-webkit-search-cancel-button {
cursor: pointer;
filter: grayscale(1);
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,598 @@
/*!
* Bootstrap Reboot v5.3.8 (https://getbootstrap.com/)
* Copyright 2011-2025 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
line-height: inherit;
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type=search]::-webkit-search-cancel-button {
cursor: pointer;
filter: grayscale(1);
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
<div>
<!-- Simplicity is the ultimate sophistication. - Leonardo da Vinci -->
</div>
+81 -2
View File
@@ -1,3 +1,82 @@
<div>
<!-- Knowing is not enough; we must apply. Being willing is not enough; we must do. - Leonardo da Vinci -->
@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-3">
<div class="theme-search-results-item">
<ul>
<li>
<a href="{{ url('/account') }}">
داشبورد
</a>
</li>
<li>
<a href="{{ url('/account/bookings') }}">
رزروهای من
</a>
</li>
<li>
<a href="{{ url('/account/favorites') }}">
علاقه‌مندی‌ها
</a>
</li>
<li>
<a href="{{ url('/account/comments') }}">
نظرات
</a>
</li>
<li>
<a href="{{ url('/account/edit-profile') }}">
ویرایش پروفایل
</a>
</li>
</ul>
</div>
</div>
<div class="col-md-9">
<h3>
خوش آمدید
</h3>
<p>
از این بخش می‌توانید رزروها و اطلاعات حساب خود را مدیریت کنید.
</p>
</div>
</div>
</div>
</div>
@endsection
@@ -1,3 +0,0 @@
<div>
<!-- Very little is needed to make a happy life. - Marcus Aurelius -->
</div>
+81 -2
View File
@@ -1,3 +1,82 @@
<div>
<!-- Because you are alive, everything is possible. - Thich Nhat Hanh -->
@extends('admin.layouts.app')
@section('title', 'مدیریت نظرات')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0">مدیریت نظرات</h4>
<span class="badge text-bg-primary">{{ $comments->total() }} نظر</span>
</div>
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="بستن"></button>
</div>
@endif
<div class="card shadow-sm">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>#</th>
<th>کاربر</th>
<th>مرتبط با</th>
<th>متن نظر</th>
<th>وضعیت</th>
<th>تاریخ</th>
<th class="text-center">عملیات</th>
</tr>
</thead>
<tbody>
@forelse ($comments as $comment)
<tr>
<td>{{ $comments->firstItem() + $loop->index }}</td>
<td>{{ $comment->user?->name ?? 'کاربر حذف‌شده' }}</td>
<td>
<span
class="d-block text-muted small">{{ class_basename($comment->commentable_type) }}</span>
<span class="small">شناسه: {{ $comment->commentable_id }}</span>
</td>
<td class="text-truncate" style="max-width: 250px;">
{{ \Illuminate\Support\Str::limit($comment->body, 60) }}
</td>
<td>
@include('admin.comments.status', ['status' => $comment->status])
</td>
<td class="small text-muted">{{ $comment->created_at->format('Y/m/d') }}</td>
<td class="text-center">
<div class="btn-group btn-group-sm" role="group">
<a href="{{ route('admin.comments.show', $comment) }}"
class="btn btn-outline-secondary" title="نمایش">نمایش</a>
<a href="{{ route('admin.comments.edit', $comment) }}"
class="btn btn-outline-primary" title="ویرایش">ویرایش</a>
<form action="{{ route('admin.comments.destroy', $comment) }}" method="POST"
class="d-inline"
onsubmit="return confirm('نظر حذف شود؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-outline-danger" title="حذف">حذف</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="text-center text-muted py-4">هنوز نظری ثبت نشده است.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="mt-3">
{{ $comments->links() }}
</div>
</div>
@endsection
+50 -2
View File
@@ -1,3 +1,51 @@
<div>
<!-- Knowing is not enough; we must apply. Being willing is not enough; we must do. - Leonardo da Vinci -->
@extends('admin.layouts.app')
@section('title', 'جزئیات نظر')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0">جزئیات نظر #{{ $comment->id }}</h4>
<a href="{{ route('admin.comments.index') }}" class="btn btn-outline-secondary btn-sm">بازگشت</a>
</div>
<div class="card shadow-sm">
<div class="card-body">
<dl class="row mb-0">
<dt class="col-sm-3">کاربر</dt>
<dd class="col-sm-9">
{{ $comment->user?->name ?? 'کاربر حذف‌شده' }}
<span class="text-muted small">({{ $comment->user?->email ?? '—' }})</span>
</dd>
<dt class="col-sm-3">مرتبط با</dt>
<dd class="col-sm-9">
{{ class_basename($comment->commentable_type) }}
<span class="text-muted small">(شناسه: {{ $comment->commentable_id }})</span>
</dd>
<dt class="col-sm-3">وضعیت</dt>
<dd class="col-sm-9">@include('admin.comments.status', ['status' => $comment->status])</dd>
<dt class="col-sm-3">تاریخ ثبت</dt>
<dd class="col-sm-9">{{ $comment->created_at->format('Y/m/d H:i') }}</dd>
<dt class="col-sm-3">متن نظر</dt>
<dd class="col-sm-9">
<div class="p-3 bg-light rounded" style="white-space: pre-wrap;">{{ $comment->body }}</div>
</dd>
</dl>
</div>
<div class="card-footer bg-white">
<a href="{{ route('admin.comments.edit', $comment) }}" class="btn btn-primary btn-sm">ویرایش</a>
<form action="{{ route('admin.comments.destroy', $comment) }}" method="POST" class="d-inline"
onsubmit="return confirm('نظر حذف شود؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">حذف</button>
</form>
</div>
</div>
</div>
@endsection
@@ -1,3 +1,58 @@
<div>
<!-- Let all your things have their places; let each part of your business have its time. - Benjamin Franklin -->
@extends('admin.layouts.app')
@section('title', 'لیست علاقه‌مندی‌ها')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h4 class="mb-0">علاقه‌مندی‌های کاربران</h4>
<span class="badge text-bg-info">{{ $favorites->total() }} مورد</span>
</div>
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<div class="card shadow-sm">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th>کاربر</th>
<th>نوع آیتم</th>
<th>شناسه آیتم</th>
<th>تاریخ ثبت</th>
<th class="text-center">عملیات</th>
</tr>
</thead>
<tbody>
@forelse ($favorites as $favorite)
<tr>
<td>{{ $favorite->user?->name ?? 'نامشخص' }}</td>
<td>
<span
class="badge text-bg-secondary">{{ class_basename($favorite->favoritable_type) }}</span>
</td>
<td>{{ $favorite->favoritable_id }}</td>
<td class="text-muted small">{{ $favorite->created_at->format('Y/m/d') }}</td>
<td class="text-center">
<div class="btn-group btn-group-sm">
<a href="{{ route('admin.favorites.show', $favorite) }}" class="btn btn-outline-info">نمایش</a>
<form action="{{ route('admin.favorites.destroy', $favorite) }}" method="POST"
onsubmit="return confirm('حذف شود؟')">
@csrf @method('DELETE')
<button class="btn btn-outline-danger">حذف</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center">موردی یافت نشد.</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-3">{{ $favorites->links() }}</div>
</div>
@endsection
+23 -2
View File
@@ -1,3 +1,24 @@
<div>
<!-- If you do not have a consistent goal in life, you can not live it in a consistent way. - Marcus Aurelius -->
@extends('admin.layouts.app')
@section('title', 'جزئیات علاقه‌مندی')
@section('content')
<div class="container-fluid py-4">
<div class="card shadow-sm">
<div class="card-header bg-white">جزئیات علاقه‌مندی #{{ $favorite->id }}</div>
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item"><strong>کاربر:</strong> {{ $favorite->user?->name }}</li>
<li class="list-group-item"><strong>مدل:</strong> {{ $favorite->favoritable_type }}</li>
<li class="list-group-item"><strong>شناسه مدل:</strong> {{ $favorite->favoritable_id }}</li>
<li class="list-group-item"><strong>تاریخ
ثبت:</strong> {{ $favorite->created_at->format('Y/m/d H:i') }}</li>
</ul>
</div>
<div class="card-footer">
<a href="{{ route('admin.favorites.index') }}" class="btn btn-secondary">بازگشت</a>
</div>
</div>
</div>
@endsection
@@ -15,6 +15,7 @@
{{-- Bootstrap --}}
<link rel="stylesheet"
href="{{ asset('assets/css/bootstrap.css') }}">
{{-- href="{{ asset('assets/plugins/bootstrap/css/bootstrap.css') }}">--}}
{{-- Font Awesome --}}
<link rel="stylesheet"
@@ -207,6 +208,7 @@
{{-- Bootstrap --}}
<script src="{{ asset('assets/js/bootstrap.js') }}"></script>
<script src="{{ asset('assets/plugins/bootstrap/js/bootstrap.min.js') }}"></script>
{{-- Main JS --}}
<script src="{{ asset('assets/js/custom.js') }}"></script>
+7 -362
View File
@@ -130,16 +130,16 @@
</div>
<a href="{{ route('admin.payments.index') }}"
class="{{ request()->routeIs('admin.payments.*') ? 'active' : '' }}">
{{-- <a href="{{ route('admin.payments.index') }}"--}}
{{-- class="{{ request()->routeIs('admin.payments.*') ? 'active' : '' }}">--}}
<i class="fa fa-credit-card"></i>
{{-- <i class="fa fa-credit-card"></i>--}}
<span>
پرداخت‌ها
</span>
{{-- <span>--}}
{{-- پرداخت‌ها--}}
{{-- </span>--}}
</a>
{{-- </a>--}}
<div class="admin-menu-title">
@@ -206,358 +206,3 @@
</nav>
</aside>
{{--<aside class="app-sidebar sticky" id="sidebar">--}}
{{-- --}}{{-- Logo --}}
{{-- <div class="main-sidebar-header">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}"--}}
{{-- class="header-logo">--}}
{{-- <span class="text-primary fs-6 fw-bold">--}}
{{-- پنل مدیریت آژانس--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </div>--}}
{{-- <div class="main-sidebar">--}}
{{-- <nav class="main-menu-container">--}}
{{-- <ul class="main-menu">--}}
{{-- --}}{{-- Dashboard --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.dashboard.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar(['admin.dashboard.index']) }}">--}}
{{-- <svg xmlns="http://www.w3.org/2000/svg"--}}
{{-- class="side-menu__icon"--}}
{{-- width="1em"--}}
{{-- height="1em"--}}
{{-- viewBox="0 0 24 24"--}}
{{-- fill="none"--}}
{{-- stroke="currentColor"--}}
{{-- stroke-width="1.5">--}}
{{-- <path d="M3 11.5L12 4l9 7.5"/>--}}
{{-- <path d="M5 10v9h14v-9"/>--}}
{{-- <path d="M9 19v-5h6v5"/>--}}
{{-- </svg>--}}
{{-- <span class="side-menu__label">--}}
{{-- داشبورد--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- سفر و گردشگری --}}
{{-- <li class="slide__category">--}}
{{-- <span class="category-name">--}}
{{-- مدیریت سفر--}}
{{-- </span>--}}
{{-- </li>--}}
{{-- --}}{{-- Tours --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.tours.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.tours.index',--}}
{{-- 'admin.tours.create',--}}
{{-- 'admin.tours.show',--}}
{{-- 'admin.tours.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-map-pin-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت تورها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Travel Types --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.travelTypes.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.travelTypes.index',--}}
{{-- 'admin.travelTypes.create',--}}
{{-- 'admin.travelTypes.show',--}}
{{-- 'admin.travelTypes.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-route-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- انواع سفر--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Flights --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.flights.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.flights.index',--}}
{{-- 'admin.flights.create',--}}
{{-- 'admin.flights.show',--}}
{{-- 'admin.flights.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-flight-takeoff-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت پروازها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Airports --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.airports.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.airports.index',--}}
{{-- 'admin.airports.create',--}}
{{-- 'admin.airports.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-building-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت فرودگاه‌ها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Users --}}
{{-- <li class="slide__category">--}}
{{-- <span class="category-name">--}}
{{-- کاربران و تعاملات--}}
{{-- </span>--}}
{{-- </li>--}}
{{-- --}}{{-- Users --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.users.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.users.index',--}}
{{-- 'admin.users.show',--}}
{{-- 'admin.users.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-user-3-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت کاربران--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Comments --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.comments.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.comments.index',--}}
{{-- 'admin.comments.show',--}}
{{-- 'admin.comments.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-chat-3-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت نظرات--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Favorites --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.favorites.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.favorites.index',--}}
{{-- 'admin.favorites.show'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-heart-3-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- علاقه‌مندی‌ها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Financial --}}
{{-- <li class="slide__category">--}}
{{-- <span class="category-name">--}}
{{-- مالی--}}
{{-- </span>--}}
{{-- </li>--}}
{{-- --}}{{-- Payments --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.payments.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.payments.index',--}}
{{-- 'admin.payments.show'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-bank-card-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت پرداخت‌ها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Content --}}
{{-- <li class="slide__category">--}}
{{-- <span class="category-name">--}}
{{-- محتوا--}}
{{-- </span>--}}
{{-- </li>--}}
{{-- --}}{{-- Sliders --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.sliders.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.sliders.index',--}}
{{-- 'admin.sliders.create',--}}
{{-- 'admin.sliders.show',--}}
{{-- 'admin.sliders.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-slideshow-3-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت اسلایدرها--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- System --}}
{{-- <li class="slide__category">--}}
{{-- <span class="category-name">--}}
{{-- سیستم--}}
{{-- </span>--}}
{{-- </li>--}}
{{-- --}}{{-- Admins --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.auth.login.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.admins.index',--}}
{{-- 'admin.admins.create',--}}
{{-- 'admin.admins.edit'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-admin-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- مدیریت مدیران--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- --}}{{-- Settings --}}
{{-- <li class="slide">--}}
{{-- <a href="{{ route('admin.settings.index') }}"--}}
{{-- class="side-menu__item--}}
{{-- {{ ActiveAdminSidebar([--}}
{{-- 'admin.settings.index'--}}
{{-- ]) }}">--}}
{{-- <i class="ri-settings-3-line side-menu__icon"></i>--}}
{{-- <span class="side-menu__label">--}}
{{-- تنظیمات--}}
{{-- </span>--}}
{{-- </a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </nav>--}}
{{-- </div>--}}
{{--</aside>--}}
+157 -1
View File
@@ -1,3 +1,159 @@
@extends('admin.layouts.app')
@section('title', 'تنظیمات سایت')
@section('content')
<div class="container-fluid py-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<!-- Because you are alive, everything is possible. - Thich Nhat Hanh -->
<h4 class="mb-0">تنظیمات سایت</h4>
<span class="text-muted small">مقادیر زیر در سراسر سایت (هدر، فوتر، بخش تماس) استفاده می‌شوند</span>
</div>
</div>
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="بستن"></button>
</div>
@endif
<form action="{{ route('admin.settings.update') }}" method="POST">
@csrf
{{-- گروه: اطلاعات عمومی --}}
<div class="card shadow-sm mb-4">
<div class="card-header bg-white fw-semibold">
<i class="bi bi-globe2 me-1"></i> اطلاعات عمومی
</div>
<div class="card-body row g-3">
<div class="col-md-6">
<label for="site_name" class="form-label">نام سایت *</label>
<input type="text" name="site_name" id="site_name"
class="form-control @error('site_name') is-invalid @enderror"
value="{{ old('site_name', $settings->where('code', 'site_name')->first()?->value) }}">
@error('site_name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="site_slogan" class="form-label">شعار سایت</label>
<input type="text" name="site_slogan" id="site_slogan"
class="form-control @error('site_slogan') is-invalid @enderror"
value="{{ old('site_slogan', $settings->where('code', 'site_slogan')->first()?->value) }}">
@error('site_slogan')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-12">
<label for="site_description" class="form-label">توضیحات کوتاه سایت</label>
<textarea name="site_description" id="site_description" rows="2"
class="form-control @error('site_description') is-invalid @enderror">{{ old('site_description', $settings->where('code', 'site_description')->first()?->value) }}</textarea>
@error('site_description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
{{-- گروه: راه‌های ارتباطی --}}
<div class="card shadow-sm mb-4">
<div class="card-header bg-white fw-semibold">
<i class="bi bi-telephone me-1"></i> راه‌های ارتباطی
</div>
<div class="card-body row g-3">
<div class="col-md-6">
<label for="contact_email" class="form-label">ایمیل تماس</label>
<input type="email" name="contact_email" id="contact_email"
class="form-control @error('contact_email') is-invalid @enderror"
value="{{ old('contact_email', $settings->where('code', 'contact_email')->first()?->value) }}">
@error('contact_email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="contact_phone" class="form-label">تلفن / موبایل</label>
<input type="text" name="contact_phone" id="contact_phone"
class="form-control @error('contact_phone') is-invalid @enderror"
value="{{ old('contact_phone', $settings->where('code', 'contact_phone')->first()?->value) }}">
@error('contact_phone')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-12">
<label for="contact_address" class="form-label">آدرس</label>
<input type="text" name="contact_address" id="contact_address"
class="form-control @error('contact_address') is-invalid @enderror"
value="{{ old('contact_address', $settings->where('code', 'contact_address')->first()?->value) }}">
@error('contact_address')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
{{-- گروه: شبکه‌های اجتماعی --}}
<div class="card shadow-sm mb-4">
<div class="card-header bg-white fw-semibold">
<i class="bi bi-share me-1"></i> شبکه‌های اجتماعی
</div>
<div class="card-body row g-3">
<div class="col-md-6">
<label for="instagram" class="form-label">اینستاگرام</label>
<input type="url" name="instagram" id="instagram"
class="form-control @error('instagram') is-invalid @enderror"
value="{{ old('instagram', $settings->where('code', 'instagram')->first()?->value) }}"
placeholder="https://instagram.com/...">
@error('instagram')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="col-md-6">
<label for="telegram" class="form-label">تلگرام</label>
<input type="url" name="telegram" id="telegram"
class="form-control @error('telegram') is-invalid @enderror"
value="{{ old('telegram', $settings->where('code', 'telegram')->first()?->value) }}"
placeholder="https://t.me/...">
@error('telegram')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
{{-- گروه: فوتر --}}
<div class="card shadow-sm mb-4">
<div class="card-header bg-white fw-semibold">
<i class="bi bi-file-earmark-text me-1"></i> فوتر
</div>
<div class="card-body">
<label for="copyright_text" class="form-label">متن کپی‌رایت</label>
<textarea name="copyright_text" id="copyright_text" rows="2"
class="form-control @error('copyright_text') is-invalid @enderror">{{ old('copyright_text', $settings->where('code', 'copyright_text')->first()?->value) }}</textarea>
@error('copyright_text')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-lg"></i> ذخیره تنظیمات
</button>
<a href="{{ route('admin.dashboard.index') }}" class="btn btn-light">انصراف</a>
</div>
</form>
</div>
@endsection
+39 -37
View File
@@ -2,61 +2,63 @@
@section('content')
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">ثبت تور جدید</h4>
<div class="d-flex justify-content-between align-items-center mb-3">
<h2>افزودن تور جدید</h2>
<a href="{{ route('admin.tours.index') }}" class="btn btn-secondary">بازگشت</a>
</div>
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="card shadow">
<div class="card-body">
<form action="{{ route('admin.tours.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="mb-3">
<label class="form-label">عنوان تور</label>
<input type="text" name="title"
<div class="row">
{{-- تصویر --}}
<div class="col-md-4 mb-3">
<label for="image" class="form-label">تصویر تور</label>
<input type="file" name="image" id="image"
class="form-control @error('image') is-invalid @enderror">
@error('image')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
{{-- عنوان --}}
<div class="col-md-4 mb-3">
<label for="title" class="form-label">عنوان تور</label>
<input type="text" name="title" id="title"
class="form-control @error('title') is-invalid @enderror"
value="{{ old('title') }}">
@error('title')
<div class="invalid-feedback">{{ $message }}</div> @enderror
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label class="form-label">توضیحات</label>
<textarea name="description"
class="form-control @error('description') is-invalid @enderror"
rows="4">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">قیمت</label>
<input type="number" name="price"
{{-- قیمت --}}
<div class="col-md-4 mb-3">
<label for="price" class="form-label">قیمت (تومان)</label>
<input type="number" name="price" id="price" step="1000" min="0"
class="form-control @error('price') is-invalid @enderror"
value="{{ old('price') }}">
@error('price')
<div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="col-md-6 mb-3">
<label class="form-label">تصویر تور</label>
<input type="file" name="image"
class="form-control @error('image') is-invalid @enderror">
@error('image')
<div class="invalid-feedback">{{ $message }}</div> @enderror
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
<div class="mt-4 d-flex justify-content-between">
<a href="{{ route('admin.tours.index') }}" class="btn btn-secondary">انصراف</a>
<button type="submit" class="btn btn-success">ذخیره تور</button>
</div>
<button type="submit" class="btn btn-primary">ذخیره تور</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
+190
View File
@@ -0,0 +1,190 @@
@extends('layouts.app')
@section('title', 'ورود | آژانس مسافرتی')
@section('content')
<div class="auth-page">
<div class="container">
<div class="auth-card login-card">
{{-- عنوان --}}
<div class="auth-header">
<div class="auth-icon">
<i class="fa fa-sign-in"></i>
</div>
<h1>
ورود به حساب کاربری
</h1>
<p>
برای ورود، نام کاربری یا ایمیل و رمز عبور خود را وارد کنید.
</p>
</div>
{{-- خطاها --}}
@if($errors->any())
<div class="auth-alert auth-alert-danger">
<i class="fa fa-exclamation-circle"></i>
<div>
<strong>
ورود انجام نشد.
</strong>
<ul>
@foreach($errors->all() as $error)
<li>
{{ $error }}
</li>
@endforeach
</ul>
</div>
</div>
@endif
{{-- پیام موفقیت --}}
@if(session('success'))
<div class="auth-alert auth-alert-success">
<i class="fa fa-check-circle"></i>
{{ session('success') }}
</div>
@endif
{{-- فرم --}}
<form
action="{{ route('auth.login.post') }}"
method="POST"
class="auth-form"
>
@csrf
<div class="form-group">
<label for="login">
ایمیل یا نام کاربری
</label>
<input
type="text"
id="login"
name="login"
value="{{ old('login') }}"
class="form-control"
placeholder="ایمیل یا نام کاربری"
dir="ltr"
autocomplete="username"
required
>
</div>
<div class="form-group">
<label for="password">
رمز عبور
</label>
<input
type="password"
id="password"
name="password"
class="form-control"
placeholder="رمز عبور"
autocomplete="current-password"
required
>
</div>
{{-- مرا به خاطر بسپار --}}
<div class="login-options">
<label class="remember-me">
<input
type="checkbox"
name="remember"
value="1"
{{ old('remember') ? 'checked' : '' }}
>
<span>
مرا به خاطر بسپار
</span>
</label>
</div>
{{-- دکمه --}}
<button
type="submit"
class="auth-btn"
>
<i class="fa fa-sign-in"></i>
ورود به حساب
</button>
</form>
{{-- ثبت نام --}}
<div class="auth-footer">
حساب کاربری ندارید؟
<a href="{{ route('auth.register.index') }}">
ثبت‌نام کنید
</a>
</div>
</div>
</div>
</div>
@endsection
+659
View File
@@ -0,0 +1,659 @@
@extends('layouts.app')
@section('title', 'ثبت نام | آژانس مسافرتی')
@section('content')
<div class="auth-page">
<div class="container">
<div class="auth-card register-card">
{{-- =========================================
عنوان
========================================== --}}
<div class="auth-header">
<div class="auth-icon">
<i class="fa fa-user-plus"></i>
</div>
<h1>
ایجاد حساب کاربری
</h1>
<p>
برای استفاده از امکانات سایت، اطلاعات خود را وارد کنید.
</p>
</div>
{{-- =========================================
خطاهای کلی
========================================== --}}
@if($errors->any())
<div class="auth-alert auth-alert-danger">
<i class="fa fa-exclamation-circle"></i>
<div>
<strong>
لطفاً خطاهای زیر را بررسی کنید:
</strong>
<ul>
@foreach($errors->all() as $error)
<li>
{{ $error }}
</li>
@endforeach
</ul>
</div>
</div>
@endif
{{-- =========================================
فرم ثبت نام
========================================== --}}
<form
action="{{ route('auth.register.post') }}"
method="POST"
enctype="multipart/form-data"
class="auth-form"
>
@csrf
{{-- =====================================
اطلاعات شخصی
====================================== --}}
<div class="form-section">
<div class="form-section-title">
<i class="fa fa-user"></i>
اطلاعات شخصی
</div>
<div class="row">
{{-- نام --}}
<div class="col-md-6">
<div class="form-group">
<label for="first_name">
نام
<span>*</span>
</label>
<input
type="text"
id="first_name"
name="first_name"
value="{{ old('first_name') }}"
class="form-control"
placeholder="نام خود را وارد کنید"
maxlength="100"
required
>
</div>
</div>
{{-- نام خانوادگی --}}
<div class="col-md-6">
<div class="form-group">
<label for="last_name">
نام خانوادگی
<span>*</span>
</label>
<input
type="text"
id="last_name"
name="last_name"
value="{{ old('last_name') }}"
class="form-control"
placeholder="نام خانوادگی خود را وارد کنید"
maxlength="100"
required
>
</div>
</div>
{{-- کد ملی --}}
<div class="col-md-6">
<div class="form-group">
<label for="national_code">
کد ملی
<span>*</span>
</label>
<input
type="text"
id="national_code"
name="national_code"
value="{{ old('national_code') }}"
class="form-control"
placeholder="مثلاً 0012345678"
maxlength="10"
inputmode="numeric"
required
>
</div>
</div>
{{-- جنسیت --}}
<div class="col-md-6">
<div class="form-group">
<label for="gender">
جنسیت
<span>*</span>
</label>
<select
id="gender"
name="gender"
class="form-control"
required
>
<option value="">
انتخاب کنید
</option>
<option
value="1"
{{ old('gender') == 1 ? 'selected' : '' }}
>
مرد
</option>
<option
value="2"
{{ old('gender') == 2 ? 'selected' : '' }}
>
زن
</option>
</select>
</div>
</div>
{{-- وضعیت تأهل --}}
<div class="col-md-6">
<div class="form-group">
<label for="marital_status">
وضعیت تأهل
<span>*</span>
</label>
<select
id="marital_status"
name="marital_status"
class="form-control"
required
>
<option value="">
انتخاب کنید
</option>
<option
value="1"
{{ old('marital_status') == 1 ? 'selected' : '' }}
>
مجرد
</option>
<option
value="2"
{{ old('marital_status') == 2 ? 'selected' : '' }}
>
متأهل
</option>
<option
value="3"
{{ old('marital_status') == 3 ? 'selected' : '' }}
>
متارکه
</option>
</select>
</div>
</div>
{{-- نام همسر --}}
<div class="col-md-6">
<div class="form-group">
<label for="spouse_name">
نام و نام خانوادگی همسر
</label>
<input
type="text"
id="spouse_name"
name="spouse_name"
value="{{ old('spouse_name') }}"
class="form-control"
placeholder="در صورت تأهل وارد کنید"
maxlength="200"
>
</div>
</div>
</div>
</div>
{{-- =====================================
اطلاعات تماس
====================================== --}}
<div class="form-section">
<div class="form-section-title">
<i class="fa fa-phone"></i>
اطلاعات تماس
</div>
<div class="row">
{{-- موبایل --}}
<div class="col-md-6">
<div class="form-group">
<label for="mobile">
شماره همراه
<span>*</span>
</label>
<input
type="text"
id="mobile"
name="mobile"
value="{{ old('mobile') }}"
class="form-control"
placeholder="09123456789"
maxlength="11"
inputmode="numeric"
required
>
</div>
</div>
{{-- ایمیل --}}
<div class="col-md-6">
<div class="form-group">
<label for="email">
ایمیل
<span>*</span>
</label>
<input
type="email"
id="email"
name="email"
value="{{ old('email') }}"
class="form-control"
placeholder="example@email.com"
maxlength="150"
dir="ltr"
required
>
</div>
</div>
</div>
</div>
{{-- =====================================
اطلاعات حساب
====================================== --}}
<div class="form-section">
<div class="form-section-title">
<i class="fa fa-lock"></i>
اطلاعات حساب کاربری
</div>
<div class="row">
{{-- نام کاربری --}}
<div class="col-md-6">
<div class="form-group">
<label for="username">
نام کاربری
<span>*</span>
</label>
<input
type="text"
id="username"
name="username"
value="{{ old('username') }}"
class="form-control"
placeholder="مثلاً ali123"
maxlength="100"
dir="ltr"
pattern="[A-Za-z0-9]+"
required
>
<small class="form-help">
فقط حروف انگلیسی و اعداد مجاز است.
</small>
</div>
</div>
{{-- رمز --}}
<div class="col-md-6">
<div class="form-group">
<label for="password">
رمز عبور
<span>*</span>
</label>
<input
type="password"
id="password"
name="password"
class="form-control"
placeholder="رمز عبور"
minlength="8"
required
>
</div>
</div>
{{-- تکرار رمز --}}
<div class="col-md-6">
<div class="form-group">
<label for="password_confirmation">
تکرار رمز عبور
</label>
<input
type="password"
id="password_confirmation"
name="password_confirmation"
class="form-control"
placeholder="تکرار رمز عبور"
minlength="8"
>
</div>
</div>
</div>
</div>
{{-- =====================================
استان و شهرستان
====================================== --}}
<div class="form-section">
<div class="form-section-title">
<i class="fa fa-map-marker"></i>
محل سکونت
</div>
<div class="row">
{{-- استان --}}
<div class="col-md-6">
<div class="form-group">
<label for="province_id">
استان
</label>
<select
name="province_id"
id="province_id"
class="form-control"
>
<option value="">
انتخاب استان
</option>
@if(isset($provinces))
@foreach($provinces as $province)
<option
value="{{ $province->id }}"
{{ old('province_id') == $province->id ? 'selected' : '' }}
>
{{ $province->name }}
</option>
@endforeach
@endif
</select>
</div>
</div>
{{-- شهرستان --}}
<div class="col-md-6">
<div class="form-group">
<label for="city_id">
شهرستان
</label>
<select
name="city_id"
id="city_id"
class="form-control"
>
<option value="">
ابتدا استان را انتخاب کنید
</option>
</select>
</div>
</div>
</div>
</div>
{{-- =====================================
عکس
====================================== --}}
<div class="form-section">
<div class="form-section-title">
<i class="fa fa-image"></i>
تصویر پروفایل
</div>
<div class="form-group">
<label for="image">
عکس
</label>
<input
type="file"
id="image"
name="image"
class="form-control"
accept="image/jpeg,image/png,image/jpg"
>
<small class="form-help">
فرمت‌های مجاز:
JPG ، JPEG ، PNG
<br>
حداکثر حجم:
800 کیلوبایت
</small>
</div>
</div>
{{-- =====================================
دکمه ثبت
====================================== --}}
<div class="auth-submit">
<button
type="submit"
class="auth-btn"
>
<i class="fa fa-user-plus"></i>
ایجاد حساب کاربری
</button>
</div>
</form>
{{-- =====================================
ورود
====================================== --}}
<div class="auth-footer">
قبلاً حساب ساخته‌اید؟
<a href="{{ route('auth.login.index') }}">
وارد شوید
</a>
</div>
</div>
</div>
</div>
@endsection
+202
View File
@@ -0,0 +1,202 @@
@extends('layouts.app')
@section('content')
<div class="container" style="padding: 50px 0;">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3>
رزرو پرواز
</h3>
</div>
<div class="panel-body">
{{-- اطلاعات پرواز --}}
<div class="flight-booking-info">
<h3>
{{ $flight->title }}
</h3>
<hr>
<p>
<strong>
شماره پرواز:
</strong>
{{ $flight->flight_number ?? '-' }}
</p>
<p>
<strong>
مبدا:
</strong>
{{ $flight->origin->name ?? $flight->origin ?? '-' }}
</p>
<p>
<strong>
مقصد:
</strong>
{{ $flight->destination->name ?? $flight->destination ?? '-' }}
</p>
<p>
<strong>
تاریخ حرکت:
</strong>
{{ $flight->departure_date ?? '-' }}
</p>
<p>
<strong>
قیمت:
</strong>
{{ number_format($flight->price ?? 0) }}
تومان
</p>
</div>
<hr>
{{-- فرم رزرو --}}
<form
action="{{ route('booking.flight.store', $flight) }}"
method="POST"
>
@csrf
<div class="form-group">
<label>
نام مسافر
</label>
<input
type="text"
name="first_name"
class="form-control"
value="{{ old('first_name') }}"
required
>
</div>
<div class="form-group">
<label>
نام خانوادگی
</label>
<input
type="text"
name="last_name"
class="form-control"
value="{{ old('last_name') }}"
required
>
</div>
<div class="form-group">
<label>
کد ملی
</label>
<input
type="text"
name="national_code"
class="form-control"
value="{{ old('national_code') }}"
required
>
</div>
<div class="form-group">
<label>
شماره موبایل
</label>
<input
type="text"
name="phone"
class="form-control"
value="{{ old('phone') }}"
required
>
</div>
<div class="form-group">
<label>
تعداد مسافر
</label>
<input
type="number"
name="passengers"
class="form-control"
value="{{ old('passengers', 1) }}"
min="1"
max="10"
required
>
</div>
<button
type="submit"
class="btn btn-success btn-lg"
>
ثبت رزرو
</button>
<a
href="{{ route('flights.show', $flight) }}"
class="btn btn-default btn-lg"
>
بازگشت
</a>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
File diff suppressed because it is too large Load Diff
+147 -3
View File
@@ -1,33 +1,50 @@
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>قالب رزرواسیون</title>
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', 'آژانس مسافرتی')</title>
{{-- Google Fonts --}}
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,700" rel="stylesheet">
{{-- Template CSS --}}
<link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/custom.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/auth.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">
{{-- صفحه‌هایی که CSS اختصاصی دارند --}}
@stack('styles')
</head>
<body>
{{-- Header --}}
@include('layouts.header')
{{-- Navbar --}}
@include('layouts.navbar')
{{-- محتوای اصلی هر صفحه --}}
@yield('content')
{{-- Footer --}}
@include('layouts.footer')
{{-- Template JavaScript --}}
<script src="{{ asset('assets/js/jquery.js') }}"></script>
<script src="{{ asset('assets/js/moment.js') }}"></script>
<script src="{{ asset('assets/js/bootstrap.js') }}"></script>
<script src="{{ asset('assets/js/owl-carousel.js') }}"></script>
<script src="{{ asset('assets/js/blur-area.js') }}"></script>
<script src="{{ asset('assets/js/icheck.js') }}"></script>
@@ -46,10 +63,137 @@
<script src="{{ asset('assets/js/youtube-bg.js') }}"></script>
<script src="{{ asset('assets/js/custom.js') }}"></script>
</body>
@stack('scripts')
</body>
</html>
{{-- resources/views/layouts/app.blade.php --}}
{{-- <!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{-- <meta name="csrf-token" content="{{ csrf_token() }}">--}}
{{-- <title>@yield('title', 'آژانس مسافرتی')</title>--}}
{{-- @vite(['resources/css/app.css', 'resources/js/app.js'])--}}
{{-- @stack('styles')--}}
{{--</head>--}}
{{--<body>--}}
{{-- ===== ناوبری بالا ===== --}}
{{--<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">--}}
{{-- <div class="container">--}}
{{-- <a class="navbar-brand" href="{{ route('home') }}">آژانس پرواز</a>--}}
{{-- <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav">--}}
{{-- <span class="navbar-toggler-icon"></span>--}}
{{-- </button>--}}
{{-- <div class="collapse navbar-collapse" id="mainNav">--}}
{{-- <ul class="navbar-nav ms-auto">--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('tours.index') }}">تورها</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('flights.index') }}">پروازها</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('about') }}">درباره ما</a></li>--}}
{{-- <li class="nav-item"><a class="nav-link" href="{{ route('contact') }}">تماس با ما</a></li>--}}
{{-- </ul>--}}
{{-- --}}{{-- منوی کاربر --}}
{{-- <ul class="navbar-nav ms-auto">--}}
{{-- @auth--}}
{{-- <li class="nav-item dropdown">--}}
{{-- <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown">--}}
{{-- {{ Auth::user()->name }}--}}
{{-- </a>--}}
{{-- <ul class="dropdown-menu dropdown-menu-end">--}}
{{-- <li><a class="dropdown-item" href="{{ route('dashboard') }}">پیشخوان</a></li>--}}
{{-- <li><a class="dropdown-item" href="{{ route('account.bookings') }}">رزروهای من</a></li>--}}
{{-- <li><a class="dropdown-item" href="{{ route('account.favorites') }}">علاقه‌مندی‌ها</a></li>--}}
{{-- <li><hr class="dropdown-divider"></li>--}}
{{-- <li>--}}
{{-- <form method="POST" action="{{ route('logout') }}">--}}
{{-- @csrf--}}
{{-- <button class="dropdown-item" type="submit">خروج</button>--}}
{{-- </form>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- @else--}}
{{-- <a href="{{ route('login') }}" class="btn btn-outline-light me-2">ورود</a>--}}
{{-- <a href="{{ route('register') }}" class="btn btn-primary">ثبت‌نام</a>--}}
{{-- @endauth--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</nav>--}}
{{-- ===== محتوای صفحه ===== --}}
{{--<main class="py-5 mt-5">--}}
{{-- @yield('content')--}}
{{--</main>--}}
{{-- ===== فوتر ===== --}}
{{--<footer class="bg-dark text-light py-4 mt-5">--}}
{{-- <div class="container text-center">--}}
{{-- <p class="mb-0">© {{ date('Y') }} — آژانس مسافرتی | تمامی حقوق محفوظ است</p>--}}
{{-- </div>--}}
{{--</footer>--}}
{{--@stack('scripts')--}}
{{--</body>--}}
{{--</html>--}}
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
{{-- <meta charset="UTF-8">--}}
{{-- <meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{-- <title>قالب رزرواسیون</title>--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">--}}
{{-- <link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">--}}
{{--</head>--}}
{{--<body>--}}
{{--@include('layouts.header')--}}
{{--@include('layouts.navbar')--}}
{{--@yield('content')--}}
{{--@include('layouts.footer')--}}
{{--<script src="{{ asset('assets/js/jquery.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/moment.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/bootstrap.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/owl-carousel.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/blur-area.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/icheck.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/gmap.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/magnific-popup.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/ion-range-slider.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/sticky-kit.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/smooth-scroll.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/fotorama.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/bs-datepicker.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/typeahead.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/quantity-selector.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/countdown.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/window-scroll-action.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/fitvid.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/youtube-bg.js') }}"></script>--}}
{{--<script src="{{ asset('assets/js/custom.js') }}"></script>--}}
{{--</body>--}}
{{--</html>--}}
{{--<!DOCTYPE html>--}}
{{--<html lang="fa" dir="rtl">--}}
{{--<head>--}}
+362 -102
View File
@@ -1,151 +1,411 @@
<footer class="theme-footer">
<div class="theme-footer-area theme-footer-area-dark">
<div class="container-fluid">
<footer class="theme-footer" id="mainFooter">
<div class="row row-col-gap">
<div class="container _ph-mob-0">
<div class="col-md-4">
<div class="theme-footer-section theme-footer-">
<h5 class="theme-footer-section-title">سفر کنید</h5>
<div class="row row-eq-height row-mob-full" data-gutter="60">
<ul class="theme-footer-section-list">
<li>
<a href="#">کشورها</a>
</li>
<li>
<a href="#">مناطق</a>
</li>
<li>
<a href="#">شهرها</a>
</li>
<li>
<a href="#">نواحی</a>
</li>
<li>
<a href="#">فرودگاه ها</a>
</li>
<li>
<a href="#">هتل</a>
</li>
<li>
<a href="#">مکان های مورد علاقه</a>
</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="theme-footer-section theme-footer-">
<h5 class="theme-footer-section-title">کتاب</h5>
{{-- Logo --}}
<div class="col-md-3">
<ul class="theme-footer-section-list">
<li>
<a href="#">آپارتمان ها</a>
</li>
<li>
<a href="#">استراحتگاه ها</a>
</li>
<li>
<a href="#">ویلاها</a>
</li>
<li>
<a href="#">خوابگاه ها</a>
</li>
<li>
<a href="#">رستوران</a>
</li>
<li>
<a href="#">مهمانخانه</a>
</li>
<li>
<a href="#">هتل های زنجیره ای</a>
</li>
</ul>
</div>
</div>
<div class="theme-footer-section">
<div class="col-md-4">
<div class="theme-footer-section theme-footer-section-subscribe bg-grad _mt-mob-30">
<a
class="theme-footer-brand _mb-mob-30"
href="{{ url('/') }}">
<div class="theme-footer-section-subscribe-bg"
style="background-image:url('{{ asset('assets/img/footer/footer_subscribe_bg.png') }}');">
</div>
<img
src="{{ asset('img/logo-black.png') }}"
alt="آژانس مسافرتی">
<div class="theme-footer-section-subscribe-content">
</a>
<h5 class="theme-footer-section-title">
تا 50 درصد از سفر بعدی خود صرفه جویی کنید
</h5>
<div class="theme-footer-brand-text">
<p class="text-muted">
برای باز کردن قفل معاملات مخفی ما مشترک شوید
<p>
با ما بهترین مسیرها و پروازها را پیدا کنید.
</p>
<form>
<div class="form-group">
<input
class="form-control theme-footer-subscribe-form-control"
type="email"
placeholder="ایمیل خود را اینجا تایپ کنید">
</div>
<button
class="btn btn-primary-invert btn-shadow text-upcase theme-footer-subscribe-btn"
type="submit">
معاملات دریافت کنید
</button>
</form>
</div>
</div>
</div>
</div>
</div>
{{-- Links --}}
<div class="col-md-5">
<div class="row">
<div class="col-md-4">
<div class="theme-footer-section">
<h5 class="theme-footer-section-title">
آژانس
</h5>
<ul class="theme-footer-section-list">
<li>
<a href="{{ url('/about') }}">
درباره ما
</a>
</li>
<li>
<a href="{{ url('/contact') }}">
تماس با ما
</a>
</li>
<li>
<a href="{{ url('/faq') }}">
سوالات متداول
</a>
</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="theme-footer-section">
<h5 class="theme-footer-section-title">
پروازها
</h5>
<ul class="theme-footer-section-list">
<li>
<a href="{{ url('/flights') }}">
جستجوی پرواز
</a>
</li>
<li>
<a href="{{ url('/offers') }}">
پیشنهادهای ویژه
</a>
</li>
<li>
<a href="#">
مقصدهای محبوب
</a>
</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="theme-footer-section">
<h5 class="theme-footer-section-title">
حساب کاربری
</h5>
<ul class="theme-footer-section-list">
<li>
<a href="{{ url('/account') }}">
داشبورد
</a>
</li>
<li>
<a href="{{ url('/account/bookings') }}">
رزروهای من
</a>
</li>
<li>
<a href="{{ url('/account/favorites') }}">
علاقه‌مندی‌ها
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
{{-- Newsletter --}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-section-subscribe bg-grad">--}}
{{-- <div--}}
{{-- class="theme-footer-section-subscribe-bg"--}}
{{-- style="background-image:url('{{ asset('img/footer/footer_subscribe_bg.png') }}');">--}}
{{-- </div>--}}
{{-- <div class="theme-footer-section-subscribe-content">--}}
{{-- <h5 class="theme-footer-section-title">--}}
{{-- از پیشنهادهای ویژه باخبر شوید--}}
{{-- </h5>--}}
{{-- <p class="text-muted">--}}
{{-- ایمیل خود را وارد کنید تا پیشنهادهای ویژه را دریافت کنید.--}}
{{-- </p>--}}
{{-- <form>--}}
{{-- <div class="form-group">--}}
{{-- <input--}}
{{-- class="form-control theme-footer-subscribe-form-control"--}}
{{-- type="email"--}}
{{-- placeholder="ایمیل شما">--}}
{{-- </div>--}}
{{-- <button--}}
{{-- class="btn btn-primary-invert btn-shadow text-upcase theme-footer-subscribe-btn"--}}
{{-- type="submit">--}}
{{-- عضویت--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
</div>
</div>
</footer>
{{-- Copyright --}}
<div class="theme-copyright">
<div class="container-fluid">
<div class="container">
<div class="row">
<div class="col-md-6">
<p class="theme-copyright-text">
حق چاپ © 1400
<a href="#">Bookify</a>
. تمامی حقوق محفوظ است.
© {{ date('Y') }}
<a href="{{ url('/') }}">
آژانس مسافرتی
</a>
- تمامی حقوق محفوظ است.
</p>
</div>
<div class="col-md-6">
<ul class="theme-copyright-social">
<li>
<a class="fa fa-facebook" href="#"></a>
</li>
<li>
<a class="fa fa-google" href="#"></a>
</li>
<li>
<a class="fa fa-twitter" href="#"></a>
</li>
<li>
<a class="fa fa-youtube-play" href="#"></a>
</li>
<li>
<a class="fa fa-instagram" href="#"></a>
</li>
<li>
<a class="fa fa-youtube-play" href="#"></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</footer>
{{--<footer class="theme-footer">--}}
{{-- <div class="theme-footer-area theme-footer-area-dark">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="row row-col-gap">--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-">--}}
{{-- <h5 class="theme-footer-section-title">سفر کنید</h5>--}}
{{-- <ul class="theme-footer-section-list">--}}
{{-- <li>--}}
{{-- <a href="#">کشورها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مناطق</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">شهرها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">نواحی</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">فرودگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">هتل</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مکان های مورد علاقه</a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-">--}}
{{-- <h5 class="theme-footer-section-title">کتاب</h5>--}}
{{-- <ul class="theme-footer-section-list">--}}
{{-- <li>--}}
{{-- <a href="#">آپارتمان ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">استراحتگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">ویلاها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">خوابگاه ها</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">رستوران</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">مهمانخانه</a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a href="#">هتل های زنجیره ای</a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="col-md-4">--}}
{{-- <div class="theme-footer-section theme-footer-section-subscribe bg-grad _mt-mob-30">--}}
{{-- <div class="theme-footer-section-subscribe-bg"--}}
{{-- style="background-image:url('{{ asset('assets/img/footer/footer_subscribe_bg.png') }}');">--}}
{{-- </div>--}}
{{-- <div class="theme-footer-section-subscribe-content">--}}
{{-- <h5 class="theme-footer-section-title">--}}
{{-- تا 50 درصد از سفر بعدی خود صرفه جویی کنید--}}
{{-- </h5>--}}
{{-- <p class="text-muted">--}}
{{-- برای باز کردن قفل معاملات مخفی ما مشترک شوید--}}
{{-- </p>--}}
{{-- <form>--}}
{{-- <div class="form-group">--}}
{{-- <input--}}
{{-- class="form-control theme-footer-subscribe-form-control"--}}
{{-- type="email"--}}
{{-- placeholder="ایمیل خود را اینجا تایپ کنید">--}}
{{-- </div>--}}
{{-- <button--}}
{{-- class="btn btn-primary-invert btn-shadow text-upcase theme-footer-subscribe-btn"--}}
{{-- type="submit">--}}
{{-- معاملات دریافت کنید--}}
{{-- </button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <div class="theme-copyright">--}}
{{-- <div class="container-fluid">--}}
{{-- <div class="row">--}}
{{-- <div class="col-md-6">--}}
{{-- <p class="theme-copyright-text">--}}
{{-- حق چاپ © 1400--}}
{{-- <a href="#">Bookify</a>--}}
{{-- . تمامی حقوق محفوظ است.--}}
{{-- </p>--}}
{{-- </div>--}}
{{-- <div class="col-md-6">--}}
{{-- <ul class="theme-copyright-social">--}}
{{-- <li>--}}
{{-- <a class="fa fa-facebook" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-google" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-twitter" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-youtube-play" href="#"></a>--}}
{{-- </li>--}}
{{-- <li>--}}
{{-- <a class="fa fa-instagram" href="#"></a>--}}
{{-- </li>--}}
{{-- </ul>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{--</footer>--}}
+312 -8
View File
@@ -1,10 +1,314 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<header id="site-header" class="travel-header">
<title>@yield('title', 'Dornica')</title>
{{-- پس‌زمینه هدر / Hero --}}
<div class="travel-header-bg">
<link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">
<div
class="travel-header-bg-image"
style="background-image:url('{{ asset('assets/img/o14abktz5iy_1500x800.jpg') }}');">
</div>
<div class="travel-header-overlay"></div>
</div>
<div class="travel-header-content">
<div class="container">
{{-- ==============================
NAVBAR
=============================== --}}
<div class="travel-navbar">
{{-- لوگو --}}
<div class="travel-logo">
<a href="{{ url('/') }}">
<span class="travel-logo-icon">
<i class="fa fa-plane"></i>
</span>
<span class="travel-logo-content">
<strong>
آژانس مسافرتی
</strong>
<small>
سفر خوب، خاطره خوب
</small>
</span>
</a>
</div>
{{-- منوی اصلی --}}
<nav class="travel-menu">
<ul>
<li class="{{ request()->is('/') ? 'active' : '' }}">
<a href="{{ url('/') }}">
خانه
</a>
</li>
<li class="{{ request()->routeIs('tours.*') ? 'active' : '' }}">
<a href="{{ route('tours.index') }}">
تورها
</a>
</li>
@if(Route::has('flights.index'))
<li class="{{ request()->routeIs('flights.*') ? 'active' : '' }}">
<a href="{{ route('flights.index') }}">
پروازها
</a>
</li>
@endif
<li>
<a href="#">
درباره ما
</a>
</li>
<li>
<a href="#">
تماس با ما
</a>
</li>
</ul>
</nav>
{{-- سمت چپ --}}
<div class="travel-navbar-actions">
@guest
{{-- کاربر وارد نشده --}}
<a href="{{ route('auth.login.index') }}" class="travel-login">
<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="منو">
<i class="fa fa-bars"></i>
</button>
</div>
{{-- <div class="travel-navbar-actions">--}}
{{-- <a href="{{ route('auth') }}" class="travel-login">--}}
{{-- <i class="fa fa-user"></i>--}}
{{-- ورود / ثبت‌نام--}}
{{-- </a>--}}
{{-- <button--}}
{{-- type="button"--}}
{{-- class="travel-mobile-toggle"--}}
{{-- aria-label="منو">--}}
{{-- <i class="fa fa-bars"></i>--}}
{{-- </button>--}}
{{-- </div>--}}
</div>
{{-- ==============================
HERO
=============================== --}}
<div class="travel-hero">
<div class="travel-hero-content">
<span class="travel-hero-label">
<i class="fa fa-globe"></i>
سفر خود را شروع کنید
</span>
<h1>
بهترین مقصدها،
<br>
<span>بهترین خاطره‌ها</span>
</h1>
<p>
تورها و پروازهای مورد نظر خود را پیدا کنید
و با بهترین قیمت سفر کنید.
</p>
<div class="travel-hero-buttons">
<a
href="{{ route('tours.index') }}"
class="hero-btn hero-btn-primary">
<i class="fa fa-suitcase"></i>
مشاهده تورها
</a>
@if(Route::has('flights.index'))
<a
href="{{ route('flights.index') }}"
class="hero-btn hero-btn-outline">
<i class="fa fa-plane"></i>
مشاهده پروازها
</a>
@endif
</div>
</div>
</div>
</div>
</div>
{{-- منوی موبایل --}}
<div class="travel-mobile-menu">
<div class="container">
<a href="{{ url('/') }}">
<i class="fa fa-home"></i>
خانه
</a>
<a href="{{ route('tours.index') }}">
<i class="fa fa-suitcase"></i>
تورها
</a>
@if(Route::has('flights.index'))
<a href="{{ route('flights.index') }}">
<i class="fa fa-plane"></i>
پروازها
</a>
@endif
<a href="#">
<i class="fa fa-info-circle"></i>
درباره ما
</a>
<a href="#">
<i class="fa fa-phone"></i>
تماس با ما
</a>
</div>
</div>
</header>
{{--<meta charset="UTF-8">--}}
{{--<meta name="viewport" content="width=device-width, initial-scale=1.0">--}}
{{--<title>@yield('title', 'Dornica')</title>--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/font-awesome.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/lineicons.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/weather-icons.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/bootstrap.css') }}">--}}
{{--<link rel="stylesheet" href="{{ asset('assets/css/styles.css') }}">--}}
File diff suppressed because it is too large Load Diff
+386 -24
View File
@@ -1,38 +1,400 @@
@extends('layouts.app')
@section('content')
<h1>{{ $tour->title }}</h1>
{{-- گالری تصاویر (اسلایدر) --}}
<div id="tourGallery" class="carousel slide" data-bs-ride="carousel">
@foreach ($tour->images as $image)
<div class="carousel-item @if($loop->first) active @endif">
<img src="{{ $image->path }}" class="d-block w-100" alt="">
</div>
@endforeach
<div 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>
<p>{{ $tour->description }}</p>
<p>تاریخ شروع: {{ $tour->start_date?->format('Y/m/d') }}</p>
@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>
{{-- پروازهای این تور --}}
<h3>پروازهای همراه</h3>
@foreach($tour->flights as $flight)
<x-flight :flight="$flight"/>
<div class="flight-item">
<div>
<span>
مبدأ
</span>
<strong>
{{ $flight->origin ?? '-' }}
</strong>
</div>
<div>
<span>
مقصد
</span>
<strong>
{{ $flight->destination ?? '-' }}
</strong>
</div>
</div>
@endforeach
{{-- نظرات --}}
<h3>نظرات ({{ $tour->comments->count() }})</h3>
@foreach ($tour->comments as $comment)
<x-comment :comment="$comment"/>
</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
@auth
<form method="POST" action="{{ route('comments.store', $tour) }}">
@csrf
<textarea name="body" required></textarea>
<button type="submit">ثبت نظر</button>
</form>
@endauth
</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')--}}
{{--@section('title', $tour->name)--}}
{{--@section('content')--}}
{{-- <div class="container py-5 mt-4">--}}
{{-- --}}{{-- اطلاعات تور --}}
{{-- <div class="card mb-4 shadow-sm">--}}
{{-- <div class="card-body">--}}
{{-- <h2 class="card-title">{{ $tour->name }}</h2>--}}
{{-- <p class="text-muted">{{ $tour->description }}</p>--}}
{{-- <hr>--}}
{{-- <div class="row">--}}
{{-- <div class="col-md-3"><strong>مبدأ:</strong> {{ $tour->origin->name ?? '—' }}</div>--}}
{{-- <div class="col-md-3"><strong>مقصد:</strong> {{ $tour->destination->name ?? '—' }}</div>--}}
{{-- <div class="col-md-3"><strong>تاریخ رفت:</strong> {{ $tour->start_date }}</div>--}}
{{-- <div class="col-md-3"><strong>بازگشت:</strong> {{ $tour->end_date }}</div>--}}
{{-- </div>--}}
{{-- <div class="row mt-3">--}}
{{-- <div class="col-md-4"><strong>قیمت:</strong> {{ number_format($tour->price) }} تومان</div>--}}
{{-- <div class="col-md-4"><strong>ظرفیت:</strong> {{ $tour->capacity }} نفر</div>--}}
{{-- <div class="col-md-4"><strong>موجودی:</strong> {{ $tour->available_seats ?? $tour->capacity }} نفر--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- <hr>--}}
{{-- <p>{{ $tour->description }}</p>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </section>--}}
{{-- --}}{{-- ===== فرم رزرو تور ===== --}}
{{-- @auth--}}
{{-- <section class="pb-5">--}}
{{-- <div class="container">--}}
{{-- <div class="card shadow-sm">--}}
{{-- <div class="card-header bg-success text-white">--}}
{{-- رزرو تور {{ $tour->name }}--}}
{{-- </div>--}}
{{-- <div class="card-body">--}}
{{-- <form action="{{ route('booking.store', $tour) }}" method="POST">--}}
{{-- @csrf--}}
{{-- <div class="mb-3">--}}
{{-- <label class="form-label">تعداد نفرات</label>--}}
{{-- <input type="number" name="seats" min="1" max="{{ $tour->capacity }}" value="1"--}}
{{-- class="form-control @error('seats') is-invalid @enderror" required>--}}
{{-- @error('seats')--}}
{{-- <span class="invalid-feedback">{{ $message }}</span>--}}
{{-- @enderror--}}
{{-- </div>--}}
{{-- <button type="submit" class="btn btn-success w-100">رزرو تور</button>--}}
{{-- </form>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- </section>--}}
{{-- @else--}}
{{-- --}}{{-- کاربر لاگین نیست => دکمه ورود به روت login --}}
{{-- <div class="alert alert-warning text-center">--}}
{{-- برای رزرو تور ابتدا <a href="{{ route('login') }}">وارد شوید</a>.--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- @endauth--}}
{{--@endsection--}}
{{--@extends('layouts.app')--}}
{{--@section('content')--}}
{{-- <h1>{{ $tour->title }}</h1>--}}
{{-- --}}{{----}}{{-- گالری تصاویر (اسلایدر) --}}
{{-- <div id="tourGallery" class="carousel slide" data-bs-ride="carousel">--}}
{{-- @foreach ($tour->images as $image)--}}
{{-- <div class="carousel-item @if($loop->first) active @endif">--}}
{{-- <img src="{{ $image->path }}" class="d-block w-100" alt="">--}}
{{-- </div>--}}
{{-- @endforeach--}}
{{-- </div>--}}
{{-- <p>{{ $tour->description }}</p>--}}
{{-- <p>تاریخ شروع: {{ $tour->start_date?->format('Y/m/d') }}</p>--}}
{{-- --}}{{----}}{{-- پروازهای این تور --}}
{{-- <h3>پروازهای همراه</h3>--}}
{{-- @foreach ($tour->flights as $flight)--}}
{{-- <x-flight :flight="$flight"/>--}}
{{-- @endforeach--}}
{{-- --}}{{----}}{{-- نظرات --}}
{{-- <h3>نظرات ({{ $tour->comments->count() }})</h3>--}}
{{-- @foreach ($tour->comments as $comment)--}}
{{-- <x-comment :comment="$comment"/>--}}
{{-- @endforeach--}}
{{-- @auth--}}
{{-- <form method="POST" action="{{ route('comments.store', $tour) }}">--}}
{{-- @csrf--}}
{{-- <textarea name="body" required></textarea>--}}
{{-- <button type="submit">ثبت نظر</button>--}}
{{-- </form>--}}
{{-- @endauth--}}
{{--@endsection--}}
+235 -25
View File
@@ -1,18 +1,28 @@
<?php
//use App\Http\Controllers\Account\EditProfileController;
//use App\Http\Controllers\Account\BookingController;
//use App\Http\Controllers\Account\FavoriteController;
//use App\Http\Controllers\BookingController as SiteBookingController;
use App\Http\Controllers\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\FavoriteController as SiteFavoriteController;
//use App\Http\Controllers\FlightController;
use App\Http\Controllers\FlightController;
use App\Http\Controllers\IndexController;
//use App\Http\Controllers\PageController;
//use App\Http\Controllers\PaymentController;
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');
@@ -22,26 +32,226 @@ 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');
});
// json-suggestion-search (جستجوی پیشنهادی تورها)
Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'])
->name('tours.searchSuggestion');
// ------------------------------ flights ------------------------------
//Route::prefix('flights')->name('flights.')->controller(FlightController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('search', 'search')->name('search');
// Route::get('{flight}', 'show')->name('show');
// });
Route::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;
//use App\Http\Controllers\Account\EditProfileController;
//use App\Http\Controllers\Account\FavoriteController as AccountFavoriteController;
//use App\Http\Controllers\Account\HomeController;
//use App\Http\Controllers\Account\CommentController as AccountCommentController;
//use App\Http\Controllers\BookingController as SiteBookingController;
//use App\Http\Controllers\CommentController;
//use App\Http\Controllers\FavoriteController as SiteFavoriteController;
//use App\Http\Controllers\FlightController;
//use App\Http\Controllers\IndexController;
//use App\Http\Controllers\PageController;
//use App\Http\Controllers\TourController;
//use Illuminate\Support\Facades\Route;
//
//// ------------------------------ index ------------------------------
//Route::get('/', [IndexController::class, 'index'])->name('index');
//
//// ------------------------------ json-suggestion-search (جستجوی پیشنهادی تورها) ------------------------------
//// قبل از گروه tours تعریف شد تا با روت {tour} تداخل پیدا نکند
//Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'])
// ->name('tours.searchSuggestion');
//
//// ------------------------------ tours ------------------------------
//Route::prefix('tours')
// ->name('tours.')
// ->controller(TourController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('remove-filters', 'removeFilters')->name('remove-filters');
// Route::get('{tour}', 'show')->name('show');
// });
//
//// ------------------------------ flights ------------------------------
//Route::prefix('flights')
// ->name('flights.')
// ->controller(FlightController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('search', 'search')->name('search');
// Route::get('{flight}', 'show')->name('show');
// });
//
//// ------------------------------ نظرات (فقط کاربر واردشده) ------------------------------
//Route::post('tours/{tour}/comments', [CommentController::class, 'store'])
// ->middleware('auth')
// ->name('comments.store');
//
//// ------------------------------ علاقهمندیها ------------------------------
//Route::prefix('favorites')
// ->name('favorites.')
// ->middleware('auth')
// ->controller(SiteFavoriteController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('toggle', 'toggle')->name('toggle'); // افزودن/حذف با ajax
// Route::get('clear', 'clear')->name('clear');
// });
//
//// ------------------------------ رزرو (بدون پرداخت) ------------------------------
//Route::prefix('booking')
// ->name('booking.')
// ->middleware('auth')
// ->controller(SiteBookingController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index'); // فرم رزرو تور
// Route::post('tours/{tour}', 'store')->name('store'); // ثبت رزرو
// });
//
//// ------------------------------ پنل شخصی کاربر ------------------------------
//Route::prefix('account')
// ->name('account.')
// ->middleware('auth')
// ->group(function () {
//
// Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
//
// Route::get('bookings', [AccountBookingController::class, 'index'])->name('bookings');
// Route::get('favorites', [AccountFavoriteController::class, 'index'])->name('favorites');
// Route::get('comments', [AccountCommentController::class, 'index'])->name('comments');
//
// Route::prefix('edit-profile')
// ->name('edit-profile.')
// ->controller(EditProfileController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::post('/', 'post')->name('post');
// });
// });
//
//// ------------------------------ صفحات ثابت ------------------------------
//Route::get('/about', [PageController::class, 'about'])->name('about');
//Route::get('/contact', [PageController::class, 'contact'])->name('contact');
//Route::get('/faq', [PageController::class, 'faq'])->name('faq');
//
//
////use App\Http\Controllers\Account\EditProfileController;
////use App\Http\Controllers\Account\BookingController;
////use App\Http\Controllers\Account\FavoriteController;
////use App\Http\Controllers\BookingController as SiteBookingController;
////use App\Http\Controllers\CommentController;
////use App\Http\Controllers\FavoriteController as SiteFavoriteController;
////use App\Http\Controllers\FlightController;
//use App\Http\Controllers\IndexController;
////use App\Http\Controllers\PageController;
////use App\Http\Controllers\PaymentController;
//use App\Http\Controllers\TourController;
//use Illuminate\Support\Facades\Route;
//
//// ------------------------------ index ------------------------------
//Route::get('/', [IndexController::class, 'index'])->name('index');
//
//// ------------------------------ tours (مثل products) ------------------------------
//Route::prefix('tours')->name('tours.')->controller(TourController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('remove-filters', 'removeFilters')->name('remove-filters');
// Route::get('{tour}', 'show')->name('show');
// });
//
//// json-suggestion-search (جستجوی پیشنهادی تورها)
//Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'])
// ->name('tours.searchSuggestion');
//
//// ------------------------------ flights ------------------------------
//Route::prefix('flights')->name('flights.')->controller(FlightController::class)
// ->group(function () {
// Route::get('/', 'index')->name('index');
// Route::get('search', 'search')->name('search');
// Route::get('{flight}', 'show')->name('show');
// });
//
//// ------------------------------ نظرات (مهمان یا عضو) ------------------------------
//Route::post('tours/{tour}/comments', [CommentController::class, 'store'])
// ->middleware('auth')->name('comments.store');
//
//// ------------------------------ علاقه‌مندی‌ها ------------------------------
//Route::prefix('favorites')->name('favorites.')
// ->middleware('auth')->controller(SiteFavoriteController::class)
// ->group(function () {
@@ -49,8 +259,8 @@ Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'
// 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 () {
@@ -60,8 +270,8 @@ Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'
//
//Route::get('payment/{booking}/pay', [PaymentController::class, 'pay'])
// ->middleware('auth')->name('payment.pay');
// ------------------------------ پنل شخصی کاربر ------------------------------
//
//// ------------------------------ پنل شخصی کاربر ------------------------------
//Route::prefix('account')->name('account.')->middleware('auth')->group(function () {
//
// Route::get('/', [HomeController::class, 'index'])->name('index'); // داشبورد
@@ -75,8 +285,8 @@ Route::get('tours/search/suggestion', [TourController::class, 'searchSuggestion'
// 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');