set admin2

This commit is contained in:
imadhigp 2026-08-15 10:46:55 +05:30
parent d6e1fe2c5d
commit 13ecc12812
3 changed files with 224 additions and 202 deletions

View File

@ -100,32 +100,87 @@ class AdminDashboardController extends Controller
return redirect()->back()->with('success', 'Notification deleted successfully!'); return redirect()->back()->with('success', 'Notification deleted successfully!');
} }
// Store Student Portal Log
public function storePortalLog(Request $request)
{
$request->validate([
'user_id' => 'required|exists:users,id',
]);
return $this->sendToPortalLog($request->user_id);
}
// Send User to Portal Log // Send User to Portal Log
public function sendToPortalLog($userId) public function sendToPortalLog($userId)
{ {
try { try {
$user = User::findOrFail($userId); $user = User::findOrFail($userId);
// Check if user is already logged // User දැනටමත් Portal Log එකේ සිටීදැයි පරීක්ෂා කිරීම
$exists = StudentPortalLog::where('user_id', $user->id)->exists(); $exists = StudentPortalLog::where('user_id', $user->id)->exists();
if ($exists) { if ($exists) {
return redirect()->back()->with('error', 'This user is already in Portal Logs!'); return redirect()->back()->with('error', 'This user is already in Portal Logs!');
} }
// Create new portal log // Student Portal Log එකට පමණක් Data Insert කිරීම
StudentPortalLog::create([ StudentPortalLog::create([
'user_id' => $user->id, 'user_id' => $user->id,
'first_name' => $user->first_name ?? '', 'first_name' => $user->first_name ?? '',
'last_name' => $user->last_name ?? '', 'last_name' => $user->last_name ?? '',
'email' => $user->email, 'email' => $user->email,
'phone' => $user->phone ?? null, 'phone' => $user->phone ?? null,
'pin' => null,
]); ]);
return redirect()->back()->with('success', 'User successfully added to Portal Logs!'); return redirect()->back()->with('success', 'User successfully added to Portal Logs!');
} catch (Exception $e) { } catch (Exception $e) {
\Log::error('Send to Portal Log Error: ' . $e->getMessage()); \Log::error('Send to Portal Log Error: ' . $e->getMessage());
return redirect()->back()->with('error', 'Failed to add user to Portal Log.'); return redirect()->back()->with('error', 'Failed to add user to Portal Log: ' . $e->getMessage());
} }
} }
// Update or Delete User Portal PIN
public function updatePin(Request $request, $id)
{
$request->validate([
'pin' => 'nullable|string|max:20',
]);
try {
$portalLog = StudentPortalLog::findOrFail($id);
$portalLog->pin = $request->filled('pin') ? $request->pin : null;
$portalLog->save();
$message = $request->filled('pin')
? 'Portal PIN updated successfully!'
: 'Portal PIN deleted successfully!';
return redirect()->back()->with('success', $message);
} catch (Exception $e) {
\Log::error('Update PIN Error: ' . $e->getMessage());
return redirect()->back()->with('error', 'Failed to update PIN: ' . $e->getMessage());
}
}
// =========================================================================
// STUDENT PORTAL LOG DELETION ONLY (Main User Account එක ඉතිරි වේ)
// =========================================================================
public function destroyPortalLog($id)
{
try {
$portalLog = StudentPortalLog::findOrFail($id);
$portalLog->delete(); // student_portal_logs Table එකෙන් පමණක් Delete වේ
return redirect()->back()->with('success', 'Student Portal access record deleted successfully!');
} catch (Exception $e) {
\Log::error('Delete Portal Log Error: ' . $e->getMessage());
return redirect()->back()->with('error', 'Failed to remove from Student Portal: ' . $e->getMessage());
}
}
} }

View File

