Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
velz 2026-04-28 18:42:48 +05:30
commit a06b74da6a
39 changed files with 1870 additions and 744 deletions

View File

@ -817,6 +817,8 @@ $routes->group("/ticket", ["filter" => "authMVC"], function ($routes) {
$routes->post('saveIRDocsJson',"TicketController::saveIRDocsJson"); $routes->post('saveIRDocsJson',"TicketController::saveIRDocsJson");
$routes->get('getTpaClaimStatus',"ApiServiceController::getClaimStatus"); $routes->get('getTpaClaimStatus',"ApiServiceController::getClaimStatus");
$routes->post('manualTpaClaimPush',"ApiServiceController::manualTpaClaimPush"); $routes->post('manualTpaClaimPush',"ApiServiceController::manualTpaClaimPush");
$routes->match(['get', 'post'], 'getClaimTemplateData', 'TicketController::getClaimTemplateData');
$routes->post('uploadApprovedLetterFromReply', 'TicketController::uploadApprovedLetterFromReply');
}); });
// Non-EB Claims // Non-EB Claims

View File

@ -3925,7 +3925,6 @@ class EmployeeRestController extends AdminController
$count = $this->ticketMaster->where('id', $ticket_id)->where('is_active', 1)->where('tpa_claim_push_reference_no IS NULL')->countAllResults(); $count = $this->ticketMaster->where('id', $ticket_id)->where('is_active', 1)->where('tpa_claim_push_reference_no IS NULL')->countAllResults();
log_message('error', 'Ticket validation | Ticket ID: ' . $ticket_id . ' | Matching active tickets with NULL TPA reference: ' . $count); log_message('error', 'Ticket validation | Ticket ID: ' . $ticket_id . ' | Matching active tickets with NULL TPA reference: ' . $count);
if ($count > 0 && $pdf_exist_in_the_file && $tpa_claim_push == true) { if ($count > 0 && $pdf_exist_in_the_file && $tpa_claim_push == true) {
try { try {
// this call for TPA integration // this call for TPA integration
@ -3945,6 +3944,16 @@ class EmployeeRestController extends AdminController
} }
} }
if($tpa_claim_push == false){
try {
// this call for TPA integration Multiple document push for IR DOCUMENTS
$apiServiceController = new ApiServiceController();
$apiServiceController->pushClaimFiles($ticket_id);
log_message('error', "pushClaimFiles IR FILE SUBMISSION function called with Ticket ID: {$ticket_id}, In Employee Rest Controller");
} catch (\Throwable $e) {
log_message('error', "Error in TPA Claim Files Push via CRM : ApiServiceController pushClaims function call for Ticket ID: {$ticket_id}. Error: " . $e->getMessage() . " Trace: " . $e->getTraceAsString());
}
}
return $insert_ids; return $insert_ids;
} }
@ -4530,8 +4539,8 @@ class EmployeeRestController extends AdminController
// print_r($post_data); die; // print_r($post_data); die;
$Query = $this->clientPolicyModel $Query = $this->clientPolicyModel
->select(" ->select("
client_policy.id as client_policy_id , client_policy.id as client_policy_id ,
client_policy.client_id as client_id, client_policy.client_id as client_id,
client_policy.policy_type_id as policy_type_id, client_policy.policy_type_id as policy_type_id,
@ -4544,14 +4553,14 @@ class EmployeeRestController extends AdminController
DATE_FORMAT(client_policy.policy_end_date, '%d-%m-%Y') AS policy_expiry_date, DATE_FORMAT(client_policy.policy_end_date, '%d-%m-%Y') AS policy_expiry_date,
CASE WHEN policy_type.allocg IN ('Non-EB', 'Marine') THEN 'Non-EB' ELSE 'EB' END as allocg CASE WHEN policy_type.allocg IN ('Non-EB', 'Marine') THEN 'Non-EB' ELSE 'EB' END as allocg
", false) ", false)
->join('policy_type', 'policy_type.id = client_policy.policy_type_id', 'left') ->join('policy_type', 'policy_type.id = client_policy.policy_type_id', 'left')
->where('md5(client_policy.client_id)', $post_data['client_id']) ->where('md5(client_policy.client_id)', $post_data['client_id'])
->where('client_policy.client_branch_id', $post_data['client_branch_id']) ->where('client_policy.client_branch_id', $post_data['client_branch_id'])
->where('client_policy.is_active', 1); ->where('client_policy.is_active', 1);
// ->where('client_policy.policy_status', $this->request->getGet('policy_status')) // ->where('client_policy.policy_status', $this->request->getGet('policy_status'))
if(is_array($post_data['policy_id'])){ if (is_array($post_data['policy_id'])) {
$Query->whereIn('client_policy.id', $post_data['policy_id']); $Query->whereIn('client_policy.id', $post_data['policy_id']);
}else{ } else {
$Query->where('client_policy.id', $post_data['policy_id']); $Query->where('client_policy.id', $post_data['policy_id']);
} }
$ClientPolicyData = $Query->first(); $ClientPolicyData = $Query->first();
@ -4581,9 +4590,9 @@ class EmployeeRestController extends AdminController
} }
return $this->respondCreated($responce); return $this->respondCreated($responce);
} catch (\Exception $e) { } catch (\Exception $e) {
// return $this->failServerError($e->getMessage()); // return $this->failServerError($e->getMessage());
log_message('error', 'Error in hrFileUpload: ' . $e->getMessage() . ' in file ' . $e->getFile() . ' on line ' . $e->getLine() . ' Trace: ' . $e->getTraceAsString());
return $this->respondCreated(['status' => false, 'message' => $e->getMessage(), 'data' => []]); return $this->respondCreated(['status' => false, 'message' => $e->getMessage(), 'data' => []]);
} }
} }

View File

@ -277,61 +277,61 @@ class MasterController extends AdminController
echo view('insurer_onboarding', $data); echo view('insurer_onboarding', $data);
echo view('layout/footer'); echo view('layout/footer');
} }
public function createInsurerGeneralInfo() public function createInsurerGeneralInfo()
{ {
$this->myLogger->logme('error','Insurer general info function called'); $this->myLogger->logme('error', 'Insurer general info function called');
$rules = [ $rules = [
'name' => [ 'name' => [
'label' => 'Insurer Name', 'label' => 'Insurer Name',
'rules' => ['required', 'regex_match[/^[a-zA-Z0-9\s\-_]+$/]'], 'rules' => ['required', 'regex_match[/^[a-zA-Z0-9\s\-_]+$/]'],
'errors' => [ 'errors' => [
'required' => 'Insurer Name is required.', 'required' => 'Insurer Name is required.',
'regex_match' => 'Insurer Name can only contain letters, numbers, spaces, hyphens, and underscores.', 'regex_match' => 'Insurer Name can only contain letters, numbers, spaces, hyphens, and underscores.',
] ]
], ],
'short_name' => [ 'short_name' => [
'label' => 'Insurer Short Name', 'label' => 'Insurer Short Name',
'rules' => ['required', 'regex_match[/^[a-zA-Z0-9\-_]+$/]'], 'rules' => ['required', 'regex_match[/^[a-zA-Z0-9\-_]+$/]'],
'errors' => [ 'errors' => [
'required' => 'Short Name is required.', 'required' => 'Short Name is required.',
'regex_match' => 'Short Name can only contain letters, numbers, hyphens, and underscores.', 'regex_match' => 'Short Name can only contain letters, numbers, hyphens, and underscores.',
] ]
], ],
'type' => [ 'type' => [
'label' => 'Insurer Type', 'label' => 'Insurer Type',
'rules' => 'permit_empty|in_list[pvt,psu]', 'rules' => 'permit_empty|in_list[pvt,psu]',
'errors' => [ 'errors' => [
'in_list' => 'Please select a valid Insurer Type (PVT or PSU).' 'in_list' => 'Please select a valid Insurer Type (PVT or PSU).'
] ]
], ],
'category' => [ 'category' => [
'label' => 'Insurer Category', 'label' => 'Insurer Category',
'rules' => 'permit_empty|in_list[life,general]', 'rules' => 'permit_empty|in_list[life,general]',
'errors' => [ 'errors' => [
'in_list' => 'Please select a valid Category (Life or General).' 'in_list' => 'Please select a valid Category (Life or General).'
] ]
], ],
'addition_add_day' => [ 'addition_add_day' => [
'rules' => 'permit_empty' // Checkboxes return null if unchecked 'rules' => 'permit_empty' // Checkboxes return null if unchecked
], ],
'deletion_add_day' => [ 'deletion_add_day' => [
'rules' => 'permit_empty' 'rules' => 'permit_empty'
], ],
'is_multi_event' => [ 'is_multi_event' => [
'rules' => 'permit_empty' 'rules' => 'permit_empty'
], ],
'insurer_logo' => [ 'insurer_logo' => [
'rules' => 'if_exist|is_image[insurer_logo]|max_size[insurer_logo,200]|ext_in[insurer_logo,jpg,jpeg,png]', 'rules' => 'if_exist|is_image[insurer_logo]|max_size[insurer_logo,200]|ext_in[insurer_logo,jpg,jpeg,png]',
'errors' => [ 'errors' => [
'is_image' => 'The uploaded file must be an image', 'is_image' => 'The uploaded file must be an image',
'max_size' => 'File size should not exceed 200 KB', 'max_size' => 'File size should not exceed 200 KB',
'ext_in' => 'Allowed file types: jpg, jpeg, png', 'ext_in' => 'Allowed file types: jpg, jpeg, png',
] ]
], ],
]; ];
// $rules = [ // $rules = [
// 'name' => [ // 'name' => [
// 'rules' => 'required', // 'rules' => 'required',
@ -3538,8 +3538,9 @@ class MasterController extends AdminController
{ {
$posModel = new PartnerPosModel(); $posModel = new PartnerPosModel();
$method = $this->request->getMethod(); $method = $this->request->getMethod();
if ($this->request->getMethod() === 'post') { if ($this->request->getMethod() === 'post') {
try {
$rules = [ $rules = [
'manager_id' => [ 'manager_id' => [
@ -3555,7 +3556,7 @@ class MasterController extends AdminController
'required' => 'Name is required', 'required' => 'Name is required',
'min_length' => 'Name must be at least 3 characters', 'min_length' => 'Name must be at least 3 characters',
'max_length' => 'Name cannot exceed 100 characters', 'max_length' => 'Name cannot exceed 100 characters',
'alpha_space'=> 'Name can contain only letters and spaces' 'alpha_space' => 'Name can contain only letters and spaces'
] ]
], ],
'pos_code' => [ 'pos_code' => [
@ -3589,27 +3590,27 @@ class MasterController extends AdminController
] ]
], ],
'state' => [ 'state' => [
'label' => 'State', 'label' => 'State',
'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]', 'rules' => 'required|regex_match[/^[a-zA-Z0-9\/\-\_\.\s]+$/]',
'errors' => [ 'errors' => [
'required' => 'State is required.', 'required' => 'State is required.',
'regex_match' => 'State name can only contain letters, spaces, and hyphens.' 'regex_match' => 'State name can only contain letters, spaces, and hyphens.'
] ]
], ],
'city' => [ 'city' => [
'rules' => 'required|regex_match[/^[a-zA-Z0-9\s\-]+$/]', 'rules' => 'required|regex_match[/^[a-zA-Z0-9\s\-]+$/]',
'errors' => [ 'errors' => [
'regex_match' => 'City can contain letters, numbers, spaces, and hyphens.' 'regex_match' => 'City can contain letters, numbers, spaces, and hyphens.'
] ]
], ],
'pincode' => [ 'pincode' => [
'rules' => 'required|numeric|exact_length[6]', 'rules' => 'required|numeric|exact_length[6]',
'errors' => [ 'errors' => [
'required' => 'Pincode is required.', 'required' => 'Pincode is required.',
'numeric' => 'Pincode must be digits only.', 'numeric' => 'Pincode must be digits only.',
'exact_length' => 'Pincode must be exactly 6 digits.' 'exact_length' => 'Pincode must be exactly 6 digits.'
] ]
], ],
'aadhar' => [ 'aadhar' => [
'rules' => 'required|numeric|exact_length[12]', 'rules' => 'required|numeric|exact_length[12]',
'errors' => [ 'errors' => [
@ -3632,25 +3633,22 @@ class MasterController extends AdminController
] ]
], ],
'aadhar_file_name' => [ 'aadhar_file_name' => [
'rules' => 'permit_empty|uploaded[aadhar_file_name]|max_size[aadhar_file_name,5120]|ext_in[aadhar_file_name,pdf,jpg,jpeg,png]', 'rules' => 'if_exist|max_size[aadhar_file_name,5120]|ext_in[aadhar_file_name,pdf,jpg,jpeg,png]',
'errors' => [ 'errors' => [
'uploaded' => 'Invalid Aadhaar file',
'max_size' => 'Aadhaar file size should not exceed 5MB', 'max_size' => 'Aadhaar file size should not exceed 5MB',
'ext_in' => 'Aadhaar must be PDF or image (jpg, jpeg, png)' 'ext_in' => 'Aadhaar must be PDF or image (jpg, jpeg, png)'
] ]
], ],
'pan_file_name' => [ 'pan_file_name' => [
'rules' => 'permit_empty|uploaded[pan_file_name]|max_size[pan_file_name,5120]|ext_in[pan_file_name,pdf,jpg,jpeg,png]', 'rules' => 'if_exist|max_size[pan_file_name,5120]|ext_in[pan_file_name,pdf,jpg,jpeg,png]',
'errors' => [ 'errors' => [
'uploaded' => 'Invalid PAN file',
'max_size' => 'PAN file size should not exceed 5MB', 'max_size' => 'PAN file size should not exceed 5MB',
'ext_in' => 'PAN must be PDF or image (jpg, jpeg, png)' 'ext_in' => 'PAN must be PDF or image (jpg, jpeg, png)'
] ]
], ],
'certificate_file_name' => [ 'certificate_file_name' => [
'rules' => 'permit_empty|uploaded[certificate_file_name]|max_size[certificate_file_name,5120]|ext_in[certificate_file_name,pdf,jpg,jpeg,png]', 'rules' => 'if_exist|max_size[certificate_file_name,5120]|ext_in[certificate_file_name,pdf,jpg,jpeg,png]',
'errors' => [ 'errors' => [
'uploaded' => 'Invalid Certificate file',
'max_size' => 'Certificate file size should not exceed 5MB', 'max_size' => 'Certificate file size should not exceed 5MB',
'ext_in' => 'Certificate must be PDF or image (jpg, jpeg, png)' 'ext_in' => 'Certificate must be PDF or image (jpg, jpeg, png)'
] ]
@ -3669,138 +3667,217 @@ class MasterController extends AdminController
$data = $this->request->getPost(); $data = $this->request->getPost();
$sanitized_post_data = sanitizeInputArrayAdvanced($data); $sanitized_post_data = sanitizeInputArrayAdvanced($data);
$id = $sanitized_post_data['pk'] ?? null; $id = $sanitized_post_data['pk'] ?? null;
unset($sanitized_post_data['pk']); unset($sanitized_post_data['pk']);
try { try {
// Certificate // Certificate
$certificate = $this->uploadPOSFile('certificate_file_name', 'pos_certificate_files'); $certificate = $this->uploadPOSFile('certificate_file_name', 'pos_certificate_files');
if ($certificate !== null) { $sanitized_post_data['certificate_file_name'] = $certificate; } else { unset($sanitized_post_data['certificate_file_name']); } if ($certificate !== null) {
$sanitized_post_data['certificate_file_name'] = $certificate;
} else {
unset($sanitized_post_data['certificate_file_name']);
}
// PAN file // PAN file
$panFile = $this->uploadPOSFile('pan_file_name', 'pos_certificate_files'); $panFile = $this->uploadPOSFile('pan_file_name', 'pos_certificate_files');
if ($panFile !== null) { $sanitized_post_data['pan_file_name'] = $panFile; } else { unset($sanitized_post_data['pan_file_name']);} if ($panFile !== null) {
$sanitized_post_data['pan_file_name'] = $panFile;
} else {
unset($sanitized_post_data['pan_file_name']);
}
// Aadhaar file // Aadhaar file
$aadharFile = $this->uploadPOSFile('aadhar_file_name', 'pos_certificate_files'); $aadharFile = $this->uploadPOSFile('aadhar_file_name', 'pos_certificate_files');
if ($aadharFile !== null) { $sanitized_post_data['aadhar_file_name'] = $aadharFile; } else { unset($sanitized_post_data['aadhar_file_name']);} if ($aadharFile !== null) {
$sanitized_post_data['aadhar_file_name'] = $aadharFile;
} catch (\RuntimeException $e) { } else {
return $this->respond([ 'status' => false, 'code' => 400, 'message' => $e->getMessage(), 'data' => $sanitized_post_data ], 400); unset($sanitized_post_data['aadhar_file_name']);
}
} catch (\Exception $e) {
log_message('error', 'File upload error: ' . $e->getMessage() . ' | POST data: ' . json_encode($sanitized_post_data) . $e->getTraceAsString());
return $this->respond(['status' => false, 'code' => 400, 'message' => $e->getMessage(), 'data' => $sanitized_post_data], 400);
} }
foreach ($sanitized_post_data as $k => $v) { foreach ($sanitized_post_data as $k => $v) {
if ($v === '' || $v === null) { if ($v === '' || $v === null) {
unset($sanitized_post_data[$k]); unset($sanitized_post_data[$k]);
}
} }
}
// INSERT / UPDATE // INSERT / UPDATE
if (empty($id)) { try {
$status = $posModel->insert($sanitized_post_data); if (empty($id)) {
} else { $status = $posModel->insert($sanitized_post_data);
$status = $posModel->update($id, $sanitized_post_data); } else {
} $status = $posModel->update($id, $sanitized_post_data);
}
if ($status) { if ($status) {
return $this->respond([ 'status' => true, 'code' => 200, 'message' => 'POS updated successfully', 'data' => $sanitized_post_data ], 200); return $this->respond(['status' => true, 'code' => 200, 'message' => 'POS updated successfully', 'data' => $sanitized_post_data], 200);
} }
return $this->respond([ 'status' => false, 'code' => 400, 'message' => 'Failed to update', 'data' => $sanitized_post_data ], 400); $modelErrors = method_exists($posModel, 'errors') ? $posModel->errors() : [];
} return $this->respond([
elseif ($method === 'get') { 'status' => false,
'code' => 400,
'message' => 'Failed to update',
'errors' => $modelErrors,
'data' => $sanitized_post_data
], 400);
} catch (\Throwable $e) {
log_message('error', 'partnerPOS DB error: ' . $e->getMessage() . ' | payload: ' . json_encode($sanitized_post_data) . ' | trace: ' . $e->getTraceAsString());
$id = $this->request->getGet('pk') ?? null; $message = 'Something went wrong while saving POS details.';
$statusCode = 500;
$db = db_connect(); if (stripos($e->getMessage(), 'Duplicate entry') !== false) {
$statusCode = 400;
$builder = $db->table('partner_staff'); if (stripos($e->getMessage(), 'email') !== false) {
$message = 'Email already exists.';
$data['manager_list'] = $builder->select('partner_staff.id, partner_staff.name') } elseif (stripos($e->getMessage(), 'mobile') !== false) {
->where('partner_staff.is_active', 1) $message = 'Mobile number already exists.';
->where('partner_staff.role_id', 1) } else {
->get() $message = 'Duplicate data found. Please check email/mobile.';
->getResultArray();
if (!empty($id)) {
$data['pos_list'] = $posModel
->select('partner_pos.*, partner_staff.name AS manager_name')
->join('partner_staff', 'partner_staff.id = partner_pos.manager_id', 'left')
->where('partner_pos.id', $id)
->orderBy('partner_pos.id', 'DESC')
->findAll();
if (!empty($data)) {
return $this->respond(['status' => true, 'code' => 200, 'data' => $data], 200);
} else {
return $this->respond(['status' => false, 'code' => 400, 'message' => 'No data found'], 200);
}
}
$data['pos_list'] = $posModel
->select('partner_pos.*, ps.name AS manager_name')
->join('partner_staff ps', 'ps.id = partner_pos.manager_id', 'left')
->orderBy('partner_pos.id', 'DESC')
->findAll();
return $this->loadLayout('pos_list', ['data' => $data,'tab_name' => 'POS details','page_name' => 'POS details']);
} elseif ($method === 'delete') {
// $input = $this->request->getRawInput();
$id = $this->request->getGet('pk'); // ✅ THIS
$id = $id ?? null;
if (empty($id)) {
return $this->respond([
'status' => false,
'code' => 404,
'message' => 'No ID provided for deletion'
], 200);
}
$update_status = $posModel->where('id', $id)->set(['is_active' => 0])->update();
if ($update_status) {
return $this->respond([
'status' => true,
'code' => 200,
'message' => 'Data removed successfully',
'pk' => $id
], 200);
} else {
return $this->respond([
'status' => false,
'code' => 400,
'message' => 'Failed to remove data',
'pk' => $id
], 200);
}
} }
} }
private function uploadPOSFile(string $fieldName, string $uploadDir) return $this->respond([
{ 'status' => false,
$file = $this->request->getFile($fieldName); 'code' => $statusCode,
'message' => $message
], $statusCode);
}
} catch (\Throwable $e) {
log_message(
'error',
'partnerPOS fatal error: ' . $e->getMessage() .
' | file: ' . $e->getFile() .
' | line: ' . $e->getLine() .
' | trace: ' . $e->getTraceAsString()
);
return $this->respond([
'status' => false,
'code' => 500,
'message' => 'Internal server error while processing POS request.'
], 500);
}
} elseif ($method === 'get') {
if (!$file || !$file->isValid()) { return null; } $id = $this->request->getGet('pk') ?? null;
$allowedMime = [ 'image/jpg', 'image/jpeg', 'image/png', 'image/webp', 'application/pdf']; $db = db_connect();
if (!in_array($file->getMimeType(), $allowedMime)) { throw new \RuntimeException('Invalid file format'); } $builder = $db->table('partner_staff');
$path = ROOTPATH . 'public/uploads/' . $uploadDir . '/'; $data['manager_list'] = $builder->select('partner_staff.id, partner_staff.name')
->where('partner_staff.is_active', 1)
->where('partner_staff.role_id', 1)
->get()
->getResultArray();
if (!is_dir($path)) { mkdir($path, 0755, true); }
$newName = $file->getRandomName(); if (!empty($id)) {
$file->move($path, $newName);
return $newName; $data['pos_list'] = $posModel
->select('partner_pos.*, partner_staff.name AS manager_name')
->join('partner_staff', 'partner_staff.id = partner_pos.manager_id', 'left')
->where('partner_pos.id', $id)
->orderBy('partner_pos.id', 'DESC')
->findAll();
if (!empty($data)) {
return $this->respond(['status' => true, 'code' => 200, 'data' => $data], 200);
} else {
return $this->respond(['status' => false, 'code' => 400, 'message' => 'No data found'], 200);
} }
}
$data['pos_list'] = $posModel
->select('partner_pos.*, ps.name AS manager_name')
->join('partner_staff ps', 'ps.id = partner_pos.manager_id', 'left')
->orderBy('partner_pos.id', 'DESC')
->findAll();
} return $this->loadLayout('pos_list', ['data' => $data, 'tab_name' => 'POS details', 'page_name' => 'POS details']);
} elseif ($method === 'delete') {
// $input = $this->request->getRawInput();
$id = $this->request->getGet('pk'); // ✅ THIS
$id = $id ?? null;
if (empty($id)) {
return $this->respond([
'status' => false,
'code' => 404,
'message' => 'No ID provided for deletion'
], 200);
}
$update_status = $posModel->where('id', $id)->set(['is_active' => 0])->update();
if ($update_status) {
return $this->respond([
'status' => true,
'code' => 200,
'message' => 'Data removed successfully',
'pk' => $id
], 200);
} else {
return $this->respond([
'status' => false,
'code' => 400,
'message' => 'Failed to remove data',
'pk' => $id
], 200);
}
}
}
private function uploadPOSFile(string $fieldName, string $uploadDir)
{
$file = $this->request->getFile($fieldName);
if (!$file) {
return null;
}
// No file selected for this optional input.
if ($file->getError() === UPLOAD_ERR_NO_FILE) {
return null;
}
if (!$file->isValid()) {
throw new \RuntimeException('File upload failed for ' . $fieldName);
}
$allowedMime = [
'image/jpg',
'image/jpeg',
'image/pjpeg',
'image/png',
'image/x-png',
'image/webp',
'application/pdf'
];
$mimeType = (string) $file->getMimeType();
if (!in_array($mimeType, $allowedMime, true)) {
throw new \RuntimeException('Invalid file format for ' . $fieldName);
}
$path = ROOTPATH . 'public/uploads/' . $uploadDir . '/';
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
$newName = $file->getRandomName();
$file->move($path, $newName);
return $newName;
}
}

