| Line 178... |
Line 178... |
| 178 |
.img-x:hover{background:rgba(255,255,255,.3)}
|
178 |
.img-x:hover{background:rgba(255,255,255,.3)}
|
| 179 |
.modal-back.show{display:flex}
|
179 |
.modal-back.show{display:flex}
|
| 180 |
.modal{background:#fff;border-radius:14px;max-width:780px;width:100%;padding:20px 22px;box-shadow:0 20px 60px rgba(10,20,50,.3);position:relative}
|
180 |
.modal{background:#fff;border-radius:14px;max-width:780px;width:100%;padding:20px 22px;box-shadow:0 20px 60px rgba(10,20,50,.3);position:relative}
|
| 181 |
.modal h3{margin:0 0 2px;font-size:17px;text-align:center}
|
181 |
.modal h3{margin:0 0 2px;font-size:17px;text-align:center}
|
| 182 |
.modal > .desc{text-align:center}
|
182 |
.modal > .desc{text-align:center}
|
| 183 |
.modal .x{position:absolute;top:14px;right:16px;cursor:pointer;color:var(--soft);font-size:22px;line-height:1;border:0;background:none}
|
183 |
.modal .x,.rh-panel .x{position:absolute;top:14px;right:16px;cursor:pointer;color:var(--soft);font-size:22px;line-height:1;border:0;background:none}
|
| 184 |
/* journey totals bar */
|
184 |
/* journey totals bar */
|
| 185 |
.jstats{display:flex;gap:9px;margin:12px 0 2px;flex-wrap:wrap}
|
185 |
.jstats{display:flex;gap:9px;margin:12px 0 2px;flex-wrap:wrap}
|
| 186 |
.js{flex:1;min-width:104px;background:#f8f9fc;border:1px solid var(--line2);border-radius:10px;padding:9px 10px;text-align:center}
|
186 |
.js{flex:1;min-width:104px;background:#f8f9fc;border:1px solid var(--line2);border-radius:10px;padding:9px 10px;text-align:center}
|
| 187 |
.js .jv{font-size:15.5px;font-weight:760;color:var(--ink);font-variant-numeric:tabular-nums}
|
187 |
.js .jv{font-size:15.5px;font-weight:760;color:var(--ink);font-variant-numeric:tabular-nums}
|
| 188 |
.js .jl{font-size:10px;color:var(--soft);text-transform:uppercase;letter-spacing:.04em;margin-top:3px;font-weight:600}
|
188 |
.js .jl{font-size:10px;color:var(--soft);text-transform:uppercase;letter-spacing:.04em;margin-top:3px;font-weight:600}
|
| Line 204... |
Line 204... |
| 204 |
.tlrow.left .tlremark{justify-content:flex-start}
|
204 |
.tlrow.left .tlremark{justify-content:flex-start}
|
| 205 |
.tlremark .rk{max-width:100%;background:#fbfcfe;border:1px solid var(--line2);border-left:3px solid #c7d0e8;border-radius:8px;padding:7px 10px;font-size:11.5px;color:#4a5468;line-height:1.45;word-break:break-word}
|
205 |
.tlremark .rk{max-width:100%;background:#fbfcfe;border:1px solid var(--line2);border-left:3px solid #c7d0e8;border-radius:8px;padding:7px 10px;font-size:11.5px;color:#4a5468;line-height:1.45;word-break:break-word}
|
| 206 |
.tlrow.right .tlremark .rk{text-align:right}
|
206 |
.tlrow.right .tlremark .rk{text-align:right}
|
| 207 |
.tlrow.left .tlremark .rk{text-align:left}
|
207 |
.tlrow.left .tlremark .rk{text-align:left}
|
| 208 |
.tlremark .rkl{font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:var(--soft);font-weight:700;margin-bottom:3px}
|
208 |
.tlremark .rkl{font-size:9px;text-transform:uppercase;letter-spacing:.05em;color:var(--soft);font-weight:700;margin-bottom:3px}
|
| - |
|
209 |
.tlremark .rkhist{display:inline-block;margin-top:6px;background:none;border:0;padding:0;color:var(--brand);font-size:10.5px;font-weight:700;cursor:pointer}
|
| - |
|
210 |
.tlremark .rkhist:hover{text-decoration:underline}
|
| - |
|
211 |
/* past-discussions drawer */
|
| - |
|
212 |
.rh-back{position:fixed;inset:0;background:rgba(15,22,40,.42);z-index:1200;display:none}
|
| - |
|
213 |
.rh-back.show{display:block}
|
| - |
|
214 |
.rh-panel{position:absolute;top:0;right:0;height:100%;width:min(400px,92vw);background:#fff;box-shadow:-8px 0 30px rgba(20,30,60,.18);display:flex;flex-direction:column;padding:18px 18px 14px;transform:translateX(100%);transition:transform .22s ease}
|
| - |
|
215 |
.rh-back.show .rh-panel{transform:translateX(0)}
|
| - |
|
216 |
.rh-panel h3{margin:0 0 2px;font-size:15px;color:var(--ink)}
|
| - |
|
217 |
.rh-panel .desc{margin:0;font-size:12px;color:var(--soft)}
|
| - |
|
218 |
.rh-list{flex:1;overflow-y:auto;margin-top:12px;display:flex;flex-direction:column;gap:9px}
|
| - |
|
219 |
.rhitem{background:#fbfcfe;border:1px solid var(--line2);border-left:3px solid #c7d0e8;border-radius:9px;padding:9px 11px}
|
| - |
|
220 |
.rhtop{display:flex;justify-content:space-between;align-items:center;gap:8px}
|
| - |
|
221 |
.rhdate{font-size:11px;font-weight:700;color:var(--muted);font-variant-numeric:tabular-nums}
|
| - |
|
222 |
.rhb{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;padding:1px 6px;border-radius:5px;white-space:nowrap}
|
| - |
|
223 |
.rhb.ok{background:#e7f7ec;color:#1a7a3c}
|
| - |
|
224 |
.rhb.def{background:#fff4e6;color:#e8590c}
|
| - |
|
225 |
.rhexec{font-size:10px;color:var(--soft);font-weight:600;margin:3px 0 4px}
|
| - |
|
226 |
.rhtext{font-size:12px;color:#4a5468;line-height:1.45;word-break:break-word;white-space:pre-wrap}
|
| - |
|
227 |
.rhloading,.rhempty{color:var(--soft);font-size:12px;text-align:center;padding:24px 8px}
|
| - |
|
228 |
.rh-more{margin-top:10px;background:var(--brand);color:#fff;border:0;border-radius:8px;padding:9px;font-weight:650;font-size:12.5px;cursor:pointer;display:none}
|
| - |
|
229 |
.rh-more:disabled{opacity:.6;cursor:default}
|
| 209 |
.tlcard .tm{flex:none;width:62px;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;font-weight:750;font-size:13px;padding:6px 4px;line-height:1.05}
|
230 |
.tlcard .tm{flex:none;width:62px;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;font-weight:750;font-size:13px;padding:6px 4px;line-height:1.05}
|
| 210 |
.tlcard .tm small{font-weight:600;font-size:8.5px;opacity:.9;text-transform:uppercase;letter-spacing:.04em;margin-top:3px}
|
231 |
.tlcard .tm small{font-weight:600;font-size:8.5px;opacity:.9;text-transform:uppercase;letter-spacing:.04em;margin-top:3px}
|
| 211 |
.tlcard .bd{padding:8px 11px;flex:1;min-width:0}
|
232 |
.tlcard .bd{padding:8px 11px;flex:1;min-width:0}
|
| 212 |
.tlcard .bd .ti{font-size:12.5px;font-weight:700;color:var(--ink);line-height:1.25;word-break:break-word}
|
233 |
.tlcard .bd .ti{font-size:12.5px;font-weight:700;color:var(--ink);line-height:1.25;word-break:break-word}
|
| 213 |
.tlcard .bd .stt{display:inline-block;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;padding:1px 6px;border-radius:5px;margin-top:5px;color:#fff}
|
234 |
.tlcard .bd .stt{display:inline-block;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;padding:1px 6px;border-radius:5px;margin-top:5px;color:#fff}
|
| Line 280... |
Line 301... |
| 280 |
<div class="img-back" id="bj-img-back">
|
301 |
<div class="img-back" id="bj-img-back">
|
| 281 |
<button class="img-x" id="bj-img-x" title="Close">×</button>
|
302 |
<button class="img-x" id="bj-img-x" title="Close">×</button>
|
| 282 |
<img id="bj-img" alt="Attachment">
|
303 |
<img id="bj-img" alt="Attachment">
|
| 283 |
</div>
|
304 |
</div>
|
| 284 |
|
305 |
|
| - |
|
306 |
<!-- past-discussions drawer — slides in from the right, above the journey modal -->
|
| - |
|
307 |
<div class="rh-back" id="bj-rh-back" onclick="if(event.target===this)closeRemarkHistory()">
|
| - |
|
308 |
<div class="rh-panel" id="bj-rh-panel">
|
| - |
|
309 |
<button class="x" onclick="closeRemarkHistory()">×</button>
|
| - |
|
310 |
<h3 id="bj-rh-title"></h3>
|
| - |
|
311 |
<p class="desc" id="bj-rh-sub"></p>
|
| - |
|
312 |
<div class="rh-list" id="bj-rh-list"></div>
|
| - |
|
313 |
<button class="rh-more" id="bj-rh-more" onclick="bjLoadRemarkHistory()">Load more</button>
|
| - |
|
314 |
</div>
|
| - |
|
315 |
</div>
|
| - |
|
316 |
|
| 285 |
<script>
|
317 |
<script>
|
| 286 |
var CTX = '${rc.contextPath}';
|
318 |
var CTX = '${rc.contextPath}';
|
| 287 |
var BASE = CTX + '/beat-journey';
|
319 |
var BASE = CTX + '/beat-journey';
|
| 288 |
var LENS = 'today';
|
320 |
var LENS = 'today';
|
| 289 |
var TODAY = '$today';
|
321 |
var TODAY = '$today';
|
| Line 1501... |
Line 1533... |
| 1501 |
'<span class="stt" style="background:'+s.c+'">'+s.l+'</span>'+
|
1533 |
'<span class="stt" style="background:'+s.c+'">'+s.l+'</span>'+
|
| 1502 |
(tt==='lead' ? '<span class="stt unplanned">Unplanned</span>' : '')+
|
1534 |
(tt==='lead' ? '<span class="stt unplanned">Unplanned</span>' : '')+
|
| 1503 |
'<div class="mt">'+meta+'</div>'+extra+'</div>'+
|
1535 |
'<div class="mt">'+meta+'</div>'+extra+'</div>'+
|
| 1504 |
'</div>';
|
1536 |
'</div>';
|
| 1505 |
// remark sits on the opposite half of the timeline (empty spacer when none)
|
1537 |
// remark sits on the opposite half of the timeline (empty spacer when none)
|
| - |
|
1538 |
var rk='';
|
| - |
|
1539 |
if(!x._punch && x.remarks){
|
| 1506 |
var rk=(!x._punch && x.remarks) ? '<div class="rk"><div class="rkl">Remark</div>'+esc(x.remarks)+'</div>' : '';
|
1540 |
rk='<div class="rk"><div class="rkl">Remark</div>'+esc(x.remarks);
|
| - |
|
1541 |
if(x.taskId && x.taskId>0){
|
| - |
|
1542 |
// one big-string timeline -> global fn + primitive args (partner name escaped for the attribute)
|
| - |
|
1543 |
rk+='<button type="button" class="rkhist" onclick="bjOpenRemarkHistory('+x.taskId+',\''+js(x.taskType||'')+'\',\''+js(tlTitle(x))+'\')">📜 Past discussions</button>';
|
| - |
|
1544 |
}
|
| - |
|
1545 |
rk+='</div>';
|
| - |
|
1546 |
}
|
| 1507 |
var remark='<div class="tlremark">'+rk+'</div>';
|
1547 |
var remark='<div class="tlremark">'+rk+'</div>';
|
| 1508 |
var halves = side==='left' ? (card+remark) : (remark+card);
|
1548 |
var halves = side==='left' ? (card+remark) : (remark+card);
|
| 1509 |
return '<div class="tlrow '+side+'">'+
|
1549 |
return '<div class="tlrow '+side+'">'+
|
| 1510 |
'<div class="node" style="background:'+s.c+'">'+s.ic+'</div>'+
|
1550 |
'<div class="node" style="background:'+s.c+'">'+s.ic+'</div>'+
|
| 1511 |
halves+'</div>';
|
1551 |
halves+'</div>';
|
| Line 1513... |
Line 1553... |
| 1513 |
function closeModal(){ el('bj-modal-back').classList.remove('show'); }
|
1553 |
function closeModal(){ el('bj-modal-back').classList.remove('show'); }
|
| 1514 |
// Image lightbox — opens an attachment larger, stacked above the journey modal.
|
1554 |
// Image lightbox — opens an attachment larger, stacked above the journey modal.
|
| 1515 |
function bjOpenImage(src){ if(!src) return; el('bj-img').src=src; el('bj-img-back').classList.add('show'); }
|
1555 |
function bjOpenImage(src){ if(!src) return; el('bj-img').src=src; el('bj-img-back').classList.add('show'); }
|
| 1516 |
function bjCloseImage(){ el('bj-img-back').classList.remove('show'); el('bj-img').removeAttribute('src'); }
|
1556 |
function bjCloseImage(){ el('bj-img-back').classList.remove('show'); el('bj-img').removeAttribute('src'); }
|
| 1517 |
|
1557 |
|
| - |
|
1558 |
/* ===================== REMARK HISTORY DRAWER ===================== */
|
| - |
|
1559 |
// All prior discussions for one partner/lead (task_id + task_type), across every
|
| - |
|
1560 |
// executive and date, newest first. Paged via /beat-journey/remark-history.
|
| - |
|
1561 |
function bjOpenRemarkHistory(taskId, taskType, name){
|
| - |
|
1562 |
if(!taskId || taskId<=0) return;
|
| - |
|
1563 |
window._rh = { taskId:taskId, taskType:taskType, name:name, offset:0, limit:8, items:[], loading:false, total:0 };
|
| - |
|
1564 |
el('bj-rh-title').innerHTML='📜 '+esc(name);
|
| - |
|
1565 |
el('bj-rh-sub').textContent='Past discussions across all executives';
|
| - |
|
1566 |
el('bj-rh-list').innerHTML='<div class="rhloading"><div class="spinner"></div>Loading…</div>';
|
| - |
|
1567 |
el('bj-rh-more').style.display='none';
|
| - |
|
1568 |
el('bj-rh-back').classList.add('show');
|
| - |
|
1569 |
bjLoadRemarkHistory();
|
| - |
|
1570 |
}
|
| - |
|
1571 |
function closeRemarkHistory(){ el('bj-rh-back').classList.remove('show'); window._rh=null; }
|
| - |
|
1572 |
function bjLoadRemarkHistory(){
|
| - |
|
1573 |
var s=window._rh; if(!s || s.loading) return; // block re-entrant fetches
|
| - |
|
1574 |
s.loading=true;
|
| - |
|
1575 |
var more=el('bj-rh-more'); more.disabled=true; more.textContent='Loading…';
|
| - |
|
1576 |
var u=CTX+'/beat-journey/remark-history?taskId='+s.taskId
|
| - |
|
1577 |
+'&taskType='+encodeURIComponent(s.taskType||'')
|
| - |
|
1578 |
+'&offset='+s.offset+'&limit='+s.limit;
|
| - |
|
1579 |
fetch(u,{headers:{'Accept':'application/json'}})
|
| - |
|
1580 |
.then(function(r){ return r.json(); })
|
| - |
|
1581 |
.then(function(d){
|
| - |
|
1582 |
var st=window._rh; if(!st || st.taskId!==s.taskId) return; // drawer changed mid-flight
|
| - |
|
1583 |
st.total=d.total||0;
|
| - |
|
1584 |
(d.items||[]).forEach(function(it){ st.items.push(it); });
|
| - |
|
1585 |
st.offset += (d.items||[]).length;
|
| - |
|
1586 |
st.loading=false;
|
| - |
|
1587 |
bjRenderRemarkHistory(!!d.hasMore);
|
| - |
|
1588 |
})
|
| - |
|
1589 |
.catch(function(){
|
| - |
|
1590 |
var st=window._rh; if(st) st.loading=false;
|
| - |
|
1591 |
el('bj-rh-list').innerHTML='<div class="rhempty">Could not load past discussions.</div>';
|
| - |
|
1592 |
el('bj-rh-more').style.display='none';
|
| - |
|
1593 |
});
|
| - |
|
1594 |
}
|
| - |
|
1595 |
function bjRenderRemarkHistory(hasMore){
|
| - |
|
1596 |
var s=window._rh; if(!s) return;
|
| - |
|
1597 |
if(!s.items.length){
|
| - |
|
1598 |
el('bj-rh-list').innerHTML='<div class="rhempty">No earlier discussions for this partner.</div>';
|
| - |
|
1599 |
el('bj-rh-more').style.display='none';
|
| - |
|
1600 |
return;
|
| - |
|
1601 |
}
|
| - |
|
1602 |
var h='';
|
| - |
|
1603 |
s.items.forEach(function(it){
|
| - |
|
1604 |
var mt=(it.markType||'').toUpperCase();
|
| - |
|
1605 |
var badge = mt.indexOf('CHECKOUT')>=0 ? '<span class="rhb ok">visited</span>'
|
| - |
|
1606 |
: (mt==='DEFERRED' ? '<span class="rhb def">deferred</span>' : '');
|
| - |
|
1607 |
var when = esc(it.date||'')+(it.time?' · '+esc(hhmm(it.time)):'');
|
| - |
|
1608 |
h+='<div class="rhitem">'
|
| - |
|
1609 |
+'<div class="rhtop"><span class="rhdate">'+when+'</span>'+badge+'</div>'
|
| - |
|
1610 |
+'<div class="rhexec">'+esc(it.exec||'')+'</div>'
|
| - |
|
1611 |
+'<div class="rhtext">'+esc(it.remark||'')+'</div></div>';
|
| - |
|
1612 |
});
|
| - |
|
1613 |
el('bj-rh-list').innerHTML=h;
|
| - |
|
1614 |
var more=el('bj-rh-more');
|
| - |
|
1615 |
more.disabled=false; more.textContent='Load more';
|
| - |
|
1616 |
more.style.display = hasMore ? 'block' : 'none';
|
| - |
|
1617 |
}
|
| - |
|
1618 |
|
| 1518 |
/* ============================ APPROVAL ============================ */
|
1619 |
/* ============================ APPROVAL ============================ */
|
| 1519 |
function loadApproval(){
|
1620 |
function loadApproval(){
|
| 1520 |
spinner();
|
1621 |
spinner();
|
| 1521 |
var from=el('bj-start').value, to=el('bj-end').value;
|
1622 |
var from=el('bj-start').value, to=el('bj-end').value;
|
| 1522 |
var u=CTX+'/beat-report/approval/data?fromDate='+encodeURIComponent(from)+'&toDate='+encodeURIComponent(to)+qs();
|
1623 |
var u=CTX+'/beat-report/approval/data?fromDate='+encodeURIComponent(from)+'&toDate='+encodeURIComponent(to)+qs();
|