feat: edit routes

This commit is contained in:
2026-08-18 16:25:12 -07:00
parent c0c2d093e8
commit 4794d7f732
42 changed files with 2760 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum BookingStatus: int
{
case PENDING = 0;
case CONFIRMED = 1;
case CANCELLED = 2;
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App\Enums;
enum TourDateStatus: int
{
case DISABLE = 1;
case ENABLE = 2;
}
+178
View File
@@ -0,0 +1,178 @@
@extends('account.layouts.app')
@section('title', 'رزروهای من')
@section('account-content')
<div class="col-lg-9">
<div class="user-profile-wrapper">
@error('')
<span class="text-success">{{ $message }}</span>
@enderror
<div class="user-profile-card">
<h4 class="user-profile-card-title">
رزروهای من
</h4>
<div class="row mt-30">
@forelse($bookings as $booking)
<div class="col-12 mb-4">
<div class="review-item">
<div class="review-item-content">
@if($booking->flight)
<div class="mb-2">
<span class="badge">
<i class="far fa-plane"></i>
رزرو پرواز
</span>
</div>
<h5 class="mt-2">
{{ $booking->flight->title }}
</h5>
<p>
قیمت:
{{ number_format($booking->flight->price) }}
تومان
</p>
@if($booking->flight->departureAirport)
<p>
مبدا:
{{ $booking->flight->departureAirport->city->name }}
</p>
@endif
@if($booking->flight->arrivalAirport)
<p>
مقصد:
{{ $booking->flight->arrivalAirport->city->name }}
</p>
@endif
@elseif($booking->tour)
<div class="mb-2">
<span class="badge">
<i class="far fa-map"></i>
رزرو تور
</span>
</div>
<h5 class="mt-2">
{{ $booking->tour->title }}
</h5>
<p>
قیمت:
{{ number_format($booking->tour->price) }}
تومان
</p>
<p>
مبدا:
{{ $booking->tour->origin }}
</p>
<p>
مقصد:
{{ $booking->tour->destination }}
</p>
@endif
<small>
وضعیت رزرو:
@if($booking->status === \App\Enums\BookingStatus::PENDING)
در انتظار تأیید
@elseif($booking->status === \App\Enums\BookingStatus::CONFIRMED)
تأیید شده
@elseif($booking->status === \App\Enums\BookingStatus::CANCELLED)
لغو شده
@endif
</small>
<br>
<small>
کد پیگیری:
{{ $booking->tracking_code }}
</small>
<br>
<small>
تاریخ رزرو:
{{ $booking->created_at->toJalali()->format('Y/m/d') }}
</small>
</div>
</div>
</div>
@empty
<div class="col-12">
<div class="text-center py-5">
<i class="far fa-shopping-bag fa-3x mb-3"></i>
<h5>
هنوز رزروی ندارید.
</h5>
<p>
رزروهای پرواز و تور شما در این قسمت نمایش داده می‌شوند.
</p>
</div>
</div>
@endforelse
</div>
{{-- Pagination --}}
@if($bookings->hasPages())
<div class="pagination-area my-4">
{{ $bookings->links() }}
</div>
@endif
</div>
</div>
</div>
@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">لاگ تغییرات</h1><span class="text-muted fs-12">ثبت چه کسی، چه زمانی و چه تغییری روی اطلاعات پرواز و تور</span></div>@endsection
@section('content')<div class="container-fluid pt-4"><div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-4"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجو در توضیحات"></div><div class="col-md-3"><select class="form-control" name="subject_type"><option value="">همه بخش‌ها</option><option value="flight" @selected(request('subject_type')==='flight')>پرواز</option><option value="tour" @selected(request('subject_type')==='tour')>تور</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap"><thead><tr><th>مدیر</th><th>بخش</th><th>عملیات</th><th>شرح تغییر</th><th>تاریخ</th></tr></thead><tbody>@forelse(($logs ?? []) as $log)<tr><td>{{ $log->admin->first_name ?? '-' }} {{ $log->admin->last_name ?? '' }}</td><td>{{ $log->subject_type ?? '-' }}</td><td>{{ $log->action ?? '-' }}</td><td>{{ $log->description ?? '-' }}</td><td>{{ isset($log->created_at) ? $log->created_at->toJalali()->format('Y/m/d H:i') : '-' }}</td></tr>@empty<tr><td colspan="5" class="text-center text-muted py-5">لاگی برای نمایش وجود ندارد.</td></tr>@endforelse</tbody></table></div></div>{{ ($logs ?? collect())->links() }}</div>@endsection
@@ -0,0 +1,14 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">ایجاد مدیر</h1><span class="text-muted fs-12">اطلاعات مدیر سامانه</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<form action="{{ isset($admin) ? route('admin.admins.update',$admin) : route('admin.admins.store') }}" method="POST">@csrf @if(isset($admin)) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات مدیر</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">نام</label><input class="form-control" name="first_name" value="{{ old('first_name',$admin->first_name ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">نام خانوادگی</label><input class="form-control" name="last_name" value="{{ old('last_name',$admin->last_name ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">ایمیل</label><input type="email" class="form-control" name="email" value="{{ old('email',$admin->email ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">رمز عبور {{ isset($admin) ? '(در صورت تغییر)' : '' }}</label><input type="password" class="form-control" name="password" {{ isset($admin) ? '' : 'required' }}></div>
<div class="col-md-6"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$admin->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$admin->status ?? 1)==='0')>غیرفعال</option></select></div>
</div></div></div></div>
<div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">دسترسی مدیر</div></div><div class="card-body"><div class="alert alert-warning fs-12">جدول فعلی admins ستون دسترسی ندارد. برای فعال‌سازی واقعی دسترسی‌ها باید جدول permissions/roles اضافه شود.</div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت کاربران</label></div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت پرواز و تور</label></div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت رزروها</label></div><div class="form-check form-switch"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">گزارش و لاگ</label></div></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.admins.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($admin) ? 'ذخیره تغییرات' : 'ثبت مدیر' }}</button></div></div>
</form></div>@endsection
@@ -0,0 +1,14 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">{{ isset($admin) ? 'ویرایش مدیر' : 'ایجاد مدیر' }}</h1><span class="text-muted fs-12">اطلاعات مدیر سامانه</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<form action="{{ isset($admin) ? route('admin.admins.update',$admin) : route('admin.admins.store') }}" method="POST">@csrf @if(isset($admin)) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات مدیر</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">نام</label><input class="form-control" name="first_name" value="{{ old('first_name',$admin->first_name ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">نام خانوادگی</label><input class="form-control" name="last_name" value="{{ old('last_name',$admin->last_name ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">ایمیل</label><input type="email" class="form-control" name="email" value="{{ old('email',$admin->email ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">رمز عبور {{ isset($admin) ? '(در صورت تغییر)' : '' }}</label><input type="password" class="form-control" name="password" {{ isset($admin) ? '' : 'required' }}></div>
<div class="col-md-6"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$admin->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$admin->status ?? 1)==='0')>غیرفعال</option></select></div>
</div></div></div></div>
<div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">دسترسی مدیر</div></div><div class="card-body"><div class="alert alert-warning fs-12">جدول فعلی admins ستون دسترسی ندارد. برای فعال‌سازی واقعی دسترسی‌ها باید جدول permissions/roles اضافه شود.</div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت کاربران</label></div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت پرواز و تور</label></div><div class="form-check form-switch mb-3"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">مدیریت رزروها</label></div><div class="form-check form-switch"><input class="form-check-input" type="checkbox" disabled checked><label class="form-check-label">گزارش و لاگ</label></div></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.admins.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($admin) ? 'ذخیره تغییرات' : 'ثبت مدیر' }}</button></div></div>
</form></div>@endsection
@@ -0,0 +1,10 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت مدیران سایت</h1><span class="text-muted fs-12">تعریف مدیر، فعال/غیرفعال‌سازی و مدیریت دسترسی</span></div>@endsection
@section('content')<div class="container-fluid pt-4">
@include('admin.partials.errors')
<div class="card custom-card"><div class="card-body p-3"><form method="GET"><div class="row g-2 align-items-center"><div class="col-md-5"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجو نام، نام خانوادگی یا ایمیل"></div><div class="col-md-3"><select class="form-control" name="status"><option value="">همه وضعیت‌ها</option><option value="1" @selected(request('status')==='1')>فعال</option><option value="0" @selected(request('status')==='0')>غیرفعال</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.admins.create') }}" class="btn btn-primary w-100"><i class="ri-add-line"></i> مدیر جدید</a></div></div></form></div></div>
<div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap table-hover mb-0"><thead><tr><th>مدیر</th><th>ایمیل</th><th>وضعیت</th><th>آخرین ورود</th><th>تاریخ ثبت</th><th>عملیات</th></tr></thead><tbody>
@forelse(($admins ?? []) as $admin)<tr><td><div class="fw-semibold">{{ $admin->first_name }} {{ $admin->last_name }}</div><small class="text-muted">#{{ $admin->id }}</small></td><td>{{ $admin->email }}</td><td>@if($admin->status)<span class="badge bg-success-transparent">فعال</span>@else<span class="badge bg-danger-transparent">غیرفعال</span>@endif</td><td>{{ isset($admin->last_login_at) && $admin->last_login_at ? $admin->last_login_at->toJalali()->format('Y/m/d H:i') : '-' }}</td><td>{{ isset($admin->created_at) ? $admin->created_at->toJalali()->format('Y/m/d H:i') : '-' }}</td><td><div class="hstack gap-2"><a href="{{ route('admin.admins.edit',$admin) }}" class="btn btn-secondary-light btn-icon btn-sm" title="ویرایش"><i class="ri-edit-line"></i></a><form method="POST" action="{{ route('admin.admins.destroy',$admin) }}" onsubmit="return confirm('آیا از حذف مدیر مطمئن هستید؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-icon btn-sm"><i class="ri-delete-bin-line"></i></button></form></div></td></tr>
@empty<tr><td colspan="6" class="text-center py-5 text-muted">مدیری ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>
{{ ($admins ?? collect())->links() }}
</div>@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت رزروها</h1><span class="text-muted fs-12">مشاهده و پیگیری رزروهای پرواز و تور</span></div>@endsection
@section('content')<div class="container-fluid pt-4"><div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-5"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="کد رهگیری یا نام کاربر"></div><div class="col-md-3"><select class="form-control" name="status"><option value="">همه وضعیت‌ها</option><option value="0">در انتظار</option><option value="1">تأیید شده</option><option value="2">لغو شده</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap"><thead><tr><th>کد رهگیری</th><th>کاربر</th><th>نوع</th><th>تعداد مسافر</th><th>مبلغ</th><th>وضعیت</th><th>تاریخ</th></tr></thead><tbody>@forelse(($bookings ?? []) as $booking)<tr><td>{{ $booking->tracking_code }}</td><td>{{ $booking->user->first_name ?? '' }} {{ $booking->user->last_name ?? '' }}</td><td>{{ $booking->flight_id ? 'پرواز' : 'تور' }}</td><td>{{ ($booking->adult_count ?? 0)+($booking->child_count ?? 0) }}</td><td>{{ number_format($booking->total_price) }} تومان</td><td>{{ $booking->status->name ?? $booking->status }}</td><td>{{ $booking->created_at?->toJalali()->format('Y/m/d H:i') }}</td></tr>@empty<tr><td colspan="7" class="text-center text-muted py-5">رزروی ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($bookings ?? collect())->links() }}</div>@endsection
@@ -0,0 +1,71 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
@error('general')
<span class="text-danger">{{ $message }}</span>
@enderror
<!-- Create Category Form -->
<form action="{{ route('admin.categories.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="card custom-card mb-4">
<div class="card-header">
<div class="card-title">ایجاد دسته‌بندی</div>
</div>
<div class="card-body">
<div class="row gy-3">
<div class="col-xl-6">
<label class="form-label">نام دسته‌بندی</label>
<input type="text" class="form-control" name="name"
placeholder="نام دسته بندی را وارد کنید"
value={{ old('name') }} >
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-12">
<label class="form-label">توضیحات</label>
<textarea class="form-control" name="description" rows="3"
placeholder="توضیحات دسته‌بندی را وارد کنید">{{ old('description') }}</textarea>
@error('description')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<div class="card-avatar mt-3" style="min-height: unset">
<div class="text-center">
<label class="form-label d-block mb-2 fw-semibold">تصویر دسته بندی</label>
<label class="avatar-picker" id="avatarPreview"
style="background-image: url({{ asset('assets/admin/images/faces/DefaultAvatar.jpg') }})">
<input type="file" name="image" accept="image/*"
onchange="previewAvatar(this)">
</label>
@error('image')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ایجاد دسته‌بندی</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,75 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
@error('general')
<span class="text-danger">{{ $message }}</span>
@enderror
<!-- Edit Category Form -->
<form action="{{ route('admin.categories.update', $category) }}" method="POST"
enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="card-header">
<div class="card-title">ویرایش دسته‌بندی</div>
</div>
<div class="card-body">
<div class="row gy-3">
<div class="col-xl-6">
<label class="form-label">نام دسته‌بندی</label>
<input type="text" class="form-control" name="name"
value="{{ old('name', $category->name) }}"
placeholder="نام دسته‌بندی را وارد کنید">
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-12">
<label class="form-label">توضیحات</label>
<textarea class="form-control" name="description" rows="3"
placeholder="توضیحات دسته‌بندی را وارد کنید">{{ old('description', $category->description) }}</textarea>
@error('description')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<div class="card-avatar mt-3" style="min-height: unset">
<!-- Avatar Picker -->
<div class="text-center">
<label class="form-label d-block fw-semibold">تصویر دسته بندی</label>
<label class="avatar-picker" id="avatarPreview"
style="background-image: url({{ asset('storage/' .old('image', $category->image)) }})">
<input type="file" name="image" accept="image/*"
onchange="previewAvatar(this)">
</label>
@error('image')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,181 @@
@extends('admin.layouts.app')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">لیست دسته بندی ها</h1>
<div>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="javascript:void(0)">مدیریت دسته بندی ها</a></li>
<li class="breadcrumb-item active" aria-current="page">لیست دسته بندی ها</li>
</ol>
</nav>
</div>
</div>
@endsection
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
@error('general')
<span class="text-danger ">{{ $message }}</span>
@enderror
@error('success')
<span class="text-success ">{{ $message }}</span>
@enderror
<!-- Filters -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-body p-3">
<form method="GET">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<!-- Sort Dropdown -->
<div class="d-flex flex-wrap gap-1 align-items-center">
<div class="d-flex me-2">
<input class="form-control me-2" type="search" name="search"
placeholder="جستجو دسته‌بندی"
value="{{ request()->input('search') }}">
<button class="btn btn-light" type="submit">جستجو</button>
</div>
<select id="choices-single-default" class="form-control" name="sort">
<option value="">مرتب‌سازی بر اساس</option>
<option
value="newest" @selected(request()->missing('sort') || request()->input('sort') == 'newest')>
جدیدترین
</option>
<option
value="oldest" @selected(request()->input('sort') == 'oldest')>
قدیمی ترین
</option>
<option value="name_asc" @selected(request()->input('sort') == 'name_asc')>
الفبا (الف - ی)
</option>
<option
value="name_desc" @selected(request()->input('sort') == 'name_desc')>
الفبا (ی - الف)
</option>
</select>
</div>
<!-- Search -->
<div class="d-flex" role="search">
<a href="{{ route('admin.categories.create') }}" class="btn btn-primary me-2">
<i class="ri-add-line me-1 fw-medium align-middle"></i>
ایجاد دسته بندی
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Categories Table -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="table-responsive">
<table class="table text-nowrap table-bordered">
<thead>
<tr>
<th>دسته‌بندی</th>
<th>تعداد محصولات</th>
<th scope="col">وضعیت</th>
<th>تاریخ ایجاد</th>
<th>اقدامات</th>
</tr>
</thead>
<tbody>
@foreach($categories as $category)
<tr>
<td>
<div class="d-flex">
<span class="avatar avatar-md avatar-square bg-light">
@if($category->image)
<img
src="{{ asset('storage/'. $category->image) }}"
class="w-100 h-100"
alt="{{ $category->name }}">
@else
<img
src="{{asset('assets/admin/images/product-default-image.png')}}"
class="w-100 h-100"
alt="{{ $category->name }}">
@endif
</span>
<div class="ms-2">
<p class="fw-semibold mb-0 name-limit">
<a href="{{ route('admin.categories.show', $category->id) }}">{{ $category->name }}</a>
</p>
<p class="fs-12 text-muted mb-0 ">#{{ $category->id }}</p>
</div>
</div>
</td>
<td>{{ $category->products->count() }}</td>
<td>
@if($category->is_active)
<span
class="badge bg-success-transparent">
فعال
</span>
@else
<span
class="badge bg-danger-transparent">
غیر فعال
</span>
@endif
</td>
<td>{{ $category->created_at->toJalali()->format('H:i Y-m-d') }}</td>
<td>
<div class="hstack gap-2 fs-15">
<a href="{{ route('admin.categories.show', $category->id) }}"
class="btn btn-primary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="مشاهده">
<i class="ri-eye-line"></i>
</a>
<a href="{{route('admin.categories.edit', $category->id)}}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ti ti-pencil"></i>
</a>
<form action="{{ route('admin.categories.destroy', $category->id) }}"
method="POST"
onsubmit="return confirm('آیا از حذف این دسته‌بندی مطمئن هستید؟')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-icon btn-sm btn-danger-light">
<i class="ri-delete-bin-line"></i>
</button>
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Pagination -->
{{$categories->links()}}
</div>
</div>
@endsection
@@ -0,0 +1,159 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
<div class="card custom-card mb-4">
<div class="card-header">
<div class="card-title">اطلاعات دسته‌بندی</div>
</div>
<div class="card-body">
<div class="row gx-4 gy-4 align-items-center">
<div class="col-md-8">
<h2 class="fw-bold mb-3">{{ $category->name }}</h2>
<dl class="row mb-4">
<dt class="col-sm-4 fw-semibold">توضیحات:</dt>
<dd class="col-sm-8">{{ $category->description }}</dd>
</dl>
<div class="row text-center text-md-start">
<div class="col-6 col-md-4 mb-3">
<div class="p-3 border rounded bg-light">
<div class="fs-4 fw-bold">{{ $category->products->count() }}</div>
<div class="text-muted">تعداد محصولات</div>
</div>
</div>
<div class="col-6 col-md-4 mb-3">
<div class="p-3 border rounded bg-light">
<div class="fs-4 fw-bold">
@if($category->is_active)
<span class="text-success pe-3 py-2 fs-6">
فعال
</span>
@else
<span class="text-danger pe-3 py-2 fs-6">
غیر فعال
</span>
@endif
</div>
<div class="text-muted">وضعیت دسته‌بندی</div>
</div>
</div>
<!-- اگر اطلاعات وضعیت دیگه‌ای داری می‌تونی اینجا اضافه کنی -->
</div>
</div>
</div>
</div>
</div>
<!-- Products List -->
<div class="card custom-card">
<div class="card-header">
<div class="card-title">محصولات دسته‌بندی</div>
</div>
<div class="table-responsive">
<table class="table text-nowrap table-bordered">
<thead>
<tr>
<th>محصول</th>
<th>دسته‌بندی فعلی</th>
<th>قیمت</th>
<th>قیمت تخفیف‌خورده</th>
<th>موجودی</th>
<th>وضعیت</th>
<th>منتشر شده</th>
<th>اقدامات</th>
</tr>
</thead>
<tbody>
@foreach($products as $product)
<tr>
<td>
<div class="d-flex align-items-center">
<span class="avatar avatar-md avatar-square bg-light">
@if($product->defaultImage )
<img
src="{{ asset('storage/'.$product->defaultImage->file->path) }}"
class="w-100 h-100"
alt="{{ $product->name }}"
>
@else
<img
src="{{ asset('images/no-image.png') }}"
class="w-100 h-100"
alt="{{ $product->name }}"
>
@endif
</span>
<div class="ms-2">
<p class="fw-semibold mb-0">{{ $product->name}}</p>
<p class="fs-12 text-muted mb-0 description-limit">{{ $product->description }}</p>
</div>
</div>
</td>
<td>{{ $product->productCategory->name }}</td>
<td>{{number_format($product->price)}} تومان</td>
<td>
<span class="text-success"> {{ number_format(discount($product->price , $product->discount)) }}تومان</span>
</td>
<td>{{ $product->qty }}</td>
<td>
@switch($product->status)
@case(\App\Enums\ProductStatus::DISABLE)
<span class="badge bg-danger-transparent">غیر فعال</span>
@break
@case(\App\Enums\ProductStatus::DRAFT)
<span class="badge bg-warning-transparent">پیش نویس</span>
@break
@case(\App\Enums\ProductStatus::PUBLISHED)
<span class="badge bg-primary-transparent"> منتشر شده</span>
@break
@case(\App\Enums\ProductStatus::ENABLE)
<span class="badge bg-success-transparent"> فعال</span>
@break
@endswitch
</td>
<td>{{ $category->created_at->toJalali()->format('H:i Y-F-d') }}</td>
<td>
<div class="hstack gap-2 fs-15">
<a href="{{ route('admin.product.show', $product->id) }}"
class="btn btn-primary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="مشاهده">
<i class="ri-eye-line"></i>
</a>
<a href="{{ route('admin.product.edit', $product->id) }}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ti ti-pencil"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت شهرها</h1></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-5"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجوی شهر"></div><div class="col-md-3"><select class="form-control" name="province_id"><option value="">همه استان‌ها</option>@foreach(($provinces ?? []) as $province)<option value="{{ $province->id }}" @selected((string)request('province_id')===(string)$province->id)>{{ $province->name }}</option>@endforeach</select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.cities.create') }}" class="btn btn-primary w-100">شهر جدید</a></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table"><thead><tr><th>#</th><th>شهر</th><th>استان</th><th>عملیات</th></tr></thead><tbody>@forelse(($cities ?? []) as $city)<tr><td>{{ $city->id }}</td><td>{{ $city->name }}</td><td>{{ $city->province->name ?? '-' }}</td><td><a href="{{ route('admin.cities.edit',$city) }}" class="btn btn-secondary-light btn-sm">ویرایش</a><form class="d-inline" method="POST" action="{{ route('admin.cities.destroy',$city) }}" onsubmit="return confirm('حذف شهر؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="4" class="text-center text-muted py-5">شهری ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($cities ?? collect())->links() }}</div>@endsection
+42
View File
@@ -0,0 +1,42 @@
@extends('admin.layouts.app')
@section('breadcrumb')
<div><h1 class="page-title fw-medium fs-18 mb-1">داشبورد مدیریت</h1><span class="text-muted fs-12">نمای کلی سامانه هواپیمایی و تور</span></div>
@endsection
@section('content')
<div class="container-fluid pt-4">
<div class="row g-3">
@php($cards = [
['title'=>'کاربران ثبت‌نام‌شده','value'=>$usersCount ?? 0,'icon'=>'ri-group-line','class'=>'primary'],
['title'=>'پروازهای فعال','value'=>$flightsCount ?? 0,'icon'=>'ri-flight-takeoff-line','class'=>'success'],
['title'=>'تورهای فعال','value'=>$toursCount ?? 0,'icon'=>'ri-map-2-line','class'=>'warning'],
['title'=>'رزروهای در انتظار','value'=>$pendingBookings ?? 0,'icon'=>'ri-calendar-check-line','class'=>'danger'],
])
@foreach($cards as $card)
<div class="col-xl-3 col-lg-6 col-md-6"><div class="card custom-card h-100"><div class="card-body"><div class="d-flex align-items-center gap-3"><div class="avatar avatar-md bg-{{ $card['class'] }} svg-white"><i class="{{ $card['icon'] }} fs-24"></i></div><div><div class="fw-medium fs-13 text-dark">{{ $card['title'] }}</div><div class="fs-22 fw-semibold text-primary mt-1">{{ number_format($card['value']) }}</div></div></div></div></div></div>
@endforeach
</div>
<div class="row g-3 mt-1">
<div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">تعداد بازدید سایت در ۱۰ روز اخیر</div></div><div class="card-body"><div id="visits-chart" style="min-height:320px"></div></div></div></div>
<div class="col-xl-4"><div class="card custom-card h-100"><div class="card-header"><div class="card-title">آخرین فعالیت‌ها</div></div><div class="card-body"><div class="list-group list-group-flush">
@forelse(($latestLogs ?? []) as $log)
<div class="list-group-item px-0"><div class="d-flex justify-content-between"><span class="fw-semibold">{{ $log->action ?? 'تغییر اطلاعات' }}</span><small class="text-muted">{{ isset($log->created_at) ? $log->created_at->toJalali()->format('Y/m/d H:i') : '-' }}</small></div><div class="text-muted fs-12 mt-1">{{ $log->description ?? '' }}</div></div>
@empty
<div class="text-muted text-center py-5">فعالیتی برای نمایش وجود ندارد.</div>
@endforelse
</div></div></div></div>
</div>
</div>
@endsection
@push('scripts')
<script src="{{ asset('assets/admin/plugins/apexcharts/apexcharts.min.js') }}"></script>
<script>
document.addEventListener('DOMContentLoaded', function(){
const el=document.querySelector('#visits-chart'); if(!el || !window.ApexCharts) return;
new ApexCharts(el,{chart:{type:'area',height:320,toolbar:{show:false}},series:[{name:'بازدید',data:@json($visitData ?? [])}],xaxis:{categories:@json($visitLabels ?? [])},stroke:{curve:'smooth',width:3},dataLabels:{enabled:false},grid:{borderColor:'#eee'}}).render();
});
</script>
@endpush
@@ -0,0 +1,18 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">درج پرواز</h1><span class="text-muted fs-12">اطلاعات مورد نیاز سفر</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<form action="{{ isset($flight) ? route('admin.flights.update',$flight) : route('admin.flights.store') }}" method="POST" enctype="multipart/form-data">@csrf @if(isset($flight)) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات پرواز</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">عنوان سفر *</label><input class="form-control" name="title" value="{{ old('title',$flight->title ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">نوع سفر *</label><select class="form-control" name="flight_type" required><option value="1" @selected((string)old('flight_type',$flight->flight_type ?? '')==='1')>داخلی</option><option value="2" @selected((string)old('flight_type',$flight->flight_type ?? '')==='2')>خارجی</option><option value="3" @selected((string)old('flight_type',$flight->flight_type ?? '')==='3')>چارتر</option></select></div>
<div class="col-md-6"><label class="form-label">فرودگاه مبدأ</label><select class="form-control" name="departure_airport_id" required><option value="">انتخاب فرودگاه</option>@foreach(($airports ?? []) as $airport)<option value="{{ $airport->id }}" @selected((string)old('departure_airport_id',$flight->departure_airport_id ?? '')===(string)$airport->id)>{{ $airport->title ?? $airport->name ?? ('#'.$airport->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">فرودگاه مقصد</label><select class="form-control" name="arrival_aiport_id" required><option value="">انتخاب فرودگاه</option>@foreach(($airports ?? []) as $airport)<option value="{{ $airport->id }}" @selected((string)old('arrival_aiport_id',$flight->arrival_aiport_id ?? '')===(string)$airport->id)>{{ $airport->title ?? $airport->name ?? ('#'.$airport->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">شرکت هواپیمایی</label><select class="form-control" name="airline_id" required><option value="">انتخاب ایرلاین</option>@foreach(($airlines ?? []) as $airline)<option value="{{ $airline->id }}" @selected((string)old('airline_id',$flight->airline_id ?? '')===(string)$airline->id)>{{ $airline->title ?? $airline->name ?? ('#'.$airline->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">تاریخ حرکت (شمسی) *</label><input type="text" class="form-control jalali-date" name="departure_time_jalali" value="{{ old('departure_time_jalali', isset($flight) && $flight->departure_time ? $flight->departure_time->toJalali()->format('Y/m/d H:i') : '') }}" placeholder="1405/06/01 12:00" autocomplete="off" required><small class="text-muted">تاریخ حرکت نباید قبل از امروز باشد.</small></div>
<div class="col-md-4"><label class="form-label">قیمت *</label><input type="number" min="0" class="form-control" name="price" value="{{ old('price',$flight->price ?? '') }}" required></div>
<div class="col-md-4"><label class="form-label">ظرفیت *</label><input type="number" min="1" class="form-control" name="capacity" value="{{ old('capacity',$flight->capacity ?? '') }}" required></div>
<div class="col-md-4"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$flight->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$flight->status ?? 1)==='0')>غیرفعال</option></select></div>
<div class="col-12"><label class="form-label">خلاصه سفر *</label><textarea class="form-control" name="summary" rows="4" required>{{ old('summary',$flight->summary ?? '') }}</textarea></div>
</div></div></div></div><div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">تصویر سفر</div></div><div class="card-body"><input type="file" class="form-control" name="image" accept="image/*"><small class="text-muted d-block mt-2">تصویر اختیاری است.</small></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.flights.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($flight) ? 'ذخیره تغییرات' : 'ثبت پرواز' }}</button></div></div></form></div>@endsection
@push('scripts')<script>$(function(){ if($.fn.persianDatepicker){ $('.jalali-date').persianDatepicker({format:'YYYY/MM/DD HH:mm',timePicker:{enabled:true},autoClose:true}); }});</script>@endpush
@@ -0,0 +1,18 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">{{ isset($flight) ? 'ویرایش پرواز' : 'درج پرواز' }}</h1><span class="text-muted fs-12">اطلاعات مورد نیاز سفر</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<form action="{{ isset($flight) ? route('admin.flights.update',$flight) : route('admin.flights.store') }}" method="POST" enctype="multipart/form-data">@csrf @if(isset($flight)) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات پرواز</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">عنوان سفر *</label><input class="form-control" name="title" value="{{ old('title',$flight->title ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">نوع سفر *</label><select class="form-control" name="flight_type" required><option value="1" @selected((string)old('flight_type',$flight->flight_type ?? '')==='1')>داخلی</option><option value="2" @selected((string)old('flight_type',$flight->flight_type ?? '')==='2')>خارجی</option><option value="3" @selected((string)old('flight_type',$flight->flight_type ?? '')==='3')>چارتر</option></select></div>
<div class="col-md-6"><label class="form-label">فرودگاه مبدأ</label><select class="form-control" name="departure_airport_id" required><option value="">انتخاب فرودگاه</option>@foreach(($airports ?? []) as $airport)<option value="{{ $airport->id }}" @selected((string)old('departure_airport_id',$flight->departure_airport_id ?? '')===(string)$airport->id)>{{ $airport->title ?? $airport->name ?? ('#'.$airport->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">فرودگاه مقصد</label><select class="form-control" name="arrival_aiport_id" required><option value="">انتخاب فرودگاه</option>@foreach(($airports ?? []) as $airport)<option value="{{ $airport->id }}" @selected((string)old('arrival_aiport_id',$flight->arrival_aiport_id ?? '')===(string)$airport->id)>{{ $airport->title ?? $airport->name ?? ('#'.$airport->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">شرکت هواپیمایی</label><select class="form-control" name="airline_id" required><option value="">انتخاب ایرلاین</option>@foreach(($airlines ?? []) as $airline)<option value="{{ $airline->id }}" @selected((string)old('airline_id',$flight->airline_id ?? '')===(string)$airline->id)>{{ $airline->title ?? $airline->name ?? ('#'.$airline->id) }}</option>@endforeach</select></div>
<div class="col-md-6"><label class="form-label">تاریخ حرکت (شمسی) *</label><input type="text" class="form-control jalali-date" name="departure_time_jalali" value="{{ old('departure_time_jalali', isset($flight) && $flight->departure_time ? $flight->departure_time->toJalali()->format('Y/m/d H:i') : '') }}" placeholder="1405/06/01 12:00" autocomplete="off" required><small class="text-muted">تاریخ حرکت نباید قبل از امروز باشد.</small></div>
<div class="col-md-4"><label class="form-label">قیمت *</label><input type="number" min="0" class="form-control" name="price" value="{{ old('price',$flight->price ?? '') }}" required></div>
<div class="col-md-4"><label class="form-label">ظرفیت *</label><input type="number" min="1" class="form-control" name="capacity" value="{{ old('capacity',$flight->capacity ?? '') }}" required></div>
<div class="col-md-4"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$flight->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$flight->status ?? 1)==='0')>غیرفعال</option></select></div>
<div class="col-12"><label class="form-label">خلاصه سفر *</label><textarea class="form-control" name="summary" rows="4" required>{{ old('summary',$flight->summary ?? '') }}</textarea></div>
</div></div></div></div><div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">تصویر سفر</div></div><div class="card-body"><input type="file" class="form-control" name="image" accept="image/*"><small class="text-muted d-block mt-2">تصویر اختیاری است.</small></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.flights.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($flight) ? 'ذخیره تغییرات' : 'ثبت پرواز' }}</button></div></div></form></div>@endsection
@push('scripts')<script>$(function(){ if($.fn.persianDatepicker){ $('.jalali-date').persianDatepicker({format:'YYYY/MM/DD HH:mm',timePicker:{enabled:true},autoClose:true}); }});</script>@endpush
@@ -0,0 +1,5 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت پروازها</h1><span class="text-muted fs-12">درج، ویرایش، حذف و جستجوی پروازهای داخلی، خارجی و چارتر</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-4"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="عنوان یا مسیر پرواز"></div><div class="col-md-2"><select class="form-control" name="flight_type"><option value="">همه انواع</option><option value="1" @selected(request('flight_type')==='1')>داخلی</option><option value="2" @selected(request('flight_type')==='2')>خارجی</option><option value="3" @selected(request('flight_type')==='3')>چارتر</option></select></div><div class="col-md-2"><select class="form-control" name="status"><option value="">همه وضعیت‌ها</option><option value="1" @selected(request('status')==='1')>فعال</option><option value="0" @selected(request('status')==='0')>غیرفعال</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.flights.create') }}" class="btn btn-primary w-100"><i class="ri-add-line"></i> پرواز جدید</a></div></div></form></div></div>
<div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap table-hover mb-0"><thead><tr><th>عنوان سفر</th><th>نوع</th><th>تاریخ حرکت</th><th>قیمت</th><th>ظرفیت</th><th>بازدید</th><th>وضعیت</th><th>عملیات</th></tr></thead><tbody>@forelse(($flights ?? []) as $flight)<tr><td><div class="fw-semibold">{{ $flight->title }}</div><small class="text-muted">#{{ $flight->id }}</small></td><td>@switch((int)$flight->flight_type) @case(1) داخلی @break @case(2) خارجی @break @case(3) چارتر @break @default - @endswitch</td><td>{{ isset($flight->departure_time) ? $flight->departure_time->toJalali()->format('Y/m/d H:i') : '-' }}</td><td>{{ number_format($flight->price) }} تومان</td><td>{{ number_format($flight->capacity) }}</td><td>{{ number_format($flight->views ?? 0) }}</td><td>@if($flight->status)<span class="badge bg-success-transparent">فعال</span>@else<span class="badge bg-danger-transparent">غیرفعال</span>@endif</td><td><div class="hstack gap-2"><a href="{{ route('admin.flights.show',$flight) }}" class="btn btn-primary-light btn-icon btn-sm"><i class="ri-eye-line"></i></a><a href="{{ route('admin.flights.edit',$flight) }}" class="btn btn-secondary-light btn-icon btn-sm"><i class="ri-edit-line"></i></a><form method="POST" action="{{ route('admin.flights.destroy',$flight) }}" onsubmit="return confirm('حذف این پرواز؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-icon btn-sm"><i class="ri-delete-bin-line"></i></button></form></div></td></tr>@empty<tr><td colspan="8" class="text-center py-5 text-muted">پروازی ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($flights ?? collect())->links() }}</div>@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">جزئیات پرواز</h1><span class="text-muted fs-12">مشاهده اطلاعات ثبت‌شده و سابقه تغییرات</span></div>@endsection
@section('content')<div class="container-fluid pt-4"><div class="card custom-card"><div class="card-body"><div class="row g-4"><div class="col-md-8"><h4>{{ $flight->title }}</h4><p class="text-muted">{{ $flight->summary }}</p><div class="row gy-3"><div class="col-md-6"><strong>نوع:</strong> {{ [1=>'داخلی',2=>'خارجی',3=>'چارتر'][$flight->flight_type] ?? '-' }}</div><div class="col-md-6"><strong>قیمت:</strong> {{ number_format($flight->price) }} تومان</div><div class="col-md-6"><strong>ظرفیت:</strong> {{ number_format($flight->capacity) }}</div><div class="col-md-6"><strong>بازدید:</strong> {{ number_format($flight->views ?? 0) }}</div><div class="col-md-6"><strong>تاریخ حرکت:</strong> {{ $flight->departure_time?->toJalali()->format('Y/m/d H:i') }}</div></div></div></div></div><div class="card-footer"><a href="{{ route('admin.flights.edit',$flight) }}" class="btn btn-primary">ویرایش</a><a href="{{ route('admin.flights.index') }}" class="btn btn-light ms-2">بازگشت</a></div></div></div>@endsection
+194
View File
@@ -0,0 +1,194 @@
<!DOCTYPE html>
<html
lang="fa"
data-nav-layout="vertical"
data-theme-mode="light"
data-header-styles="light"
data-menu-styles="light"
dir="rtl"
loader="enable"
data-vertical-style="overlay">
<head>
<!-- Meta Data -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>
پنل مدیریت
@isset($title)
|
{{$title}}
@endisset
</title>
<meta name="csrf-token" content="G3faz5te2OVLWMw1sn2U47RRUgVWPGJznIyOIEMM">
<!-- Favicon -->
<link rel="icon" href="{{ asset('assets/admin/images/brand-logos/favicon.ico') }}" type="image/x-icon">
<!-- Start::Styles -->
<!-- Choices JS -->
<script src="{{ asset('assets/admin/js/choices.min.js') }}"></script>
<!-- Main Theme Js -->
<script src="{{asset('assets/admin/js/main.js')}}"></script>
<link href="{{asset('assets/admin/css/bootstrap.rtl.min.css')}}" id="style" rel="stylesheet">
<!-- Style Css -->
<link href="{{ asset('assets/admin/css/styles.css') }}" rel="stylesheet">
<!-- Icons Css -->
<link href="{{ asset('assets/admin/css/icons.css') }}" rel="stylesheet">
<!-- Node Waves Css -->
<link href="{{ asset('assets/admin/css/waves.min.css') }}" rel="stylesheet">
<!-- Simplebar Css -->
<link href="{{ asset('assets/admin/css/simplebar.min.css') }}" rel="stylesheet">
<!-- Color Picker Css -->
<link rel="stylesheet" href="{{ asset('assets/admin/css/nano.min.css') }}">
<!-- Choices Css -->
<link rel="stylesheet" href="{{ asset('assets/admin/css/choices.min.css') }}">
<!-- FlatPickr CSS -->
<link rel="stylesheet" href="{{ asset('assets/admin/css/flatpickr.min.css') }}">
<!-- Auto Complete CSS -->
<link rel="stylesheet" href="{{ asset('assets/admin/css/autoComplete.css') }}">
<!-- Prism CSS -->
<link rel="stylesheet" href="{{ asset('assets/admin/plugins/prismjs/themes/prism-coy.min.css') }}">
<link rel="stylesheet" href="{{ asset('assets/admin/plugins/dropzone/dropzone.css') }}">
<!-- Persian Datepicker -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/persian-datepicker@1.2.0/dist/css/persian-datepicker.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"/>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body @class(['authentication-background'=> isset($rawLayout)])>
<!-- Loader -->
<div id="loader">
<img src="{{ asset('assets/admin/images/media/loader.svg') }}" alt="">
</div>
<!-- Loader -->
<!-- page -->
<div class="page">
@includeUnless(isset($rawLayout), 'admin.layouts.header')
@includeUnless(isset($rawLayout), 'admin.layouts.sidebar')
<!-- Start::app-content -->
<div @class(['main-content','app-content' => !isset($rawLayout)])>
@yield('content')
</div>
<!-- End::app-content -->
@includeUnless(isset($rawLayout), 'admin.layouts.footer')
</div>
<!-- End Page -->
<!-- Scroll To Top -->
<div class="scrollToTop" style="display: none;">
<span class="arrow lh-1"><i class="ri-rocket-line align-middle fs-18"></i></span>
</div>
<div id="responsive-overlay"></div>
<!-- Scroll To Top -->
<!-- Persian Date Library -->
<script src="https://cdn.jsdelivr.net/npm/persian-date/dist/persian-date.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/persian-datepicker@1.2.0/dist/js/persian-datepicker.min.js"></script>
<!-- Popper JS -->
<script src="{{ asset('assets/admin/js/popper.min.js') }}"></script>
<!-- Bootstrap JS -->
<script src="{{ asset('assets/admin/js/bootstrap.bundle.min.js') }}"></script>
<!-- Defaultmenu JS -->
<script src="{{ asset('assets/admin/js/defaultmenu.js') }}"></script>
<!-- Node Waves JS -->
<script src="{{ asset('assets/admin/js/waves.min.js') }}"></script>
<!-- Sticky JS -->
<script src="{{ asset('assets/admin/js/sticky.js') }}"></script>
<!-- Color Picker JS -->
<script src="{{ asset('assets/admin/js/pickr.es5.min.js') }}"></script>
<!-- Date & Time Picker JS -->
<script src="{{ asset('assets/admin/js/flatpickr.min.js') }}"></script>
<!-- Custom-Switcher JS -->
<script src="{{ asset('assets/admin/js/custom-switcher.js') }}"></script>
<!-- Custom JS -->
<script src="{{ asset('assets/admin/js/custom.js') }}"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
// ===== Choices =====
const choicesEl = document.querySelector('#choices-single-default');
if (choicesEl && window.Choices) {
const choices = new Choices(choicesEl, {
allowHTML: true,
searchEnabled: false,
shouldSort: false,
itemSelectText: '',
placeholder: true,
placeholderValue: 'مرتب‌سازی بر اساس'
});
if (choicesEl) {
choicesEl.addEventListener('change', function () {
if (this.form) this.form.submit();
});
}
}
// ===== ApexCharts =====
const charts = document.querySelectorAll(".apex-chart");
charts.forEach(chartEl => {
if (chartEl) {
const options = chartEl.dataset.options ? JSON.parse(chartEl.dataset.options) : {};
const chart = new ApexCharts(chartEl, options);
chart.render();
}
});
// ===== Popper Example =====
const popperRefs = document.querySelectorAll("[data-popper-ref]");
popperRefs.forEach(ref => {
const targetId = ref.getAttribute("data-popper-target");
const popperEl = document.getElementById(targetId);
if (popperEl) {
Popper.createPopper(ref, popperEl, {
placement: 'bottom'
});
}
});
});
</script>
@stack('scripts')
</body>
</html>
@@ -0,0 +1,11 @@
<!-- Start::main-footer -->
<footer class="footer mt-auto py-3 bg-white text-center">
<div class="container">
<span class="text-muted">
<span id="year"></span>
|
<span>تمامی حقوق محفوظ است.</span>
</span>
</div>
</footer>
<!-- End::main-footer -->
@@ -0,0 +1,137 @@
<header class="app-header sticky" id="header">
<!-- Start::main-header-container -->
<div class="main-header-container container-fluid">
<!-- Start::header-content-left -->
<div class="header-content-left">
<!-- Start::header-element -->
<div class="header-element mx-lg-0 me-2 d-lg-none">
<a aria-label="Hide Sidebar" class="sidemenu-toggle header-link" data-bs-toggle="sidebar"
href="javascript:void(0);">
<svg xmlns="http://www.w3.org/2000/svg" class="header-link-icon menu-btn" width="24" height="24"
viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="1.5" d="M4 5h12M4 12h16M4 19h8" color="currentColor"></path>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" class="header-link-icon menu-btn-close" width="24"
height="24" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="1.5" d="m18 6l-6 6m0 0l-6 6m6-6l6 6m-6-6L6 6"
color="currentColor">
</path>
</svg>
</a>
</div>
<!-- End::header-element -->
<!-- Start::header-element -->
<div class="header-element">
<div class="horizontal-logo">
<a href="{{route('admin.dashboard.index')}}" class="header-logo">
<span class="text-primary fs-6 fw-bold">پنل مدیریت</span>
</a>
</div>
</div>
<!-- End::header-element -->
<!-- Start::header-element -->
<div class="header-element header-search d-md-block d-none my-auto">
@yield('breadcrumb')
</div>
<!-- End::header-element -->
</div>
<!-- End::header-content-left -->
<!-- Start::header-content-right -->
<ul class="header-content-right">
<!-- Start::header-element -->
<li class="header-element header-theme-mode">
<!-- Start::header-link|layout-setting -->
<a href="javascript:void(0);" class="header-link layout-setting">
<span class="light-layout">
<!-- Start::header-link-icon -->
<svg xmlns="http://www.w3.org/2000/svg" class="header-link-icon" width="1em"
height="1em" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M21.5 14.078A8.557 8.557 0 0 1 9.922 2.5C5.668 3.497 2.5 7.315 2.5 11.873a9.627 9.627 0 0 0 9.627 9.627c4.558 0 8.376-3.168 9.373-7.422"
color="currentColor"></path>
</svg>
<!-- End::header-link-icon -->
</span>
<span class="dark-layout">
<!-- Start::header-link-icon -->
<svg xmlns="http://www.w3.org/2000/svg" class="header-link-icon" width="1em"
height="1em" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
d="M17 12a5 5 0 1 1-10 0a5 5 0 0 1 10 0M12 2v1.5m0 17V22m7.07-2.929l-1.06-1.06M5.99 5.989L4.928 4.93M22 12h-1.5m-17 0H2m17.071-7.071l-1.06 1.06M5.99 18.011l-1.06 1.06"
color="currentColor"></path>
</svg>
<!-- End::header-link-icon -->
</span>
</a>
<!-- End::header-link|layout-setting -->
</li>
<!-- End::header-element -->
<!-- Start::header-element -->
<li class="header-element dropdown">
<!-- Start::header-link|dropdown-toggle -->
<a href="javascript:void(0);" class="header-link dropdown-toggle" id="mainHeaderProfile"
data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
<div class="d-flex align-items-center">
<div>
<img
src="{{ asset('assets/admin/images/faces/DefaultAvatar.jpg') }}"
alt="img"
class="avatar avatar-sm avatar-rounded">
</div>
</div>
</a>
<!-- End::header-link|dropdown-toggle -->
<ul class="main-header-dropdown dropdown-menu pt-0 overflow-hidden header-profile-dropdown dropdown-menu-end"
aria-labelledby="mainHeaderProfile">
<li class="p-3 border-bottom">
<div class="d-flex align-items-center">
<div>
<p class="mb-0 fw-semibold lh-1">{{ auth('admin')->user()->first_name }}</p>
<span class="fs-11 text-muted">{{ auth('admin')->user()->email }}</span>
</div>
</div>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<a class="dropdown-item d-flex align-items-center text-danger px-3"
href="{{ route('admin.auth.logout') }}">
<i
class="ri-logout-circle-line fs-15 me-2 text-danger fw-normal"
style="position: relative; top: -2px"
></i>
خروج
</a>
</li>
</ul>
</li>
<!-- End::header-element -->
</ul>
<!-- End::header-content-right -->
</div>
<!-- End::main-header-container -->
</header>
@@ -0,0 +1,38 @@
<aside class="app-sidebar sticky" id="sidebar">
<div class="main-sidebar-header">
<a href="{{ route('admin.dashboard.index') }}" class="header-logo">
<span class="text-primary fs-6 fw-bold">MyTrip | پنل مدیریت</span>
</a>
</div>
<div class="main-sidebar simplebar-scrollable-y" id="sidebar-scroll" data-simplebar="init">
<div class="simplebar-mask"><div class="simplebar-offset"><div class="simplebar-content-wrapper">
<div class="simplebar-content" style="padding:8px 0 80px;">
<nav class="main-menu-container nav nav-pills flex-column">
<ul class="main-menu mx-0">
<li class="slide">
<a href="{{ route('admin.dashboard.index') }}" class="side-menu__item {{ activeAdminSidebar('admin.dashboard.index') }}">
<i class="ri-dashboard-2-line side-menu__icon"></i><span class="side-menu__label">داشبورد</span>
</a>
</li>
<li class="slide has-sub"><a href="javascript:void(0);" class="side-menu__item"><i class="ri-flight-takeoff-line side-menu__icon"></i><span class="side-menu__label">مدیریت سفرها</span><i class="ri-arrow-down-s-line side-menu__angle"></i></a>
<ul class="slide-menu child1">
<li><a href="{{ route('admin.flights.index') }}" class="side-menu__item">پروازها</a></li>
<li><a href="{{ route('admin.tours.index') }}" class="side-menu__item">تورها</a></li>
<li><a href="{{ route('admin.bookings.index') }}" class="side-menu__item">رزروها</a></li>
</ul>
</li>
<li class="slide"><a href="{{ route('admin.users.index') }}" class="side-menu__item {{ activeAdminSidebar(['admin.users.index','admin.users.edit','admin.users.show']) }}"><i class="ri-group-line side-menu__icon"></i><span class="side-menu__label">ثبت‌نام‌های سایت</span></a></li>
<li class="slide"><a href="{{ route('admin.admins.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>
<li class="slide has-sub"><a href="javascript:void(0);" class="side-menu__item"><i class="ri-map-pin-line side-menu__icon"></i><span class="side-menu__label">استان‌ها و شهرها</span><i class="ri-arrow-down-s-line side-menu__angle"></i></a>
<ul class="slide-menu child1">
<li><a href="{{ route('admin.provinces.index') }}" class="side-menu__item">استان‌ها</a></li>
<li><a href="{{ route('admin.cities.index') }}" class="side-menu__item">شهرها</a></li>
</ul>
</li>
<li class="slide"><a href="{{ route('admin.activity-logs.index') }}" class="side-menu__item {{ activeAdminSidebar('admin.activity-logs.index') }}"><i class="ri-file-history-line side-menu__icon"></i><span class="side-menu__label">لاگ تغییرات</span></a></li>
</ul>
</nav>
</div>
</div></div></div>
</div>
</aside>
+31
View File
@@ -0,0 +1,31 @@
@extends('admin.layouts.app')
@section('content')
<div class="container-lg">
<div class="row justify-content-center align-items-center authentication authentication-basic h-100">
<div class="col-xxl-4 col-xl-5 col-lg-5 col-md-6 col-sm-8 col-12">
<div class="card custom-card my-4 auth-circle">
<div class="card-body p-5">
<p class="h4 mb-3 fw-semibold text-center">ورود به پنل مدیریت</p>
<p class="mb-4 text-muted text-center">برای ورود به پنل مدیریت اطلاعات حساب مدیر را وارد کنید.</p>
@error('general') <div class="alert alert-danger">{{ $message }}</div> @enderror
<form method="POST" action="{{ route('admin.auth.login.post') }}">
@csrf
<label class="form-label">ایمیل</label>
<input type="email" name="email" class="form-control" value="{{ old('email') }}" placeholder="ایمیل مدیر" required>
@error('email') <span class="text-danger fs-12">{{ $message }}</span> @enderror
<div class="mt-3">
<label class="form-label">رمز عبور</label>
<input type="password" name="password" class="form-control" placeholder="رمز عبور" required>
@error('password') <span class="text-danger fs-12">{{ $message }}</span> @enderror
</div>
<div class="d-grid mt-4">
<button type="submit" class="btn btn-primary">ورود به پنل</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,65 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="card custom-card">
<div class="card-body">
@error('status')
<span class="warning">{{ $message }}</span>
@enderror
<form action="{{ route('admin.orders.update', $order->id) }}" method="POST">
@csrf
@method('PATCH')
<div class="mb-3">
<label for="status" class="form-label fw-semibold">
وضعیت سفارش
</label>
<select name="status" id="status" class="form-select">
<option value="0"
@selected(\App\Enums\OrderStatus::PENDING)>
در انتظار ثبت
</option>
<option value="1"
@selected(\App\Enums\OrderStatus::PROCESSING)>
در حال پردازش
</option>
<option value="2"
@selected(\App\Enums\OrderStatus::SENT)>
ارسال شده
</option>
<option value="4"
@selected(\App\Enums\OrderStatus::DELIVERED)>
تحویل داده
</option>
<option value="5"
@selected(\App\Enums\OrderStatus::CANCELLED)>
لغو شده
</option>
</select>
</div>
<button type="submit" class="btn btn-primary btn-wave">
ذخیره تغییرات
</button>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,170 @@
@extends('admin.layouts.app')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">لیست سفارشات</h1>
<div>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="javascript:void(0)">مدیریت سفارشات</a></li>
<li class="breadcrumb-item active" aria-current="page">لیست سفارشات</li>
</ol>
</nav>
</div>
</div>
@endsection
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<!-- Filters -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-body p-3">
<form method="GET" >
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<!-- Sort Dropdown -->
<div class="d-flex flex-wrap gap-1 align-items-center">
<select id="choices-single-default" class="form-control" name="sort">
<option value="">مرتب‌سازی بر اساس</option>
<option
value="created_at_desc" @selected(request()->missing('sort') || request()->input('sort') == 'created_at_desc')>
جدیدترین
</option>
<option
value="created_at_asc" @selected(request()->input('sort') == 'created_at_asc')>
قدیمی‌ترین
</option>
<option
value="price_high" @selected(request()->input('sort') == 'price_high')>
مبلغ (زیاد به کم)
</option>
<option
value="price_low" @selected(request()->input('sort') == 'price_low')>
مبلغ (کم به زیاد)
</option>
<option value="status" @selected(request()->input('sort') == 'status')>
وضعیت
</option>
</select>
</div>
<!-- Search -->
<div class="d-flex" role="search">
<input class="form-control me-2" type="search" name="search"
placeholder="جستجو سفارش"
value="{{ request()->input('search') }}"
>
<button class="btn btn-light" type="submit">جستجو</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Order Table -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="table-responsive">
<table class="table text-nowrap table-hover">
<thead>
<tr>
<th>شناسه</th>
<th>مشتری</th>
<th>مبلغ</th>
<th>وضعیت</th>
<th>تاریخ ثبت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@foreach($orders as $order)
<tr>
<td>
<div class="d-flex align-items-center gap-2">
<div>
<span class="fw-semibold d-block">#{{ $order->id }}</span>
</div>
</div>
</td>
<td>
{{ getUserFullName($order->user) }}
</td>
<td>
{{ number_format($order->total_price )}}
تومان
</td>
<td>
<span class="text-info">
@switch($order->status)
@case(\App\Enums\OrderStatus::PENDING)
<span>در انتظار پرداخت</span>
@break
@case(\App\Enums\OrderStatus::PROCESSING)
<span>در حال پردازش</span>
@break
@case(\App\Enums\OrderStatus::SENT)
<span>ارسال شده</span>
@break
@case(\App\Enums\OrderStatus::DELIVERED)
<span>تحویل شده</span>
@break
@case(\App\Enums\OrderStatus::CANCELLED)
<span>لغو شده</span>
@break
@endswitch
</span>
</td>
<td>{{$order->created_at->toJalali()->format('Y/m/d H:i')}}</td>
<td>
<div class="btn-list">
<a href="{{ route('admin.orders.show' , $order->id) }}"
class="btn btn-primary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="مشاهده">
<i class="ri-eye-line"></i>
</a>
<a href="{{route('admin.orders.edit', $order->id)}}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ti ti-pencil"></i>
</a>
<a href="javascript:void(0);"
onclick="if(confirm('آیا از حذف این سفارش مطمئن هستید؟')) { document.getElementById('delete-form-2').submit(); }"
class="btn btn-pink-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="حذف">
<i class="ri-delete-bin-line"></i>
</a>
<form id="delete-form-2"
action="{{ route('admin.orders.destroy', $order->id) }}"
method="POST"
style="display:none;"
>
@csrf
@method('delete')
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
{{$orders->links()}}
</div>
</div>
@endsection
+184
View File
@@ -0,0 +1,184 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<!-- Main Row -->
<div class="row">
<div class="col-xl-8">
<div class="row">
<div class="col-md-6">
<!-- Summary -->
<div class="card custom-card overflow-hidden" style="padding-bottom: 6px !important;">
<div class="card-header justify-content-between">
<div class="card-title">خلاصه سفارش</div>
<div>شناسه: <span class="text-primary fw-semibold">{{ $order->id }}</span></div>
</div>
<div class="card-body p-0 table-responsive">
<table class="table">
<tbody>
<tr>
<td>
<div class="fw-semibold">تعداد کالا:</div>
</td>
<td>{{ $order->total_products }}</td>
</tr>
<tr>
<td>
<div class="fw-semibold">وضعیت سفارش:</div>
</td>
<td>
<span class="text-info">
@switch($order->status)
@case(\App\Enums\OrderStatus::PENDING)
<span>در انتظار پرداخت</span>
@break
@case(\App\Enums\OrderStatus::PROCESSING)
<span>در حال پردازش</span>
@break
@case(\App\Enums\OrderStatus::SENT)
<span>ارسال شده</span>
@break
@case(\App\Enums\OrderStatus::DELIVERED)
<span>تحویل شده</span>
@break
@endswitch
</span>
</td>
</tr>
<tr>
<td>
<div class="fw-semibold">مبلغ کل:</div>
</td>
<td>
<span class="fw-medium">
{{number_format($order->total_price) }}
تومان
</span>
</td>
</tr>
<tr>
<td style="border-bottom: 0;">
<div class="fw-semibold">توضیحات:</div>
</td>
<td style="border-bottom: 0;">{{ $order->description }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- Address Info -->
<div class="col-md-6">
<div class="card custom-card">
<div class="card-header">
<div class="card-title">آدرس تحویل</div>
</div>
<div class="card-body">
<p>
<strong>آدرس:</strong>
{{ $order->user_address }}
</p>
<p>
<strong>شماره تماس:</strong>
{{ $order->user_mobile }}
</p>
<p>
<strong>کد پستی:</strong>
{{ $order->user_postal_code }}
</p>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-xl-4">
<!-- User Info -->
<div class="card custom-card">
<div class="card-header">
<div class="card-title">مشخصات کاربر</div>
</div>
<div class="card-body">
<p><strong>نام:</strong>{{ getUserFullName($order->user) }}</p>
<p><strong>ایمیل:</strong> {{$order->user->email}}</p>
<p><strong>موبایل:</strong> {{ $order->user_mobile }}</p>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div>
<!-- Order Card -->
<div class="card custom-card">
<div class="card-header d-flex justify-content-between">
<div class="card-title">
محصولات سفارش
</div>
<div>
<span class="badge bg-primary-transparent">
تاریخ سفارش:
{{$order->created_at->toJalali()->format('H:i Y/m/d')}}
</span>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table text-nowrap">
<thead>
<tr>
<th scope="col">محصول</th>
<th scope="col">قیمت</th>
<th scope="col">تعداد</th>
<th scope="col">مبلغ نهایی</th>
</tr>
</thead>
<tbody>
@foreach ($order->orderItems as $orderItem)
<tr>
<td>
<div class="d-flex align-items-center">
<div>
<div class="mb-1 fs-14 fw-medium">
<span>
{{$orderItem->product->name}}
|
{{$orderItem->product->en_name}}
</span>
</div>
</div>
</div>
</td>
<td>
{{ $orderItem->product->price }}
تومان
</td>
<td>{{ $orderItem->qty }}</td>
<td>
{{ number_format(discountPrice($orderItem->unit_price, $orderItem->unit_discount) * $orderItem->qty) }}
تومان
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,4 @@
@if($errors->any())
<div class="alert alert-danger"><ul class="mb-0">@foreach($errors->all() as $error)<li>{{ $error }}</li>@endforeach</ul></div>
@endif
@if(session('success'))<div class="alert alert-success">{{ session('success') }}</div>@endif
@@ -0,0 +1,141 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
<form action="{{ route('admin.product.store') }}" method="POST" enctype="multipart/form-data">
@csrf
@error('general')
<span class="text-danger">{{ $message }}</span>
@enderror
<div class="card custom-card">
<div class="card-header">
<div class="card-title">
ایجاد محصول
</div>
</div>
<div class="card-body pt-0">
<div class="row gy-3">
<!-- Name -->
<div class="col-xl-6">
<label class="form-label">نام فارسی</label>
<input
type="text"
class="form-control" name="name"
placeholder="نام فارسی را وارد کنید"
value="{{ old('name') }}"
/>
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Name -->
<div class="col-xl-6">
<label class="form-label">نام انگلیسی</label>
<input type="text" class="form-control" name="en_name"
placeholder="نام انگلیسی را وارد کنید" value="{{ old('en_name') }}">
@error('en_name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Category -->
<div class="col-xl-6">
<label class="form-label">دسته‌ بندی</label>
<select class="form-control" name="category_id">
<option>یک دسته بندی انتخاب کنید</option>
@foreach($productCategories as $productCategory)
<option value="{{ $productCategory->id }}" >
{{ $productCategory->name }}
</option>
@endforeach
</select>
</div>
<!-- Price -->
<div class="col-xl-6">
<label class="form-label">قیمت</label>
<input type="number" class="form-control" name="price"
placeholder="قیمت را وارد کنید" value="{{old('price')}}">
@error('price')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Discount Price -->
<div class="col-xl-6">
<label class="form-label">تخفیف</label>
<input type="number" class="form-control" name="discount"
placeholder="تخفیف را وارد کنید"
value="{{ old('discount') }}">
@error('discount')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Stock -->
<div class="col-xl-6">
<label class="form-label">موجودی</label>
<input type="number" class="form-control" name="qty"
placeholder="تعداد موجودی را وارد کنید" value="{{ old('qty') }}">
@error('qty')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Description -->
<div class="col-xl-12">
<label class="form-label">توضیحات</label>
<textarea class="form-control" name="description" rows="4"
placeholder="توضیحات را وارد کنید">{{ old('description') }}</textarea>
@error('description')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<!-- Product Images -->
<div
class="image-upload-wrapper d-flex flex-wrap gap-2 px-0 pt-0 mt-3"
id="imagePreviewContainer"
style=" border-radius: 8px; padding: 10px;"
>
<label
id="uploadPlaceholder"
class="upload-placeholder"
for="imageInput"
style="cursor: pointer; width:150px; height:150px; display: flex; justify-content: center; align-items: center; border: 2px dashed #ccc; border-radius: 8px; padding: 20px; text-align: center;"
>
<div>📷<br><strong>آپلود یا کشیدن</strong></div>
<small style="color:#999;">JPG / PNG / JPEG / WEBP</small>
</label>
<input
id="imageInput"
name="images[]"
type="file"
accept=".jpg,.png,.jpeg,.webp"
multiple
style="display:none"
/>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ایجاد محصول</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,171 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
@error('error')
<span class="text-danger">{{ $message }}</span>
@enderror
<form action="{{ route('admin.product.update', $product) }}" method="POST" enctype="multipart/form-data">
@csrf
@method('put')
<div class="card custom-card">
<div class="card-header">
<div class="card-title">
ویرایش محصول
</div>
</div>
<div class="card-body pt-0">
<div class="row gy-3">
<!-- Name -->
<div class="col-xl-6">
<label class="form-label">نام فارسی</label>
<input
type="text"
class="form-control" name="name"
placeholder="نام فارسی را وارد کنید"
value="{{ old('name', $product->name) }} "
/>
@error('name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Name -->
<div class="col-xl-6">
<label class="form-label">نام انگلیسی</label>
<input type="text" class="form-control" name="en_name"
placeholder="نام انگلیسی را وارد کنید"
value="{{ old('en_name', $product->en_name) }}">
@error('en_name')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Category -->
<div class="col-xl-6">
<label class="form-label">دسته‌ بندی</label>
<select class="form-control" name="category_id">
<option>یک دسته بندی انتخاب کنید</option>
@foreach($productCategories as $productCategory)
<option
value="{{ $productCategory->id }}"
@selected(old('category_id', $product->product_category_id) == $productCategory->id)
>
{{ $productCategory->name }}
</option>
@endforeach
</select>
@error('category_id')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Price -->
<div class="col-xl-6">
<label class="form-label">قیمت</label>
<input type="number" class="form-control" name="price"
placeholder="قیمت را وارد کنید"
value="{{ old('price',$product->price) }}">
@error('price')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Discount Price -->
<div class="col-xl-6">
<label class="form-label">تخفیف</label>
<input type="number" class="form-control" name="discount"
placeholder="تخفیف را وارد کنید"
value="{{ old('discount', $product->discount) }}">
@error('discount')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Stock -->
<div class="col-xl-6">
<label class="form-label">موجودی</label>
<input type="number" class="form-control" name="qty"
placeholder="تعداد موجودی را وارد کنید"
value="{{ old('qty', $product->qty) }}">
@error('qty')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
<!-- Description -->
<div class="col-xl-12">
<label class="form-label">توضیحات</label>
<textarea class="form-control"
name="description"
rows="4"
placeholder="توضیحات را وارد کنید">{{ old('description', $product->description) }}</textarea>
@error('description')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
<!-- Product Images -->
<div
class="image-upload-wrapper d-flex flex-wrap gap-2 px-0 pt-0 mt-3"
id="imagePreviewContainer"
style=" border-radius: 8px; padding: 10px;"
>
@foreach($product->productImages as $image)
<div class="position-relative" style="width:150px;height:150px;">
<img src="{{ asset('storage/'.$image->file->path) }}"
class="img-fluid rounded"
style="width:100%;height:100%;object-fit:cover;"
alt="{{ $product->name }}">
<a href="{{ route('admin.product.remove-image', [$product, $image]) }}"
class="remove-btn btn btn-sm btn-danger position-absolute top-0 end-0 delete-image">
×
</a>
</div>
@endforeach
<label
id="uploadPlaceholder"
class="upload-placeholder"
for="imageInput"
style="cursor: pointer; width:150px; height:150px; display: flex; justify-content: center; align-items: center; border: 2px dashed #ccc; border-radius: 8px; padding: 20px; text-align: center;"
>
<div>📷<br><strong>آپلود یا کشیدن</strong></div>
<small style="color:#999;">JPG / PNG / JPEG / WEBP</small>
</label>
<input
id="imageInput"
name="images[]"
type="file"
accept=".jpg,.png,.jpeg,.webp"
multiple
style="display:none"
/>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,179 @@
@extends('admin.layouts.app')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">لیست محصولات</h1>
<div>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="javascript:void(0)">مدیریت محصولات</a></li>
<li class="breadcrumb-item active" aria-current="page">لیست محصولات</li>
</ol>
</nav>
</div>
</div>
@endsection
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
@error('success')
<span class="text-success">{{ $message }}</span>
@enderror
<div class="card-body p-3">
<form method="GET">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<div class="d-flex flex-wrap gap-1 project-list-main align-items-center">
<div class="d-flex me-2">
<input class="form-control me-2" type="search" name="search"
placeholder="جستجو محصول"
value="{{ request()->input('search') }}"
aria-label="جستجو">
<button class="btn btn-light" type="submit">جستجو</button>
</div>
<select id="choices-single-default" class="form-control" name="sort">
<option value="">مرتب‌سازی بر اساس</option>
<option
value="created_at" @selected(request()->missing('sort') || request()->input('sort') == 'created_at')>
جدیدترین
</option>
<option
value="name_asc" @selected(request()->input('sort') == 'name_asc')>
نام (صعودی)
</option>
<option
value="name_desc" @selected(request()->input('sort') == 'name_desc')>
نام (نزولی)
</option>
<option
value="price_asc" @selected(request()->input('sort') == 'price_asc')>
قیمت (کم به زیاد)
</option>
<option
value="price_desc" @selected(request()->input('sort') == 'price_desc')>
قیمت (زیاد به کم)
</option>
</select>
</div>
<div class="d-flex">
<a href="{{ route('admin.product.create') }}" class="btn btn-primary me-2">
<i class="ri-add-line me-1 fw-medium align-middle"></i>
ایجاد محصول
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Start::row-2 -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="table-responsive">
<table class="table text-nowrap table-bordered">
<thead>
<tr>
<th>نام</th>
<th>دسته‌ بندی</th>
<th>قیمت</th>
<th>تخفیف</th>
<th>موجودی</th>
<th>تاریخ ثبت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@foreach($products as $product)
<tr class="product-list">
<td>
<div class="d-flex">
<span class="avatar avatar-md avatar-square bg-light">
@if($product->defaultImage )
<img
src="{{ asset('storage/'.$product->defaultImage->file->path) }}"
class="w-100 h-100"
alt="{{ $product->name }}"
>
@else
<img
src="{{ asset('images/no-image.png') }}"
class="w-100 h-100"
alt="{{ $product->name }}"
>
@endif
</span>
<div class="ms-2">
<p class="fw-semibold mb-0 name-limit">
<a href="{{ route('admin.product.show', $product->id) }}">
{{ $product->name }} | {{ $product->en_name }}
</a>
</p>
</div>
</div>
</td>
<td>{{ $product->productCategory->name }}</td>
<td>
{{ number_format($product->price) }}
تومان
</td>
<td>
{{ $product->discount }} %
</td>
<td>
{{ $product->qty }}
</td>
<td>{{ $product->created_at->toJalali()->format('H:i Y-m-d') }}</td>
<td>
<div class="hstack gap-2 fs-15">
<a href="{{ route('admin.product.show', $product->id) }}"
class="btn btn-primary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="مشاهده">
<i class="ri-eye-line"></i>
</a>
<a href="{{ route('admin.product.edit', $product->id) }}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ti ti-pencil"></i>
</a>
<form action="{{ route('admin.product.destroy', $product->id) }}"
method="POST"
onsubmit="return confirm('آیا از حذف این محصول مطمئن هستید؟')"
>
@csrf
@method('delete')
<button type="submit" class="btn btn-icon btn-sm btn-danger-light">
<i class="ri-delete-bin-line"></i>
</button>
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- End::row-2 -->
</div>
</div>
@endsection
@@ -0,0 +1,104 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-body">
<!-- Product Images -->
<div class="image-upload-wrapper d-flex flex-wrap gap-2 mb-4"
style="border-radius: 8px; padding: 10px;">
<div style="width:150px;height:150px;">
@if($product->defaultImage)
<img src="{{ asset('storage/'.$product->defaultImage->file->path) }}"
class="img-fluid rounded"
style="width:100%;height:100%;object-fit:cover;"
alt="{{ $product->name }}">
@else
<img src="{{ asset('images/no-image.png') }}"
class="img-fluid rounded"
alt="{{ $product->name }}">
@endif
</div>
</div>
<div class="row gy-3">
<div class="col-xl-6">
<strong>نام محصول:</strong>
<p>{{ $product->name }}</p>
</div>
<div class="col-xl-6">
<strong>دسته‌بندی:</strong>
<p>{{ $product->productCategory->name }}</p>
</div>
<div class="col-xl-6">
<strong>قیمت:</strong>
<p>
{{ number_format($product->price) }}
تومان
</p>
</div>
<div class="col-xl-6">
<strong>قیمت تخفیفی:</strong>
<p>
{{ number_format(discount($product->price, $product->discount)) }}
تومان
</p>
</div>
<div class="col-xl-6">
<strong>موجودی:</strong>
<p>{{ $product->qty }}</p>
</div>
<div class="col-xl-6">
<strong>وضعیت:</strong>
<p>
@switch($product->status)
@case(\App\Enums\ProductStatus::DISABLE)
<span class="badge bg-danger">غیر فعال</span>
@break
@case(\App\Enums\ProductStatus::DRAFT)
<span class="badge bg-warning">پیش نویس</span>
@break
@case(\App\Enums\ProductStatus::PUBLISHED)
<span class="badge bg-primary"> منتشر شده</span>
@break
@case(\App\Enums\ProductStatus::ENABLE)
<span class="badge bg-success"> فعال</span>
@break
@endswitch
</p>
</div>
<div class="col-xl-12">
<strong>توضیحات:</strong>
<p>{{ $product->description }}</p>
</div>
</div>
</div>
<div class="card-footer text-end">
<a href="{{ route('admin.product.index') }}" class="btn btn-secondary">
بازگشت به لیست محصولات
</a>
<a href="{{ route('admin.product.edit', $product->id) }}" class="btn btn-warning ms-2">ویرایش محصول</a>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت استان‌ها</h1></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-8"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="جستجوی استان"></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-2"><a href="{{ route('admin.provinces.create') }}" class="btn btn-primary w-100">استان جدید</a></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table"><thead><tr><th>#</th><th>استان</th><th>عملیات</th></tr></thead><tbody>@forelse(($provinces ?? []) as $province)<tr><td>{{ $province->id }}</td><td>{{ $province->name }}</td><td><a href="{{ route('admin.provinces.edit',$province) }}" class="btn btn-secondary-light btn-sm">ویرایش</a><form class="d-inline" method="POST" action="{{ route('admin.provinces.destroy',$province) }}" onsubmit="return confirm('حذف استان؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="3" class="text-center text-muted py-5">استانی ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($provinces ?? collect())->links() }}</div>@endsection
@@ -0,0 +1,53 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
@error('general')
<span class="text-danger">{{ $message }}</span>
@enderror
<!-- Edit Category Form -->
<form action="{{ route('admin.settings.update', $setting->id) }}" method="POST"
enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="card-header">
<div class="card-title">ویرایش اطلاعات</div>
</div>
<div class="card-body">
<div class="row gy-3">
<div class="col-xl-12">
<br>
<label class="form-label">{{ $setting->title }}</label>
<textarea class="form-control" name="value" rows="3"
placeholder="">{{ old('value', $setting->value) }}</textarea>
@error('value')
<span class="text-danger">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,117 @@
@extends('admin.layouts.app')
@section('breadcrumb')
<div>
<h1 class="page-title fw-medium fs-18 mb-2">لیست اطلاعات</h1>
<div>
<nav>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="javascript:void(0)">مدیریت اطلاعات</a></li>
<li class="breadcrumb-item active" aria-current="page">لیست اطلاعات</li>
</ol>
</nav>
</div>
</div>
@endsection
@section('content')
<div class="main-content app-content">
@error('success')
<span class="text-success">{{ $message }}</span>
@enderror
<div class="container-fluid pt-4">
<!-- Page Header Close -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-body p-3">
<form method="GET">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-3">
<!-- Left: Add User + Sort Dropdown -->
<div class="d-flex flex-wrap gap-1 project-list-main align-items-center">
<div class="d-flex me-2">
<input
class="form-control me-2"
type="search"
name="search"
placeholder="جستجو"
value="{{ request()->input('search') }}"
aria-label="جستجو"
/>
<button class="btn btn-light" type="submit">جستجو</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Start::row-2 -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card ">
<div class="table-responsive">
<!-- Removed .table-responsive -->
<table class="table text-nowrap">
<thead>
<tr>
<th scope="col">شناسه</th>
<th scope="col">نام</th>
<th scope="col">مقدار</th>
<th scope="col">آپدیت</th>
<th scope="col">عملیات</th>
</tr>
</thead>
<tbody>
@foreach($settings as $setting)
<tr>
<td>
<div class="d-flex align-items-center">
<div class="flex-fill">
<a
href="javascript:void(0);"
class="fw-medium fs-14 d-block text-truncate"
>
{{ $setting->id }}
</a>
</div>
</div>
</td>
<td>{{ $setting->title }}</td>
<td>{{ $setting-> value }}</td>
<td>{{ $setting->updated_at->toJalali()->format('H:i Y-m-d') }}</td>
<td>
<div class="btn-list">
<a href="{{ route('admin.settings.edit', $setting->id )}}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ri-edit-line"></i>
</a>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
{{$settings->links()}}
</div>
</div>
<!-- End::row-2 -->
</div>
</div>
@endsection
@@ -0,0 +1,17 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">درج تور</h1><span class="text-muted fs-12">فیلدهای مورد نیاز سفر</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<form action="{{ isset($tour) ? route('admin.tours.update',$tour) : route('admin.tours.store') }}" method="POST" enctype="multipart/form-data">@csrf @if(false) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات تور</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">عنوان سفر *</label><input class="form-control" name="title" value="{{ old('title',$tour->title ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مدت تور (روز) *</label><input type="number" min="1" class="form-control" name="duration" value="{{ old('duration',$tour->duration ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مبدأ *</label><input class="form-control" name="origin" value="{{ old('origin',$tour->origin ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مقصد *</label><input class="form-control" name="destination" value="{{ old('destination',$tour->destination ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">قیمت پایه</label><input type="number" min="0" class="form-control" name="price" value="{{ old('price',$tour->price ?? '') }}"></div>
<div class="col-md-6"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$tour->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$tour->status ?? 1)==='0')>غیرفعال</option></select></div>
<div class="col-12"><label class="form-label">خلاصه تور *</label><textarea class="form-control" name="summary" rows="3" required>{{ old('summary',$tour->summary ?? '') }}</textarea></div>
<div class="col-12"><label class="form-label">توضیحات *</label><textarea class="form-control" name="descriptions" rows="7" required>{{ old('descriptions',$tour->descriptions ?? '') }}</textarea></div>
</div></div></div></div><div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">تصویر تور</div></div><div class="card-body"><input type="file" class="form-control" name="image" accept="image/*"><small class="text-muted d-block mt-2">تصویر اختیاری است.</small></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.tours.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($tour) ? 'ذخیره تغییرات' : 'ثبت تور' }}</button></div></div></form>
@if(false)<div class="card custom-card mt-3"><div class="card-header d-flex justify-content-between align-items-center"><div class="card-title mb-0">تاریخ‌های تور</div></div><div class="card-body"><form method="POST" action="{{ route('admin.tour-dates.store',$tour) }}">@csrf<div class="row g-2"><div class="col-md-3"><input class="form-control jalali-date" name="start_date_jalali" placeholder="شروع شمسی" required></div><div class="col-md-3"><input class="form-control jalali-date" name="end_date_jalali" placeholder="پایان شمسی" required></div><div class="col-md-2"><input type="number" min="0" class="form-control" name="price" placeholder="قیمت" required></div><div class="col-md-2"><input type="number" min="1" class="form-control" name="capacity" placeholder="ظرفیت" required></div><div class="col-md-2"><button class="btn btn-primary w-100">افزودن تاریخ</button></div></div></form><hr><div class="table-responsive"><table class="table text-nowrap"><thead><tr><th>شروع</th><th>پایان</th><th>قیمت</th><th>ظرفیت</th><th>وضعیت</th><th></th></tr></thead><tbody>@forelse(($tour->tourDates ?? []) as $date)<tr><td>{{ $date->start_date->toJalali()->format('Y/m/d') }}</td><td>{{ $date->end_date->toJalali()->format('Y/m/d') }}</td><td>{{ number_format($date->price) }}</td><td>{{ $date->capacity }}</td><td>{{ $date->status ? 'فعال':'غیرفعال' }}</td><td><form method="POST" action="{{ route('admin.tour-dates.destroy',$date) }}" onsubmit="return confirm('حذف تاریخ تور؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="6" class="text-center text-muted">تاریخی برای این تور ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div></div>@endif
</div>@endsection
@push('scripts')<script>$(function(){ if($.fn.persianDatepicker){ $('.jalali-date').persianDatepicker({format:'YYYY/MM/DD',autoClose:true}); }});</script>@endpush
@@ -0,0 +1,17 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">{{ isset($tour) ? 'ویرایش تور' : 'درج تور' }}</h1><span class="text-muted fs-12">فیلدهای مورد نیاز سفر</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<form action="{{ isset($tour) ? route('admin.tours.update',$tour) : route('admin.tours.store') }}" method="POST" enctype="multipart/form-data">@csrf @if(isset($tour)) @method('PUT') @endif
<div class="row g-3"><div class="col-xl-8"><div class="card custom-card"><div class="card-header"><div class="card-title">اطلاعات تور</div></div><div class="card-body"><div class="row gy-3">
<div class="col-md-6"><label class="form-label">عنوان سفر *</label><input class="form-control" name="title" value="{{ old('title',$tour->title ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مدت تور (روز) *</label><input type="number" min="1" class="form-control" name="duration" value="{{ old('duration',$tour->duration ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مبدأ *</label><input class="form-control" name="origin" value="{{ old('origin',$tour->origin ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">مقصد *</label><input class="form-control" name="destination" value="{{ old('destination',$tour->destination ?? '') }}" required></div>
<div class="col-md-6"><label class="form-label">قیمت پایه</label><input type="number" min="0" class="form-control" name="price" value="{{ old('price',$tour->price ?? '') }}"></div>
<div class="col-md-6"><label class="form-label">وضعیت</label><select class="form-control" name="status"><option value="1" @selected((string)old('status',$tour->status ?? 1)==='1')>فعال</option><option value="0" @selected((string)old('status',$tour->status ?? 1)==='0')>غیرفعال</option></select></div>
<div class="col-12"><label class="form-label">خلاصه تور *</label><textarea class="form-control" name="summary" rows="3" required>{{ old('summary',$tour->summary ?? '') }}</textarea></div>
<div class="col-12"><label class="form-label">توضیحات *</label><textarea class="form-control" name="descriptions" rows="7" required>{{ old('descriptions',$tour->descriptions ?? '') }}</textarea></div>
</div></div></div></div><div class="col-xl-4"><div class="card custom-card"><div class="card-header"><div class="card-title">تصویر تور</div></div><div class="card-body"><input type="file" class="form-control" name="image" accept="image/*"><small class="text-muted d-block mt-2">تصویر اختیاری است.</small></div></div></div></div>
<div class="card custom-card mt-3"><div class="card-footer d-flex justify-content-end gap-2"><a href="{{ route('admin.tours.index') }}" class="btn btn-light">انصراف</a><button class="btn btn-primary">{{ isset($tour) ? 'ذخیره تغییرات' : 'ثبت تور' }}</button></div></div></form>
@if(isset($tour))<div class="card custom-card mt-3"><div class="card-header d-flex justify-content-between align-items-center"><div class="card-title mb-0">تاریخ‌های تور</div></div><div class="card-body"><form method="POST" action="{{ route('admin.tour-dates.store',$tour) }}">@csrf<div class="row g-2"><div class="col-md-3"><input class="form-control jalali-date" name="start_date_jalali" placeholder="شروع شمسی" required></div><div class="col-md-3"><input class="form-control jalali-date" name="end_date_jalali" placeholder="پایان شمسی" required></div><div class="col-md-2"><input type="number" min="0" class="form-control" name="price" placeholder="قیمت" required></div><div class="col-md-2"><input type="number" min="1" class="form-control" name="capacity" placeholder="ظرفیت" required></div><div class="col-md-2"><button class="btn btn-primary w-100">افزودن تاریخ</button></div></div></form><hr><div class="table-responsive"><table class="table text-nowrap"><thead><tr><th>شروع</th><th>پایان</th><th>قیمت</th><th>ظرفیت</th><th>وضعیت</th><th></th></tr></thead><tbody>@forelse(($tour->tourDates ?? []) as $date)<tr><td>{{ $date->start_date->toJalali()->format('Y/m/d') }}</td><td>{{ $date->end_date->toJalali()->format('Y/m/d') }}</td><td>{{ number_format($date->price) }}</td><td>{{ $date->capacity }}</td><td>{{ $date->status ? 'فعال':'غیرفعال' }}</td><td><form method="POST" action="{{ route('admin.tour-dates.destroy',$date) }}" onsubmit="return confirm('حذف تاریخ تور؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-sm">حذف</button></form></td></tr>@empty<tr><td colspan="6" class="text-center text-muted">تاریخی برای این تور ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div></div>@endif
</div>@endsection
@push('scripts')<script>$(function(){ if($.fn.persianDatepicker){ $('.jalali-date').persianDatepicker({format:'YYYY/MM/DD',autoClose:true}); }});</script>@endpush
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">مدیریت تورها</h1><span class="text-muted fs-12">درج، ویرایش، حذف و مدیریت تورهای داخلی و خارجی</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-5"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="عنوان، مبدأ یا مقصد"></div><div class="col-md-2"><select class="form-control" name="status"><option value="">همه وضعیت‌ها</option><option value="1" @selected(request('status')==='1')>فعال</option><option value="0" @selected(request('status')==='0')>غیرفعال</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div><div class="col-md-3"><a href="{{ route('admin.tours.create') }}" class="btn btn-primary w-100"><i class="ri-add-line"></i> تور جدید</a></div></div></form></div></div><div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap table-hover mb-0"><thead><tr><th>عنوان تور</th><th>مسیر</th><th>مدت</th><th>قیمت</th><th>بازدید</th><th>وضعیت</th><th>عملیات</th></tr></thead><tbody>@forelse(($tours ?? []) as $tour)<tr><td><div class="fw-semibold">{{ $tour->title }}</div><small class="text-muted">#{{ $tour->id }}</small></td><td>{{ $tour->origin }} ← {{ $tour->destination }}</td><td>{{ $tour->duration }} روز</td><td>{{ number_format($tour->price ?? 0) }} تومان</td><td>{{ number_format($tour->views ?? 0) }}</td><td>@if($tour->status)<span class="badge bg-success-transparent">فعال</span>@else<span class="badge bg-danger-transparent">غیرفعال</span>@endif</td><td><div class="hstack gap-2"><a href="{{ route('admin.tours.show',$tour) }}" class="btn btn-primary-light btn-icon btn-sm"><i class="ri-eye-line"></i></a><a href="{{ route('admin.tours.edit',$tour) }}" class="btn btn-secondary-light btn-icon btn-sm"><i class="ri-edit-line"></i></a><form method="POST" action="{{ route('admin.tours.destroy',$tour) }}" onsubmit="return confirm('حذف این تور؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-icon btn-sm"><i class="ri-delete-bin-line"></i></button></form></div></td></tr>@empty<tr><td colspan="7" class="text-center py-5 text-muted">توری ثبت نشده است.</td></tr>@endforelse</tbody></table></div></div>{{ ($tours ?? collect())->links() }}</div>@endsection
@@ -0,0 +1,3 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">جزئیات تور</h1><span class="text-muted fs-12">مشاهده اطلاعات تور و تاریخ‌های قابل رزرو</span></div>@endsection
@section('content')<div class="container-fluid pt-4"><div class="card custom-card"><div class="card-body"><h4>{{ $tour->title }}</h4><p class="text-muted">{{ $tour->summary }}</p><div class="row gy-3"><div class="col-md-4"><strong>مسیر:</strong> {{ $tour->origin }} ← {{ $tour->destination }}</div><div class="col-md-4"><strong>مدت:</strong> {{ $tour->duration }} روز</div><div class="col-md-4"><strong>قیمت:</strong> {{ number_format($tour->price ?? 0) }} تومان</div><div class="col-12"><strong>توضیحات:</strong><div class="mt-2">{!! nl2br(e($tour->descriptions)) !!}</div></div></div></div><div class="card-footer"><a href="{{ route('admin.tours.edit',$tour) }}" class="btn btn-primary">ویرایش</a><a href="{{ route('admin.tours.index') }}" class="btn btn-light ms-2">بازگشت</a></div></div></div>@endsection
@@ -0,0 +1,89 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<div class="row">
<div class="col-xl-12">
<form
action="{{ route('admin.users.update', $user) }}"
method="POST"
enctype="multipart/form-data"
>
@csrf
@method('PUT')
<div class="card custom-card">
<div class="card-header">
<div class="card-title">ویرایش کاربر</div>
</div>
<div class="card-body">
<!-- User Fields -->
<div class="row gy-3">
<div class="col-xl-6">
<label class="form-label">نام</label>
<input
type="text"
class="form-control"
name="first_name"
value="{{old('first_name', $user->first_name)}}"
placeholder="نام را وارد کنید"
>
@error('first_name')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">نام خانوادگی</label>
<input type="text" class="form-control" name="last_name"
value="{{old('last_name', $user->last_name)}}"
placeholder="نام خانوادگی را وارد کنید">
@error('last_name')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">ایمیل</label>
<input type="email" class="form-control" name="email"
value="{{old('email', $user->email)}}"
placeholder="ایمیل را وارد کنید">
@error('email')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">شماره موبایل</label>
<input type="text" class="form-control" name="mobile"
value="{{old('mobile', $user->mobile)}}"
placeholder="شماره موبایل را وارد کنید">
@error('mobile')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-xl-6">
<label class="form-label">رمز عبور (در صورت تغییر)</label>
<input type="text" class="form-control" name="password" value="{{ old('password') }}"
placeholder="رمز عبور را وارد کنید">
@error('password')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<div class="card-footer text-end">
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
@@ -0,0 +1,5 @@
@extends('admin.layouts.app')
@section('breadcrumb')<div><h1 class="page-title fw-medium fs-18 mb-1">ثبت‌نام‌های سایت</h1><span class="text-muted fs-12">جستجو، مشاهده، ویرایش، حذف و مدیریت کاربران</span></div>@endsection
@section('content')<div class="container-fluid pt-4">@include('admin.partials.errors')
<div class="card custom-card"><div class="card-body"><form method="GET"><div class="row g-2"><div class="col-md-6"><input class="form-control" name="search" value="{{ request('search') }}" placeholder="نام، نام خانوادگی، ایمیل یا موبایل"></div><div class="col-md-3"><select name="sort" class="form-control"><option value="newest">جدیدترین ثبت‌نام</option><option value="oldest" @selected(request('sort')==='oldest')>قدیمی‌ترین</option><option value="name" @selected(request('sort')==='name')>نام</option></select></div><div class="col-md-2"><button class="btn btn-light w-100">جستجو</button></div></div></form></div></div>
<div class="card custom-card mt-3"><div class="table-responsive"><table class="table text-nowrap table-hover mb-0"><thead><tr><th>کاربر</th><th>ایمیل</th><th>موبایل</th><th>تاریخ ثبت‌نام</th><th>عملیات</th></tr></thead><tbody>@forelse(($users ?? []) as $user)<tr><td>{{ trim(($user->first_name ?? '').' '.($user->last_name ?? '')) ?: '-' }}</td><td>{{ $user->email }}</td><td>{{ $user->mobile ?? '-' }}</td><td>{{ isset($user->created_at) ? $user->created_at->toJalali()->format('Y/m/d H:i') : '-' }}</td><td><div class="hstack gap-2"><a href="{{ route('admin.users.show',$user) }}" class="btn btn-primary-light btn-icon btn-sm" title="مشاهده"><i class="ri-eye-line"></i></a><a href="{{ route('admin.users.edit',$user) }}" class="btn btn-secondary-light btn-icon btn-sm" title="ویرایش/تغییر رمز"><i class="ri-edit-line"></i></a><form method="POST" action="{{ route('admin.users.destroy',$user) }}" onsubmit="return confirm('آیا از حذف کاربر مطمئن هستید؟')">@csrf @method('DELETE')<button class="btn btn-danger-light btn-icon btn-sm" title="حذف"><i class="ri-delete-bin-line"></i></button></form></div></td></tr>@empty<tr><td colspan="5" class="text-center py-5 text-muted">کاربری یافت نشد.</td></tr>@endforelse</tbody></table></div></div>{{ ($users ?? collect())->links() }}</div>@endsection
+123
View File
@@ -0,0 +1,123 @@
@extends('admin.layouts.app')
@section('content')
<div class="main-content app-content">
<div class="container-fluid pt-4">
<!-- User Info Card -->
<div class="card custom-card mb-4">
<div class="card-header">
<div class="card-title">اطلاعات کاربر</div>
</div>
<div class="d-flex align-items-center p-3 pt-0">
<div class="card-body flex-grow-1">
<dl class="row mb-0">
<dt class="col-sm-3 my-2 fw-semibold">نام کامل:</dt>
<dd class="col-sm-9 my-2">{{ getUserFullName($user) }}</dd>
<dt class="col-sm-3 my-2 fw-semibold">ایمیل:</dt>
<dd class="col-sm-9 my-2">{{ $user->email }}</dd>
<dt class="col-sm-3 my-2 fw-semibold">شماره تلفن:</dt>
<dd class="col-sm-9 my-2">{{ $user->mobile }}</dd>
<dt class="col-sm-3 my-2 fw-semibold">تاریخ ثبت‌نام:</dt>
<dd class="col-sm-9 my-2">{{ $user->created_at->toJalali()->format('H:i Y/m/d') }}</dd>
</dl>
</div>
</div>
</div>
<!-- Order Table -->
<div class="row">
<div class="col-xl-12">
<div class="card custom-card mb-4">
<div class="card-header">
<div class="card-title">سفارشات اخیر کاربر</div>
</div>
<div class="table-responsive">
<table class="table text-nowrap table-hover">
<thead>
<tr>
<th>شناسه</th>
<th>مبلغ</th>
<th>وضعیت</th>
<th>تاریخ ثبت</th>
<th>عملیات</th>
</tr>
</thead>
<tbody>
@foreach($userOrders as $order)
<tr>
<td>
<div class="d-flex align-items-center gap-2">
<div>
<span class="fw-semibold d-block">#{{ $order->id }}</span>
</div>
</div>
</td>
<td>
{{ number_format($order->total_price )}}
تومان
</td>
<td>
<span class="text-info">
@switch($order->status)
@case(\App\Enums\OrderStatus::PENDING)
<span>در انتظار پرداخت</span>
@break
@case(\App\Enums\OrderStatus::PROCESSING)
<span>در حال پردازش</span>
@break
@case(\App\Enums\OrderStatus::SENT)
<span>ارسال شده</span>
@break
@case(\App\Enums\OrderStatus::DELIVERED)
<span>تحویل شده</span>
@break
@endswitch</span>
</td>
<td>{{$order->created_at->toJalali()->format('Y/m/d')}}</td>
<td>
<div class="btn-list">
<a href="{{ route('admin.orders.show' , $order->id) }}"
class="btn btn-primary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="مشاهده">
<i class="ri-eye-line"></i>
</a>
<a href="{{route('admin.orders.edit', $order->id)}}"
class="btn btn-secondary-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="ویرایش">
<i class="ti ti-pencil"></i>
</a>
<a href="javascript:void(0);"
onclick="if(confirm('آیا از حذف این سفارش مطمئن هستید؟')) { document.getElementById('delete-form-2').submit(); }"
class="btn btn-pink-light btn-icon btn-sm"
data-bs-toggle="tooltip" data-bs-placement="top" title="حذف">
<i class="ri-delete-bin-line"></i>
</a>
<form id="delete-form-2"
action="{{ route('admin.orders.destroy', $order->id) }}"
method="POST"
style="display:none;"
>
@csrf
@method('delete')
</form>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
+85
View File
@@ -0,0 +1,85 @@
<?php
use Illuminate\Support\Facades\Route;
Route::prefix('admin')->name('admin.')->group(function () {
Route::get('/', fn () => redirect()->route('admin.dashboard.index'))->name('index');
Route::prefix('auth')->name('auth.')->group(function () {
Route::middleware('guest:admin')->prefix('login')->name('login.')->group(function () {
Route::get('/', 'App\\Http\\Controllers\\Admin\\AuthController@login')->name('index');
Route::post('/', 'App\\Http\\Controllers\\Admin\\AuthController@loginPost')->name('post');
});
Route::get('logout', 'App\\Http\\Controllers\\Admin\\AuthController@logout')->middleware('auth:admin')->name('logout');
});
Route::middleware('auth:admin')->group(function () {
Route::get('dashboard', 'App\\Http\\Controllers\\Admin\\DashboardController@index')->name('dashboard.index');
Route::prefix('users')->name('users.')->controller('App\\Http\\Controllers\\Admin\\UserController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('{user}/show', 'show')->name('show');
Route::get('{user}/edit', 'edit')->name('edit');
Route::put('{user}/update', 'update')->name('update');
Route::delete('{user}/destroy', 'destroy')->name('destroy');
});
Route::prefix('admins')->name('admins.')->controller('App\\Http\\Controllers\\Admin\\AdminController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::get('{admin}/edit', 'edit')->name('edit');
Route::put('{admin}/update', 'update')->name('update');
Route::delete('{admin}/destroy', 'destroy')->name('destroy');
});
Route::prefix('flights')->name('flights.')->controller('App\\Http\\Controllers\\Admin\\FlightController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::get('{flight}/show', 'show')->name('show');
Route::get('{flight}/edit', 'edit')->name('edit');
Route::put('{flight}/update', 'update')->name('update');
Route::delete('{flight}/destroy', 'destroy')->name('destroy');
});
Route::prefix('tours')->name('tours.')->controller('App\\Http\\Controllers\\Admin\\TourController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::get('{tour}/show', 'show')->name('show');
Route::get('{tour}/edit', 'edit')->name('edit');
Route::put('{tour}/update', 'update')->name('update');
Route::delete('{tour}/destroy', 'destroy')->name('destroy');
});
Route::post('tours/{tour}/dates', 'App\\Http\\Controllers\\Admin\\TourDateController@store')->name('tour-dates.store');
Route::delete('tour-dates/{tourDate}', 'App\\Http\\Controllers\\Admin\\TourDateController@destroy')->name('tour-dates.destroy');
Route::prefix('bookings')->name('bookings.')->controller('App\\Http\\Controllers\\Admin\\BookingController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('{booking}/show', 'show')->name('show');
Route::patch('{booking}/update', 'update')->name('update');
});
Route::prefix('provinces')->name('provinces.')->controller('App\\Http\\Controllers\\Admin\\ProvinceController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::get('{province}/edit', 'edit')->name('edit');
Route::put('{province}/update', 'update')->name('update');
Route::delete('{province}/destroy', 'destroy')->name('destroy');
});
Route::prefix('cities')->name('cities.')->controller('App\\Http\\Controllers\\Admin\\CityController')->group(function () {
Route::get('/', 'index')->name('index');
Route::get('create', 'create')->name('create');
Route::post('store', 'store')->name('store');
Route::get('{city}/edit', 'edit')->name('edit');
Route::put('{city}/update', 'update')->name('update');
Route::delete('{city}/destroy', 'destroy')->name('destroy');
});
Route::get('activity-logs', 'App\\Http\\Controllers\\Admin\\ActivityLogController@index')->name('activity-logs.index');
});
});