View File

@ -539,6 +539,7 @@ class TicketController extends BaseController
'tm.emp_personal_mail', 'tm.emp_personal_mail',
'tm.mode_of_intimation', 'tm.mode_of_intimation',
'tm.claim_type', 'tm.claim_type',
'tm.tpa_claim_type',
'tm.hospital_name', 'tm.hospital_name',
'tm.doa', 'tm.doa',
'tm.dod', 'tm.dod',
@ -673,6 +674,7 @@ class TicketController extends BaseController
'tm.emp_personal_mail', 'tm.emp_personal_mail',
'tm.mode_of_intimation', 'tm.mode_of_intimation',
'tm.claim_type', 'tm.claim_type',
'tm.tpa_claim_type',
'tm.hospital_name', 'tm.hospital_name',
'tm.doa', 'tm.doa',
'tm.dod', 'tm.dod',
@ -2319,8 +2321,8 @@ class TicketController extends BaseController
->findAll(); ->findAll();
foreach ($dataToSend['messages'] as &$message) { foreach ($dataToSend['messages'] as &$message) {
$mail_content_converted = $this->convertHtmlToText($message['mail_content']); // $mail_content_converted = $this->convertHtmlToText($message['mail_content']);
$message['mail_content'] = $mail_content_converted; // $message['mail_content'] = $mail_content_converted;
$claimFiles = new ClaimFilesModel(); $claimFiles = new ClaimFilesModel();
$message["files_data"] = $claimFiles->where('is_active', 1) $message["files_data"] = $claimFiles->where('is_active', 1)
@ -2436,7 +2438,7 @@ class TicketController extends BaseController
//---- Email Trigger Part---------------------------------------------------------------------------------------------- //---- Email Trigger Part----------------------------------------------------------------------------------------------
public function constructMailContent($ticket_id) public function constructMailContent($ticket_id, $status_id = null)
{ {
$this->myLogger->logme('error', "Constructing mail content for Ticket ID: $ticket_id"); $this->myLogger->logme('error', "Constructing mail content for Ticket ID: $ticket_id");
@ -2452,9 +2454,14 @@ class TicketController extends BaseController
$this->myLogger->logme('error', "Fetched ticket data: " . json_encode($ticket_data)); $this->myLogger->logme('error', "Fetched ticket data: " . json_encode($ticket_data));
if (!empty($status_id)) {
$ticket_data['claim_status_id'] = (int) $status_id;
}
// Fetch Email Template Data // Fetch Email Template Data
$template_data = $this->ticketMasterModel->getTemplateDataByTicketID($ticket_id); $template_data = !empty($status_id)
// print_r($template_data); die; ? ($this->ticketMasterModel->getTemplateDataByStatusID((int) $status_id, (int) ($ticket_data['ticket_type_id'] ?? 0))[0] ?? null)
: $this->ticketMasterModel->getTemplateDataByTicketID($ticket_id);
if (!$template_data) { if (!$template_data) {
$this->myLogger->logme('error', "No email template found for Claim Status ID: " . $ticket_data['claim_status_id']); $this->myLogger->logme('error', "No email template found for Claim Status ID: " . $ticket_data['claim_status_id']);
@ -2626,7 +2633,7 @@ class TicketController extends BaseController
'mail' => [$mail_data['emp_mail'], $ticket_data['emp_personal_mail'] ?? ""], 'mail' => [$mail_data['emp_mail'], $ticket_data['emp_personal_mail'] ?? ""],
'subject' => $mail_data['mail_subject'], 'subject' => $mail_data['mail_subject'],
'message' => $mail_data['mail_content'], 'message' => $mail_data['mail_content'],
'common' => [], 'common' => ['module' => "claim", 'pk' => $mail_data['ticket_id']],
'cc' => $acm_mails['common_mails'], 'cc' => $acm_mails['common_mails'],
'attachments' => [] 'attachments' => []
]; ];
@ -2824,7 +2831,7 @@ class TicketController extends BaseController
'mail' => $template_data['emp_mail'], 'mail' => $template_data['emp_mail'],
'subject' => $template_data['subject'], 'subject' => $template_data['subject'],
'message' => $template_data['mail_content'], 'message' => $template_data['mail_content'],
'common' => [], 'common' => ['module' => "claim", 'pk' => $ticket_id],
'cc' => $acm_mails['common_mails'], 'cc' => $acm_mails['common_mails'],
'attachments' => [] 'attachments' => []
]; ];
@ -2985,7 +2992,7 @@ class TicketController extends BaseController
'mail' => $head_mail['email'], 'mail' => $head_mail['email'],
'subject' => $subject, 'subject' => $subject,
'message' => $message, 'message' => $message,
'common' => [], 'common' => ['module' => "claim", 'pk' => $ticket_data['id']],
]; ];
$this->sendTrigger($emailData); $this->sendTrigger($emailData);
@ -3720,7 +3727,7 @@ class TicketController extends BaseController
return $input; return $input;
} }
function convertTermsToDisplay(array $data) public function convertTermsToDisplay(array $data)
{ {
$result = []; $result = [];
@ -3900,6 +3907,106 @@ class TicketController extends BaseController
return $result; return $result;
} }
public function getClaimTemplateData()
{
try {
$ticket_id = $this->request->getPost('ticket_id') ?? $this->request->getGet('ticket_id');
$status_id = $this->request->getPost('status_id') ?? $this->request->getGet('status_id');
if (empty($ticket_id) || empty($status_id)) {
return $this->respond(['status' => false, 'message' => 'Ticket ID and Status ID are required'], 400);
}
$mail_content = $this->constructMailContent($ticket_id, $status_id);
if ($mail_content) {
return $this->respond(['status' => true, 'data' => $mail_content], 200);
}
return $this->respond(['status' => false, 'message' => 'Failed to construct mail content'], 200);
} catch (\Exception $e) {
$this->myLogger->logme('error', 'Error in getClaimTemplateData: ' . $e->getMessage() . ' in file ' . $e->getFile() . ' on line ' . $e->getLine() . $e->getTraceAsString());
return $this->respond(['status' => false, 'message' => 'An error occurred while fetching template data'], 500);
}
}
public function uploadApprovedLetterFromReply()
{
try {
$ticket_id = $this->request->getPost('ticket_id');
$status_id = $this->request->getPost('status_id');
$approvedLetterUrl = trim((string) $this->request->getPost('approved_letter'));
$approvedLetterFile = $this->request->getFile('approved_letter_file');
if (empty($ticket_id) || empty($status_id)) {
return $this->respond(['status' => false, 'message' => 'Ticket ID and Status ID are required'], 400);
}
if ((int) $status_id !== 9) {
return $this->respond(['status' => false, 'message' => 'Approved letter upload is allowed only for APPROVED status'], 400);
}
$ticket_data = $this->ticketMasterModel->getTicketDataByTicketID($ticket_id);
if (empty($ticket_data)) {
return $this->respond(['status' => false, 'message' => 'Ticket not found'], 404);
}
if (!empty($ticket_data['approved_letter'])) {
return $this->respond([
'status' => false,
'message' => 'Approved letter already available',
'data' => ['approved_letter' => $ticket_data['approved_letter']],
], 200);
}
$hasApprovedLetterFile = $approvedLetterFile !== null
&& $approvedLetterFile->isValid()
&& $approvedLetterFile->getError() !== UPLOAD_ERR_NO_FILE;
if ($approvedLetterUrl !== '' && $hasApprovedLetterFile) {
return $this->respond([
'status' => false,
'message' => 'Provide either Approved Letter URL or Approved Letter PDF file, not both.',
], 400);
}
if ($approvedLetterUrl !== '' && !$this->isClaimUploadUrl($approvedLetterUrl)) {
return $this->respond(['status' => false, 'message' => 'Approved Letter URL format is invalid.'], 400);
}
if ($approvedLetterUrl === '' && !$hasApprovedLetterFile) {
return $this->respond(['status' => false, 'message' => 'Provide Approved Letter URL or Approved Letter PDF file.'], 400);
}
$approvedLetterValue = $approvedLetterUrl;
if ($hasApprovedLetterFile) {
$uploadResult = $this->uploadApprovedLetterPdf($approvedLetterFile, 'Approved Letter');
if (!($uploadResult['status'] ?? false)) {
return $this->respond(['status' => false, 'message' => $uploadResult['message'] ?? 'Invalid Approved Letter file.'], 400);
}
$approvedLetterValue = $this->createApprovedLetterFileUrl(
(int) $ticket_id,
(int) ($ticket_data['ticket_type_id'] ?? 1),
$uploadResult['data'],
'APPROVED_LETTER_PDF'
);
}
$this->ticketMasterModel
->where('id', (int) $ticket_id)
->set(['approved_letter' => $approvedLetterValue])
->update();
return $this->respond([
'status' => true,
'message' => 'Approved letter uploaded successfully',
'data' => ['approved_letter' => $approvedLetterValue],
], 200);
} catch (\Exception $e) {
$this->myLogger->logme('error', 'Error in uploadApprovedLetterFromReply: ' . $e->getMessage() . ' in file ' . $e->getFile() . ' on line ' . $e->getLine() . $e->getTraceAsString());
return $this->respond(['status' => false, 'message' => 'An error occurred while uploading approved letter'], 500);
}
}
// -------- CLAIM DUMP UPLOAD ---------------------------------------------------------------------------------------------- // -------- CLAIM DUMP UPLOAD ----------------------------------------------------------------------------------------------

View File

@ -143,7 +143,7 @@ class AclFilter implements FilterInterface
$response = service('response'); $response = service('response');
$response->setStatusCode(403); $response->setStatusCode(403);
$response->setBody(view('errors/404', [ $response->setBody(view('errors/403', [
'message' => '403 Access denied - You do not have permission to access this resource' 'message' => '403 Access denied - You do not have permission to access this resource'
])); ]));

View File

@ -133,17 +133,20 @@ class TicketMasterModel extends Model
return $data; return $data;
} }
public function getTemplateDataByStatusID($claim_status_id) public function getTemplateDataByStatusID($claim_status_id, $ticket_type_id = null)
{ {
$builder = $this->db->table('ticket_claim_status tcs')
$template_data = $this->table('ticket_claim_status')
->select('ticket_mail_template.*') ->select('ticket_mail_template.*')
->join('ticket_mail_template', 'ticket_mail_template.trigger_type = ticket_claim_status.trigger_type') ->join('ticket_mail_template', 'ticket_mail_template.trigger_type = tcs.trigger_type')
->where('ticket_mail_template.is_active', 1) ->where('ticket_mail_template.is_active', 1)
->where('ticket_claim_status.is_active', 1) ->where('tcs.id', $claim_status_id)
->where('ticket_claim_status.id', $claim_status_id) ->where('tcs.is_active', 1);
->get()
->getResultArray(); if ($ticket_type_id !== null && $ticket_type_id !== '') {
$builder->where('ticket_mail_template.ticket_type', $ticket_type_id);
}
$template_data = $builder->get()->getResultArray();
return $template_data; return $template_data;
} }

View File

@ -1,4 +1,5 @@
<?php <?php
helper('datatable_view');
$batch_header_labels = [ $batch_header_labels = [
'S.No', 'Batch Code', 'File Name', 'Client', 'Client Branch', 'Client Policy', 'S.No', 'Batch Code', 'File Name', 'Client', 'Client Branch', 'Client Policy',
'Event Type', 'Insurer/ TPA', 'Action', 'Count', '(₹)Amount', 'User/Time', 'Status', 'Action', 'Event Type', 'Insurer/ TPA', 'Action', 'Count', '(₹)Amount', 'User/Time', 'Status', 'Action',

View File

@ -242,6 +242,7 @@
</div> </div>
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("scroll-horizontal-datatable"); const table = document.getElementById("scroll-horizontal-datatable");
@ -329,6 +330,7 @@
} }
}); });
}); });
*/
</script> </script>

View File

@ -163,7 +163,6 @@
</div> </div>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
let ticket_id = $('#ticket_master_id').val(); let ticket_id = $('#ticket_master_id').val();
$('#ticket_id_url').val(ticket_id); $('#ticket_id_url').val(ticket_id);
@ -203,6 +202,10 @@
return; return;
} }
if (typeof window.validateGlobalUploadPayload === 'function' && !window.validateGlobalUploadPayload(this)) {
return;
}
form_action = '<?php echo base_url() . 'ticket/upload_url' ?>'; form_action = '<?php echo base_url() . 'ticket/upload_url' ?>';
$('.loader').fadeIn(); $('.loader').fadeIn();

View File

