nhance/app/Views/non_eb_claim_form.php
2026-04-16 15:28:06 +05:30

844 lines
47 KiB
PHP

<style>
.readonly-color {
background-color: #e0e0e0;
color: #666;
}
.readonly-select {
pointer-events: none;
background-color: #f0f0f0;
color: #666;
}
.label-font-size {
font-size: 0.875rem;
}
.is-invalid {
border-color: #dc3545 !important;
}
.invalid-feedback {
display: none;
color: #dc3545;
font-size: 0.8rem;
margin-top: 2px;
}
.is-invalid ~ .invalid-feedback,
.is-invalid + .invalid-feedback {
display: block;
}
.select2-container .select2-selection--single.is-invalid-select2 {
border-color: #dc3545 !important;
}
</style>
<script>
var base_url = '<?= base_url() ?>';
var pageHideMainNavTitle = true;
var pageTitle = 'New Non-EB Claim';
var pageBackButton = '<a href="<?= base_url('non-eb-claim/list') ?>" class="topbar-icon-btn" data-toggle="tooltip" data-placement="top" title="Back" aria-label="Back"><i class="ri-arrow-left-s-line"></i></a>';
</script>
<?php $sections = $visible_sections ?? []; ?>
<div class="row">
<div class="col-12">
<div class="card" style="margin-right:23px;">
<div class="card-body">
<form id="nonEbClaimForm" onsubmit="return false;" enctype="multipart/form-data">
<input type="hidden" name="policy_type_id" id="policy_type_id" value="<?= $policy_type_id ?>">
<input type="hidden" name="client_id" id="client_id" value="" required>
<input type="hidden" name="insurer_id" id="insurer_id" value="">
<input type="hidden" name="client_policy_id" id="client_policy_id_hidden" value="">
<!-- Section 1: Policy & Account Details -->
<div id="accordion1" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Policy & Account Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseOne" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseOne" class="collapse show" data-parent="#accordion1">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-3">
<label class="label-font-size">Client <span class="text-danger">*</span></label>
<select class="form-control" id="client_select" required>
<option value="">Select Client</option>
<?php if(isset($clients)): foreach($clients as $c): ?>
<option value="<?= $c['id'] ?>"><?= $c['client_name'] ?></option>
<?php endforeach; endif; ?>
</select>
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Branch <span class="text-danger">*</span></label>
<select class="form-control" id="branch_id" name="branch_id" required>
<option value="">Select Branch</option>
</select>
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Policy</label>
<select class="form-control" id="client_policy_id">
<option value="">Select Policy</option>
</select>
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Insurer</label>
<input type="text" class="form-control readonly-color" id="insurer_name_display" readonly placeholder="Auto-filled from policy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Policy Type</label>
<input type="text" class="form-control" name="policy_type_name" id="policy_type_display" value="<?= $policy_type_name ?? '' ?>">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Policy No</label>
<input type="text" class="form-control readonly-color" name="policy_no" id="policy_no" readonly placeholder="Auto-filled from policy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Policy Start Date</label>
<input type="text" class="form-control readonly-color" name="policy_start_date" id="policy_start_date" readonly placeholder="Auto-filled from policy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Policy Expiry Date</label>
<input type="text" class="form-control readonly-color" name="policy_end_date" id="policy_end_date" readonly placeholder="Auto-filled from policy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Account Manager <span class="text-danger">*</span></label>
<select class="form-control select2-init" name="acm_id" id="acm_id" required>
<option value="">Select ACM</option>
<?php if(isset($acms)): foreach($acms as $a): ?>
<option value="<?= $a['id'] ?>"><?= $a['first_name'] ?></option>
<?php endforeach; endif; ?>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section 2: Insured Contact Details -->
<div id="accordion2" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Insured Contact Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseTwo" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseTwo" class="collapse show" data-parent="#accordion2">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-4">
<label class="label-font-size">Contact Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="insured_contact_name" id="insured_contact_name" minlength="3" pattern="^[a-zA-Z0-9\s_-]+$" required>
<div class="invalid-feedback">Min 3 chars. Only letters, numbers, spaces, hyphens, underscores.</div>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Contact Number <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="insured_contact_number" id="insured_contact_number" minlength="10" maxlength="15" pattern="^[0-9]+$" required>
<div class="invalid-feedback">Required. 10-15 digits, numeric only.</div>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Contact Email</label>
<input type="email" class="form-control" name="insured_contact_email" id="insured_contact_email">
<div class="invalid-feedback">Invalid email format.</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section 3: Loss / Incident Details -->
<div id="accordion3" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Loss / Incident Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseThree" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseThree" class="collapse show" data-parent="#accordion3">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-4">
<label class="label-font-size">Nature of Loss <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="nature_of_loss" id="nature_of_loss" minlength="3" required>
<div class="invalid-feedback">Required. Min 3 characters.</div>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Loss Location <span class="text-danger">*</span></label>
<input type="text" class="form-control" name="loss_location" id="loss_location" required>
<div class="invalid-feedback">Loss Location is required.</div>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Loss Date <span class="text-danger">*</span></label>
<input type="text" class="form-control date-picker" name="loss_date" id="loss_date" required placeholder="dd-mm-yyyy">
<div class="invalid-feedback">Loss Date is required.</div>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Loss Estimate</label>
<input type="number" class="form-control" name="loss_estimate" id="loss_estimate" step="0.01" min="0">
<div class="invalid-feedback">Must be a valid number.</div>
</div>
<div class="form-group col-md-8">
<label class="label-font-size">Loss Description</label>
<textarea class="form-control" name="loss_description" id="loss_description" rows="2"></textarea>
<div class="invalid-feedback">Loss Description is required when uploading an asset file.</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section 4: Intimation & Claim Reference -->
<div id="accordion4" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Intimation & Claim Reference
<a class="text-dark float-right" data-toggle="collapse" href="#collapseFour" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseFour" class="collapse show" data-parent="#accordion4">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-3">
<label class="label-font-size">Intimation Recd Date</label>
<input type="text" class="form-control date-picker" name="intimation_recd_date" placeholder="dd-mm-yyyy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Intimated to Insurer Date</label>
<input type="text" class="form-control date-picker" name="intimated_to_insurer_date" placeholder="dd-mm-yyyy">
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Nhance Claim Ref No</label>
<input type="text" class="form-control" name="nhance_claim_ref_no" id="nhance_claim_ref_no" maxlength="100">
<div class="invalid-feedback">Max 100 characters.</div>
</div>
<div class="form-group col-md-3">
<label class="label-font-size">Claim Number (Insurer)</label>
<input type="text" class="form-control" name="claim_number" id="claim_number" pattern="^[a-zA-Z0-9\/_-]+$">
<div class="invalid-feedback">Only letters, numbers, /, - allowed.</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section 5: Status & Tracking -->
<div id="accordion5" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Status & Tracking
<a class="text-dark float-right" data-toggle="collapse" href="#collapseFive" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseFive" class="collapse show" data-parent="#accordion5">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-4">
<label class="label-font-size">Status <span class="text-danger">*</span></label>
<select class="form-control" name="claim_status_id" id="claim_status_id" required>
<?php if(isset($claim_status)): foreach($claim_status as $cs): ?>
<option value="<?= $cs['id'] ?>"><?= $cs['claim_status'] ?></option>
<?php endforeach; endif; ?>
</select>
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Surveyor File Ref No</label>
<input type="text" class="form-control" name="surveyor_file_ref_no">
</div>
<div class="form-group col-md-4">
<label class="label-font-size">Priority</label>
<select class="form-control" name="priority">
<option value="">Select Priority</option>
<?php if(isset($priorityType)): foreach($priorityType as $k => $v): ?>
<option value="<?= $k ?>"><?= $v ?></option>
<?php endforeach; endif; ?>
</select>
</div>
</div>
<!-- Closure Remark: shown for Claim Closed / Rejected / Withdrawn -->
<div id="closure_remark_row" class="form-row" style="display:none;">
<div class="form-group col-md-12">
<label class="label-font-size">Closure Remark</label>
<textarea class="form-control" name="closure_remark" id="closure_remark" rows="2" placeholder="Enter closure remark..."></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Section 6: Asset Details -->
<div id="accordion6" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Asset Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseSix" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseSix" class="collapse show" data-parent="#accordion6">
<div class="card-body">
<div id="asset_container">
<div class="form-row asset-row" id="asset_row_1">
<div class="form-group col-md-3"><label class="label-font-size">Asset ID/Code</label><input type="text" class="form-control" name="asset_id_code[]"></div>
<div class="form-group col-md-2"><label class="label-font-size">Serial No</label><input type="text" class="form-control" name="serial_no[]"></div>
<div class="form-group col-md-2"><label class="label-font-size">Vehicle No</label><input type="text" class="form-control" name="vehicle_no[]"></div>
<div class="form-group col-md-4"><label class="label-font-size">Description</label><input type="text" class="form-control" name="asset_description[]"></div>
<div class="form-group col-md-1 d-flex align-items-end"><span></span></div>
</div>
</div>
<button type="button" class="btn btn-sm btn-info mt-2" onclick="addAssetRow()"><i class="mdi mdi-plus"></i> Add More Asset</button>
<!-- OR Divider -->
<div class="d-flex align-items-center my-3">
<hr class="flex-grow-1" style="border-top: 1px solid #aaa;">
<span class="mx-3 font-weight-bold text-muted" style="font-size: 0.9rem;">OR</span>
<hr class="flex-grow-1" style="border-top: 1px solid #aaa;">
</div>
<!-- Asset File Upload -->
<div class="form-row">
<div class="form-group col-md-6">
<label class="label-font-size">Upload Asset File <small class="text-muted">(Excel or PDF)</small></label>
<input type="file" class="form-control-file" name="asset_file" id="asset_file" accept=".xlsx,.xls,.csv,.pdf">
<div class="invalid-feedback">Only Excel (.xlsx, .xls, .csv) or PDF (.pdf) files allowed.</div>
</div>
</div>
<div id="asset_section_error" class="text-danger" style="display:none; font-size:0.85rem;">Please fill at least one asset row or upload an asset file.</div>
</div>
</div>
</div>
</div>
<!-- Section 7: Surveyor Details -->
<div id="section_surveyor" class="mb-3" style="<?= in_array('surveyor', $sections) ? '' : 'display:none' ?>">
<div class="card mb-1">
<h4 class="m-1">
Surveyor Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseSeven" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseSeven" class="collapse show" data-parent="#section_surveyor">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-3"><label class="label-font-size">Surveyor Name</label><input type="text" class="form-control" name="surveyor_name" maxlength="255"></div>
<div class="form-group col-md-3"><label class="label-font-size">Contact Person</label><input type="text" class="form-control" name="surveyor_contact_person" maxlength="255"></div>
<div class="form-group col-md-3"><label class="label-font-size">Contact Number</label><input type="text" class="form-control" name="surveyor_contact_number" minlength="10" maxlength="15" pattern="^[0-9]+$"><div class="invalid-feedback">10-15 digits, numeric only.</div></div>
<div class="form-group col-md-3"><label class="label-font-size">Email</label><input type="email" class="form-control" name="surveyor_email"><div class="invalid-feedback">Invalid email format.</div></div>
<div class="form-group col-md-6"><label class="label-font-size">LOR</label><textarea class="form-control" name="lor" rows="2"></textarea></div>
<div class="form-group col-md-6"><label class="label-font-size">Surveyor Remarks</label><textarea class="form-control" name="surveyor_remarks" rows="2"></textarea></div>
</div>
</div>
</div>
</div>
</div>
<?php /* Section 8: Documents & Attachments — commented out, moved to Claim Files tab on edit page
<div id="accordion8" class="mb-3">
<div class="card mb-1">
<h4 class="m-1">
Documents & Attachments
<a class="text-dark float-right" data-toggle="collapse" href="#collapseEight" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseEight" class="collapse show" data-parent="#accordion8">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-12"><label class="label-font-size">Google Drive Links</label><textarea class="form-control" name="google_drive_links" rows="2"></textarea></div>
<div class="form-group col-md-6"><label class="label-font-size">Documents Required</label><textarea class="form-control" name="documents_required" rows="2"></textarea></div>
<div class="form-group col-md-6"><label class="label-font-size">Documents Submitted</label><textarea class="form-control" name="documents_submitted" rows="2"></textarea></div>
<div class="form-group col-md-6"><label class="label-font-size">Pending Documents</label><textarea class="form-control" name="pending_documents" rows="2"></textarea></div>
<div class="form-group col-md-3"><label class="label-font-size">ETA for Documents</label><input type="text" class="form-control date-picker" name="eta_for_documents" placeholder="dd-mm-yyyy"></div>
</div>
</div>
</div>
</div>
</div>
*/ ?>
<!-- Section 9: Settlement Details -->
<div id="section_settlement" class="mb-3" style="<?= in_array('settlement', $sections) ? '' : 'display:none' ?>">
<div class="card mb-1">
<h4 class="m-1">
Settlement Details
<a class="text-dark float-right" data-toggle="collapse" href="#collapseNine" aria-expanded="true">
<i class="mdi mdi-chevron-down mr-1 text-primary" style="font-size: 28px;"></i>
</a>
</h4>
<div id="collapseNine" class="collapse show" data-parent="#section_settlement">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-4"><label class="label-font-size">Loss Assessed Value</label><input type="number" class="form-control" name="loss_assessed_value" step="0.01" min="0"><div class="invalid-feedback">Must be a valid number.</div></div>
<div class="form-group col-md-4"><label class="label-font-size">Settled Amount</label><input type="number" class="form-control" name="settled_amount" step="0.01" min="0"><div class="invalid-feedback">Must be a valid number.</div></div>
<div class="form-group col-md-4"><label class="label-font-size">Settlement UTR</label><input type="text" class="form-control" name="settlement_utr" maxlength="100"><div class="invalid-feedback">Max 100 characters.</div></div>
</div>
</div>
</div>
</div>
</div>
<div class="text-right mt-3">
<button type="button" class="btn btn-primary" onclick="submitNonEbClaim()">Create Claim</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
// Asset add/remove
var assetIndex = 1;
function addAssetRow() {
assetIndex++;
var html = '<div class="form-row asset-row" id="asset_row_'+assetIndex+'">' +
'<div class="form-group col-md-3"><input type="text" class="form-control" name="asset_id_code[]" placeholder="Asset ID/Code"></div>' +
'<div class="form-group col-md-2"><input type="text" class="form-control" name="serial_no[]" placeholder="Serial No"></div>' +
'<div class="form-group col-md-2"><input type="text" class="form-control" name="vehicle_no[]" placeholder="Vehicle No"></div>' +
'<div class="form-group col-md-4"><input type="text" class="form-control" name="asset_description[]" placeholder="Description"></div>' +
'<div class="form-group col-md-1 d-flex align-items-end"><button type="button" class="btn btn-danger btn-sm" onclick="removeAssetRow('+assetIndex+')"><i class="mdi mdi-delete"></i></button></div>' +
'</div>';
$('#asset_container').append(html);
}
function removeAssetRow(idx) { $('#asset_row_' + idx).remove(); }
// Store branch & policy & contact data after client fetch
var noneb_policy_list = {};
var noneb_contact_list = {};
function appendBranches(data) {
$('#branch_id').empty();
$('#branch_id').append($('<option>', { value: '', text: 'Select Branch' }));
$.each(data, function(index, item) {
$('#branch_id').append($('<option>', { value: item.id, text: item.branch_name }));
});
}
function appendPolicies(data) {
$('#client_policy_id').empty();
$('#client_policy_id').append($('<option>', { value: '', text: 'Select Policy' }));
$.each(data, function(index, p) {
var option = $('<option>', {
value: p.id,
text: (p.policy_type || '') + ' - ' + (p.policy_no || '')
});
var insurerDisplay = (p.insurer_short_name || p.insurer_name || '');
if (p.insurer_branch_code) { insurerDisplay += ' - ' + p.insurer_branch_code; }
option.attr('data-insurer', p.insurer_id || '');
option.attr('data-insurer-name', insurerDisplay);
option.attr('data-policy-no', p.policy_no || '');
option.attr('data-policy-type', p.policy_type || '');
option.attr('data-start-date', p.policy_start_date || '');
option.attr('data-end-date', p.policy_end_date || '');
$('#client_policy_id').append(option);
});
}
function resetBranch() {
$('#branch_id').empty().append($('<option>', { value: '', text: 'Select Branch' }));
}
function resetPolicy() {
$('#client_policy_id').empty().append($('<option>', { value: '', text: 'Select Policy' }));
$('#insurer_id').val('');
$('#insurer_name_display').val('');
$('#policy_no').val('');
$('#client_policy_id_hidden').val('');
$('#policy_start_date').val('');
$('#policy_end_date').val('');
}
function resetContact() {
$('input[name="insured_contact_name"]').val('');
$('input[name="insured_contact_number"]').val('');
$('input[name="insured_contact_email"]').val('');
}
function formatDate(dateStr) {
if (!dateStr) return '';
var str = dateStr.toString();
var months = {Jan:'01',Feb:'02',Mar:'03',Apr:'04',May:'05',Jun:'06',Jul:'07',Aug:'08',Sep:'09',Oct:'10',Nov:'11',Dec:'12'};
// Handle "12-Feb-2026 05:30 am" or "12-Feb-2026"
var m = str.match(/^(\d{1,2})-([A-Za-z]{3})-(\d{4})/);
if (m) {
return ('0' + m[1]).slice(-2) + '-' + (months[m[2]] || '00') + '-' + m[3];
}
// Handle "2026-02-12" or "2026-02-12 00:00:00"
var m2 = str.match(/^(\d{4})-(\d{2})-(\d{2})/);
if (m2) {
return m2[3] + '-' + m2[2] + '-' + m2[1];
}
return str;
}
// Clear all validation states
function clearValidation() {
$('#nonEbClaimForm .is-invalid').removeClass('is-invalid');
$('#nonEbClaimForm .is-invalid-select2').removeClass('is-invalid-select2');
}
// Mark field invalid
function setInvalid(field, msg) {
var $el = $(field);
$el.addClass('is-invalid');
if (msg) {
var $fb = $el.siblings('.invalid-feedback');
if ($fb.length) $fb.text(msg);
}
}
// Validate form - returns true if valid
function validateNonEbForm() {
clearValidation();
var errors = [];
var firstInvalid = null;
function markError(selector, msg) {
var $el = $(selector);
if ($el.length) {
$el.addClass('is-invalid');
var $fb = $el.siblings('.invalid-feedback');
if ($fb.length) $fb.text(msg);
}
errors.push(msg);
if (!firstInvalid) firstInvalid = $el;
}
function markSelect2Error(selector, msg) {
var $el = $(selector);
$el.next('.select2-container').find('.select2-selection').addClass('is-invalid-select2');
errors.push(msg);
if (!firstInvalid) firstInvalid = $el;
}
// --- Required fields ---
// Client
if (!$('#client_select').val()) {
markSelect2Error('#client_select', 'Client is required.');
}
// Branch
if (!$('#branch_id').val()) {
markSelect2Error('#branch_id', 'Branch is required.');
}
// Account Manager
if (!$('#acm_id').val()) {
markSelect2Error('#acm_id', 'Account Manager is required.');
}
// Status
if (!$('#claim_status_id').val()) {
markError('#claim_status_id', 'Status is required.');
}
// Contact Name - required, min 3, alphanumeric + space _ -
var contactName = $.trim($('input[name="insured_contact_name"]').val());
if (!contactName) {
markError('input[name="insured_contact_name"]', 'Contact Name is required.');
} else if (contactName.length < 3) {
markError('input[name="insured_contact_name"]', 'Min 3 characters.');
} else if (!/^[a-zA-Z0-9\s_-]+$/.test(contactName)) {
markError('input[name="insured_contact_name"]', 'Only letters, numbers, spaces, hyphens, underscores.');
}
// Contact Number - required, numeric, 10-15 digits
var contactNum = $.trim($('input[name="insured_contact_number"]').val());
if (!contactNum) {
markError('input[name="insured_contact_number"]', 'Contact Number is required.');
} else if (!/^[0-9]+$/.test(contactNum)) {
markError('input[name="insured_contact_number"]', 'Must be numeric only.');
} else if (contactNum.length < 10 || contactNum.length > 15) {
markError('input[name="insured_contact_number"]', 'Must be 10-15 digits.');
}
// Contact Email - optional, validate format if provided
var contactEmail = $.trim($('input[name="insured_contact_email"]').val());
if (contactEmail && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(contactEmail)) {
markError('input[name="insured_contact_email"]', 'Invalid email format.');
}
// Nature of Loss - required, min 3
var natureOfLoss = $.trim($('input[name="nature_of_loss"]').val());
if (!natureOfLoss) {
markError('input[name="nature_of_loss"]', 'Nature of Loss is required.');
} else if (natureOfLoss.length < 3) {
markError('input[name="nature_of_loss"]', 'Min 3 characters.');
}
// Loss Location - required
if (!$.trim($('input[name="loss_location"]').val())) {
markError('input[name="loss_location"]', 'Loss Location is required.');
}
// Loss Date - required
if (!$.trim($('input[name="loss_date"]').val())) {
markError('input[name="loss_date"]', 'Loss Date is required.');
}
// Loss Estimate - optional, numeric
var lossEst = $.trim($('input[name="loss_estimate"]').val());
if (lossEst && isNaN(lossEst)) {
markError('input[name="loss_estimate"]', 'Must be a valid number.');
}
// Claim Number - optional, pattern
var claimNum = $.trim($('input[name="claim_number"]').val());
if (claimNum && !/^[a-zA-Z0-9\/_-]+$/.test(claimNum)) {
markError('input[name="claim_number"]', 'Only letters, numbers, /, - allowed.');
}
// Nhance Ref No - optional, max 100
var nhanceRef = $.trim($('input[name="nhance_claim_ref_no"]').val());
if (nhanceRef && nhanceRef.length > 100) {
markError('input[name="nhance_claim_ref_no"]', 'Max 100 characters.');
}
// --- Surveyor fields (only if section visible) ---
if ($('#section_surveyor').is(':visible')) {
var survContactNum = $.trim($('input[name="surveyor_contact_number"]').val());
if (survContactNum) {
if (!/^[0-9]+$/.test(survContactNum)) {
markError('input[name="surveyor_contact_number"]', 'Must be numeric only.');
} else if (survContactNum.length < 10 || survContactNum.length > 15) {
markError('input[name="surveyor_contact_number"]', 'Must be 10-15 digits.');
}
}
var survEmail = $.trim($('input[name="surveyor_email"]').val());
if (survEmail && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(survEmail)) {
markError('input[name="surveyor_email"]', 'Invalid email format.');
}
}
// --- Settlement fields (only if section visible) ---
if ($('#section_settlement').is(':visible')) {
var lossAssessed = $.trim($('input[name="loss_assessed_value"]').val());
if (lossAssessed && isNaN(lossAssessed)) {
markError('input[name="loss_assessed_value"]', 'Must be a valid number.');
}
var settledAmt = $.trim($('input[name="settled_amount"]').val());
if (settledAmt && isNaN(settledAmt)) {
markError('input[name="settled_amount"]', 'Must be a valid number.');
}
var settlementUtr = $.trim($('input[name="settlement_utr"]').val());
if (settlementUtr && settlementUtr.length > 100) {
markError('input[name="settlement_utr"]', 'Max 100 characters.');
}
}
// --- Asset: at least one filled row OR file uploaded ---
var hasAssetRow = false;
$('.asset-row').each(function() {
var $inputs = $(this).find('input');
$inputs.each(function() {
if ($.trim($(this).val())) { hasAssetRow = true; return false; }
});
if (hasAssetRow) return false;
});
var assetFile = $('#asset_file')[0].files.length > 0;
if (assetFile) {
var fileName = $('#asset_file')[0].files[0].name.toLowerCase();
var allowedExts = ['.xlsx', '.xls', '.csv', '.pdf'];
var validExt = allowedExts.some(function(ext) { return fileName.endsWith(ext); });
if (!validExt) {
markError('#asset_file', 'Only Excel (.xlsx, .xls, .csv) or PDF (.pdf) files allowed.');
assetFile = false;
} else if (!$.trim($('textarea[name="loss_description"]').val())) {
markError('textarea[name="loss_description"]', 'Loss Description is required when uploading an asset file.');
}
}
if (!hasAssetRow && !assetFile) {
$('#asset_section_error').show();
errors.push('Please fill at least one asset row or upload an asset file.');
if (!firstInvalid) firstInvalid = $('#asset_container');
} else {
$('#asset_section_error').hide();
}
// Show errors & scroll to first invalid
if (errors.length > 0) {
errors.forEach(function(e) { toastr.error(e); });
if (firstInvalid && firstInvalid.length) {
// Expand collapsed section if needed
var $collapse = firstInvalid.closest('.collapse');
if ($collapse.length && !$collapse.hasClass('show')) {
$collapse.collapse('show');
}
$('html, body').animate({ scrollTop: firstInvalid.offset().top - 100 }, 300);
firstInvalid.focus();
}
return false;
}
return true;
}
// Submit
function submitNonEbClaim() {
if (!validateNonEbForm()) return;
var formData = new FormData(document.getElementById('nonEbClaimForm'));
$.ajax({
url: base_url + 'non-eb-claim/create',
type: 'POST',
data: formData,
processData: false,
contentType: false,
headers: { 'X-Requested-With': 'XMLHttpRequest' },
success: function(response) {
if (typeof response === 'string') response = JSON.parse(response);
if (response.status == true) {
toastr.success(response.message);
window.location.href = base_url + 'non-eb-claim/list';
} else {
if (response.errors) { Object.values(response.errors).forEach(function(e) { toastr.error(e); }); }
else { toastr.error(response.message); }
}
},
error: function(xhr) {
if (xhr.status == 400) {
var resp = JSON.parse(xhr.responseText);
if (resp.errors) { Object.values(resp.errors).forEach(function(e) { toastr.error(e); }); }
} else {
toastr.error('Something went wrong. Please try again.');
}
}
});
}
// Init
$(document).ready(function() {
if (typeof flatpickr !== 'undefined') {
$('.date-picker').flatpickr({ dateFormat: 'd-m-Y', maxDate: 'today' });
}
// Initialize Select2
$('.select2-init').select2();
$('#client_select').select2();
$('#branch_id').select2();
$('#client_policy_id').select2();
// Client change -> fetch branches, policies & contacts
$('#client_select').on('change', function() {
var client_id = $(this).val();
resetBranch();
resetPolicy();
resetContact();
if (!client_id) {
$('#client_id').val('');
return;
}
$('#client_id').val(client_id);
noneb_policy_list = {};
noneb_contact_list = {};
$('.loader').fadeIn(); $('.loader-mask').fadeIn();
sendAjaxRequestForGlobal(base_url + 'non-eb-claim/getBranchAndPolicy', 'POST', {client_id: client_id}, function(response) {
if (response.status) {
noneb_policy_list = response.policy_data || {};
noneb_contact_list = response.contact_data || {};
appendBranches(response.branch_data || []);
} else {
toastr.error(response.message || 'Failed to load branches');
}
$('.loader').fadeOut(); $('.loader-mask').delay(350).fadeOut('slow');
}, function() {
$('.loader').fadeOut(); $('.loader-mask').delay(350).fadeOut('slow');
});
});
// Branch change -> populate policies & auto-fill contact from stored data
$('#branch_id').on('change', function() {
var branch_id = $(this).val();
resetPolicy();
resetContact();
if (!branch_id) return;
var policies = noneb_policy_list[branch_id] || [];
appendPolicies(policies);
// Auto-fill insured contact from level_contacts
var contact = noneb_contact_list[branch_id];
if (contact) {
$('input[name="insured_contact_name"]').val(contact.name || '');
$('input[name="insured_contact_number"]').val(contact.mobile || '');
$('input[name="insured_contact_email"]').val(contact.email || '');
}
});
// Policy change -> auto-fill insurer, policy no, dates & section
$('#client_policy_id').on('change', function() {
var sel = $(this).find(':selected');
$('#insurer_id').val(sel.data('insurer') || '');
$('#insurer_name_display').val(sel.data('insurer-name') || '');
$('#policy_no').val(sel.data('policy-no') || '');
$('#client_policy_id_hidden').val($(this).val());
$('#policy_type_display').val(sel.data('policy-type') || '');
var startRaw = sel.attr('data-start-date') || '';
var endRaw = sel.attr('data-end-date') || '';
// API returns YYYY-MM-DD, convert to dd-mm-yyyy
if (startRaw && startRaw.indexOf('-') > -1) {
var sp = startRaw.split('-');
if (sp[0].length === 4) startRaw = sp[2] + '-' + sp[1] + '-' + sp[0];
}
if (endRaw && endRaw.indexOf('-') > -1) {
var ep = endRaw.split('-');
if (ep[0].length === 4) endRaw = ep[2] + '-' + ep[1] + '-' + ep[0];
}
$('#policy_start_date').val(startRaw);
$('#policy_end_date').val(endRaw);
});
// Clear validation on input change
$('#nonEbClaimForm').on('input change', '.form-control', function() {
$(this).removeClass('is-invalid');
});
$('#nonEbClaimForm').on('change', 'select', function() {
$(this).removeClass('is-invalid');
$(this).next('.select2-container').find('.select2-selection').removeClass('is-invalid-select2');
});
// Clear asset section error on asset input or file change
$('#nonEbClaimForm').on('input', '.asset-row input', function() {
$('#asset_section_error').hide();
});
$('#asset_file').on('change', function() {
$(this).removeClass('is-invalid');
$('#asset_section_error').hide();
});
var closureRemarkStatuses = ['Claim Closed', 'Claim Rejected', 'Claim Withdrawn'];
function toggleClosureRemark() {
var selectedText = $('#claim_status_id option:selected').text().trim();
if (closureRemarkStatuses.indexOf(selectedText) !== -1) {
$('#closure_remark_row').show();
} else {
$('#closure_remark_row').hide();
$('#closure_remark').val('');
}
}
// Status change -> toggle sections + closure remark
$('#claim_status_id').on('change', function() {
var status_id = $(this).val();
var policy_type_id = $('#policy_type_id').val();
sendAjaxRequestForGlobal(base_url + 'non-eb-claim/getVisibleSections', 'POST', {claim_status_id: status_id, policy_type_id: policy_type_id}, function(response) {
if (response.status) {
var s = response.sections;
['surveyor','settlement'].forEach(function(sec) {
if (s.includes(sec)) { $('#section_'+sec).show(); } else { $('#section_'+sec).hide(); }
});
}
});
toggleClosureRemark();
});
});
</script>