worked on workshop comments

This commit is contained in:
Kwesi Banson Jnr 2026-05-26 18:07:04 +00:00
parent 295b44c430
commit 94343f8127
41 changed files with 2637 additions and 401 deletions

View File

@ -2,7 +2,7 @@ APP_NAME=lupmisBackend
APP_ENV=local
APP_KEY=base64:pmEAeuW8clKrfKKjcMWylo68exoDO/Xr2hUhXvB7dS0=
APP_DEBUG=true
APP_URL=http://localhost:9031
APP_URL=http:https://lupmis4luspa.org
LOG_CHANNEL=daily
LUPMISAPIKEY=1c46538c712e9b5b

View File

@ -10,24 +10,35 @@ use Illuminate\Support\Collection;
class AdminController extends Controller
{
public function index(){
$users_url = "user_mgt/get_all_users.php";
$data = ['api_token' => env('LUPMISAPIKEY')];
if (session('current_user.user_type') == 'district_user') {
$users_url = "user_mgt/get_all_users_by_district.php";
$data = ['district_id' => session('district_id'), 'api_token' => env('LUPMISAPIKEY')];
}
elseif(session('current_user.user_type') == 'regional_user'){
$users_url = "user_mgt/get_all_users_by_district.php";
$data = ['region_id' => session('region_id'), 'api_token' => env('LUPMISAPIKEY')];
}
else{
$users_url = "user_mgt/get_all_users.php";
$data = ['api_token' => env('LUPMISAPIKEY')];
}
// dd($users_url);
$result = ApiCalls::CurlPost(json_encode($data), $users_url);
$users_arr = json_decode($result, true);
if ($users_arr['success'] == false) {
return redirect->back();
// dd($users_arr);
if ($users_arr == null || $users_arr['success'] == false) {
return redirect()->back()->withErrors('Your request cannot be handled at this time. Try again later');
}
$regions_url = "user_mgt/get_all_regions.php";
$data = ['api_token' => env('LUPMISAPIKEY')];
$result = ApiCalls::CurlPost(json_encode($data), $regions_url);
$regions_arr = json_decode($result, true);
if ($regions_arr['success'] == false) {
return redirect->back();
if ($regions_arr == null || $regions_arr['success'] == false) {
return redirect->back()->withErrors('Your request cannot be handled at this time. Try again later');
}
// 2. Define pagination parameters
$perPage = 15;
$search = request()->input('search');
if ($search) {
@ -48,22 +59,20 @@ class AdminController extends Controller
$currentPage = LengthAwarePaginator::resolveCurrentPage() ?: 1;
$offset = ($currentPage - 1) * $perPage;
// 3. Slice the array to get the items for the current page
$currentPageItems = array_slice($filteredData, $offset, $perPage);
// 4. Create the LengthAwarePaginator instance
$paginatedItems = new LengthAwarePaginator(
$currentPageItems, // Items for the current page
count($filteredData), // Total number of items
$perPage, // Items per page
$currentPage, // Current page number
['path' => request()->url(), 'query' => request()->query()] // Options to preserve query strings and path
$currentPageItems,
count($filteredData),
$perPage,
$currentPage,
['path' => request()->url(), 'query' => request()->query()]
);
$user_type_arr = [
'district_user' => 'District User',
'regional_user' => 'Regional User',
'national_user' => 'National User'
];
// dump($users_arr['data']);
$data = [
'page_title' => 'User Admin',
'users_arr' => $users_arr['data'],
@ -71,8 +80,7 @@ class AdminController extends Controller
'user_type_arr' => $user_type_arr,
'items' => $paginatedItems
];
// dump($data);
// 5. Pass the paginator instance to your view
return view('admin.paginated', $data);
// return view('admin.home', $data);
@ -109,7 +117,7 @@ class AdminController extends Controller
return view('admin.home', $data);
}
public function districtparams(){
/*
$url = "user_mgt/get_district_parameters.php";
$data = json_encode([
'district_id' => 171,
@ -117,11 +125,12 @@ class AdminController extends Controller
]);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
// dd($result);
dd($result);
*/
$data = [
'page_title' => "Page Under Development"
'page_title' => "District Parameters"
];
return view('common.notready', $data);
return view('admin.district_params', $data);
}
public function luspaparams(){
$data = [
@ -129,6 +138,12 @@ class AdminController extends Controller
];
return view('common.notready', $data);
}
public function systempermissions(){
$data = [
'page_title' => "System Permissions"
];
return view('admin.system-permissions', $data);
}
public function districts($reqion_id){
// return response()->json(['request' => $reqion_id]);
$url = "user_mgt/get_district_by_region_id.php";

View File

@ -12,6 +12,7 @@ class LandingpageController extends Controller
$data = [
'page_title' => 'Landing Page'
];
// dump(session('current_user'));
return view('landing', $data);
}

View File

@ -27,6 +27,23 @@ class PermitsController extends Controller
];
return view('permits.dashboard', $data);
}
public function settings(){
//pull email address, sms configs,
/*
$url = "permit/get_applications_by_district.php";
$data = json_encode([
'district_id' => session('current_user.district_id'),
'api_token' => env('LUPMISAPIKEY')
]);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
*/
$data = [
'page_title' => 'Permits Settings',
// 'permits_arr' => $result
];
return view('permits.district-settings', $data);
}
public function statusIndex($status){
$url = "permit/get_applications_by_district.php";
@ -58,10 +75,11 @@ class PermitsController extends Controller
]);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
// dump($result);
$allowed_users_to_comment = ['PPD Head', 'Works Department Head', 'luspa-it-head'];
$data = [
'page_title' => 'Permits Details',
'permit_arr' => $result['data'][0],
'allowed_users_to_comment' => $allowed_users_to_comment
];
return view('permits.show', $data);
}
@ -69,7 +87,6 @@ class PermitsController extends Controller
}
public function viewPdf($filename){
// Ensure the file exists and is in the correct storage sub-directory
$path = storage_path('app/public/site_plans/' . $filename);
if (!Storage::disk('public')->exists('site_plans/' . $filename)) {

View File

@ -25,6 +25,27 @@ class UserloginController extends Controller
$check_user_url = 'auth/auth_user.php';
$data = ['user' => $request->username, 'pass' => $request->password, 'api_token' => env('LUPMISAPIKEY')];
$check_user = ApiCalls::CurlPost(json_encode($data), $check_user_url);
/*
"success" : true, "data" : {
"ua_id":28,"user_id":"71c1f2bd-e85b-4c2a-b559-536731ea1a92",
"username":"kwesilupmis",
"title":"Mr","full_name":"Kwesi banson jnr",
"ua_position":"luspa-it-head",
"email":"kwesibanson@yahoo.com",
"phone":"0204040805","gender":null,
"is_disabled":"true",
"is_logged_in":0,"is_password_changed":"false","password_hint":"none",
"created_by_id":null,"created_date":"2026-03-10T07:09:38.815762",
"updated_by_id":"71c1f2bd-e85b-4c2a-b559-536731ea1a92",
"updated_date":"2026-05-06T10:26:09.191289",
"allowed_apps":"drawing-tools, permit-tools, admin-gui",
"region_id":10,
"district_id":122
}
*/
if($check_user == false){
return redirect("user-login")->withErrors(array("System not available at the moment. Try again later!"))->withInput();
}
@ -32,6 +53,9 @@ class UserloginController extends Controller
if($result['success'] == false){
return redirect("user-login")->withErrors(array("Incorrect Email/Password. Check and try again!"))->withInput();
}
if($result['data']['is_disabled'] == true){
##return redirect("user-login")->withErrors(array("Your Account has been disabled. Contact your administrator!"))->withInput();
}
$logged_in = $result['data'];
$request->session()->regenerate(true);
@ -41,6 +65,7 @@ class UserloginController extends Controller
$request->session()->put('current_user.title', $logged_in['title']);
$request->session()->put('current_user.full_name', $logged_in['full_name']);
$request->session()->put('current_user.email', $logged_in['email']);
$request->session()->put('current_user.user_type', $logged_in['user_type']);
$request->session()->put('current_user.phone', $logged_in['phone']);
$request->session()->put('current_user.allowed_apps', $logged_in['allowed_apps']);
$request->session()->put('current_user.ua_position', $logged_in['ua_position']);

View File

@ -7,18 +7,80 @@ use Session;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\UserAccountsMail;
use App\Mail\PasswordResetMail;
use Illuminate\Support\Str;
class UsersController extends Controller
{
public function index(){
$data = [
'page_title' => 'Users Page '
];
return view('users.index', $data);
}
public function reset(){
$data = [
'page_title' => 'Password Reset Page'
];
return view('user-auth.reset', $data);
}
public function check_reset_email(Request $request){
// code...
// dd('foo bar');
$url = "user_mgt/get_user_by_user_id.php";
$user_id = "34ba702b-18f8-4d85-948d-8c55e8500f32";
$data = json_encode([
'user_id' => "34ba702b-18f8-4d85-948d-8c55e8500f32",// $id,
'api_token' => env('LUPMISAPIKEY')// make the API token a constant
]);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
// dd($result);
$recipientEmail = $result['data']['email'];
$fullname = $result['data']['full_name'];
$phone = $result['data']['phone'];
//send reset link email
//baduhupir@mailinator.com
$reset_link = env('APP_URL') . "/reset-auth/" . $user_id;
Mail::to($recipientEmail)->send(new PasswordResetMail($fullname, $reset_link));
return redirect(url('reset-notice')); //get
// return redirect(url('new-password-form'));
}
public function reset_notice(Request $request){
return view('user-auth.email-notice');
}
public function show_new_passform(Request $request){
// code...show_new_passform
// dd('foo bar show new pass');
dump($request->all());
$data = [
'page_title' => 'New Password Form'
];
return view('user-auth.password', $data);
}
public function handle_reset(Request $request){
// code...show_new_passform
// dd('foo bar handle reset');
return redirect(url('reset-success')); //get
}
public function reset_success(Request $request){
// code...show_new_passform
// dd('foo bar handle reset');
$data = [
'page_title' => 'New Password Success'
];
return view('user-auth.password-success', $data);
}
public function edit($id){
$url = "user_mgt/get_user_by_user_id.php";
@ -94,13 +156,13 @@ class UsersController extends Controller
'password_hint' => 'none',
'phone' => $request['phone'],
'gender' => $request['gender'],
'user_type' => 'District User',
'user_type' => $request['user_type'],
'pass' => $password,
'region_id' => $request['region_id'],
'district_id' => $request['districtid'],
'api_token' => env('LUPMISAPIKEY'), //'1c46538c712e9b5b' // make the API token a constant
]);
// dd($data);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
\Log::info("Your Password is $password");
@ -116,10 +178,11 @@ class UsersController extends Controller
'recipient' => $request['phone'],
'message' => $sms_message
];
$sms_result = SmsLibrary::SendMnotitySms($sms_data);
#$sms_result = SmsLibrary::SendMnotitySms($sms_data); // will send this the API
\Log::info("SMS Body : $sms_message");
\Log::info("SMS API Response : $sms_result");
#\Log::info("SMS API Response : $sms_result");
if (request()->expectsJson()) {
return response()->json($result);
@ -131,11 +194,10 @@ class UsersController extends Controller
// return ['success' => true];
// dd($request->all());
$data = json_encode([
$user_data = [
'full_name' => $request['full_name'],
'username' => $request['username'],
'ua_position' => $request['ua_position'],
// 'ua_position' => $request['ua_position'],
'user_id' => $request['user_id'],
'email' => $request['email'],
'title' => $request['title'],
@ -144,7 +206,11 @@ class UsersController extends Controller
'gender' => $request['gender'],
'user_type' => 'District User',
'api_token' => env('LUPMISAPIKEY'),
]);
];
if ($request->has('expire_password')) {
$user_data['is_password_changed'] = 'NO';
}
$data = json_encode($user_data);
$result = ApiCalls::CurlPost($data, $url);
$result = json_decode($result, true);
// dd($result);

View File

@ -0,0 +1,58 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Mail\Mailables\Address;
class PasswordResetMail extends Mailable
{
use Queueable, SerializesModels;
public $fullname;
public $reset_url;
/**
* Create a new message instance.
*/
public function __construct($fullname, $reset_url)
{
$this->fullname = $fullname;
$this->reset_url = $reset_url;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Password Reset Mail',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'emails.reset-link',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@ -34,7 +34,9 @@ return [
'lifetime' => (int) env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
//'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
'expire_on_close' => true,
/*
|--------------------------------------------------------------------------

View File

@ -1,3 +1,7 @@
# Acounts
- assiamah/win
- kwesilupmis/7aa0478bce
composer create-project laravel/laravel:^11.0 my-laravel-11-project
chmod -R 0777 storage/
chmod -R 0777 bootstrap/

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,98 @@
$(document).ready(function(){
$('.profileLink').click(function(evt){
evt.preventDefault();
$.ajax({
type: "GET",
url: base_url + '/users/getprofile',
processData: false,
contentType: false,
async: false,
success: function (data){
console.log(data);
if (data.code === 1) {
console.log(data['user_details']);
$('.userId').val(data['user_details']['user_id']);
$('.userName').val(data['user_details']['username']);
$('.userFullName').val(data['user_details']['full_name']);
$('.userEmail').val(data['user_details']['email']);
$('.userPhone').val(data['user_details']['phone']);
$('.userDesignation').val(data['user_details']['ua_position']);
$('.userDateAdded').val(data['user_details']['created_date']);
// $('.userEmail').val(data['user_details']['email']);
$('#profileModal').modal('show');
}
else if (data.code > 1) {
$.alert({
title: 'Alert!',
content: data.msg,
});
}
else {
$.alert({
title: 'Alert!',
content: 'Your request could not be handled. Try again !',
});
}
}
});
});
$('#profileModalSubmitBtn').click(function(evt){
evt.preventDefault(evt);
console.log('info');
$('#successArea').addClass('d-none');
$('#errorsArea').removeClass('d-none');
var formData = new FormData($('#userProfileForm')[0]);
$.ajax({
url: base_url + '/profileupdate',
type: 'POST',
data: formData,
processData: false,
contentType: false,
beforeSend: function() {
$('#successArea').text("");
$('#successArea').text("Please wait ... profile update in progress!");
},
success: function(data) {
if (data['success'] == true) {
$('#successArea').removeClass('d-none');
$('#errorsArea').addClass('d-none');
$('#successArea').text("");
$('#successArea').text("Profile successfully updated!");
// location.reload();
$.alert({
title: 'Alert!',
content: 'Profile successfully updated!',
});
setTimeout(function() {
//location.reload(); // Reloads the current page
}, 2000);
}
else{
$('#successArea').addClass('d-none');
$('#errorArea').removeClass('d-none');
$('#errorArea').text("");
$('#errorArea').text("Profile could not be updated!");
$.alert({
title: 'Alert!',
content: 'Profile could not updated!',
});
}
},
error: function(xhr, status, error) {
console.error('Error:', error);
$('#successArea').text(error);
$('#successArea').text(error);
$.alert({
title: 'Alert!',
content: error,
});
}
});
});
});

View File

@ -1,228 +1,3 @@
// Store Settings Page JavaScript
// Back button functionality
function goBack() {
if (window.history.length > 1) {
window.history.back();
} else {
window.location.href = "index.html";
}
}
// Search functionality
document.addEventListener("DOMContentLoaded", function () {
const searchInput = document.getElementById("searchInput");
if (searchInput) {
searchInput.addEventListener("input", function (e) {
const searchQuery = e.target.value.toLowerCase().trim();
// Get all settings cards
const settingsCards = document.querySelectorAll(".settings-grid .col-12");
// Get all integration cards
const integrationCards = document.querySelectorAll(
".integrations-grid .col-12"
);
// Filter settings cards
settingsCards.forEach((cardCol) => {
const card = cardCol.querySelector(".settings-card");
const title = card
.querySelector(".card-title")
.textContent.toLowerCase();
const description = card
.querySelector(".card-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
// Filter integration cards
integrationCards.forEach((cardCol) => {
const card = cardCol.querySelector(".integration-card");
const title = card
.querySelector(".integration-name")
.textContent.toLowerCase();
const description = card
.querySelector(".integration-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
});
}
// Integration connect/disconnect functionality
const integrationCards = document.querySelectorAll(".integration-card");
integrationCards.forEach((card) => {
const connectBtn = card.querySelector(".connect-btn");
const disconnectBtn = card.querySelector(".disconnect-btn");
// Handle Connect button click
if (connectBtn) {
connectBtn.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
connectBtn.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
// Show confirmation dialog
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
newConnectBtn.addEventListener("click", function () {
// Recursively handle connect (reuse the same logic)
newConnectBtn.click();
});
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Handle Disconnect button click
if (disconnectBtn) {
disconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
const connectedStatus = card.querySelector(".connected-status");
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
attachConnectHandler(newConnectBtn, card);
}
});
}
});
// Helper function to attach connect handler
function attachConnectHandler(button, card) {
button.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
button.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Settings card click navigation
const settingsCards = document.querySelectorAll(".settings-card");
settingsCards.forEach((card) => {
card.style.cursor = "pointer";
card.addEventListener("click", function () {
const title = card.querySelector(".card-title").textContent;
// Map settings to placeholder pages (can be updated later)
const settingsMap = {
General: "#general-settings",
"Billing Plan": "#billing-settings",
Team: "#team-settings",
"SMS Settings": "#sms-settings",
"Web Tracking Installation": "#tracking-settings",
};
const targetPage = settingsMap[title];
if (targetPage) {
// For now, just show an alert (can be replaced with actual navigation)
console.log(`Navigating to ${title} settings...`);
// Uncomment the line below when actual pages are created
// window.location.href = targetPage;
}
});
});
});
$(document).ready(function(){
console.log('log');
});

View File

@ -0,0 +1,229 @@
// Store Settings Page JavaScript
// Back button functionality
function goBack() {
if (window.history.length > 1) {
window.history.back();
} else {
window.location.href = "index.html";
}
}
// Search functionality
document.addEventListener("DOMContentLoaded", function () {
const searchInput = document.getElementById("searchInput");
if (searchInput) {
searchInput.addEventListener("input", function (e) {
const searchQuery = e.target.value.toLowerCase().trim();
// Get all settings cards
const settingsCards = document.querySelectorAll(".settings-grid .col-12");
// Get all integration cards
const integrationCards = document.querySelectorAll(
".integrations-grid .col-12"
);
// Filter settings cards
settingsCards.forEach((cardCol) => {
const card = cardCol.querySelector(".settings-card");
const title = card
.querySelector(".card-title")
.textContent.toLowerCase();
const description = card
.querySelector(".card-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
// Filter integration cards
integrationCards.forEach((cardCol) => {
const card = cardCol.querySelector(".integration-card");
const title = card
.querySelector(".integration-name")
.textContent.toLowerCase();
const description = card
.querySelector(".integration-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
});
}
// Integration connect/disconnect functionality
const integrationCards = document.querySelectorAll(".integration-card");
integrationCards.forEach((card) => {
const connectBtn = card.querySelector(".connect-btn");
const disconnectBtn = card.querySelector(".disconnect-btn");
// Handle Connect button click
if (connectBtn) {
connectBtn.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
connectBtn.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
// Show confirmation dialog
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
newConnectBtn.addEventListener("click", function () {
// Recursively handle connect (reuse the same logic)
newConnectBtn.click();
});
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Handle Disconnect button click
if (disconnectBtn) {
disconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
const connectedStatus = card.querySelector(".connected-status");
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
attachConnectHandler(newConnectBtn, card);
}
});
}
});
// Helper function to attach connect handler
function attachConnectHandler(button, card) {
button.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
button.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Settings card click navigation
const settingsCards = document.querySelectorAll(".settings-card");
settingsCards.forEach((card) => {
card.style.cursor = "pointer";
card.addEventListener("click", function () {
const title = card.querySelector(".card-title").textContent;
console.log(title);
// Map settings to placeholder pages (can be updated later)
const settingsMap = {
General: "#general-settings",
"Billing Plan": "#billing-settings",
Team: "#team-settings",
"SMS Settings": "#sms-settings",
"Web Tracking Installation": "#tracking-settings",
};
const targetPage = settingsMap[title];
if (targetPage) {
// For now, just show an alert (can be replaced with actual navigation)
console.log(`Navigating to ${title} settings...`);
// Uncomment the line below when actual pages are created
// window.location.href = targetPage;
}
});
});
});

View File

@ -0,0 +1,230 @@
// Store Settings Page JavaScript
// Back button functionality
function goBack() {
if (window.history.length > 1) {
window.history.back();
} else {
window.location.href = "";
}
}
// Search functionality
document.addEventListener("DOMContentLoaded", function () {
const searchInput = document.getElementById("searchInput");
if (searchInput) {
searchInput.addEventListener("input", function (e) {
const searchQuery = e.target.value.toLowerCase().trim();
// Get all settings cards
const settingsCards = document.querySelectorAll(".settings-grid .col-12");
// Get all integration cards
const integrationCards = document.querySelectorAll(
".integrations-grid .col-12"
);
// Filter settings cards
settingsCards.forEach((cardCol) => {
const card = cardCol.querySelector(".settings-card");
const title = card
.querySelector(".card-title")
.textContent.toLowerCase();
const description = card
.querySelector(".card-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
// Filter integration cards
integrationCards.forEach((cardCol) => {
const card = cardCol.querySelector(".integration-card");
const title = card
.querySelector(".integration-name")
.textContent.toLowerCase();
const description = card
.querySelector(".integration-description")
.textContent.toLowerCase();
if (
title.includes(searchQuery) ||
description.includes(searchQuery) ||
searchQuery === ""
) {
cardCol.style.display = "";
} else {
cardCol.style.display = "none";
}
});
});
}
// Integration connect/disconnect functionality
const integrationCards = document.querySelectorAll(".integration-card");
integrationCards.forEach((card) => {
const connectBtn = card.querySelector(".connect-btn");
const disconnectBtn = card.querySelector(".disconnect-btn");
// Handle Connect button click
if (connectBtn) {
connectBtn.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
connectBtn.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
// Show confirmation dialog
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
newConnectBtn.addEventListener("click", function () {
// Recursively handle connect (reuse the same logic)
newConnectBtn.click();
});
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Handle Disconnect button click
if (disconnectBtn) {
disconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
const connectedStatus = card.querySelector(".connected-status");
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Add event listener to new connect button
attachConnectHandler(newConnectBtn, card);
}
});
}
});
// Helper function to attach connect handler
function attachConnectHandler(button, card) {
button.addEventListener("click", function () {
// Create connected status elements
const connectedStatus = document.createElement("div");
connectedStatus.className = "connected-status";
const badge = document.createElement("span");
badge.className = "badge connected-badge mb-2";
badge.innerHTML =
'<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i> Connected';
const newDisconnectBtn = document.createElement("button");
newDisconnectBtn.className = "btn disconnect-btn";
newDisconnectBtn.textContent = "Disconnect";
connectedStatus.appendChild(badge);
connectedStatus.appendChild(newDisconnectBtn);
// Replace connect button with connected status
button.replaceWith(connectedStatus);
// Add event listener to new disconnect button
newDisconnectBtn.addEventListener("click", function () {
const integrationName =
card.querySelector(".integration-name").textContent;
if (
confirm(`Are you sure you want to disconnect ${integrationName}?`)
) {
// Create new connect button
const newConnectBtn = document.createElement("button");
newConnectBtn.className = "btn connect-btn";
newConnectBtn.innerHTML =
'Connect <i class="fas fa-arrow-right ms-2"></i>';
// Replace connected status with connect button
connectedStatus.replaceWith(newConnectBtn);
// Re-attach the connect handler
attachConnectHandler(newConnectBtn, card);
}
});
});
}
// Settings card click navigation
const settingsCards = document.querySelectorAll(".settings-card");
settingsCards.forEach((card) => {
card.style.cursor = "pointer";
card.addEventListener("click", function () {
const title = card.querySelector(".card-title").textContent;
console.log(title);
window.location.href = "/admin/permissions";
// Map settings to placeholder pages (can be updated later)
// const settingsMap = {
// General: "#general-settings",
// "Billing Plan": "#billing-settings",
// Team: "#team-settings",
// "SMS Settings": "#sms-settings",
// "Web Tracking Installation": "#tracking-settings",
// };
// const targetPage = settingsMap[title];
// if (targetPage) {
// // For now, just show an alert (can be replaced with actual navigation)
// console.log(`Navigating to ${title} settings...`);
// // Uncomment the line below when actual pages are created
// // window.location.href = targetPage;
// }
});
});
});

View File

@ -1,4 +1,71 @@
$(document).ready(function(){
var selectedValue = $("input[name='user_type']:checked").val();
const $dropdown = $("#uaPostionAdd");
const optionsMap = {
district_user: [
"PPD Head", "Works Head", "MIS",
"PPD Staff", "Works Staff",
"Devt Planning Officer",
"MCE", "DCE",
"Urban Roads Department Head",
"District Fire Officer",
"District Disaster Prevention Department",
"Head of District Health Department",
"Representative of the Lands Commission",
"Representative of the Environmental Protection Agency",
"Rep from Traditional Council",
"Chairman of the Works Sub Committee",
"Chairman of Development Sub Planning Committee",
"Nominated Elected Assembly Memebers"
],
national_luspa: ["Director", "IT Head", "Staff"],
regional_luspa: ["Director", "Staff"]
};
$dropdown.empty();
$dropdown.append('<option value="">-- Select an option --</option>');
if (optionsMap['district_user']) {
$.each(optionsMap['district_user'], function(index, value) {
$dropdown.append($("<option></option>").attr("value", value.toLowerCase()).text(value));
});
}
$("input[name='user_type']").change(function() {
var userValue = $(this).val();
if (userValue == 'district_user') {
$('#regionID').prop('disabled', false);
$('#districtID').prop('disabled', false);
}
if (userValue == 'national_luspa') {
$('#regionID').prop('disabled', true);
$('#districtID').prop('disabled', true);
}
if (userValue == 'regional_luspa') {
$('#districtID').prop('disabled', true);
$('#regionID').prop('disabled', false);
}
$dropdown.empty();
$dropdown.append('<option value="">-- Select an option --</option>');
if (optionsMap[userValue]) {
$.each(optionsMap[userValue], function(index, value) {
$dropdown.append($("<option></option>")
.attr("value", value.toLowerCase())
.text(value));
});
}
});
$('#editAllowedApps').select2({
dropdownParent: $('#editUserModal'),
placeholder : "Select options, multiple allowed"
@ -67,6 +134,8 @@ $(document).ready(function(){
});
$('.viewUserBtn').click(function(evnt){
evnt.preventDefault();
var selectedUserId = $(this).siblings('.userIdinput').val();
@ -141,8 +210,6 @@ $(document).ready(function(){
$('#successArea').text("");
$('#successArea').text("User successfully created!");
// location.reload();
// alert('success');
$.alert({
title: 'Alert!',
content: 'User successfully created!',

View File

@ -0,0 +1,208 @@
@extends('layouts.master')
@section('page-title')
Admin | {{ $page_title }}
@endsection
@section('page-css')
<link rel="stylesheet" href="{{ url('public/assets/libs/select2/dist/css/select2.css') }}">
<link rel="stylesheet" href="{{ url('public/assets/css/params.css') }}">
@endsection
@section('page-content')
@include('layouts.partials.navbar')
<div class="container py-4">
<div class="row">
<div class="mb-4">
<h1 class="h3 mb-1">District Parameters</h1>
<p class="text-muted">Update the parameters as needed</p>
</div>
<div class="settings-section mb-5">
<div class="mb-4">
<h2
class="mb-2"
style="font-size: 1.5rem; font-weight: 600; color: #2c3e50"
>
General Settings
</h2>
<p class="text-muted mb-0" style="font-size: 0.95rem">
<!-- <a href="#" class="text-decoration-none" style="color: #3b7fb3">Profile Settings</a> -->
</p>
</div>
<!-- Settings Cards Grid -->
<div class="row g-3 settings-grid">
<!-- General Settings Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="settings-card">
<div class="card-icon mb-3">
<i class="fas fa-cog"></i>
</div>
<h3 class="card-title mb-2">District Settings</h3>
<p class="card-description mb-0">
View and update district details
</p>
</div>
</div>
<!-- Billing Plan Settings Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="settings-card">
<div class="card-icon mb-3">
<i class="fas fa-credit-card"></i>
</div>
<h3 class="card-title mb-2">Fee Fixing </h3>
<p class="card-description mb-0">View current fees</p>
</div>
</div>
<!-- Team Settings Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="settings-card">
<div class="card-icon mb-3">
<i class="fas fa-users"></i>
</div>
<h3 class="card-title mb-2">Permissions</h3>
<p class="card-description mb-0">View user groups and permissions</p>
</div>
</div>
</div>
</div>
<!-- Integrations Section -->
<div class="integrations-section mb-5">
<div class="mb-4">
<h2 class="mb-2" style="font-size: 1.5rem; font-weight: 600; color: #2c3e50">
Stakeholders
</h2>
<p class="text-muted mb-0" style="font-size: 0.95rem">
Data sharing organisations
</p>
</div>
<!-- Integration Cards Grid -->
<div class="row g-3 integrations-grid">
<!-- Shopify Integration Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fab fa-shopify" style="font-size: 3.5rem; color: #96bf48"></i> -->
<img src="{{ url('public/assets/images/logos/landscommission-logo.jpg') }}" width="80">
</div>
<h4 class="integration-name mb-2">Lands Commission</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
<!-- Klaviyo Integration Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fas fa-envelope" style="font-size: 3.5rem; color: #000000"></i> -->
<img src="{{ url('public/assets/images/logos/epa-logo.png') }}" width="80">
</div>
<h4 class="integration-name mb-2">Environmental Protection Agency (EPA)</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
<!-- Stripe Integration Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fab fa-stripe" style="font-size: 3.5rem; color: #635bff"></i> -->
<img src="{{ url('public/assets/images/logos/geology.png') }}" width="80">
</div>
<h4 class="integration-name mb-2">Ghana Geological Survey Authority</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
<!-- Instagram Integration Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fab fa-instagram" style="font-size: 3.5rem; color: #e4405f"></i> -->
<img src="{{ url('public/assets/images/logos/nadmo.png') }}" width="80">
</div>
<h4 class="integration-name mb-2">National Disaster Management Organisation</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
<!-- Facebook Integration Card -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fab fa-facebook" style="font-size: 3.5rem; color: #1877f2"></i> -->
<img src="{{ url('public/assets/images/logos/mlgrd-logo.jpeg') }}" width="80">
</div>
<h4 class="integration-name mb-2">Local Government</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
<!-- Google Integration Card (Connected) -->
<div class="col-12 col-md-6 col-lg-4">
<div class="integration-card">
<div class="integration-logo mb-3">
<!-- <i class="fab fa-google" style="font-size: 3.5rem; color: #4285f4"></i> -->
<img src="{{ url('public/assets/images/logos/gss-logo.png') }}" width="80">
</div>
<h4 class="integration-name mb-2">GSS</h4>
<p class="integration-description mb-3">
View Available Data
</p>
<!-- <div class="connected-status">
<span class="badge connected-badge mb-2">
<i class="fas fa-circle me-1" style="font-size: 0.5rem"></i>Connected
</span>
<button class="btn disconnect-btn">Disconnect</button>
</div> -->
<button class="btn connect-btn">
Open <i class="fas fa-arrow-right ms-2"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('page-js')
<script src="{{ url('public/assets/libs/select2/dist/js/select2.full.min.js') }}" type="text/javascript" ></script>
<script src="{{ url('public/assets/js/params.js') }}" type="text/javascript" ></script>
@endsection

View File

@ -14,12 +14,24 @@
<form class="row g-3" action="" method="POST" id="newUserForm">
@csrf
<input type="hidden" name="action" value="newuser">
<input type="hidden" name="user_type" value="District User">
<div class="col-md-12">
<div class="form-check">
<input class="form-check-input" type="radio" name="user_type" value="district_user" id="userTypeDistrict" checked>
<label class="form-check-label" for="userTypeDistrict">District User</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="user_type" value="regional_luspa" id="userTypeLuspaRegion">
<label class="form-check-label" for="userTypeLuspaRegion">Regional LUSPA</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="user_type" value="national_luspa" id="userTypeLuspaNational">
<label class="form-check-label" for="userTypeLuspaNational">National LUSPA</label>
</div>
</div>
<div class="col-md-2">
<label for="inputState" class="form-label">Title</label>
<select id="inputState" name="title" class="form-select" required>
<label for="titleSelecton" class="form-label">Title</label>
<select id="titleSelecton" name="title" class="form-select" required>
<option selected disabled>Choose...</option>
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
@ -54,8 +66,8 @@
<input type="text" name="phone" class="form-control" id="phone" required>
</div>
<div class="col-md-4">
<label for="uaPostion" class="form-label">Position</label>
<select id="uaPostion" name="ua_position" class="form-select" required>
<label for="uaPostionAdd" class="form-label">Position</label>
<select id="uaPostionAdd" name="ua_position" class="form-select" required>
<option selected disabled>Choose...</option>
<option value="district-mis">District MIS</option>
<option value="district-ppd-head">PPD Head</option>

View File

@ -70,7 +70,12 @@
<option value="admin-gui">Admin GUI</option>
</select>
</div>
<div class="col-md-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="expire_password" value="yes" id="expirePassword" checked>
<label class="form-check-label" for="expirePassword">Expire Password</label>
</div>
</div>
<div class="col-md-12">
<label for="inputPermissions" class="form-label">Permissions</label>
<select name="permission" id="inputPermissions" multiple class="form-select" style="width: 100%">

View File

@ -30,7 +30,7 @@
</div>
<div class="mb-3">
<label for="designation" class="form-label">Designation</label>
<input type="text" class="form-control userDesignation" name="ua_position" id="designation" value="">
<input type="text" class="form-control userDesignation" name="ua_position" id="designation" value="" disabled>
</div>
<div class="mb-3">
<label for="designation" class="form-label">Password</label>
@ -41,7 +41,7 @@
<input type="text" class="form-control userDateAdded" id="dateAdded" value="" readonly>
</div>
<button type="button" class="btn btn-primary" id="profileModalSubmitBtn">Update</button>
<button type="button" class="btn btn-primary w-100" id="profileModalSubmitBtn">Update</button>
</form>
</div>
<div class="modal-footer">

View File

@ -0,0 +1,111 @@
@extends('layouts.master')
@section('page-title')
Admin | {{ $page_title }}
@endsection
@section('page-css')
<link rel="stylesheet" href="{{ url('public/assets/libs/select2/dist/css/select2.css') }}">
<link rel="stylesheet" href="{{ url('public/assets/css/params.css') }}">
@endsection
@section('page-content')
@include('layouts.partials.navbar')
<div class="container my-5">
<div class="card shadow-sm border-0">
<div class="card-header bg-primary text-white py-3">
<h5 class="mb-0"><i class="bi bi-shield-lock me-2"></i>LUPMIS User Group Permissions Matrix</h5>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="table-light">
<tr class="text-uppercase small fw-bold">
<th class="ps-4">User Group</th>
<th class="text-center">Permit Backend</th>
<th class="text-center">Update Permits</th>
<th class="text-center">Drawing Tools</th>
<th class="text-center">View Tools</th>
<th class="text-center pe-4">Admin GUI</th>
</tr>
</thead>
<tbody>
<tr class="table-secondary"><td colspan="6" class="ps-4 fw-bold small">National & Regional Authorities</td></tr>
<tr>
<td class="ps-4 fw-bold">LUSPA National</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
</tr>
<tr>
<td class="ps-4 fw-bold">LUSPA Regional</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
</tr>
<tr class="table-secondary"><td colspan="6" class="ps-4 fw-bold small">District Technical Departments</td></tr>
<tr>
<td class="ps-4 fw-bold">Head of Physical Planning</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
</tr>
<tr>
<td class="ps-4 fw-bold">District MIS</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
</tr>
<tr class="table-secondary"><td colspan="6" class="ps-4 fw-bold small">District Administration & Stakeholders</td></tr>
<tr>
<td class="ps-4 fw-bold">District Chief Executive</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
</tr>
<tr>
<td class="ps-4 fw-bold">Traditional Council Rep</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
</tr>
<tr>
<td class="ps-4 fw-bold">Development Planning Officer</td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
<td class="text-center text-danger"><i class="bi bi-check-circle-circle"></i></td>
<td class="text-center text-success"><i class="bi bi-check-circle-fill"></i></td>
<td class="text-center text-danger"><i class="bi bi-x-circle"></i></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer bg-light text-center py-3">
<small class="text-muted">Note: Permissions are subject to District Assembly (DA) protocols.</small>
</div>
</div>
</div>
@endsection
@section('page-js')
<script src="{{ url('public/assets/libs/select2/dist/js/select2.full.min.js') }}" type="text/javascript" ></script>
<script src="{{ url('public/assets/js/params.js') }}" type="text/javascript" ></script>
@endsection

View File

@ -11,5 +11,21 @@
<li>Password: {{ $password }} </li>
<li>URL: https://lupmis4luspa.org</li>
</ol>
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="content-cell" align="center">
<!-- Your custom HTML content goes here -->
<p style="font-family: sans-serif; font-size: 12px; color: #aeaeae; text-align: center;">
&copy; {{ date('Y') }} [{{ "LUPMIS 2.0" }}](https://lupmis4luspa.org). All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</body>
</html>

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<title>LUPMIS 2.0 User Account</title>
</head>
<body>
<h2>Account Reset Request</h2>
<p>Hello {{ $fullname }} </p>
<p>Your have requested to reset your LUPMIS Account. Use the link below to complete the process.</p>
<ol>
<li><a href="{{ $reset_url }}">Reset Link</a></li>
</ol>
<p>The reset link will expire in 15 mins</p>
<p>If you did not make this request, no further action is needed.</p>
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
<tr>
<td class="content-cell" align="center">
<!-- Your custom HTML content goes here -->
<p style="font-family: sans-serif; font-size: 12px; color: #aeaeae; text-align: center;">
&copy; {{ date('Y') }} [{{ 'LUPMIS 2.0' }}](https://lupmis4luspa.org). All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</body>
</html>

View File

@ -9,7 +9,9 @@
<!-- Styles -->
<link rel="stylesheet" href="{{ url('public/assets/libs/bootstrap/css/bootstrap5.3.2.css') }}">
<link rel="stylesheet" href="{{ url('public/assets/libs/fontawesome-free-7.1.0-web/css/all.min.css') }}" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="{{ url('public/assets/libs/jquery-confirm/jquery-confirm.min.css') }}" type="text/css">
<link rel="stylesheet" href="{{ url('public/assets/css/styles.css') }}" rel="stylesheet">
@ -43,8 +45,12 @@
text-decoration: none; /* Optional: removes the underline */
}
</style>
<script type="text/javascript">
var base_url = "{!! url('/') !!}";
</script>
</head>
<body class="bg-light">
@include('admin.partials.profile')
<nav class="navbar navbar-expand-lg navbar-dark bg-primary shadow-sm">
<div class="container">
<a class="navbar-brand" href="/landing">LUPMIS4LUSPA</a>
@ -55,7 +61,7 @@
<!-- <small class="text-muted">Municipality</small> -->
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{{ url('users', session('current_user.ua_id')) }}">Profile</a></li>
<li><a class="dropdown-item profileLink" >Profile</a></li>
<li><a class="dropdown-item" href="#">Settings</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="{{ url('user-logout') }}">Logout</a></li>
@ -66,8 +72,27 @@
</nav>
<div class="container py-5">
@include('common.notifications')
<div class="row g-4">
<div class="col-md-4">
<div class="col-md-3">
<a href="https:portal.lupmis4luspa.org" class="card-link <?php //echo (stripos($_SESSION['user']['allowed_apps'], 'permit') !== false) ? "" : 'disabled-link'; ?>">
<div class="card shadow-sm">
<div class="card-body text-center p-4">
<div class="card-icon">
<!-- <svg width="48" height="48" fill="currentColor" class="bi bi-folder" viewBox="0 0 16 16">
<path d="M.54 3.87.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31zM2.19 4a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91h10.348a1 1 0 0 0 .995-.91l.637-7A1 1 0 0 0 13.81 4H2.19zm4.69-1.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707z"/>
</svg> -->
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-pc-display-horizontal" viewBox="0 0 16 16">
<path d="M1.5 0A1.5 1.5 0 0 0 0 1.5v7A1.5 1.5 0 0 0 1.5 10H6v1H1a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-5v-1h4.5A1.5 1.5 0 0 0 16 8.5v-7A1.5 1.5 0 0 0 14.5 0zm0 1h13a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .5-.5M12 12.5a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0m2 0a.5.5 0 1 1 1 0 .5.5 0 0 1-1 0M1.5 12h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1 0-1M1 14.25a.25.25 0 0 1 .25-.25h5.5a.25.25 0 1 1 0 .5h-5.5a.25.25 0 0 1-.25-.25"/>
</svg>
</div>
<h4>Public Portal</h4>
<p class="text-muted mb-0">For submitting, viewing, and managing permits by the general public</p>
</div>
</div>
</a>
</div>
<div class="col-md-3">
<a href="https://drawingtools.lupmis4luspa.org/indexGIS.php" class="card-link ">
<div class="card shadow-sm">
<div class="card-body text-center p-4">
@ -82,7 +107,7 @@
</div>
</a>
</div>
<div class="col-md-4">
<div class="col-md-3">
<a href="/permits/home" class="card-link">
<div class="card shadow-sm">
<div class="card-body text-center p-4">
@ -98,7 +123,7 @@
</a>
</div>
<div class="col-md-4">
<div class="col-md-3">
<a href="/admin/home" class="card-link ">
<div class="card shadow-sm">
<div class="card-body text-center p-4">
@ -119,5 +144,9 @@
<script src="{{ url('public/assets/libs/jquery-3.2.1.min.js') }}" type="text/javascript"></script>
<script src="{{ url('public/assets/libs/bootstrap/js/bootstrap5.3.2.js') }}"></script>
<script src="{{ url('public/assets/libs/fontawesome-free-7.1.0-web/js/all.min.js') }}"></script>
<script src="{{ url('public/assets/libs/jquery-confirm/jquery-confirm.min.js') }}"></script>
<script src="{{ url('public/assets/js/all_pages.js') }}"></script>
</body>
</html>

View File

@ -60,107 +60,8 @@
<script src="{{ url('public/assets/libs/ol/ol-ext.js') }}" type="text/javascript" ></script>
<script src="{{ url('public/assets/libs/fontawesome-free-7.1.0-web/js/all.min.js') }}"></script>
<script src="{{ url('public/assets/libs/jquery-confirm/jquery-confirm.min.js') }}"></script>
<script src="{{ url('public/assets/js/all_pages.js') }}"></script>
<script>
$(document).ready(function(){
$('.profileLink').click(function(evt){
evt.preventDefault();
$.ajax({
type: "GET",
url: base_url + '/users/getprofile',
processData: false,
contentType: false,
async: false,
success: function (data){
console.log(data);
if (data.code === 1) {
console.log(data['user_details']);
$('.userId').val(data['user_details']['user_id']);
$('.userName').val(data['user_details']['username']);
$('.userFullName').val(data['user_details']['full_name']);
$('.userEmail').val(data['user_details']['email']);
$('.userPhone').val(data['user_details']['phone']);
$('.userDesignation').val(data['user_details']['ua_position']);
$('.userDateAdded').val(data['user_details']['created_date']);
// $('.userEmail').val(data['user_details']['email']);
$('#profileModal').modal('show');
}
else if (data.code > 1) {
$.alert({
title: 'Alert!',
content: data.msg,
});
}
else {
$.alert({
title: 'Alert!',
content: 'Your request could not be handled. Try again !',
});
}
}
});
});
$('#profileModalSubmitBtnQQ').click(function(evt){
evt.preventDefault(evt);
$('#successArea').addClass('d-none');
$('#errorsArea').removeClass('d-none');
var formData = new FormData($('#userProfileForm')[0]);
$.ajax({
url: base_url + '/profileupdate',
type: 'POST',
data: formData,
processData: false,
contentType: false,
beforeSend: function() {
$('#successArea').text("");
$('#successArea').text("Please wait ... profile update in progress!");
},
success: function(data) {
if (data['success'] == true) {
$('#successArea').removeClass('d-none');
$('#errorsArea').addClass('d-none');
$('#successArea').text("");
$('#successArea').text("Profile successfully updated!");
// location.reload();
$.alert({
title: 'Alert!',
content: 'Profile successfully updated!',
});
setTimeout(function() {
//location.reload(); // Reloads the current page
}, 2000);
}
else{
$('#successArea').addClass('d-none');
$('#errorArea').removeClass('d-none');
$('#errorArea').text("");
$('#errorArea').text("Profile could not be updated!");
$.alert({
title: 'Alert!',
content: 'Profile could not updated!',
});
}
},
error: function(xhr, status, error) {
console.error('Error:', error);
$('#successArea').text(error);
$('#successArea').text(error);
$.alert({
title: 'Alert!',
content: error,
});
}
});
});
});
</script>
@yield('page-js')
</body>

View File

@ -3,7 +3,7 @@
<div class="navbar-nav me-auto">
<a class="nav-link text-muted" href="{{ url('/admin/home') }}">Home</a>
<a class="nav-link text-muted" href="{{ url('/admin/districtparams') }}">District Parameters</a>
<a class="nav-link text-muted" href="{{ url('/admin/luspaparams') }}">LUSPA Parameters</a>
<!-- <a class="nav-link text-muted" href="{{ url('/admin/luspaparams') }}">LUSPA Parameters</a> -->
<a class="nav-link text-muted" href="{{ url('/admin/luspaparams') }}">Reports</a>
</div>
</div>

View File

@ -1,10 +1,10 @@
<nav class="navbar navbar-expand-lg">
<div class="container">
<div class="navbar-nav me-auto">
<a class="nav-link text-muted" href="{{ url('/admin/home') }}">Home</a>
<a class="nav-link text-muted" href="{{ url('/admin/districtparams') }}">District Parameters</a>
<a class="nav-link text-muted" href="{{ url('/admin/luspaparams') }}">LUSPA Parameters</a>
<a class="nav-link text-muted" href="{{ url('/admin/luspaparams') }}">Reports</a>
<a class="nav-link text-muted" href="{{ url('/permits/home') }}">Home</a>
<a class="nav-link text-muted" href="{{ url('/permits/districtsettings') }}">District Settings</a>
<!-- <a class="nav-link text-muted" href="{{ url('/permits/luspaparams') }}">LUSPA Parameters</a> -->
<a class="nav-link text-muted" href="{{ url('/permits/reports') }}">Reports</a>
</div>
</div>
</nav>

View File

@ -0,0 +1,85 @@
@extends('layouts.master')
@section('page-title')
Permits | {{ $page_title }}
@endsection
@section('page-css')
@endsection
@section('page-content')
@include('layouts.partials.permits-navbar')
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="mb-4">
<h1 class="h3 mb-1">Permit Settings</h1>
<p class="text-muted">Update these settings as needed</p>
</div>
<form>
<!-- EMAIL SETTINGS CARD -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white py-3">
<h5 class="card-title mb-0 text-primary">
<i class="bi bi-envelope-fill me-2"></i>Email Notifications
</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="outgoingEmail" class="form-label fw-bold">Outgoing Email Address</label>
<input type="email" class="form-control" id="outgoingEmail" value="" placeholder="e.g. ppd@stma.gov.gh" required>
</div>
<div class="mb-3">
<label for="displayName" class="form-label fw-bold">Display Name</label>
<input type="text" class="form-control" id="displayName" value="" placeholder="e.g. Physical Planning Department" required>
</div>
<hr class="my-4">
</div>
</div>
<!-- SMS SETTINGS CARD -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white py-3">
<h5 class="card-title mb-0 text-success">
<i class="bi bi-chat-left-text-fill me-2"></i>SMS Notifications
</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="userPhone" class="form-label fw-bold">Sender Name</label>
<div class="input-group">
<input type="text" class="form-control" id="senderName" placeholder="e.g. STMA" value="">
</div>
</div>
<hr class="my-4">
</div>
</div>
<!-- SAVE / ACTIONS (Using Bootstrap 5 responsive block strategy) -->
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
<button type="button" class="btn btn-outline-secondary px-4">Cancel</button>
<button type="submit" class="btn btn-primary px-4">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
@endsection
@section('page-js')
<script type="text/javascript">
$(document).ready(function(){
});
</script>
@endsection

View File

@ -1,5 +1,5 @@
<div class="modal fade" id="pdfModal" tabindex="-1" aria-labelledby="pdfModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="pdfModalLabel">Document Preview</h5>

View File

@ -8,7 +8,6 @@
@section('page-content')
@include('permits.partials.pdf-modal')
@include('layouts.partials.permits-navbar')
<div class="container">
<div class="row">
<div class="col-md-7">
@ -102,6 +101,10 @@
<p class="detail-value">{{ $permit_arr['permit_type'] }}</p>
</div>
<div class="col-md-12">
<h6 class="detail-label">Description</h6>
<p class="detail-value">{{ $permit_arr['project_description'] }}</p>
</div>
<div class="col-md-6">
<h6 class="detail-label">Purpose</h6>
<p class="detail-value">{{ $permit_arr['land_request_use'] }}</p>
@ -172,7 +175,13 @@
<div class="col-md-6">
<h6 class="detail-label">Processing Days Remaining</h6>
<p class="detail-value">
<span class="badge bg-warning text-dark">27 Days</span>
<span class="badge bg-warning text-dark">
<?php
if ($permit_arr['status'] == 'submitted') {
echo "N/A";
}
?>
</span>
</p>
</div>
</div>
@ -181,19 +190,30 @@
<h3 class="section-title">Remarks</h3>
<div class="row mb-3">
<label for="permitCurrentStatus" class="form-label fw-bold text-primary"><i class="fa-solid fa-temperature-three-quarters"></i> Status Update</label>
@if(in_array(session('current_user.ua_position'), $allowed_users_to_comment))
<select class="form-select form-select-lg" id="permitCurrentStatus">
<option value="" selected disabled>First select status ...</option>
<option value="status_one">Application Received</option>
<option value="status_five">Applicant to Review</option>
<option value="status_two">Permit Pending TSC Review</option>
<option value="status_three">Permit Pending SPC Decision</option>
<option value="status_four">Permit Approved</option>
<option value="status_five">Permit Refused</option>
<option value="status_five">Permit Deferred</option>
<option value="status_one">Application Received</option>
<option value="status_two" disabled>Application Accepted</option>
<option value="status_three" disabled>Permit Pending TSC Review</option>
<option value="status_four" disabled>Permit Pending SPC Decision</option>
<option value="status_five" disabled>Permit Approved (In Principle)</option>
<option value="status_size" disabled>Permit Approved</option>
<option value="status_seven" disabled>Permit Refused</option>
<option value="status_eight" disabled>Permit Deferred</option>
</select>
@else
<p class="badge bg-success text-dark">You don't have the right permission to update the status.</p>
@endif
</div>
<div class="row mb-3">
@if(in_array(session('current_user.ua_position'), $allowed_users_to_comment))
<textarea class="form-control mb-3" rows="4" placeholder="Write a message" ></textarea>
@else
<p class="badge bg-info text-dark">You don't have the right permission to add comments.</p>
@endif
</div>
<div class="row mb-3">
<div class="d-flex gap-1">

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LUPMIS4LUSPA | Reset Password</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<style>
body { background-color: #f8f9fa; }
.reset-container { margin-top: 100px; max-width: 400px; }
</style>
</head>
<body>
<div class="container d-flex justify-content-center">
<div class="reset-container w-100">
<div class="card shadow-sm">
<div class="card-body p-4">
<div class="text-center mb-4">
<h3 class="fw-bold">Email Notice </h3>
<p class="text-muted">An Email has been sent to your address with the password reset link. Check and proceed.</p>
</div>
<!-- <div class="text-center mt-4">
<a class="text-decoration-none small text-muted">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div> -->
<div class="text-center mt-4">
<a href="{{ url('user-login') }}" class="text-decoration-none small text-muted">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div>
</div>
</div>
<div class="text-center mt-3 text-muted small">
&copy; LUPMIS 2.0
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -16,6 +16,7 @@
<link rel="stylesheet" href="{{ url('public/assets/libs/ol/ol-ext.css') }}" />
<link rel="stylesheet" href="{{ url('public/assets/css/l4l.css') }}" rel="stylesheet">
<link rel="stylesheet" href="{{ url('public/assets/css/styles.css') }}" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
</head>
@ -57,17 +58,18 @@
<input type="password" class="form-control" name="password" id="password" placeholder="********" required>
<div class="invalid-feedback">Password is required.</div>
</div>
<div class="col-12">
<div class="text-end my-3">
<a class="lupmis-primary-text-500" href="#">Forgot Password</a>
</div>
</div>
<button class="w-100 btn lupmis-btn-primary btn-lg" type="submit">Sign In</button>
</form>
<!-- <div class="m-3 text-center request-account">
<div class="col-12">
<div class="text-end my-3">
<a class="lupmis-primary-text-500" href="{{ url('user-reset') }}">Forgot Password</a>
</div>
</div>
<div class="m-3 text-center request-account">
<p class="m-0">Don't have an account?</p>
<a class="lupmis-primary-text-500" href="#">Request an account</a>
</div> -->
<a class="lupmis-primary-text-500" href="">Request an account</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LUPMIS4LUSPA | Reset Password</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<style>
body { background-color: #f8f9fa; }
.reset-container { margin-top: 100px; max-width: 400px; }
</style>
</head>
<body>
<div class="container d-flex justify-content-center">
<div class="reset-container w-100">
<div class="card shadow-sm">
<div class="card-body p-4">
<div class="text-center mb-4">
<h3 class="fw-bold">Success </h3>
<p class="text-muted">Your password has been successfully reset. Use the link below to login</p>
</div>
<div class="d-grid gap-2">
<a href="{{ url('user-login') }}" class="btn btn-primary btn-lg">Login Page</a>
</div>
<!-- <div class="text-center mt-4">
<a class="text-decoration-none small text-muted">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div> -->
</div>
</div>
<div class="text-center mt-3 text-muted small">
&copy; LUPMIS 2.0
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LUPMIS4LUSPA | Reset Password</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<style>
body { background-color: #f8f9fa; }
.reset-container { margin-top: 100px; max-width: 400px; }
</style>
</head>
<body>
<!-- Kwesi the Grey -->
<div class="container d-flex justify-content-center">
<div class="reset-container w-100">
<div class="card shadow-sm">
<div class="card-body p-4">
<div class="text-center mb-4">
<h3 class="fw-bold">Password Reset</h3>
<p class="text-muted">Enter your new password to reset</p>
</div>
<form action="{{ url('passowrd-reset') }}" method="POST">
@csrf
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control form-control-lg" id="password" name="password" placeholder="***********" required autofocus>
</div>
<div class="mb-3">
<label for="passwordConfirm" class="form-label">Confirm Password</label>
<input type="password" class="form-control form-control-lg" id="passwordConfirm" name="confirm_password" placeholder="***********" required autofocus>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary btn-lg">Submit</button>
</div>
</form>
<div class="text-center mt-4">
<a href="{{ url('user-login') }}" class="text-decoration-none small text-muted">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div>
</div>
</div>
<div class="text-center mt-3 text-muted small">
&copy; LUPMIS 2.0
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LUPMIS4LUSPA | Reset Password</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<style>
body { background-color: #f8f9fa; }
.reset-container { margin-top: 100px; max-width: 400px; }
</style>
</head>
<body>
<div class="container d-flex justify-content-center">
<div class="reset-container w-100">
<div class="card shadow-sm">
<div class="card-body p-4">
<div class="text-center mb-4">
<h3 class="fw-bold">Forgot Password?</h3>
<p class="text-muted">Enter your email and we'll send you a link to reset your password.</p>
</div>
<form action="{{ url('user-reset') }}" method="POST">
@csrf
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control form-control-lg" id="email" name="email" placeholder="name@example.com" required autofocus>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary btn-lg">Send Reset Link</button>
</div>
</form>
<div class="text-center mt-4">
<a href="{{ url('user-login') }}" class="text-decoration-none small text-muted">
<i class="bi bi-arrow-left"></i> Back to Login
</a>
</div>
</div>
</div>
<div class="text-center mt-3 text-muted small">
&copy; LUPMIS 2.0
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -30,6 +30,15 @@ Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name
Route::get('/user-login', [App\Http\Controllers\UserloginController::class, 'index']);
Route::post('/user-login', [App\Http\Controllers\UserloginController::class, 'handleLogin']);
Route::get('/user-logout', [App\Http\Controllers\UserloginController::class, 'handle_logout'])->name('user-logout');
Route::get('/user-reset', [App\Http\Controllers\UsersController::class, 'reset']); // shows form for user enter reset email
Route::post('/user-reset', [App\Http\Controllers\UsersController::class, 'check_reset_email']); // checks email and calls show new pass form
Route::get('/reset-auth/{id}', [App\Http\Controllers\UsersController::class, 'show_new_passform']); // checks email and calls show new pass form
Route::get('/new-password-form', [App\Http\Controllers\UsersController::class, 'show_new_passform']); // handles pass change and shows success
Route::get('/reset-notice', [App\Http\Controllers\UsersController::class, 'reset_notice']);
Route::post('/passowrd-reset', [App\Http\Controllers\UsersController::class, 'handle_reset']);
Route::get('/reset-success', [App\Http\Controllers\UsersController::class, 'reset_success']);
@ -45,6 +54,8 @@ Route::middleware([CheckBackendSession::class])->group(function () {
Route::get('/admin/luspaparams', [App\Http\Controllers\AdminController::class, 'luspaparams']);
Route::get('/admin/reports', [App\Http\Controllers\AdminController::class, 'reports']);
Route::get('/admin/districts/{region_id}', [App\Http\Controllers\AdminController::class, 'districts']);
Route::get('/admin/permissions', [App\Http\Controllers\AdminController::class, 'systempermissions']);
Route::get('/users/getprofile', [App\Http\Controllers\UsersController::class, 'getprofile_json']);
Route::get('/users/{user_id}', [App\Http\Controllers\UsersController::class, 'show']);
@ -59,6 +70,9 @@ Route::middleware([CheckBackendSession::class])->group(function () {
Route::get('/permits/home', [App\Http\Controllers\PermitsController::class, 'index']);
Route::get('/permits/districtsettings', [App\Http\Controllers\PermitsController::class, 'settings']);
Route::get('/permits/viewapplication/{id}', [App\Http\Controllers\PermitsController::class, 'show']);
Route::get('/permits/status/{name}', [App\Http\Controllers\PermitsController::class, 'statusIndex']);