chore: finalize project updates

This commit is contained in:
2026-08-22 11:42:16 +03:30
parent 7719d750e9
commit 691290c340
55 changed files with 1923 additions and 6498 deletions
@@ -17,7 +17,7 @@ class CommentController extends Controller
$tour->comments()->create([
'user_id' => auth()->id(),
'body' => $request->validated('body'),
'status' => 1, // در انتظار تایید (طبق قرارداد: 1 = پیشنویس/فعال، 2 = منتشرشده)
'status' => 1,
]);
return back()->with('success', 'نظر شما با موفقیت ثبت شد.');
@@ -15,7 +15,7 @@ class FavoriteController extends Controller
$user = Auth::user();
$favorites = Favorite::with('favoritable') // لود پلیمورفیک
$favorites = Favorite::with('favoritable')
->where('user_id', $user->id)
->orderByDesc('id')
->paginate(9);
@@ -23,10 +23,6 @@ class FavoriteController extends Controller
return view('account.favorites', compact('favorites'));
}
/**
* افزودن/حذف به صورت toggle (اگر موجود بود حذف کن، اگر نبود بساز).
* این متد با پلیمورفیک بودن Favorite از هر دو مدل تور و پرواز پشتیبانی میکنه.
*/
public function toggle(Request $request)
{
// چک اینکه کاربر ورود شدهست
@@ -42,7 +38,7 @@ class FavoriteController extends Controller
$type = $data['favoritable_type'];
$id = $data['favoritable_id'];
// بررسی اینکه مدل درخواستی واقعاً وجود داره (مثلاً Tour یا Flight)
if (!class_exists($type)) {
return back()->with('error', 'مدل معتبر نیست');
}
@@ -13,9 +13,7 @@ use Illuminate\Support\Facades\Hash;
class RegisterController extends Controller
{
/**
* نمایش فرم ثبت نام
*/
public function index()
{
$provinces = Province::orderBy('name')->get();
@@ -24,9 +22,7 @@ class RegisterController extends Controller
}
/**
* ثبت نام کاربر
*/
public function post(RegisterPostRequest $request)
{
@@ -86,9 +82,6 @@ class RegisterController extends Controller
}
/**
* دریافت شهرستان‌های یک استان
*/
public function cities(Province $province)
{
$cities = City::where('province_id', $province->id)
+3 -13
View File
@@ -8,9 +8,7 @@ use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* لیست پروازهای فعال
*/
public function index(Request $request)
{
$query = Flight::query()
@@ -56,9 +54,7 @@ class FlightController extends Controller
}
/**
* جستجوی پروازها
*/
public function search(Request $request)
{
$query = Flight::query()
@@ -108,15 +104,9 @@ class FlightController extends Controller
}
/**
* جزئیات پرواز
*/
public function show(Flight $flight)
{
// // فقط پرواز فعال قابل مشاهده باشد
// if (!$flight->isActive()) {
// abort(404);
// }
$flight->load([
'travelType',
+2 -2
View File
@@ -13,12 +13,12 @@ class IndexController extends Controller
$tours = Tour::query()
->where('status', 1)
->orderByDesc('created_at')
->paginate(6, ['*'], 'tours_page');
->paginate(3, ['*'], 'tours_page');
$flights = Flight::query()
->where('status', 1)
->orderByDesc('created_at')
->paginate(6, ['*'], 'flights_page');
->paginate(3, ['*'], 'flights_page');
$latestTours= Tour::latest()->limit(6)->get();
$latestFlights = Flight::latest()->limit(6)->get();
+13 -167
View File
@@ -13,15 +13,15 @@ use Illuminate\Http\Request;
class TourController extends Controller
{
/**
* لیست / آرشیو تورها با قابلیت فیلتر
*/
public function index(Request $request)
{
$query = Tour::query()
->where('status', 1)
->with(['travelType', 'flights']);
if ($request->filled('travel_type')) {
$query->where('travel_type_id', $request->input('travel_type'));
}
@@ -44,15 +44,18 @@ class TourController extends Controller
$query->latest();
}
$tours = $query->paginate(9);
$travelTypes = TravelType::where('status', 1)->get();
if ($request->routeIs('index')) {
return view('tours.index', compact('tours', 'travelTypes'));
$tours = $query->latest()->limit(4)->get();
return view('index', compact('tours'));
} else {
$tours = $query->latest()->paginate(2);
$travelTypes = TravelType::where('status', 1)->get();
return view('tours.index', compact('tours', 'travelTypes'));
}
}
/**
* نمایش جزئیات یک تور
*/
public function show(Tour $tour)
{
if ($tour->status != 1) {
@@ -75,7 +78,7 @@ class TourController extends Controller
->where('travel_type_id', $tour->travel_type_id)
->where('id', '!=', $tour->id)
->latest()
->limit(4)
->limit(3)
->get();
$isFav = false;
@@ -117,160 +120,3 @@ class TourController extends Controller
);
}
}
//
//namespace App\Http\Controllers;
//
//use App\Models\Favorite;
//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']);
//
// // فیلتر بر اساس نوع سفر
// 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(9);
//
// // انواع سفر
// $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 != 1) {
// abort(404);
// }
//
// // افزایش تعداد بازدید
// $tour->increment('views_count');
//
// // بارگذاری اطلاعات مورد نیاز
// $tour->load([
// 'flights',
// 'travelType',
// ]);
//
// // تورهای مرتبط
// $relatedTours = Tour::where('status', 1)
// ->where('travel_type_id', $tour->travel_type_id)
// ->where('id', '!=', $tour->id)
// ->latest()
// ->limit(4)
// ->get();
//
// $isFav = false;
//
// if (auth()->check()) {
// $isFav = Favorite::where('user_id', auth()->id())
// ->where('favoritable_type', Tour::class)
// ->where('favoritable_id', $tour->id)
// ->exists();
// }
//
//
// return view(
// 'tours.show',
// compact('tour', 'relatedTours', 'isFav')
// );
// }
//
//
// /**
// * جستجوی پیشنهادی
// */
// 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);
// }
//}
@@ -67,8 +67,9 @@ class AdminController extends Controller
public function update(
AdminUpdateRequest $request,
Admin $admin
) {
Admin $admin
)
{
$data = $request->validated();
$permissions = $data['permissions'] ?? [];
@@ -96,7 +97,6 @@ class AdminController extends Controller
->with('success', 'مدیر با موفقیت ویرایش شد.');
}
public function destroy(Admin $admin)
{
$admin->permissions()->detach();
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\CommentUpdateRequest;
use App\Http\Requests\UpdateCommentRequest;
use App\Models\Comment;
class CommentController extends Controller
@@ -23,10 +22,6 @@ class CommentController extends Controller
return view('admin.comments.show', compact('comment'));
}
// public function edit(Comment $comment)
// {
// return view('admin.comments.edit', compact('comment'));
// }
public function update(CommentUpdateRequest $request, Comment $comment)
{
@@ -78,9 +78,7 @@ class FlightController extends Controller
return view('admin.flights.show', compact('flight'));
}
/**
* نمایش فرم ویرایش پرواز
*/
public function edit(Flight $flight)
{
abort_unless(auth('admin')->user()?->canManageFlights('update'), 403);
@@ -90,9 +88,7 @@ class FlightController extends Controller
return view('admin.flights.edit', compact('flight', 'travelTypes'));
}
/**
* بروزرسانی پرواز
*/
public function update(FlightUpdateRequest $request, Flight $flight)
{
abort_unless(auth('admin')->user()?->canManageFlights('update'), 403);
+5 -33
View File
@@ -14,13 +14,9 @@ use Illuminate\Support\Str;
class TourController extends Controller
{
/**
* لیست تورها
*/
public function index()
{
// همه تورها نمایش داده می‌شوند
// اگر فقط تورهای تایید شده را می‌خواهی:
// ->where('status', 2)
$tours = Tour::latest()->paginate(20);
@@ -57,15 +53,6 @@ class TourController extends Controller
$data['slug'] = Str::slug($data['title']);
}
/*
* وضعیت تور
*
* 1 = در انتظار
* 2 = تایید شده
*
* اگر می‌خواهی تور بلافاصله در لیست نمایش داده شود،
* مقدار 2 قرار می‌دهیم.
*/
$data['status'] = 2;
// ایجاد تور
@@ -114,17 +101,13 @@ class TourController extends Controller
}
}
/**
* نمایش جزئیات تور
*/
public function show(Tour $tour)
{
return view('admin.tours.show', compact('tour'));
}
/**
* فرم ویرایش تور
*/
public function edit(Tour $tour)
{
$travelTypes = TravelType::all();
@@ -135,9 +118,7 @@ class TourController extends Controller
);
}
/**
* بروزرسانی تور
*/
public function update(
TourStoreRequest $request,
Tour $tour
@@ -153,10 +134,6 @@ class TourController extends Controller
$data['slug'] = Str::slug($data['title']);
}
/*
* اگر status از فرم ارسال نشده باشد،
* وضعیت فعلی تور حفظ شود.
*/
if (!isset($data['status'])) {
$data['status'] = $tour->status ?? 2;
}
@@ -217,9 +194,6 @@ class TourController extends Controller
}
}
/**
* حذف تصویر تور
*/
public function removeImage(Tour $tour)
{
try {
@@ -251,9 +225,7 @@ class TourController extends Controller
}
}
/**
* حذف تور
*/
public function destroy(Tour $tour)
{
try {
@@ -10,9 +10,7 @@ use Illuminate\Http\Request;
class TravelTypeController extends Controller
{
/**
* لیست + جستجو + صفحه‌بندی انواع سفر
*/
public function index(Request $request)
{
abort_unless(auth('admin')->user()->canManageTravelTypes('view'), 403);
@@ -27,7 +25,7 @@ class TravelTypeController extends Controller
});
}
// فیلتر وضعیت (1=فعال، 0=غیرفعال)
// فیلتر وضعیت
if ($request->filled('status')) {
$query->where('status', $request->status);
}
@@ -16,7 +16,7 @@ class UserController extends Controller
public function index(Request $request)
{
// چک دسترسی: فقط مدیرانی که مجوز «مشاهده کاربران» دارند
abort_unless(auth('admin')->user()->canManageUsers('view'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('view'), 403);
$query = User::query();
@@ -57,7 +57,7 @@ class UserController extends Controller
public function update(UserUpdateRequest $request, User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('edit'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('edit'), 403);
$data = $request->validated();
@@ -82,14 +82,14 @@ class UserController extends Controller
public function changePassword(User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
return view('admin.users.change-password', compact('user'));
}
public function updatePassword(UserUpdateRequest $request, User $user)
public function updatePassword(UserPasswordUpdateRequest $request, User $user)
{
abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
// abort_unless(auth('admin')->user()->canManageUsers('password'), 403);
$user->update([
'password' => Hash::make($request->password),
+1 -14
View File
@@ -14,6 +14,7 @@ class AirportStoreRequest extends FormRequest
{
return true;
}
protected function prepareForValidation(): void
{
// کد فرودگاه همیشه با حروف بزرگ ذخیره شود (IATA)
@@ -68,18 +69,4 @@ class AirportStoreRequest extends FormRequest
'code' => 'کد فرودگاه',
];
}
// public function messages(): array
// {
// return [
// 'name.required' => 'نام فرودگاه الزامی است.',
// 'name.max' => 'نام فرودگاه حداکثر ۱۵۰ کاراکتر باشد.',
// 'city.required' => 'نام شهر الزامی است.',
// 'city.max' => 'نام شهر حداکثر ۱۰۰ کاراکتر باشد.',
// 'country.required' => 'نام کشور الزامی است.',
// 'country.max' => 'نام کشور حداکثر ۱۰۰ کاراکتر باشد.',
// 'code.required' => 'کد فرودگاه (IATA) الزامی است.',
// 'code.max' => 'کد فرودگاه حداکثر ۱۰ کاراکتر باشد.',
// ];
// }
}
@@ -30,8 +30,7 @@ class RegisterPostRequest extends FormRequest
'persian_alpha',
'string',
'min:3',
'max:100',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'max:100'
],
@@ -39,8 +38,7 @@ class RegisterPostRequest extends FormRequest
'required',
'persian_alpha',
'string',
'max:100',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'max:100'
],
@@ -70,8 +68,7 @@ class RegisterPostRequest extends FormRequest
'nullable',
'string',
'max:200',
'required_if:marital_status,2',
// 'regex:/^[\x{0600}-\x{06FF}\x{200C}\s]+$/u',
'required_if:marital_status,2'
],
@@ -79,7 +76,6 @@ class RegisterPostRequest extends FormRequest
'required',
'digits:11',
'ir_mobile:zero',
// 'regex:/^09\d{9}$/',
'unique:users,mobile',
],
@@ -98,7 +94,6 @@ class RegisterPostRequest extends FormRequest
'string',
'min:3',
'max:50',
// 'regex:/^[A-Za-z0-9]+$/',
'unique:users,username',
],
+1 -3
View File
@@ -29,9 +29,7 @@ class SettingUpdateRequest extends FormRequest
$this->merge($filtered);
}
/**
* قوانین اعتبارسنجی.
*/
public function rules(): array
{
$codes = Setting::pluck('code')->all();
-11
View File
@@ -47,15 +47,4 @@ class UserStoreRequest extends FormRequest
],
];
}
// public function messages(): array
// {
// return [
// 'name.required' => 'نام و نام خانوادگی الزامی است.',
// 'email.required' => 'ایمیل الزامی است.',
// 'email.email' => 'فرمت ایمیل معتبر نیست.',
// 'email.unique' => 'این ایمیل قبلاً ثبت شده است.',
// 'password.required' => 'رمز عبور الزامی است.',
// 'password.confirmed' => 'تکرار رمز عبور مطابقت ندارد.',
// ];
// }
}
+10 -5
View File
@@ -23,19 +23,24 @@ class UserUpdateRequest extends FormRequest
public function rules(): array
{
return [
'name' =>
'first_name' =>
[
'required',
'string',
'max:255'
'max:100'
],
'last_name' =>
[
'required',
'string',
'max:100'
],
'email' =>
[
'required',
'nullable',
'email',
'max:255',
'unique:users',
'email,' . $this->user->id
'unique:users,email,' . $this->user->id,
],
'mobile' =>