diff --git a/app/Config/Routes.php b/app/Config/Routes.php index d74d1d3f..0e25537d 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -73,6 +73,9 @@ $routes->group("/user", ["filter" => "authMVC"], function ($routes) { $routes->get("deactive/(:hash)", "UserController::deactive/$1"); $routes->get("rolesandteams", "UserController::getRolesAndTeams"); $routes->get("getUserActivityHistory", "UserController::getUserActivityHistory"); + $routes->match(['get','post','put'], 'partner', 'UserController::partner'); + $routes->match(['get','post','put'], 'partnerIncentive', 'UserController::partnerIncentive'); + $routes->get("download-incentive-file/(:any)", "UserController::downloadIncentivesFile/$1"); }); $routes->group("/dashboard", ["filter" => "authMVC"], function ($routes) { diff --git a/app/Controllers/UserController.php b/app/Controllers/UserController.php index 78d3a6c0..2ce2e529 100755 --- a/app/Controllers/UserController.php +++ b/app/Controllers/UserController.php @@ -18,6 +18,8 @@ use App\Models\UserTeamsModel; use App\Helpers\BookStackUserHelper; use App\Models\AuthHistoryModel; use App\Models\UserActivityHistoryModel; +use App\Models\PartnerStaffModel; +use App\Models\PartnerManagerIncentiveFileModel; class UserController extends AdminController @@ -32,6 +34,8 @@ class UserController extends AdminController protected $bookStack; protected $authHistoryModel; protected $userActivityHistoryModel; + protected $partnerStaffModel; + protected $partnerManagerIncentiveFileModel; public function __construct() { @@ -45,6 +49,8 @@ class UserController extends AdminController $this->bookStack = new BookStackUserHelper(); $this->authHistoryModel = new AuthHistoryModel(); $this->userActivityHistoryModel = new UserActivityHistoryModel(); + $this->partnerStaffModel = new PartnerStaffModel(); + $this->partnerManagerIncentiveFileModel = new PartnerManagerIncentiveFileModel(); } public function list() @@ -563,4 +569,211 @@ class UserController extends AdminController } } + public function partner() + { + $method = $this->request->getMethod(); // get, post + try{ + // Listing + if ($method === 'get') { + $types = $this->partnerStaffModel->findAll(); + if (empty($types)) { + return $this->response->setJSON(['status' => 'error','message' => 'No Staff found'])->setStatusCode(404); + } + return $this->response->setJSON(['status' => 'success','data' => $types])->setStatusCode(200); + } + + // add/update + if ($method === 'post') { + + $data = $this->request->getPost(); + if (!empty($data['id'])) { + $text = "update"; + $result = $this->partnerStaffModel->update($data['id'], $data); + $updateID = $data['id']; + } else { + $text = "create"; + $data['role_id'] = 1; + $data['created_by'] = get_session_userid(); + $insertID = $this->partnerStaffModel->insert($data); + $result = true; + } + + $id = isset($insertID) && !empty($insertID) ? $insertID : ($updateID ?? null); + + return $this->response->setJSON([ + 'status' => $id ? 'success' : 'error', + 'message' => $id ? "Staff {$text}d successfully" : "Unable to {$text} staff. Please try again.", + 'id' => $id + ])->setStatusCode($id ? 200 : 400); + } + + // delete + if ($method === 'put') { + $data = $this->request->getRawInput(); + $id = $data['id'] ?? null; + + if (!$id) { + return $this->response->setJSON(['status' => 'error', 'message' => 'ID is required'])->setStatusCode(400); + } + + $staff = $this->partnerStaffModel->find($id); + if (!$staff) { + return $this->response->setJSON(['status' => 'error','message' => 'Staff not found'])->setStatusCode(404); + } + + if ($staff['is_active'] == 1) { + $result = $this->partnerStaffModel->update($id, ['is_active' => 0]); + $message = "Staff deleted successfully"; + } else { + return $this->response->setJSON(['status' => 'error','message' => 'Staff already deleted'])->setStatusCode(400); + } + + return $this->response->setJSON([ + 'status' => $result ? 'success' : 'error', + 'message' => $result ? $message : "Unable to delete staff. Please try again.", + 'id' => $id + ])->setStatusCode($result ? 200 : 400); + } + return $this->response->setJSON([ 'status' => 'error', 'message' => 'Invalid request method' ])->setStatusCode(405); + } + catch (\Throwable $e) { + $code = ($e->getCode() && $e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : 500; + + $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException + || $e instanceof \mysqli_sql_exception + || $e instanceof \PDOException; + + $context = ['title' => get_class($e),'type' => get_class($e),'code' => $code,'message' => $e->getMessage(),'file' => $e->getFile(),'line' => $e->getLine()]; + + $this->myLogger->logme('error', "Exception: {message} in {file} on line {line}", $context, 0); + + return $this->response->setJSON([ 'status' => 'error', 'message' => $isDbError ? 'Data Access Error' : $e->getMessage(), + 'ref' => $isDbError ? 'database - ' : 'application - ' . $code . ' - ' . $e->getLine() + ])->setStatusCode($code); + } + } + + public function partnerIncentive() + { + $method = $this->request->getMethod(); // get, post + try{ + // Listing + if ($method === 'get') { + $manager_id = $this->request->getGet('manager_id'); + $files = $this->partnerManagerIncentiveFileModel->where('manager_id', $manager_id)->findAll(); + if (empty($files)) { + return $this->response->setJSON(['status' => 'error','message' => 'No Records found'])->setStatusCode(404); + } + return $this->response->setJSON(['status' => 'success','data' => $files])->setStatusCode(200); + } + + // add/update + if ($method === 'post') { + + $file = $this->request->getFile('incentive_file_name'); + $month = $this->request->getPost('incentive_month'); + $managerId = $this->request->getPost('manager_id'); + $fileId = $this->request->getPost('id'); + + if ($file && $file->isValid() && !$file->hasMoved()) { + $fileName = $file->getName(); + $path = WRITEPATH.'uploads/incentives'; + $file->move($path, $fileName); + $data = [ + 'manager_id' => $managerId, + 'incentive_month' => date('Y-m-d', strtotime($month)), + 'incentive_file_name' => $fileName, + 'created_by' => get_session_userid() + ]; + + if ($fileId) { + $text = "update"; + $this->partnerManagerIncentiveFileModel->update($fileId, $data); + $updateID = $data['id']; + } else { + $text = "create"; + $insertID = $this->partnerManagerIncentiveFileModel->insert($data); + $result = true; + } + + $id = isset($insertID) && !empty($insertID) ? $insertID : ($updateID ?? null); + + return $this->response->setJSON([ + 'status' => $id ? 'success' : 'error', + 'message' => $id ? "File {$text}d successfully" : "Unable to {$text} file. Please try again.", + 'id' => $id + ])->setStatusCode($id ? 200 : 400); + } + return $this->response->setJSON([ + 'status' => 'error', + 'message' => "Unable to Upload file. Please try again.", + 'id' => '' + ])->setStatusCode(400); + } + + // delete + if ($method === 'put') { + $data = $this->request->getRawInput(); + $id = $data['id'] ?? null; + + if (!$id) { + return $this->response->setJSON(['status' => 'error', 'message' => 'ID is required'])->setStatusCode(400); + } + + $files = $this->partnerManagerIncentiveFileModel->find($id); + if (!$files) { + return $this->response->setJSON(['status' => 'error','message' => 'No Records found'])->setStatusCode(404); + } + + if ($files['is_active'] == 1) { + $result = $this->partnerManagerIncentiveFileModel->update($id, ['is_active' => 0]); + $message = "Files deleted successfully"; + } else { + return $this->response->setJSON(['status' => 'error','message' => 'files already deleted'])->setStatusCode(400); + } + + return $this->response->setJSON([ + 'status' => $result ? 'success' : 'error', + 'message' => $result ? $message : "Unable to delete staff. Please try again.", + 'id' => $id + ])->setStatusCode($result ? 200 : 400); + } + return $this->response->setJSON([ 'status' => 'error', 'message' => 'Invalid request method' ])->setStatusCode(405); + } + catch (\Throwable $e) { + $code = ($e->getCode() && $e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : 500; + + $isDbError = $e instanceof \CodeIgniter\Database\Exceptions\DatabaseException + || $e instanceof \mysqli_sql_exception + || $e instanceof \PDOException; + + $context = ['title' => get_class($e),'type' => get_class($e),'code' => $code,'message' => $e->getMessage(),'file' => $e->getFile(),'line' => $e->getLine()]; + + $this->myLogger->logme('error', "Exception: {message} in {file} on line {line}", $context, 0); + + return $this->response->setJSON([ 'status' => 'error', 'message' => $isDbError ? 'Data Access Error' : $e->getMessage(), + 'ref' => $isDbError ? 'database - ' : 'application - ' . $code . ' - ' . $e->getLine() + ])->setStatusCode($code); + } + } + + public function downloadIncentivesFile($file_name) + { + $file_name = basename($file_name); + $filePath = WRITEPATH . 'uploads/incentives/' . $file_name; + try { + if (file_exists($filePath)) { + return $this->response->download($filePath, null); + } else { + $data['message'] = 'File Not Found'; + echo view('errors/404', $data); + } + } catch (\Exception $e) { + // Handle any exceptions + $errorMessage = $e->getMessage(); + $this->myLogger->logme('error', $errorMessage); + // You can return an error response here + echo $errorMessage; + } + } } \ No newline at end of file diff --git a/app/Models/PartnerManagerIncentiveFileModel.php b/app/Models/PartnerManagerIncentiveFileModel.php new file mode 100755 index 00000000..32e59444 --- /dev/null +++ b/app/Models/PartnerManagerIncentiveFileModel.php @@ -0,0 +1,56 @@ + 'required|integer', + // 'incentive_month' => 'required|valid_date', + // 'incentive_file_name'=> 'required|string|max_length[150]', + // ]; + + // protected $validationMessages = [ + // 'manager_id' => [ + // 'required' => 'Manager ID is required', + // 'integer' => 'Manager ID must be a number', + // ], + // 'incentive_month' => [ + // 'required' => 'Incentive Month is required', + // 'valid_date' => 'Incentive Month must be a valid date (Y-m-d)', + // ], + // 'incentive_file_name' => [ + // 'required' => 'File name is required', + // 'max_length' => 'File name cannot exceed 150 characters', + // ], + // ]; + + // protected $skipValidation = false; +} diff --git a/app/Models/PartnerStaffModel.php b/app/Models/PartnerStaffModel.php new file mode 100755 index 00000000..474f14d1 --- /dev/null +++ b/app/Models/PartnerStaffModel.php @@ -0,0 +1,50 @@ + 'required|min_length[2]|max_length[150]', + // 'email' => 'permit_empty|valid_email|max_length[150]', + // 'mobile' => 'permit_empty|regex_match[/^[0-9]{10,20}$/]', + // ]; + + // protected $validationMessages = [ + // 'name' => [ + // 'required' => 'Name is required', + // 'min_length' => 'Name must have at least 2 characters', + // 'max_length' => 'Name cannot exceed 150 characters' + // ], + // 'email' => [ + // 'valid_email' => 'Please provide a valid email address', + // 'max_length' => 'Email cannot exceed 150 characters' + // ], + // 'mobile' => [ + // 'regex_match' => 'Mobile number must be 10–20 digits only' + // ] + // ]; + + // protected $skipValidation = false; +} diff --git a/app/Views/UserList.php b/app/Views/UserList.php index ea8a21ae..3e83907b 100755 --- a/app/Views/UserList.php +++ b/app/Views/UserList.php @@ -42,7 +42,8 @@ table.dataTable tbody td { padding: 20px; } - #mobile::placeholder { + #mobile::placeholder, + #mobile_no::placeholder { font-size: 13px; } @@ -246,9 +247,102 @@ table.dataTable tbody td { border:1px solid rgba(41, 139, 142, 1); } + .dt-buttons.btn-group{ + display: grid; + grid-template-columns: 1fr .4fr .5fr .2fr; + } + + #user-table_filter input{ width:100%; } + + button.dt-button, + button.dt-button:focus, + button.dt-button:active, + button.dt-button:hover { + background: none !important; + border: none !important; + box-shadow: none !important; + padding: 0 !important; + margin: 0 !important; + } + + + /* main button wrapper */ + .tab-button { + width: 201px; + height: 37px; + border-radius: 10px !important; + font-weight: 700; + font-size: 14px; + line-height: 100%; + border: 1px solid #BAF1F3; + background: #F5FFFF; + cursor: pointer; + transition: all 0.2s ease-in-out; + display: flex; + justify-content: center; + align-items: center; + gap: 6px; + } + + /* divider style */ + .divider-line { + color: #DBDBDB; + font-weight: 400; + } + + /* active state */ + .highlight-link.active { + color: #00999E; + } + + /* inactive state */ + .highlight-link:not(.active) { + color: #707070; + } + + .no-files-message { + width: 900px; + height: 300px; + background: #ECECEC; + opacity: 1; + + display: flex; + align-items: center; + justify-content: center; + + font-weight: 500; /* Medium */ + font-size: 18px; + line-height: 100%; + letter-spacing: 0; + color: #333; /* Adjust text color if needed */ + text-align: center; + + border-radius: 8px; /* optional for smooth edges */ + margin: 13px; /* center horizontally */ + } + + #container { + max-height: 400px; /* set fixed height */ + overflow-y: auto; /* enable vertical scroll */ + overflow-x: hidden; /* prevent horizontal scroll */ + } + + + .file-icon-box { + /* width: 40px; + height: 50px; + display: flex; + align-items: center; + justify-content: center; */ + border-radius: 10px; + background: #F4F6F8; + border: 1px solid #ddd; /* matches border-width:1px */ + padding: 3px; + } +
| Name | @@ -278,7 +372,7 @@ table.dataTable tbody td {mobile; ?> | user_role; ?> | - + is_active == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?> | @@ -296,6 +390,67 @@ table.dataTable tbody td {
|---|