feat: add index and tour public controllers
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class IndexController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('index');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Tour;
|
||||||
|
use App\Models\TravelType;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TourController extends Controller
|
||||||
|
{
|
||||||
|
//لیست/آرشیو تورها با قابلیت فیلتر
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = Tour::query()
|
||||||
|
->where('status', 1) // فقط تورهای فعال
|
||||||
|
->with(['travelType', 'flights']); // بارگذاری زودهنگام برای جلوگیری از N+1
|
||||||
|
|
||||||
|
// فیلتر بر اساس نوع سفر (travel_type_id)
|
||||||
|
if ($request->filled('travel_type')) {
|
||||||
|
$query->where('travel_type_id', $request->input('travel_type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر جستجوی متنی (عنوان)
|
||||||
|
if ($request->filled('q')) {
|
||||||
|
$query->where('title', 'like', '%' . $request->input('q') . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
// فیلتر بازه قیمتی
|
||||||
|
if ($request->filled('price_min')) {
|
||||||
|
$query->where('price', '>=', $request->input('price_min'));
|
||||||
|
}
|
||||||
|
if ($request->filled('price_max')) {
|
||||||
|
$query->where('price', '<=', $request->input('price_max'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// مرتبسازی بر اساس قیمت (اگر خواستی)
|
||||||
|
if ($request->filled('sort')) {
|
||||||
|
$query->orderBy('price', $request->input('sort') === 'desc' ? 'desc' : 'asc');
|
||||||
|
} else {
|
||||||
|
$query->latest(); // جدیدترینها اول
|
||||||
|
}
|
||||||
|
|
||||||
|
$tours = $query->paginate(12);
|
||||||
|
$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) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// بارگذاری پروازها + نوع سفر + نظرات تاییدشده
|
||||||
|
$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)
|
||||||
|
->limit(4)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
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 . '%')
|
||||||
|
->limit(8)
|
||||||
|
->get(['id', 'title', 'slug', 'price']);
|
||||||
|
|
||||||
|
return response()->json($tours);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user