Merge branch 'dev' of bitbucket.org:jubilian/nhance into dev

This commit is contained in:
VENKATESHWARAN 2026-04-20 18:31:04 +05:30
commit 3e8b4dcd2d
12 changed files with 568 additions and 144 deletions

View File

@ -106,6 +106,58 @@ input:checked + .slider:before {
.slider.round:before {
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>
<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"
accept="image/jpeg, image/jpg, image/png"
onchange="PreviewImage0(event);"
data-parsley-max-file-size="200"
data-parsley-file-extension="jpg,jpeg,png"
data-parsley-client-max-file-size="200"
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"
/>
</div>
@ -198,25 +252,29 @@ input:checked + .slider:before {
<div class="form-group col-md-4">
<label for="client_name">Client Name<span
class="text-danger">*</span></label>
<input type="text" class="form-control" id="client_name" data-old-name="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>"
placeholder="Enter Client Name" value="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>" name="client_name"
required maxlength="255" data-parsley-maxlength="255">
<input type="text" class="form-control" id="client_name"
data-old-name="<?= isset($client['client_name']) ? $client['client_name'] : '' ?>"
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 class="form-group col-md-4">
<label for="short_name">Client Short Name<span
class="text-danger">*</span></label>
<input type="text" class="form-control" id="short_name"
maxlength="100" data-parsley-maxlength="100"
data-old-short="<?= isset($client['short_name']) ? $client['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>
<input type="text" class="form-control" id="short_name" data-parsley-minlength="2"
data-parsley-maxlength="15" data-parsley-pattern="/^[a-zA-Z0-9_\- ]+$/"
data-old-short="<?= isset($client['short_name']) ? $client['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>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<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"
maxlength="10" data-parsley-maxlength="10" data-parsley-trigger="change" data-parsley-pattern="^[A-Z]{5}[0-9]{4}[A-Z]$">
<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="keyup" data-parsley-pattern="^[A-Z]{5}[0-9]{4}[A-Z]$">
</div>
<!-- <div class="form-group col-md-4">
<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">
<label>HR File Processed By <span class="text-danger">*</span></label>
<div class="d-flex align-items-center">
<div class="form-check form-check-inline mb-0" style="margin-right: -356px;">
<input class="form-check-input"
<div class="hr-processed-options">
<div class="hr-processed-option">
<input class="hr-radio-input"
type="radio"
name="hr_file_processed_by"
id="hr_processed"
value="1" required <?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 1) ? 'checked' : '' ?>>
<label class="form-check-label" for="hr_processed">HR</label>
value="1"
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 class="form-check form-check-inline mb-0">
<input class="form-check-input"
<div class="hr-processed-option">
<input class="hr-radio-input"
type="radio"
name="hr_file_processed_by"
id="account_manager_processed"
value="2"
<?php echo(isset($client['hr_file_processed_by']) && $client['hr_file_processed_by'] == 2) ? 'checked' : '' ?>>
<label class="form-check-label" for="account_manager_processed">Account Manager</label>
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'] == 2) ? 'checked' : '' ?>>
<label class="hr-radio-label" for="account_manager_processed">Account Manager</label>
</div>
</div>
<div id="hr_file_processed_by_error_container"></div>
</div>
@ -342,6 +407,31 @@ input:checked + .slider:before {
var form_action = '';
$(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() {
validateFile(this);
return;
@ -365,6 +455,9 @@ input:checked + .slider:before {
});
$(document).ready(function () {
$('#general_form').parsley({
trigger: 'input'
});
$("#general_form").submit(function(event) {
@ -574,7 +667,7 @@ input:checked + .slider:before {
// For example, you can display the image
const reader = new FileReader();
reader.onload = function(e) {
$("#uploadPreview").attr("src", e.target.result);
$("#uploadPreview0").attr("src", e.target.result);
};
reader.readAsDataURL(file);
}
@ -585,7 +678,9 @@ input:checked + .slider:before {
// Helper function to clear the preview and the file input
function resetImageInput(input) {
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>

View File

@ -171,12 +171,16 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-6">
<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>
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 class="form-group col-md-6">
<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" 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>
@ -204,23 +208,29 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-3">
<label for="district">District<span class="text-danger">*</span></label>
<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 class="form-group col-md-3">
<label for="city">City<span class="text-danger">*</span></label>
<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 class="form-group col-md-3">
<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 class="form-row">
<div class="form-group col-md-4">
<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 class="form-group col-md-4">
<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">
<label for="first_name">Name<span class="text-danger">*</span></label>
<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 class="form-group col-md-6">
<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
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, '')"
title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed">
</div>
@ -267,7 +281,10 @@ input:checked + .slider-branch-contact:before {
<div class="form-group col-md-6">
<label for="last_name">Email<span class="text-danger">*</span></label>
<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 class="form-group col-md-6">
<label for="mobile">Mobile<span class="text-danger">*</span></label>
@ -275,8 +292,9 @@ input:checked + .slider-branch-contact:before {
name="mobile[]" id="mobile"
onchange="validateDuplicateByClientBranch(this, 'mobile','branchBtnSubmit')"
onkeypress="return onlyNumbers(event)" maxlength="10" minlength="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."
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>
@ -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 : ''}">
<div class="form-group col-md-6">
<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 class="form-group col-md-6">
<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
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, '')"
title="Designation may only contain letters, numbers, /, -, _ and spaces only allowed">
</div>
@ -765,11 +787,11 @@ function appendContactHtml(contact = false, reset = false) {
<div class="form-row">
<div class="form-group col-md-6">
<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 class="form-group col-md-6">
<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 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) {
overflow: visible;
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 {
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>
<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}"); ?>">
<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>
</td>
</tr>

View File

@ -43,11 +43,13 @@
<div class="form-row additional-doc-row" data-row-index="0">
<div class="form-group col-md-4">
<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 class="form-group col-md-4">
<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">
<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 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>
@ -96,17 +98,79 @@
<script>
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) {
return `
<div class="form-row additional-doc-row" data-row-index="${index}">
<div class="form-group col-md-4">
<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 class="form-group col-md-4">
<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">
<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 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>
@ -126,7 +190,6 @@
var form = $(this).closest('form');
var formData = new FormData(form[0]);
var fileInputs = form.find('input[type="file"]');
var allowedExtensions = ['pdf', 'png', 'jpeg', 'jpg'];
if (kycPrimaryKey === '') {
toastr.error('Client is required', 'Error');
@ -135,24 +198,26 @@
}
var isFormEmpty = true;
var hasInvalidFile = false;
fileInputs.each(function() {
var files = $(this)[0].files;
var $currentFileInput = $(this);
var files = $currentFileInput[0].files;
if (files.length > 0) {
for (var i = 0; i < files.length; i++) {
var fileName = files[i].name;
var fileExtension = fileName.split('.').pop().toLowerCase();
if (allowedExtensions.indexOf(fileExtension) === -1) {
form.trigger('reset')
toastr.warning('File type not allowed: ' + fileName, 'Only Allowed pdf, png, jpg and jpeg');
return;
}
if (!validateOtherDocFileField($currentFileInput, true)) {
hasInvalidFile = true;
return false;
}
isFormEmpty = false;
return false;
}
});
if (hasInvalidFile) {
return;
}
if (isFormEmpty) {
form.find('.kyc-primary-file-error').text('Please select a file.');
fileInputs.addClass('is-invalid');
toastr.warning('Form is Empty', 'Warning');
return;
}
@ -238,31 +303,29 @@
var isValid = $('#kyc_form').parsley().validate();
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-file-error').text('');
$('#additional_docs_rows .additional-doc-row').each(function() {
var docNameField = $(this).find('.other-doc-name-field');
var fileField = $(this).find('.other-doc-file-field');
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;
if (docNameValue === '') {
docNameField.addClass('is-invalid');
}
if (!selectedFile) {
if (!hasSelectedFile) {
fileField.addClass('is-invalid');
}
return;
}
var fileExtension = selectedFile.name.split('.').pop().toLowerCase();
if (allowedExtensions.indexOf(fileExtension) === -1) {
if (!validateOtherDocFileField(fileField, true)) {
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){
$.ajax({
@ -433,6 +504,8 @@
<input type="hidden" class="form-control" value="${item.id}" name="kyc_doc_type_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>
<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>
</td>
<td id="name_${item.id}" style="display:none;"></td>

View File

@ -205,7 +205,9 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4">
<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>
<?php foreach ($policy_types as $value) { ?>
<option value="<?= $value['id']?>"><?= $value['policy_type'] ?></option>
@ -248,7 +250,9 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4">
<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>
@ -280,12 +284,18 @@ input:checked + .slider_blue::before {
<div class="form-group col-md-4">
<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 class="form-group col-md-4">
<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 class="form-group col-md-4">

View File

@ -30,10 +30,6 @@
white-space: normal;
}
.dataTables_filter{
position: absolute;
}
.right-align-input {
text-align: right;
}
@ -216,7 +212,8 @@ $gst_total = 0;
<h4 style="position: relative;">Employees</h4>
</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 dt-responsive" cellspacing="0" id="employee-data-list-table">
<thead class="bg-light">
<tr>
<th class="font-weight-medium">S.No&nbsp;</th>
@ -281,19 +278,19 @@ $gst_total = 0;
<?php
switch ($employee['status']) {
case 'draft':
echo '<span class="badge badge-secondary">' . $employee['status'] . '</span>';
echo '<span class="badge badge-secondary">' . ucfirst($employee['status']) . '</span>';
break;
case 'active':
echo '<span class="badge badge-success">' . $employee['status'] . '</span>';
echo '<span class="badge badge-success">' . ucfirst($employee['status']) . '</span>';
break;
case 'inactive':
echo '<span class="badge badge-warning">' . $employee['status'] . '</span>';
echo '<span class="badge badge-warning">' . ucfirst($employee['status']) . '</span>';
break;
case 'expired':
echo '<span class="badge badge-danger">' . $employee['status'] . '</span>';
echo '<span class="badge badge-danger">' . ucfirst($employee['status']) . '</span>';
break;
case 'enrolled':
echo '<span class="badge2 badge2-secondary2">' . $employee['status'] . '</span>';
echo '<span class="badge2 badge2-secondary2">' . ucfirst($employee['status']) . '</span>';
break;
default:
echo $employee['status'];
@ -373,6 +370,7 @@ $gst_total = 0;
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div><!-- end col -->
@ -473,35 +471,54 @@ $gst_total = 0;
$(document).ready(function() {
var ticketsTable = $('#employee-data-list-table');
if (ticketsTable.length) {
nhanceListDataTableBeforeInit();
var nhEmpDataTable = ticketsTable.DataTable(nhanceMergeListDataTableOptions({
// dom: "<'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 align-items-center'<'col-5 text-start'i><'col-7 d-flex justify-content-end align-items-center'<'me-2'l>p>>",
if (ticketsTable.length) {
var _dtDefScroll = {
scrollX: $.fn.dataTable.defaults.scrollX,
scrollY: $.fn.dataTable.defaults.scrollY,
scrollCollapse: $.fn.dataTable.defaults.scrollCollapse
};
$.extend($.fn.dataTable.defaults, { scrollX: false, scrollY: false, scrollCollapse: false });
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]],
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: [
{
extend: 'collection',
text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
className: 'btn app-btn-secondary ',
buttons: [
{
extend: 'csv',
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
className: 'app-btn-primary ',
title: 'Members',
},
{
extend: 'excel',
text: '<i class="mdi mdi-file-excel " ></i><span class=" btn-custom"> EXCEL </span>',
className: 'app-btn-primary ',
title: 'Members',
sheetName: 'Members'
}
{
extend: 'csv',
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
className: 'app-btn-primary ',
title: 'Members',
},
{
extend: 'excel',
text: '<i class="mdi mdi-file-excel " ></i><span class=" btn-custom"> EXCEL </span>',
className: 'app-btn-primary ',
title: 'Members',
sheetName: 'Members'
}
]
}
],
@ -517,16 +534,28 @@ $gst_total = 0;
searchPlaceholder: "Search",
emptyTable: '<div class="text-center text-muted">No Data found</div>'
},
paging: true, // Enable pagination
pageLength: 25, // Set default number of rows per page (optional)
paging: true,
pageLength: 25,
autoWidth: false,
responsive: false,
columnDefs: [
<?php for ($i = 0; $i < $emp_col_count; $i++) : ?>
{ targets: <?= $i ?>, width: '<?= (int) $emp_col_width_px[$i] ?>px' },
<?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 {
console.error("Table not found.");
}

View File

@ -170,8 +170,10 @@ input:checked + .slider:before {
<div class="input-icon">
<input type="file" class="form-control" id="insurer_logo" name="insurer_logo"
accept="image/jpeg, image/jpg, image/png" onchange="PreviewImage();"
data-parsley-max-file-size="200"
data-parsley-file-extension="jpg,jpeg,png"
data-parsley-insurer-max-file-size="200"
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">
<i class="mdi mdi-upload additional-icon"></i>
</div>
@ -204,8 +206,8 @@ input:checked + .slider:before {
<script>
$(document).ready(function() {
// Custom Parsley validator for file size
window.Parsley.addValidator('maxFileSize', {
// Custom Parsley validator for insurer logo file size
window.Parsley.addValidator('insurerMaxFileSize', {
validateString: function(value, maxSize, parsleyInstance) {
if (!window.FileReader) {
alert('Your browser does not support FileReader API, please upgrade.');
@ -223,8 +225,8 @@ input:checked + .slider:before {
}
});
// Custom Parsley validator for file extension
window.Parsley.addValidator('fileExtension', {
// Custom Parsley validator for insurer logo file extension
window.Parsley.addValidator('insurerFileExtension', {
validateString: function(value, requirement, parsleyInstance) {
var file = parsleyInstance.$element[0].files[0];
if (!file) { return true; } // No file, so validation passes
@ -239,12 +241,16 @@ input:checked + .slider:before {
});
$('#insurer_logo').on('change', function() {
PreviewImage();
PreviewImage();
});
$("#insurer_general_form").submit(function(events) {
events.preventDefault();
if (!validateInsurerLogoFile(true)) {
return;
}
// var isValid = $('#insurer_General_PrimaryKey').parsley().validate();
var isValid = $('#insurer_general_form').parsley().validate();
@ -357,22 +363,22 @@ input:checked + .slider:before {
var file = fileInput.files[0];
var fileName = file.name.toLowerCase();
var parts = fileName.split('.');
$('#logo_error_container').empty();
// VALIDATION: Extensions and Double Extensions (e.g. .php.jpeg)
var allowedExtensions = /(\.jpg|\.jpeg|\.png)$/i;
if (!allowedExtensions.exec(fileName) || parts.length > 2) {
toastr.error("Security violation: Invalid format or double extension.", "Blocked");
fileInput.value = ""; // Clear the field
preview.src = defaultAvatar; // RESET PREVIEW
resetInsurerLogoInput();
return;
}
// VALIDATION: Size (200KB)
if ((file.size / 1024) > 200) {
toastr.warning("File size exceeds 200 KB limit.", "Warning");
fileInput.value = ""; // Clear the field
preview.src = defaultAvatar; // RESET PREVIEW
resetInsurerLogoInput();
return;
}
@ -383,6 +389,47 @@ input:checked + .slider:before {
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">
<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>
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 class="form-group col-md-6">
<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>
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>
@ -141,7 +146,9 @@
<div class="form-group col-md-6">
<label for="district">District <span class="text-danger">*</span></label>
<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>
@ -150,11 +157,15 @@
<div class="form-group col-md-6">
<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>
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 class="form-group col-md-6">
<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>
@ -185,19 +196,25 @@
<!-- <input type="hidden" name="primarykey[]" id="contact_id_1" value=""/> -->
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
@ -435,8 +452,11 @@
switch (key) {
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 '';
case 'branch_code':
if (!/^[a-zA-Z0-9_-]+$/.test(v)) return 'Branch Code can contain letters, numbers, underscore (_) and hyphen (-).';
return '';
case 'address1':
return '';
@ -458,6 +478,7 @@
if (!contactNamePattern.test(v)) return 'Contact name is invalid Format';
return '';
case 'designation':
if (!/^[A-Za-z0-9\-_\/ ]+$/.test(v)) return 'Designation may only contain letters, numbers, /, -, _ and spaces.';
return '';
case 'email':
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-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">

View File

@ -689,6 +689,17 @@
//------------------------------ GET DATA ( EDIT, BRANCH, POLICY ) ---------------------------------------------------------------------------
//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) {
$('.loader').fadeIn();
@ -718,6 +729,7 @@
if (typeof window.refreshLeadsFormValidation === 'function') {
window.refreshLeadsFormValidation();
}
togglePolicyTypeDivider(dataIncrement);
let policy_type_id = res.data.policy_type_id;
let lead_type = res.data.lead_type;
@ -1105,6 +1117,7 @@
if (typeof window.refreshLeadsFormValidation === 'function') {
window.refreshLeadsFormValidation();
}
togglePolicyTypeDivider(dataIncrement);
console.log("Policy Type ID : ", policy_type_id);
if (policy_type_id == 1 || policy_type_id == 6 || policy_type_id == 7) {

View File

@ -13,16 +13,16 @@
<div class="form-row">
<div class="form-group col-md-12">
<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 class="form-group col-md-12">
<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 class="form-group col-md-12">
<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>
@ -48,7 +48,7 @@
</div>
<div class="form-group col-md-12">
<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>
@ -72,17 +72,17 @@
<div class="form-group col-md-6">
<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 class="form-group col-md-6">
<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 class="form-group col-md-6">
<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 class="form-group col-md-6">
@ -97,7 +97,7 @@
<div class="form-group col-md-12">
<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')"
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>
@ -116,6 +116,34 @@
let isGSTValidating = 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) {
let owner_type = $('#Owner_type').val();

View File

@ -240,11 +240,16 @@
<div class="form-row">
<div class="form-group col-md-6">
<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 class="form-group col-md-6">
<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>
@ -274,7 +279,9 @@
</div>
<div class="form-group col-md-6">
<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>
@ -282,11 +289,15 @@
<div class="form-row">
<div class="form-group col-md-6">
<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 class="form-group col-md-6">
<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>
@ -313,25 +324,33 @@
<div class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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>
@ -950,25 +969,33 @@ function renumberContacts() {
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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 class="form-row">
<div class="form-group col-md-12">
<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>

View File

@ -225,7 +225,12 @@
<div class="col-md-6">
<div class="form-group">
<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>
@ -428,11 +433,26 @@
var cd_ac_no = $('#cd_ac_no').val();
var cd_ac_pk = $('#cd_ac_pk').val();
if (amount == "") {
toastr.warning('Amount field is required')
amount = (amount || '').trim();
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;
}
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 == "") {
toastr.warning('Description field is required')
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>