@ -106,6 +106,58 @@ input:checked + .slider:before {
.slider.round:before { .slider.round:before {
border-radius: 50%; border-radius: 50%;
} }
.hr-processed-options {
display: inline-flex;
align-items: center;
justify-content: flex-start;
gap: 1.25rem;
flex-wrap: nowrap;
white-space: nowrap;
width: auto;
max-width: 100%;
}
.hr-processed-option {
display: inline-flex;
align-items: center;
justify-content: flex-start;
flex: 0 0 auto;
width: auto;
margin: 0;
}
.hr-radio-input {
appearance: auto;
-webkit-appearance: radio;
width: 14px;
height: 14px;
margin-top: 0;
margin-right: 0.35rem;
margin-left: 0;
position: static;
float: none;
vertical-align: middle;
}
.hr-radio-label {
display: inline-block;
width: auto;
margin: 0;
white-space: nowrap;
line-height: 1.2;
}
#hr_file_processed_by_error_container {
display: block;
width: 100%;
margin-top: 0.25rem;
clear: both;
}
#hr_file_processed_by_error_container .parsley-errors-list {
margin-bottom: 0;
}
</style> </style>
<div class="tab-pane fade active show" id="general-q-tab"> <div class="tab-pane fade active show" id="general-q-tab">
@ -170,8 +222,10 @@ input:checked + .slider:before {
id="client_logo" name="client_logo" id="client_logo" name="client_logo"
accept="image/jpeg, image/jpg, image/png" accept="image/jpeg, image/jpg, image/png"
onchange="PreviewImage0(event);" onchange="PreviewImage0(event);"
data-parsley-max-file-size="200" data-parsley-client-max-file-size="200"
data-parsley-file-extension="jpg,jpeg,png" data-parsley-client-file-extension="jpg,jpeg,png"
data-parsley-client-max-file-size-message="Maximum file size allowed is 200KB."
data-parsley-client-file-extension-message="Only JPG, JPEG, PNG files are allowed."
data-parsley-errors-container="#client_logo_error_container" data-parsley-errors-container="#client_logo_error_container"
/> />
</div> </div>
@ -198,25 +252,29 @@ input:checked + .slider:before {
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="client_name">Client Name<span <label for="client_name">Client Name<span
class="text-danger">*</span></label> class="text-danger">*</span></label>
<input type="text" class="form-control" id="client_name" data-old-name="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>" <input type="text" class="form-control" id="client_name"
placeholder="Enter Client Name" value="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>" name="client_name" data-old-name="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>"
required maxlength="255" data-parsley-maxlength="255"> placeholder="Enter Client Name"
value="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>" name="client_name"
required maxlength="45" data-parsley-minlength="2" data-parsley-maxlength="45"
data-parsley-pattern="^[a-zA-Z0-9\s_-]+$"
data-parsley-pattern-message="Only letters, numbers, spaces, underscore (_) and hyphen (-) are allowed.">
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="short_name">Client Short Name<span <label for="short_name">Client Short Name<span
class="text-danger">*</span></label> class="text-danger">*</span></label>
<input type="text" class="form-control" id="short_name" <input type="text" class="form-control" id="short_name" data-parsley-minlength="2"
maxlength="100" data-parsley-maxlength="100" data-parsley-maxlength="15" data-parsley-pattern="/^[a-zA-Z0-9_\- ]+$/"
data-old-short="<?= isset($client['short_name']) ? $client['short_name'] : '' ?>" data-old-short="<?= isset($client['short_name']) ? $client['short_name'] : '' ?>" placeholder="Enter Short Name"
placeholder="Enter Short Name" value="<?= isset($client['short_name']) ? $client['short_name'] : '' ?>" name="short_name" onkeyup="validateInput(this, 'clients', 'short_name', 'clientBtnSubmit')" required> value="<?= isset($client['short_name']) ? $client['short_name'] : '' ?>" name="short_name" onkeyup="validateInput(this, 'clients', 'short_name', 'clientBtnSubmit')" required>
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="pan">PAN<span class="text-danger"></span></label> <label for="pan">PAN<span class="text-danger"></span></label>
<input type="text" class="form-control" id="pan" placeholder="Enter PAN Number" data-parsley-error-message="Invalid PAN Number. Example: ABCDE1234F" value="<?= isset($client['pan']) ? $client['pan'] : '' ?>" name="pan" <input type="text" class="form-control" id="pan" placeholder="Enter PAN Number" data-parsley-error-message="Invalid PAN Number. Example: ABCDE1234F" value="<?= isset($client['pan']) ? $client['pan'] : '' ?>" name="pan"
maxlength="10" data-parsley-maxlength="10" data-parsley-trigger="change" data-parsley-pattern="^[A-Z]{5}[0-9]{4}[A-Z]$"> maxlength="10" data-parsley-maxlength="10" data-parsley-trigger="keyup" data-parsley-pattern="^[A-Z]{5}[0-9]{4}[A-Z]$">
</div> </div>
<!-- <div class="form-group col-md-4"> <!-- <div class="form-group col-md-4">
<label for="gst">GST<span class="text-danger">*</span></label> <label for="gst">GST<span class="text-danger">*</span></label>
@ -236,26 +294,33 @@ input:checked + .slider:before {
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>HR File Processed By <span class="text-danger">*</span></label> <label>HR File Processed By <span class="text-danger">*</span></label>
<div class="d-flex align-items-center"> <div class="hr-processed-options">
<div class="form-check form-check-inline mb-0" style="margin-right: -356px;"> <div class="hr-processed-option">
<input class="form-check-input" <input class="hr-radio-input"
type="radio" type="radio"
name="hr_file_processed_by" name="hr_file_processed_by"
id="hr_processed" id="hr_processed"
value="1" required <?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 1) ? 'checked' : '' ?>> value="1"
<label class="form-check-label" for="hr_processed">HR</label> required
data-parsley-trigger="change"
data-parsley-errors-container="#hr_file_processed_by_error_container"
<?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 1) ? 'checked' : '' ?>>
<label class="hr-radio-label" for="hr_processed">HR</label>
</div> </div>
<div class="form-check form-check-inline mb-0"> <div class="hr-processed-option">
<input class="form-check-input" <input class="hr-radio-input"
type="radio" type="radio"
name="hr_file_processed_by" name="hr_file_processed_by"
id="account_manager_processed" id="account_manager_processed"
value="2" value="2"
<?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 2) ? 'checked' : '' ?>> data-parsley-trigger="change"
<label class="form-check-label" for="account_manager_processed">Account Manager</label> data-parsley-errors-container="#hr_file_processed_by_error_container"
<?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 2) ? 'checked' : '' ?>>
<label class="hr-radio-label" for="account_manager_processed">Account Manager</label>
</div> </div>
</div> </div>
<div id="hr_file_processed_by_error_container"></div>
</div> </div>
@ -342,6 +407,31 @@ input:checked + .slider:before {
var form_action = ''; var form_action = '';
$(document).ready(function() { $(document).ready(function() {
if (window.Parsley) {
Parsley.addValidator('clientMaxFileSize', {
requirementType: 'integer',
validateString: function(_value, maxSizeKb, parsleyInstance) {
const files = parsleyInstance.element.files;
if (!files || !files.length) return true;
return (files[0].size / 1024) <= maxSizeKb;
}
});
Parsley.addValidator('clientFileExtension', {
requirementType: 'string',
validateString: function(_value, allowedExtensions, parsleyInstance) {
const files = parsleyInstance.element.files;
if (!files || !files.length) return true;
const allowed = allowedExtensions.split(',').map(function(ext) {
return ext.trim().toLowerCase();
});
const fileName = files[0].name || '';
const extension = fileName.split('.').pop().toLowerCase();
return allowed.indexOf(extension) !== -1;
}
});
}
$('#client_logo').change(function() { $('#client_logo').change(function() {
validateFile(this); validateFile(this);
return; return;
@ -365,6 +455,9 @@ input:checked + .slider:before {
}); });
$(document).ready(function () { $(document).ready(function () {
$('#general_form').parsley({
trigger: 'input'
});
$("#general_form").submit(function(event) { $("#general_form").submit(function(event) {
@ -574,7 +667,7 @@ input:checked + .slider:before {
// For example, you can display the image // For example, you can display the image
const reader = new FileReader(); const reader = new FileReader();
reader.onload = function(e) { reader.onload = function(e) {
$("#uploadPreview").attr("src", e.target.result); $("#uploadPreview0").attr("src", e.target.result);
}; };
reader.readAsDataURL(file); reader.readAsDataURL(file);
} }
@ -585,7 +678,9 @@ input:checked + .slider:before {
// Helper function to clear the preview and the file input // Helper function to clear the preview and the file input
function resetImageInput(input) { function resetImageInput(input) {
input.value = ""; // This clears the file so it won't be submitted input.value = ""; // This clears the file so it won't be submitted
$("#uploadPreview").attr("src", "<?= base_url()?>/public/assets/images/avatar_2x.png"); $("#uploadPreview0").attr("src", "<?= base_url()?>/public/assets/images/avatar_2x.png");
$("#fileNameText0").text("( Upload Your Logo )");
$("#client_logo_error_container").empty();
} }
</script> </script>

View File

@ -171,12 +171,16 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_name">Branch Name<span class="text-danger">*</span></label> <label for="branch_name">Branch Name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" <input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name"
name="branch_name" required> name="branch_name" required data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code<span class="text-danger">*</span></label> <label for="branch_code">Branch Code<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" <input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code"
name="branch_code" onchange="setDefaultUnitValue(this)" required> name="branch_code" onchange="setDefaultUnitValue(this)" required
data-parsley-pattern="^[a-zA-Z0-9_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
@ -204,23 +208,29 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="district">District<span class="text-danger">*</span></label> <label for="district">District<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" placeholder="Enter District" <input type="text" class="form-control" id="district" placeholder="Enter District"
name="district" required> name="district" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="city">City<span class="text-danger">*</span></label> <label for="city">City<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" placeholder="Enter City" <input type="text" class="form-control" id="branch_city" placeholder="Enter City"
name="city" required> name="city" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-3"> <div class="form-group col-md-3">
<label for="gst">Pincode<span class="text-danger">*</span></label> <label for="gst">Pincode<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required> <input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode"
maxlength="6" required data-parsley-pattern="^[0-9]{6}$"
data-parsley-pattern-message="Pincode must be exactly 6 digits.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="gst">GST<span class="text-danger">*</span></label> <label for="gst">GST<span class="text-danger">*</span></label>
<input type="text" name="gst" class="form-control" id="gst" placeholder="Enter GST Number" data-parsley-error-message="Invalid GST Number. Example: 12ABCDE1234F5Z6" data-parsley-trigger="change" data-parsley-pattern="^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1}$" required> <input type="text" name="gst" class="form-control" id="gst" placeholder="Enter GST Number" data-parsley-error-message="Invalid GST Number format." data-parsley-trigger="change" data-parsley-pattern="^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}Z[A-Z\d]{1}$" required>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="state">Units<span class="text-danger"></span></label> <label for="state">Units<span class="text-danger"></span></label>
@ -252,13 +262,17 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="first_name">Name<span class="text-danger">*</span></label> <label for="first_name">Name<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" <input value="" type="text" class="form-control" placeholder="Enter Contact Name"
name="name[]" id="name" required> name="name[]" id="name" required
data-parsley-pattern="^[A-Za-z\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="designation">Designation<span class="text-danger">*</span></label> <label for="designation">Designation<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Designation Name" <input value="" type="text" class="form-control" placeholder="Enter Designation Name"
name="designation[]" id="designation" required name="designation[]" id="designation" required
pattern="[A-Za-z0-9\-_/ ]+" pattern="[A-Za-z0-9\-_/ ]+"
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces."
oninput="this.value = this.value.replace(/[^A-Za-z0-9\-_\/ ]/g, '')" oninput="this.value = this.value.replace(/[^A-Za-z0-9\-_\/ ]/g, '')"
title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed"> title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed">
</div> </div>
@ -267,7 +281,10 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="last_name">Email<span class="text-danger">*</span></label> <label for="last_name">Email<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Email" <input value="" type="text" class="form-control" placeholder="Enter Contact Email"
name="email[]" id="email" data-parsley-trigger="change" data-parsley-type="email" onchange="validateDuplicateByClientBranch(this, 'email','branchBtnSubmit')" required> name="email[]" id="email" data-parsley-trigger="change"
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)."
onchange="validateDuplicateByClientBranch(this, 'email','branchBtnSubmit')" required>
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="mobile">Mobile<span class="text-danger">*</span></label> <label for="mobile">Mobile<span class="text-danger">*</span></label>
@ -275,8 +292,9 @@ input:checked + .slider-branch-contact:before {
name="mobile[]" id="mobile" name="mobile[]" id="mobile"
onchange="validateDuplicateByClientBranch(this, 'mobile','branchBtnSubmit')" onchange="validateDuplicateByClientBranch(this, 'mobile','branchBtnSubmit')"
onkeypress="return onlyNumbers(event)" maxlength="10" minlength="10" onkeypress="return onlyNumbers(event)" maxlength="10" minlength="10"
data-parsley-type-message="Please enter a valid 10-digit mobile number." data-parsley-pattern="^[0-9]{10}$"
data-parsley-required-message="Please enter a valid 10-digit mobile number." data-parsley-pattern-message="Mobile number must be exactly 10 digits."
data-parsley-required-message="Mobile number must be exactly 10 digits."
required> required>
</div> </div>
</div> </div>
@ -752,12 +770,16 @@ function appendContactHtml(contact = false, reset = false) {
<input type="hidden" name="branch_table_pk[]" id="${uniqueId}_branch_table_pk" value="${contact !== undefined && contact !== false ? contact.id : ''}"> <input type="hidden" name="branch_table_pk[]" id="${uniqueId}_branch_table_pk" value="${contact !== undefined && contact !== false ? contact.id : ''}">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="${uniqueId}_first_name">Name<span class="text-danger">*</span></label> <label for="${uniqueId}_first_name">Name<span class="text-danger">*</span></label>
<input value="${contact !== undefined && contact !== false ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="${uniqueId}_name" required> <input value="${contact !== undefined && contact !== false ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="${uniqueId}_name" required
data-parsley-pattern="^[A-Za-z\\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="${uniqueId}_designation">Designation<span class="text-danger">*</span></label> <label for="${uniqueId}_designation">Designation<span class="text-danger">*</span></label>
<input value="${contact !== undefined && contact !== false ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="${uniqueId}_designation" required <input value="${contact !== undefined && contact !== false ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="${uniqueId}_designation" required
pattern="[A-Za-z0-9\-_/ ]+" pattern="[A-Za-z0-9\-_/ ]+"
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces."
oninput="this.value = this.value.replace(/[^A-Za-z0-9\-_\/ ]/g, '')" oninput="this.value = this.value.replace(/[^A-Za-z0-9\-_\/ ]/g, '')"
title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed"> title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed">
</div> </div>
@ -765,11 +787,11 @@ function appendContactHtml(contact = false, reset = false) {
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="${uniqueId}_last_name">Email<span class="text-danger">*</span></label> <label for="${uniqueId}_last_name">Email<span class="text-danger">*</span></label>
<input value="${contact !== undefined && contact !== false ? contact.email : ''}" type="text" class="form-control" placeholder="Enter Contact Email" name="email[]" id="${uniqueId}_email" data-parsley-trigger="change" data-parsley-type="email" onchange="validateDuplicateByClientBranch(this, 'email', 'branchBtnSubmit')" required> <input value="${contact !== undefined && contact !== false ? contact.email : ''}" type="text" class="form-control" placeholder="Enter Contact Email" name="email[]" id="${uniqueId}_email" data-parsley-trigger="change" data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com)." onchange="validateDuplicateByClientBranch(this, 'email', 'branchBtnSubmit')" required>
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="${uniqueId}_mobile">Mobile<span class="text-danger">*</span></label> <label for="${uniqueId}_mobile">Mobile<span class="text-danger">*</span></label>
<input value="${contact !== undefined && contact !== false ? contact.mobile : ''}" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" id="${uniqueId}_mobile" onchange="validateDuplicateByClientBranch(this, 'mobile', 'branchBtnSubmit')" onkeypress = "return onlyNumbers(event)" maxlength="10" min="10" data-parsley-type-message="Please enter a valid 10-digit mobile number." data-parsley-required-message="Please enter a valid 10-digit mobile number." required> <input value="${contact !== undefined && contact !== false ? contact.mobile : ''}" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" id="${uniqueId}_mobile" onchange="validateDuplicateByClientBranch(this, 'mobile', 'branchBtnSubmit')" onkeypress = "return onlyNumbers(event)" maxlength="10" minlength="10" data-parsley-pattern="^[0-9]{10}$" data-parsley-pattern-message="Mobile number must be exactly 10 digits." data-parsley-required-message="Mobile number must be exactly 10 digits." required>
</div> </div>
</div> </div>
<div class="form-group" style="display: flex;"> <div class="form-group" style="display: flex;">

View File

@ -54,6 +54,19 @@ $cd_col_width_px = nhance_dt_column_widths_px($cd_header_labels, $cd_col_max_len
#client-deposit-list-table tbody td:nth-child(5) { #client-deposit-list-table tbody td:nth-child(5) {
overflow: visible; overflow: visible;
text-overflow: clip; text-overflow: clip;
white-space: nowrap;
text-align: center;
}
#client-deposit-list-table .view-deposit-link {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
text-decoration: none;
}
#client-deposit-list-table .view-deposit-link:hover {
background-color: #f5f7fa;
} }
#client-deposit-list-table tbody td { #client-deposit-list-table tbody td {
padding: 5px 11px !important; padding: 5px 11px !important;
@ -123,9 +136,9 @@ $cd_col_width_px = nhance_dt_column_widths_px($cd_header_labels, $cd_col_max_len
?> ?>
</td> </td>
<td> <td>
<a class="dropdown-item" <a class="view-deposit-link"
href="<?= base_url("client/view_deposit/{$value->insurer_id}?client_id={$value->client_id}&cd_ac_pk={$value->cd_ac_pk}"); ?>"> href="<?= base_url("client/view_deposit/{$value->insurer_id}?client_id={$value->client_id}&cd_ac_pk={$value->cd_ac_pk}"); ?>">
<i class="mdi mdi-eye mr-2 text-muted font-18 vertical-middle"></i>View Deposit <i class="mdi mdi-eye text-muted font-18 vertical-middle"></i><span>View Deposit</span>
</a> </a>
</td> </td>
</tr> </tr>

View File

@ -10,11 +10,20 @@
</style> </style>
<script>
var pageHideMainNavTitle = true;
var pageTitle = 'Client Details - <?= $client['client_name'] ?> ( <?= $client['short_name'] ?> ) ';
var pageBackButton = '<a href="<?= base_url("client/list"); ?>" class="topbar-icon-btn" data-toggle="tooltip" data-placement="top" title="Back to Client List" aria-label="Back to Client List"><i class="ri-arrow-left-s-line"></i></a>';
if (typeof window.applyTopNavbarTitle === 'function') {
window.applyTopNavbarTitle();
}
</script>
<div class="row" id="client_info">
<div class="col-12">
<div class="card">
<div class="card-body">
<div id="client_info">
<div class="row">
<div class="col-12"> <div class="col-12">
<div id="accordion" class="mb-3"> <div id="accordion" class="mb-3">
<div class="card"> <div class="card">
@ -23,14 +32,19 @@
<div class="col-6"> <div class="col-6">
<h4 style="position: relative; left: 18px; top: 2px;"> <h4 style="position: relative; left: 18px; top: 2px;">
<!--
<span class="client_info_close fs-6" id="close_btn"> <span class="client_info_close fs-6" id="close_btn">
<i class="mdi mdi-chevron-left" style="font-size: 28px;cursor:pointer;"></i> <i class="mdi mdi-chevron-left" style="font-size: 28px;cursor:pointer;"></i>
</span> </span>
-->
<span> <span>
<!--
Client Basic Info - Client Basic Info -
<strong> <?= $client['client_name'] ?> ( <?= $client['short_name'] ?> ) </strong> <strong> <?= $client['client_name'] ?> ( <?= $client['short_name'] ?> ) </strong>
-->
Client Basic Information
</span> </span>
</h4> </h4>
</div> </div>
@ -228,8 +242,9 @@
</div> </div>
<!-- end row --> <!-- end row -->
</div> </div>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -43,11 +43,13 @@
<div class="form-row additional-doc-row" data-row-index="0"> <div class="form-row additional-doc-row" data-row-index="0">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>Document Name<span class="text-danger">*</span></label> <label>Document Name<span class="text-danger">*</span></label>
<input type="text" class="form-control other-doc-name-field" placeholder="Document Name" name="other_docs_name[]" data-parsley-inceptioncharset="true" data-parsley-trigger="input change" required> <input type="text" class="form-control other-doc-name-field" placeholder="Document Name" name="other_docs_name[]" data-parsley-inceptioncharset="true" data-parsley-trigger="input change" data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$" data-parsley-pattern-message="Only letters, numbers, spaces, underscore (_) and hyphen (-) are allowed." required>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>File<span class="text-danger">*</span></label> <label>File<span class="text-danger">*</span></label>
<input class="form-control other-doc-file-field" type="file" name="file_name[]" required accept=".pdf, .jpeg, .jpg, .png"> <input class="form-control other-doc-file-field" type="file" name="file_name[]" required accept=".pdf, .jpeg, .jpg, .png">
<small class="mt-1 text-muted d-block">Allowed: PDF, JPG, JPEG, PNG. Size : 200KB/image 25MB/PDF</small>
<div class="other-doc-file-error text-danger small mt-1"></div>
</div> </div>
<div class="form-group col-md-4" style="<?= isset($client['id']) ? 'margin-top: 41px;' : 'margin-top: 30px;' ?>"> <div class="form-group col-md-4" style="<?= isset($client['id']) ? 'margin-top: 41px;' : 'margin-top: 30px;' ?>">
<button type="button" class="btn btn-outline-danger remove-additional-doc-row" style="display:none;">Remove</button> <button type="button" class="btn btn-outline-danger remove-additional-doc-row" style="display:none;">Remove</button>
@ -96,17 +98,79 @@
<script> <script>
var kycPrimaryKey = $('#client_id_kyc').val(); var kycPrimaryKey = $('#client_id_kyc').val();
var allowedExtensions = ['pdf', 'png', 'jpeg', 'jpg'];
var maxImageSizeInBytes = 200 * 1024;
var maxPdfSizeInBytes = 25 * 1024 * 1024;
function resetOtherDocFileField($field) {
$field.val('');
}
function validateOtherDocFileField($field, showToastr) {
var $row = $field.closest('.additional-doc-row');
var $scope = $row.length ? $row : $field.closest('form');
var $error = $scope.find('.other-doc-file-error, .kyc-primary-file-error').first();
var file = $field[0].files && $field[0].files[0];
if ($error.length) {
$error.text('');
}
$field.removeClass('is-invalid');
if (!file) {
return true;
}
var fileName = file.name || '';
var fileExtension = fileName.split('.').pop().toLowerCase();
var sizeErrorMessage = '';
if (allowedExtensions.indexOf(fileExtension) === -1) {
var typeMessage = 'Only PDF, JPG, JPEG, PNG files are allowed.';
if ($error.length) {
$error.text(typeMessage);
}
$field.addClass('is-invalid');
resetOtherDocFileField($field);
if (showToastr) {
toastr.warning(typeMessage, 'Invalid file type');
}
return false;
}
if (fileExtension === 'pdf' && file.size > maxPdfSizeInBytes) {
sizeErrorMessage = 'PDF size should be up to 25MB.';
} else if (['png', 'jpg', 'jpeg'].indexOf(fileExtension) !== -1 && file.size > maxImageSizeInBytes) {
sizeErrorMessage = 'Image size should be up to 200KB.';
}
if (sizeErrorMessage) {
if ($error.length) {
$error.text(sizeErrorMessage);
}
$field.addClass('is-invalid');
resetOtherDocFileField($field);
if (showToastr) {
toastr.warning(sizeErrorMessage, 'Invalid file size');
}
return false;
}
return true;
}
function getAdditionalDocRowTemplate(index) { function getAdditionalDocRowTemplate(index) {
return ` return `
<div class="form-row additional-doc-row" data-row-index="${index}"> <div class="form-row additional-doc-row" data-row-index="${index}">
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>Document Name<span class="text-danger">*</span></label> <label>Document Name<span class="text-danger">*</span></label>
<input type="text" class="form-control other-doc-name-field" placeholder="Document Name" name="other_docs_name[]" data-parsley-inceptioncharset="true" data-parsley-trigger="input change" required> <input type="text" class="form-control other-doc-name-field" placeholder="Document Name" name="other_docs_name[]" data-parsley-inceptioncharset="true" data-parsley-trigger="input change" data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$" data-parsley-pattern-message="Only letters, numbers, spaces, underscore (_) and hyphen (-) are allowed." required>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label>File<span class="text-danger">*</span></label> <label>File<span class="text-danger">*</span></label>
<input class="form-control other-doc-file-field" type="file" name="file_name[]" required accept=".pdf, .jpeg, .jpg, .png"> <input class="form-control other-doc-file-field" type="file" name="file_name[]" required accept=".pdf, .jpeg, .jpg, .png">
<small class="mt-1 text-muted d-block">Allowed: PDF, JPG, JPEG, PNG. Size : 200KB/image 25MB/PDF</small>
<div class="other-doc-file-error text-danger small mt-1"></div>
</div> </div>
<div class="form-group col-md-4" style="<?= isset($client['id']) ? 'margin-top: 41px;' : 'margin-top: 30px;' ?>"> <div class="form-group col-md-4" style="<?= isset($client['id']) ? 'margin-top: 41px;' : 'margin-top: 30px;' ?>">
<button type="button" class="btn btn-outline-danger remove-additional-doc-row">Remove</button> <button type="button" class="btn btn-outline-danger remove-additional-doc-row">Remove</button>
@ -126,7 +190,6 @@
var form = $(this).closest('form'); var form = $(this).closest('form');
var formData = new FormData(form[0]); var formData = new FormData(form[0]);
var fileInputs = form.find('input[type="file"]'); var fileInputs = form.find('input[type="file"]');
var allowedExtensions = ['pdf', 'png', 'jpeg', 'jpg'];
if (kycPrimaryKey === '') { if (kycPrimaryKey === '') {
toastr.error('Client is required', 'Error'); toastr.error('Client is required', 'Error');
@ -135,24 +198,26 @@
} }
var isFormEmpty = true; var isFormEmpty = true;
var hasInvalidFile = false;
fileInputs.each(function() { fileInputs.each(function() {
var files = $(this)[0].files; var $currentFileInput = $(this);
var files = $currentFileInput[0].files;
if (files.length > 0) { if (files.length > 0) {
for (var i = 0; i < files.length; i++) { if (!validateOtherDocFileField($currentFileInput, true)) {
var fileName = files[i].name; hasInvalidFile = true;
var fileExtension = fileName.split('.').pop().toLowerCase(); return false;
if (allowedExtensions.indexOf(fileExtension) === -1) {
form.trigger('reset')
toastr.warning('File type not allowed: ' + fileName, 'Only Allowed pdf, png, jpg and jpeg');
return;
}
} }
isFormEmpty = false; isFormEmpty = false;
return false;
} }
}); });
if (hasInvalidFile) {
return;
}
if (isFormEmpty) { if (isFormEmpty) {
form.find('.kyc-primary-file-error').text('Please select a file.');
fileInputs.addClass('is-invalid');
toastr.warning('Form is Empty', 'Warning'); toastr.warning('Form is Empty', 'Warning');
return; return;
} }
@ -238,31 +303,29 @@
var isValid = $('#kyc_form').parsley().validate(); var isValid = $('#kyc_form').parsley().validate();
var form_action = ''; var form_action = '';
var allowedExtensions = ['pdf', 'png', 'jpeg', 'jpg'];
$('#kyc_form .other-doc-name-field, #kyc_form .other-doc-file-field').removeClass('is-invalid'); $('#kyc_form .other-doc-name-field, #kyc_form .other-doc-file-field').removeClass('is-invalid');
$('#kyc_form .other-doc-file-error').text('');
$('#additional_docs_rows .additional-doc-row').each(function() { $('#additional_docs_rows .additional-doc-row').each(function() {
var docNameField = $(this).find('.other-doc-name-field'); var docNameField = $(this).find('.other-doc-name-field');
var fileField = $(this).find('.other-doc-file-field'); var fileField = $(this).find('.other-doc-file-field');
var docNameValue = (docNameField.val() || '').trim(); var docNameValue = (docNameField.val() || '').trim();
var selectedFile = fileField[0].files[0]; var hasSelectedFile = !!(fileField[0].files[0]);
if (docNameValue === '' || !selectedFile) { if (docNameValue === '' || !hasSelectedFile) {
isValid = false; isValid = false;
if (docNameValue === '') { if (docNameValue === '') {
docNameField.addClass('is-invalid'); docNameField.addClass('is-invalid');
} }
if (!selectedFile) { if (!hasSelectedFile) {
fileField.addClass('is-invalid'); fileField.addClass('is-invalid');
} }
return; return;
} }
var fileExtension = selectedFile.name.split('.').pop().toLowerCase(); if (!validateOtherDocFileField(fileField, true)) {
if (allowedExtensions.indexOf(fileExtension) === -1) {
isValid = false; isValid = false;
fileField.addClass('is-invalid');
} }
}); });
@ -401,6 +464,14 @@
}); });
}); });
$(document).on('change', '.other-doc-file-field', function () {
validateOtherDocFileField($(this), true);
});
$(document).on('change', '.file-input__input', function () {
validateOtherDocFileField($(this), true);
});
function getKYCEntityDocument(entity_type_id, client_id){ function getKYCEntityDocument(entity_type_id, client_id){
$.ajax({ $.ajax({
@ -433,6 +504,8 @@
<input type="hidden" class="form-control" value="${item.id}" name="kyc_doc_type_id"> <input type="hidden" class="form-control" value="${item.id}" name="kyc_doc_type_id">
<input type="hidden" name="client_id" value="${client_id}"> <input type="hidden" name="client_id" value="${client_id}">
<button class="btn btn-sm btn-primary submit" style="position: relative; right:0px;">Submit</button> <button class="btn btn-sm btn-primary submit" style="position: relative; right:0px;">Submit</button>
<small class="mt-1 text-muted d-block">Allowed: PDF, JPG, JPEG, PNG. Size : 200KB/image 25MB/PDF</small>
<div class="kyc-primary-file-error text-danger small mt-1"></div>
</form> </form>
</td> </td>
<td id="name_${item.id}" style="display:none;"></td> <td id="name_${item.id}" style="display:none;"></td>

View File

@ -205,6 +205,10 @@ table.dataTable thead th {
<?php if(in_array(get_role_id(), [1, 5])) { ?> <?php if(in_array(get_role_id(), [1, 5])) { ?>
<a class="dropdown-item" data-id="<?= $row->id;?>" onclick="removeClient(this)"><i class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle"></i>Delete</a> <a class="dropdown-item" data-id="<?= $row->id;?>" onclick="removeClient(this)"><i class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle"></i>Delete</a>
<?php } ?> <?php } ?>
<a class="dropdown-item" href="javascript:void(0);" onclick="openClientDetailsPage(<?= $row->id ?>)">
<i class="mdi mdi-eye mr-2 text-muted font-18 vertical-middle"></i>Open Client Details
</a>
</div> </div>
</div> </div>
</td> </td>
@ -257,6 +261,7 @@ table.dataTable thead th {
<script> <script>
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
/**
const table = document.getElementById("client-list-table"); const table = document.getElementById("client-list-table");
// Create custom dropdown // Create custom dropdown
@ -344,9 +349,9 @@ table.dataTable thead th {
activeDropdown = null; activeDropdown = null;
} }
}); });
*/
// Open client details page // Open client details page
function openClientDetailsPage(clientId) { window.openClientDetailsPage = function(clientId) {
$('.loader').fadeIn(); $('.loader').fadeIn();
$('.loader-mask').fadeIn(); $('.loader-mask').fadeIn();
@ -369,7 +374,7 @@ table.dataTable thead th {
$('.loader-mask').delay(350).fadeOut('slow'); $('.loader-mask').delay(350).fadeOut('slow');
} }
}); });
} };
}); });
</script> </script>

View File

@ -205,7 +205,9 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="policy_type"> Policy Type<span class="text-danger">*</span></label> <label for="policy_type"> Policy Type<span class="text-danger">*</span></label>
<select class="form-control" id="policy_type" name="policy_type_id" required> <select class="form-control" id="policy_type" name="policy_type_id" required
data-parsley-pattern="^[1-9][0-9]*$"
data-parsley-pattern-message="Please select a valid Policy Type.">
<option value="0">Select Policy Type</option> <option value="0">Select Policy Type</option>
<?php foreach ($policy_types as $value) { ?> <?php foreach ($policy_types as $value) { ?>
<option value="<?= $value['id']?>"><?= $value['policy_type'] ?></option> <option value="<?= $value['id']?>"><?= $value['policy_type'] ?></option>
@ -248,7 +250,9 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="policy_no">Policy No<span class="text-danger">*</span></label> <label for="policy_no">Policy No<span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" oninput="checkPolicyNo(this)" placeholder="Enter Policy Number" name="policy_no" id="policy_no" required> <input value="" type="text" class="form-control" oninput="checkPolicyNo(this)" placeholder="Enter Policy Number" name="policy_no" id="policy_no" required
data-parsley-pattern="^[a-zA-Z0-9\\s_\\-/\\\\]+$"
data-parsley-pattern-message="Invalid characters in Policy No.">
</div> </div>
</div> </div>
@ -280,12 +284,18 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="gst_no">GST ( % )<span class="text-danger">*</span></label> <label for="gst_no">GST ( % )<span class="text-danger">*</span></label>
<input type="text" class="form-control" placeholder="GST (%)" id="gst_no" name="gst" required> <input type="text" class="form-control" placeholder="GST (%)" id="gst_no" name="gst" required
data-parsley-type="number"
data-parsley-range="[0, 100]"
data-parsley-type-message="GST must be a valid number."
data-parsley-range-message="GST percentage must be between 0 and 100.">
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="wellness_plan_id">Wellness Plan ID<span class="text-danger"></span></label> <label for="wellness_plan_id">Wellness Plan ID<span class="text-danger"></span></label>
<input type="text" class="form-control" id="wellness_plan_id" name="wellness_plan_id"> <input type="text" class="form-control" id="wellness_plan_id" name="wellness_plan_id"
data-parsley-pattern="^[a-zA-Z0-9/_-]+$"
data-parsley-pattern-message="Wellness Plan ID can only contain letters, numbers, hyphens (-), underscores (_), and forward slashes (/).">
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">

View File

@ -30,10 +30,6 @@
white-space: normal; white-space: normal;
} }
.dataTables_filter{
position: absolute;
}
.right-align-input { .right-align-input {
text-align: right; text-align: right;
} }
@ -95,9 +91,9 @@ if ($emp_show_branch) {
$emp_header_labels[] = 'Branch'; $emp_header_labels[] = 'Branch';
} }
$emp_header_labels = array_merge($emp_header_labels, [ $emp_header_labels = array_merge($emp_header_labels, [
'Name', 'EMP Code', 'Relationship', 'Gender', 'Email', 'Mobile', 'Date of Birth', 'Name ', 'EMP Code ', 'Relationship ', 'Gender ', 'Email', 'Mobile', 'Date of Birth',
'Policy name', 'Insurer name', 'TPA ID', 'Risk ID', 'Policy status', 'Policy name ', 'Insurer name ', 'TPA ID ', 'Risk ID ', 'Policy status ',
'(₹)Sum Insured', '(₹)Premium', '(₹)Pro Rata Premium', '(₹)GST', 'Action', '(₹)Sum Insured ', '(₹)Premium ', '(₹)Pro Rata Premium ', '(₹)GST ', 'Action ',
]); ]);
$emp_col_count = count($emp_header_labels); $emp_col_count = count($emp_header_labels);
$emp_col_max_len = array_fill(0, $emp_col_count, 0); $emp_col_max_len = array_fill(0, $emp_col_count, 0);
@ -161,8 +157,20 @@ if (isset($employees)) {
$emp_col_max_len[$emp_col_count - 6] = max($emp_col_max_len[$emp_col_count - 6], mb_strlen('Total')); $emp_col_max_len[$emp_col_count - 6] = max($emp_col_max_len[$emp_col_count - 6], mb_strlen('Total'));
$emp_col_min_px = array_fill(0, $emp_col_count, 80); $emp_col_min_px = array_fill(0, $emp_col_count, 80);
$emp_col_max_px = array_fill(0, $emp_col_count, 360); $emp_col_max_px = array_fill(0, $emp_col_count, 360);
$emp_col_min_px[0] = 48; $emp_col_min_px[0] = 64;
$emp_col_max_px[0] = 72; $emp_col_max_px[0] = 88;
$emp_dynamic_idx = 1;
if ($emp_show_client_branch || $emp_show_branch) {
$emp_col_min_px[$emp_dynamic_idx] = max($emp_col_min_px[$emp_dynamic_idx], 120);
$emp_col_max_px[$emp_dynamic_idx] = max($emp_col_max_px[$emp_dynamic_idx], 190);
$emp_dynamic_idx++;
}
$emp_col_min_px[$emp_dynamic_idx] = max($emp_col_min_px[$emp_dynamic_idx], 110); // Name
$emp_dynamic_idx++;
$emp_col_min_px[$emp_dynamic_idx] = max($emp_col_min_px[$emp_dynamic_idx], 100); // EMP Code
$emp_col_max_px[$emp_dynamic_idx] = max($emp_col_max_px[$emp_dynamic_idx], 140);
$emp_col_min_px[$emp_col_count - 1] = 72; $emp_col_min_px[$emp_col_count - 1] = 72;
$emp_col_max_px[$emp_col_count - 1] = 96; $emp_col_max_px[$emp_col_count - 1] = 96;
$emp_col_width_px = nhance_dt_column_widths_px($emp_header_labels, $emp_col_max_len, $emp_col_min_px, $emp_col_max_px); $emp_col_width_px = nhance_dt_column_widths_px($emp_header_labels, $emp_col_max_len, $emp_col_min_px, $emp_col_max_px);
@ -187,6 +195,11 @@ $gst_total = 0;
vertical-align: middle; vertical-align: middle;
} }
<?php endfor; ?> <?php endfor; ?>
#employee-data-list-table,
#employee-data-list-table_wrapper .dataTables_scrollHead table,
#employee-data-list-table_wrapper .dataTables_scrollBody table {
table-layout: fixed !important;
}
#employee-data-list-table tbody td:not(:last-child) { #employee-data-list-table tbody td:not(:last-child) {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -205,6 +218,15 @@ $gst_total = 0;
font-size: 13px; font-size: 13px;
line-height: 1.25; line-height: 1.25;
} }
#employee-data-list-table_wrapper table.dataTable thead .sorting:before,
#employee-data-list-table_wrapper table.dataTable thead .sorting:after,
#employee-data-list-table_wrapper table.dataTable thead .sorting_asc:before,
#employee-data-list-table_wrapper table.dataTable thead .sorting_asc:after,
#employee-data-list-table_wrapper table.dataTable thead .sorting_desc:before,
#employee-data-list-table_wrapper table.dataTable thead .sorting_desc:after {
right: 0.55rem !important;
opacity: 1 !important;
}
</style> </style>
<div class="row" id="client_list"> <div class="row" id="client_list">
@ -216,7 +238,8 @@ $gst_total = 0;
<h4 style="position: relative;">Employees</h4> <h4 style="position: relative;">Employees</h4>
</div> </div>
</div> </div>
<table data-custom-table-css="table" class="table table-striped mb-0 nowrap" cellspacing="0" id="employee-data-list-table"> <div class="table-responsive">
<table data-custom-table-css="table" class="table table-hover m-0 table-centered nowrap w-100" cellspacing="0" id="employee-data-list-table">
<thead class="bg-light"> <thead class="bg-light">
<tr> <tr>
<th class="font-weight-medium">S.No&nbsp;</th> <th class="font-weight-medium">S.No&nbsp;</th>
@ -243,7 +266,7 @@ $gst_total = 0;
<th class="font-weight-medium">Policy status&nbsp;</th> <th class="font-weight-medium">Policy status&nbsp;</th>
<th class="font-weight-medium">()Sum Insured&nbsp;</th> <th class="font-weight-medium">()Sum Insured&nbsp;</th>
<th class="font-weight-medium">()Premium&nbsp;</th> <th class="font-weight-medium">()Premium&nbsp;</th>
<th class="font-weight-medium" id="rata_premium" data-toggle="tooltip" data-placement="top">()Pro Rata <br> Premium&nbsp;</th> <th class="font-weight-medium" id="rata_premium" data-toggle="tooltip" data-placement="top">()Pro Rata Premium&nbsp;</th>
<th class="font-weight-medium" id="gst" data-toggle="tooltip" data-placement="top">()GST&nbsp;</th> <th class="font-weight-medium" id="gst" data-toggle="tooltip" data-placement="top">()GST&nbsp;</th>
<th class="font-weight-medium" > Action &nbsp;</th> <th class="font-weight-medium" > Action &nbsp;</th>
</tr> </tr>
@ -281,19 +304,19 @@ $gst_total = 0;
<?php <?php
switch ($employee['status']) { switch ($employee['status']) {
case 'draft': case 'draft':
echo '<span class="badge badge-secondary">' . $employee['status'] . '</span>'; echo '<span class="badge badge-secondary">' . ucfirst($employee['status']) . '</span>';
break; break;
case 'active': case 'active':
echo '<span class="badge badge-success">' . $employee['status'] . '</span>'; echo '<span class="badge badge-success">' . ucfirst($employee['status']) . '</span>';
break; break;
case 'inactive': case 'inactive':
echo '<span class="badge badge-warning">' . $employee['status'] . '</span>'; echo '<span class="badge badge-warning">' . ucfirst($employee['status']) . '</span>';
break; break;
case 'expired': case 'expired':
echo '<span class="badge badge-danger">' . $employee['status'] . '</span>'; echo '<span class="badge badge-danger">' . ucfirst($employee['status']) . '</span>';
break; break;
case 'enrolled': case 'enrolled':
echo '<span class="badge2 badge2-secondary2">' . $employee['status'] . '</span>'; echo '<span class="badge2 badge2-secondary2">' . ucfirst($employee['status']) . '</span>';
break; break;
default: default:
echo $employee['status']; echo $employee['status'];
@ -347,32 +370,21 @@ $gst_total = 0;
<tfoot> <tfoot>
<tr> <tr>
<th></th> <?php for ($i = 0; $i < $emp_col_count; $i++) : ?>
<?php if (isset($getData)) { <?php if ($i === ($emp_col_count - 4)) : ?>
if ($getData['client_id'] == '0' && $getData['policy_id'] == '0' && $getData['branch_id'] == '0' && ($getData['emp_code'] != "" || $getData['emp_name'] != "" || $getData['status'] != "")) { ?> <th>Total</th>
<th></th> <?php elseif ($i === ($emp_col_count - 3)) : ?>
<?php } <th><?php echo format_indian_number($pro_rata_total); ?></th>
if ($getData['client_id'] != '0' && $getData['branch_id'] == '0') { ?> <?php elseif ($i === ($emp_col_count - 2)) : ?>
<th></th> <th><?php echo format_indian_number($gst_total); ?></th>
<?php } } ?> <?php else : ?>
<th></th> <th></th>
<th></th> <?php endif; ?>
<th></th> <?php endfor; ?>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th>Total</th>
<th><?php echo format_indian_number($pro_rata_total); ?></th>
<th><?php echo format_indian_number($gst_total); ?></th>
<th></th>
</tr> </tr>
</tfoot> </tfoot>
</table> </table>
</div>
</div> </div>
</div> </div>
</div><!-- end col --> </div><!-- end col -->
@ -473,35 +485,54 @@ $gst_total = 0;
$(document).ready(function() { $(document).ready(function() {
var ticketsTable = $('#employee-data-list-table'); var ticketsTable = $('#employee-data-list-table');
if (ticketsTable.length) { if (ticketsTable.length) {
nhanceListDataTableBeforeInit(); var _dtDefScroll = {
var nhEmpDataTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({ scrollX: $.fn.dataTable.defaults.scrollX,
// dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right scrollY: $.fn.dataTable.defaults.scrollY,
// "<'row'<'col-sm-12'tr>>" + scrollCollapse: $.fn.dataTable.defaults.scrollCollapse
// "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector };
dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right $.extend($.fn.dataTable.defaults, { scrollX: false, scrollY: false, scrollCollapse: false });
"<'row'<'col-sm-12'tr>>" +
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>", var nhEmpDataTable = ticketsTable.DataTable({
dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]], lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
scrollX: false,
scrollY: false,
scrollCollapse: false,
initComplete: function () {
var $wrap = $(this.api().table().container());
var $body = $wrap.find('.dataTables_scrollBody');
var $head = $wrap.find('.dataTables_scrollHead');
if ($body.length && $head.length) {
$body.off('scroll.nhEmpHScroll').on('scroll.nhEmpHScroll', function () {
$head.scrollLeft($(this).scrollLeft());
});
$head.off('scroll.nhEmpHScroll').on('scroll.nhEmpHScroll', function () {
$body.scrollLeft($(this).scrollLeft());
});
}
},
buttons: [ buttons: [
{ {
extend: 'collection', extend: 'collection',
text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>', text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
className: 'btn app-btn-secondary ', className: 'btn app-btn-secondary ',
buttons: [ buttons: [
{ {
extend: 'csv', extend: 'csv',
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>', text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
className: 'app-btn-primary ', className: 'app-btn-primary ',
title: 'Members', title: 'Members',
}, },
{ {
extend: 'excel', extend: 'excel',
text: '<i class="mdi mdi-file-excel " ></i><span class=" btn-custom"> EXCEL </span>', text: '<i class="mdi mdi-file-excel " ></i><span class=" btn-custom"> EXCEL </span>',
className: 'app-btn-primary ', className: 'app-btn-primary ',
title: 'Members', title: 'Members',
sheetName: 'Members' sheetName: 'Members'
} }
] ]
} }
], ],
@ -517,16 +548,28 @@ $gst_total = 0;
searchPlaceholder: "Search", searchPlaceholder: "Search",
emptyTable: '<div class="text-center text-muted">No Data found</div>' emptyTable: '<div class="text-center text-muted">No Data found</div>'
}, },
paging: true, // Enable pagination paging: true,
pageLength: 25, // Set default number of rows per page (optional) pageLength: 25,
autoWidth: false,
responsive: false,
columnDefs: [ columnDefs: [
<?php for ($i = 0; $i < $emp_col_count; $i++) : ?> <?php for ($i = 0; $i < $emp_col_count; $i++) : ?>
{ targets: <?= $i ?>, width: '<?= (int) $emp_col_width_px[$i] ?>px' }, { targets: <?= $i ?>, width: '<?= (int) $emp_col_width_px[$i] ?>px' },
<?php endfor; ?> <?php endfor; ?>
], ],
})); });
nhanceListDataTableAfterInit();
nhanceListDataTableBindAdjust(nhEmpDataTable); $.extend($.fn.dataTable.defaults, _dtDefScroll);
nhEmpDataTable.on('draw.dt', function () {
nhEmpDataTable.columns.adjust();
});
$(window).on('resize', function () {
nhEmpDataTable.columns.adjust();
});
setTimeout(function () {
nhEmpDataTable.columns.adjust();
}, 0);
} else { } else {
console.error("Table not found."); console.error("Table not found.");
} }

View File

@ -239,6 +239,7 @@
</div> </div>
</div> </div>
<!--
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("scroll-horizontal-datatable"); const table = document.getElementById("scroll-horizontal-datatable");
@ -328,6 +329,7 @@
}); });
}); });
</script> </script>
-->
@ -338,11 +340,7 @@ $(document).ready(function () {
if (ticketsTable.length) { if (ticketsTable.length) {
ticketsTable.DataTable({ ticketsTable.DataTable({
// dom: dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" +
// "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right
// "<'row'<'col-sm-12'tr>>" +
// "<'row'<'col-sm-5'i><'col-sm-7'p>>", // Pagination at the bottom, without page length selector
dom: "<'row'<'col-sm-6'f><'col-sm-6 text-right'B>>" + // Filter left, buttons right
"<'row'<'col-sm-12'tr>>" + "<'row'<'col-sm-12'tr>>" +
"<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>", "<'row align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]], lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
@ -409,110 +407,23 @@ $(document).ready(function () {
} else { } else {
console.error("Table not found."); console.error("Table not found.");
} }
});
getURLParams();
$(document).ready(function() {
getURLParams()
$('#client_id').select2(); $('#client_id').select2();
$('#insurer_id').select2(); $('#insurer_id').select2();
$('#policy_type_id').select2(); $('#policy_type_id').select2();
})
function fetchEmpolyeeList(event) {
event.preventDefault(); // Prevent default action
var start_date = $('#startDate').val();
var end_date = $('#endDate').val();
var client_id = $('#client_id').val();
var insurer_id = $('#insurer_id').val();
var policy_type_id = $('#policy_type_id').val();
var date_type = $('#date_type').val();
var issuer = $('#issuer').val();
console.log(start_date + '-' + end_date);
var queryParams = {
start_date: start_date,
end_date: end_date,
client_id: client_id,
insurer_id: insurer_id,
policy_type_id: policy_type_id,
date_type: date_type,
issuer: issuer,
};
const queryString = objectToQueryString(queryParams);
const apiURL = $('#get-emp-list').attr('href') + "?" + queryString;
console.log(apiURL);
window.location.href = apiURL;
}
function objectToQueryString(obj) {
return Object.keys(obj).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&');
}
function getURLParams() {
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
const startDate = params.get('start_date') || 0; // Default to 0 if not found
const endDate = params.get('end_date') || 0; // Default to 0 if not found
const client_id = params.get('client_id') || 0; // Default to 0 if not found
const insurer_id = params.get('insurer_id') || 0; // Default to 0 if not found
const policy_type_id = params.get('policy_type_id') || 0; // Default to 0 if not found
const date_type = params.get('date_type') || 0; // Default to 0 if not found
const issuer = params.get('issuer') || 0; // Default to 0 if not found
hideDateField(date_type)
console.log('startDate', startDate)
console.log('endDate', endDate)
console.log('client_id', client_id)
console.log('insurer_id', insurer_id)
console.log('policy_type_id', policy_type_id)
console.log('date_type', date_type)
console.log('issuer', issuer)
// Log the values or use them as needed
console.log('Start Date:', startDate);
console.log('End Date:', endDate);
if (startDate != 0 && endDate != 0) {
setTimeout(function() {
$('#start_date').val(startDate)
$('#end_date').val(endDate)
$('#client_id').val(client_id).change()
$('#insurer_id').val(insurer_id).change()
$('#policy_type_id').val(policy_type_id).change()
$('#date_type').val(date_type)
$('#issuer').val(issuer)
}, 1000)
}
}
$(function() {
const url = new URL(window.location.href); const url = new URL(window.location.href);
const params = new URLSearchParams(url.search); const params = new URLSearchParams(url.search);
// Get start and end dates from URL parameters, or use default values
const startDateParam = params.get('start_date') || moment().subtract(29, 'days').format('DD-MM-YYYY'); const startDateParam = params.get('start_date') || moment().subtract(29, 'days').format('DD-MM-YYYY');
const endDateParam = params.get('end_date') || moment().format('DD-MM-YYYY'); const endDateParam = params.get('end_date') || moment().format('DD-MM-YYYY');
// Parse the dates to moment objects
var start = moment(startDateParam, 'DD-MM-YYYY'); var start = moment(startDateParam, 'DD-MM-YYYY');
var end = moment(endDateParam, 'DD-MM-YYYY'); var end = moment(endDateParam, 'DD-MM-YYYY');
// var start = moment().subtract(29, 'days'); function cb(startDate, endDate) {
// var end = moment(); $('#reportrange').html(startDate.format('D-MM-YYYY') + ' - ' + endDate.format('D-MM-YYYY'));
$('#startDate').val(startDate.format('DD-MM-YYYY'));
function cb(start, end) { $('#endDate').val(endDate.format('DD-MM-YYYY'));
$('#reportrange').html(start.format('D-MM-YYYY') + ' - ' + end.format('D-MM-YYYY'));
$('#startDate').val(start.format('DD-MM-YYYY'));
$('#endDate').val(end.format('DD-MM-YYYY'));
} }
$('#reportrange').daterangepicker({ $('#reportrange').daterangepicker({
@ -525,18 +436,24 @@ $(function() {
'Last 7 Days': [moment().subtract(6, 'days'), moment()], 'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()], 'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')], 'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month') 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
.endOf('month')
]
} }
}); }, cb);
$(document).ready(function() { cb(start, end);
getURLParams()
$('#client_id').select2(); $('#clear-filters').on('click', function() {
$('#insurer_id').select2(); $('#client_id').val('0').change();
$('#policy_type_id').select2(); $('#insurer_id').val('0').change();
}) $('#policy_type_id').val('0').change();
$('#date_type').val('0');
$('#issuer').val('0');
$('#date_div').hide();
$('#reportrange').data('daterangepicker').setStartDate(moment().subtract(29, 'days'));
$('#reportrange').data('daterangepicker').setEndDate(moment());
cb(moment().subtract(29, 'days'), moment());
});
});
function fetchEmpolyeeList(event) { function fetchEmpolyeeList(event) {
event.preventDefault(); // Prevent default action event.preventDefault(); // Prevent default action
@ -568,7 +485,9 @@ $(function() {
} }
function objectToQueryString(obj) { function objectToQueryString(obj) {
return Object.keys(obj).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`).join('&'); return Object.keys(obj).map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]);
}).join('&');
} }
function getURLParams() { function getURLParams() {
@ -599,78 +518,17 @@ $(function() {
if (startDate != 0 && endDate != 0) { if (startDate != 0 && endDate != 0) {
setTimeout(function() { setTimeout(function() {
$('#start_date').val(startDate) $('#startDate').val(startDate);
$('#end_date').val(endDate) $('#endDate').val(endDate);
$('#client_id').val(client_id).change() $('#client_id').val(client_id).change();
$('#insurer_id').val(insurer_id).change() $('#insurer_id').val(insurer_id).change();
$('#policy_type_id').val(policy_type_id).change() $('#policy_type_id').val(policy_type_id).change();
$('#date_type').val(date_type) $('#date_type').val(date_type);
$('#issuer').val(issuer) $('#issuer').val(issuer);
}, 1000) }, 300);
} }
} }
$(function() {
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
// Get start and end dates from URL parameters, or use default values
const startDateParam = params.get('start_date') || moment().subtract(29, 'days').format('DD-MM-YYYY');
const endDateParam = params.get('end_date') || moment().format('DD-MM-YYYY');
// Parse the dates to moment objects
var start = moment(startDateParam, 'DD-MM-YYYY');
var end = moment(endDateParam, 'DD-MM-YYYY');
// var start = moment().subtract(29, 'days');
// var end = moment();
function cb(start, end) {
$('#reportrange').html(start.format('D-MM-YYYY') + ' - ' + end.format('D-MM-YYYY'));
$('#startDate').val(start.format('DD-MM-YYYY'));
$('#endDate').val(end.format('DD-MM-YYYY'));
}
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
locale: {
format: 'DD-MM-YYYY'
},
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
'Last 7 Days': [moment().subtract(6, 'days'), moment()],
'Last 30 Days': [moment().subtract(29, 'days'), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month')
.endOf('month')
]
}
}, cb);
cb(start, end);
$('#clear-filters').on('click', function() {
// Reset all select dropdowns to the first option
$('#client_id').val('0').change();
$('#insurer_id').val('0').change();
$('#policy_type_id').val('0').change();
$('#date_type').val('0');
$('#issuer').val('0');
$('#date_div').hide()
// Reset the date range picker to default
$('#reportrange').data('daterangepicker').setStartDate(moment().subtract(29, 'days'));
$('#reportrange').data('daterangepicker').setEndDate(moment());
cb(start, end); // Update the displayed date range
});
});
function hideDateField(input = null) { function hideDateField(input = null) {
let val = $('#date_type').val(); let val = $('#date_type').val();

View File

@ -170,8 +170,10 @@ input:checked + .slider:before {
<div class="input-icon"> <div class="input-icon">
<input type="file" class="form-control" id="insurer_logo" name="insurer_logo" <input type="file" class="form-control" id="insurer_logo" name="insurer_logo"
accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();" accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();"
data-parsley-max-file-size="200" data-parsley-insurer-max-file-size="200"
data-parsley-file-extension="jpg,jpeg,png" data-parsley-insurer-file-extension="jpg,jpeg,png"
data-parsley-insurer-max-file-size-message="File size should not exceed 200KB."
data-parsley-insurer-file-extension-message="Only JPG, JPEG, PNG files are allowed."
data-parsley-errors-container="#logo_error_container"> data-parsley-errors-container="#logo_error_container">
<i class="mdi mdi-upload additional-icon"></i> <i class="mdi mdi-upload additional-icon"></i>
</div> </div>
@ -204,8 +206,8 @@ input:checked + .slider:before {
<script> <script>
$(document).ready(function() { $(document).ready(function() {
// Custom Parsley validator for file size // Custom Parsley validator for insurer logo file size
window.Parsley.addValidator('maxFileSize', { window.Parsley.addValidator('insurerMaxFileSize', {
validateString: function(value, maxSize, parsleyInstance) { validateString: function(value, maxSize, parsleyInstance) {
if (!window.FileReader) { if (!window.FileReader) {
alert('Your browser does not support FileReader API, please upgrade.'); alert('Your browser does not support FileReader API, please upgrade.');
@ -223,8 +225,8 @@ input:checked + .slider:before {
} }
}); });
// Custom Parsley validator for file extension // Custom Parsley validator for insurer logo file extension
window.Parsley.addValidator('fileExtension', { window.Parsley.addValidator('insurerFileExtension', {
validateString: function(value, requirement, parsleyInstance) { validateString: function(value, requirement, parsleyInstance) {
var file = parsleyInstance.$element[0].files[0]; var file = parsleyInstance.$element[0].files[0];
if (!file) { return true; } // No file, so validation passes if (!file) { return true; } // No file, so validation passes
@ -239,12 +241,16 @@ input:checked + .slider:before {
}); });
$('#insurer_logo').on('change', function() { $('#insurer_logo').on('change', function() {
PreviewImage(); PreviewImage();
}); });
$("#insurer_general_form").submit(function(events) { $("#insurer_general_form").submit(function(events) {
events.preventDefault(); events.preventDefault();
if (!validateInsurerLogoFile(true)) {
return;
}
// var isValid = $('#insurer_General_PrimaryKey').parsley().validate(); // var isValid = $('#insurer_General_PrimaryKey').parsley().validate();
var isValid = $('#insurer_general_form').parsley().validate(); var isValid = $('#insurer_general_form').parsley().validate();
@ -357,22 +363,22 @@ input:checked + .slider:before {
var file = fileInput.files[0]; var file = fileInput.files[0];
var fileName = file.name.toLowerCase(); var fileName = file.name.toLowerCase();
var parts = fileName.split('.'); var parts = fileName.split('.');
$('#logo_error_container').empty();
// VALIDATION: Extensions and Double Extensions (e.g. .php.jpeg) // VALIDATION: Extensions and Double Extensions (e.g. .php.jpeg)
var allowedExtensions = /(\.jpg|\.jpeg|\.png)$/i; var allowedExtensions = /(\.jpg|\.jpeg|\.png)$/i;
if (!allowedExtensions.exec(fileName) || parts.length > 2) { if (!allowedExtensions.exec(fileName) || parts.length > 2) {
toastr.error("Security violation: Invalid format or double extension.", "Blocked"); toastr.error("Security violation: Invalid format or double extension.", "Blocked");
fileInput.value = ""; // Clear the field resetInsurerLogoInput();
preview.src = defaultAvatar; // RESET PREVIEW
return; return;
} }
// VALIDATION: Size (200KB) // VALIDATION: Size (200KB)
if ((file.size / 1024) > 200) { if ((file.size / 1024) > 200) {
toastr.warning("File size exceeds 200 KB limit.", "Warning"); toastr.warning("File size exceeds 200 KB limit.", "Warning");
fileInput.value = ""; // Clear the field resetInsurerLogoInput();
preview.src = defaultAvatar; // RESET PREVIEW
return; return;
} }
@ -383,6 +389,47 @@ input:checked + .slider:before {
preview.src = oFREvent.target.result; preview.src = oFREvent.target.result;
}; };
} }
function resetInsurerLogoInput() {
var fileInput = document.getElementById("insurer_logo");
var preview = document.getElementById("uploadPreview");
fileInput.value = "";
preview.src = '<?= base_url() . "public/assets/images/avatar_2x.png" ?>';
$('#logo_error_container').empty();
}
function validateInsurerLogoFile(showToastr) {
var fileInput = document.getElementById("insurer_logo");
if (!fileInput.files || !fileInput.files[0]) {
return true;
}
var file = fileInput.files[0];
var fileName = file.name.toLowerCase();
var parts = fileName.split('.');
var allowedExtensions = /(\.jpg|\.jpeg|\.png)$/i;
if (!allowedExtensions.exec(fileName) || parts.length > 2) {
$('#logo_error_container').html('<ul class="parsley-errors-list filled"><li class="parsley-required">Only JPG, JPEG, PNG files are allowed.</li></ul>');
if (showToastr) {
toastr.warning("Only JPG, JPEG, PNG files are allowed.", "Invalid file type");
}
resetInsurerLogoInput();
return false;
}
if ((file.size / 1024) > 200) {
$('#logo_error_container').html('<ul class="parsley-errors-list filled"><li class="parsley-required">File size should not exceed 200KB.</li></ul>');
if (showToastr) {
toastr.warning("File size should not exceed 200KB.", "Invalid file size");
}
resetInsurerLogoInput();
return false;
}
$('#logo_error_container').empty();
return true;
}
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------

View File

@ -106,12 +106,17 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_name">Branch Name <span class="text-danger">*</span></label> <label for="branch_name">Branch Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" <input type="text" class="form-control" id="branch_name"
placeholder="Enter Branch Name" name="branch_name" required> placeholder="Enter Branch Name" name="branch_name" required
data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code <span class="text-danger">*</span></label> <label for="branch_code">Branch Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" <input type="text" class="form-control" id="branch_code"
placeholder="Enter Branch Code" name="branch_code" required> placeholder="Enter Branch Code" name="branch_code" required
data-parsley-pattern="^[a-zA-Z0-9_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
@ -141,7 +146,9 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="district">District <span class="text-danger">*</span></label> <label for="district">District <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" <input type="text" class="form-control" id="district"
placeholder="Enter District" name="district" required> placeholder="Enter District" name="district" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
</div> </div>
@ -150,11 +157,15 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_city">City <span class="text-danger">*</span></label> <label for="branch_city">City <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" <input type="text" class="form-control" id="branch_city"
placeholder="Enter City" name="city" required> placeholder="Enter City" name="city" required
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="pincode">Pincode <span class="text-danger">*</span></label> <label for="pincode">Pincode <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required maxlength="6" inputmode="numeric"> <input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required maxlength="6" inputmode="numeric"
data-parsley-pattern="^[0-9]{6}$"
data-parsley-pattern-message="Pincode must be exactly 6 digits.">
</div> </div>
</div> </div>
@ -185,19 +196,25 @@
<!-- <input type="hidden" name="primarykey[]" id="contact_id_1" value=""/> --> <!-- <input type="hidden" name="primarykey[]" id="contact_id_1" value=""/> -->
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="name">Name <span class="text-danger">*</span></label> <label for="name">Name <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required> <input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required
data-parsley-pattern="^[A-Za-z\\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="designation">Designation <span class="text-danger">*</span></label> <label for="designation">Designation <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="designation" required> <input value="" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="designation" required
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="email">Email <span class="text-danger">*</span></label> <label for="email">Email <span class="text-danger">*</span></label>
<input value="" type="email" data-parsley-type="email" data-parsley-trigger="change"class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required> <input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
@ -435,8 +452,11 @@
switch (key) { switch (key) {
case 'branch_name': case 'branch_name':
if (v.length < 3) return 'Branch Name must be at least 3 characters.';
if (!/^[a-zA-Z0-9\s_-]+$/.test(v)) return 'Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).';
return ''; return '';
case 'branch_code': case 'branch_code':
if (!/^[a-zA-Z0-9_-]+$/.test(v)) return 'Branch Code can contain letters, numbers, underscore (_) and hyphen (-).';
return ''; return '';
case 'address1': case 'address1':
return ''; return '';
@ -458,6 +478,7 @@
if (!contactNamePattern.test(v)) return 'Contact name is invalid Format'; if (!contactNamePattern.test(v)) return 'Contact name is invalid Format';
return ''; return '';
case 'designation': case 'designation':
if (!/^[A-Za-z0-9\-_\/ ]+$/.test(v)) return 'Designation may only contain letters, numbers, /, -, _ and spaces.';
return ''; return '';
case 'email': case 'email':
if (!emailPattern.test(v)) return 'Please enter a valid email format (e.g., name@domain.com).'; if (!emailPattern.test(v)) return 'Please enter a valid email format (e.g., name@domain.com).';
@ -946,19 +967,25 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Name<span class="text-danger">*</span></label> <label>Name<span class="text-danger">*</span></label>
<input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required> <input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required
data-parsley-pattern="^[A-Za-z\\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Designation<span class="text-danger">*</span></label> <label>Designation<span class="text-danger">*</span></label>
<input value="${contact ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" required> <input value="${contact ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" required
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Email<span class="text-danger">*</span></label> <label>Email<span class="text-danger">*</span></label>
<input value="${contact ? contact.email : ''}" type="email" data-parsley-type="email" data-parsley-trigger="change"class="form-control" placeholder="Enter Contact Email" name="email[]" required> <input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">

View File

@ -614,6 +614,7 @@ $isl_col_width_px = nhance_dt_column_widths_px($isl_header_labels, $isl_col_max_
</div> </div>
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
/**
const table = document.getElementById("insurer-statement-list-table"); const table = document.getElementById("insurer-statement-list-table");
// Create custom dropdown // Create custom dropdown
@ -690,6 +691,7 @@ $isl_col_width_px = nhance_dt_column_widths_px($isl_header_labels, $isl_col_max_
activeDropdown = null; activeDropdown = null;
} }
}); });
*/
}); });
</script> </script>

View File

@ -138,7 +138,9 @@ $kyc_col_width_px = nhance_dt_column_widths_px($kyc_header_labels, $kyc_col_max_
</div><!-- end col --> </div><!-- end col -->
</div> </div>
<!-- end row --> <!-- end row -->
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
const table = document.getElementById("kyc-list-table"); const table = document.getElementById("kyc-list-table");
@ -226,6 +228,7 @@ $kyc_col_width_px = nhance_dt_column_widths_px($kyc_header_labels, $kyc_col_max_
} }
}); });
}); });
*/
</script> </script>
<script> <script>

View File

@ -274,6 +274,99 @@
"closeButton": true, "closeButton": true,
}; };
</script> </script>
<script>
(function (window, document) {
var MAX_GLOBAL_UPLOAD_BYTES = 25 * 1024 * 1024; // 25 MB
function formatBytesToMb(bytes) {
return (bytes / (1024 * 1024)).toFixed(2);
}
function getFilesSizeFromInput(input) {
if (!input || !input.files || !input.files.length) {
return 0;
}
var total = 0;
for (var i = 0; i < input.files.length; i++) {
total += input.files[i].size || 0;
}
return total;
}
function getAllFileInputsScope(source) {
if (!source) {
return [];
}
if (source.matches && source.matches('form')) {
return source.querySelectorAll('input[type="file"]');
}
if (source.form) {
return source.form.querySelectorAll('input[type="file"]');
}
return document.querySelectorAll('input[type="file"]');
}
function getTotalPayloadBytes(source) {
var inputs = getAllFileInputsScope(source);
var total = 0;
for (var i = 0; i < inputs.length; i++) {
total += getFilesSizeFromInput(inputs[i]);
}
return total;
}
function showGlobalFileWarning(message) {
if (window.toastr && typeof window.toastr.warning === 'function') {
window.toastr.warning(message, 'Validation');
} else {
window.alert(message);
}
}
function validateGlobalUploadPayload(source) {
var totalPayloadBytes = getTotalPayloadBytes(source);
if (totalPayloadBytes > MAX_GLOBAL_UPLOAD_BYTES) {
showGlobalFileWarning(
'Total selected file size is ' +
formatBytesToMb(totalPayloadBytes) +
' MB. Allowed maximum is 25 MB.'
);
return false;
}
return true;
}
window.validateGlobalUploadPayload = validateGlobalUploadPayload;
document.addEventListener('change', function (event) {
var target = event.target;
if (!target || !target.matches || !target.matches('input[type="file"]')) {
return;
}
if (!validateGlobalUploadPayload(target)) {
target.value = '';
}
});
document.addEventListener(
'submit',
function (event) {
var form = event.target;
if (!form || !form.matches || !form.matches('form')) {
return;
}
if (!form.querySelector('input[type="file"]')) {
return;
}
if (!validateGlobalUploadPayload(form)) {
event.preventDefault();
event.stopPropagation();
}
},
true
);
})(window, document);
</script>
<script> <script>
window.__navPageName = "<?= esc($page_name ?? '') ?>"; window.__navPageName = "<?= esc($page_name ?? '') ?>";
window.__navUserName = "<?= esc(get_session_userdata()->first_name ?? 'NOT SET') ?>"; window.__navUserName = "<?= esc(get_session_userdata()->first_name ?? 'NOT SET') ?>";
@ -1453,35 +1546,6 @@ $(function(){
}); });
} }
function nhApplyMenuScrollLimit($menu, usableSpace) {
if (!$menu || !$menu.length) {
return;
}
var $items = $menu.children('.dropdown-item:visible, a:visible, button:visible');
var visibleItems = 3;
var fixedMenuMax = 0;
if ($items.length) {
$items.slice(0, visibleItems).each(function () {
fixedMenuMax += $(this).outerHeight(true) || 0;
});
}
if (!fixedMenuMax) {
fixedMenuMax = 132; // safe default for 3 items
}
fixedMenuMax += 14; // include menu paddings/borders
var viewportMax = Math.max(140, usableSpace - 12);
var finalMax = Math.max(132, Math.min(fixedMenuMax, viewportMax));
$menu.css({
maxHeight: finalMax + 'px',
overflowY: 'auto',
overflowX: 'hidden',
scrollBehavior: 'smooth',
overscrollBehavior: 'contain',
zIndex: '20050'
});
}
function nhNormalizeActionCells(tableApi) { function nhNormalizeActionCells(tableApi) {
if (!tableApi) { if (!tableApi) {
return; return;
@ -1584,12 +1648,16 @@ $(function(){
$dd.data('nh-auto-dropup', 1); $dd.data('nh-auto-dropup', 1);
} }
// Keep height capped to ~3 items and allow vertical scroll for extra actions. // Keep action menu fully expanded (no inner scroll).
if ($menu.length && menuHeight > 0) { if ($menu.length && menuHeight > 0) {
var usableSpace = openUp ? above : below; $menu.css({
nhApplyMenuScrollLimit($menu, usableSpace); maxHeight: '',
$menu.addClass('nh-action-menu-elevated'); overflowY: '',
$menu.scrollTop(0); overflowX: '',
scrollBehavior: '',
overscrollBehavior: '',
zIndex: '20050'
}).addClass('nh-action-menu-elevated');
} }
}); });

View File

@ -196,14 +196,15 @@
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="issuer">Issuer<span class="text-danger">*</span></label> <label for="issuer">Issuer<span class="text-danger">*</span></label>
<select class="form-control" id="issuer" name="issuer" required> <select class="form-control" id="issuer" name="issuer" required>
<option value="">Select Issuer</option> <option value='2' selected>Nhance</option>;
<?php
<!-- <?php
if (isset($issuer) && count($issuer)) { if (isset($issuer) && count($issuer)) {
foreach ($issuer as $key => $value) { foreach ($issuer as $key => $value) {
echo "<option value=" . $key . ">" . $value . "</option>"; echo "<option value=" . $key . ">" . $value . "</option>";
} }
} }
?> ?> -->
</select> </select>
</div> </div>
@ -229,14 +230,14 @@
<hr> <hr>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloverhide" style="display: none;">
<label for="client_id">Client<span class="text-danger">*</span></label> <label for="client_id">Client<span class="text-danger">*</span></label>
<select class="form-control" id="client_id" name="client_id"> <select class="form-control" id="client_id" name="client_id">
<option value="">Select Client</option> <option value="">Select Client</option>
</select> </select>
</div> </div>
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloverhide" style="display: none;">
<label for="client_branch_id">Branch<span class="text-danger">*</span></label> <label for="client_branch_id">Branch<span class="text-danger">*</span></label>
<select class="form-control" id="client_branch_id" name="client_branch_id" <select class="form-control" id="client_branch_id" name="client_branch_id"
onchange="getBranchData(this,1)"> onchange="getBranchData(this,1)">
@ -343,7 +344,7 @@
placeholder="Enter Branch Code" required> placeholder="Enter Branch Code" required>
</div> </div>
<div class="form-group col-md-4 renewalFields"> <div class="form-group col-md-4 renewalFields rolloverhide">
<label for="contact_person_summary">Contact Person<span class="text-danger">*</span></label> <label for="contact_person_summary">Contact Person<span class="text-danger">*</span></label>
<select class="form-control" name="contact_person_summary" id="contact_person_summary"> <select class="form-control" name="contact_person_summary" id="contact_person_summary">
<option value="">Select a Contact</option> <option value="">Select a Contact</option>
@ -541,8 +542,8 @@
var lead_type = $(this).val(); var lead_type = $(this).val();
var increment = 1; // Example increment value (modify as needed) var increment = 1; // Example increment value (modify as needed)
var start_date_id = (lead_type == "1" || lead_type == "3") ? `policy_start_date_${increment}` : "policy_start_date"; var start_date_id = (lead_type == "1") ? `policy_start_date_${increment}` : "policy_start_date";
var end_date_id = (lead_type == "1" || lead_type == "3") ? `policy_end_date_${increment}` : "policy_end_date"; var end_date_id = (lead_type == "1") ? `policy_end_date_${increment}` : "policy_end_date";
$(".policy_start_date").attr("id", start_date_id); $(".policy_start_date").attr("id", start_date_id);
// $("label[for]").attr("for", start_date_id); // $("label[for]").attr("for", start_date_id);
@ -553,7 +554,7 @@
// $('#leads_form_id')[0].reset(); // $('#leads_form_id')[0].reset();
// console.log("Updated ID:", newId); // console.log("Updated ID:", newId);
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
var policy_start_datePicker = flatpickr("#policy_start_date_" + increment, { var policy_start_datePicker = flatpickr("#policy_start_date_" + increment, {
dateFormat: "d/m/Y", dateFormat: "d/m/Y",
@ -561,8 +562,7 @@
onChange: function(selectedDates) { onChange: function(selectedDates) {
var policy_end_date = new Date(selectedDates[0]); var policy_end_date = new Date(selectedDates[0]);
policy_end_date.setFullYear(policy_end_date.getFullYear() + 1); policy_end_date.setFullYear(policy_end_date.getFullYear() + 1);
policy_end_date.setDate(policy_end_date.getDate() - policy_end_date.setDate(policy_end_date.getDate() - 1); // Set end date to last day of selected year
1); // Set end date to last day of selected year
policy_end_datePicker.setDate(policy_end_date); policy_end_datePicker.setDate(policy_end_date);
// console.log('this object', this); // console.log('this object', this);
@ -585,7 +585,7 @@
// } // }
} }
}); });
} else if (lead_type != 1 && lead_type != 3) { } else if (lead_type == 2) {
$("#source_policy_id").prop("required", true); $("#source_policy_id").prop("required", true);
$("#source_policy_start_date").prop("required", true); $("#source_policy_start_date").prop("required", true);
$("#source_policy_end_date").prop("required", true); $("#source_policy_end_date").prop("required", true);
@ -624,7 +624,7 @@
} }
if (lead_type != 1 && lead_type != 3) { if (lead_type != 1) {
dataIncrement = 1; dataIncrement = 1;
// updateRenewalFields(dataIncrement); // updateRenewalFields(dataIncrement);
@ -689,6 +689,17 @@
//------------------------------ GET DATA ( EDIT, BRANCH, POLICY ) --------------------------------------------------------------------------- //------------------------------ GET DATA ( EDIT, BRANCH, POLICY ) ---------------------------------------------------------------------------
//view and edit Lead data function ( NOT IN USE DON'T DELETE ) //view and edit Lead data function ( NOT IN USE DON'T DELETE )
function togglePolicyTypeDivider(dataIncrement) {
var $policyType = $('#policy_type_id_' + dataIncrement);
var selectedPolicyText = ($policyType.find('option:selected').text() || '').toLowerCase();
var isGmcPolicy = selectedPolicyText.indexOf('gmc') !== -1;
var $policyDivider = $('#appendArea_' + dataIncrement).find('hr').first();
if ($policyDivider.length) {
$policyDivider.toggle(!isGmcPolicy);
}
}
function getLeadsDataForEdit(input) { function getLeadsDataForEdit(input) {
$('.loader').fadeIn(); $('.loader').fadeIn();
@ -718,6 +729,7 @@
if (typeof window.refreshLeadsFormValidation === 'function') { if (typeof window.refreshLeadsFormValidation === 'function') {
window.refreshLeadsFormValidation(); window.refreshLeadsFormValidation();
} }
togglePolicyTypeDivider(dataIncrement);
let policy_type_id = res.data.policy_type_id; let policy_type_id = res.data.policy_type_id;
let lead_type = res.data.lead_type; let lead_type = res.data.lead_type;
@ -732,12 +744,9 @@
leadTypeBsedHideAndShow(lead_type) leadTypeBsedHideAndShow(lead_type)
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
$('.claim-row').hide(); $('.claim-row').hide();
} else { } else {
$('.claim-row').show(); $('.claim-row').show();
if (policy_type_id == 1) { if (policy_type_id == 1) {
$('.gpaClaimFileds').show(); $('.gpaClaimFileds').show();
@ -745,50 +754,50 @@
} else if (policy_type_id == 6 || policy_type_id == 7) { } else if (policy_type_id == 6 || policy_type_id == 7) {
$('.gpaClaimFileds').hide(); $('.gpaClaimFileds').hide();
$('.lifeClaimFields').show(); $('.lifeClaimFields').show();
} else {
// updateRenewalFields(dataIncrement);
// let incurred_claim_date_id = 'incurred_claim_date_' + dataIncrement;
let incurred_claim_date_id = 'incurred_claim_date';
var incurred_claim_datepicker = flatpickr("#" + incurred_claim_date_id, {
dateFormat: "d/m/Y",
allowInput: false,
onChange: function(selectedDates) {
console.log('Flatpickr instance:', this);
console.log('ID of this element:', this.input.id);
// Extract the increment value from the element's ID
let increment = this.input.id.split('_').pop();
console.log('Extracted increment:', increment);
let lead_type = $('#lead_type').val();
var policyStartDate = $("#source_policy_start_date");
if (lead_type == 3) {
policyStartDate = $("#policy_start_date");
}
console.log('Selected Dates:', selectedDates);
console.log('policy start date instance', policyStartDate)
console.log('Policy Start Date:', policyStartDate.val());
// Recalculate policy_run_days if policy start date is already selected
// if (policyStartDate.val()) {
// calculatePolicyRunDays(increment);
// }
}
});
// var premium_date_datepicker = flatpickr("#" + premium_date_id, {
// dateFormat: "d/m/Y",
// allowInput: false
// });
$('#proposed_insurer_' + dataIncrement).select2();
$('#proposed_tpa_' + dataIncrement).select2();
} }
} }
if (lead_type != 1 && policy_type_id != 1 && policy_type_id != 6 && policy_type_id != 7) {
// updateRenewalFields(dataIncrement);
// let incurred_claim_date_id = 'incurred_claim_date_' + dataIncrement;
let incurred_claim_date_id = 'incurred_claim_date';
var incurred_claim_datepicker = flatpickr("#" + incurred_claim_date_id, {
dateFormat: "d/m/Y",
allowInput: false,
onChange: function(selectedDates) {
console.log('Flatpickr instance:', this);
console.log('ID of this element:', this.input.id);
// Extract the increment value from the element's ID
let increment = this.input.id.split('_').pop();
console.log('Extracted increment:', increment);
let lead_type = $('#lead_type').val();
var policyStartDate = $("#source_policy_start_date");
if (lead_type == 3) {
policyStartDate = $("#policy_start_date");
}
console.log('Selected Dates:', selectedDates);
console.log('policy start date instance', policyStartDate)
console.log('Policy Start Date:', policyStartDate.val());
// Recalculate policy_run_days if policy start date is already selected
// if (policyStartDate.val()) {
// calculatePolicyRunDays(increment);
// }
}
});
// var premium_date_datepicker = flatpickr("#" + premium_date_id, {
// dateFormat: "d/m/Y",
// allowInput: false
// });
$('#proposed_insurer_' + dataIncrement).select2();
$('#proposed_tpa_' + dataIncrement).select2();
}
hide_list_show_add(); hide_list_show_add();
pageTitle = 'Edit Opportunities - (EB)'; pageTitle = 'Edit Opportunities - (EB)';
@ -1105,6 +1114,7 @@
if (typeof window.refreshLeadsFormValidation === 'function') { if (typeof window.refreshLeadsFormValidation === 'function') {
window.refreshLeadsFormValidation(); window.refreshLeadsFormValidation();
} }
togglePolicyTypeDivider(dataIncrement);
console.log("Policy Type ID : ", policy_type_id); console.log("Policy Type ID : ", policy_type_id);
if (policy_type_id == 1 || policy_type_id == 6 || policy_type_id == 7) { if (policy_type_id == 1 || policy_type_id == 6 || policy_type_id == 7) {
@ -1118,12 +1128,9 @@
leadTypeBsedHideAndShow(lead_type) leadTypeBsedHideAndShow(lead_type)
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
$('.claim-row').hide(); $('.claim-row').hide();
} else { } else {
$('.claim-row').show(); $('.claim-row').show();
if (policy_type_id == 1) { if (policy_type_id == 1) {
@ -1132,47 +1139,47 @@
} else if (policy_type_id == 6 || policy_type_id == 7) { } else if (policy_type_id == 6 || policy_type_id == 7) {
$('.gpaClaimFileds').hide(); $('.gpaClaimFileds').hide();
$('.lifeClaimFields').show(); $('.lifeClaimFields').show();
} else {
if (lead_type == 1 || lead_type == 3) {
updateRenewalFields(dataIncrement);
}
// let incurred_claim_date_id = 'incurred_claim_date_' + dataIncrement;
let incurred_claim_date_id = 'incurred_claim_date';
var incurred_claim_datepicker = flatpickr("#" + incurred_claim_date_id, {
dateFormat: "d/m/Y",
allowInput: false,
onChange: function(selectedDates) {
console.log('Flatpickr instance:', this);
console.log('ID of this element:', this.input.id);
// Extract the increment value from the element's ID
let increment = this.input.id.split('_').pop();
console.log('Extracted increment:', increment);
var policyStartDate = $("#source_policy_start_date");
if (lead_type == 3) {
policyStartDate = $("#policy_start_date");
}
console.log('Selected Dates:', selectedDates);
console.log('policy start date instance', policyStartDate)
console.log('Policy Start Date:', policyStartDate.val());
// Recalculate policy_run_days if policy start date is already selected
// if (policyStartDate.val()) {
// calculatePolicyRunDays(increment);
// }
}
});
$('#proposed_insurer_' + dataIncrement).select2();
$('#proposed_tpa_' + dataIncrement).select2();
} }
} }
if (lead_type != 1 && policy_type_id != 1 && policy_type_id != 6 && policy_type_id != 7) {
if (lead_type == 1) {
updateRenewalFields(dataIncrement);
}
// let incurred_claim_date_id = 'incurred_claim_date_' + dataIncrement;
let incurred_claim_date_id = 'incurred_claim_date';
var incurred_claim_datepicker = flatpickr("#" + incurred_claim_date_id, {
dateFormat: "d/m/Y",
allowInput: false,
onChange: function(selectedDates) {
console.log('Flatpickr instance:', this);
console.log('ID of this element:', this.input.id);
// Extract the increment value from the element's ID
let increment = this.input.id.split('_').pop();
console.log('Extracted increment:', increment);
var policyStartDate = $("#source_policy_start_date");
if (lead_type == 3) {
policyStartDate = $("#policy_start_date");
}
console.log('Selected Dates:', selectedDates);
console.log('policy start date instance', policyStartDate)
console.log('Policy Start Date:', policyStartDate.val());
// Recalculate policy_run_days if policy start date is already selected
// if (policyStartDate.val()) {
// calculatePolicyRunDays(increment);
// }
}
});
$('#proposed_insurer_' + dataIncrement).select2();
$('#proposed_tpa_' + dataIncrement).select2();
}
} else { } else {
console.log(response.message, 'WARNING'); console.log(response.message, 'WARNING');
} }
@ -1274,7 +1281,7 @@
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="policy_start_date">Date of Commencement <span class="text-danger">*</span></label> <label for="policy_start_date">Date of Commencement <span class="text-danger">*</span></label>
<div class="input-icon"> <div class="input-icon">
<input type="text" class="form-control policy_start_date" id="policy_start_date_${increment}" name="policy_start_date[]" placeholder="Enter DOC" onchange="calculatePolicyMetrics(this)"> <input type="text" class="form-control policy_start_date" id="policy_start_date_${increment}" name="policy_start_date[]" placeholder="Enter DOC" onchange="calculatePolicyMetrics(this)" autocomplete="off" >
<i class="mdi mdi-calendar-blank-outline additional-icon"></i> <i class="mdi mdi-calendar-blank-outline additional-icon"></i>
</div> </div>
@ -1283,7 +1290,7 @@
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="policy_end_date">Date of Expiry <span class="text-danger">*</span></label> <label for="policy_end_date">Date of Expiry <span class="text-danger">*</span></label>
<div class="input-icon"> <div class="input-icon">
<input type="text" class="form-control policy_end_date" id="policy_end_date_${increment}" name="policy_end_date[]" placeholder="Enter DOE"> <input type="text" class="form-control policy_end_date" id="policy_end_date_${increment}" name="policy_end_date[]" placeholder="Enter DOE" autocomplete="off">
<i class="mdi mdi-calendar-blank-outline additional-icon"></i> <i class="mdi mdi-calendar-blank-outline additional-icon"></i>
</div> </div>
</div> </div>
@ -1338,7 +1345,7 @@
// $(".policy_end_date").attr("id", end_date_id); // $(".policy_end_date").attr("id", end_date_id);
// Initialize date pickers // Initialize date pickers
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
var policy_start_datePicker = flatpickr("#policy_start_date_" + increment, { var policy_start_datePicker = flatpickr("#policy_start_date_" + increment, {
dateFormat: "d/m/Y", dateFormat: "d/m/Y",
@ -1552,7 +1559,7 @@
console.log('Lead Type:', lead_type); console.log('Lead Type:', lead_type);
let increment = input.id.split('_').pop(); // Extract increment let increment = input.id.split('_').pop(); // Extract increment
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
return; return;
} }
@ -1670,7 +1677,7 @@
var lead_type = $('#lead_type').val(); var lead_type = $('#lead_type').val();
if (lead_type == 1 || lead_type == 3) { if (lead_type == 1) {
let formRow = input.closest('.form-row'); let formRow = input.closest('.form-row');
@ -1911,6 +1918,7 @@
onChange: function(selectedDates) { onChange: function(selectedDates) {
try { try {
let increment = this.input.id.split('_').pop(); let increment = this.input.id.split('_').pop();
console.log('Incurred claim date changed:', selectedDates);
let policyStartDate = $("#source_policy_start_date"); let policyStartDate = $("#source_policy_start_date");
if (policyStartDate.val()) { if (policyStartDate.val()) {
calculatePolicyRunDays(increment); calculatePolicyRunDays(increment);
@ -2288,7 +2296,7 @@
function leadTypeBsedHideAndShow(value, resetValues = false) { function leadTypeBsedHideAndShow(value, resetValues = false) {
if (value == 1 || value == 3) { if (value == 1) {
$('.btnDiv').show(); $('.btnDiv').show();
$('.claim-row').hide(); $('.claim-row').hide();
@ -2304,6 +2312,56 @@
// $('.proposed_div').hide().find('select, input').removeAttr('required'); // $('.proposed_div').hide().find('select, input').removeAttr('required');
if (resetValues) {
$('#gst').val('');
$('#pan').val('');
$('#branch_name').val('');
$('#branch_code').val('');
$('#contact_person_name').val('');
$('#contact_person_mobile').val('');
$('#contact_person_email').val('');
$('#client_type').val('');
$('#client_name').val('');
$('#client_short_name').val('');
$('#entity_type_id').val('');
}
$('#exixting_client').removeAttr('required');
} else if (value == 3) {
$('.btnDiv').hide();
$('.claim-row').show();
$('.emp_title_text').text('No of Employees at Inception')
$('.depnd_title_text').text(' No of Dependents at Inception')
$('.total_title_text').text('Total Lives at Inception')
$('.freshFields').find('select, input').attr('required', 'required');
$('.freshFields').show();
$('.rolloOverFields').find('select, input').attr('required', 'required');
$('.renewalFields').show();
$('#source_policy_id').hide();
$('#source_policy_start_date').hide();
$('#source_policy_end_date').hide();
$('#source_policy_id').closest('.form-group').hide();
$('#source_policy_start_date').closest('.form-group').hide();
$('#source_policy_end_date').closest('.form-group').hide();
$('.source_policy_id').find('select, input').attr('required', 'required');
$('.source_policy_start_date').find('select, input').attr('required', 'required');
$('.source_policy_end_date').find('select, input').attr('required', 'required');
$('.rolloverhide').hide();
if (resetValues) { if (resetValues) {
$('#gst').val(''); $('#gst').val('');

View File

@ -935,6 +935,30 @@ if (isset($selected_lead_type)) {
} }
} }
if(lead_type == 3){
let incurred_claim_date_id = 'incurred_claim_date';
if ($('#' + incurred_claim_date_id).length) {
flatpickr("#" + incurred_claim_date_id, {
dateFormat: "d/m/Y",
allowInput: false,
onChange: function (selectedDates) {
try {
let increment = this.input.id.split('_').pop();
let policyStartDate = $("#source_policy_start_date");
if (policyStartDate.val()) {
calculatePolicyRunDays(increment);
}
} catch (error) {
console.error('Error in incurred_claim_datepicker:', error);
}
}
});
} else {
console.warn(`Incurred claim date field #${incurred_claim_date_id} not found.`);
}
}
// if (lead_type == 3) { // if (lead_type == 3) {
// $('#client_id').prepend($('<option>', { // $('#client_id').prepend($('<option>', {

View File

@ -13,16 +13,16 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="client_name">Client Name<span class="text-danger">*</span></label> <label for="client_name">Client Name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="client_name" name="client_name" required> <input type="text" class="form-control" id="client_name" name="client_name" onkeypress="return restrictCharacters(event, /[a-zA-Z0-9 ,\\/_-]/)" required>
</div> </div>
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="short_name">Client Short name<span class="text-danger">*</span></label> <label for="short_name">Client Short name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="short_name" name="short_name" onkeyup="validateInputForClient(this, 'clients', 'short_name')" required> <input type="text" class="form-control" id="short_name" name="short_name" onkeyup="validateInputForClient(this, 'clients', 'short_name')" onkeypress="return restrictCharacters(event, /[a-zA-Z0-9,\\/_-]/)" required>
</div> </div>
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="cost_center">PAN</label> <label for="cost_center">PAN</label>
<input type="text" class="form-control" id="pan" placeholder="Enter PAN No" name="pan" onchange="validateInputForClient(this, 'clients', 'pan')"> <input type="text" class="form-control" id="pan" placeholder="Enter PAN No" name="pan" onchange="validateInputForClient(this, 'clients', 'pan')" onkeypress="return restrictCharacters(event, /[A-Z0-9]/)" oninput="this.value = this.value.toUpperCase()">
</div> </div>
</div> </div>
@ -48,7 +48,7 @@
</div> </div>
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="aadhar">Aadhar</label> <label for="aadhar">Aadhar</label>
<input type="text" class="form-control" id="aadhar" placeholder="Enter Aadher No" name="aadhar" maxlength="12" onchange="validateInputForClient(this, 'clients', 'aadhar')"> <input type="text" class="form-control" id="aadhar" placeholder="Enter Aadher No" name="aadhar" maxlength="12" onchange="validateInputForClient(this, 'clients', 'aadhar')" onkeypress="return onlyNumbers(event)">
</div> </div>
</div> </div>
@ -72,17 +72,17 @@
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="client_name">Branch Name<span class="text-danger">*</span></label> <label for="client_name">Branch Name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" name="branch_name" required> <input type="text" class="form-control" id="branch_name" name="branch_name" onkeypress="return restrictCharacters(event, /[a-zA-Z0-9 ,\\/_-]/)" required>
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code<span class="text-danger">*</span></label> <label for="branch_code">Branch Code<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" name="branch_code" required> <input type="text" class="form-control" id="branch_code" name="branch_code" onkeypress="return restrictCharacters(event, /[a-zA-Z0-9,\\/_-]/)" required>
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Name<span class="text-danger">*</span></label> <label for="branch_code">Name<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="name" name="name" required> <input type="text" class="form-control" id="name" name="name" onkeypress="return restrictCharacters(event, /[a-zA-Z\s]/)" required>
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
@ -97,7 +97,7 @@
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="gst">GST<span class="text-danger">*</span></label> <label for="gst">GST<span class="text-danger">*</span></label>
<input type="text" class="form-control" id="gst" placeholder="Enter GST Number" oninput="validateInputForClient(this, 'client_branch', 'gst')" <input type="text" class="form-control" id="gst" placeholder="Enter GST Number" oninput="validateInputForClient(this, 'client_branch', 'gst')"
data-parsley-error-message="Invalid GST Number. Example: 12ABCDE1234F5Z6" name="gst" data-parsley-trigger="change" data-parsley-pattern="^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1}$" required> data-parsley-error-message="Invalid GST Number. Example: 12ABCDE1234F5Z6" name="gst" data-parsley-trigger="change" data-parsley-pattern="^\d{2}[A-Z]{5}\d{4}[A-Z]{1}[A-Z\d]{1}[Z]{1}[A-Z\d]{1}$" onkeypress="return restrictCharacters(event, /[A-Z0-9]/)" oninput="this.value = this.value.toUpperCase()" required>
</div> </div>
</div> </div>
@ -116,6 +116,34 @@
let isGSTValidating = false; let isGSTValidating = false;
let isGSTValid = false; let isGSTValid = false;
function restrictCharacters(event, pattern) {
// Allow control keys (Backspace, Tab, Enter, etc.) which have charCode < 32
// or are navigation keys.
if (event.which < 32 || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Delete" || event.key === "Backspace" || event.key === "Tab") {
return true;
}
const char = String.fromCharCode(event.which);
if (!pattern.test(char)) {
event.preventDefault();
return false;
}
return true;
}
function onlyNumbers(event) {
const charCode = (event.which) ? event.which : event.keyCode;
// Allow control keys
if (event.which < 32 || event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Delete" || event.key === "Backspace" || event.key === "Tab") {
return true;
}
// Allow numbers 0-9
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
event.preventDefault();
return false;
}
return true;
}
function validateInputForClient(input, table, field) { function validateInputForClient(input, table, field) {
let owner_type = $('#Owner_type').val(); let owner_type = $('#Owner_type').val();

View File

@ -367,6 +367,7 @@ table.dataTable thead th {
<?php include('policy_transaction_endorsement_form_2.php'); ?> <?php include('policy_transaction_endorsement_form_2.php'); ?>
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("tickets-table"); const table = document.getElementById("tickets-table");
@ -446,6 +447,7 @@ table.dataTable thead th {
} }
}); });
}); });
*/
</script> </script>
<script> <script>
var client_list = ''; var client_list = '';

