CHANGE_User + Nhance Partner
This commit is contained in:
parent
9682865454
commit
33581a37a5
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
app/Models/PartnerManagerIncentiveFileModel.php
Executable file
56
app/Models/PartnerManagerIncentiveFileModel.php
Executable file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class PartnerManagerIncentiveFileModel extends Model
|
||||
{
|
||||
protected $table = 'partner_manager_incentive_file';
|
||||
protected $primaryKey = 'id';
|
||||
protected $useAutoIncrement = true;
|
||||
|
||||
protected $returnType = 'array'; // or 'object'
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $allowedFields = [
|
||||
'manager_id',
|
||||
'incentive_month',
|
||||
'incentive_file_name',
|
||||
'is_active',
|
||||
'created_by',
|
||||
'created_on',
|
||||
'updated_by',
|
||||
'updated_on'
|
||||
];
|
||||
|
||||
// Timestamps
|
||||
protected $useTimestamps = true;
|
||||
protected $createdField = 'created_on';
|
||||
protected $updatedField = 'updated_on';
|
||||
protected $dateFormat = 'datetime'; // can be 'date' or 'int'
|
||||
|
||||
// Validation Rules (optional, can add more)
|
||||
// protected $validationRules = [
|
||||
// 'manager_id' => '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;
|
||||
}
|
||||
50
app/Models/PartnerStaffModel.php
Executable file
50
app/Models/PartnerStaffModel.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class PartnerStaffModel extends Model
|
||||
{
|
||||
protected $table = 'partner_staff'; // table name
|
||||
protected $primaryKey = 'id'; // primary key
|
||||
|
||||
protected $useAutoIncrement = true;
|
||||
|
||||
// return results as array
|
||||
protected $returnType = 'array';
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
// allowed fields for insert/update
|
||||
protected $allowedFields = ['name','email','mobile','emp_id','role_id','email_otp','is_active','created_by','updated_by','manager_id'];
|
||||
|
||||
// automatic timestamps
|
||||
protected $useTimestamps = true;
|
||||
protected $createdField = 'created_on';
|
||||
protected $updatedField = 'updated_on';
|
||||
protected $dateFormat = 'datetime';
|
||||
|
||||
// validation rules
|
||||
// protected $validationRules = [
|
||||
// 'name' => '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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<!-- End ADD and EDIT Page HTML -->
|
||||
<div class="row" id="List-page">
|
||||
<div class="col-12">
|
||||
@ -259,7 +353,7 @@ table.dataTable tbody td {
|
||||
<h4 style="position: relative;">Users</h4>
|
||||
</div>
|
||||
</div>
|
||||
<table data-custom-table-css="table" class="table table-sm table-hover m-0 table-centered dt-responsive nowrap w-100" cellspacing="0" id="tickets-table">
|
||||
<table data-custom-table-css="table" class="table table-sm table-hover m-0 table-centered dt-responsive nowrap w-100" cellspacing="1" id="user-table">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="font-weight-medium">Name</th>
|
||||
@ -278,7 +372,7 @@ table.dataTable tbody td {
|
||||
<td><?php echo $row->mobile; ?></td>
|
||||
<td><?php echo $row->user_role; ?></td>
|
||||
<td>
|
||||
<span class="<?php if($row->is_active == 1){ echo 'badge badge-success'; }else{ echo 'badge badge-danger'; } ?>">
|
||||
<span class="<?php if($row->is_active == 1){ echo 'badge badge-primary'; }else{ echo 'badge badge-danger'; } ?>">
|
||||
<?php if($row->is_active == 1){ echo 'Active'; }else{ echo 'In-Active'; } ?>
|
||||
</span>
|
||||
</td>
|
||||
@ -296,6 +390,67 @@ table.dataTable tbody td {
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<!-- <table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table w-100 nowrap text-custom-black text-custom app-datatable">
|
||||
<thead class="app-table-head">
|
||||
<tr>
|
||||
<th>Ticket ID</th>
|
||||
<th class="app-text-left">Name</th>
|
||||
<th>Policy Number</th>
|
||||
<th>Ticket Type</th>
|
||||
<th>Subject</th>
|
||||
<th>Status</th>
|
||||
<th class="app-text-left">Assign To</th>
|
||||
<th>Created At</th>
|
||||
<th>Updated At</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="app-table-body">
|
||||
<?php if (isset($ticket_data)) { ?>
|
||||
<?php foreach($ticket_data as $index => $row){ ?>
|
||||
|
||||
<tr data-id="<?= $row['thz_id']; ?>" style="cursor: pointer;">
|
||||
<td class="app-text-right"><?php echo $row['thz_id']; ?></td>
|
||||
<td class="app-text-left">
|
||||
<?php echo $row['name']; ?>
|
||||
<span class="text-custom-grey"><?php if (!empty($row['empcode'])): echo '('.$row['empcode'].')'; endif; ?></span><br>
|
||||
<span class="text-custom-grey"><?php if (!empty($row['mobile'])): echo $row['mobile']; endif; ?></span>
|
||||
</td>
|
||||
<td class="app-text-center"><?php echo (!empty($row['policy_no']) && strtolower($row['policy_no']) !== 'null')
|
||||
? $row['policy_no']
|
||||
: 'N/A'; ?>
|
||||
</td>
|
||||
<td class="app-text-center"><?php echo $row['ticket_type'] ? $row['ticket_type'] : '-'; ?></td>
|
||||
<td class="app-text-center wrap" title="<?php echo htmlspecialchars($row['subject']); ?>">
|
||||
<?php
|
||||
$subject = $row['subject'] ? $row['subject'] : 'N/A';
|
||||
echo (strlen($subject) > 50)
|
||||
? htmlspecialchars(substr($subject, 0, 50)) . "..."
|
||||
: htmlspecialchars($subject);
|
||||
?>
|
||||
</td>
|
||||
<td class="app-text-center"><?php echo $row['status'] ? $row['status'] : '-' ; ?></td>
|
||||
<td class="app-text-left"><?php echo $row['assignee_name'] ? $row['assignee_name'] : '-'; ?></td>
|
||||
<td class="app-text-left">
|
||||
<?php if (!empty($row['created_at'])):
|
||||
$cd = date("j F Y", strtotime($row['created_at']));
|
||||
$ct = date("h:i a", strtotime($row['created_at']));
|
||||
echo $cd . "<br><span class='time'> " . $ct . "</span>";
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
<td class="app-text-left">
|
||||
<?php if (!empty($row['updated_at'])):
|
||||
$ud = date("j F Y", strtotime($row['updated_at']));
|
||||
$ut = date("h:i a", strtotime($row['updated_at']));
|
||||
echo $ud . "<br><span class='time'> " . $ut . "</span>";
|
||||
endif;
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</tbody> -->
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -387,6 +542,119 @@ table.dataTable tbody td {
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.modal -->
|
||||
<div id="nhance-partner-modal" class="modal fade app-font-family" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;" data-backdrop="static">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Add Nhance Partner </h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body p-4">
|
||||
<div class="">
|
||||
|
||||
<form role="form" class="parsley-examples" method="post" id="PartnerForm" action="" enctype="multipart/form-data">
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>"/>
|
||||
<input type="hidden" name="PrimaryKey" id="partner_id" name="id"/>
|
||||
<div class="form-group">
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="partner_name">Name<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="partner_name" placeholder="Ente Name" name="name" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="mobile_no">Mobile Number<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="mobile_no" placeholder="Enter Mobile Number ( starting with 6, 7, 8, or 9 only. )" name="mobile" onkeypress = "return onlyNumbers(event)" maxlength="10" minlength="10" pattern="^[6-9]\d{9}$" data-parsley-type-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." data-parsley-required-message="Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9." required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="email_addr">Email<span class="text-danger">*</span></label>
|
||||
<input type="text" class="form-control" id="email_addr" placeholder="Enter Email" name="email" data-parsley-trigger="change" data-parsley-type="email" required>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="locn">Address</label>
|
||||
<textarea class="form-control" id="locn" name="address" placeholder="Enter address" rows="3" maxlength="1500"></textarea>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-group text-right m-b-0">
|
||||
<button class="btn app-btn-outline-secondary mr-2 " type="button" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
<button class="btn app-btn-secondary waves-effect waves-light" type="button" id="btnPartnerSubmit" onclick="submitPartner(event)">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.modal -->
|
||||
<div id="upload-incentive-file-modal" class="modal fade app-font-family" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;" data-backdrop="static">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title"></h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<form role="form" class="parsley-examples" method="post" id="PartnerIncentiveForm" action="" enctype="multipart/form-data">
|
||||
<input type="hidden" value="<?= csrf_hash() ?>" name="<?= csrf_token() ?>"/>
|
||||
<input type="hidden" id="manager_id" name="manager_id" />
|
||||
<div class="form-group">
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-5">
|
||||
<label for="incentive_month">Date</label>
|
||||
<div class="input-icon">
|
||||
<input type="text" class="form-control" name="incentive_month" id="incentive_month" required>
|
||||
<i class="mdi mdi-calendar-blank-outline additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-5">
|
||||
<label for="incentive_file_name">Upload File</label>
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" name="incentive_file_name" id="incentive_file_name" required>
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-2 text-right" style="margin-top: 27px;">
|
||||
<button class="btn app-btn-secondary waves-effect waves-light" type="button" id="btnPartnerIncentiveSubmit" onclick="submitIncentivePartner(event)">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!-- <div class="row">
|
||||
<div class="col-2">
|
||||
<label for="filter">Files </label>
|
||||
</div>
|
||||
<div class="offset-col-7 col-3">
|
||||
<div class="input-icon text-right">
|
||||
<input type="text" class="form-control" id="filter">
|
||||
<i class="mdi mdi-magnify additional-icon"></i>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="row align-items-center">
|
||||
<div class="col-2">
|
||||
<label for="filter" class="mb-0">Files</label>
|
||||
</div>
|
||||
<div class="col-5 ml-auto">
|
||||
<div class="input-icon">
|
||||
<input type="text" class="form-control" id="filter" placeholder="Search...">
|
||||
<i class="mdi mdi-magnify additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
<!-- Tooltip container separate from trigger -->
|
||||
<div class="tooltip-container" id="tooltipContainer">
|
||||
@ -523,43 +791,129 @@ table.dataTable tbody td {
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var table;
|
||||
$(document).ready(function () {
|
||||
|
||||
var incentiveMonthPicker = flatpickr("#incentive_month", {
|
||||
dateFormat: "Y-m-d", // real value stored (hidden)
|
||||
altInput: true, // show a user-friendly display
|
||||
altFormat: "M-Y", // what you want to display (Aug-2025)
|
||||
allowInput: false,
|
||||
});
|
||||
|
||||
$('#tickets-table').DataTable({
|
||||
dom: "<'row'<'col-sm-0'f><'col-sm-9 text-right'B>>" + // Keep your original alignment for the search and buttons
|
||||
"<'row'<'col-sm-12'tr>>" + // Table rows
|
||||
"<'row'<'col-sm-6'i><'col-sm-6'p>>",
|
||||
table = $('#user-table').DataTable({
|
||||
scrollX: true,
|
||||
dom: "<'row'<'col-sm-3'f><'col-sm-9'B>>" +
|
||||
"<'row'<'col-sm-12'tr>>" +
|
||||
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
|
||||
buttons: [
|
||||
// {
|
||||
// extend: 'collection',
|
||||
// text: '<i class="mdi mdi-account-multiple"></i><span class="btn-custom"> Load Data </span>',
|
||||
// className: 'btn app-btn-primary mr-2',
|
||||
// buttons: [
|
||||
// {
|
||||
// text: 'Load User',
|
||||
// action: function () { loadUser(); }
|
||||
// },
|
||||
// {
|
||||
// text: 'Load Nhance Partner',
|
||||
// action: function () { loadPartner(); }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// text: '<i class="mdi mdi-account-multiple"></i><span class="btn-custom">Load User</span>',
|
||||
// className: 'btn app-btn-primary mr-2 toggleLoadBtn',
|
||||
// action: function (e, dt, node, config) {
|
||||
// let $btn = $(node).find('span.btn-custom');
|
||||
// let currentText = $btn.text().trim();
|
||||
// if (currentText === "Load User") {
|
||||
// loadUser();
|
||||
// $btn.text("Load user"); // toggle text
|
||||
// } else {
|
||||
// loadPartner();
|
||||
// $btn.text("Load partner"); // toggle back
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// text: '<i class="mdi mdi-account-multiple"></i><span class="btn-custom">Load User</span>',
|
||||
// className: 'btn app-btn-primary mr-2 toggleLoadBtn',
|
||||
// action: function (e, dt, node, config) {
|
||||
// let $btn = $(node).find('span.btn-custom');
|
||||
// // check current mode from button dataset (default: user)
|
||||
// let currentMode = $btn.data("mode") || "user";
|
||||
// if (currentMode === "user") {
|
||||
// loadUser();
|
||||
// $btn.text("Load Nhance Partner");
|
||||
// $btn.data("mode", "partner"); // switch mode
|
||||
// } else {
|
||||
// loadPartner();
|
||||
// $btn.text("Load User");
|
||||
// $btn.data("mode", "user"); // switch back
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
{
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add User </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
attr: { id: 'btnAdd' }
|
||||
},
|
||||
{
|
||||
text: '<i class="mdi mdi-plus"></i><span class="btn-custom"> Add Nhance Partner </span>',
|
||||
className: 'btn app-btn-primary mr-2',
|
||||
attr: { id: 'btnNhancePartnerAdd' }
|
||||
},
|
||||
{
|
||||
extend: 'collection',
|
||||
text: '<span class="btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
|
||||
className: 'btn app-btn-secondary',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'csv',
|
||||
text: 'CSV',
|
||||
title: 'UserList',
|
||||
exportOptions: {
|
||||
columns: ':not(:last-child)'
|
||||
}
|
||||
text: '<i class="mdi mdi-file-delimited"></i><span class="btn-custom"> CSV </span>',
|
||||
className: 'app-btn-primary'
|
||||
},
|
||||
{
|
||||
text: 'ADD',
|
||||
className: 'btn-color',
|
||||
attr: {
|
||||
id: 'btnAdd',
|
||||
title: 'Add'
|
||||
extend: 'excel',
|
||||
text: '<i class="mdi mdi-file-excel"></i><span class="btn-custom"> EXCEL </span>',
|
||||
exportOptions: { orthogonal: 'sort' },
|
||||
className: 'app-btn-primary'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
|
||||
|
||||
paging: true,
|
||||
pageLength: 25,
|
||||
language: {
|
||||
search: "_INPUT_",
|
||||
searchPlaceholder: "Search..."
|
||||
},
|
||||
initComplete: function () {
|
||||
$(".dt-buttons").prepend(`
|
||||
<div class="tab-button mr-2" id="toggleButton" style="float:left;">
|
||||
<span id="btnUsers" class="highlight-link active">Users</span>
|
||||
<span class="divider-line"> | </span>
|
||||
<span id="btnPartners" class="highlight-link">Nhance Partner</span>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$('#btnUsers').on('click', function () {
|
||||
$('#btnPartners').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
loadUser();
|
||||
});
|
||||
|
||||
$('#btnPartners').on('click', function () {
|
||||
$('#btnUsers').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
loadPartner();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
$('#team').multiselect({
|
||||
nonSelectedText: 'Select Team',
|
||||
@ -569,9 +923,6 @@ table.dataTable tbody td {
|
||||
buttonWidth:'100%'
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$('.close').click(function(){
|
||||
$('#UserId').val('');
|
||||
$('#first_name').val('');
|
||||
@ -581,6 +932,17 @@ table.dataTable tbody td {
|
||||
$('#role').val('')
|
||||
})
|
||||
|
||||
// $('body').on('click', '#btnUsers', function () {
|
||||
// $('#btnPartners').removeClass('active');
|
||||
// $(this).addClass('active');
|
||||
// loadUser();
|
||||
// });
|
||||
|
||||
// $('body').on('click', '#btnPartners', function () {
|
||||
// $('#btnUsers').removeClass('active');
|
||||
// $(this).addClass('active');
|
||||
// loadPartner();
|
||||
// });
|
||||
|
||||
$('body').on('click', '.btnEdit', function () {
|
||||
var user_id = $(this).attr('data-id');
|
||||
@ -622,7 +984,6 @@ table.dataTable tbody td {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('body').on('click', '.btnDelete', function () {
|
||||
|
||||
Swal.fire({
|
||||
@ -645,6 +1006,68 @@ table.dataTable tbody td {
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '.btnPartnerEdit', function () {
|
||||
let user = JSON.parse($(this).attr('data-obj')); // ✅ convert back to object
|
||||
$('#PartnerForm').attr('action', '<?php echo base_url('/user/partner');?>');
|
||||
$('#partner_id').val(user.id);
|
||||
$('#partner_name').val(user.name);
|
||||
$('#email_addr').val(user.email);
|
||||
$('#mobile_no').val(user.mobile);
|
||||
$('#locn').val(user.address);
|
||||
// $('#btnPartnerSubmit').html('Update');
|
||||
$('.modal-title').html('Update Nhance Partner');
|
||||
let myModal = new bootstrap.Modal(document.getElementById('nhance-partner-modal'));
|
||||
myModal.show(); // open modal
|
||||
});
|
||||
|
||||
$('body').on('click', '.btnPartnerDelete', function () {
|
||||
Swal.fire({
|
||||
title: "Are you sure?",
|
||||
text: "You need to remove this user",
|
||||
icon: "info",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#3085d6",
|
||||
confirmButtonText: "Yes",
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
var partner_id = $(this).attr('data-id');
|
||||
|
||||
|
||||
$.ajax({ url: "<?= base_url('user/partner') ?>",
|
||||
type: "PUT",
|
||||
data: { id: partner_id },
|
||||
success: function(response) {
|
||||
console.log("Deleted:", response);
|
||||
toastr.success(response.message, 'Success');
|
||||
loadPartner(); // refresh table
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error("Delete Error:", xhr.responseText);
|
||||
let res = xhr.responseJSON || {};
|
||||
toastr.error(res.message || "Unable to delete staff", 'Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click', '.btnPartnerIncentive', function () {
|
||||
let user = JSON.parse($(this).attr('data-obj'));
|
||||
|
||||
$('#PartnerIncentiveForm').attr('action', '<?= base_url('/user/partnerIncentive');?>');
|
||||
$('#manager_id').val(user.id);
|
||||
$('#incentive_file_name').val(user.incentive_file_name);
|
||||
$('#incentive_month').val(user.incentive_month);
|
||||
|
||||
$('.modal-title').text(user.name);
|
||||
|
||||
// ✅ Load files separately
|
||||
loadIncentiveFiles(user.id);
|
||||
|
||||
let myModal = new bootstrap.Modal(document.getElementById('upload-incentive-file-modal'));
|
||||
myModal.show();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function onlyNumbers(event){
|
||||
@ -662,6 +1085,418 @@ table.dataTable tbody td {
|
||||
// document.getElementById("btnSubmit").disabled = true;
|
||||
});
|
||||
|
||||
function submitPartner(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var form = document.getElementById('PartnerForm');
|
||||
var btn = document.getElementById('btnPartnerSubmit');
|
||||
var myModal = new bootstrap.Modal(document.getElementById('nhance-partner-modal'));
|
||||
|
||||
// reset any old error styles
|
||||
form.classList.remove('was-validated');
|
||||
|
||||
var name = document.getElementById('partner_name').value.trim();
|
||||
var mobile = document.getElementById('mobile_no').value.trim();
|
||||
var email = document.getElementById('email_addr').value.trim();
|
||||
var address = document.getElementById('locn').value.trim();
|
||||
|
||||
// Validation checks
|
||||
if (name === "" || mobile === "" || email === "") {
|
||||
console.log(name);
|
||||
console.log(mobile);
|
||||
console.log(email);
|
||||
toastr.warning('Please fill all required fields.', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
if (address.length > 1500) {
|
||||
toastr.error('Address cannot exceed 1500 characters', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
var mobilePattern = /^[6-9]\d{9}$/; // must start with 6–9 and be 10 digits
|
||||
if (!mobilePattern.test(mobile)) {
|
||||
toastr.warning('Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.', 'Warning');
|
||||
document.getElementById('mobile').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var emailPattern = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
||||
if (!emailPattern.test(email)) {
|
||||
toastr.warning('Please enter a valid email address.', 'Warning');
|
||||
document.getElementById('email').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable button during submit
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Saving...";
|
||||
|
||||
var formData = new FormData(form);
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('user/partner') ?>",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
if (response.status === "success") {
|
||||
toastr.success('Partner saved successfully!', 'Success');
|
||||
myModal.hide();
|
||||
form.reset(); // reset form after success
|
||||
} else {
|
||||
toastr.warning(response.message || 'Something went wrong.', 'Warning');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.log("Error: " + xhr.statusText);
|
||||
toastr.error('Server error occurred.', 'Error');
|
||||
},
|
||||
complete: function() {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Submit";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function submitIncentivePartner(event) {
|
||||
event.preventDefault();
|
||||
|
||||
|
||||
var form = document.getElementById('PartnerIncentiveForm');
|
||||
var btn = document.getElementById('btnPartnerIncentiveSubmit');
|
||||
var myModal = new bootstrap.Modal(document.getElementById('upload-incentive-file-modal'));
|
||||
|
||||
// reset any old error styles
|
||||
form.classList.remove('was-validated');
|
||||
|
||||
|
||||
var month = document.getElementById('incentive_month').value.trim();
|
||||
var fileInput = document.getElementById('incentive_file_name');
|
||||
|
||||
if (month === "" || !fileInput.files.length) {
|
||||
toastr.warning('Please fill all required fields.', 'Warning');
|
||||
form.classList.add('was-validated');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Disable button during submit
|
||||
btn.disabled = true;
|
||||
btn.innerText = "Saving...";
|
||||
|
||||
var formData = new FormData(form);
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('user/partnerIncentive') ?>",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
dataType: 'json',
|
||||
success: function(response) {
|
||||
if (response.status === "success") {
|
||||
toastr.success('Partner Incentive saved successfully!', 'Success');
|
||||
form.reset();
|
||||
|
||||
// ✅ Reload incentive files list
|
||||
let manager_id = $('#manager_id').val();
|
||||
loadIncentiveFiles(manager_id);
|
||||
} else {
|
||||
toastr.warning(response.message || 'Something went wrong.', 'Warning');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.log("Error: " + xhr.statusText);
|
||||
toastr.error('Server error occurred.', 'Error');
|
||||
},
|
||||
complete: function() {
|
||||
btn.disabled = false;
|
||||
btn.innerText = "Submit";
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function renderRows(data, type = 'user') {
|
||||
table.clear(); // Remove old rows
|
||||
|
||||
if (Array.isArray(data) && data.length) {
|
||||
data.forEach(row => {
|
||||
let statusClass = row.is_active == 1 ? 'badge-success' : 'badge-danger';
|
||||
let statusText = row.is_active == 1 ? 'Active' : 'In-Active';
|
||||
|
||||
let rowData = [];
|
||||
if (type === 'user') {
|
||||
rowData = [
|
||||
row.first_name,
|
||||
row.email,
|
||||
row.mobile,
|
||||
row.user_role,
|
||||
`<span class="badge ${statusClass}">${statusText}</span>`,
|
||||
`<div class="btn-group dropdown">
|
||||
<a href="javascript:void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown">
|
||||
<i class="mdi mdi-dots-horizontal"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a data-toggle="modal" data-target="#con-close-modal" class="dropdown-item btnEdit" data-id="${row.id}">
|
||||
<i data-id="${row.id}" class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnEdit"></i>Edit
|
||||
</a>
|
||||
<a class="dropdown-item btnDelete" data-id="${row.id}">
|
||||
<i data-id="${row.id}" class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle btnDelete"></i>Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>`
|
||||
];
|
||||
} else { // partner
|
||||
rowData = [
|
||||
row.name,
|
||||
row.email,
|
||||
row.mobile,
|
||||
'Staff',
|
||||
`<span class="badge ${statusClass}">${statusText}</span>`,
|
||||
`<div class="btn-group dropdown">
|
||||
<a href="javascript:void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown">
|
||||
<i class="mdi mdi-dots-horizontal"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a data-toggle="modal" data-target="#nhance-partner-modal" class="dropdown-item btnPartnerEdit" data-obj='${JSON.stringify(row)}'>
|
||||
<i data-obj='${JSON.stringify(row)}' class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnPartnerEdit"></i>Edit
|
||||
</a>
|
||||
<a class="dropdown-item btnPartnerDelete" data-id="${row.id}">
|
||||
<i data-id="${row.id}" class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle btnPartnerDelete"></i>Delete
|
||||
</a>
|
||||
<a class="dropdown-item btnPartnerPerformance" data-id="${row.id}">
|
||||
<i data-id="${row.id}" class="mdi mdi-speedometer mr-2 text-muted font-18 vertical-middle btnPartnerPerformance"></i>View Performance
|
||||
</a>
|
||||
<a data-toggle="modal" data-target="#upload-incentive-file-modal" class="dropdown-item btnPartnerIncentive" data-obj='${JSON.stringify(row)}'>
|
||||
<i data-obj='${JSON.stringify(row)}' class="mdi mdi-upload mr-2 text-muted font-18 vertical-middle btnPartnerIncentive"></i>Upload Incentive File
|
||||
</a>
|
||||
</div>
|
||||
</div>`
|
||||
];
|
||||
}
|
||||
|
||||
table.row.add(rowData);
|
||||
});
|
||||
} else {
|
||||
// Show placeholder if no data
|
||||
table.row.add([
|
||||
`<td colspan="6" class="text-center text-muted">No ${type === 'user' ? 'users' : 'partners'} found</td>`
|
||||
]);
|
||||
}
|
||||
|
||||
table.draw(); // Redraw table
|
||||
}
|
||||
|
||||
// function loadUser() {
|
||||
|
||||
// let tbody = $('#loadDynamicDetails');
|
||||
// tbody.empty();
|
||||
// let users = <?= json_encode($UserList) ?>;
|
||||
// users.forEach(row => {
|
||||
// let statusClass = row.is_active == 1 ? 'badge-success' : 'badge-danger';
|
||||
// let statusText = row.is_active == 1 ? 'Active' : 'In-Active';
|
||||
|
||||
// tbody.append(`
|
||||
// <tr id="${row.id}">
|
||||
// <td class="text-dark">${row.first_name}</td>
|
||||
// <td>${row.email}</td>
|
||||
// <td>${row.mobile}</td>
|
||||
// <td>${row.user_role}</td>
|
||||
// <td><span class="badge ${statusClass}">${statusText}</span></td>
|
||||
// <td>
|
||||
// <div class="btn-group dropdown">
|
||||
// <a href="javascript:void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown">
|
||||
// <i class="mdi mdi-dots-horizontal"></i>
|
||||
// </a>
|
||||
// <div class="dropdown-menu dropdown-menu-right">
|
||||
// <a data-toggle="modal" data-target="#con-close-modal" class="dropdown-item btnEdit" data-id="${row.id}">
|
||||
// <i data-id="${row.id}" class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnEdit"></i>Edit
|
||||
// </a>
|
||||
// <a class="dropdown-item btnDelete" data-id="${row.id}">
|
||||
// <i data-id="${row.id}" class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle btnDelete"></i>Delete
|
||||
// </a>
|
||||
// </div>
|
||||
// </div>
|
||||
// </td>
|
||||
// </tr>
|
||||
// `);
|
||||
// });
|
||||
// }
|
||||
function loadUser() {
|
||||
let users = <?= json_encode($UserList) ?>;
|
||||
renderRows(users, 'user');
|
||||
}
|
||||
|
||||
// function loadPartner() {
|
||||
// $.ajax({
|
||||
// url: '<?= base_url("user/partner"); ?>',
|
||||
// method: 'GET',
|
||||
// success: function(response) {
|
||||
// console.log(response); // {status: "success", data: [...]}
|
||||
|
||||
// if (response.status === "success" && Array.isArray(response.data)) {
|
||||
// let tbody = $('#loadDynamicDetails');
|
||||
// tbody.empty();
|
||||
|
||||
// response.data.forEach(row => {
|
||||
// let statusClass = row.is_active == 1 ? 'badge-success' : 'badge-danger';
|
||||
// let statusText = row.is_active == 1 ? 'Active' : 'In-Active';
|
||||
|
||||
// tbody.append(`
|
||||
// <tr id="${row.id}">
|
||||
// <td class="text-dark">${row.name}</td>
|
||||
// <td>${row.email}</td>
|
||||
// <td>${row.mobile}</td>
|
||||
// <td>Staff</td>
|
||||
// <td><span class="badge ${statusClass}">${statusText}</span></td>
|
||||
// <td>
|
||||
// <div class="btn-group dropdown">
|
||||
// <a href="javascript:void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown">
|
||||
// <i class="mdi mdi-dots-horizontal"></i>
|
||||
// </a>
|
||||
// <div class="dropdown-menu dropdown-menu-right">
|
||||
// <a data-toggle="modal" data-target="#nhance-partner-modal" class="dropdown-item btnPartnerEdit" data-obj='${JSON.stringify(row)}'>
|
||||
// <i data-obj='${JSON.stringify(row)}' class="mdi mdi-pencil mr-2 text-muted font-18 vertical-middle btnPartnerEdit"></i>Edit
|
||||
// </a>
|
||||
// <a class="dropdown-item btnPartnerDelete" data-id="${row.id}">
|
||||
// <i data-id="${row.id}" class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle btnPartnerDelete"></i>Delete
|
||||
// </a>
|
||||
// <a class="dropdown-item btnPartnerPerformance" data-id="${row.id}">
|
||||
// <i data-id="${row.id}" class="mdi mdi-speedometer mr-2 text-muted font-18 vertical-middle btnPartnerPerformance"></i>View Performance
|
||||
// </a>
|
||||
// <a data-toggle="modal" data-target="#upload-incentive-file-modal" class="dropdown-item btnPartnerIncentive" data-obj='${JSON.stringify(row)}'>
|
||||
// <i data-obj='${JSON.stringify(row)}' class="mdi mdi-upload mr-2 text-muted font-18 vertical-middle btnPartnerIncentive"></i>Upload Incentive File
|
||||
// </a>
|
||||
// </div>
|
||||
// </div>
|
||||
// </td>
|
||||
// </tr>
|
||||
// `);
|
||||
// });
|
||||
// } else {
|
||||
// console.warn("No partner data found");
|
||||
// $('#loadDynamicDetails').html(`<tr><td colspan="6" class="text-center text-muted">No partners found</td></tr>`);
|
||||
// }
|
||||
// },
|
||||
// error: function(xhr, status, error) {
|
||||
// console.error("Error loading partners:", error);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
function loadPartner() {
|
||||
$.ajax({
|
||||
url: '<?= base_url("user/partner"); ?>',
|
||||
method: 'GET',
|
||||
success: function(response) {
|
||||
if (response.status === "success" && Array.isArray(response.data)) {
|
||||
renderRows(response.data, 'partner');
|
||||
} else {
|
||||
renderRows([], 'partner');
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("Error loading partners:", error);
|
||||
renderRows([], 'partner');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadIncentiveFiles(manager_id) {
|
||||
|
||||
// let modal = $("#upload-incentive-file-modal");
|
||||
// let container = modal.find(".container");
|
||||
|
||||
let container = $("#container");
|
||||
container.html(`<div class="text-muted small">Loading...</div>`); // temporary loading msg
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('user/partnerIncentive') ?>",
|
||||
method: 'GET',
|
||||
data: { manager_id: manager_id }, // pass manager_id if required
|
||||
success: function(response) {
|
||||
container.empty();
|
||||
|
||||
if (response.status === "success" && response.data && response.data.length) {
|
||||
response.data.forEach((file) => {
|
||||
let date = new Date(file.updated_on);
|
||||
let options = {
|
||||
day: '2-digit',
|
||||
month: 'short',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false
|
||||
};
|
||||
let uploaded = date.toLocaleString('en-GB', options).replace(',', '');
|
||||
let color = file.incentive_file_name ? "app-text-success" : "app-text-black";
|
||||
let download_url = "<?= base_url('user/download-incentive-file/') ?>" + encodeURIComponent(file.incentive_file_name);
|
||||
|
||||
|
||||
let card = `<div class="col-md-6 mt-2 file-card"
|
||||
data-name="${file.incentive_file_name.toLowerCase()}"
|
||||
data-date="${uploaded.toLowerCase()}">
|
||||
<div class="d-flex align-items-center justify-content-between border rounded p-2 bg-white">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="file-icon-box d-flex align-items-center justify-content-center">
|
||||
<i class="mdi mdi-file-document-outline app-text-black" style="font-size: 24px;"></i>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<div class="font-weight-bold app-text-black small">${file.incentive_file_name}</div>
|
||||
<div class="text-muted small">Uploaded ${uploaded}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="${download_url}" target="_blank" class="text-decoration-none">
|
||||
<i class="mdi mdi-download ${color}" style="font-size: 22px;"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
container.append(card);
|
||||
});
|
||||
} else {
|
||||
container.append(`<div class="no-files-message">No Files have been Uploaded</div>`);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
container.html(`<div class="no-files-message">No Files have been Uploaded</div>`);
|
||||
toastr.error('Server error occurred.', 'Error');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#filter').on('keyup', function () {
|
||||
let value = $(this).val().toLowerCase().trim();
|
||||
let cards = $("#container .file-card");
|
||||
let matchCount = 0;
|
||||
|
||||
cards.each(function () {
|
||||
let name = $(this).data('name');
|
||||
let date = $(this).data('date');
|
||||
|
||||
if (name.includes(value) || date.includes(value)) {
|
||||
$(this).show();
|
||||
matchCount++;
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle "no files" message
|
||||
$(".no-files-message").remove();
|
||||
if (matchCount === 0) {
|
||||
$("#container").append(`<div class="no-files-message col-12">No Files have been Uploaded</div>`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>
|
||||
@ -848,5 +1683,17 @@ table.dataTable tbody td {
|
||||
myModal.show(); // open modal
|
||||
|
||||
});
|
||||
$(document).on('click', '#btnNhancePartnerAdd', function(){
|
||||
$('#partner_name').val('');
|
||||
$('#email').val('');
|
||||
$('#partner_id').val('');
|
||||
$('#mobile_no').val('');
|
||||
$('#locn').val('');
|
||||
$('#PartnerForm').attr('action', '<?php echo base_url('/user/partner');?>');
|
||||
let myModal = new bootstrap.Modal(document.getElementById('nhance-partner-modal'));
|
||||
myModal.show(); // open modal
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
@ -1,25 +1,4 @@
|
||||
<style>
|
||||
.input-icon {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-icon .form-control {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-icon .additional-icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
pointer-events: none;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<!-- modal content -->
|
||||
<div id="con-close-modal" class="modal fade app-font-family" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg" <?= !isset($CD_Master_Data) ? 'style="max-width: 35% !important; margin:5px auto!important;"' : '' ?>>
|
||||
|
||||
@ -61,37 +61,6 @@ input:checked + .slider:before {
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.form-input-icon {
|
||||
position: relative;
|
||||
width: 100%; /* match Bootstrap's width */
|
||||
}
|
||||
|
||||
.form-input-icon input[type="file"].form-control {
|
||||
padding-right: 40px; /* space for the icon */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.form-input-icon input[type="file"].form-control::file-selector-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-input-icon .form-additional-icon {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
accent-color: #40B2B6; /* sets the checked color */
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="tab-pane fade active show" id="general-q-tab">
|
||||
|
||||
@ -190,10 +159,10 @@ input:checked + .slider:before {
|
||||
<div class="form-group row">
|
||||
<label for="insurer_logo" class="col-md-4 col-form-label">Insurer Logo</label>
|
||||
<div class="col-md-5">
|
||||
<div class="form-input-icon">
|
||||
<div class="input-icon">
|
||||
<input type="file" class="form-control" id="insurer_logo" name="insurer_logo"
|
||||
accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();">
|
||||
<i class="mdi mdi-upload form-additional-icon"></i>
|
||||
<i class="mdi mdi-upload additional-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
|
||||
@ -1124,6 +1124,58 @@ a.app-badge-secondary:focus, a.app-badge-secondary.focus {
|
||||
padding-top: 0px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.btn-custom {
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
|
||||
/* Common wrapper (works for text/file inputs) */
|
||||
.input-icon {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* All form controls inside */
|
||||
.input-icon .form-control {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-right: 40px; /* always keep space for icon */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Hide default file button */
|
||||
.input-icon .form-control[type="file"]::file-selector-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.input-icon input[type="file"].form-control {
|
||||
padding-right: 40px; /* space for the icon */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Common icon class */
|
||||
.input-icon .additional-icon {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
font-size: 18px;
|
||||
color: #555;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
accent-color: #40B2B6; /* sets the checked color */
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
|
||||
@ -32,21 +32,6 @@ table.dataTable td.wrap {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
|
||||
.btn-custom {
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
letter-spacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user