added leave request, profile and staff members controllers

This commit is contained in:
Kwesi Banson Jnr
2026-08-20 09:30:43 +00:00
parent 1c4d32833a
commit 81d26dc138
152 changed files with 1627 additions and 152101 deletions

View File

@@ -0,0 +1,143 @@
<?php
namespace App\Http\Controllers;
use App\Models\LeaveRequest;
use App\Models\StaffMember;
use Illuminate\Http\Request;
use Carbon\Carbon;
class LeaveRequestController extends Controller
{
public function index(Request $request)
{
$query = LeaveRequest::with('staff');
// Search by Staff Name
if ($request->filled('search')) {
$search = $request->search;
$query->whereHas('staff', function($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
}
// Filter by Status
if ($request->filled('status')) {
$query->where('status', $request->status);
} else {
// Default to showing pending requests first if no filter is applied
$query->orderByRaw("FIELD(status, 'PENDING', 'APPROVED', 'REJECTED')");
}
$leaveRequests = $query->orderBy('created_at', 'desc')->paginate(15);
$leaveRequests->appends($request->query());
// KPIs for HR
$pendingCount = LeaveRequest::where('status', 'PENDING')->count();
$approvedThisMonth = LeaveRequest::where('status', 'APPROVED')
->whereMonth('start_date', Carbon::now()->month)
->whereYear('start_date', Carbon::now()->year)
->count();
$data = [
'leaveRequests' => $leaveRequests,
'pendingCount' => $pendingCount,
'approvedThisMonth' => $approvedThisMonth,
];
return view('leave.index', $data);
}
public function myLeave()
{
// Find the staff profile of the currently logged-in user
// Adjust this logic if you link Users to StaffMembers differently (e.g., via a staff_id foreign key)
$staff = StaffMember::where('email', auth()->user()->email)->firstOrFail();
// Fetch their leave history, latest first
$leaveRequests = LeaveRequest::where('staff_member_id', $staff->id)
->orderBy('created_at', 'desc')
->paginate(10);
$data = [
'staff' => $staff,
'leaveRequests' => $leaveRequests,
];
return view('leave.my_leave', $data);
}
public function store(Request $request)
{
$validated = $request->validate([
'staff_member_id' => 'required|exists:staff_members,id',
'leave_type' => 'required|string',
'start_date' => 'required|date',
'end_date' => 'required|date|after_or_equal:start_date',
'reason' => 'required|string',
]);
$start = Carbon::parse($validated['start_date']);
$end = Carbon::parse($validated['end_date']);
// Calculate total days excluding weekends
$totalDays = $start->diffInDaysFiltered(function (Carbon $date) {
return !$date->isWeekend();
}, $end) + 1; // +1 to include both the start and end day
if ($validated['leave_type'] === 'Annual') {
$staff = StaffMember::find($validated['staff_member_id']);
if ($staff->annual_leave_balance < $totalDays) {
return response()->json([
'success' => false,
'message' => "Insufficient balance. Requested: $totalDays days. Available: {$staff->annual_leave_balance} days."
], 422);
}
}
$validated['total_days'] = $totalDays;
$validated['status'] = 'PENDING';
LeaveRequest::create($validated);
return response()->json(['success' => true, 'message' => 'Leave request submitted successfully!']);
}
public function updateStatus(Request $request, $id)
{
$leaveRequest = LeaveRequest::findOrFail($id);
$validated = $request->validate([
'status' => 'required|in:APPROVED,REJECTED',
'admin_remarks' => 'nullable|string',
]);
if ($validated['status'] === 'APPROVED' && $leaveRequest->status !== 'APPROVED') {
if ($leaveRequest->leave_type === 'Annual') {
$staff = $leaveRequest->staff;
$staff->annual_leave_balance -= $leaveRequest->total_days;
$staff->save();
}
}
if ($validated['status'] === 'REJECTED' && $leaveRequest->status === 'APPROVED') {
if ($leaveRequest->leave_type === 'Annual') {
$staff = $leaveRequest->staff;
$staff->annual_leave_balance += $leaveRequest->total_days;
$staff->save();
}
}
$leaveRequest->update([
'status' => $validated['status'],
'admin_remarks' => $validated['admin_remarks'],
'approved_by' => auth()->id(), // Track who approved it
]);
return response()->json(['success' => true, 'message' => 'Leave status updated successfully!']);
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace App\Http\Controllers;
use App\Models\StaffMember;
use App\Models\StaffDependent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class ProfileController extends Controller
{
public function index()
{
$staff = StaffMember::with('dependents')->where('email', auth()->user()->email)->firstOrFail();
return view('profile.index', compact('staff'));
}
public function update(Request $request)
{
$staff = StaffMember::where('email', auth()->user()->email)->firstOrFail();
$validated = $request->validate([
'name' => 'required|string|max:200',
'phone' => 'nullable|string|max:200',
'personal_email' => 'nullable|email|max:191',
'location_country' => 'nullable|string|max:191',
'birth_month' => 'nullable|string|size:2',
'birth_day' => 'nullable|string|size:2',
'photo' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
// Combine month and day if both are provided (e.g., "12-25")
if (!empty($request->birth_month) && !empty($request->birth_day)) {
$validated['dob'] = $request->birth_month . '-' . $request->birth_day;
} else {
$validated['dob'] = null;
}
// Clean up temporary keys
unset($validated['birth_month'], $validated['birth_day'], $validated['photo']);
if ($request->hasFile('photo')) {
if ($staff->profile_pic && Storage::disk('public')->exists($staff->profile_pic)) {
Storage::disk('public')->delete($staff->profile_pic);
}
$validated['profile_pic'] = $request->file('photo')->store('staff_profiles', 'public');
}
unset($validated['photo']);
$staff->update($validated);
return response()->json(['success' => true, 'message' => 'Profile updated successfully!']);
}
// --- DEPENDENTS / EMERGENCY CONTACTS CRUD ---
public function storeDependent(Request $request)
{
$staff = StaffMember::where('email', auth()->user()->email)->firstOrFail();
$validated = $request->validate([
'fullname' => 'required|string|max:255',
'relationship' => 'required|string|max:192',
'phone' => 'nullable|string|max:20',
'medical_details' => 'nullable|string',
]);
$validated['staff_id'] = $staff->id;
StaffDependent::create($validated);
return response()->json(['success' => true, 'message' => 'Emergency contact added successfully!']);
}
public function updateDependent(Request $request, $id)
{
$staff = StaffMember::where('email', auth()->user()->email)->firstOrFail();
$dependent = StaffDependent::where('staff_id', $staff->id)->findOrFail($id);
$validated = $request->validate([
'fullname' => 'required|string|max:255',
'relationship' => 'required|string|max:192',
'phone' => 'nullable|string|max:20',
'medical_details' => 'nullable|string',
]);
$dependent->update($validated);
return response()->json(['success' => true, 'message' => 'Emergency contact updated successfully!']);
}
public function destroyDependent($id)
{
$staff = StaffMember::where('email', auth()->user()->email)->firstOrFail();
$dependent = StaffDependent::where('staff_id', $staff->id)->findOrFail($id);
$dependent->delete();
return redirect()->back()->with('success', 'Emergency contact removed.');
}
}

View File

@@ -1,16 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class StaffController extends Controller
{
public function index()
{
$data = [
'page_title' => 'Dashboard'
];
return view('staff.index', $data);
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace App\Http\Controllers;
use App\Models\StaffMember;
use App\Models\Department;
use App\Models\Country;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;
class StaffMembersController extends Controller
{
public function index(Request $request)
{
$query = StaffMember::query();
// 1. Search Filter
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhere('designation', 'like', "%{$search}%")
->orWhere('phone', 'like', "%{$search}%");
});
}
// 2. Department Filter
if ($request->filled('department_id')) {
$query->where('department_id', $request->department_id);
}
// 3. Status Filter
if ($request->filled('status')) {
$query->where('status', $request->status);
}
$staffMembers = $query->orderBy('name', 'asc')->paginate(12);
$staffMembers->appends($request->query());
// Fetch dynamic dropdown lists
$departments = Department::orderBy('name', 'asc')->get();
$countries = Country::orderBy('en_short_name', 'asc')->get();
$data = [
'staffMembers' => $staffMembers,
'departments' => $departments,
'countries' => $countries,
];
return view('staff.index', $data);
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:200',
'designation' => 'required|string|max:191',
'email' => 'required|email|max:200',
'phone' => 'nullable|string|max:200',
'department_id' => 'required|integer',
'location_country' => 'nullable|string|max:191',
'status' => 'required|string|max:20',
'photo' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
if ($request->hasFile('photo')) {
$validated['profile_pic'] = $request->file('photo')->store('staff_profiles', 'public');
}
$validated['created_by'] = auth()->id() ?? 1;
$validated['password'] = Hash::make('default_password');
$validated['hire_date'] = now();
StaffMember::create($validated);
return response()->json(['success' => true, 'message' => 'Staff member added successfully!']);
}
public function update(Request $request, $id)
{
$staff = StaffMember::findOrFail($id);
$validated = $request->validate([
'name' => 'required|string|max:200',
'designation' => 'required|string|max:191',
'email' => 'required|email|max:200',
'phone' => 'nullable|string|max:200',
'department_id' => 'required|integer',
'location_country' => 'nullable|string|max:191',
'status' => 'required|string|max:20',
'photo' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
if ($request->hasFile('photo')) {
if ($staff->profile_pic && Storage::disk('public')->exists($staff->profile_pic)) {
Storage::disk('public')->delete($staff->profile_pic);
}
$validated['profile_pic'] = $request->file('photo')->store('staff_profiles', 'public');
}
$validated['modified_by'] = auth()->id() ?? 1;
$staff->update($validated);
return response()->json(['success' => true, 'message' => 'Staff member updated successfully!']);
}
public function destroy($id)
{
$staff = StaffMember::findOrFail($id);
if ($staff->profile_pic && Storage::disk('public')->exists($staff->profile_pic)) {
Storage::disk('public')->delete($staff->profile_pic);
}
$staff->delete();
return redirect()->back()->with('success', 'Staff member removed.');
}
public function getUpcomingBirthdays()
{
$today = Carbon::now();
$thirtyDaysFromNow = Carbon::now()->addDays(30);
$currentMonthDay = $today->format('m-d');
$futureMonthDay = $thirtyDaysFromNow->format('m-d');
if ($currentMonthDay <= $futureMonthDay) {
// Simple range check within the same calendar year
$upcomingStaff = StaffMember::whereBetween('dob', [$currentMonthDay, $futureMonthDay])
->orderBy('dob', 'asc')
->get();
} else {
// Handles the year-end crossover (e.g., looking from December into January)
$upcomingStaff = StaffMember::where(function($query) use ($currentMonthDay, $futureMonthDay) {
$query->where('dob', '>=', $currentMonthDay)
->orWhere('dob', '<=', $futureMonthDay);
})
->orderBy('dob', 'asc')
->get();
}
return $upcomingStaff;
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class LeaveRequest extends Model
{
protected $casts = [
'start_date' => 'date',
'end_date' => 'date',
];
protected $guarded = ['id'];
public function staff()
{
return $this->belongsTo(StaffMember::class, 'staff_member_id');
}
// In StaffMember.php
public function leaveRequests()
{
return $this->hasMany(LeaveRequest::class, 'staff_member_id');
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class StaffDependent extends Model
{
protected $table = 'staff_dependents';
protected $guarded = [];
public function staff()
{
return $this->belongsTo(StaffMember::class, 'staff_id');
}
}

View File

@@ -21,9 +21,16 @@ class StaffMember extends Authenticatable
'password',
];
public function leaveRequests() {
return $this->hasMany(LeaveRequest::class, 'staff_member_id');
}
public function dependents() {
return $this->hasMany(StaffDependent::class, 'staff_id');
}
// 4. Cast dates correctly
protected $casts = [
'dob' => 'date',
// 'dob' => 'date',
'hire_date' => 'datetime',
'password' => 'hashed', // Laravel 10+ password casting
];

0
bootstrap/cache/.gitignore vendored Normal file → Executable file
View File

View File

@@ -10,7 +10,8 @@
"barryvdh/laravel-dompdf": "^3.1",
"laravel/framework": "^11.31",
"laravel/tinker": "^2.9",
"laravel/ui": "^4.6"
"laravel/ui": "^4.6",
"symfony/filesystem": "^7.4"
},
"require-dev": {
"fakerphp/faker": "^1.23",

72
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "711d540522a4f4b214df3c5d35f3f416",
"content-hash": "4090af069360d112f49872b58f33e0a6",
"packages": [
{
"name": "barryvdh/laravel-dompdf",
@@ -4280,6 +4280,76 @@
],
"time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/filesystem",
"version": "v7.4.15",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "ff16a16bf87fdf264638b8f6995b3515975e3c79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/ff16a16bf87fdf264638b8f6995b3515975e3c79",
"reference": "ff16a16bf87fdf264638b8f6995b3515975e3c79",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
"symfony/process": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v7.4.15"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-07-22T07:36:05+00:00"
},
{
"name": "symfony/finder",
"version": "v7.4.5",

View File

@@ -52,6 +52,12 @@ return [
'url' => env('APP_URL').'/client_files',
'visibility' => 'public',
],
'staff_images' => [
'driver' => 'local',
'root' => public_path('staff_images'),
'url' => env('APP_URL').'/staff_images',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),

View File

@@ -15,3 +15,4 @@ resources/views/
└── users/
├── index.blade.php
└── create.blade.php

View File

@@ -1,9 +0,0 @@
Bootstrap-only ERP starter pages
Files:
- index.html: dashboard page
- blank.html: general page layout
- assets/css/bootstrap.min.css: original Bootstrap 5 CSS
- assets/js/bootstrap.bundle.min.js: original Bootstrap 5 JS bundle
These pages avoid the Adminator-specific utility classes such as peer, mT-30, bgc-white, bd, and similar theme classes. The markup uses Bootstrap classes and components directly.

View File

@@ -1,162 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ERP General Page</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
</head>
<body class="bg-body-tertiary">
<nav class="navbar navbar-expand-lg bg-body border-bottom sticky-top">
<div class="container-fluid">
<button class="btn btn-outline-secondary d-lg-none me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebar" aria-controls="sidebar">
Menu
</button>
<a class="navbar-brand fw-semibold" href="index.html">ERP</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#topbar" aria-controls="topbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="topbar">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="index.html">Dashboard</a></li>
<li class="nav-item"><a class="nav-link active" aria-current="page" href="blank.html">General Page</a></li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<aside class="col-lg-2 d-none d-lg-block bg-body border-end min-vh-100 p-3">
<div class="list-group list-group-flush">
<a class="list-group-item list-group-item-action" href="index.html">Dashboard</a>
<a class="list-group-item list-group-item-action active" href="blank.html">General Page</a>
<a class="list-group-item list-group-item-action" href="#">Customers</a>
<a class="list-group-item list-group-item-action" href="#">Invoices</a>
<a class="list-group-item list-group-item-action" href="#">Reports</a>
<a class="list-group-item list-group-item-action" href="#">Settings</a>
</div>
</aside>
<div class="offcanvas offcanvas-start d-lg-none" tabindex="-1" id="sidebar" aria-labelledby="sidebarLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="sidebarLabel">ERP</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div class="list-group list-group-flush">
<a class="list-group-item list-group-item-action" href="index.html">Dashboard</a>
<a class="list-group-item list-group-item-action active" href="blank.html">General Page</a>
<a class="list-group-item list-group-item-action" href="#">Customers</a>
<a class="list-group-item list-group-item-action" href="#">Invoices</a>
<a class="list-group-item list-group-item-action" href="#">Reports</a>
<a class="list-group-item list-group-item-action" href="#">Settings</a>
</div>
</div>
</div>
<main class="col-lg-10 p-4">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="index.html">Dashboard</a></li>
<li class="breadcrumb-item active" aria-current="page">General Page</li>
</ol>
</nav>
<div class="d-flex flex-column flex-md-row justify-content-between gap-3 mb-4">
<div>
<h1 class="h3 mb-1">General Page</h1>
<p class="text-secondary mb-0">A Bootstrap-only starter page for ERP screens</p>
</div>
<div class="d-flex gap-2">
<button class="btn btn-outline-secondary" type="button">Cancel</button>
<button class="btn btn-primary" type="button">Save Changes</button>
</div>
</div>
<div class="row g-4">
<div class="col-xl-8">
<div class="card">
<div class="card-header bg-body">
<h2 class="h5 mb-0">Record Details</h2>
</div>
<div class="card-body">
<form class="row g-3">
<div class="col-md-6">
<label for="customerName" class="form-label">Customer Name</label>
<input type="text" class="form-control" id="customerName" placeholder="Enter customer name">
</div>
<div class="col-md-6">
<label for="customerEmail" class="form-label">Email</label>
<input type="email" class="form-control" id="customerEmail" placeholder="name@example.com">
</div>
<div class="col-md-6">
<label for="department" class="form-label">Department</label>
<select id="department" class="form-select">
<option selected>Choose...</option>
<option>Finance</option>
<option>Operations</option>
<option>Sales</option>
</select>
</div>
<div class="col-md-6">
<label for="status" class="form-label">Status</label>
<select id="status" class="form-select">
<option selected>Active</option>
<option>Pending</option>
<option>Inactive</option>
</select>
</div>
<div class="col-12">
<label for="notes" class="form-label">Notes</label>
<textarea class="form-control" id="notes" rows="5" placeholder="Add notes"></textarea>
</div>
<div class="col-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="sendNotification">
<label class="form-check-label" for="sendNotification">
Send notification after saving
</label>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-xl-4">
<div class="card mb-4">
<div class="card-header bg-body">
<h2 class="h5 mb-0">Summary</h2>
</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-5">Owner</dt>
<dd class="col-7">Admin User</dd>
<dt class="col-5">Created</dt>
<dd class="col-7">May 31, 2026</dd>
<dt class="col-5">Updated</dt>
<dd class="col-7">Today</dd>
</dl>
</div>
</div>
<div class="card">
<div class="card-header bg-body">
<h2 class="h5 mb-0">Actions</h2>
</div>
<div class="list-group list-group-flush">
<button class="list-group-item list-group-item-action" type="button">Duplicate record</button>
<button class="list-group-item list-group-item-action" type="button">Print summary</button>
<button class="list-group-item list-group-item-action text-danger" type="button">Archive record</button>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script src="assets/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -1,205 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ERP Dashboard</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
</head>
<body class="bg-body-tertiary">
<nav class="navbar navbar-expand-lg bg-body border-bottom sticky-top">
<div class="container-fluid">
<button class="btn btn-outline-secondary d-lg-none me-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebar" aria-controls="sidebar">
Menu
</button>
<a class="navbar-brand fw-semibold" href="index.html">ERP</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#topbar" aria-controls="topbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="topbar">
<form class="d-flex ms-lg-4 my-3 my-lg-0 w-100" role="search">
<input class="form-control" type="search" placeholder="Search records" aria-label="Search">
</form>
<div class="dropdown ms-lg-3">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
Admin
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="blank.html">General page</a></li>
<li><a class="dropdown-item" href="#">Settings</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Sign out</a></li>
</ul>
</div>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<aside class="col-lg-2 d-none d-lg-block bg-body border-end min-vh-100 p-3">
<div class="list-group list-group-flush">
<a class="list-group-item list-group-item-action active" href="index.html">Dashboard</a>
<a class="list-group-item list-group-item-action" href="blank.html">General Page</a>
<a class="list-group-item list-group-item-action" href="#">Customers</a>
<a class="list-group-item list-group-item-action" href="#">Invoices</a>
<a class="list-group-item list-group-item-action" href="#">Reports</a>
<a class="list-group-item list-group-item-action" href="#">Settings</a>
</div>
</aside>
<div class="offcanvas offcanvas-start d-lg-none" tabindex="-1" id="sidebar" aria-labelledby="sidebarLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="sidebarLabel">ERP</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<div class="list-group list-group-flush">
<a class="list-group-item list-group-item-action active" href="index.html">Dashboard</a>
<a class="list-group-item list-group-item-action" href="blank.html">General Page</a>
<a class="list-group-item list-group-item-action" href="#">Customers</a>
<a class="list-group-item list-group-item-action" href="#">Invoices</a>
<a class="list-group-item list-group-item-action" href="#">Reports</a>
<a class="list-group-item list-group-item-action" href="#">Settings</a>
</div>
</div>
</div>
<main class="col-lg-10 p-4">
<div class="d-flex flex-column flex-md-row justify-content-between gap-3 mb-4">
<div>
<h1 class="h3 mb-1">Dashboard</h1>
<p class="text-secondary mb-0">Business overview and recent activity</p>
</div>
<div class="d-flex gap-2">
<button class="btn btn-outline-secondary" type="button">Export</button>
<button class="btn btn-primary" type="button">New Record</button>
</div>
</div>
<div class="row g-3 mb-4">
<div class="col-sm-6 col-xl-3">
<div class="card h-100">
<div class="card-body">
<p class="text-secondary mb-1">Revenue</p>
<h2 class="h4 mb-1">GHS 128,400</h2>
<span class="badge text-bg-success">Up 12%</span>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card h-100">
<div class="card-body">
<p class="text-secondary mb-1">Orders</p>
<h2 class="h4 mb-1">1,284</h2>
<span class="badge text-bg-primary">Today</span>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card h-100">
<div class="card-body">
<p class="text-secondary mb-1">Pending</p>
<h2 class="h4 mb-1">38</h2>
<span class="badge text-bg-warning">Review</span>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-3">
<div class="card h-100">
<div class="card-body">
<p class="text-secondary mb-1">Customers</p>
<h2 class="h4 mb-1">864</h2>
<span class="badge text-bg-info">Active</span>
</div>
</div>
</div>
</div>
<div class="row g-4">
<div class="col-xl-8">
<div class="card">
<div class="card-header bg-body d-flex justify-content-between align-items-center">
<h2 class="h5 mb-0">Recent Transactions</h2>
<a class="btn btn-sm btn-outline-primary" href="#">View all</a>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th scope="col">Reference</th>
<th scope="col">Customer</th>
<th scope="col">Status</th>
<th scope="col" class="text-end">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>INV-1024</td>
<td>North Ridge Ltd</td>
<td><span class="badge text-bg-success">Paid</span></td>
<td class="text-end">GHS 12,000</td>
</tr>
<tr>
<td>INV-1025</td>
<td>Adenta Stores</td>
<td><span class="badge text-bg-warning">Pending</span></td>
<td class="text-end">GHS 4,850</td>
</tr>
<tr>
<td>INV-1026</td>
<td>Osu Supplies</td>
<td><span class="badge text-bg-secondary">Draft</span></td>
<td class="text-end">GHS 9,300</td>
</tr>
<tr>
<td>INV-1027</td>
<td>Labone Foods</td>
<td><span class="badge text-bg-success">Paid</span></td>
<td class="text-end">GHS 7,600</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-xl-4">
<div class="card mb-4">
<div class="card-header bg-body">
<h2 class="h5 mb-0">Tasks</h2>
</div>
<div class="list-group list-group-flush">
<label class="list-group-item d-flex gap-3">
<input class="form-check-input flex-shrink-0" type="checkbox" value="">
<span>Approve purchase requests</span>
</label>
<label class="list-group-item d-flex gap-3">
<input class="form-check-input flex-shrink-0" type="checkbox" value="">
<span>Review pending invoices</span>
</label>
<label class="list-group-item d-flex gap-3">
<input class="form-check-input flex-shrink-0" type="checkbox" value="">
<span>Send stock report</span>
</label>
</div>
</div>
<div class="card">
<div class="card-body">
<h2 class="h5">Monthly Target</h2>
<p class="text-secondary">Current progress toward the sales target.</p>
<div class="progress" role="progressbar" aria-label="Monthly target" aria-valuenow="72" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar" style="width: 72%">72%</div>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
</div>
<script src="assets/js/bootstrap.bundle.min.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

View File

@@ -1,7 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator circle logo icon">
<title>Adminator Logo Circle</title>
<!-- Circular background -->
<circle cx="32" cy="32" r="30" fill="#4B7CF3" />
<!-- Stylised "A" -->
<path d="M20 46L32 18l12 28h-6l-3-7H29l-3 7h-6zm13-11l-4-10-4 10h8z" fill="#FFFFFF" />
</svg>

Before

Width:  |  Height:  |  Size: 380 B

View File

@@ -1,13 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator gradient logo icon">
<title>Adminator Logo Gradient</title>
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4B7CF3;stop-opacity:1" />
<stop offset="100%" style="stop-color:#7B4BF3;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Rounded square background with gradient -->
<rect width="64" height="64" rx="12" fill="url(#grad)" />
<!-- Stylised "A" -->
<path d="M20 46L32 18l12 28h-6l-3-7H29l-3 7h-6zm13-11l-4-10-4 10h8z" fill="#FFFFFF" />
</svg>

Before

Width:  |  Height:  |  Size: 661 B

View File

@@ -1,7 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator outline logo icon">
<title>Adminator Logo Outline</title>
<!-- Hexagon outline -->
<polygon points="32 4 56 18 56 46 32 60 8 46 8 18" fill="none" stroke="#4B7CF3" stroke-width="4" />
<!-- Stylised "A" -->
<path d="M20 44L32 18l12 26h-6l-3-6H29l-3 6h-6zm13-10l-4-9-4 9h8z" fill="#4B7CF3" />
</svg>

Before

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="colorlib adminator" preserveAspectRatio="xMidYMid meet">
<path fill="#6366f1" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"/>
<path fill="#ffffff" d="M14.747 9.125c.527-1.426 1.736-2.573 3.317-2.573c1.643 0 2.792 1.085 3.318 2.573l6.077 16.867c.186.496.248.931.248 1.147c0 1.209-.992 2.046-2.139 2.046c-1.303 0-1.954-.682-2.264-1.611l-.931-2.915h-8.62l-.93 2.884c-.31.961-.961 1.642-2.232 1.642c-1.24 0-2.294-.93-2.294-2.17c0-.496.155-.868.217-1.023l6.233-16.867zm.34 11.256h5.891l-2.883-8.992h-.062l-2.946 8.992z"/>
</svg>

Before

Width:  |  Height:  |  Size: 768 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 229 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 B

View File

@@ -1,7 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator circle logo icon">
<title>Adminator Logo Circle</title>
<!-- Circular background -->
<circle cx="32" cy="32" r="30" fill="#4B7CF3" />
<!-- Stylised "A" -->
<path d="M20 46L32 18l12 28h-6l-3-7H29l-3 7h-6zm13-11l-4-10-4 10h8z" fill="#FFFFFF" />
</svg>

Before

Width:  |  Height:  |  Size: 380 B

View File

@@ -1,13 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator gradient logo icon">
<title>Adminator Logo Gradient</title>
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4B7CF3;stop-opacity:1" />
<stop offset="100%" style="stop-color:#7B4BF3;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Rounded square background with gradient -->
<rect width="64" height="64" rx="12" fill="url(#grad)" />
<!-- Stylised "A" -->
<path d="M20 46L32 18l12 28h-6l-3-7H29l-3 7h-6zm13-11l-4-10-4 10h8z" fill="#FFFFFF" />
</svg>

Before

Width:  |  Height:  |  Size: 661 B

View File

@@ -1,7 +0,0 @@
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Adminator outline logo icon">
<title>Adminator Logo Outline</title>
<!-- Hexagon outline -->
<polygon points="32 4 56 18 56 46 32 60 8 46 8 18" fill="none" stroke="#4B7CF3" stroke-width="4" />
<!-- Stylised "A" -->
<path d="M20 44L32 18l12 26h-6l-3-6H29l-3 6h-6zm13-10l-4-9-4 9h8z" fill="#4B7CF3" />
</svg>

Before

Width:  |  Height:  |  Size: 427 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="colorlib adminator" preserveAspectRatio="xMidYMid meet">
<path fill="#6366f1" d="M36 32a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4v28z"/>
<path fill="#ffffff" d="M14.747 9.125c.527-1.426 1.736-2.573 3.317-2.573c1.643 0 2.792 1.085 3.318 2.573l6.077 16.867c.186.496.248.931.248 1.147c0 1.209-.992 2.046-2.139 2.046c-1.303 0-1.954-.682-2.264-1.611l-.931-2.915h-8.62l-.93 2.884c-.31.961-.961 1.642-2.232 1.642c-1.24 0-2.294-.93-2.294-2.17c0-.496.155-.868.217-1.023l6.233-16.867zm.34 11.256h5.891l-2.883-8.992h-.062l-2.946 8.992z"/>
</svg>

Before

Width:  |  Height:  |  Size: 768 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 229 KiB

View File

@@ -1,537 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<title>Blank</title>
<style>
#loader {
transition: all 0.3s ease-in-out;
opacity: 1;
visibility: visible;
position: fixed;
height: 100vh;
width: 100%;
background: #fff;
z-index: 90000;
}
#loader.fadeOut {
opacity: 0;
visibility: hidden;
}
.spinner {
width: 40px;
height: 40px;
position: absolute;
top: calc(50% - 20px);
left: calc(50% - 20px);
background-color: #333;
border-radius: 100%;
-webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
animation: sk-scaleout 1.0s infinite ease-in-out;
}
@-webkit-keyframes sk-scaleout {
0% { -webkit-transform: scale(0) }
100% {
-webkit-transform: scale(1.0);
opacity: 0;
}
}
@keyframes sk-scaleout {
0% {
-webkit-transform: scale(0);
transform: scale(0);
} 100% {
-webkit-transform: scale(1.0);
transform: scale(1.0);
opacity: 0;
}
}
</style>
<script defer="defer" src="runtime.js">
</script>
<script defer="defer" src="vendor-fullcalendar.js"></script>
<script defer="defer" src="vendor-chartjs.js"></script><script defer="defer" src="vendors.js"></script>
<script defer="defer" src="main.js"></script>
<link href="style.css" rel="stylesheet">
</head>
<body class="app">
<div id="loader">
<div class="spinner"></div>
</div>
<script>
window.addEventListener('load', function load() {
const loader = document.getElementById('loader');
setTimeout(function() {
loader.classList.add('fadeOut');
}, 300);
});
</script>
<div>
<!-- #Left Sidebar ==================== -->
<div class="sidebar">
<div class="sidebar-inner">
<!-- ### $Sidebar Header ### -->
<div class="sidebar-logo">
<div class="peers ai-c fxw-nw">
<div class="peer peer-greed">
<a class="sidebar-link td-n" href="index.html">
<div class="peers ai-c fxw-nw">
<div class="peer">
<div class="logo">
<img src="assets/static/images/logo.svg" alt="">
</div>
</div>
<div class="peer peer-greed">
<h5 class="lh-1 mB-0 logo-text">Adminator</h5>
</div>
</div>
</a>
</div>
<div class="peer">
<div class="mobile-toggle sidebar-toggle">
<a href="" class="td-n">
<i class="ti-arrow-circle-left"></i>
</a>
</div>
</div>
</div>
</div>
<!-- ### $Sidebar Menu ### -->
<ul class="sidebar-menu scrollable pos-r">
<li class="nav-item mT-30">
<a class="sidebar-link" href="index.html">
<span class="icon-holder">
<i class="c-blue-500 ti-home"></i>
</span>
<span class="title">Dashboard</span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="https://dashboardpack.com/?utm_source=adminator&utm_medium=sidebar&utm_campaign=go_pro" target="_blank" rel="noopener">
<span class="icon-holder">
<i class="c-purple-500 ti-crown"></i>
</span>
<span class="title">Go Pro <span class="badge bg-primary ms-2">PRO</span></span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="email.html">
<span class="icon-holder">
<i class="c-brown-500 ti-email"></i>
</span>
<span class="title">Email</span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="compose.html">
<span class="icon-holder">
<i class="c-blue-500 ti-share"></i>
</span>
<span class="title">Compose</span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="calendar.html">
<span class="icon-holder">
<i class="c-deep-orange-500 ti-calendar"></i>
</span>
<span class="title">Calendar <span class="badge bg-danger ms-2">HOT</span></span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="chat.html">
<span class="icon-holder">
<i class="c-deep-purple-500 ti-comment-alt"></i>
</span>
<span class="title">Chat</span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="charts.html">
<span class="icon-holder">
<i class="c-indigo-500 ti-bar-chart"></i>
</span>
<span class="title">Charts <span class="badge bg-success ms-2">NEW</span></span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="forms.html">
<span class="icon-holder">
<i class="c-light-blue-500 ti-pencil"></i>
</span>
<span class="title">Forms</span>
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="ui.html">
<span class="icon-holder">
<i class="c-pink-500 ti-palette"></i>
</span>
<span class="title">UI Elements</span>
</a>
</li>
<li class="nav-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0);">
<span class="icon-holder">
<i class="c-orange-500 ti-layout-list-thumb"></i>
</span>
<span class="title">Tables</span>
<span class="arrow">
<i class="ti-angle-right"></i>
</span>
</a>
<ul class="dropdown-menu">
<li>
<a class="sidebar-link" href="basic-table.html">Basic Table</a>
</li>
<li>
<a class="sidebar-link" href="datatable.html">Data Table <span class="badge bg-success ms-1">NEW</span></a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0);">
<span class="icon-holder">
<i class="c-purple-500 ti-map"></i>
</span>
<span class="title">Maps</span>
<span class="arrow">
<i class="ti-angle-right"></i>
</span>
</a>
<ul class="dropdown-menu">
<li>
<a href="google-maps.html">Google Map</a>
</li>
<li>
<a href="vector-maps.html">Vector Map</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0);">
<span class="icon-holder">
<i class="c-red-500 ti-files"></i>
</span>
<span class="title">Pages</span>
<span class="arrow">
<i class="ti-angle-right"></i>
</span>
</a>
<ul class="dropdown-menu">
<li>
<a class="sidebar-link" href="blank.html">Blank</a>
</li>
<li>
<a class="sidebar-link" href="404.html">404</a>
</li>
<li>
<a class="sidebar-link" href="500.html">500</a>
</li>
<li>
<a class="sidebar-link" href="signin.html">Sign In</a>
</li>
<li>
<a class="sidebar-link" href="signup.html">Sign Up</a>
</li>
</ul>
</li>
<li class="nav-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0);">
<span class="icon-holder">
<i class="c-teal-500 ti-view-list-alt"></i>
</span>
<span class="title">Multiple Levels</span>
<span class="arrow">
<i class="ti-angle-right"></i>
</span>
</a>
<ul class="dropdown-menu">
<li class="nav-item dropdown">
<a href="javascript:void(0);">
<span>Menu Item</span>
</a>
</li>
<li class="nav-item dropdown">
<a href="javascript:void(0);">
<span>Menu Item</span>
<span class="arrow">
<i class="ti-angle-right"></i>
</span>
</a>
<ul class="dropdown-menu">
<li>
<a href="javascript:void(0);">Menu Item</a>
</li>
<li>
<a href="javascript:void(0);">Menu Item</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- #Main ============================ -->
<div class="page-container">
<!-- ### $Topbar ### -->
<div class="header navbar">
<div class="header-container">
<ul class="nav-left">
<li>
<a id="sidebar-toggle" class="sidebar-toggle" href="javascript:void(0);">
<i class="ti-menu"></i>
</a>
</li>
<li class="search-box">
<a class="search-toggle no-pdd-right" href="javascript:void(0);">
<i class="search-icon ti-search pdd-right-10"></i>
<i class="search-icon-close ti-close pdd-right-10"></i>
</a>
</li>
<li class="search-input">
<input class="form-control" type="text" placeholder="Search...">
</li>
</ul>
<ul class="nav-right">
<li class="notifications dropdown">
<span class="counter bgc-red">3</span>
<a href="" class="dropdown-toggle no-after" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
<i class="ti-bell"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<li class="pX-20 pY-15 bdB">
<i class="ti-bell pR-10"></i>
<span class="fsz-sm fw-600 c-grey-900">Notifications</span>
</li>
<li>
<ul class="ovY-a pos-r scrollable lis-n p-0 m-0 fsz-sm">
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/1.jpg" alt="">
</div>
<div class="peer peer-greed">
<span>
<span class="fw-500">John Doe</span>
<span class="c-grey-600">liked your <span class="text-dark">post</span>
</span>
</span>
<p class="m-0">
<small class="fsz-xs">5 mins ago</small>
</p>
</div>
</a>
</li>
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/2.jpg" alt="">
</div>
<div class="peer peer-greed">
<span>
<span class="fw-500">Moo Doe</span>
<span class="c-grey-600">liked your <span class="text-dark">cover image</span>
</span>
</span>
<p class="m-0">
<small class="fsz-xs">7 mins ago</small>
</p>
</div>
</a>
</li>
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/3.jpg" alt="">
</div>
<div class="peer peer-greed">
<span>
<span class="fw-500">Lee Doe</span>
<span class="c-grey-600">commented on your <span class="text-dark">video</span>
</span>
</span>
<p class="m-0">
<small class="fsz-xs">10 mins ago</small>
</p>
</div>
</a>
</li>
</ul>
</li>
<li class="pX-20 pY-15 ta-c bdT">
<span>
<a href="" class="c-grey-600 cH-blue fsz-sm td-n">View All Notifications <i class="ti-angle-right fsz-xs mL-10"></i></a>
</span>
</li>
</ul>
</li>
<li class="notifications dropdown">
<span class="counter bgc-blue">3</span>
<a href="" class="dropdown-toggle no-after" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
<i class="ti-email"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<li class="pX-20 pY-15 bdB">
<i class="ti-email pR-10"></i>
<span class="fsz-sm fw-600 c-grey-900">Emails</span>
</li>
<li>
<ul class="ovY-a pos-r scrollable lis-n p-0 m-0 fsz-sm">
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/1.jpg" alt="">
</div>
<div class="peer peer-greed">
<div>
<div class="peers jc-sb fxw-nw mB-5">
<div class="peer">
<p class="fw-500 mB-0">John Doe</p>
</div>
<div class="peer">
<small class="fsz-xs">5 mins ago</small>
</div>
</div>
<span class="c-grey-600 fsz-sm">
Want to create your own customized data generator for your app...
</span>
</div>
</div>
</a>
</li>
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/2.jpg" alt="">
</div>
<div class="peer peer-greed">
<div>
<div class="peers jc-sb fxw-nw mB-5">
<div class="peer">
<p class="fw-500 mB-0">Moo Doe</p>
</div>
<div class="peer">
<small class="fsz-xs">15 mins ago</small>
</div>
</div>
<span class="c-grey-600 fsz-sm">
Want to create your own customized data generator for your app...
</span>
</div>
</div>
</a>
</li>
<li>
<a href="" class="peers fxw-nw td-n p-20 bdB c-grey-800 cH-blue bgcH-grey-100">
<div class="peer mR-15">
<img class="w-3r bdrs-50p" src="https://randomuser.me/api/portraits/men/3.jpg" alt="">
</div>
<div class="peer peer-greed">
<div>
<div class="peers jc-sb fxw-nw mB-5">
<div class="peer">
<p class="fw-500 mB-0">Lee Doe</p>
</div>
<div class="peer">
<small class="fsz-xs">25 mins ago</small>
</div>
</div>
<span class="c-grey-600 fsz-sm">
Want to create your own customized data generator for your app...
</span>
</div>
</div>
</a>
</li>
</ul>
</li>
<li class="pX-20 pY-15 ta-c bdT">
<span>
<a href="email.html" class="c-grey-600 cH-blue fsz-sm td-n">View All Email <i class="fs-xs ti-angle-right mL-10"></i></a>
</span>
</li>
</ul>
</li>
<li class="dropdown">
<a href="" class="dropdown-toggle no-after peers fxw-nw ai-c lh-1" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
<div class="peer mR-10">
<img class="w-2r bdrs-50p" src="https://randomuser.me/api/portraits/men/10.jpg" alt="">
</div>
<div class="peer">
<span class="fsz-sm c-grey-900">John Doe</span>
</div>
</a>
<ul class="dropdown-menu fsz-sm" aria-labelledby="dropdownMenuLink">
<li>
<a href="" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
<i class="ti-settings mR-10"></i>
<span>Setting</span>
</a>
</li>
<li>
<a href="" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
<i class="ti-user mR-10"></i>
<span>Profile</span>
</a>
</li>
<li>
<a href="email.html" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
<i class="ti-email mR-10"></i>
<span>Messages</span>
</a>
</li>
<li role="separator" class="divider"></li>
<li>
<a href="" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
<i class="ti-power-off mR-10"></i>
<span>Logout</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
<!-- ### $App Screen Content ### -->
<main class="main-content bgc-grey-100">
<div id="mainContent">
<div class="full-container">
</div>
</div>
</main>
<!-- ### $App Screen Footer ### -->
<footer class="bdT ta-c p-30 lh-0 fsz-sm c-grey-600">
<span>Copyright © 2026 Designed by <a href="https://colorlib.com" target="_blank" rel="nofollow noopener noreferrer" title="Colorlib">Colorlib</a>. All rights reserved.</span>
</footer>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,151 +0,0 @@
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({});
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/chunk loaded */
/******/ (() => {
/******/ var deferred = [];
/******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var [chunkIds, fn, priority] = deferred[i];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ var r = fn();
/******/ if (r !== undefined) result = r;
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ 121: 0
/******/ };
/******/
/******/ // no chunk on demand loading
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ return __webpack_require__.O(result);
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
/******/
/******/
/******/ })()
;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 434 KiB

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More