View File

@ -426,7 +426,7 @@ table.dataTable tbody td {
function closeFilterNav() { function closeFilterNav() {
document.getElementById("filter-sidebar").style.width = "0"; document.getElementById("filter-sidebar").style.width = "0";
} }
/**
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
const table = document.getElementById("tickets-table"); const table = document.getElementById("tickets-table");
@ -518,6 +518,7 @@ document.addEventListener("DOMContentLoaded", function () {
} }
}); });
}); });
*/
</script> </script>
<script> <script>

View File

@ -195,6 +195,7 @@ $pt_col_width_px = nhance_dt_column_widths_px($pt_header_labels, $pt_col_max_len
<!-- end row --> <!-- end row -->
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("policy-type-list-table"); const table = document.getElementById("policy-type-list-table");
@ -276,6 +277,7 @@ $pt_col_width_px = nhance_dt_column_widths_px($pt_header_labels, $pt_col_max_len
} }
}); });
}); });
*/
</script> </script>

View File

@ -233,6 +233,7 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
<input type="file" class="form-control" name="aadhar_file_name" id="aadhar_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation> <input type="file" class="form-control" name="aadhar_file_name" id="aadhar_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
<i class="mdi mdi-upload additional-icon"></i> <i class="mdi mdi-upload additional-icon"></i>
</div> </div>
<small id="aadhar_file_name_display" class="text-muted d-block" style="display:none !important;"></small>
<small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small> <small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
@ -241,6 +242,7 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
<input type="file" class="form-control" name="pan_file_name" id="pan_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation> <input type="file" class="form-control" name="pan_file_name" id="pan_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
<i class="mdi mdi-upload additional-icon"></i> <i class="mdi mdi-upload additional-icon"></i>
</div> </div>
<small id="pan_file_name_display" class="text-muted d-block" style="display:none !important;"></small>
<small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small> <small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small>
</div> </div>
<div class="form-group col-md-4"> <div class="form-group col-md-4">
@ -249,6 +251,7 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
<input type="file" class="form-control" name="certificate_file_name" id="certificate_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation> <input type="file" class="form-control" name="certificate_file_name" id="certificate_file_name" accept=".pdf,.jpg,.jpeg,.png" data-parsley-file-validation>
<i class="mdi mdi-upload additional-icon"></i> <i class="mdi mdi-upload additional-icon"></i>
</div> </div>
<small id="certificate_file_name_display" class="text-muted d-block" style="display:none !important;"></small>
<small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small> <small class="text-muted d-block">Allowed: PDF, PNG, JPG, JPEG.</small>
</div> </div>
</div> </div>
@ -433,11 +436,17 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
}, },
error: function (xhr) { error: function (xhr) {
$('.loader, .loader-mask').fadeOut(); $('.loader, .loader-mask').fadeOut();
let response = null;
try {
response = xhr.responseText ? JSON.parse(xhr.responseText) : null;
} catch (e) {
response = null;
}
if (xhr.status === 400) { if (xhr.status === 400) {
let response = JSON.parse(xhr.responseText);
let errorMessages = ""; let errorMessages = "";
let seenMessages = []; // Array to store unique messages let seenMessages = []; // Array to store unique messages
if (response.errors) { if (response && response.errors) {
$.each(response.errors, function (field, message) { $.each(response.errors, function (field, message) {
if (!seenMessages.includes(message)) { if (!seenMessages.includes(message)) {
errorMessages += `• ${message}<br>`; errorMessages += `• ${message}<br>`;
@ -446,16 +455,15 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
}); });
toastr.error(errorMessages, 'Validation Error', { "allowHtml": true }); toastr.error(errorMessages, 'Validation Error', { "allowHtml": true });
} else { } else {
toastr.warning(response.message || 'Validation failed', 'Warning'); toastr.warning((response && response.message) ? response.message : 'Validation failed', 'Warning');
} }
} else if (xhr.status === 403) { } else if (xhr.status === 403) {
let response = JSON.parse(xhr.responseText); toastr.error((response && response.message) ? response.message : 'Security policy error', 'Security Policy');
toastr.error(response.message, 'Security Policy');
} else if (xhr.status === 500) { } else if (xhr.status === 500) {
toastr.error('Something went wrong . Please try again later.', 'Server Error'); toastr.error((response && response.message) ? response.message : 'Something went wrong . Please try again later.', 'Server Error');
} else { } else {
toastr.error('An unexpected error occurred. Please try again later.', 'Error'); toastr.error((response && response.message) ? response.message : 'An unexpected error occurred. Please try again later.', 'Error');
} }
console.error('Unexpected error:', xhr.responseText); console.error('Unexpected error:', xhr.responseText);
@ -470,9 +478,32 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
$('#partnerPOSForm').parsley().reset(); $('#partnerPOSForm').parsley().reset();
} }
$('#manager_id').val(null).trigger('change'); $('#manager_id').val(null).trigger('change');
updateFileNameDisplay('#aadhar_file_name', '#aadhar_file_name_display', '');
updateFileNameDisplay('#pan_file_name', '#pan_file_name_display', '');
updateFileNameDisplay('#certificate_file_name', '#certificate_file_name_display', '');
} }
function updateFileNameDisplay(inputSelector, displaySelector, existingName = '') {
const $display = $(displaySelector);
let fileName = '';
if (existingName && String(existingName).trim() !== '') {
fileName = String(existingName).trim();
} else {
const inputEl = $(inputSelector)[0];
if (inputEl && inputEl.files && inputEl.files.length > 0) {
fileName = inputEl.files[0].name || '';
}
}
if (fileName) {
$display.text('Uploaded: ' + fileName).show();
} else {
$display.text('').hide();
}
}
function appendEditData(data){ function appendEditData(data){
$('#pos_id').val(data.id); $('#pos_id').val(data.id);
@ -481,14 +512,12 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
$('#mobile').val(data.mobile); $('#mobile').val(data.mobile);
$('#pos_code').val(data.pos_code); $('#pos_code').val(data.pos_code);
// Instead of setting the file input
$('#current_file_name').text(data['certificate_file_name'] || 'No file uploaded');
$('#aadhar').val(data.aadhar); $('#aadhar').val(data.aadhar);
$('#aadhar_file_name').text(data['aadhar_file_name'] || 'No file uploaded'); updateFileNameDisplay('#aadhar_file_name', '#aadhar_file_name_display', data['aadhar_file_name'] || '');
$('#pan').val(data.pan); $('#pan').val(data.pan);
$('#pan_file_name').text(data['pan_file_name'] || 'No file uploaded'); updateFileNameDisplay('#pan_file_name', '#pan_file_name_display', data['pan_file_name'] || '');
updateFileNameDisplay('#certificate_file_name', '#certificate_file_name_display', data['certificate_file_name'] || '');
$('#bank_name').val(data.bank_name); $('#bank_name').val(data.bank_name);
$('#account_holder_name').val(data.account_holder_name); $('#account_holder_name').val(data.account_holder_name);
@ -508,6 +537,18 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
}); });
} }
$('#aadhar_file_name').on('change', function () {
updateFileNameDisplay('#aadhar_file_name', '#aadhar_file_name_display');
});
$('#pan_file_name').on('change', function () {
updateFileNameDisplay('#pan_file_name', '#pan_file_name_display');
});
$('#certificate_file_name').on('change', function () {
updateFileNameDisplay('#certificate_file_name', '#certificate_file_name_display');
});
$('#aadhar').on('input', function () { $('#aadhar').on('input', function () {
this.value = this.value.replace(/[^0-9]/g, ''); this.value = this.value.replace(/[^0-9]/g, '');
@ -598,6 +639,7 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
</script> </script>
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("pos-list-table"); const table = document.getElementById("pos-list-table");
@ -685,4 +727,5 @@ $pos_col_width_px = nhance_dt_column_widths_px($pos_header_labels, $pos_col_max_
} }
}); });
}); });
*/
</script> </script>