@ -30,16 +30,22 @@
font-size: 24px; font-size: 24px;
} }
/* Edit Mode Control Styles */ /* Edit Mode Control Styles */
/* Edit Mode Control Styles */
.edit-only { .edit-only {
display: none !important; display: none !important;
} }
/* Display rule based on element types */
.is-editing .edit-only { .is-editing .edit-only {
display: inline-block !important; display: inline-block !important;
} }
.is-editing div.edit-only { .is-editing div.edit-only {
display: block !important; display: block !important;
} }
.is-editing flex.edit-only, .is-editing td.edit-only,
.is-editing th.edit-only {
display: table-cell !important;
}
.is-editing .d-flex.edit-only { .is-editing .d-flex.edit-only {
display: flex !important; display: flex !important;
} }
@ -53,13 +59,7 @@
<h3 class="fw-bold mb-1"><i class="fa-solid fa-gauge me-2"></i>Welcome to Admin Dashboard</h3> <h3 class="fw-bold mb-1"><i class="fa-solid fa-gauge me-2"></i>Welcome to Admin Dashboard</h3>
<p class="mb-0 text-white-50">Automobile Engineering Academy System Overview</p> <p class="mb-0 text-white-50">Automobile Engineering Academy System Overview</p>
</div> </div>
<!-- <div class="text-end d-flex align-items-center gap-2"> -->
<!-- Pin Unlock Button -->
<!-- <button id="btnLockToggle" class="btn btn-warning text-dark fw-bold rounded-pill px-3 py-2 shadow-sm" data-bs-toggle="modal" data-bs-target="#pinAuthModal">
<i class="fa-solid fa-lock me-1" id="lockIcon"></i> <span id="lockStatusText">Unlock Edit Mode</span>
</button>
<span class="badge bg-danger fs-6 px-3 py-2 rounded-pill d-none d-md-inline-block"><i class="fa-solid fa-shield-halved me-1"></i> System Active</span>
</div> -->
</div> </div>
<!-- Alert Messages --> <!-- Alert Messages -->
@ -320,103 +320,65 @@
</div> </div>
</div> </div>
<!-- Registered Users Table -->
<div class="row g-4 mb-4"> <!-- Registered Users Table -->
<div class="col-12"> <div class="row g-4 mb-4">
<div class="card border-0 shadow-sm rounded-3"> <div class="col-12">
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center"> <div class="card border-0 shadow-sm rounded-3">
<h5 class="fw-bold mb-0 text-dark"> <div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
<i class="fa-solid fa-users text-primary me-2"></i>Registered System Users List <h5 class="fw-bold mb-0 text-dark">
</h5> <i class="fa-solid fa-users text-primary me-2"></i>Registered System Users List
<span class="badge bg-primary rounded-pill">{{ count($users ?? []) }} Users</span> </h5>
</div> <span class="badge bg-primary rounded-pill">{{ count($users ?? []) }} Users</span>
<div class="card-body p-0"> </div>
<div class="table-responsive"> <div class="card-body p-0">
<table class="table table-hover align-middle mb-0"> <div class="table-responsive">
<thead class="table-light"> <table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr>
<th class="ps-3">ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Created Date</th>
<th class="text-end pe-3">Action</th>
</tr>
</thead>
<tbody>
@forelse($users ?? [] as $user)
<tr> <tr>
<th class="ps-3">ID</th> <td class="ps-3 fw-bold">#{{ $user->id }}</td>
<th>Name</th> <td>{{ $user->first_name }} {{ $user->last_name }}</td>
<th>Email</th> <td>{{ $user->email }}</td>
<th>Phone</th> <td>{{ $user->phone ?? 'N/A' }}</td>
<th class="text-center" style="min-width: 210px;">Portal PIN</th> <td>{{ $user->created_at ? $user->created_at->format('Y-m-d H:i') : 'N/A' }}</td>
<th>Created Date</th>
<th class="text-end pe-3 edit-only">Action</th> <td class="text-end pe-3">
<form action="{{ route('admin.portallogs.send', $user->id) }}" method="POST" class="d-inline">
@csrf
<button type="submit" class="btn btn-sm btn-primary rounded-2">
<i class="fa-solid fa-paper-plane me-1"></i> Send to Portal Log
</button>
</form>
</td>
</tr> </tr>
</thead> @empty
<tbody> <tr>
@forelse($users ?? [] as $user) <td colspan="6" class="text-center py-4 text-muted">
<tr> <i class="fa-solid fa-user-slash fs-3 d-block mb-2 text-secondary"></i>
<td class="ps-3 fw-bold">#{{ $user->id }}</td> No registered users found.
<td>{{ $user->first_name }} {{ $user->last_name }}</td> </td>
<td>{{ $user->email }}</td> </tr>
<td>{{ $user->phone ?? 'N/A' }}</td> @endforelse
<!-- DIRECT PIN EDIT / ADD / DELETE CONTROLS INSIDE CELL --> </tbody>
<td class="text-center"> </table>
<div class="d-flex align-items-center justify-content-center gap-2">
@if(!empty($log->pin) && $log->pin !== 'N/A')
<!-- Current PIN Badge -->
<span class="badge bg-dark font-monospace fs-6 px-3 py-2 shadow-sm">
<i class="fa-solid fa-key text-warning me-1"></i>{{ $log->pin }}
</span>
<!-- Direct Edit PIN Button -->
<button class="btn btn-sm btn-outline-primary border-0 rounded-circle"
data-bs-toggle="modal"
data-bs-target="#editPinModal{{ $log->id }}"
title="Edit PIN">
<i class="fa-solid fa-pen-to-square"></i>
</button>
<!-- Direct Delete PIN Form/Button -->
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this PIN?');">
@csrf
@method('PUT')
<input type="hidden" name="pin" value="">
<button type="submit" class="btn btn-sm btn-outline-danger border-0 rounded-circle" title="Delete PIN">
<i class="fa-solid fa-trash-can"></i>
</button>
</form>
@else
<!-- N/A Badge -->
<span class="badge bg-secondary font-monospace fs-6 px-3 py-2 opacity-75">
<i class="fa-solid fa-key text-white-50 me-1"></i>N/A
</span>
<!-- Direct Add New PIN Button -->
<button class="btn btn-sm btn-success rounded-pill px-2 py-1"
data-bs-toggle="modal"
data-bs-target="#editPinModal{{ $log->id }}">
<i class="fa-solid fa-plus me-1"></i>Add PIN
</button>
@endif
</div>
</td>
<td>{{ $log->created_at ? $log->created_at->format('Y-m-d H:i') : 'N/A' }}</td>
<td class="text-end pe-3 edit-only">
<form action="{{ route('admin.portallogs.send', $user->id) }}" method="POST" class="d-inline">
@csrf
<button type="submit" class="btn btn-sm btn-primary rounded-2">
<i class="fa-solid fa-paper-plane me-1"></i> Send to Portal Log
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center py-4 text-muted">
<i class="fa-solid fa-user-slash fs-3 d-block mb-2 text-secondary"></i>
No registered users found.
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Student Portal Active Logs Table (PIN, Add, Edit & Delete) --> <!-- Student Portal Active Logs Table (PIN, Add, Edit & Delete) -->
<div class="row g-4" id="portal-logs-section"> <div class="row g-4" id="portal-logs-section">
@ -428,7 +390,7 @@
</h5> </h5>
<div class="d-flex align-items-center gap-2"> <div class="d-flex align-items-center gap-2">
<span class="badge bg-success rounded-pill">{{ count($portalLogs ?? []) }} Active Student Logs</span> <span class="badge bg-success rounded-pill">{{ count($portalLogs ?? []) }} Active Student Logs</span>
<!-- Add New Portal Log Button (Edit mode එකේදී විතරක් පෙනේ) -->
<button class="btn btn-sm btn-success rounded-3 edit-only" data-bs-toggle="modal" data-bs-target="#addPortalLogModal"> <button class="btn btn-sm btn-success rounded-3 edit-only" data-bs-toggle="modal" data-bs-target="#addPortalLogModal">
<i class="fa-solid fa-plus me-1"></i> Add Portal Log <i class="fa-solid fa-plus me-1"></i> Add Portal Log
</button> </button>
@ -468,37 +430,105 @@
<td>{{ $log->email }}</td> <td>{{ $log->email }}</td>
<td>{{ $log->phone ?? ($log->user->phone ?? 'N/A') }}</td> <td>{{ $log->phone ?? ($log->user->phone ?? 'N/A') }}</td>
<!-- PIN Column --> <!-- Portal PIN Column -->
<td class="text-center"> <td class="text-center">
<span class="badge bg-dark font-monospace fs-6 px-3 py-1"> <div class="d-flex align-items-center justify-content-center gap-2">
<i class="fa-solid fa-key me-1 text-warning"></i>{{ $log->pin ?? 'N/A' }}
</span> @if(!empty($log->pin) && $log->pin !== 'N/A')
<!-- Current PIN Badge -->
<span class="badge bg-dark font-monospace fs-6 px-3 py-2 shadow-sm">
<i class="fa-solid fa-key text-warning me-1"></i>{{ $log->pin }}
</span>
<!-- Edit PIN Button (Triggers Modal) -->
<button type="button"
class="btn btn-sm btn-outline-primary border-0 rounded-circle"
data-bs-toggle="modal"
data-bs-target="#editPinModal{{ $log->id }}"
title="Edit PIN">
<i class="fa-solid fa-pen-to-square"></i>
</button>
<!-- Delete PIN Form -->
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this PIN?');">
@csrf
@method('PUT')
<input type="hidden" name="pin" value="">
<button type="submit" class="btn btn-sm btn-outline-danger border-0 rounded-circle" title="Delete PIN">
<i class="fa-solid fa-trash-can"></i>
</button>
</form>
@else
<!-- N/A Badge -->
<span class="badge bg-secondary font-monospace fs-6 px-3 py-2 opacity-75">
<i class="fa-solid fa-key text-white-50 me-1"></i>N/A
</span>
<!-- Add New PIN Button (Triggers Modal) -->
<button type="button"
class="btn btn-sm btn-success rounded-pill px-2 py-1"
data-bs-toggle="modal"
data-bs-target="#editPinModal{{ $log->id }}">
<i class="fa-solid fa-plus me-1"></i>Add PIN
</button>
@endif
</div>
<!-- Edit/Add PIN Bootstrap Modal -->
<div class="modal fade" id="editPinModal{{ $log->id }}" tabindex="-1" aria-labelledby="editPinModalLabel{{ $log->id }}" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content text-start">
<div class="modal-header">
<h5 class="modal-title fw-bold" id="editPinModalLabel{{ $log->id }}">
<i class="fa-solid fa-key text-warning me-2"></i>Edit Portal PIN
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST">
@csrf
@method('PUT')
<div class="modal-body p-4">
<div class="mb-3">
<label class="form-label fw-bold">Student Name</label>
<input type="text" class="form-control" value="{{ trim(($log->first_name ?? '') . ' ' . ($log->last_name ?? '')) }}" disabled>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Portal PIN</label>
<input type="text" name="pin" class="form-control" value="{{ $log->pin }}" placeholder="Enter new PIN" required>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-save me-1"></i> Save PIN</button>
</div>
</form>
</div>
</div>
</div>
</td> </td>
<td>{{ $log->created_at ? $log->created_at->format('Y-m-d H:i') : 'N/A' }}</td> <td>{{ $log->created_at ? $log->created_at->format('Y-m-d H:i') : 'N/A' }}</td>
<td class="text-end pe-3"> <td class="text-end pe-3">
<!-- Edit / Delete (Edit mode නොමැති විට Status එක පමණක් පෙනේ) --> @if($user->is_active)
<span class="badge bg-success bg-opacity-10 text-success border border-success px-3 py-2 rounded-pill edit-hidden">
<i class="fa-solid fa-circle-check me-1"></i> Active <form action="{{ route('admin.portallogs.send', $user->id) }}" method="POST" class="inline" onsubmit="return confirm('Are you sure you want to send this record to Student Portal?');">
</span> @csrf
<button type="submit" class="portal" style="background-color: #7e3c37; border-color: #e6e939;">
<div class="d-flex gap-1 justify-content-end edit-only"> <i class="fa-solid fa-paper-plane me-1"></i> Send to Portal Log
<!-- Edit PIN Modal Trigger Button --> </button>
<button class="btn btn-sm btn-outline-primary rounded-2" data-bs-toggle="modal" data-bs-target="#editPortalLogModal{{ $log->id }}" title="Edit Student PIN / Details"> </form>
<i class="fa-solid fa-pen-to-square me-1"></i> Edit @else
</button>
<form action="{{ route('admin.portallogs.destroy', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to remove this record from Student Portal? (User account will remain safe)');">
<!-- Delete Log Button --> @csrf
<form action="{{ route('admin.portallogs.destroy', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this Student Portal Log?');"> @method('DELETE')
@csrf <button type="submit" class="btn btn-danger btn-sm">
@method('DELETE') <i class="fa-solid fa-trash me-1"></i> Delete Student Log
<button type="submit" class="btn btn-sm btn-outline-danger rounded-2" title="Delete Log"> </button>
<i class="fa-solid fa-trash-can"></i> </form>
</button> @endif
</form> </td>
</div>
</td>
</tr> </tr>
<!-- Edit Portal Log Modal --> <!-- Edit Portal Log Modal -->
@ -635,67 +665,4 @@
</div> </div>
</div> </div>
<!--
<script>
document.addEventListener("DOMContentLoaded", function () {
const ADMIN_PIN = "1234";
const dashboardWrapper = document.getElementById("dashboardWrapper");
const inputPin = document.getElementById("inputPin");
const btnSubmitPin = document.getElementById("btnSubmitPin");
const pinErrorMessage = document.getElementById("pinErrorMessage");
const btnLockToggle = document.getElementById("btnLockToggle");
const lockIcon = document.getElementById("lockIcon");
const lockStatusText = document.getElementById("lockStatusText");
const pinModal = new bootstrap.Modal(document.getElementById('pinAuthModal'));
if (sessionStorage.getItem("adminEditUnlocked") === "true") {
enableEditMode();
}
function verifyPin() {
if (inputPin.value.trim() === ADMIN_PIN) {
sessionStorage.setItem("adminEditUnlocked", "true");
enableEditMode();
pinModal.hide();
inputPin.value = "";
pinErrorMessage.classList.add("d-none");
} else {
pinErrorMessage.classList.remove("d-none");
inputPin.value = "";
inputPin.focus();
}
}
btnSubmitPin.addEventListener("click", verifyPin);
inputPin.addEventListener("keypress", function (e) {
if (e.key === "Enter") {
verifyPin();
}
});
function enableEditMode() {
dashboardWrapper.classList.add("is-editing");
btnLockToggle.classList.replace("btn-warning", "btn-success");
lockIcon.classList.replace("fa-lock", "fa-lock-open");
lockStatusText.innerText = "Edit Mode Active";
btnLockToggle.removeAttribute("data-bs-toggle");
btnLockToggle.removeAttribute("data-bs-target");
}
btnLockToggle.addEventListener("click", function () {
if (dashboardWrapper.classList.contains("is-editing")) {
sessionStorage.removeItem("adminEditUnlocked");
dashboardWrapper.classList.remove("is-editing");
btnLockToggle.classList.replace("btn-success", "btn-warning");
lockIcon.classList.replace("fa-lock-open", "fa-lock");
lockStatusText.innerText = "Unlock Edit Mode";
btnLockToggle.setAttribute("data-bs-toggle", "modal");
btnLockToggle.setAttribute("data-bs-target", "#pinAuthModal");
}
});
});
</script> -->
@endsection @endsection

