3423 lines
144 KiB
PHP
3423 lines
144 KiB
PHP
<style>
|
||
h3 {
|
||
margin-bottom: 15px !important;
|
||
}
|
||
|
||
/* Table general styles */
|
||
table {
|
||
margin-bottom: 15px;
|
||
width: 1400px;
|
||
min-width: 1200px;
|
||
table-layout: fixed;
|
||
border-collapse: collapse;
|
||
word-wrap: break-word;
|
||
font-size: 11px;
|
||
}
|
||
|
||
/* Header and body cells */
|
||
th,
|
||
td {
|
||
padding: 2px 4px !important;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
line-height: 1 !important;
|
||
}
|
||
|
||
/* Table header */
|
||
th {
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
background-color: #f8f9fa;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
#policyTable,
|
||
#policyTable th,
|
||
#policyTable td {
|
||
border: 1px solid #007bff;
|
||
}
|
||
|
||
|
||
/* Fixed width columns */
|
||
#policyTable th:nth-child(1),
|
||
#policyTable td:nth-child(1) {
|
||
width: 110px !important;
|
||
min-width: 120px !important;
|
||
max-width: 120px !important;
|
||
word-wrap: break-word;
|
||
white-space: normal;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
|
||
}
|
||
|
||
#policyTable th:last-child,
|
||
#policyTable td:last-child {
|
||
width: 260px !important;
|
||
min-width: 260px !important;
|
||
max-width: 260px !important;
|
||
text-align: center;
|
||
white-space: nowrap;
|
||
text-align: center;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
/* Fixed width for particulars columns */
|
||
.particulars {
|
||
width: 400px !important;
|
||
min-width: 400px !important;
|
||
max-width: 400px !important;
|
||
word-wrap: break-word !important;
|
||
white-space: normal !important;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Fixed width for risk location columns */
|
||
.risk-col {
|
||
width: 180px !important;
|
||
min-width: 180px !important;
|
||
max-width: 180px !important;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Fixed width for index value columns */
|
||
.index-val-col {
|
||
width: 180px !important;
|
||
min-width: 180px !important;
|
||
max-width: 180px !important;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Fixed width for insurer columns */
|
||
.insurer-col {
|
||
width: 180px !important;
|
||
min-width: 180px !important;
|
||
max-width: 180px !important;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Fixed width for total sum insured columns */
|
||
.sum_insured {
|
||
width: 180px !important;
|
||
min-width: 180px !important;
|
||
max-width: 180px !important;
|
||
text-align: center !important;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Fixed width for index sum insured columns */
|
||
.index_sum_insured {
|
||
width: 180px !important;
|
||
min-width: 180px !important;
|
||
max-width: 180px !important;
|
||
text-align: center !important;
|
||
;
|
||
vertical-align: middle !important;
|
||
}
|
||
|
||
/* Compact rows */
|
||
#policyTable tbody tr {
|
||
height: 28px !important;
|
||
}
|
||
|
||
/* Compact rows */
|
||
#policyTable thead tr {
|
||
height: 30px !important;
|
||
/* Fixed row height */
|
||
}
|
||
|
||
/* Sub-options and checkboxes */
|
||
.sub-options {
|
||
margin-left: 15px;
|
||
margin-top: 3px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
.sub-options label {
|
||
margin-right: 12px;
|
||
}
|
||
|
||
input[type="checkbox"] {
|
||
transform: scale(0.9);
|
||
margin: 1px 3px;
|
||
}
|
||
|
||
/* Labels and forms */
|
||
label {
|
||
font-size: 11px;
|
||
margin-right: 12px;
|
||
margin-bottom: 3px;
|
||
}
|
||
|
||
.form-control {
|
||
font-size: 11px;
|
||
padding: 4px 6px;
|
||
}
|
||
|
||
/* Dropdown items */
|
||
.dropdown .btn {
|
||
padding: 2px 4px;
|
||
font-size: 10px;
|
||
margin: 0;
|
||
}
|
||
|
||
.dropdown-menu {
|
||
font-size: 11px;
|
||
min-width: 100px;
|
||
}
|
||
|
||
.dropdown-item {
|
||
padding: 4px 8px;
|
||
}
|
||
|
||
.dropdown-item .form-check-label{
|
||
position: relative !important;
|
||
left: 30px !important;
|
||
}
|
||
|
||
/* Policy header rows */
|
||
.policy-header-row {
|
||
cursor: pointer;
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
/* Hidden policy details rows */
|
||
.policy-detail-row {
|
||
display: none;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------------------------------------*/
|
||
|
||
|
||
/* Collapsed column styles */
|
||
.risk-col.collapsed
|
||
{
|
||
width: 40px !important;
|
||
min-width: 50px !important;
|
||
max-width: 50px !important;
|
||
overflow: visible !important;
|
||
position: relative;
|
||
padding: 5px !important;
|
||
}
|
||
|
||
.index-val-col.collapsed
|
||
{
|
||
width: 40px !important;
|
||
min-width: 50px !important;
|
||
max-width: 50px !important;
|
||
overflow: visible !important;
|
||
position: relative;
|
||
padding: 5px !important;
|
||
}
|
||
|
||
.insurer-col.collapsed
|
||
{
|
||
width: 40px !important;
|
||
min-width: 50px !important;
|
||
max-width: 50px !important;
|
||
overflow: visible !important;
|
||
position: relative;
|
||
padding: 5px !important;
|
||
}
|
||
|
||
/* Hide content when collapsed, but keep dropdown visible */
|
||
.risk-col.collapsed>div:not(.dropdown) {
|
||
display: none;
|
||
}
|
||
|
||
.insurer-col.collapsed>*:not(.dropdown) {
|
||
display: none;
|
||
}
|
||
|
||
.index-val-col.collapsed>*:not(.dropdown) {
|
||
display: none;
|
||
}
|
||
|
||
/* Position and style dropdown in collapsed state */
|
||
.risk-col.collapsed .dropdown,
|
||
.insurer-col.collapsed .dropdown,
|
||
.index-val-col.collapsed .dropdown
|
||
{
|
||
position: static !important;
|
||
display: block !important;
|
||
width: 100%;
|
||
text-align: center;
|
||
float: none !important;
|
||
}
|
||
|
||
.risk-col.collapsed .dropdown .btn,
|
||
.insurer-col.collapsed .dropdown .btn,
|
||
.index-val-col.collapsed .dropdown .btn
|
||
{
|
||
width: 100% !important;
|
||
height: 25px;
|
||
display: flex !important;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border: 1px solid #dee2e6;
|
||
background-color: #f8f9fa;
|
||
font-size: 13px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
/* Hide cell content when parent column is collapsed */
|
||
.risk-col.collapsed[data-risk-id="1"]~* td.risk-col[data-risk-id="1"],
|
||
.risk-col.collapsed[data-risk-id="2"]~* td.risk-col[data-risk-id="2"],
|
||
.risk-col.collapsed[data-risk-id="3"]~* td.risk-col[data-risk-id="3"]
|
||
{
|
||
width: 40px !important;
|
||
min-width: 40px !important;
|
||
max-width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
.insurer-col.collapsed[data-insurer-id="1"]~* td.insurer-col[data-insurer-id="1"],
|
||
.insurer-col.collapsed[data-insurer-id="2"]~* td.insurer-col[data-insurer-id="2"],
|
||
.insurer-col.collapsed[data-insurer-id="3"]~* td.insurer-col[data-insurer-id="3"]
|
||
{
|
||
width: 40px !important;
|
||
min-width: 40px !important;
|
||
max-width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
.index-val-col.collapsed[data-index-value-id="1"]~* td.index-val-col[data-index-value-id="1"],
|
||
.index-val-col.collapsed[data-index-value-id="2"]~* td.index-val-col[data-index-value-id="2"],
|
||
.index-val-col.collapsed[data-index-value-id="3"]~* td.index-val-col[data-index-value-id="3"]
|
||
{
|
||
width: 40px !important;
|
||
min-width: 40px !important;
|
||
max-width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
/* Apply collapsed state to matching data attributes */
|
||
th.risk-col.collapsed[data-risk-id="1"]~tbody tr td[data-risk-id="1"],
|
||
th.risk-col.collapsed[data-risk-id="2"]~tbody tr td[data-risk-id="2"],
|
||
th.risk-col.collapsed[data-risk-id="3"]~tbody tr td[data-risk-id="3"] {
|
||
width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
th.insurer-col.collapsed[data-insurer-id="1"]~tbody tr td[data-insurer-id="1"],
|
||
th.insurer-col.collapsed[data-insurer-id="2"]~tbody tr td[data-insurer-id="2"],
|
||
th.insurer-col.collapsed[data-insurer-id="3"]~tbody tr td[data-insurer-id="3"]
|
||
{
|
||
width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
th.index-val-col.collapsed[data-index-value-id="1"]~tbody tr td[data-index-value-id="1"],
|
||
th.index-val-col.collapsed[data-index-value-id="2"]~tbody tr td[data-index-value-id="2"],
|
||
th.index-val-col.collapsed[data-index-value-id="3"]~tbody tr td[data-index-value-id="3"]
|
||
{
|
||
width: 40px !important;
|
||
overflow: hidden;
|
||
text-indent: -9999px;
|
||
}
|
||
|
||
/* Transition effect */
|
||
.risk-col,
|
||
.insurer-col,
|
||
.index-val-col
|
||
{
|
||
transition: width 0.3s ease, min-width 0.3s ease, max-width 0.3s ease;
|
||
}
|
||
|
||
/* Table responsive wrapper */
|
||
.table-wrapper {
|
||
overflow-x: auto;
|
||
max-width: 100%;
|
||
}
|
||
|
||
/* Dropdown menu styling */
|
||
.dropdown-menu {
|
||
min-width: 180px;
|
||
}
|
||
|
||
/* Add visual indicator for collapsed state */
|
||
.risk-col.collapsed .dropdown-toggle::after,
|
||
.insurer-col.collapsed .dropdown-toggle::after ,
|
||
.index-val-col.collapsed .dropdown-toggle::after
|
||
{
|
||
content: "▶";
|
||
border: none;
|
||
vertical-align: middle;
|
||
font-size: 10px;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
.risk-col:not(.collapsed) .dropdown-toggle::after,
|
||
.insurer-col:not(.collapsed) .dropdown-toggle::after,
|
||
.index-val-col:not(.collapsed) .dropdown-toggle::after
|
||
{
|
||
content: "▼";
|
||
border: none;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
/*-------------------------------------------------------------------------------------*/
|
||
|
||
.table-scroll-container {
|
||
width: 100%;
|
||
overflow-x: auto;
|
||
overflow-y: visible;
|
||
}
|
||
|
||
/* Scrollbar styling */
|
||
.table-scroll-container::-webkit-scrollbar {
|
||
height: 5px;
|
||
}
|
||
|
||
.table-scroll-container::-webkit-scrollbar-track {
|
||
background: #f1f1f1;
|
||
/* border-radius: 3px; */
|
||
}
|
||
|
||
.table-scroll-container::-webkit-scrollbar-thumb {
|
||
background: #888;
|
||
/* border-radius: 3px; */
|
||
}
|
||
|
||
.table-scroll-container::-webkit-scrollbar-thumb:hover {
|
||
background: #555;
|
||
}
|
||
|
||
/* Content editable styling */
|
||
[contenteditable="true"]:focus {
|
||
outline: 2px solid #0d6efd;
|
||
outline-offset: -2px;
|
||
background-color: #f8f9fa;
|
||
}
|
||
|
||
.policy-collapse {
|
||
display: inline-block;
|
||
width: 20px; /* increased size */
|
||
height: 20px; /* increased size */
|
||
margin-left: 8px;
|
||
vertical-align: middle;
|
||
cursor: pointer;
|
||
position: relative;
|
||
border: 1.5px solid #4a90e2; /* slightly thicker */
|
||
border-radius: 50%;
|
||
background: #f8f9fa;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* Arrow pointing up (collapsed - will expand down when clicked) */
|
||
.policy-collapse::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 6px; /* adjusted for bigger circle */
|
||
left: 6px;
|
||
width: 6px; /* bigger arrow */
|
||
height: 6px;
|
||
border-right: 2px solid #4a90e2;
|
||
border-bottom: 2px solid #4a90e2;
|
||
transform: rotate(-135deg);
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
/* Arrow pointing down (expanded - will collapse up when clicked) */
|
||
.policy-collapse.expanded::before {
|
||
transform: rotate(45deg);
|
||
top: 5px;
|
||
left: 6px;
|
||
}
|
||
|
||
/* Hover effect */
|
||
.policy-collapse:hover {
|
||
background: #4a90e2;
|
||
transform: scale(1.2); /* slightly larger on hover */
|
||
}
|
||
|
||
.policy-collapse:hover::before {
|
||
border-color: white;
|
||
}
|
||
|
||
|
||
/* For check box switch */
|
||
.switch {
|
||
position: relative;
|
||
display: inline-block;
|
||
width: 54px;
|
||
height: 34px;
|
||
}
|
||
|
||
.switch input {
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
|
||
.slider {
|
||
position: absolute;
|
||
cursor: pointer;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: #ccc;
|
||
-webkit-transition: .4s;
|
||
transition: .4s;
|
||
}
|
||
|
||
.slider:before {
|
||
position: absolute;
|
||
content: "";
|
||
height: 19px;
|
||
width: 19px;
|
||
left: 4px;
|
||
bottom: 4px;
|
||
background-color: white;
|
||
-webkit-transition: .4s;
|
||
transition: .4s;
|
||
}
|
||
|
||
input:checked + .slider {
|
||
background-color: #2196F3;
|
||
}
|
||
|
||
input:focus + .slider {
|
||
box-shadow: 0 0 1px #2196F3;
|
||
}
|
||
|
||
input:checked + .slider:before {
|
||
-webkit-transform: translateX(26px);
|
||
-ms-transform: translateX(26px);
|
||
transform: translateX(26px);
|
||
}
|
||
|
||
/* Rounded sliders */
|
||
.slider.round {
|
||
border-radius: 34px;
|
||
}
|
||
|
||
.slider.round:before {
|
||
border-radius: 50%;
|
||
}
|
||
|
||
tbody .sum_insured, tbody .index_sum_insured, tbody .insurer-col {
|
||
cursor: pointer;
|
||
position: relative;
|
||
}
|
||
|
||
/* Skip cursor pointer for particulars rows */
|
||
tbody tr[data-key="particulars"] .sum_insured,
|
||
tbody tr[data-key="particulars"] .index_sum_insured,
|
||
tbody tr[data-key="particulars"] .insurer-col
|
||
{
|
||
cursor: default;
|
||
}
|
||
|
||
tbody .sum_insured:hover, tbody .index_sum_insured:hover, tbody .insurer-col:hover {
|
||
background-color: #e8f5e8 !important;
|
||
}
|
||
|
||
/* Skip hover effect for particulars rows */
|
||
tbody tr[data-key="particulars"] .sum_insured:hover,
|
||
tbody tr[data-key="particulars"] .index_sum_insured:hover,
|
||
tbody tr[data-key="particulars"] .insurer-col:hover
|
||
{
|
||
background-color: rgb(224, 254, 201) !important; /* Keep original color */
|
||
}
|
||
|
||
.cell-dropdown {
|
||
position: absolute;
|
||
top: 100%;
|
||
left: 0;
|
||
right: 0;
|
||
background: white;
|
||
border: 1px solid #ccc;
|
||
border-top: none;
|
||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||
z-index: 1000;
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
display: none;
|
||
}
|
||
|
||
.cell-dropdown-item {
|
||
padding: 8px 12px;
|
||
cursor: pointer;
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
|
||
.cell-dropdown-item:hover {
|
||
background-color: #f0f8ff;
|
||
}
|
||
|
||
.cell-dropdown-item.selected {
|
||
background-color: #007bff;
|
||
color: white;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.cell-dropdown-item.selected:hover {
|
||
background-color: #0056b3;
|
||
}
|
||
|
||
.cell-dropdown-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.btn-add-row, .btn-remove-row {
|
||
padding: 2px 6px;
|
||
font-size: 16px;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
</style>
|
||
|
||
<style>
|
||
|
||
#policyCheckboxes {
|
||
max-width: 100%;
|
||
margin: 0 auto;
|
||
background: white;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
/* Hide the actual checkbox */
|
||
#policyCheckboxes input[type="checkbox"] {
|
||
position: absolute;
|
||
opacity: 0;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Style the labels as compact buttons */
|
||
#policyCheckboxes label {
|
||
display: inline-block;
|
||
margin: 2px;
|
||
padding: 4px 8px;
|
||
background-color: #ffffff;
|
||
border: 1px solid #e0e0e0;
|
||
border-radius: 15px;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
font-weight: 500;
|
||
text-align: center;
|
||
user-select: none;
|
||
position: relative;
|
||
min-width: 60px;
|
||
font-size: 0.75em;
|
||
height: 28px;
|
||
line-height: 18px;
|
||
}
|
||
|
||
/* Hover effect with your specified border */
|
||
#policyCheckboxes label:hover {
|
||
background-color: #f8f9fa;
|
||
border: 2px solid #007bff;
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 2px 6px rgba(0,123,255,0.2);
|
||
}
|
||
|
||
/* Checked state - Fixed for proper HTML structure */
|
||
#policyCheckboxes input[type="checkbox"]:checked + span,
|
||
#policyCheckboxes label:has(input[type="checkbox"]:checked)
|
||
{
|
||
background-color: #007bff !important;
|
||
color: white !important;
|
||
border-color: #007bff !important;
|
||
box-shadow: 0 2px 8px rgba(0,123,255,0.3) !important;
|
||
}
|
||
|
||
/* Fallback for browsers without :has support */
|
||
#policyCheckboxes input[type="checkbox"]:checked {
|
||
+ label {
|
||
background-color: #007bff !important;
|
||
color: white !important;
|
||
border-color: #007bff !important;
|
||
}
|
||
}
|
||
|
||
/* Fire sub-options styling - default same as main buttons */
|
||
.sub-options {
|
||
display: inline-block;
|
||
margin-left: 8px;
|
||
}
|
||
|
||
/* Sub-options default style (compact) */
|
||
.sub-options label {
|
||
background-color: #ffffff;
|
||
border: 1px solid #e0e0e0;
|
||
color: #333333;
|
||
font-size: 0.7em;
|
||
min-width: 55px;
|
||
padding: 3px 6px;
|
||
height: 26px;
|
||
line-height: 18px;
|
||
}
|
||
|
||
.sub-options label:hover {
|
||
background-color: #f8f9fa !important;
|
||
border: 2px solid rgba(253, 32, 106, 1) !important;
|
||
color: #333333 !important;
|
||
}
|
||
|
||
/* When sub-option checkbox is CHECKED - turn pink - Fixed */
|
||
.sub-options input[type="checkbox"]:checked + span,
|
||
.sub-options label:has(input[type="checkbox"]:checked) {
|
||
background-color: rgba(253, 32, 106, 1) !important;
|
||
border-color: #ee3390ff !important;
|
||
color: white !important;
|
||
}
|
||
|
||
/* Active/pressed effect */
|
||
#policyCheckboxes label:active {
|
||
transform: translateY(0);
|
||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||
}
|
||
|
||
/* Responsive design */
|
||
@media (max-width: 768px) {
|
||
#policyCheckboxes label {
|
||
margin: 1px;
|
||
font-size: 0.7em;
|
||
min-width: 50px;
|
||
padding: 3px 6px;
|
||
height: 24px;
|
||
line-height: 16px;
|
||
}
|
||
|
||
.sub-options {
|
||
margin-left: 4px;
|
||
}
|
||
|
||
.sub-options label {
|
||
margin: 1px;
|
||
min-width: 45px;
|
||
padding: 2px 4px;
|
||
font-size: 0.65em;
|
||
height: 22px;
|
||
line-height: 16px;
|
||
}
|
||
}
|
||
|
||
/* Focus accessibility */
|
||
#policyCheckboxes input[type="checkbox"]:focus + label {
|
||
outline: 1px solid #007bff;
|
||
outline-offset: 1px;
|
||
}
|
||
</style>
|
||
|
||
<h3>RFQ</h3>
|
||
|
||
<!-- Controls -->
|
||
<div>
|
||
<button class="btn btn-sm btn-secondary" id="addLocation">+ Add Risk Location</button>
|
||
<button class="btn btn-sm btn-primary" onclick="getJson()">Save</button>
|
||
<button class="btn btn-sm btn-info" id="addInsurer">+ Add Insurer</button>
|
||
<button class="btn btn-sm btn-success" onclick="generateTableFromLocal()">Generate Table</button>
|
||
</div>
|
||
|
||
<br>
|
||
|
||
<!-- Policies Checkbox -->
|
||
<div id="policyCheckboxes">
|
||
<label><input type="checkbox" class="policy" value="fire" id="fire_check_box"> Fire</label>
|
||
<label><input type="checkbox" class="policy" value="burglary" id="burglary_check_box"> Burglary</label>
|
||
<label><input type="checkbox" class="policy" value="flop" id="flop_check_box"> FLOP</label>
|
||
<label><input type="checkbox" class="policy" value="all_risk" id="all_risk_check_box"> All Risk</label>
|
||
<label><input type="checkbox" class="policy" value="MBD" id="MBD_check_box"> MBD</label>
|
||
<label><input type="checkbox" class="policy" value="EEI" id="EEI_check_box"> EEI</label>
|
||
<label><input type="checkbox" class="policy" value="fidelity" id="fidelity_check_box"> Fidelity</label>
|
||
<label><input type="checkbox" class="policy" value="money" id="money_check_box"> Money</label>
|
||
<label><input type="checkbox" class="policy" value="plate_glass" id="plate_glass_check_box"> Plate Glass</label>
|
||
<label><input type="checkbox" class="policy" value="neon_sign" id="neon_sign_check_box"> Neon Sign</label>
|
||
<label><input type="checkbox" class="policy" value="public_liability" id="public_liability_check_box"> Public
|
||
Liability</label>
|
||
<label><input type="checkbox" class="policy" value="pedal_cycle" id="pedal_cycle_check_box"> Pedal Cycle</label>
|
||
<label><input type="checkbox" class="policy" value="premium" id="premium_check_box"> Premium</label>
|
||
</div>
|
||
|
||
<br>
|
||
|
||
<!-- table div -->
|
||
<div class="table-wrapper table-scroll-container" id="container">
|
||
<table id="policyTable" class="table table-bordered">
|
||
<thead>
|
||
<tr id="policyHeader">
|
||
<th>Policy</th>
|
||
<th class="particulars">Particulars</th>
|
||
<!-- Risk Locations will be inserted here -->
|
||
<th class="sum_insured">Total Sum Insured</th>
|
||
<th class="index_sum_insured">
|
||
Index Sum Insured
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</th>
|
||
<!-- Insurers will be inserted here -->
|
||
<th>Action</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Insurer Selection Modal -->
|
||
<div class="modal fade" id="insurerModal" tabindex="-1" aria-labelledby="insurerModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="insurerModalLabel">Insurer</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div class="mb-4">
|
||
<select id="insurerSelect2" class="form-control" required>
|
||
<option value="">Select an insurer</option>
|
||
<?php if (isset($insurer) && !empty($insurer) && is_array($insurer)) { ?>
|
||
<?php foreach ($insurer as $key => $value): ?>
|
||
<option data-id="<?= esc($value['id'] . '-' . $value['insurer_id']) ?>" value="<?= esc($value['insurer_name'] . '-' . $value['branch_code']) ?>"><?= esc($value['insurer_name'] . '-' . $value['branch_code']) ?></option>
|
||
<?php endforeach; ?>
|
||
<?php } ?>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-primary" id="insurer_save">Save</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Risk Location Details Modal -->
|
||
<div class="modal fade" id="riskLocationModal" tabindex="-1" aria-labelledby="riskLocationModalLabel"
|
||
aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<!-- wider modal for 3 columns -->
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="riskLocationModalLabel">Add Risk Location Details</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="riskLocationForm">
|
||
<div class="form-row">
|
||
|
||
<!-- Location Name -->
|
||
<div class="form-group col-md-4">
|
||
<label for="locationName" class="form-label">Location Name</label>
|
||
<input type="text" class="form-control" id="locationName" placeholder="e.g., Mumbai Branch"
|
||
value="Karnataka Branch" required>
|
||
</div>
|
||
|
||
<!-- Address -->
|
||
<div class="form-group col-md-4">
|
||
<label for="locationAddress" class="form-label">Address</label>
|
||
<textarea class="form-control" id="locationAddress" rows="2"
|
||
placeholder="Enter full address" required>123, MG Road, Indiranagar, Bengaluru, Karnataka 560038, India</textarea>
|
||
</div>
|
||
|
||
<!-- Constructio -->
|
||
<div class="form-group col-md-4">
|
||
<label for="construction_type" class="form-label">Construction Type</label>
|
||
<select class="form-control" id="construction_type" required>
|
||
<option value="">Select</option>
|
||
<option value="Kutcha">Kutcha</option>
|
||
<option value="Pucca">Pucca</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Basement -->
|
||
<div class="form-group col-md-4">
|
||
<label class="switch" style="position: relative;top: 22px;left: 0px;">
|
||
<input id="has_basement" type="checkbox" name="has_basement">
|
||
<span class="slider round" style="height: 27px;"></span>
|
||
</label>
|
||
|
||
<label for="has_basement" style="position: relative;top: 25px;left: 0px;">Basement</label>
|
||
</div>
|
||
|
||
<!-- Basement Utilisation -->
|
||
<div class="form-group col-md-4 d-none" id="basementUtilisationDiv">
|
||
<label for="basement_utilisation" class="form-label">Basement Utilisation</label>
|
||
<textarea class="form-control" id="basement_utilisation" rows="2"
|
||
placeholder="Describe basement usage"></textarea>
|
||
</div>
|
||
|
||
<!-- Occupancy Risk -->
|
||
<div class="form-group col-md-4">
|
||
<label for="occupancy_risk" class="form-label">Occupancy Risk</label>
|
||
<select class="form-control occupancy-risk" id="occupancy_risk">
|
||
<option value="">Select</option>
|
||
<option value="OR1">Occupancy 1</option>
|
||
<option value="OR2">Occupancy 2</option>
|
||
<option value="OR3">Occupancy 3</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- IIB Code -->
|
||
<div class="form-group col-md-4">
|
||
<label for="iib_code" class="form-label">IIB Code</label>
|
||
<input type="text" class="form-control" id="iib_code"
|
||
placeholder="Auto-filled from Occupancy Risk" required>
|
||
</div>
|
||
|
||
<!-- Business Description -->
|
||
<div class="form-group col-md-8">
|
||
<label for="business_description" class="form-label">Business Description</label>
|
||
<textarea class="form-control" id="business_description" rows="2"
|
||
placeholder="Enter business description"></textarea>
|
||
</div>
|
||
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-primary" id="saveRiskLocation">Add Location</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<script>
|
||
|
||
// let policyData = {
|
||
|
||
// "fire": {
|
||
// "particulars": {
|
||
// "fire_building": " <strong> Building : </strong> All Buildings and civil structures including Super Structure, plinth & foundation, other Civil Structures, Roads, gates, pavements, internal Pathways, stone works, stone arts etc., Street Lights, Landscaping, Play Area, Culvert, drainage, retaining walls, etc. Compound Wall including utility, admin block, security office and all other similar structures pertaining to insured within the premises, Kutcha Constructions, Temporary Sheds, parking Sheds, Shelters, Civil Structure / bed for DG set / Genset, Interlocking Pathways, LVP Pathway Widening, Roads including internal roads, Mini Conference, Swimming pool, rest areas, shelters, Kitchen-Exhaust System Work, Red Earth for Garden, Arch Wall, Retaining Wall, Boundary, compound walls, Water, Vetrified Tiles, Capital Additions related to Building. All other civil structures related to insured at the covered premises.",
|
||
// "fire_content": "<strong> Content : </strong> Contents, AC & Accessories, FFF, P & M & Accessories, Electronic Equipments & Accessories, Electrical Items & Fittings, Plumbing Items, Structural Products, Structures, Leasehold Work including Civil Works, Interiors Temporary Structures including Sheds and Containers, Interiors, Plate Glass, Workstations, Office Equipments, Consumables, Goods held in commission / Trust, Trading Goods, Other contents / Items related to Insured's trade, Other Contents related to Insured's Trade",
|
||
// },
|
||
// "risk_split_up": [
|
||
// "Building",
|
||
// "Contents",
|
||
// "Plant and Machinery",
|
||
// "Electronic Equipments",
|
||
// "FFF",
|
||
// "Office Equipments / Contents",
|
||
// "Stocks (RM, WIP, SFG, FG, PM & Any others stocks related to Insured's Trade)"
|
||
// ],
|
||
// "add_on_covers": [
|
||
// "STFI (Storm Tempest Flood & Inundation)",
|
||
// "EQ (EarthQuake)",
|
||
// "Terrorism",
|
||
// "Designated Property Clause",
|
||
// "Agreed Bank Clause",
|
||
// "Reinstatement Value Clause",
|
||
// "Local Authorites Clause",
|
||
// "Payment on Account Clause of 75% of Claim amount on recommendation of Surveyor"
|
||
// ],
|
||
// "inbuilt_covers": [
|
||
// "Fire and Allied Perils, Including STFI",
|
||
// "Costs for Removal of debris upto 2 % of the claim amount",
|
||
// "Additions, alterations or extensions upto 15% of the Sum Insured for that item (excluding stocks)",
|
||
// "Temporary removal of stocks upto 10% of value",
|
||
// "Start-Up Expenses upto 5 Lakhs",
|
||
// "Costs compelled by Municipal Regulations",
|
||
// "Cover for Specific Contents- Money upto 50,000",
|
||
// "Cover for documents upto 50,000",
|
||
// "Cover for computer programmes, information and data upto 5 Lakh",
|
||
// "Cover for personal effects of employees, Directors and visitors upto 15,000"
|
||
// ],
|
||
// "excess": "Policy Fire"
|
||
// },
|
||
// "burglary": {
|
||
// "particulars": "Contents, AC & Accessories, FFF, P & M & Accessories, Electronic Equipments & Accessories, Electrical Items & Fittings, Plumbing Items, Structural Products, Structures, Leasehold Work including Civil Works, Interiors Temporary Structures including Sheds and Containers, Interiors, Plate Glass, Workstations, Office Equipments, Consumables, Goods held in commission / Trust, Trading Goods, Other contents / Items related to Insured's trade, Other Contents related to Insured's Trade",
|
||
// "risk_split_up": [
|
||
// "Building",
|
||
// "Contents",
|
||
// "Furniture/Office Equipment",
|
||
// "Plant and Machinery",
|
||
// "Electrical Fittings",
|
||
// "Stock In Process",
|
||
// "Raw Material",
|
||
// "Stock"
|
||
// ],
|
||
// "additional_coverage": [
|
||
// "First Loss Limit",
|
||
// "Theft & RSMD",
|
||
// "Waiver of FIR, NTC and Final Investigation reports",
|
||
// "Goods held in trust are covered if the same is included in TSI"
|
||
// ],
|
||
// "excess": "Policy Burglary"
|
||
// },
|
||
// "flop": {
|
||
// "particulars": "Loss of Gross Profit due to peril covered in the Standard Fire & Special Perils Policy.",
|
||
// "risk_split_up": ["Sample Flop Risk Split Up"],
|
||
// "flop_coverage": [
|
||
// "Sum Insured",
|
||
// "Indemnity Period",
|
||
// "Basis of Sum Insured / Indemnification",
|
||
// "Insurance on Gross Profit"
|
||
// ],
|
||
// "add_on_coverage": [
|
||
// "Earthquake",
|
||
// "STFI (Storm, Tempest, Flood and Inundation)",
|
||
// "Terrorism",
|
||
// "Prevention of Access",
|
||
// "Auditors Fees",
|
||
// "Alternate basis clause",
|
||
// "Claims preparation clause",
|
||
// "Accumulated stocks clause"
|
||
// ],
|
||
// "excess": "Policy Flop"
|
||
// },
|
||
// "all_risk": {
|
||
// "particulars": "Laptops, Notebooks Computers, Tablets, Mobile Phones & Cameras, projectors, and other portable equipments.",
|
||
// "risk_split_up": ["Sample Risk Split Up"],
|
||
// "additional_coverage": [
|
||
// "RSMD",
|
||
// "Terrorism",
|
||
// "Coverage",
|
||
// "Electrical and Mechanical Breakdown",
|
||
// "Asset warranty clause",
|
||
// "Water/liquid damage cover",
|
||
// "No restriction on age of the asset / equipments - all the equipments / assets to be covered"
|
||
// ],
|
||
// "excess": "Policy All Risk"
|
||
// },
|
||
// "MBD": {
|
||
// "particulars": "Plant & Machinery including and not limited to DG Set, Lifts, Refrigerator, Cooler, Air Conditioner, Pump, Water Dispenser, Freezer, Oven, Motor, Transformer, etc. and other P&M related to Insured",
|
||
// "risk_split_up": ["Sample Risk Split Up"],
|
||
// "additional_coverage": [
|
||
// "Accidental / Mechanical breakdown",
|
||
// "Express Freight",
|
||
// "Air Freight",
|
||
// "Third Party Liability (Limited upto 10% of Individual Equipment Value)",
|
||
// "Owner's Surrounding Property",
|
||
// "Reinstatement Value Clause",
|
||
// "Escalation--10% of Individual Equipment Value"
|
||
// ],
|
||
// "excess": "Policy MBD Excess"
|
||
// },
|
||
// "EEI": {
|
||
// "particulars": "Various electronic Items including and not limited to Computer, Printer, CCTV, Telephone Instruments, Control System, Router, Switches, BMS System, DVD Player, Music Systems, Scanner, Photo Copier and Electronic Lock System, and other electronic items.",
|
||
// "risk_split_up": ["Sample Risk Split Up"],
|
||
// "additional_coverage": [
|
||
// "As per Electronic Equipment Policy including STFI, EQ, Terrorism",
|
||
// "Accidental / Electrical Breakdown",
|
||
// "Damage to electronic equipment incl. systems software, cost of external data media, cost of reconstruction of data",
|
||
// "Waiver of FIR, NTC and Final Investigation reports for claims upto INR 2 Lacs",
|
||
// "No restriction on age of the asset / equipments - all the equipments / assets to be covered",
|
||
// "Depreciation subject to 10% PA subject to maximum of 50%",
|
||
// "Reinstatement Value Clause"
|
||
// ],
|
||
// "excess": "Policy EEI"
|
||
// },
|
||
// "fidelity": {
|
||
// "particulars": [
|
||
// "Dishonest acts / Fraudulent Act of employees",
|
||
// "No Of Employees",
|
||
// "Per Person Limit",
|
||
// "Third Party Fidelity Cover"
|
||
// ],
|
||
// "risk_split_up": ["Sample Fidelity Risk Split Up"],
|
||
// "additional_coverage": [
|
||
// "Any One Person",
|
||
// "Including contract Employees",
|
||
// "Un-named Basis",
|
||
// "Employees are covered without any selection",
|
||
// "Floater Cover"
|
||
// ],
|
||
// "excess": "Policy Fidelity"
|
||
// },
|
||
// "money": {
|
||
// "particulars": [
|
||
// "Money in transit",
|
||
// "Money in Safe",
|
||
// "Money in Counter",
|
||
// "Annual Transit"
|
||
// ],
|
||
// "risk_split_up": ["Sample Money Split up"],
|
||
// "additional_coverage": [
|
||
// "RSMD",
|
||
// "Terrorism",
|
||
// "Cash by Public Transport/Vehicle",
|
||
// "Cash by Two Wheeler",
|
||
// "Cash should be carried by the authorised/designated employee of the company. Employee should be read as Pay Rolls of the company including Contract Employee",
|
||
// "Employee means any such person as authorised by the Employer either expressly or impliedly in the course of employment",
|
||
// "Place of Transit:- Cash in Transit Between Bank to office/ Resorts and offices / resorts to bank and Viceversa"
|
||
// ],
|
||
// "excess": "Policy Money"
|
||
// },
|
||
// "plate_Glass": {
|
||
// "particulars": "Glass items, including frames and fittings",
|
||
// "risk_split_up": ["Sample Plate Glass Risk Split up"],
|
||
// "coverage": [
|
||
// "Accidental Damage",
|
||
// "RSMD",
|
||
// "Waiver of Survey upto INR 2 Lacs",
|
||
// "Including frames and fittings",
|
||
// "Self destruction due to climatic change / due to temp"
|
||
// ],
|
||
// "excess": "Policy Plate Glass"
|
||
// },
|
||
// "neon_sign": {
|
||
// "particulars": "Neon Tubes, Frame, Electrical Components, Glass Panels, Lettering and Graphics",
|
||
// "risk_split_up": ["Sample Neon Sign Risk split up"],
|
||
// "coverage": [
|
||
// "Accidental/Physical/Electronic Damage",
|
||
// "RSMD",
|
||
// "Waiver of Survey upto INR 2 Lacs"
|
||
// ],
|
||
// "excess": "Policy Neon"
|
||
// },
|
||
// "public_liability": {
|
||
// "particulars": [
|
||
// "As per Public Liability including extensions such as Lift Liability & Food & Beverage: AOA : AOY - 1:4",
|
||
// "AOA:AOY"
|
||
// ],
|
||
// "risk_split_up": ["Sample Public Liability Risk Split Up"],
|
||
// "coverage": [
|
||
// "AOG Perils Extension",
|
||
// "Third Party Includes visitors",
|
||
// "Owners / Tenants occupying the premises",
|
||
// "Terrorism",
|
||
// "Liability Arising out from use",
|
||
// "Ownership or operations of lifts elevators",
|
||
// "Food & Beverage Extn"
|
||
// ]
|
||
// },
|
||
// "pedal_cycle": {
|
||
// "particulars": "Financial protection against various risks associated with owning and using a bicycle or other pedal-powered vehicle.",
|
||
// "risk_split_up": ["Sample Pedal Cycle Risk Split Up"],
|
||
// "coverage": [
|
||
// "Coverage is Limited to Fire and Allied Perils including Eq as per AIFT",
|
||
// "Burglary including Theft and Impact Damage with in the radius of 50Kms from Insured Premises",
|
||
// "Reistatement Value Clause",
|
||
// "Accidental Damage Cover"
|
||
// ],
|
||
// "excess": "Policy Pedal Cycle"
|
||
// },
|
||
// "premium": {
|
||
// "premium": [
|
||
// "Premium",
|
||
// "GST (%)",
|
||
// "GST Amount (₹)",
|
||
// "Total",
|
||
// ]
|
||
// }
|
||
// };
|
||
|
||
let policyData = {
|
||
"fire": {
|
||
"particulars": {
|
||
"fire_building": " <strong> Building : </strong> All Buildings and civil structures including Super Structure, plinth & foundation, other Civil Structures, Roads, gates, pavements, internal Pathways, stone works, stone arts etc., Street Lights, Landscaping, Play Area, Culvert, drainage, retaining walls, etc. Compound Wall including utility, admin block, security office and all other similar structures pertaining to insured within the premises, Kutcha Constructions, Temporary Sheds, parking Sheds, Shelters, Civil Structure / bed for DG set / Genset, Interlocking Pathways, LVP Pathway Widening, Roads including internal roads, Mini Conference, Swimming pool, rest areas, shelters, Kitchen-Exhaust System Work, Red Earth for Garden, Arch Wall, Retaining Wall, Boundary, compound walls, Water, Vetrified Tiles, Capital Additions related to Building. All other civil structures related to insured at the covered premises.",
|
||
"fire_content": "<strong> Content : </strong> Contents, AC & Accessories, FFF, P & M & Accessories, Electronic Equipments & Accessories, Electrical Items & Fittings, Plumbing Items, Structural Products, Structures, Leasehold Work including Civil Works, Interiors Temporary Structures including Sheds and Containers, Interiors, Plate Glass, Workstations, Office Equipments, Consumables, Goods held in commission / Trust, Trading Goods, Other contents / Items related to Insured's trade, Other Contents related to Insured's Trade",
|
||
},
|
||
"risk_split_up": [
|
||
{ "name": "Building", "default_answer": "Agreed" },
|
||
{ "name": "Contents", "default_answer": "Agreed" },
|
||
{ "name": "Plant and Machinery", "default_answer": "Agreed" },
|
||
{ "name": "Electronic Equipments", "default_answer": "Agreed" },
|
||
{ "name": "FFF", "default_answer": "Agreed" },
|
||
{ "name": "Office Equipments / Contents", "default_answer": "Agreed" },
|
||
{ "name": "Stocks (RM, WIP, SFG, FG, PM & Any others stocks related to Insured's Trade)", "default_answer": "Agreed" }
|
||
],
|
||
"add_on_covers": [
|
||
{ "name": "STFI (Storm Tempest Flood & Inundation)", "default_answer": "Agreed" },
|
||
{ "name": "EQ (EarthQuake)", "default_answer": "Agreed" },
|
||
{ "name": "Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Designated Property Clause", "default_answer": "Agreed" },
|
||
{ "name": "Agreed Bank Clause", "default_answer": "Agreed" },
|
||
{ "name": "Reinstatement Value Clause", "default_answer": "Agreed" },
|
||
{ "name": "Local Authorites Clause", "default_answer": "Agreed" },
|
||
{ "name": "Payment on Account Clause of 75% of Claim amount...", "default_answer": "Agreed" }
|
||
],
|
||
"inbuilt_covers": [
|
||
{ "name": "Fire and Allied Perils, Including STFI", "default_answer": "Agreed" },
|
||
{ "name": "Costs for Removal of debris upto 2 % of the claim amount", "default_answer": "Agreed" },
|
||
{ "name": "Additions, alterations or extensions upto 15%", "default_answer": "Agreed" },
|
||
{ "name": "Temporary removal of stocks upto 10% of value", "default_answer": "Agreed" },
|
||
{ "name": "Start-Up Expenses upto 5 Lakhs", "default_answer": "Agreed" },
|
||
{ "name": "Costs compelled by Municipal Regulations", "default_answer": "Agreed" },
|
||
{ "name": "Cover for Specific Contents- Money upto 50,000", "default_answer": "Agreed" },
|
||
{ "name": "Cover for documents upto 50,000", "default_answer": "Agreed" },
|
||
{ "name": "Cover for computer programmes upto 5 Lakh", "default_answer": "Agreed" },
|
||
{ "name": "Cover for personal effects upto 15,000", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Fire"
|
||
},
|
||
|
||
"burglary": {
|
||
"particulars": "Contents, AC & Accessories, FFF, P & M & Accessories...",
|
||
"risk_split_up": [
|
||
{ "name": "Building", "default_answer": "Agreed" },
|
||
{ "name": "Contents", "default_answer": "Agreed" },
|
||
{ "name": "Furniture/Office Equipment", "default_answer": "Agreed" },
|
||
{ "name": "Plant and Machinery", "default_answer": "Agreed" },
|
||
{ "name": "Electrical Fittings", "default_answer": "Agreed" },
|
||
{ "name": "Stock In Process", "default_answer": "Agreed" },
|
||
{ "name": "Raw Material", "default_answer": "Agreed" },
|
||
{ "name": "Stock", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "First Loss Limit", "default_answer": "Agreed" },
|
||
{ "name": "Theft & RSMD", "default_answer": "Agreed" },
|
||
{ "name": "Waiver of FIR, NTC and Final Investigation reports", "default_answer": "Agreed" },
|
||
{ "name": "Goods held in trust covered if included in TSI", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Burglary"
|
||
},
|
||
|
||
"flop": {
|
||
"particulars": "Loss of Gross Profit due to peril covered...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Flop Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"flop_coverage": [
|
||
{ "name": "Sum Insured", "default_answer": "Agreed" },
|
||
{ "name": "Indemnity Period", "default_answer": "Agreed" },
|
||
{ "name": "Basis of Sum Insured / Indemnification", "default_answer": "Agreed" },
|
||
{ "name": "Insurance on Gross Profit", "default_answer": "Agreed" }
|
||
],
|
||
"add_on_coverage": [
|
||
{ "name": "Earthquake", "default_answer": "Agreed" },
|
||
{ "name": "STFI (Storm, Tempest, Flood and Inundation)", "default_answer": "Agreed" },
|
||
{ "name": "Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Prevention of Access", "default_answer": "Agreed" },
|
||
{ "name": "Auditors Fees", "default_answer": "Agreed" },
|
||
{ "name": "Alternate basis clause", "default_answer": "Agreed" },
|
||
{ "name": "Claims preparation clause", "default_answer": "Agreed" },
|
||
{ "name": "Accumulated stocks clause", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Flop"
|
||
},
|
||
|
||
"all_risk": {
|
||
"particulars": "Laptops, Notebooks Computers, Tablets, Mobile Phones & Cameras...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "RSMD", "default_answer": "Agreed" },
|
||
{ "name": "Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Coverage", "default_answer": "Agreed" },
|
||
{ "name": "Electrical and Mechanical Breakdown", "default_answer": "Agreed" },
|
||
{ "name": "Asset warranty clause", "default_answer": "Agreed" },
|
||
{ "name": "Water/liquid damage cover", "default_answer": "Agreed" },
|
||
{ "name": "No restriction on age of the asset", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy All Risk"
|
||
},
|
||
|
||
"MBD": {
|
||
"particulars": "Plant & Machinery including and not limited to DG Set, Lifts...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "Accidental / Mechanical breakdown", "default_answer": "Agreed" },
|
||
{ "name": "Express Freight", "default_answer": "Agreed" },
|
||
{ "name": "Air Freight", "default_answer": "Agreed" },
|
||
{ "name": "Third Party Liability (Limited upto 10%)", "default_answer": "Agreed" },
|
||
{ "name": "Owner's Surrounding Property", "default_answer": "Agreed" },
|
||
{ "name": "Reinstatement Value Clause", "default_answer": "Agreed" },
|
||
{ "name": "Escalation--10% of Individual Equipment Value", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy MBD Excess"
|
||
},
|
||
|
||
"EEI": {
|
||
"particulars": "Various electronic Items including and not limited to Computer, Printer, CCTV...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "As per Electronic Equipment Policy including STFI, EQ, Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Accidental / Electrical Breakdown", "default_answer": "Agreed" },
|
||
{ "name": "Damage to electronic equipment incl. software", "default_answer": "Agreed" },
|
||
{ "name": "Waiver of FIR/NTC for claims upto INR 2 Lacs", "default_answer": "Agreed" },
|
||
{ "name": "No restriction on age of the asset", "default_answer": "Agreed" },
|
||
{ "name": "Depreciation subject to 10% PA max 50%", "default_answer": "Agreed" },
|
||
{ "name": "Reinstatement Value Clause", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy EEI"
|
||
},
|
||
|
||
"fidelity": {
|
||
"particulars": [
|
||
{ "name": "Dishonest acts / Fraudulent Act of employees", "default_answer": "Agreed" },
|
||
{ "name": "No Of Employees", "default_answer": "Agreed" },
|
||
{ "name": "Per Person Limit", "default_answer": "Agreed" },
|
||
{ "name": "Third Party Fidelity Cover", "default_answer": "Agreed" }
|
||
],
|
||
"risk_split_up": [
|
||
{ "name": "Sample Fidelity Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "Any One Person", "default_answer": "Agreed" },
|
||
{ "name": "Including contract Employees", "default_answer": "Agreed" },
|
||
{ "name": "Un-named Basis", "default_answer": "Agreed" },
|
||
{ "name": "Employees covered without selection", "default_answer": "Agreed" },
|
||
{ "name": "Floater Cover", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Fidelity"
|
||
},
|
||
|
||
"money": {
|
||
"particulars": [
|
||
{ "name": "Money in transit", "default_answer": "Agreed" },
|
||
{ "name": "Money in Safe", "default_answer": "Agreed" },
|
||
{ "name": "Money in Counter", "default_answer": "Agreed" },
|
||
{ "name": "Annual Transit", "default_answer": "Agreed" }
|
||
],
|
||
"risk_split_up": [
|
||
{ "name": "Sample Money Split up", "default_answer": "Agreed" }
|
||
],
|
||
"additional_coverage": [
|
||
{ "name": "RSMD", "default_answer": "Agreed" },
|
||
{ "name": "Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Cash by Public Transport/Vehicle", "default_answer": "Agreed" },
|
||
{ "name": "Cash by Two Wheeler", "default_answer": "Agreed" },
|
||
{ "name": "Cash carried by authorised employee", "default_answer": "Agreed" },
|
||
{ "name": "Employee means payroll & contract", "default_answer": "Agreed" },
|
||
{ "name": "Place of Transit: Bank ↔ Office/Resorts", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Money"
|
||
},
|
||
|
||
"plate_Glass": {
|
||
"particulars": "Glass items, including frames and fittings",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Plate Glass Risk Split up", "default_answer": "Agreed" }
|
||
],
|
||
"coverage": [
|
||
{ "name": "Accidental Damage", "default_answer": "Agreed" },
|
||
{ "name": "RSMD", "default_answer": "Agreed" },
|
||
{ "name": "Waiver of Survey upto INR 2 Lacs", "default_answer": "Agreed" },
|
||
{ "name": "Including frames and fittings", "default_answer": "Agreed" },
|
||
{ "name": "Self destruction due to climatic change", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Plate Glass"
|
||
},
|
||
|
||
"neon_sign": {
|
||
"particulars": "Neon Tubes, Frame, Electrical Components, Glass Panels...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Neon Sign Risk split up", "default_answer": "Agreed" }
|
||
],
|
||
"coverage": [
|
||
{ "name": "Accidental/Physical/Electronic Damage", "default_answer": "Agreed" },
|
||
{ "name": "RSMD", "default_answer": "Agreed" },
|
||
{ "name": "Waiver of Survey upto INR 2 Lacs", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Neon"
|
||
},
|
||
|
||
"public_liability": {
|
||
"particulars": [
|
||
{ "name": "As per Public Liability including extensions", "default_answer": "Agreed" },
|
||
{ "name": "AOA:AOY", "default_answer": "Agreed" }
|
||
],
|
||
"risk_split_up": [
|
||
{ "name": "Sample Public Liability Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"coverage": [
|
||
{ "name": "AOG Perils Extension", "default_answer": "Agreed" },
|
||
{ "name": "Third Party Includes visitors", "default_answer": "Agreed" },
|
||
{ "name": "Owners / Tenants occupying the premises", "default_answer": "Agreed" },
|
||
{ "name": "Terrorism", "default_answer": "Agreed" },
|
||
{ "name": "Liability Arising out from use", "default_answer": "Agreed" },
|
||
{ "name": "Ownership or operations of lifts elevators", "default_answer": "Agreed" },
|
||
{ "name": "Food & Beverage Extn", "default_answer": "Agreed" }
|
||
]
|
||
},
|
||
|
||
"pedal_cycle": {
|
||
"particulars": "Financial protection against risks of bicycles...",
|
||
"risk_split_up": [
|
||
{ "name": "Sample Pedal Cycle Risk Split Up", "default_answer": "Agreed" }
|
||
],
|
||
"coverage": [
|
||
{ "name": "Coverage is Limited to Fire and Allied Perils", "default_answer": "Agreed" },
|
||
{ "name": "Burglary incl. Theft and Impact Damage", "default_answer": "Agreed" },
|
||
{ "name": "Reinstatement Value Clause", "default_answer": "Agreed" },
|
||
{ "name": "Accidental Damage Cover", "default_answer": "Agreed" }
|
||
],
|
||
"excess": "Policy Pedal Cycle"
|
||
},
|
||
|
||
"premium": {
|
||
"premium": [
|
||
"Premium",
|
||
"GST (%)",
|
||
"GST Amount (₹)",
|
||
"Total",
|
||
]
|
||
}
|
||
};
|
||
|
||
let policyOrder = {
|
||
fire: 1,
|
||
burglary: 2,
|
||
flop: 3,
|
||
all_risk: 4,
|
||
mbd: 5,
|
||
eei: 6,
|
||
fidelity: 7,
|
||
money: 8,
|
||
plate_glass: 9,
|
||
neon_sign: 10,
|
||
public_liability: 11,
|
||
pedal_cycle: 12,
|
||
premium: 13
|
||
};
|
||
|
||
// GLOBAL VARABLES DECLARATION
|
||
|
||
let riskCount = 0; // for Risk Location Count
|
||
let insurerCount = 0; // for Insurer Count
|
||
let insurerVersionCount = 1; // for Insurer Version controll
|
||
let editingInsurerId = null; // for Edit Insurer
|
||
let editingLocationIndex = null; // for Edit Risk Location
|
||
let risk_location_details = {}; // for Store Risk Location Details
|
||
let insurer_details = {}; // for Store Insurer Details
|
||
let active_policy_data = {}; // for Store the Active Policy Data (eg : Fire, Burglary) based on the checkbox
|
||
|
||
$(document).ready(function() {
|
||
|
||
// Add Risk Location Column (show modal first)
|
||
$("#addLocation").click(function() {
|
||
editingLocationIndex = null; // Clear editing mode
|
||
$("#riskLocationForm")[0].reset();
|
||
$("#riskLocationModalLabel").text("Add Risk Location Details");
|
||
$("#saveRiskLocation").text("Add Location");
|
||
// $("#riskLocationModal").modal('show');
|
||
var myModal = new bootstrap.Modal(document.getElementById('riskLocationModal'));
|
||
myModal.show();
|
||
});
|
||
|
||
// Save Risk Location Details and Add Column
|
||
$("#saveRiskLocation").click(function() {
|
||
|
||
let locationName = $("#locationName").val().trim();
|
||
let locationAddress = $("#locationAddress").val().trim();
|
||
let construction_type = $("#construction_type").val();
|
||
let has_basement = $("#has_basement").is(":checked");
|
||
let basement_utilisation = $("#basement_utilisation").val().trim();
|
||
let occupancy_risk = $("#occupancy_risk").val();
|
||
let iib_code = $("#iib_code").val().trim();
|
||
let business_description = $("#business_description").val().trim();
|
||
|
||
if (!locationName || !locationAddress) {
|
||
alert("Please fill in required fields (Location Name and Address)");
|
||
return;
|
||
}
|
||
|
||
if (editingLocationIndex === null) {
|
||
|
||
// Adding new location count
|
||
riskCount++;
|
||
|
||
// Store details for this risk location
|
||
risk_location_details[riskCount] = {
|
||
name: locationName,
|
||
address: locationAddress,
|
||
construction_type: construction_type,
|
||
has_basement: has_basement,
|
||
basement_utilisation: basement_utilisation,
|
||
occupancy_risk: occupancy_risk,
|
||
iib_code: iib_code,
|
||
business_description: business_description
|
||
};
|
||
|
||
// Create header
|
||
let header = `
|
||
<th class="risk-col" data-risk-id="${riskCount}">
|
||
|
||
<div class="loc-details" style="text-align: center;">
|
||
<div style="font-weight: bold;">Risk Location ${riskCount}</div>
|
||
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
||
<span class="loc_name" style="display: block;">${locationName}</span>
|
||
<span class="loc_address" style="display: block;">${locationAddress}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item edit-location" href="#" data-risk-id="${riskCount}">Edit</a></li>
|
||
<li><a class="dropdown-item text-danger remove-location" href="#" data-risk-id="${riskCount}">Remove</a></li>
|
||
<li><a class="dropdown-item add-index-value" href="#" data-risk-id="${riskCount}">Add Index Value</a></li>
|
||
<li><a class="dropdown-item toggle-collapse" href="#" data-risk-id="${riskCount}" data-type="risk">Collapse</a></li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</th>
|
||
`;
|
||
|
||
// Find index of "Total Sum Insured" column
|
||
let sumInsuredIndex = $("#policyHeader th").filter(function() {
|
||
return $(this).text().trim().toLowerCase().includes("total sum insured");
|
||
}).index();
|
||
|
||
// Insert header before Total Sum Insured
|
||
$("#policyHeader th").eq(sumInsuredIndex).before(header);
|
||
|
||
// --- after you inserted the new header TH into #policyHeader ---
|
||
var $headerRow = $("#policyHeader");
|
||
if (!$headerRow.is("tr")) $headerRow = $headerRow.find("tr").first();
|
||
|
||
var $newTh = $headerRow.find(`th.risk-col[data-risk-id="${riskCount}"]`).first();
|
||
if (!$newTh.length) {
|
||
console.error("New header not found");
|
||
} else {
|
||
// compute visual column index (sum of colspans of preceding THs)
|
||
var targetVisualIndex = 0;
|
||
$headerRow.children("th").each(function() {
|
||
if (this === $newTh[0])
|
||
return false; // stop when we reach the inserted header
|
||
targetVisualIndex += parseInt($(this).attr("colspan")) || 1;
|
||
});
|
||
|
||
// occupied[col] = how many more rows this visual column is still covered by an earlier rowspan
|
||
var occupied = [];
|
||
|
||
$("#policyTable tbody tr").each(function() {
|
||
var $tr = $(this);
|
||
var $tds = $tr.children("td");
|
||
var visual = 0;
|
||
var inserted = false;
|
||
|
||
for (var i = 0; i < $tds.length; i++) {
|
||
// skip visual columns already occupied by rowspans
|
||
while (occupied[visual] > 0) visual++;
|
||
|
||
var $td = $tds.eq(i);
|
||
|
||
// get the full inline style string (if any)
|
||
var inlineStyle = $td.attr("style");
|
||
|
||
// get just the background-color (works whether inline or CSS-applied)
|
||
var bgColor = $td.css("background-color");
|
||
|
||
var colspan = parseInt($td.attr("colspan")) || 1;
|
||
var rowspan = parseInt($td.attr("rowspan")) || 1;
|
||
|
||
// if target is exactly at this visual start -> insert before this cell
|
||
if (targetVisualIndex === visual) {
|
||
$td.before(
|
||
`<td style="background-color:${bgColor}" class="risk-col" data-risk-id="${riskCount}"></td>`);
|
||
inserted = true;
|
||
break;
|
||
}
|
||
|
||
// if target falls inside this spanning cell -> insert after this cell
|
||
if (targetVisualIndex > visual && targetVisualIndex < visual +
|
||
colspan) {
|
||
$td.after(`<td style="background-color:${bgColor}" class="risk-col" data-risk-id="${riskCount}"></td>`);
|
||
inserted = true;
|
||
break;
|
||
}
|
||
|
||
// mark columns as occupied by this cell's rowspan
|
||
for (var k = 0; k < colspan; k++) {
|
||
occupied[visual + k] = rowspan;
|
||
}
|
||
|
||
visual += colspan;
|
||
}
|
||
|
||
if (!inserted) {
|
||
// if not inserted yet, append at the end of the row
|
||
$tr.append(`<td class="risk-col" data-risk-id="${riskCount}"></td>`);
|
||
}
|
||
|
||
// decrease occupied counters for next row
|
||
for (var c = 0; c < occupied.length; c++) {
|
||
if (occupied[c] > 0) occupied[c]--;
|
||
}
|
||
});
|
||
|
||
// restore editability (if desired)
|
||
$("#policyTable tbody tr").find("td:not(:first-child)").attr("contenteditable", "true");
|
||
}
|
||
|
||
} else {
|
||
|
||
// Editing existing location
|
||
let riskId = editingLocationIndex;
|
||
risk_location_details[riskId] = {
|
||
name: locationName,
|
||
address: locationAddress,
|
||
construction_type: construction_type,
|
||
has_basement: has_basement,
|
||
basement_utilisation: basement_utilisation,
|
||
occupancy_risk: occupancy_risk,
|
||
iib_code: iib_code,
|
||
business_description: business_description
|
||
};
|
||
|
||
// Update header
|
||
$(`.risk-col[data-risk-id="${riskId}"]`).first().html(`
|
||
|
||
<div class="loc-details" style="text-align: center;">
|
||
<div style="font-weight: bold;">Risk Location ${riskId}</div>
|
||
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
||
<span class="loc_name" style="display: block;">${locationName}</span>
|
||
<span class="loc_address" style="display: block;">${locationAddress}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item edit-location" href="#" data-risk-id="${riskId}">Edit</a></li>
|
||
<li><a class="dropdown-item text-danger remove-location" href="#" data-risk-id="${riskId}">Remove</a></li>
|
||
<li><a class="dropdown-item toggle-collapse" href="#" data-risk-id="${riskId}" data-type="risk">Collapse</a></li>
|
||
<li class="dropdown-item">
|
||
<label class="form-check-label">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-risk-id="${riskCount}" checked >
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<label class="form-check-label">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-risk-id="${riskCount}" checked>
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
`);
|
||
}
|
||
|
||
// Clear form and close modal
|
||
$("#riskLocationForm")[0].reset();
|
||
editingLocationIndex = null;
|
||
$('.close').click();
|
||
|
||
console.log("Risk Location JSON:", JSON.stringify(risk_location_details, null, 2));
|
||
});
|
||
|
||
// Add Insurer button click - show modal
|
||
$("#addInsurer").click(function() {
|
||
// $("#insurerModal").modal('show');
|
||
$('#insurerSelect2').val('').select2();
|
||
var myModal = new bootstrap.Modal(document.getElementById('insurerModal'));
|
||
myModal.show();
|
||
});
|
||
|
||
// Insurer selection from modal
|
||
$(document).off("click", "#insurer_save").on("click", "#insurer_save", function(e) {
|
||
|
||
const $selected = $("#insurerSelect2 option:selected");
|
||
const insurerId = $selected.data("id"); // from data-id
|
||
let insurerName = $selected.val(); // from value="..."
|
||
const insurerText = $selected.text(); // visible text
|
||
|
||
console.log("ID:", insurerId);
|
||
console.log("Value:", insurerName);
|
||
console.log("Text:", insurerText);
|
||
|
||
if(!insurerName){
|
||
alert('Please select the insurer');
|
||
return;
|
||
}
|
||
|
||
// if(insurer_details[insurerCount] && insurer_details[insurerCount].id == insurerId && insurer_details[insurerCount].name == insurerName){
|
||
// if (confirm('Duplicate insurer found. Do you continue with version control?')) {
|
||
// insurerName = insurerName + '-V' + insurerVersionCount;
|
||
// insurerVersionCount++;
|
||
// }
|
||
// }
|
||
|
||
if (insurer_details[insurerCount]
|
||
&& insurer_details[insurerCount].id === insurerId
|
||
&& insurer_details[insurerCount].name === insurerName) {
|
||
|
||
if (confirm("Duplicate insurer found. Do you want to continue with version control?")) {
|
||
// Initialize version counter if not already set
|
||
insurer_details[insurerCount].version = (insurer_details[insurerCount].version || 1) + 1;
|
||
|
||
// Append version suffix
|
||
insurerName = insurerName + "-V" + insurer_details[insurerCount].version;
|
||
}
|
||
}
|
||
|
||
// Case 1: Editing existing insurer
|
||
if (editingInsurerId !== null) {
|
||
|
||
insurer_details[editingInsurerId] = {
|
||
id: insurerId,
|
||
name: insurerName,
|
||
};
|
||
|
||
// Update header text
|
||
const $header = $(`.insurer-col[data-insurer-id="${editingInsurerId}"]`);
|
||
$header.contents().first()[0].textContent = insurerName + " ";
|
||
|
||
// Update all rows for this insurer column
|
||
$("#policyTable tbody tr").each(function() {
|
||
const $cell = $(this).find(
|
||
`td.insurer-col[data-insurer-id="${editingInsurerId}"]`);
|
||
$cell.html("--"); // or keep old value if you prefer
|
||
});
|
||
|
||
editingInsurerId = null;
|
||
$('.close').click();
|
||
console.log("Insurer Details JSON:", JSON.stringify(insurer_details, null, 2));
|
||
|
||
return;
|
||
}
|
||
|
||
// Case 2: Adding new insurer (existing logic)
|
||
insurerCount++;
|
||
|
||
// Add the insurer details to the JSON
|
||
insurer_details[insurerCount] = {
|
||
id: insurerId,
|
||
name: insurerName,
|
||
};
|
||
|
||
const header = `
|
||
<th class="insurer-col" data-insurer-id="${insurerCount}" data-insurer-pk="${insurerId}">
|
||
${insurerName}
|
||
<div class="dropdown d-inline-block float-end">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item edit-insurer" href="#" data-insurer-id="${insurerCount}">Edit</a></li>
|
||
<li><a class="dropdown-item text-danger remove-insurer" href="#" data-insurer-id="${insurerCount}" data-type="insurer">Remove</a></li>
|
||
<li><a class="dropdown-item toggle-collapse" href="#" data-insurer-id="${insurerCount}" data-type="insurer">Collapse</a></li>
|
||
</ul>
|
||
</div>
|
||
</th>
|
||
`;
|
||
|
||
let $actionHeader = $("#policyHeader th").filter(function() {
|
||
return $(this).text().trim().toLowerCase().includes("action");
|
||
}).first();
|
||
if (!$actionHeader.length) $actionHeader = $("#policyHeader th").last();
|
||
|
||
$actionHeader.before(header);
|
||
|
||
$("#policyTable tbody tr").each(function() {
|
||
const $row = $(this);
|
||
const $actionCell = $row.children("td").last();
|
||
var bgColor = $actionCell.css("background-color");
|
||
const prevData = $row.children("td.insurer-col").last().html(); // for getting from the last insurer value
|
||
const prevData2 = $row.children("td.sum_insured").html(); // for getting from the total sum insured
|
||
const cellHtml =
|
||
`<td style="background-color:${bgColor}" class="insurer-col" data-insurer-id="${insurerCount}">${prevData2 != null ? prevData2 : "--"}</td>`;
|
||
$actionCell.before(cellHtml);
|
||
$row.find("td:not(:first-child)").attr("contenteditable", "true");
|
||
});
|
||
|
||
$('#insurerSelect2').val('').select2();
|
||
$('.close').click();
|
||
|
||
console.log("Insurer Details JSON:", JSON.stringify(insurer_details, null, 2));
|
||
});
|
||
|
||
// Remove Risk Location Column
|
||
$(document).on("click", ".remove-location", function(e) {
|
||
e.preventDefault();
|
||
let riskId = $(this).data('risk-id');
|
||
|
||
if (confirm('Are you sure you want to remove this risk location?')) {
|
||
$(`.risk-col[data-risk-id="${riskId}"]`).remove();
|
||
$(`.index-val-col[data-index-value-id="${riskId}"]`).remove();
|
||
delete risk_location_details[riskId];
|
||
|
||
// Update risk count if needed
|
||
let remainingRisks = Object.keys(risk_location_details).length;
|
||
if (remainingRisks === 0) {
|
||
riskCount = 0;
|
||
}
|
||
}
|
||
});
|
||
|
||
// Remove Insurer Column
|
||
$(document).on("click", ".remove-insurer", function(e) {
|
||
e.preventDefault();
|
||
let insurerId = $(this).data('insurer-id');
|
||
|
||
if (confirm('Are you sure you want to remove this insurer?')) {
|
||
$(`.insurer-col[data-insurer-id="${insurerId}"]`).remove();
|
||
// insurerCount--;
|
||
delete insurer_details[insurerId];
|
||
|
||
// Update insurer count if needed
|
||
let remainingInsurer = Object.keys(insurer_details).length;
|
||
if (remainingInsurer === 0) {
|
||
insurerCount = 0;
|
||
}
|
||
|
||
console.log("Insurer Details JSON:", JSON.stringify(insurer_details, null, 2));
|
||
|
||
}
|
||
});
|
||
|
||
// Edit Risk Location
|
||
$(document).on("click", ".edit-location", function(e) {
|
||
e.preventDefault();
|
||
let riskId = $(this).data('risk-id');
|
||
editingLocationIndex = riskId;
|
||
|
||
let details = risk_location_details[riskId];
|
||
|
||
if (details) {
|
||
|
||
$("#locationName").val(details.name);
|
||
$("#locationAddress").val(details.address);
|
||
$("#construction_type").val(details.construction_type);
|
||
$("#has_basement").prop("checked", details.has_basement);
|
||
|
||
if (details.has_basement) {
|
||
$("#basementUtilisationDiv").removeClass("d-none");
|
||
$("#basement_utilisation").prop("required", true).val(details.basement_utilisation);
|
||
} else {
|
||
$("#basementUtilisationDiv").addClass("d-none");
|
||
$("#basement_utilisation").prop("required", false).val("");
|
||
}
|
||
|
||
$("#occupancy_risk").val(details.occupancy_risk).trigger("change");
|
||
$("#iib_code").val(details.iib_code);
|
||
$("#business_description").val(details.business_description);
|
||
|
||
|
||
$("#riskLocationModalLabel").text("Edit Risk Location Details");
|
||
$("#saveRiskLocation").text("Update Location");
|
||
$("#riskLocationModal").modal("show");
|
||
}
|
||
});
|
||
|
||
// Handle Edit Insurer
|
||
$(document).on("click", ".edit-insurer", function(e) {
|
||
e.preventDefault();
|
||
|
||
editingInsurerId = $(this).data("insurer-id");
|
||
console.log('editingInsurerId : ', editingInsurerId);
|
||
|
||
$('#insurerSelect2').val('').select2();
|
||
|
||
var myModal = new bootstrap.Modal(document.getElementById('insurerModal'));
|
||
myModal.show();
|
||
});
|
||
|
||
// Handle Add index value column
|
||
$(document).on("click", ".add-index-value", function(e) {
|
||
|
||
e.preventDefault();
|
||
|
||
let risk_id = $(this).data("risk-id");
|
||
console.log('risk_id :', risk_id);
|
||
|
||
// Get clicked th and its index
|
||
let $th = $(this).closest("th");
|
||
let colIndex = $th.index(); // column index in the table
|
||
console.log('colIndex :', colIndex)
|
||
|
||
// Clone the header cell
|
||
let $newTh = $th.clone(true);
|
||
|
||
// Example: change class (remove old, add new)
|
||
$newTh.removeClass("risk-col").addClass("index-val-col");
|
||
|
||
// Remove the data-risk-id attribute
|
||
$newTh.removeAttr("data-risk-id");
|
||
|
||
// update data attributes
|
||
$newTh.attr("data-index-value-id", risk_id);
|
||
|
||
let locationName = $th.find(".loc-details .loc_name").html() ?? "";
|
||
let locationAddress = $th.find(".loc-details .loc_address").html() ?? "";
|
||
|
||
console.log("locationName", locationName);
|
||
console.log("locationAddress", locationAddress);
|
||
|
||
let header = `
|
||
<div class="loc-details" style="text-align: center;">
|
||
<div class="risk_location_" style="font-weight: bold;">Risk Location ${risk_id}</div>
|
||
<div style="font-weight: bold;">( Indexed Value )</div>
|
||
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
||
<span class="loc_name" style="display: block;">${locationName}</span>
|
||
<span class="loc_address" style="display: block;">${locationAddress}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item text-danger remove-index-value" href="#" data-index-value-id="${risk_id}">Remove</a></li>
|
||
<li><a class="dropdown-item toggle-collapse" href="#" data-index-value-id="${risk_id}" data-type="index-value">Collapse</a></li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-index-value-id="${risk_id}" checked>
|
||
<label class="form-check-label">
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-index-value-id="${risk_id}" checked>
|
||
<label class="form-check-label">
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
`;
|
||
|
||
$newTh.html(header);
|
||
|
||
$th.after($newTh); // insert after clicked column in header
|
||
|
||
// Clone each row's td in this column
|
||
let skipRows = 0;
|
||
let baseColIndex = $th.index();
|
||
|
||
$("#policyTable tbody tr").each(function() {
|
||
let colIndex;
|
||
|
||
if (skipRows > 0) {
|
||
skipRows--;
|
||
colIndex = baseColIndex - 1; // adjust since rowspan already occupied this column
|
||
} else {
|
||
colIndex = baseColIndex;
|
||
}
|
||
|
||
let $firstTd = $(this).children("td").eq(0);
|
||
console.log('$firstTd', $firstTd);
|
||
|
||
let rowspan = parseInt($firstTd.attr("rowspan") || 1, 10);
|
||
console.log('rowspan :', rowspan);
|
||
|
||
if (rowspan > 1) {
|
||
skipRows = rowspan - 1; // mark how many rows to skip
|
||
}
|
||
|
||
let $td = $(this).children("td").eq(colIndex);
|
||
console.log('$td', $td);
|
||
|
||
if ($td.length) {
|
||
let $newTd = $td.clone(false); // false = no event handlers
|
||
|
||
$newTd.removeClass("risk-col").addClass("index-val-col");
|
||
$newTd.removeAttr("data-risk-id");
|
||
$newTd.attr("data-index-value-id", risk_id);
|
||
|
||
$td.after($newTd);
|
||
}
|
||
});
|
||
|
||
// Hide specific one
|
||
$(`.add-index-value[data-risk-id="${risk_id}"]`).hide();
|
||
|
||
|
||
});
|
||
|
||
// Remove Index value Column
|
||
$(document).on("click", ".remove-index-value", function(e) {
|
||
e.preventDefault();
|
||
let riskId = $(this).data('index-value-id');
|
||
console.log('riskId :', riskId)
|
||
|
||
if (confirm('Are you sure you want to remove this Index value?')) {
|
||
$(`.index-val-col[data-index-value-id="${riskId}"]`).remove();
|
||
// Hide specific one
|
||
$(`.add-index-value[data-risk-id="${riskId}"]`).show();
|
||
}
|
||
});
|
||
|
||
// Main policy checkbox toggle
|
||
$(".policy").on("change", function() {
|
||
|
||
let policy = $(this).val();
|
||
let policy_color = getRandomLightColor();
|
||
|
||
if ($(this).is(":checked")) {
|
||
|
||
// Add sub-options for Fire policy
|
||
if (policy === "fire") {
|
||
$(this).parent().after(`
|
||
<div class="sub-options" id="fireOptions">
|
||
<label><input type="checkbox" class="fireSub" value="fire_building" checked> Fire Building</label>
|
||
<label><input type="checkbox" class="fireSub" value="fire_content" checked> Fire Content</label>
|
||
</div>
|
||
`);
|
||
}
|
||
|
||
if (policyData[policy]) {
|
||
|
||
let data = policyData[policy];
|
||
let rows = [];
|
||
|
||
Object.keys(data).forEach(key => {
|
||
|
||
let value = data[key];
|
||
console.log('value', value);
|
||
console.log('value type', typeof value);
|
||
|
||
if (key === "particulars") {
|
||
|
||
let rowId = `row-${policy}`;
|
||
|
||
// Build row with proper number of columns
|
||
let row =
|
||
`<tr class="policy-details" id="${rowId}" data-policy="${policy}" data-key="${key}" data-index="0">
|
||
<td>${formatHeader(policy)} <i class="mdi mdi-arrow-collapse-up policy-collapse" data-policy="${policy}" aria-hidden="true"></i></td>
|
||
<td class="particulars" contenteditable="true" id="${rowId}-particulars">${formatParticulars(value)}</td>`;
|
||
|
||
// Add empty cells for risk locations
|
||
for (let i = 0; i < riskCount; i++) {
|
||
row += `<td contenteditable="true" class="risk-col"></td>`;
|
||
}
|
||
|
||
// Add sum insured cell
|
||
row +=
|
||
`<td class="sum_insured" contenteditable="true">${data.sum_insured || "50000000"}</td>`;
|
||
|
||
// Add index sum insured cell
|
||
row +=
|
||
`<td class="index_sum_insured" contenteditable="true">${data.index_sum_insured || "50000000"}</td>`;
|
||
|
||
// Add empty cells for insurers
|
||
for (let i = 0; i < insurerCount; i++) {
|
||
row += `<td contenteditable="true" class="insurer-col"></td>`;
|
||
}
|
||
|
||
// Add QCR column
|
||
let qcrId = `qcrCheckbox_${rowId}`;
|
||
row += `<td contenteditable="false" class="action"></td>`;
|
||
row += `</tr>`;
|
||
|
||
rows.push(row);
|
||
|
||
// $("#policyTable tbody").append(row);
|
||
// $(`#${rowId}`).fadeIn();
|
||
} else if (Array.isArray(value) && key == "premium") {
|
||
value.forEach((item, index) => {
|
||
let rowId = `row-${policy}-${key}-${index}`;
|
||
let firstCell = index === 0 ?
|
||
`<td rowspan="${value.length}">${formatHeader(key)}</td>` :
|
||
"";
|
||
|
||
let row = `<tr class="policy-details" id="${rowId}" data-policy="${policy}" data-key="${key}" data-index="${index}" data-array-length="${value.length}">
|
||
${firstCell}
|
||
<td class="particulars" contenteditable="true">${item}</td>`;
|
||
|
||
// Add empty cells for risk locations
|
||
for (let i = 0; i < riskCount; i++) {
|
||
row +=
|
||
`<td contenteditable="true" class="risk-col"></td>`;
|
||
}
|
||
|
||
// Add sum insured cell
|
||
row +=
|
||
`<td class="sum_insured" contenteditable="true"></td>`;
|
||
|
||
// Add index sum insured cell
|
||
row +=
|
||
`<td class="index_sum_insured" contenteditable="true"></td>`;
|
||
|
||
// Add empty cells for insurers
|
||
for (let i = 0; i < insurerCount; i++) {
|
||
row +=
|
||
`<td contenteditable="true" class="insurer-col"></td>`;
|
||
}
|
||
|
||
// Add QCR column
|
||
let qcrId = `qcrCheckbox_${rowId}`;
|
||
row += `<td contenteditable="false" class="action" ></td>`;
|
||
|
||
row += `</tr>`;
|
||
rows.push(row);
|
||
|
||
// $("#policyTable tbody").append(row);
|
||
// $(`#${rowId}`).fadeIn();
|
||
});
|
||
} else if (Array.isArray(value) && key !== "particulars") {
|
||
value.forEach((item, index) => {
|
||
let rowId = `row-${policy}-${key}-${index}`;
|
||
let firstCell = index === 0 ?
|
||
`<td rowspan="${value.length}">${formatHeader(key)}</td>` :
|
||
"";
|
||
|
||
let row = `<tr class="policy-details ${policy}_${key}" id="${rowId}" data-policy="${policy}" data-key="${key}" data-index="${index}" data-array-length="${value.length}">
|
||
${firstCell}
|
||
<td class="particulars" contenteditable="true">${item.name}</td>`;
|
||
|
||
// Add empty cells for risk locations
|
||
for (let i = 0; i < riskCount; i++) {
|
||
row +=
|
||
`<td contenteditable="true" class="risk-col"></td>`;
|
||
}
|
||
|
||
// Add sum insured cell
|
||
row +=
|
||
`<td class="sum_insured" contenteditable="true">${item.default_answer || "50000000"}</td>`;
|
||
|
||
// Add index sum insured cell
|
||
row +=
|
||
`<td class="index_sum_insured" contenteditable="true">${item.default_answer || "50000000"}</td>`;
|
||
|
||
// Add empty cells for insurers
|
||
for (let i = 0; i < insurerCount; i++) {
|
||
row +=
|
||
`<td contenteditable="true" class="insurer-col"></td>`;
|
||
}
|
||
|
||
// Add QCR column
|
||
let qcrId = `qcrCheckbox_${rowId}`;
|
||
row += `<td contenteditable="false" class="action">
|
||
<input class="qcr-checkbox" id="${qcrId}" name="qcr" type="checkbox" checked>
|
||
<label for="${qcrId}">QCR</label>
|
||
<input class="client-checkbox" name="stc" type="checkbox" checked>
|
||
<label> Client </label>
|
||
<button class="btn btn-primary btn-sm btn-add-row">+</button>
|
||
<button class="btn btn-danger btn-sm btn-remove-row">-</button>
|
||
</td>`;
|
||
|
||
row += `</tr>`;
|
||
rows.push(row);
|
||
|
||
// $("#policyTable tbody").append(row);
|
||
// $(`#${rowId}`).fadeIn();
|
||
});
|
||
} else if (key === "excess") {
|
||
// Normal string/value row
|
||
|
||
let rowId = `row-${policy}-${key}`;
|
||
let row = `<tr class="policy-details ${policy}_${key}" id="${rowId}" data-policy="${policy}" data-key="${key}" data-index="0">
|
||
<td rowspan="1" contenteditable="true">${formatHeader(key)}</td>
|
||
<td class="particulars" contenteditable="true">${formatParticulars(value)}</td>`;
|
||
|
||
// Add empty cells for risk locations
|
||
for (let i = 0; i < riskCount; i++) {
|
||
row += `<td contenteditable="true" class="risk-col"></td>`;
|
||
}
|
||
|
||
// Add sum insured cell
|
||
row +=
|
||
`<td class="sum_insured" contenteditable="true">${data.sum_insured || "50000000"}</td>`;
|
||
|
||
// Add index sum insured cell
|
||
row +=
|
||
`<td class="index_sum_insured" contenteditable="true">${data.sum_insured || "50000000"}</td>`;
|
||
|
||
// Add empty cells for insurers
|
||
for (let i = 0; i < insurerCount; i++) {
|
||
row += `<td contenteditable="true" class="insurer-col"></td>`;
|
||
}
|
||
|
||
// Add QCR column
|
||
let qcrId = `qcrCheckbox_${rowId}`;
|
||
row += `<td contenteditable="false" class="action">
|
||
<input class="qcr-checkbox" id="${qcrId}" name="qcr" type="checkbox" checked>
|
||
<label for="${qcrId}">QCR</label>
|
||
<input class="client-checkbox" name="stc" type="checkbox" checked> <label> Client </label>
|
||
<button class="btn btn-primary btn-sm btn-add-row">+</button>
|
||
<button class="btn btn-danger btn-sm btn-remove-row">-</button>
|
||
</td>`;
|
||
|
||
row += `</tr>`;
|
||
rows.push(row);
|
||
|
||
// $("#policyTable tbody").append(row);
|
||
// $(`#${rowId}`).fadeIn();
|
||
|
||
}
|
||
});
|
||
|
||
// Insert all rows at once in correct order
|
||
if (rows.length > 0) {
|
||
|
||
let $rows = $(rows.join(""));
|
||
insertPolicyRows($rows, policy);
|
||
$rows.hide().fadeIn();
|
||
|
||
// 🎨 Add random light color for each <td>
|
||
$rows.find("td").each(function () {
|
||
$(this).css("background-color", policy_color);
|
||
});
|
||
}
|
||
}
|
||
|
||
} else {
|
||
// Remove policy rows and sub-options
|
||
$(`.policy-details[id^="row-${policy}"]`).fadeOut(function() {
|
||
$(this).remove();
|
||
});
|
||
|
||
if (policy === "fire") {
|
||
$("#fireOptions").remove();
|
||
}
|
||
}
|
||
});
|
||
|
||
// Handle the policy order
|
||
function insertPolicyRows(row, policy) {
|
||
let newPriority = policyOrder[policy] || 999; // default lowest if not found
|
||
let inserted = false;
|
||
|
||
$("#policyTable tbody tr.policy-details").each(function() {
|
||
let existingPolicy = $(this).data("policy");
|
||
let existingPriority = policyOrder[existingPolicy] || 999;
|
||
|
||
if (newPriority < existingPriority) {
|
||
$(this).before(row);
|
||
inserted = true;
|
||
return false; // break loop
|
||
}
|
||
});
|
||
|
||
if (!inserted) {
|
||
$("#policyTable tbody").append(row); // add at end if no higher priority found
|
||
}
|
||
}
|
||
|
||
// Utility: find the group's first row (the row which holds the rowspan cell)
|
||
function findGroupFirstRow($tr) {
|
||
return $tr.prevAll().addBack().filter(function() {
|
||
return $(this).find('td[rowspan], th[rowspan]').length > 0;
|
||
}).last();
|
||
}
|
||
|
||
// Utility: count rows that belong to the same group (from the first row until the next group header or end)
|
||
function countGroupRows($firstRow) {
|
||
if (!$firstRow || $firstRow.length === 0) return 0;
|
||
let count = 0;
|
||
let $cur = $firstRow;
|
||
while ($cur && $cur.length) {
|
||
// stop if we reach another header row (except the firstRow itself)
|
||
if ($cur[0] !== $firstRow[0] && $cur.find('td[rowspan], th[rowspan]').length > 0) break;
|
||
count++;
|
||
$cur = $cur.next();
|
||
console.log("$cur", $cur)
|
||
}
|
||
|
||
let excess_id = $firstRow[0].id;
|
||
console.log("Original ID:", excess_id);
|
||
|
||
let parts = excess_id.split('-');
|
||
console.log("Split parts:", parts);
|
||
|
||
let lastPart = parts[parts.length - 1];
|
||
console.log("Last part:", lastPart);
|
||
|
||
if (lastPart == "excess" && count > 2) {
|
||
count = count - 1;
|
||
}
|
||
|
||
return count;
|
||
}
|
||
|
||
// Update rowspan attribute for the group's header cell
|
||
function updateRowspanForGroup($anyRowInGroup) {
|
||
let $firstRow = findGroupFirstRow($anyRowInGroup);
|
||
console.log('$firstRow :', $firstRow);
|
||
if (!$firstRow || $firstRow.length === 0) return;
|
||
let $cell = $firstRow.find('td[rowspan], th[rowspan]').first();
|
||
console.log("$cell ", $cell)
|
||
if ($cell.length === 0) return;
|
||
let cnt = countGroupRows($firstRow);
|
||
console.log("rowspan cnt", cnt);
|
||
$cell.attr('rowspan', cnt);
|
||
}
|
||
|
||
// Add row handler (+) using the Action Column
|
||
$(document).on("click", ".btn-add-row", function(e) {
|
||
e.preventDefault();
|
||
let $tr = $(this).closest("tr");
|
||
|
||
// clone WITHOUT copying event handlers
|
||
let $clone = $tr.clone(false);
|
||
|
||
// remove any header cell (the rowspan cell) in the cloned row so header isn't duplicated
|
||
$clone.find('td[rowspan], th[rowspan]').remove();
|
||
|
||
// make ids unique in clone (and update labels pointing to them)
|
||
$clone.find('[id]').each(function() {
|
||
let $el = $(this);
|
||
let oldId = $el.attr('id');
|
||
if (!oldId) return;
|
||
let newId = oldId + '_' + Date.now() + '_' + Math.floor(Math.random() * 1000);
|
||
$el.attr('id', newId);
|
||
// update label[s] inside the clone that referenced oldId
|
||
$clone.find('label[for="' + oldId + '"]').attr('for', newId);
|
||
});
|
||
|
||
// clear editable cells and form fields inside clone
|
||
$clone.find('[contenteditable]').text();
|
||
$clone.find('input[type="text"], input[type="number"], textarea').val();
|
||
$clone.find('select').prop('selectedIndex', 0);
|
||
$clone.find('input[type="checkbox"], input[type="radio"]').prop('checked', true);
|
||
|
||
// insert the clone after current row
|
||
$tr.after($clone);
|
||
|
||
// update rowspan for this group
|
||
updateRowspanForGroup($tr);
|
||
});
|
||
|
||
// Remove row handler (-) using the Action Column
|
||
$(document).on("click", ".btn-remove-row", function(e) {
|
||
e.preventDefault();
|
||
let $tr = $(this).closest("tr");
|
||
let $firstRow = findGroupFirstRow($tr);
|
||
let groupCount = countGroupRows($firstRow);
|
||
|
||
if (confirm('Are you sure you want to remove this ROW?')) {
|
||
// If this row contains the header (rowspan cell)
|
||
let $headerCell = $tr.find('td[rowspan], th[rowspan]').first();
|
||
|
||
if ($headerCell.length > 0) {
|
||
// If it's the only row in the group, prevent removal
|
||
if (groupCount <= 1) {
|
||
alert("Cannot remove the last row of this group.");
|
||
return;
|
||
}
|
||
|
||
// Move header cell to the next row, then remove the current row
|
||
let $next = $tr.next();
|
||
if ($next.length === 0) {
|
||
alert("Cannot remove header row (no next row to move header to).");
|
||
return;
|
||
}
|
||
let $detachedHeader = $headerCell.detach(); // remove but keep element
|
||
// prepend header cell to the next row (so it becomes the group's new first row)
|
||
$next.prepend($detachedHeader);
|
||
// now remove the original row
|
||
$tr.remove();
|
||
|
||
// update rowspan based on the new first row
|
||
updateRowspanForGroup($next);
|
||
} else {
|
||
// normal row removal (not a header)
|
||
if (groupCount <= 1) {
|
||
// safety: if groupCount is 1 and row is not header, still avoid leaving group empty
|
||
alert("Cannot remove the last row of this group.");
|
||
return;
|
||
}
|
||
$tr.remove();
|
||
// update rowspan referring to the group's header (pass any neighbor row)
|
||
updateRowspanForGroup($firstRow);
|
||
}
|
||
}
|
||
});
|
||
|
||
// Fire sub-options handling ( Fire content, Fire building ) using the checkbox
|
||
$(document).on("change", ".fireSub", function() {
|
||
|
||
let data = policyData["fire"];
|
||
let value = data['risk_split_up']
|
||
let policy = "fire"
|
||
console.log(value);
|
||
|
||
let bg = "";
|
||
$('tr.fire_risk_split_up').each(function() {
|
||
bg = $(this).find('td:first').css('background-color');
|
||
console.log(bg);
|
||
});
|
||
console.log('bg color :', bg);
|
||
|
||
|
||
|
||
$('.fire_risk_split_up').remove();
|
||
|
||
let fireBuilding = $(".fireSub[value='fire_building']");
|
||
let fireContent = $(".fireSub[value='fire_content']");
|
||
|
||
let fireBuildingChecked = fireBuilding.is(":checked");
|
||
let fireContentChecked = fireContent.is(":checked");
|
||
|
||
// Prevent both from being unchecked
|
||
if (!fireBuildingChecked && !fireContentChecked) {
|
||
$(this).prop("checked", true);
|
||
return;
|
||
}
|
||
|
||
let fireParticularsContainer = $("#row-fire-particulars");
|
||
if (fireParticularsContainer.length > 0) {
|
||
let content = "";
|
||
|
||
if (fireBuildingChecked) {
|
||
content += policyData["fire"].particulars.fire_building + "<br><br>";
|
||
$('.fire_risk_split_up').remove();
|
||
appendBuildingAndContent(value, "Buildings", bg);
|
||
}
|
||
|
||
if (fireContentChecked) {
|
||
content += policyData["fire"].particulars.fire_content;
|
||
$('.fire_risk_split_up').remove();
|
||
appendBuildingAndContent(value, "Contents", bg);
|
||
}
|
||
|
||
if (fireBuildingChecked && fireContentChecked) {
|
||
$('.fire_risk_split_up').remove();
|
||
appendBuildingAndContent(value, "All", bg);
|
||
}
|
||
|
||
fireParticularsContainer.html(content);
|
||
}
|
||
});
|
||
|
||
// function for append the Fire sub option rows
|
||
function appendBuildingAndContent(value, type, bgColor) {
|
||
|
||
console.log(value);
|
||
|
||
if (type === "Buildings") {
|
||
value = value.slice(0, 1);
|
||
} else if (type === "Contents") {
|
||
value = value.slice(1); // keep all except index 0
|
||
} else {
|
||
value = value;
|
||
}
|
||
|
||
let firstTwo = value.slice(0, 2);
|
||
|
||
// Get remaining items
|
||
let remaining = value.slice(2);
|
||
|
||
console.log("✅ First 2 items:", firstTwo);
|
||
console.log("✅ Remaining items:", remaining);
|
||
|
||
let row = ""; // ✅ initialize correctly
|
||
|
||
value.forEach((item, index) => {
|
||
let condition = true;
|
||
|
||
if (condition) {
|
||
|
||
let policy = "fire";
|
||
let key = "risk_split_up";
|
||
let rowId = `row-${policy}-${key}-${index}`;
|
||
|
||
let firstCell = index === 0 ? `<td style="background-color:${bgColor}" rowspan="${value.length}">${formatHeader(key)}</td>` : "";
|
||
|
||
row += `<tr class="policy-details fire_risk_split_up"
|
||
id="${rowId}"
|
||
data-policy="${policy}"
|
||
data-key="${key}"
|
||
data-index="${index}"
|
||
data-array-length="${value.length}">
|
||
${firstCell}
|
||
<td style="background-color:${bgColor}" class="particulars" contenteditable="true">${item.name}</td>`;
|
||
|
||
// Empty cells for risk locations
|
||
for (let i = 0; i < riskCount; i++) {
|
||
row += `<td style="background-color:${bgColor}" contenteditable="true" class="risk-col"></td>`;
|
||
}
|
||
|
||
// Sum insured cell
|
||
row += `<td style="background-color:${bgColor}" class="sum_insured" contenteditable="true">${item.default_answer}</td>`;
|
||
|
||
// index Sum insured cell
|
||
row += `<td style="background-color:${bgColor}" class="index_sum_insured" contenteditable="true">${item.default_answer}</td>`;
|
||
|
||
// Insurer cells
|
||
for (let i = 0; i < insurerCount; i++) {
|
||
row += `<td style="background-color:${bgColor}" contenteditable="true" class="insurer-col"></td>`;
|
||
}
|
||
|
||
// Action column
|
||
let qcrId = `qcrCheckbox_${rowId}`;
|
||
row += `<td style="background-color:${bgColor}" class="action">
|
||
<input class="qcr-checkbox" id="${qcrId}" name="qcr" type="checkbox" checked>
|
||
<label for="${qcrId}">QCR</label>
|
||
<input class="client-checkbox" name="stc" type="checkbox" checked> <label> Client </label>
|
||
<button class="btn btn-primary btn-sm btn-add-row">+</button>
|
||
<button class="btn btn-danger btn-sm btn-remove-row">-</button>
|
||
</td>`;
|
||
|
||
row += `</tr>`;
|
||
}
|
||
});
|
||
|
||
// ✅ insert rows after #row-fire
|
||
if (row) {
|
||
$("#row-fire").after(row);
|
||
}
|
||
}
|
||
|
||
// Formats particulars (array, object, or string) into an HTML-friendly string
|
||
function formatParticulars(particulars) {
|
||
if (Array.isArray(particulars)) {
|
||
return particulars.join("<br>");
|
||
} else if (typeof particulars === "object" && particulars !== null) {
|
||
return Object.values(particulars).join("<br><br>");
|
||
} else {
|
||
return particulars || "";
|
||
}
|
||
}
|
||
|
||
// Converts a string with underscores into a human-readable ( Example: "risk_split_up" → "Risk Split Up" )
|
||
function formatHeader(str) {
|
||
|
||
if (!str) return "";
|
||
|
||
// Replace underscores with spaces and capitalize
|
||
let words = str.replace(/_/g, ' ').split(' ');
|
||
words = words.map(word => word.charAt(0).toUpperCase() + word.slice(1));
|
||
return words.join(' ');
|
||
}
|
||
|
||
// Convert labels to snake_case keys
|
||
function toSnakeCase(str) {
|
||
return str.toLowerCase().replace(/\s+/g, "_").replace(/-/g, "_");
|
||
}
|
||
|
||
// Builds a JSON object of policies with their active status and selected sub-options
|
||
function buildPolicyJson() {
|
||
active_policy_data = {};
|
||
$("#policyCheckboxes .policy").each(function() {
|
||
let policy = $(this).val();
|
||
let isChecked = $(this).is(":checked") ? 1 : 0;
|
||
|
||
active_policy_data[policy] = {
|
||
active: isChecked,
|
||
options: {}
|
||
};
|
||
|
||
// If checked, capture sub-options
|
||
let subOptions = $(this).closest("label").next(".sub-options").find("input");
|
||
subOptions.each(function() {
|
||
let optionKey = toSnakeCase($(this).val());
|
||
active_policy_data[policy].options[optionKey] = $(this).is(":checked") ? 1 : 0;
|
||
});
|
||
});
|
||
}
|
||
|
||
// Listen for changes
|
||
$("#policyCheckboxes").on("change", "input[type=checkbox]", function() {
|
||
buildPolicyJson();
|
||
console.log("Updated Policy JSON:", JSON.stringify(active_policy_data, null, 2));
|
||
});
|
||
|
||
// This is for the Action column QCR uncheck and check row wise check
|
||
$(document).on("change", ".qcr-checkbox", function() {
|
||
let $row = $(this).closest("td"); // find the same cell
|
||
if (!$(this).is(":checked")) {
|
||
$row.find(".client-checkbox").prop("checked", false);
|
||
} else {
|
||
$row.find(".client-checkbox").prop("checked", true);
|
||
}
|
||
});
|
||
|
||
// This function for Risk Location Cloumn show or hide in the QCR
|
||
$(document).on("change", ".qcr-check-col", function() {
|
||
let $menu = $(this).closest(".dropdown-menu");
|
||
|
||
// If QCR is unchecked → uncheck Client in the same dropdown
|
||
if (!$(this).is(":checked")) {
|
||
$menu.find(".client-check-col").prop("checked", false);
|
||
} else {
|
||
$menu.find(".client-check-col").prop("checked", true);
|
||
}
|
||
});
|
||
|
||
// Basement show/hide
|
||
$("#has_basement").on("change", function() {
|
||
if ($(this).is(":checked")) {
|
||
$("#basementUtilisationDiv").removeClass("d-none");
|
||
$("#basementUtilisation").prop("required", true);
|
||
} else {
|
||
$("#basementUtilisationDiv").addClass("d-none");
|
||
$("#basementUtilisation").prop("required", false).val("");
|
||
}
|
||
});
|
||
|
||
// Occupancy Risk → fill IIB Code
|
||
$("#occupancy_risk").on("change", function() {
|
||
let selectedText = $(this).find("option:selected").val();
|
||
if (selectedText) {
|
||
$("#iib_code").val(selectedText).prop("required", true);
|
||
} else {
|
||
$("#iib_code").val("").prop("required", false);
|
||
}
|
||
});
|
||
|
||
// Toggle policy rows on clicking the collapse icon
|
||
$(document).on("click", ".policy-collapse", function() {
|
||
|
||
let policy = $(this).data("policy"); // get policy from data attribute
|
||
console.log('policy', policy);
|
||
let $iconRow = $(this).closest("tr"); // row containing the clicked icon
|
||
console.log('iconRow', $iconRow);
|
||
|
||
|
||
// Find all rows of the same policy except the icon row
|
||
let $policyRows = $(`tr.policy-details[data-policy="${policy}"]`).not($iconRow);
|
||
|
||
// Toggle visibility
|
||
$policyRows.toggle();
|
||
|
||
// Optional: change icon to indicate collapse/expand
|
||
if ($policyRows.is(":visible")) {
|
||
$(this).removeClass("mdi-arrow-collapse-down").addClass("mdi-arrow-collapse-up");
|
||
} else {
|
||
$(this).removeClass("mdi-arrow-collapse-up").addClass("mdi-arrow-collapse-down");
|
||
}
|
||
});
|
||
|
||
// Sum the location value changes in any risk-col input (contenteditable)
|
||
$(document).on("input", "#policyTable tbody td.risk-col[contenteditable='true']", function() {
|
||
let $row = $(this).closest("tr"); // current row
|
||
let sum = 0;
|
||
|
||
// Loop through all risk-col cells in this row
|
||
$row.find("td.risk-col").each(function() {
|
||
let val = parseFloat($(this).text().replace(/,/g, '')) ||
|
||
0; // remove commas and convert to number
|
||
sum += val;
|
||
});
|
||
|
||
// Update sum_insured column
|
||
if (sum != 0) {
|
||
$row.find("td.sum_insured").text(sum);
|
||
}
|
||
});
|
||
|
||
// Sum the index-value value changes in any index-val-col input (contenteditable)
|
||
$(document).on("input", "#policyTable tbody td.index-val-col[contenteditable='true']", function() {
|
||
let $row = $(this).closest("tr"); // current row
|
||
let sum = 0;
|
||
|
||
// Loop through all index-val-col cells in this row
|
||
$row.find("td.index-val-col").each(function() {
|
||
let val = parseFloat($(this).text().replace(/,/g, '')) ||
|
||
0; // remove commas and convert to number
|
||
sum += val;
|
||
});
|
||
|
||
// Update sum_insured column
|
||
if (sum != 0) {
|
||
$row.find("td.index_sum_insured").text(sum);
|
||
}
|
||
});
|
||
|
||
// Handle collapse/expand functionality
|
||
document.addEventListener('click', function(e) {
|
||
if (e.target.classList.contains('toggle-collapse')) {
|
||
e.preventDefault();
|
||
|
||
const type = e.target.dataset.type;
|
||
console.log('type', type)
|
||
let id = null;
|
||
|
||
if(type === 'risk'){
|
||
id = e.target.dataset.riskId;
|
||
}else if(type === 'insurer'){
|
||
id = e.target.dataset.insurerId;
|
||
}else if(type === 'index-value') {
|
||
id = e.target.dataset.indexValueId;
|
||
}
|
||
console.log('id', id)
|
||
|
||
|
||
// Find the header column
|
||
let headerCol;
|
||
if (type === 'risk') {
|
||
headerCol = document.querySelector(`th.risk-col[data-risk-id="${id}"]`);
|
||
} else if(type === 'insurer') {
|
||
headerCol = document.querySelector(`th.insurer-col[data-insurer-id="${id}"]`);
|
||
}else if(type === 'index-value') {
|
||
headerCol = document.querySelector(`th.index-val-col[data-index-value-id="${id}"]`);
|
||
}
|
||
console.log('headerCol', headerCol)
|
||
|
||
let attrName = type === 'risk' ? 'risk-id' : type === 'insurer' ? 'insurer-id' : 'index-value-id';
|
||
console.log('attrName', attrName);
|
||
|
||
if (headerCol) {
|
||
const isCollapsed = headerCol.classList.contains('collapsed');
|
||
|
||
if (isCollapsed) {
|
||
// Expand
|
||
headerCol.classList.remove('collapsed');
|
||
e.target.textContent = 'Collapse';
|
||
|
||
// Show corresponding body cells
|
||
// const bodyCells = document.querySelectorAll(`td[data-${type === 'risk' ? 'risk' : 'insurer'}-id="${id}"]`);
|
||
const bodyCells = document.querySelectorAll(`td[data-${attrName}="${id}"]`);
|
||
// console.log('bodyCells', bodyCells);
|
||
bodyCells.forEach(cell => {
|
||
cell.style.width = '';
|
||
cell.style.minWidth = '';
|
||
cell.style.maxWidth = '';
|
||
cell.style.overflow = '';
|
||
cell.style.textIndent = '';
|
||
});
|
||
|
||
} else {
|
||
// Collapse
|
||
headerCol.classList.add('collapsed');
|
||
e.target.textContent = 'Expand';
|
||
|
||
// Hide corresponding body cells content
|
||
// const bodyCells = document.querySelectorAll(`td[data-${type === 'risk' ? 'risk' : 'insurer'}-id="${id}"]`);
|
||
const bodyCells = document.querySelectorAll(`td[data-${attrName}="${id}"]`);
|
||
// console.log('bodyCells', bodyCells);
|
||
bodyCells.forEach(cell => {
|
||
cell.style.width = '40px';
|
||
cell.style.minWidth = '40px';
|
||
cell.style.maxWidth = '40px';
|
||
cell.style.overflow = 'hidden';
|
||
cell.style.textIndent = '-9999px';
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
});
|
||
|
||
// This document ready function to handle the document init load function
|
||
$(document).ready(function(){
|
||
|
||
$('#insurerSelect2').select2({
|
||
placeholder: 'Search and select an insurer',
|
||
allowClear: true,
|
||
});
|
||
|
||
})
|
||
|
||
// Function to generate random light color
|
||
function getRandomLightColor() {
|
||
// High RGB values = lighter colors
|
||
let r = Math.floor(200 + Math.random() * 55); // 200–255
|
||
let g = Math.floor(200 + Math.random() * 55);
|
||
let b = Math.floor(200 + Math.random() * 55);
|
||
return `rgb(${r}, ${g}, ${b})`;
|
||
}
|
||
|
||
</script>
|
||
|
||
<script>
|
||
|
||
// ----------------- GENERATE JSON FROM TABLE FUNCTIONS ------------------------------------------------------------------------------------
|
||
|
||
// Function to convert table to JSON with rowspan information
|
||
function convertTableToJSON() {
|
||
const table = document.getElementById('policyTable');
|
||
if (!table) {
|
||
throw new Error('Table with ID "policyTable" not found');
|
||
}
|
||
|
||
// Extract risk locations
|
||
const risk_locations = [];
|
||
const riskHeaders = table.querySelectorAll('th.risk-col');
|
||
riskHeaders.forEach(header => {
|
||
|
||
const riskId = header.getAttribute('data-risk-id');
|
||
const nameElement = header.querySelector('.loc_name');
|
||
const addressElement = header.querySelector('.loc_address');
|
||
const checkboxStates = getRiskLocationCheckboxStates(header);
|
||
let details = risk_location_details[riskId];
|
||
|
||
risk_locations.push({
|
||
id: riskId,
|
||
name: nameElement ? nameElement.textContent.trim() : '',
|
||
address: addressElement ? addressElement.textContent.trim() : '',
|
||
construction_type: details.construction_type,
|
||
has_basement: details.has_basement,
|
||
basement_utilisation: details.basement_utilisation,
|
||
occupancy_risk: details.occupancy_risk,
|
||
iib_code: details.iib_code,
|
||
business_description: details.business_descript,
|
||
qcr: checkboxStates.qcr,
|
||
client: checkboxStates.client
|
||
});
|
||
|
||
});
|
||
|
||
// Extract insurers
|
||
const insurers = [];
|
||
const insurerHeaders = table.querySelectorAll('th.insurer-col');
|
||
insurerHeaders.forEach(header => {
|
||
const insurerId = header.getAttribute('data-insurer-id');
|
||
const insurerName = header.textContent.trim().split('\n')[0];
|
||
|
||
insurers.push({
|
||
id: insurerId,
|
||
name: insurerName
|
||
});
|
||
});
|
||
|
||
// Extract policies
|
||
const policies = [];
|
||
const policyRows = table.querySelectorAll('tr[data-policy][data-key="particulars"]');
|
||
|
||
policyRows.forEach(row => {
|
||
|
||
const policyId = row.getAttribute('data-policy');
|
||
const policyName = row.querySelector('td:first-child').textContent.trim();
|
||
const particulars = row.querySelector('td.particulars').innerHTML.trim();
|
||
const totalSumInsured = parseFloat(row.querySelector('td.sum_insured').textContent.trim()) || 0;
|
||
const indexSumInsured = parseFloat(row.querySelector('td.index_sum_insured').textContent.trim()) || 0;
|
||
|
||
// Extract policy row data (risk locations and insurers)
|
||
const policyRowData = extractPolicyRowData(table, policyId, risk_locations, insurers);
|
||
|
||
const policy = {
|
||
id: policyId,
|
||
name: policyName,
|
||
particulars: particulars.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]*>/g, ''),
|
||
total_sum_insured: totalSumInsured,
|
||
index_sum_insured: indexSumInsured,
|
||
risk_locations: policyRowData.risk_locations,
|
||
insurers: policyRowData.insurers
|
||
};
|
||
|
||
|
||
// Extract different sections for this policy
|
||
const sections = extractPolicySections(table, policyId, risk_locations, insurers);
|
||
Object.assign(policy, sections);
|
||
|
||
policies.push(policy);
|
||
});
|
||
|
||
return {
|
||
risk_locations,
|
||
insurers,
|
||
policies,
|
||
risk_location_details,
|
||
active_policy_data
|
||
};
|
||
}
|
||
|
||
function extractPolicySections(table, policyId, risk_locations, insurers) {
|
||
const sections = {};
|
||
|
||
// Find all rows for this policy
|
||
const policyRows = table.querySelectorAll(`tr[data-policy="${policyId}"]`);
|
||
|
||
// Group rows by section type (data-key attribute)
|
||
const sectionGroups = {};
|
||
policyRows.forEach(row => {
|
||
const key = row.getAttribute('data-key');
|
||
if (key && key !== 'particulars') {
|
||
if (!sectionGroups[key]) {
|
||
sectionGroups[key] = [];
|
||
}
|
||
sectionGroups[key].push(row);
|
||
}
|
||
});
|
||
|
||
// Process each section
|
||
Object.keys(sectionGroups).forEach(sectionKey => {
|
||
const rows = sectionGroups[sectionKey];
|
||
|
||
if (sectionKey === 'excess') {
|
||
sections.excess = extractRowData(rows[0], risk_locations, insurers);
|
||
} else {
|
||
// const sectionName = convertSectionKey(sectionKey);
|
||
const sectionName = sectionKey;
|
||
sections[sectionName] = {
|
||
items: rows.map(row => extractRowData(row, risk_locations, insurers)),
|
||
rowspan: rows.length > 0 ? getRowspan(rows[0]) : 1,
|
||
sectionTitle: getSectionTitle(rows[0])
|
||
};
|
||
}
|
||
});
|
||
|
||
return sections;
|
||
}
|
||
|
||
function extractPolicyRowData(table, policyId, risk_locations, insurers) {
|
||
|
||
// console.log("table" , table)
|
||
// console.log("policyId" , policyId)
|
||
// console.log("risk_locations" , risk_locations)
|
||
// console.log("insurers" , insurers)
|
||
|
||
// Find the particulars row for this policy
|
||
const particularsRow = table.querySelector(`tr[data-policy="${policyId}"][data-key="particulars"]`);
|
||
console.log("particularsRow" , particularsRow)
|
||
|
||
if (!particularsRow) {
|
||
return { risk_locations: {}, insurers: {} };
|
||
}
|
||
|
||
const policy_risk_locations = {};
|
||
const policy_insurers = {};
|
||
|
||
// Extract risk location data
|
||
const riskCells = particularsRow.querySelectorAll('td.risk-col');
|
||
riskCells.forEach(cell => {
|
||
const riskId = cell.getAttribute('data-risk-id');
|
||
// console.log("riskId" , riskId)
|
||
const value = cell.textContent.trim();
|
||
|
||
policy_risk_locations[riskId] = value;
|
||
});
|
||
|
||
// Extract insurer data
|
||
const insurerCells = particularsRow.querySelectorAll('td.insurer-col');
|
||
insurerCells.forEach(cell => {
|
||
const insurerId = cell.getAttribute('data-insurer-id');
|
||
// console.log("insurerId" , insurerId)
|
||
|
||
const value = cell.textContent.trim();
|
||
|
||
policy_insurers[insurerId] = value;
|
||
});
|
||
|
||
return {
|
||
risk_locations: policy_risk_locations,
|
||
insurers: policy_insurers
|
||
};
|
||
}
|
||
|
||
function extractRowData(row, risk_locations, insurers) {
|
||
|
||
const particularsCell = row.querySelector('td.particulars');
|
||
const sumInsuredCell = row.querySelector('td.sum_insured');
|
||
const indexSumInsuredCell = row.querySelector('td.index_sum_insured');
|
||
const qcrCheckbox = row.querySelector('input.qcr-checkbox');
|
||
const clientCheckbox = row.querySelector('input.client-checkbox');
|
||
|
||
const data = {
|
||
item: particularsCell ? particularsCell.textContent.trim() : '',
|
||
sum_insured: sumInsuredCell ? (parseFloat(sumInsuredCell.textContent.trim()) || 0) : 0,
|
||
index_sum_insured: indexSumInsuredCell ? (parseFloat(indexSumInsuredCell.textContent.trim()) || 0) : 0,
|
||
risk_locations: {},
|
||
insurers: {},
|
||
qcr: qcrCheckbox ? qcrCheckbox.checked : false,
|
||
client: clientCheckbox ? clientCheckbox.checked : false
|
||
};
|
||
|
||
// Extract risk location values
|
||
risk_locations.forEach(location => {
|
||
const riskCell = row.querySelector(`td.risk-col[data-risk-id="${location.id}"]`);
|
||
data.risk_locations[location.id] = riskCell ? riskCell.textContent.trim() : '';
|
||
});
|
||
|
||
// Extract insurer values
|
||
insurers.forEach(insurer => {
|
||
const insurerCell = row.querySelector(`td.insurer-col[data-insurer-id="${insurer.id}"]`);
|
||
data.insurers[insurer.id] = insurerCell ? insurerCell.textContent.trim() : '';
|
||
});
|
||
|
||
return data;
|
||
}
|
||
|
||
function getRowspan(row) {
|
||
const firstCell = row.querySelector('td[rowspan]');
|
||
return firstCell ? parseInt(firstCell.getAttribute('rowspan')) : 1;
|
||
}
|
||
|
||
function getSectionTitle(row) {
|
||
const firstCell = row.querySelector('td[rowspan]');
|
||
return firstCell ? firstCell.textContent.trim() : '';
|
||
}
|
||
|
||
function convertSectionKey(key) {
|
||
return key.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase());
|
||
}
|
||
|
||
// Helper function to get checkbox states from risk location headers
|
||
function getRiskLocationCheckboxStates(header) {
|
||
const dropdownCheckboxes = header.querySelectorAll('.dropdown-menu input[type="checkbox"]');
|
||
return {
|
||
qcr: dropdownCheckboxes[0] ? dropdownCheckboxes[0].checked : false,
|
||
client: dropdownCheckboxes[1] ? dropdownCheckboxes[1].checked : false
|
||
};
|
||
}
|
||
|
||
|
||
// ------------- GENERATE TABLE FROM JSON FUNCTIONS --------------------------------------------------------------
|
||
|
||
|
||
// Function to generate table from JSON
|
||
function generateTableFromJSON(jsonData) {
|
||
|
||
const { risk_locations, insurers, policies, active_policy_data } = jsonData;
|
||
|
||
// set the risk locations count
|
||
riskCount = risk_locations.length;
|
||
|
||
// set the insurer count
|
||
insurerCount = insurers.length;
|
||
|
||
// set the location details
|
||
risk_location_details = jsonData.risk_location_details;
|
||
|
||
// function for set policy checkbox
|
||
setActivePolicyCheckboxesFromJson(active_policy_data);
|
||
|
||
let html = `<table id="policyTable" class="table table-bordered">
|
||
<thead>
|
||
<tr id="policyHeader">
|
||
<th>Policy</th>
|
||
<th>Particulars</th>`;
|
||
|
||
// Add risk location headers
|
||
risk_locations.forEach(location => {
|
||
html += `
|
||
<th class="risk-col" data-risk-id="${location.id}">
|
||
|
||
<div class="loc-details" style="text-align: center;">
|
||
<div style="font-weight: bold;">Risk Location ${location.id}</div>
|
||
<div style="font-size: 11px; color: #666; margin-top: 2px;">
|
||
<span class="loc_name" style="display: block;">${location.name}</span>
|
||
<span class="loc_address" style="display: block;">${location.address}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item edit-location" href="#" data-risk-id="${location.id}">Edit</a></li>
|
||
<li><a class="dropdown-item text-danger remove-location" href="#" data-risk-id="${location.id}">Remove</a></li>
|
||
<li><a class="dropdown-item toggle-collapse" href="#" data-risk-id="${location.id}" data-type="risk">Collapse</a></li>
|
||
<li class="dropdown-item">
|
||
<label class="form-check-label">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-risk-id="${location.id}" ${location.qcr ? 'checked' : ''}>
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<label class="form-check-label">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-risk-id="${location.id}" ${location.client ? 'checked' : ''}>
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</th>
|
||
`;
|
||
});
|
||
|
||
html += `<th class="sum_insured">Total Sum Insured</th>`;
|
||
|
||
html += `
|
||
<th class="index_sum_insured">
|
||
Index Sum Insured
|
||
<div class="dropdown d-inline-block float-end loc-menu">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 qcr-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
QCR
|
||
</label>
|
||
</li>
|
||
<li class="dropdown-item">
|
||
<input type="checkbox" class="form-check-input me-2 client-check-col" data-risk-id="${riskCount}" checked>
|
||
<label class="form-check-label">
|
||
Client
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</th>
|
||
`;
|
||
|
||
// Add insurer headers
|
||
insurers.forEach(insurer => {
|
||
html += `
|
||
<th class="insurer-col" data-insurer-id="${insurer.id}">
|
||
${insurer.name}
|
||
<div class="dropdown d-inline-block float-end">
|
||
<button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
|
||
⋮
|
||
</button>
|
||
<ul class="dropdown-menu dropdown-menu-end">
|
||
<li><a class="dropdown-item edit-insurer" href="#" data-insurer-id="${insurer.id}">Edit</a></li>
|
||
<li><a class="dropdown-item text-danger remove-insurer" href="#" data-insurer-id="${insurer.id}">Remove</a></li>
|
||
</ul>
|
||
</div>
|
||
</th>`;
|
||
});
|
||
|
||
html += `<th>Action</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>`;
|
||
|
||
// Generate policy rows
|
||
policies.forEach(policy => {
|
||
|
||
// get the random_color
|
||
let random_color = getRandomLightColor();
|
||
|
||
// Main policy row
|
||
html += generatePolicyRow(policy, risk_locations, insurers, random_color);
|
||
|
||
// Generate section rows
|
||
Object.keys(policy).forEach(key => {
|
||
if (key !== 'id' && key !== 'name' && key !== 'particulars' && key !== 'total_sum_insured') {
|
||
const section = policy[key];
|
||
if (key === 'excess') {
|
||
html += generateExcessRow(policy.id, section, risk_locations, insurers, random_color);
|
||
} else if (section.items) {
|
||
html += generateSectionRows(policy.id, key, section, risk_locations, insurers, random_color);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
html += `</tbody></table>`;
|
||
return html;
|
||
}
|
||
|
||
function generatePolicyRow(policy, risk_locations, insurers, random_color) {
|
||
|
||
let html =
|
||
` <tr class="policy-details" id="row-${policy.id}" data-policy="${policy.id}" data-key="particulars" data-index="0">
|
||
<td style="background-color:${random_color}">${policy.name} <i class="mdi mdi-arrow-collapse-up policy-collapse" data-policy="${policy.id}" aria-hidden="true"></i></td>
|
||
<td style="background-color:${random_color}" class="particulars" contenteditable="true" id="row-${policy.id}-particulars">${policy.particulars}</td>`;
|
||
|
||
// Risk location cells
|
||
risk_locations.forEach(location => {
|
||
html += `<td style="background-color:${random_color}" class="risk-col" data-risk-id="${location.id}" contenteditable="true">${policy.risk_locations?.[location.id] ?? ""}</td>`;
|
||
});
|
||
|
||
html += `<td style="background-color:${random_color}" class="sum_insured" contenteditable="true">${policy.total_sum_insured}</td>`;
|
||
|
||
html += `<td style="background-color:${random_color}" class="index_sum_insured" contenteditable="true">${policy.total_sum_insured}</td>`;
|
||
|
||
// Insurer cells
|
||
insurers.forEach(insurer => {
|
||
html += `<td style="background-color:${random_color}" class="insurer-col" data-insurer-id="${insurer.id}" contenteditable="true">${policy.insurers?.[insurer.id] ?? '--'}</td>`;
|
||
});
|
||
|
||
html += `<td style="background-color:${random_color}" contenteditable="false" class="action"></td></tr>`;
|
||
return html;
|
||
}
|
||
|
||
function generateSectionRows(policyId, sectionKey, section, risk_locations, insurers, random_color) {
|
||
let html = '';
|
||
const sectionClass = `${policyId}_${sectionKey}`;
|
||
|
||
section.items.forEach((item, index) => {
|
||
const isFirstRow = index === 0;
|
||
html +=
|
||
`<tr class="policy-details ${sectionClass}" id="row-${policyId}-${sectionKey}-${index}" data-policy="${policyId}" data-key="${sectionKey}" data-index="${index}" data-array-length="${section.items.length}">`;
|
||
|
||
if (isFirstRow) {
|
||
html += `<td style="background-color:${random_color}" rowspan="${section.rowspan}">${section.sectionTitle}</td>`;
|
||
}
|
||
|
||
html += `<td style="background-color:${random_color}" class="particulars" contenteditable="true">${item.item}</td>`;
|
||
|
||
// Risk location cells
|
||
risk_locations.forEach(location => {
|
||
const value = item.risk_locations[location.id] || '';
|
||
html +=
|
||
`<td style="background-color:${random_color}" class="risk-col" data-risk-id="${location.id}" contenteditable="true">${value}</td>`;
|
||
});
|
||
|
||
// sum insured
|
||
html += `<td style="background-color:${random_color}" class="sum_insured" contenteditable="true">${item.sum_insured}</td>`;
|
||
|
||
// index sum insured
|
||
html += `<td style="background-color:${random_color}" class="index_sum_insured" contenteditable="true">${item.sum_insured}</td>`;
|
||
|
||
// Insurer cells
|
||
insurers.forEach(insurer => {
|
||
const value = item.insurers[insurer.id] || '--';
|
||
html +=
|
||
`<td style="background-color:${random_color}" class="insurer-col" data-insurer-id="${insurer.id}" contenteditable="true">${value}</td>`;
|
||
});
|
||
|
||
html += `<td style="background-color:${random_color}" contenteditable="false" class="action">
|
||
<input class="qcr-checkbox" id="qcrCheckbox_row-${policyId}-${sectionKey}-${index}" name="qcr" type="checkbox" ${item.qcr ? 'checked' : ''}>
|
||
<label for="qcrCheckbox_row-${policyId}-${sectionKey}-${index}">QCR</label>
|
||
<input class="client-checkbox" name="stc" type="checkbox" ${item.client ? 'checked' : ''}> <label> Client </label>
|
||
<button class="btn btn-primary btn-sm btn-add-row">+</button>
|
||
<button class="btn btn-danger btn-sm btn-remove-row">-</button>
|
||
</td></tr>`;
|
||
});
|
||
|
||
return html;
|
||
}
|
||
|
||
function generateExcessRow(policyId, excess, risk_locations, insurers, random_color) {
|
||
let html = `<tr class="policy-details ${policyId}_excess" id="row-${policyId}-excess" data-policy="${policyId}" data-key="excess" data-index="0">
|
||
<td style="background-color:${random_color}" rowspan="1" contenteditable="true">Excess</td>
|
||
<td style="background-color:${random_color}" class="particulars" contenteditable="true">${excess.item}</td>`;
|
||
|
||
// Risk location cells
|
||
risk_locations.forEach(location => {
|
||
const value = excess.risk_locations[location.id] || '';
|
||
html += `<td style="background-color:${random_color}" class="risk-col" data-risk-id="${location.id}" contenteditable="true">${value}</td>`;
|
||
});
|
||
|
||
// sum insured
|
||
html += `<td style="background-color:${random_color}" class="sum_insured" contenteditable="true">${excess.sum_insured}</td>`;
|
||
|
||
// index sum insured
|
||
html += `<td style="background-color:${random_color}" class="index_sum_insured" contenteditable="true">${excess.sum_insured}</td>`;
|
||
|
||
// Insurer cells
|
||
insurers.forEach(insurer => {
|
||
const value = excess.insurers[insurer.id] || '--';
|
||
html += `<td style="background-color:${random_color}" class="insurer-col" data-insurer-id="${insurer.id}" contenteditable="true">${value}</td>`;
|
||
});
|
||
|
||
html += `<td style="background-color:${random_color}" contenteditable="false" class="action">
|
||
<input class="qcr-checkbox" id="qcrCheckbox_row-${policyId}-excess" name="qcr" type="checkbox" ${excess.qcr ? 'checked' : ''}>
|
||
<label for="qcrCheckbox_row-${policyId}-excess">QCR</label>
|
||
<input class="client-checkbox" name="stc" type="checkbox" ${excess.client ? 'checked' : ''}> <label> Client </label>
|
||
<button class="btn btn-primary btn-sm btn-add-row">+</button>
|
||
<button class="btn btn-danger btn-sm btn-remove-row">-</button>
|
||
</td></tr>`;
|
||
|
||
return html;
|
||
}
|
||
|
||
function setActivePolicyCheckboxesFromJson(data) {
|
||
|
||
for (let key in data) {
|
||
|
||
if (key == "fire" && data['fire'].active === 1) {
|
||
$('#fire_check_box').parent().after(`
|
||
<div class="sub-options" id="fireOptions">
|
||
<label><input type="checkbox" class="fireSub" value="fire_building" id="fire_building_check_box" checked> Fire Building</label>
|
||
<label><input type="checkbox" class="fireSub" value="fire_content" id="fire_content_check_box" checked> Fire Content</label>
|
||
</div>
|
||
`);
|
||
}
|
||
|
||
if (data.hasOwnProperty(key)) {
|
||
// Check top-level checkbox if active
|
||
if (data[key].active === 1) {
|
||
$("#" + key + '_check_box').prop("checked", true);
|
||
} else {
|
||
$("#" + key + '_check_box').prop("checked", false);
|
||
}
|
||
|
||
// Check option checkboxes if value is 1
|
||
if (data[key].options) {
|
||
for (let optionKey in data[key].options) {
|
||
if (data[key].options.hasOwnProperty(optionKey)) {
|
||
if (data[key].options[optionKey] === 1) {
|
||
$("#" + optionKey + '_check_box').prop("checked", true);
|
||
} else {
|
||
$("#" + optionKey + '_check_box').prop("checked", false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// ------------- CALLBACK FOR SAVE AND VIEW FUNCTIONS --------------------------------------------------------------
|
||
|
||
// save function
|
||
function getJson() {
|
||
// Usage example:
|
||
const jsonData = convertTableToJSON();
|
||
console.log(JSON.stringify(jsonData, null, 2));
|
||
localStorage.setItem('insuranceData', JSON.stringify(jsonData));
|
||
|
||
|
||
let url = '<?= base_url('test/saverfq') ?>';
|
||
|
||
// Data to send in the AJAX request
|
||
let requestData = {
|
||
json: jsonData,
|
||
};
|
||
|
||
// Send AJAX request
|
||
sendAjaxRequestForGlobal(url, 'POST', requestData, function(response) {
|
||
|
||
console.log('Data fetched successfully:', response);
|
||
|
||
}, function(xhr, status, error) {
|
||
console.error('Error fetching data:', error);
|
||
console.error(xhr.responseText);
|
||
toastr.error('An error occurred while checking the CD amount.', 'Error');
|
||
});
|
||
}
|
||
|
||
// view function
|
||
function generateTableFromLocal() {
|
||
$('#policyTable').remove();
|
||
let jsonData = localStorage.getItem('insuranceData');
|
||
console.log("jsonData", jsonData);
|
||
jsonData = JSON.parse(jsonData);
|
||
console.log("jsonData", jsonData);
|
||
|
||
// Generate table from JSON
|
||
const tableHTML = generateTableFromJSON(jsonData);
|
||
document.getElementById('container').innerHTML = tableHTML;
|
||
}
|
||
|
||
</script>
|
||
|
||
<script>
|
||
$(document).ready(function() {
|
||
// Define dropdown options for each type
|
||
const dropdownOptions = {
|
||
sum_insured: [
|
||
'Agreed',
|
||
'Market Value',
|
||
'Replacement Value',
|
||
'Book Value',
|
||
'Reinstatement Value',
|
||
'Declared Value'
|
||
],
|
||
index_sum_insured: [
|
||
'Agreed',
|
||
'Indexed',
|
||
'Non-Indexed',
|
||
'Automatic Indexation',
|
||
'Manual Indexation'
|
||
],
|
||
insurer: [
|
||
'Agreed',
|
||
'Company A',
|
||
'Company B',
|
||
'Company C',
|
||
'HDFC ERGO',
|
||
'ICICI Lombard',
|
||
'Bajaj Allianz',
|
||
'New India Assurance',
|
||
'Oriental Insurance'
|
||
]
|
||
};
|
||
|
||
let currentDropdown = null;
|
||
|
||
// Function to create dropdown menu
|
||
function createDropdown($cell, options) {
|
||
const $dropdown = $('<div class="cell-dropdown"></div>');
|
||
const currentValue = $cell.text().trim(); // Get current cell value
|
||
|
||
$.each(options, function(index, option) {
|
||
const $option = $('<div class="cell-dropdown-item"></div>').text(option);
|
||
|
||
// Highlight if this option matches the current cell value
|
||
if (option === currentValue) {
|
||
$option.addClass('selected');
|
||
}
|
||
|
||
$option.on('click', function(e) {
|
||
e.stopPropagation();
|
||
selectOption($cell, option);
|
||
});
|
||
$dropdown.append($option);
|
||
});
|
||
|
||
return $dropdown;
|
||
}
|
||
|
||
// Function to select an option
|
||
function selectOption($cell, value) {
|
||
$cell.text(value);
|
||
hideAllDropdowns();
|
||
}
|
||
|
||
// Function to show dropdown
|
||
function showDropdown($cell) {
|
||
hideAllDropdowns();
|
||
|
||
// Determine dropdown type based on class
|
||
let dropdownType;
|
||
if ($cell.hasClass('sum_insured')) {
|
||
dropdownType = 'sum_insured';
|
||
} else if ($cell.hasClass('index_sum_insured')) {
|
||
dropdownType = 'index_sum_insured';
|
||
} else if ($cell.hasClass('insurer-col')) {
|
||
dropdownType = 'insurer';
|
||
}
|
||
|
||
const options = dropdownOptions[dropdownType];
|
||
|
||
if (options) {
|
||
const $dropdown = createDropdown($cell, options);
|
||
$cell.append($dropdown);
|
||
$dropdown.show();
|
||
currentDropdown = $dropdown;
|
||
}
|
||
}
|
||
|
||
// Function to hide all dropdowns
|
||
function hideAllDropdowns() {
|
||
$('.cell-dropdown').remove();
|
||
currentDropdown = null;
|
||
}
|
||
|
||
// Event delegation for dropdown cells (works with dynamically added rows) - ONLY TBODY
|
||
$(document).on('click', 'tbody .sum_insured, tbody .index_sum_insured, tbody .insurer-col', function(e) {
|
||
e.stopPropagation();
|
||
|
||
const $cell = $(this);
|
||
const $row = $cell.closest('tr');
|
||
|
||
// Skip dropdown if row has data-key="particulars"
|
||
if ($row.attr('data-key') === 'particulars') {
|
||
return; // Exit without showing dropdown
|
||
}
|
||
|
||
// If this cell already has a dropdown open, close it
|
||
if (currentDropdown && currentDropdown.parent().is($cell)) {
|
||
hideAllDropdowns();
|
||
} else {
|
||
showDropdown($cell);
|
||
}
|
||
});
|
||
|
||
// Close dropdown when clicking outside
|
||
$(document).on('click', function(e) {
|
||
if (!$(e.target).closest('tbody .sum_insured, tbody .index_sum_insured, tbody .insurer-col').length) {
|
||
hideAllDropdowns();
|
||
}
|
||
});
|
||
|
||
// Prevent dropdown from closing when clicking inside it
|
||
$(document).on('click', '.cell-dropdown', function(e) {
|
||
e.stopPropagation();
|
||
});
|
||
|
||
});
|
||
</script>
|
||
|
||
|
||
|