View File

@ -5,75 +5,75 @@
<div class="form-row renewalCalculation"> <div class="form-row renewalCalculation">
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="incurred_claim_date">Incurred Claim Date<span class="text-danger">*</span></label> <label for="incurred_claim_date">Incurred Claim Date<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['incurred_claims_date']) ? $lead_edit_data['incurred_claims_date'] : '' ?>" type="text" class="form-control incurred_claim" id="incurred_claim_date<?= $increment ?>" <input value="<?= isset($lead_edit_data['incurred_claims_date']) ? $lead_edit_data['incurred_claims_date'] : '' ?>" type="text" class="form-control incurred_claim" id="incurred_claim_date<?= $increment ?>"
name="incurred_claim_date[]" placeholder="Enter DOE" oninput="calculatePolicyMetrics(this)"> name="incurred_claim_date[]" placeholder="Enter DOE" oninput="calculatePolicyMetrics(this)">
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="paid_claims">Paid Claims<span class="text-danger">*</span></label> <label for="paid_claims">Paid Claims<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['paid_claims']) ? $lead_edit_data['paid_claims'] : '' ?>" type="text" class="form-control" id="paid_claims<?= $increment ?>" name="paid_claims[]" <input value="<?= isset($lead_edit_data['paid_claims']) ? $lead_edit_data['paid_claims'] : '' ?>" type="text" class="form-control" id="paid_claims<?= $increment ?>" name="paid_claims[]"
placeholder="Enter Paid Claims" oninput="calculatePolicyMetrics(this)"> placeholder="Enter Paid Claims" oninput="calculatePolicyMetrics(this)">
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="outstanding_claims">Outstanding Claims<span class="text-danger">*</span></label> <label for="outstanding_claims">Outstanding Claims<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['outstanding_claims']) ? $lead_edit_data['outstanding_claims'] : '' ?>" type="text" class="form-control" id="outstanding_claims<?= $increment ?>" name="outstanding_claims[]" <input value="<?= isset($lead_edit_data['outstanding_claims']) ? $lead_edit_data['outstanding_claims'] : '' ?>" type="text" class="form-control" id="outstanding_claims<?= $increment ?>" name="outstanding_claims[]"
placeholder="Enter Outstanding Claims" oninput="calculatePolicyMetrics(this)"> placeholder="Enter Outstanding Claims" oninput="calculatePolicyMetrics(this)">
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="incurred_claims">Incurred Claim<span class="text-danger">*</span></label> <label for="incurred_claims">Incurred Claim<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['incurred_claims']) ? $lead_edit_data['incurred_claims'] : '' ?>" type="text" class="form-control" id="incurred_claims<?= $increment ?>" name="incurred_claims[]" <input value="<?= isset($lead_edit_data['incurred_claims']) ? $lead_edit_data['incurred_claims'] : '' ?>" type="text" class="form-control" id="incurred_claims<?= $increment ?>" name="incurred_claims[]"
placeholder="Enter Incurred Claim" oninput="calculatePolicyMetrics(this)" readonly> placeholder="Enter Incurred Claim" oninput="calculatePolicyMetrics(this)" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="policy_run_days">Policy Run Days<span class="text-danger">*</span></label> <label for="policy_run_days">Policy Run Days<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['policy_run_days']) ? $lead_edit_data['policy_run_days'] : '' ?>" type="text" class="form-control" id="policy_run_days<?= $increment ?>" name="policy_run_days[]" <input value="<?= isset($lead_edit_data['policy_run_days']) ? $lead_edit_data['policy_run_days'] : '' ?>" type="text" class="form-control" id="policy_run_days<?= $increment ?>" name="policy_run_days[]"
placeholder="Enter Policy Run Days" oninput="calculatePolicyMetrics(this)" readonly> placeholder="Enter Policy Run Days" oninput="calculatePolicyMetrics(this)" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="premium_at_inception">Premium Paid at Inception<span <label for="premium_at_inception">Premium Paid at Inception<span
class="text-danger">*</span></label> class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['premium_at_inception']) ? $lead_edit_data['premium_at_inception'] : '' ?>" type="text" class="form-control" id="premium_at_inception<?= $increment ?>" name="premium_at_inception[]" <input value="<?= isset($lead_edit_data['premium_at_inception']) ? $lead_edit_data['premium_at_inception'] : '' ?>" type="text" class="form-control" id="premium_at_inception<?= $increment ?>" name="premium_at_inception[]"
placeholder="Enter Premium Paid" oninput="calculatePolicyMetrics(this)"> placeholder="Enter Premium Paid" oninput="calculatePolicyMetrics(this)">
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="premium_date">Premium as on Date<span class="text-danger">*</span></label> <label for="premium_date">Premium as on Date<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['premium_date']) ? $lead_edit_data['premium_date'] : '' ?>" type="text" class="form-control" id="premium_date<?= $increment ?>" name="premium_date[]" <input value="<?= isset($lead_edit_data['premium_date']) ? $lead_edit_data['premium_date'] : '' ?>" type="text" class="form-control" id="premium_date<?= $increment ?>" name="premium_date[]"
placeholder="Enter Premium Date" oninput="calculatePolicyMetrics(this)"> placeholder="Enter Premium Date" oninput="calculatePolicyMetrics(this)">
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="earned_premium">Earned Premium<span class="text-danger">*</span></label> <label for="earned_premium">Earned Premium<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['earned_premium']) ? $lead_edit_data['earned_premium'] : '' ?>" type="text" class="form-control" id="earned_premium<?= $increment ?>" name="earned_premium[]" <input value="<?= isset($lead_edit_data['earned_premium']) ? $lead_edit_data['earned_premium'] : '' ?>" type="text" class="form-control" id="earned_premium<?= $increment ?>" name="earned_premium[]"
placeholder="Enter Earned Premium" oninput="calculatePolicyMetrics(this)" readonly> placeholder="Enter Earned Premium" oninput="calculatePolicyMetrics(this)" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="annualised_claims">Annualised Claims<span class="text-danger">*</span></label> <label for="annualised_claims">Annualised Claims<span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['annualised_claims']) ? $lead_edit_data['annualised_claims'] : '' ?>" type="text" class="form-control" id="annualised_claims<?= $increment ?>" name="annualised_claims[]" <input value="<?= isset($lead_edit_data['annualised_claims']) ? $lead_edit_data['annualised_claims'] : '' ?>" type="text" class="form-control" id="annualised_claims<?= $increment ?>" name="annualised_claims[]"
placeholder="Enter Annualised Claims" oninput="calculatePolicyMetrics(this)" readonly> placeholder="Enter Annualised Claims" oninput="calculatePolicyMetrics(this)" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="incurred_claims_ratio">Incurred Claims Ratio(%) <span <label for="incurred_claims_ratio">Incurred Claims Ratio(%) <span
class="text-danger">*</span></label> class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['incurred_claims_ratio']) ? $lead_edit_data['incurred_claims_ratio'] : '' ?>" type="text" class="form-control" id="incurred_claims_ratio<?= $increment ?>" <input value="<?= isset($lead_edit_data['incurred_claims_ratio']) ? $lead_edit_data['incurred_claims_ratio'] : '' ?>" type="text" class="form-control" id="incurred_claims_ratio<?= $increment ?>"
name="incurred_claims_ratio[]" placeholder="Enter Incurred Claims Ratio" readonly> name="incurred_claims_ratio[]" placeholder="Enter Incurred Claims Ratio" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="earned_claims_ratio">Earned Claims Ratio(%) <span class="text-danger">*</span></label> <label for="earned_claims_ratio">Earned Claims Ratio(%) <span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['earned_claims_ratio']) ? $lead_edit_data['earned_claims_ratio'] : '' ?>" type="text" class="form-control" id="earned_claims_ratio<?= $increment ?>" name="earned_claims_ratio[]" <input value="<?= isset($lead_edit_data['earned_claims_ratio']) ? $lead_edit_data['earned_claims_ratio'] : '' ?>" type="text" class="form-control" id="earned_claims_ratio<?= $increment ?>" name="earned_claims_ratio[]"
placeholder="Enter Earned Claims Ratio" readonly> placeholder="Enter Earned Claims Ratio" readonly>
</div> </div>
<div class="form-group col-md-3 renewalFields" style="display: none;"> <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<span class="info-icon-wrapper"> <span class="info-icon-wrapper">
<i class="mdi mdi-information-outline text-primary"></i> <i class="mdi mdi-information-outline text-primary"></i>
<div class="info-tooltip"> <div class="info-tooltip">
@ -89,7 +89,7 @@
</div> </div>
<!-- <div class="form-group col-md-3 renewalFields" style="display: none;"> <!-- <div class="form-group col-md-3 renewalFields rolloOverFields" style="display: none;">
<label for="location">Location <span class="text-danger">*</span></label> <label for="location">Location <span class="text-danger">*</span></label>
<input value="<?php //echo isset($lead_edit_data['location']) ? $lead_edit_data['location'] : '' ?>" type="text" class="form-control" id="location" name="location[]" placeholder="Enter Location"> <input value="<?php //echo isset($lead_edit_data['location']) ? $lead_edit_data['location'] : '' ?>" type="text" class="form-control" id="location" name="location[]" placeholder="Enter Location">
</div> --> </div> -->
@ -161,20 +161,20 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="exp_emp_count"> No of Employees at Expiry <span class="text-danger"></span></label> <label for="exp_emp_count"> No of Employees at Expiry <span class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['exp_emp_count']) ? $lead_edit_data['exp_emp_count'] : '' ?>" type="text" class="form-control" id="exp_emp_count" name="exp_emp_count[]" <input value="<?= isset($lead_edit_data['exp_emp_count']) ? $lead_edit_data['exp_emp_count'] : '' ?>" type="text" class="form-control" id="exp_emp_count" name="exp_emp_count[]"
placeholder="Enter Lives"> placeholder="Enter Lives">
</div> </div>
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="exp_dept_count"> No of Dependents at Expiry <span <label for="exp_dept_count"> No of Dependents at Expiry <span
class="text-danger"></span></label> class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['exp_dept_count']) ? $lead_edit_data['exp_dept_count'] : '' ?>" type="text" class="form-control" id="exp_dept_count" name="exp_dept_count[]" <input value="<?= isset($lead_edit_data['exp_dept_count']) ? $lead_edit_data['exp_dept_count'] : '' ?>" type="text" class="form-control" id="exp_dept_count" name="exp_dept_count[]"
placeholder="Enter Lives"> placeholder="Enter Lives">
</div> </div>
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="exp_no_of_lives"> Total Lives at Expiry <span class="text-danger"></span></label> <label for="exp_no_of_lives"> Total Lives at Expiry <span class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['exp_no_of_lives']) ? $lead_edit_data['exp_no_of_lives'] : '' ?>" type="text" class="form-control" id="exp_no_of_lives" name="exp_no_of_lives[]" <input value="<?= isset($lead_edit_data['exp_no_of_lives']) ? $lead_edit_data['exp_no_of_lives'] : '' ?>" type="text" class="form-control" id="exp_no_of_lives" name="exp_no_of_lives[]"
placeholder="Enter Lives"> placeholder="Enter Lives">
@ -184,21 +184,21 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="renewal_emp_count"> No of Employees at Renewal <span <label for="renewal_emp_count"> No of Employees at Renewal <span
class="text-danger"></span></label> class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['renewal_emp_count']) ? $lead_edit_data['renewal_emp_count'] : '' ?>" type="text" class="form-control" id="renewal_emp_count" name="renewal_emp_count[]" <input value="<?= isset($lead_edit_data['renewal_emp_count']) ? $lead_edit_data['renewal_emp_count'] : '' ?>" type="text" class="form-control" id="renewal_emp_count" name="renewal_emp_count[]"
placeholder="Enter Lives"> placeholder="Enter Lives">
</div> </div>
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="renewal_dept_count"> No of Dependents at Renewal <span <label for="renewal_dept_count"> No of Dependents at Renewal <span
class="text-danger"></span></label> class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['renewal_dept_count']) ? $lead_edit_data['renewal_dept_count'] : '' ?>" type="text" class="form-control" id="renewal_dept_count" name="renewal_dept_count[]" <input value="<?= isset($lead_edit_data['renewal_dept_count']) ? $lead_edit_data['renewal_dept_count'] : '' ?>" type="text" class="form-control" id="renewal_dept_count" name="renewal_dept_count[]"
placeholder="Enter Lives"> placeholder="Enter Lives">
</div> </div>
<div class="form-group col-md-4 renewalFields" style="display: none;"> <div class="form-group col-md-4 renewalFields rolloOverFields" style="display: none;">
<label for="renewal_no_of_lives"> Total Lives at Renewal <span <label for="renewal_no_of_lives"> Total Lives at Renewal <span
class="text-danger"></span></label> class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['renewal_no_of_lives']) ? $lead_edit_data['renewal_no_of_lives'] : '' ?>" type="text" class="form-control" id="renewal_no_of_lives" name="renewal_no_of_lives[]" <input value="<?= isset($lead_edit_data['renewal_no_of_lives']) ? $lead_edit_data['renewal_no_of_lives'] : '' ?>" type="text" class="form-control" id="renewal_no_of_lives" name="renewal_no_of_lives[]"