View File

@ -143,11 +143,20 @@ Route::middleware(['web'])->prefix('admin')->group(function () {
Route::delete('/notifications/{id}', [AdminDashboardController::class, 'destroy'])->name('admin.notifications.destroy'); Route::delete('/notifications/{id}', [AdminDashboardController::class, 'destroy'])->name('admin.notifications.destroy');
Route::post('/notifications/read/{id}', [AdminDashboardController::class, 'markAsRead'])->name('admin.notifications.read'); Route::post('/notifications/read/{id}', [AdminDashboardController::class, 'markAsRead'])->name('admin.notifications.read');
// Admin Users Management
Route::delete('/users/{id}', [AdminDashboardController::class, 'destroyUser'])->name('admin.users.destroy');
// Student Portal Log Management (Main User Table එකට හානියක් නොවී Portal Log එක පමණක් පාලනය කිරීමට)
Route::post('/portal-logs', [AdminDashboardController::class, 'storePortalLog'])->name('admin.portallogs.store');
Route::post('/portal-logs/send/{userId}', [AdminDashboardController::class, 'sendToPortalLog'])->name('admin.portallogs.send');
Route::put('/portal-logs/{userId}/pin', [AdminDashboardController::class, 'updatePin'])->name('admin.portallogs.update');
Route::delete('/portal-logs/{id}', [AdminDashboardController::class, 'destroyPortalLog'])->name('admin.portallogs.destroy');
// Admin Courses // Admin Courses
Route::get('/adminmycourses', [adminmycoursesController::class, 'index'])->name('admin.mycourses'); Route::get('/adminmycourses', [adminmycoursesController::class, 'index'])->name('admin.mycourses');
Route::post('/adminmycourses/store', [adminmycoursesController::class, 'store'])->name('admin.courses.store'); Route::post('/adminmycourses/store', [adminmycoursesController::class, 'store'])->name('admin.courses.store');
Route::post('/adminmycourses/update/{id}', [adminmycoursesController::class, 'update'])->name('admin.courses.update'); Route::post('/adminmycourses/update/{id}', [adminmycoursesController::class, 'update'])->name('admin.courses.update');
Route::delete('/admin/courses/{id}', [adminmycoursesController::class, 'destroy'])->name('admin.courses.delete'); Route::delete('/courses/{id}', [adminmycoursesController::class, 'destroy'])->name('admin.courses.delete');
// Admin Timetable Routes // Admin Timetable Routes
Route::get('/timetable', [AdminTimetableController::class, 'index'])->name('admin.timetable'); Route::get('/timetable', [AdminTimetableController::class, 'index'])->name('admin.timetable');
@ -165,13 +174,4 @@ Route::middleware(['web'])->prefix('admin')->group(function () {
Route::get('/profile', [AdminProfileController::class, 'index'])->name('admin.profile'); Route::get('/profile', [AdminProfileController::class, 'index'])->name('admin.profile');
Route::put('/profile/update', [AdminProfileController::class, 'update'])->name('admin.profile.update'); Route::put('/profile/update', [AdminProfileController::class, 'update'])->name('admin.profile.update');
Route::put('/profile/password', [AdminProfileController::class, 'updatePassword'])->name('admin.profile.password'); Route::put('/profile/password', [AdminProfileController::class, 'updatePassword'])->name('admin.profile.password');
Route::post('/admin/portal-log/store', [AdminDashboardController::class, 'storePortalLog'])->name('admin.portal.store');
Route::post('/admin/portal-logs/send/{userId}', [AdminDashboardController::class, 'sendToPortalLog'])->name('admin.portallogs.send');
Route::prefix('admin')->name('admin.')->group(function () {
Route::post('/portal-logs', [PortalLogController::class, 'store'])->name('portallogs.store');
Route::put('/portal-logs/{id}', [PortalLogController::class, 'update'])->name('portallogs.update');
Route::delete('/portal-logs/{id}', [PortalLogController::class, 'destroy'])->name('portallogs.destroy');
});
}); });