Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 931d67cdd8 | |||
| 7107286c1a | |||
| 994add824f | |||
| 0b7e0b8e94 |
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromArray;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||||
|
|
||||||
|
class VisitsExport implements FromArray, WithHeadings, ShouldAutoSize
|
||||||
|
{
|
||||||
|
protected $rows;
|
||||||
|
|
||||||
|
public function __construct(array $rows)
|
||||||
|
{
|
||||||
|
$this->rows = $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function headings(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'شناسه',
|
||||||
|
'نام',
|
||||||
|
'نام خانوادگی',
|
||||||
|
'ایمیل',
|
||||||
|
'موبایل',
|
||||||
|
'تاریخ ثبتنام',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function array(): array
|
||||||
|
{
|
||||||
|
return $this->rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,16 +4,100 @@
|
|||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\AdminStoreRequest;
|
||||||
|
use App\Http\Requests\AdminUpdateRequest;
|
||||||
use App\Models\Admin;
|
use App\Models\Admin;
|
||||||
|
use App\Models\Permission;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
|
||||||
class AdminController extends Controller
|
class AdminController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$admins = Admin::query()
|
$admins = Admin::query()
|
||||||
|
->with('permissions')
|
||||||
->latest()
|
->latest()
|
||||||
->paginate(10);
|
->paginate(10);
|
||||||
|
|
||||||
return view('admin.admins.index', compact('admins'));
|
return view('admin.admins.index', compact('admins'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$permissions = Permission::query()
|
||||||
|
->orderBy('name')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'admin.admins.create',
|
||||||
|
compact('permissions')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(AdminStoreRequest $request)
|
||||||
|
{
|
||||||
|
$data = $request->validated();
|
||||||
|
|
||||||
|
$permissions = $data['permissions'] ?? [];
|
||||||
|
|
||||||
|
unset($data['permissions']);
|
||||||
|
|
||||||
|
$data['password'] = Hash::make($data['password']);
|
||||||
|
|
||||||
|
$admin = Admin::create($data);
|
||||||
|
|
||||||
|
$admin->permissions()->sync($permissions);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('admin.admins.index')
|
||||||
|
->with('success', 'مدیر با موفقیت ایجاد شد.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Admin $admin)
|
||||||
|
{
|
||||||
|
$permissions = Permission::query()
|
||||||
|
->orderBy('name')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$admin->load('permissions');
|
||||||
|
|
||||||
|
return view(
|
||||||
|
'admin.admins.edit',
|
||||||
|
compact('admin', 'permissions')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(AdminUpdateRequest $request, Admin $admin)
|
||||||
|
{
|
||||||
|
$data = $request->validated();
|
||||||
|
|
||||||
|
$permissions = $data['permissions'] ?? [];
|
||||||
|
|
||||||
|
unset($data['permissions']);
|
||||||
|
|
||||||
|
if (!empty($data['password'])) {
|
||||||
|
$data['password'] = Hash::make($data['password']);
|
||||||
|
} else {
|
||||||
|
unset($data['password']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$admin->update($data);
|
||||||
|
|
||||||
|
$admin->permissions()->sync($permissions);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('admin.admins.index')
|
||||||
|
->with('success', 'اطلاعات مدیر با موفقیت ویرایش شد.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Admin $admin)
|
||||||
|
{
|
||||||
|
$admin->permissions()->detach();
|
||||||
|
|
||||||
|
$admin->delete();
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('admin.admins.index')
|
||||||
|
->with('success', 'مدیر با موفقیت حذف شد.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ use App\Models\Flight;
|
|||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
use App\Models\Tour;
|
use App\Models\Tour;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use App\Exports\VisitsExport;
|
||||||
|
use App\Models\VisitStatistic;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Hekmatinasser\Verta\Verta;
|
||||||
|
|
||||||
class DashboardController extends Controller
|
class DashboardController extends Controller
|
||||||
{
|
{
|
||||||
@@ -39,4 +44,25 @@ class DashboardController extends Controller
|
|||||||
'paymentsCount'
|
'paymentsCount'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function exportExcel()
|
||||||
|
{
|
||||||
|
// ۱. لیست کاربران با فیلدهایی که واقعاً در جدول users داری
|
||||||
|
$users = User::select('id', 'first_name', 'last_name', 'email', 'mobile', 'created_at')->get();
|
||||||
|
|
||||||
|
|
||||||
|
// ۲. تبدیل به آرایه برای اکسل
|
||||||
|
$rows = $users->map(fn($user) => [
|
||||||
|
$user->id,
|
||||||
|
$user->first_name,
|
||||||
|
$user->last_name,
|
||||||
|
$user->email,
|
||||||
|
$user->mobile,
|
||||||
|
$user->created_at ? Verta::instance($user->created_at)->format('Y/m/d') : '-',
|
||||||
|
])->toArray();
|
||||||
|
|
||||||
|
// ۳. تغییر کلاس اکسل و اسم فایل
|
||||||
|
return Excel::download(new VisitsExport($rows), 'users-report-' . now()->format('Y-m-d') . '.xlsx');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/* ========================================
|
||||||
|
Admin Panel
|
||||||
|
Airline Agency
|
||||||
|
======================================== */
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f5f7fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Main admin layout */
|
||||||
|
|
||||||
|
.admin-wrapper {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
|
||||||
|
.admin-sidebar {
|
||||||
|
width: 260px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #ffffff;
|
||||||
|
border-left: 1px solid #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Main content */
|
||||||
|
|
||||||
|
.admin-content {
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Cards */
|
||||||
|
|
||||||
|
.admin-card {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Dashboard stat cards */
|
||||||
|
|
||||||
|
.admin-stat-card {
|
||||||
|
transition: all .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-stat-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sidebar links */
|
||||||
|
|
||||||
|
.admin-sidebar .nav-link {
|
||||||
|
color: #495057;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-sidebar .nav-link:hover {
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-sidebar .nav-link.active {
|
||||||
|
background-color: #eaf2ff;
|
||||||
|
color: #0d6efd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Airline icon box */
|
||||||
|
|
||||||
|
.admin-icon-box {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tables */
|
||||||
|
|
||||||
|
.admin-table th {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-table td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Breadcrumb */
|
||||||
|
|
||||||
|
.admin-breadcrumb {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
|
||||||
|
@media (max-width: 991px) {
|
||||||
|
|
||||||
|
.admin-sidebar {
|
||||||
|
width: 100%;
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'تغییر رمز کاربر')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid pt-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
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="card custom-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h5 class="mb-0">تغییر رمز عبور — {{ $user->full_name ?? $user->name }}</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST" action="{{ route('admin.users.update-password', $user) }}">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">رمز عبور جدید</label>
|
||||||
|
<input type="password" name="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror">
|
||||||
|
@error('password')
|
||||||
|
<div class="invalid-feedback">{{ $message }}</div>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">تکرار رمز جدید</label>
|
||||||
|
<input type="password" name="password_confirmation"
|
||||||
|
class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button type="submit" class="btn btn-success">ذخیره رمز</button>
|
||||||
|
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary">انصراف</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
Reference in New Issue
Block a user