View File

@ -13,25 +13,25 @@
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="total_lives_at_incept" class="total_title"> <label for="total_lives_at_incept" class="total_title">
<span class="total_title_text"> Total Lives at Inception </span> <span class="text-danger"></span></label> <span class="total_title_text"> Total Lives at Inception </span> <span class="text-danger"></span></label>
<input value="<?= isset($lead_edit_data['total_lives_at_incept']) ? $lead_edit_data['total_lives_at_incept'] : '' ?>" type="text" class="form-control" id="total_lives_at_incept" name="total_lives_at_incept[]" placeholder="Enter Lives" disabled> <input value="<?= isset($lead_edit_data['total_lives_at_incept']) ? $lead_edit_data['total_lives_at_incept'] : '' ?>" type="text" class="form-control" id="total_lives_at_incept" name="total_lives_at_incept[]" placeholder="Enter Lives">
</div> </div>
<div class="form-group col-md-4 renewalFields"> <div class="form-group col-md-4 renewalFields rolloOverFields">
<label for="total_si_at_incept"> Total Sum Insured at Inception <span class="text-danger">*</span></label> <label for="total_si_at_incept"> Total Sum Insured at Inception <span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['total_si_at_incept']) ? $lead_edit_data['total_si_at_incept'] : '' ?>" type="text" class="form-control" id="total_si_at_incept" name="total_si_at_incept[]" placeholder="Enter Sum Insured" required> <input value="<?= isset($lead_edit_data['total_si_at_incept']) ? $lead_edit_data['total_si_at_incept'] : '' ?>" type="text" class="form-control" id="total_si_at_incept" name="total_si_at_incept[]" placeholder="Enter Sum Insured" required>
</div> </div>
<div class="form-group col-md-4 renewalFields"> <div class="form-group col-md-4 renewalFields rolloOverFields">
<label for="premium_at_incept"> Premium at inception <span class="text-danger">*</span></label> <label for="premium_at_incept"> Premium at inception <span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['premium_at_incept']) ? $lead_edit_data['premium_at_incept'] : '' ?>" type="text" class="form-control" id="premium_at_incept" name="premium_at_incept[]" placeholder="Enter Premium" required> <input value="<?= isset($lead_edit_data['premium_at_incept']) ? $lead_edit_data['premium_at_incept'] : '' ?>" type="text" class="form-control" id="premium_at_incept" name="premium_at_incept[]" placeholder="Enter Premium" required>
</div> </div>
<div class="form-group col-md-4 renewalFields"> <div class="form-group col-md-4 renewalFields rolloOverFields">
<label for="renewal_emp_count"> No of Employees at Renewal <span class="text-danger">*</span></label> <label for="renewal_emp_count"> No of Employees at Renewal <span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['renewal_emp_count']) ? $lead_edit_data['renewal_emp_count'] : '' ?>" type="text" class="form-control" id="renewal_emp_count" name="renewal_emp_count[]" placeholder="Enter Lives" > <input value="<?= isset($lead_edit_data['renewal_emp_count']) ? $lead_edit_data['renewal_emp_count'] : '' ?>" type="text" class="form-control" id="renewal_emp_count" name="renewal_emp_count[]" placeholder="Enter Lives" >
</div> </div>
<div class="form-group col-md-4 renewalFields"> <div class="form-group col-md-4 renewalFields rolloOverFields">
<label for="total_si_at_renewal"> Total Sum Insured at Renewal <span class="text-danger">*</span></label> <label for="total_si_at_renewal"> Total Sum Insured at Renewal <span class="text-danger">*</span></label>
<input value="<?= isset($lead_edit_data['total_si_at_renewal']) ? $lead_edit_data['total_si_at_renewal'] : '' ?>" type="text" class="form-control" id="total_si_at_renewal" name="total_si_at_renewal[]" placeholder="Enter Sum Insured" > <input value="<?= isset($lead_edit_data['total_si_at_renewal']) ? $lead_edit_data['total_si_at_renewal'] : '' ?>" type="text" class="form-control" id="total_si_at_renewal" name="total_si_at_renewal[]" placeholder="Enter Sum Insured" >
</div> </div>

View File

@ -30,6 +30,22 @@ table.dataTable tbody td {
color: #6c757d !important; color: #6c757d !important;
} }
.policy-type-icon {
display: inline-flex;
align-items: center;
margin-right: 6px;
font-size: 0.95rem;
vertical-align: middle;
}
.policy-type-icon--cashless {
color: #0ea5e9;
}
.policy-type-icon--reimbursement {
color: #f59e0b;
}
/* Claim source pill — text only, fixed width (DUMP_TPA); hidden when no value */ /* Claim source pill — text only, fixed width (DUMP_TPA); hidden when no value */
.claim-source-badge { .claim-source-badge {
display: inline-flex; display: inline-flex;
@ -221,7 +237,19 @@ table.dataTable tbody td {
]; ];
$claimSrcClass = $claimSrcClassMap[$claimSrc] ?? null; $claimSrcClass = $claimSrcClassMap[$claimSrc] ?? null;
$policyTypeLabel = str_replace('Claim-', '', $ticket_type[$row['ticket_type_id']] ?? 'N/A'); $policyTypeLabel = str_replace('Claim-', '', $ticket_type[$row['ticket_type_id']] ?? 'N/A');
echo esc($policyTypeLabel); $tpaClaimTypeRaw = trim((string)($row['tpa_claim_type'] ?? ''));
$tpaClaimType = strtolower($tpaClaimTypeRaw);
$policyTypeIconHtml = '';
if ($tpaClaimType !== '') {
if (strpos($tpaClaimType, 'cash') !== false) {
$policyTypeIconHtml = '<span class="policy-type-icon policy-type-icon--cashless" title="Cashless"><i class="mdi mdi-hospital-box-outline" aria-hidden="true"></i></span>';
} elseif (strpos($tpaClaimType, 'reimburse') !== false) {
$policyTypeIconHtml = '<span class="policy-type-icon policy-type-icon--reimbursement" title="Reimbursement"><i class="mdi mdi-cash-refund" aria-hidden="true"></i></span>';
}
}
echo $policyTypeIconHtml . esc($policyTypeLabel);
if ($claimSrcClass !== null) { if ($claimSrcClass !== null) {
echo '<br><span class="claim-source-badge ' . esc($claimSrcClass, 'attr') . '">' . esc($claimSrc) . '</span>'; echo '<br><span class="claim-source-badge ' . esc($claimSrcClass, 'attr') . '">' . esc($claimSrc) . '</span>';
} }
@ -368,6 +396,18 @@ function getClaimSourceBadgeHtml(claimCreatedBy) {
return '<span class="claim-source-badge ' + cls + '">' + escapeHtml(key) + '</span>'; return '<span class="claim-source-badge ' + cls + '">' + escapeHtml(key) + '</span>';
} }
function getPolicyTypeIconHtml(tpaClaimType) {
var type = (tpaClaimType || '').toString().trim().toLowerCase();
if (!type) return '';
if (type.indexOf('cash') !== -1) {
return '<span class="policy-type-icon policy-type-icon--cashless" title="Cashless"><i class="mdi mdi-hospital-box-outline" aria-hidden="true"></i></span>';
}
if (type.indexOf('reimburse') !== -1) {
return '<span class="policy-type-icon policy-type-icon--reimbursement" title="Reimbursement"><i class="mdi mdi-cash-refund" aria-hidden="true"></i></span>';
}
return '';
}
function getStatusDisplay(row) { function getStatusDisplay(row) {
var status = row.status || ''; var status = row.status || '';
var claimStatusId = Number(row.claim_status_id || 0); var claimStatusId = Number(row.claim_status_id || 0);
@ -413,6 +453,7 @@ function buildTicketRowHtml(row) {
var statusUpdated = row.ticket_updated_date ? '<span class="text-custom-grey"><br>Updated at ' + escapeHtml(row.ticket_updated_date) + '</span>' : ''; var statusUpdated = row.ticket_updated_date ? '<span class="text-custom-grey"><br>Updated at ' + escapeHtml(row.ticket_updated_date) + '</span>' : '';
var claimCreated = row.ticket_created_date ? '<span class="text-custom-grey"><br>Created at ' + escapeHtml(row.ticket_created_date) + '</span>' : ''; var claimCreated = row.ticket_created_date ? '<span class="text-custom-grey"><br>Created at ' + escapeHtml(row.ticket_created_date) + '</span>' : '';
var policyType = (window.ticketTypeMap[row.ticket_type_id] || '').replace('Claim-', ''); var policyType = (window.ticketTypeMap[row.ticket_type_id] || '').replace('Claim-', '');
var policyTypeIcon = getPolicyTypeIconHtml(row.tpa_claim_type);
var claimSourceBadge = getClaimSourceBadgeHtml(row.claim_created_by); var claimSourceBadge = getClaimSourceBadgeHtml(row.claim_created_by);
var modeOfIntimation = window.modeOfIntimateMap[row.mode_of_intimation] || ''; var modeOfIntimation = window.modeOfIntimateMap[row.mode_of_intimation] || '';
var priority = window.priorityTypeMap[row.priority || 0] || ''; var priority = window.priorityTypeMap[row.priority || 0] || '';
@ -423,7 +464,7 @@ function buildTicketRowHtml(row) {
'<span class="status-tooltip">' + getStatusDisplay(row) + '</span>' + '<span class="status-tooltip">' + getStatusDisplay(row) + '</span>' +
statusUpdated + statusUpdated +
'</td>' + '</td>' +
'<td>' + asText(policyType) + (claimSourceBadge ? '<br>' + claimSourceBadge : '') + '</td>' + '<td>' + policyTypeIcon + asText(policyType) + (claimSourceBadge ? '<br>' + claimSourceBadge : '') + '</td>' +
'<td>' + asText(row.claim_no) + claimCreated + '</td>' + '<td>' + asText(row.claim_no) + claimCreated + '</td>' +
'<td>' + asText(row.tpa_no) + '</td>' + '<td>' + asText(row.tpa_no) + '</td>' +
'<td>' + asText(row.emp_code) + '</td>' + '<td>' + asText(row.emp_code) + '</td>' +

View File

@ -590,6 +590,7 @@
} }
</script> </script>
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("scroll-horizontal-datatable"); const table = document.getElementById("scroll-horizontal-datatable");
@ -676,4 +677,5 @@
} }
}); });
}); });
*/
</script> </script>

View File

@ -4,6 +4,27 @@
<form role="form" class="parsley-examples" style="color:black;" method="post" id="ticket_reply_form" enctype="multipart/form-data"> <form role="form" class="parsley-examples" style="color:black;" method="post" id="ticket_reply_form" enctype="multipart/form-data">
<div class="form-group"> <div class="form-group">
<div class="form-row"> <div class="form-row">
<?php
$showApprovedStatusDropdown =
isset($ticket_data['claim_status_id'], $ticket_data['ticket_type_id']) && (int) $ticket_data['claim_status_id'] === 10 && (int) $ticket_data['ticket_type_id'] === 1 &&
(
(isset($ticket_data['claim_created_by']) && $ticket_data['claim_created_by'] == 'TPA') ||
(array_key_exists('tpa_claim_push_reference_no', $ticket_data) && $ticket_data['tpa_claim_push_reference_no'] !== null)
);
?>
<?php if ($showApprovedStatusDropdown): ?>
<div class="form-group col-md-4">
<label for="status_back_option">Status</label>
<select class="form-control" id="status_back_option">
<option value="">Select</option>
<option value="9">APPROVED</option>
</select>
</div>
<?php endif; ?>
<!-- Email To Field --> <!-- Email To Field -->
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="emp_mail_for_to">To</label> <label for="emp_mail_for_to">To</label>
@ -46,10 +67,140 @@
</div> </div>
</div> </div>
<style>
.approved-letter-mode-option {
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 10px 12px;
margin-bottom: 10px;
cursor: pointer;
}
.approved-letter-mode-option.selected {
border-color: #0a8794;
background-color: #f2fbfc;
}
</style>
<div class="modal fade" id="approvedLetterUploadModal" tabindex="-1" role="dialog" aria-labelledby="approvedLetterUploadModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="approvedLetterUploadModalLabel">Upload Approved Letter</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="approved-letter-mode-option selected" onclick="selectApprovedLetterOption(this, 'approved_letter_mode_url')">
<div class="form-check">
<input class="form-check-input" type="radio" name="approved_letter_mode" id="approved_letter_mode_url" value="url" checked>
<label class="form-check-label" for="approved_letter_mode_url">Approved Letter URL</label>
</div>
</div>
<div class="approved-letter-mode-option" onclick="selectApprovedLetterOption(this, 'approved_letter_mode_pdf')">
<div class="form-check">
<input class="form-check-input" type="radio" name="approved_letter_mode" id="approved_letter_mode_pdf" value="pdf">
<label class="form-check-label" for="approved_letter_mode_pdf">Approved Letter PDF</label>
</div>
</div>
<div class="form-group" id="approved_letter_url_block">
<label for="approved_letter_reply_url">Approved Letter URL</label>
<input type="text" class="form-control" id="approved_letter_reply_url" placeholder="Enter Approved Letter URL">
<small class="text-danger d-none" id="approved_letter_reply_url_error"></small>
</div>
<div class="form-group mb-0" id="approved_letter_pdf_block" style="display:none;">
<label for="approved_letter_reply_file">Approved Letter PDF</label>
<input type="file" class="form-control" id="approved_letter_reply_file" accept=".pdf,application/pdf">
<small class="text-muted">Only PDF is allowed for file upload.</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="uploadApprovedLetterBtn">Upload</button>
</div>
</div>
</div>
</div>
<script> <script>
var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,"; var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,";
function selectApprovedLetterOption(element, inputId) {
$('.approved-letter-mode-option').removeClass('selected');
$(element).addClass('selected');
$('#' + inputId).prop('checked', true).trigger('change');
}
function validateApprovedLetterPdf(fileInput) {
const file = fileInput.files && fileInput.files[0] ? fileInput.files[0] : null;
if (!file) {
return true;
}
const fileName = (file.name || '').toLowerCase();
const isPdfByName = fileName.endsWith('.pdf');
const mimeType = (file.type || '').toLowerCase();
const isPdfByType = mimeType === '' || mimeType === 'application/pdf' || mimeType === 'application/x-pdf';
if (!isPdfByName || !isPdfByType) {
fileInput.value = '';
toastr.warning('Only PDF files are allowed for Approved Letter.', 'Warning');
return false;
}
return true;
}
function isValidApprovedLetterUrl(urlValue) {
const url = (urlValue || '').trim();
if (!url) {
return false;
}
try {
const normalizedUrl = /^https?:\/\//i.test(url) ? url : `https://${url}`;
const parsed = new URL(normalizedUrl);
if (!['http:', 'https:'].includes(parsed.protocol)) {
return false;
}
const host = (parsed.hostname || '').toLowerCase();
if (!host) {
return false;
}
if (host === 'localhost') {
return true;
}
if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) {
return true;
}
return host.includes('.');
} catch (e) {
return false;
}
}
function setApprovedLetterUrlError(message) {
const $urlInput = $('#approved_letter_reply_url');
const $errorEl = $('#approved_letter_reply_url_error');
if (message) {
$urlInput.addClass('is-invalid');
$errorEl.text(message).removeClass('d-none');
} else {
$urlInput.removeClass('is-invalid');
$errorEl.text('').addClass('d-none');
}
}
const editorConfig = { const editorConfig = {
buttons: toolbar.concat(['fontsize']), buttons: toolbar.concat(['fontsize']),
fontsize: [8, 10, 12, 14, 16, 18, 20, 22, 24], // Customize font sizes fontsize: [8, 10, 12, 14, 16, 18, 20, 22, 24], // Customize font sizes
@ -71,6 +222,13 @@ const editorConfig = {
}; };
$(document).ready(function() { $(document).ready(function() {
const replyTicketId = `<?= isset($ticket_data['id']) ? (int) $ticket_data['id'] : 0 ?>`;
let replyApprovedLetter = <?= json_encode($ticket_data['approved_letter'] ?? null) ?>;
console.log('Approved Letter from server:', replyApprovedLetter);
function hasApprovedLetterValue(value) {
return value !== null && value !== undefined && String(value).trim() !== '';
}
var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,"; var toolbar = "bold,italic,strikethrough,|,superscript,subscript,|,align,";
@ -134,6 +292,216 @@ $(document).ready(function() {
} }
}); });
async function loadClaimTemplateForStatus(ticketId, statusId) {
if (!ticketId || !statusId) {
return;
}
$.ajax({
url: '<?= base_url('/ticket/getClaimTemplateData') ?>',
type: 'POST',
dataType: 'json',
data: {
ticket_id: ticketId,
status_id: statusId
},
success: function(res) {
if (res && res.status && res.data) {
if (typeof res.data.subject !== 'undefined') {
$('#mail_subject').val(res.data.subject || '');
}
if (typeof res.data.message !== 'undefined') {
editor.value = res.data.message || '';
}
} else {
toastr.warning(res.message || 'Failed to load mail template', 'Warning');
}
},
error: function(xhr) {
console.error(xhr.responseText);
toastr.error('Unable to fetch mail template.', 'Error');
}
});
}
function openApprovedLetterUploadModalAndHandle(ticketId, statusId) {
const dfd = $.Deferred();
const $modal = $('#approvedLetterUploadModal');
const $modeUrl = $('#approved_letter_mode_url');
const $modePdf = $('#approved_letter_mode_pdf');
const $urlBlock = $('#approved_letter_url_block');
const $pdfBlock = $('#approved_letter_pdf_block');
const $urlInput = $('#approved_letter_reply_url');
const $fileInput = $('#approved_letter_reply_file');
const $uploadBtn = $('#uploadApprovedLetterBtn');
const approvedLetterModalEl = document.getElementById('approvedLetterUploadModal');
const approvedLetterModalInstance = new bootstrap.Modal(approvedLetterModalEl, {
backdrop: 'static',
keyboard: false
});
$urlInput.val('');
$fileInput.val('');
$modeUrl.prop('checked', true).trigger('change');
$('.approved-letter-mode-option').removeClass('selected');
$('.approved-letter-mode-option').first().addClass('selected');
$uploadBtn.prop('disabled', false);
approvedLetterModalInstance.show();
function cleanup() {
$uploadBtn.off('click.approvedUpload');
$modal.off('hidden.bs.modal.approvedUpload');
$modeUrl.off('change.approvedUpload');
$modePdf.off('change.approvedUpload');
}
$modal.on('hidden.bs.modal.approvedUpload', function() {
cleanup();
if (dfd.state() === 'pending') {
dfd.reject('Upload cancelled');
}
});
$modeUrl.on('change.approvedUpload', function() {
if ($(this).is(':checked')) {
$urlBlock.show();
$pdfBlock.hide();
$fileInput.val('');
}
});
$modePdf.on('change.approvedUpload', function() {
if ($(this).is(':checked')) {
$pdfBlock.show();
$urlBlock.hide();
$urlInput.val('');
}
});
$urlInput.on('input.approvedUpload', function() {
const currentValue = $.trim($(this).val());
if (currentValue === '') {
setApprovedLetterUrlError('');
return;
}
if (!isValidApprovedLetterUrl(currentValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
} else {
setApprovedLetterUrlError('');
}
});
$urlInput.on('blur.approvedUpload', function() {
const currentValue = $.trim($(this).val());
if (currentValue === '') {
setApprovedLetterUrlError('');
return;
}
if (!isValidApprovedLetterUrl(currentValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
} else {
setApprovedLetterUrlError('');
}
});
$fileInput.on('change.approvedUpload', function() {
validateApprovedLetterPdf(this);
});
$uploadBtn.on('click.approvedUpload', function() {
const selectedMode = $('input[name="approved_letter_mode"]:checked').val();
const urlValue = $.trim($urlInput.val());
const file = $fileInput[0].files && $fileInput[0].files[0] ? $fileInput[0].files[0] : null;
if (selectedMode === 'url' && !urlValue) {
setApprovedLetterUrlError('Please enter Approved Letter URL.');
return;
}
if (selectedMode === 'url' && !isValidApprovedLetterUrl(urlValue)) {
setApprovedLetterUrlError('Approved Letter URL format is invalid.');
return;
}
setApprovedLetterUrlError('');
if (selectedMode === 'pdf' && !file) {
toastr.warning('Please select Approved Letter PDF.', 'Warning');
return;
}
if (selectedMode === 'pdf' && file) {
if (!validateApprovedLetterPdf($fileInput[0])) {
return;
}
}
const formData = new FormData();
formData.append('ticket_id', ticketId);
formData.append('status_id', statusId);
formData.append('approved_letter', selectedMode === 'url' ? urlValue : '');
if (selectedMode === 'pdf' && file) {
formData.append('approved_letter_file', file);
}
$uploadBtn.prop('disabled', true);
$.ajax({
url: '<?= base_url('/ticket/uploadApprovedLetterFromReply') ?>',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(res) {
if (res && res.status) {
replyApprovedLetter = (res.data && res.data.approved_letter) ? res.data.approved_letter : replyApprovedLetter;
toastr.success(res.message || 'Approved letter uploaded successfully', 'Success');
cleanup();
approvedLetterModalInstance.hide();
dfd.resolve();
} else {
$uploadBtn.prop('disabled', false);
toastr.error((res && res.message) ? res.message : 'Approved letter upload failed', 'Error');
}
},
error: function(xhr) {
$uploadBtn.prop('disabled', false);
console.error(xhr.responseText);
toastr.error('Unable to upload approved letter.', 'Error');
}
});
});
return dfd.promise();
}
function handleStatusTemplateFlow() {
const selectedStatusId = $('#status_back_option').val();
if (!selectedStatusId || !replyTicketId) {
return;
}
if (String(selectedStatusId) === '9' && !hasApprovedLetterValue(replyApprovedLetter)) {
openApprovedLetterUploadModalAndHandle(replyTicketId, selectedStatusId)
.done(function() {
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
});
return;
}
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
}
$('#status_back_option').on('change', function() {
handleStatusTemplateFlow();
});
if ($('#status_back_option').length && hasApprovedLetterValue(replyApprovedLetter)) {
const selectedStatusId = $('#status_back_option').val();
if (selectedStatusId) {
loadClaimTemplateForStatus(replyTicketId, selectedStatusId);
}
}
function insertAtCursor(input, textToInsert) { function insertAtCursor(input, textToInsert) {
if (document.selection) { if (document.selection) {
input.focus(); input.focus();

View File

@ -240,11 +240,16 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_name">Branch Name <span class="text-danger">*</span></label> <label for="branch_name">Branch Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" name="branch_name" required maxlength="255" data-parsley-maxlength="255"> <input type="text" class="form-control" id="branch_name" placeholder="Enter Branch Name" name="branch_name" required maxlength="255" data-parsley-maxlength="255"
data-parsley-minlength="3"
data-parsley-pattern="^[a-zA-Z0-9\\s_-]+$"
data-parsley-pattern-message="Branch Name can contain letters, numbers, spaces, underscore (_) and hyphen (-).">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_code">Branch Code <span class="text-danger">*</span></label> <label for="branch_code">Branch Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" name="branch_code" required maxlength="100" data-parsley-maxlength="100"> <input type="text" class="form-control" id="branch_code" placeholder="Enter Branch Code" name="branch_code" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9_-]+$"
data-parsley-pattern-message="Branch Code can contain letters, numbers, underscore (_) and hyphen (-).">
</div> </div>
</div> </div>
@ -274,7 +279,9 @@
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="district">District <span class="text-danger">*</span></label> <label for="district">District <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="district" placeholder="Enter District" name="district" required maxlength="100" data-parsley-maxlength="100"> <input type="text" class="form-control" id="district" placeholder="Enter District" name="district" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="District can contain letters, numbers, spaces, and hyphens.">
</div> </div>
</div> </div>
@ -282,11 +289,15 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="branch_city">City <span class="text-danger">*</span></label> <label for="branch_city">City <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="branch_city" placeholder="Enter City" name="city" required maxlength="100" data-parsley-maxlength="100"> <input type="text" class="form-control" id="branch_city" placeholder="Enter City" name="city" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[a-zA-Z0-9\\s-]+$"
data-parsley-pattern-message="City can contain letters, numbers, spaces, and hyphens.">
</div> </div>
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="pincode">Pincode <span class="text-danger">*</span></label> <label for="pincode">Pincode <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required data-parsley-type="digits" data-parsley-length="[6,6]" maxlength="6"> <input type="text" class="form-control" id="pincode" placeholder="Enter Pincode" name="pincode" required data-parsley-type="digits" data-parsley-length="[6,6]" maxlength="6"
data-parsley-pattern="^[0-9]{6}$"
data-parsley-pattern-message="Pincode must be exactly 6 digits.">
</div> </div>
</div> </div>
@ -313,25 +324,33 @@
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="name">Name <span class="text-danger">*</span></label> <label for="name">Name <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required maxlength="100" data-parsley-maxlength="100"> <input value="" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" id="name" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z\\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="designation">Designation <span class="text-danger">*</span></label> <label for="designation">Designation <span class="text-danger">*</span></label>
<input value="" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="designation" required maxlength="100" data-parsley-maxlength="100"> <input value="" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" id="designation" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="email">Email <span class="text-danger">*</span></label> <label for="email">Email <span class="text-danger">*</span></label>
<input value="" data-parsley-type="email" type="email" data-parsley-trigger="change" data-parsley-type="email" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required> <input value="" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" id="email" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label for="mobile">Mobile <span class="text-danger">*</span></label> <label for="mobile">Mobile <span class="text-danger">*</span></label>
<input value="" data-parsley-type="digits" data-parsley-length="[10,10]" data-parsley-trigger="change" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" id="mobile" required maxlength="10" inputmode="numeric"> <input value="" data-parsley-type="digits" data-parsley-length="[10,10]" data-parsley-trigger="change" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" id="mobile" required maxlength="10" inputmode="numeric"
data-parsley-pattern="^[0-9]{10}$"
data-parsley-pattern-message="Mobile number must be exactly 10 digits.">
</div> </div>
</div> </div>
</div> </div>
@ -950,25 +969,33 @@ function renumberContacts() {
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Name<span class="text-danger">*</span></label> <label>Name<span class="text-danger">*</span></label>
<input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required maxlength="100" data-parsley-maxlength="100"> <input value="${contact ? contact.name : ''}" type="text" class="form-control" placeholder="Enter Contact Name" name="name[]" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z\\s]+$"
data-parsley-pattern-message="Contact name may contain only letters and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Designation<span class="text-danger">*</span></label> <label>Designation<span class="text-danger">*</span></label>
<input value="${contact ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" required maxlength="100" data-parsley-maxlength="100"> <input value="${contact ? contact.designation : ''}" type="text" class="form-control" placeholder="Enter Designation Name" name="designation[]" required maxlength="100" data-parsley-maxlength="100"
data-parsley-pattern="^[A-Za-z0-9\\-_\\/ ]+$"
data-parsley-pattern-message="Designation may only contain letters, numbers, /, -, _ and spaces.">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Email<span class="text-danger">*</span></label> <label>Email<span class="text-danger">*</span></label>
<input value="${contact ? contact.email : ''}" data-parsley-type="email" type="email" data-parsley-trigger="change" data-parsley-type="email" class="form-control" placeholder="Enter Contact Email" name="email[]" required> <input value="${contact ? contact.email : ''}" type="email" data-parsley-trigger="change" class="form-control" placeholder="Enter Contact Email" name="email[]" required
data-parsley-pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
data-parsley-pattern-message="Please enter a valid email format (e.g., name@domain.com).">
</div> </div>
</div> </div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-12"> <div class="form-group col-md-12">
<label>Mobile<span class="text-danger">*</span></label> <label>Mobile<span class="text-danger">*</span></label>
<input value="${contact ? contact.mobile : ''}" data-parsley-type="digits" data-parsley-length="[10,10]" data-parsley-trigger="change" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" required maxlength="10" inputmode="numeric"> <input value="${contact ? contact.mobile : ''}" data-parsley-type="digits" data-parsley-length="[10,10]" data-parsley-trigger="change" type="text" class="form-control" placeholder="Enter Contact Mobile" name="mobile[]" required maxlength="10" inputmode="numeric"
data-parsley-pattern="^[0-9]{10}$"
data-parsley-pattern-message="Mobile number must be exactly 10 digits.">
</div> </div>
</div> </div>
</div> </div>

View File

@ -144,6 +144,7 @@ $tpa_col_width_px = nhance_dt_column_widths_px($tpa_header_labels, $tpa_col_max_
<!-- end row --> <!-- end row -->
<script> <script>
/**
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("tpa-list-table"); const table = document.getElementById("tpa-list-table");
if (!table) { if (!table) {
@ -234,6 +235,7 @@ $tpa_col_width_px = nhance_dt_column_widths_px($tpa_header_labels, $tpa_col_max_
} }
}); });
}); });
*/
</script> </script>
<script> <script>

View File

@ -225,7 +225,12 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="field-1" class="control-label">Amount<span class="text-danger">*</span></label> <label for="field-1" class="control-label">Amount<span class="text-danger">*</span></label>
<input type="number" class="form-control" id="amount" placeholder="Amount" required> <input type="text" class="form-control" id="amount" placeholder="Amount" required
inputmode="decimal" maxlength="12"
data-parsley-pattern="^[0-9]+(\\.[0-9]{1,2})?$"
data-parsley-pattern-message="Amount must be a valid number."
data-parsley-required-message="Amount field is required.">
<div id="amount_error" class="text-danger small mt-1" style="display:none;"></div>
</div> </div>
</div> </div>
@ -428,11 +433,26 @@
var cd_ac_no = $('#cd_ac_no').val(); var cd_ac_no = $('#cd_ac_no').val();
var cd_ac_pk = $('#cd_ac_pk').val(); var cd_ac_pk = $('#cd_ac_pk').val();
if (amount == "") { amount = (amount || '').trim();
toastr.warning('Amount field is required') var amountRegex = /^[0-9]+(\.[0-9]{1,2})?$/;
if (amount === "") {
$('#amount_error').text('Amount field is required.').show();
$('#amount').addClass('is-invalid');
toastr.warning('Amount field is required');
return; return;
} }
if (!amountRegex.test(amount)) {
$('#amount_error').text('Amount must be a valid number.').show();
$('#amount').addClass('is-invalid');
toastr.warning('Amount must be a valid number.');
return;
}
$('#amount_error').hide().text('');
$('#amount').removeClass('is-invalid');
if (description == "") { if (description == "") {
toastr.warning('Description field is required') toastr.warning('Description field is required')
return; return;
@ -526,4 +546,24 @@
}); });
}); });
</script>
<script>
$(document).on('input', '#amount', function () {
var value = $(this).val();
value = value.replace(/[^0-9.]/g, '');
var parts = value.split('.');
if (parts.length > 2) {
value = parts[0] + '.' + parts.slice(1).join('');
parts = value.split('.');
}
if (parts[1] && parts[1].length > 2) {
value = parts[0] + '.' + parts[1].slice(0, 2);
}
$(this).val(value);
if (value.length) {
$('#amount_error').hide().text('');
$(this).removeClass('is-invalid');
}
});
</script> </script>

View File

@ -757,6 +757,9 @@ div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu
border: 1px solid rgba(0, 0, 0, 0.12) !important; border: 1px solid rgba(0, 0, 0, 0.12) !important;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12) !important; box-shadow: 0 8px 16px rgba(0, 0, 0, 0.12) !important;
z-index: 1080 !important; z-index: 1080 !important;
max-height: none !important;
overflow-y: visible !important;
overflow-x: visible !important;
} }
div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu .dropdown-item { div.dataTables_wrapper table.dataTable tbody td.table-action-cell .dropdown-menu .dropdown-item {