tango-app-api-trax 3.7.76 → 3.7.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,261 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8"/>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1"/>
6
+ <title>{{checklistTitle}}</title>
7
+ <style>
8
+ *{box-sizing:border-box;margin:0;padding:0}
9
+ body{font-family:Arial,Helvetica,sans-serif;background:#fff;padding:0}
10
+ .page{width:794px;min-height:1123px;background:#fff;padding:0;overflow:hidden;position:relative;page-break-after:always}
11
+ .cover-wrap{position:relative;width:794px;height:1123px;background:#fff;overflow:hidden;font-family:Arial,Helvetica,sans-serif}
12
+ /* Cover — match brand PDF (cyan title, right geometry, grey footer rule) */
13
+ /* Right-edge artwork: flush right; height 1043px leaves ~80px for footer band on 1123px cover */
14
+ .cover-deco{position:absolute;top:0;right:0;left:auto;width:493px;height:1043px;pointer-events:none;z-index:0}
15
+ .cover-brand{position:absolute;top:48px;left:48px;display:flex;align-items:center;gap:10px;z-index:1}
16
+ .cover-brand-name{font-size:22px;font-weight:600;color:#1a1a1a;letter-spacing:.02em;text-transform:lowercase}
17
+ .cover-title-block{position:absolute;top:188px;left:48px;max-width:440px;z-index:1}
18
+ .cover-title-line1,.cover-title-line2{font-size:54px;font-weight:600;color:#00AEEF;line-height:1.06;letter-spacing:-.5px}
19
+ .cover-meta-block{position:absolute;top:418px;left:48px;z-index:1}
20
+ .cover-ref{font-size:22px;font-weight:700;color:#1a1a1a;letter-spacing:.02em}
21
+ .cover-datetime{font-size:15px;color:#1a1a1a;font-weight:400;margin-top:10px}
22
+ .cover-summary{position:absolute;top:548px;left:48px;width:400px;display:flex;flex-direction:column;gap:16px;z-index:1}
23
+ .cover-sum-row{display:grid;grid-template-columns:182px 14px 1fr;column-gap:4px;align-items:baseline;font-size:16px;line-height:1.35}
24
+ .cover-sum-label{color:#1a1a1a;font-weight:400;text-align:left}
25
+ .cover-sum-colon{color:#1a1a1a;font-weight:400;text-align:center}
26
+ .cover-sum-val{color:#000;font-weight:700}
27
+ .cover-footer{position:absolute;bottom:36px;left:48px;right:48px;display:flex;justify-content:space-between;align-items:center;border-top:1px solid #d9d9d9;padding-top:14px;z-index:1}
28
+ .cover-footer-page{font-size:11px;color:#999}
29
+ .cover-footer-gen{display:flex;align-items:center;gap:8px;font-size:12px;color:#00AEEF;font-weight:600}
30
+ /* Score page */
31
+ .score-page{padding:40px}
32
+ .score-hero{text-align:center;margin-bottom:36px}
33
+ .score-pct{font-size:72px;font-weight:700;color:#00AEEF;line-height:1}
34
+ .score-sub{font-size:18px;color:#444;margin-top:8px}
35
+ .score-date{font-size:14px;color:#888;margin-top:4px}
36
+ .section-title{font-size:16px;font-weight:700;color:#1a1a2e;margin-bottom:16px;padding-bottom:8px;border-bottom:2px solid #00AEEF}
37
+ .history-bars{display:flex;align-items:flex-end;gap:8px;height:160px;margin-bottom:36px}
38
+ .bar-wrap{flex:1;display:flex;flex-direction:column;align-items:center;gap:4px}
39
+ .bar{width:100%;background:#00AEEF;border-radius:4px 4px 0 0;display:flex;align-items:flex-start;justify-content:center}
40
+ .bar-pct{font-size:10px;color:#fff;padding-top:4px;font-weight:600}
41
+ .bar-date{font-size:9px;color:#888;text-align:center;white-space:nowrap}
42
+ .bar-axis{width:100%;height:1px;background:#ddd;margin-bottom:8px}
43
+ /* Section wise table */
44
+ .sw-table{width:100%;border-collapse:collapse;font-size:14px}
45
+ .sw-table th{background:#f0f7ff;color:#1a1a2e;font-weight:600;padding:10px 14px;text-align:left}
46
+ .sw-table td{padding:10px 14px;border-bottom:1px solid #f0f0f0;color:#444}
47
+ .sw-table tr:last-child td{border-bottom:none}
48
+ .pct-pill{display:inline-block;padding:2px 10px;border-radius:20px;font-size:12px;font-weight:600}
49
+ .pct-hi{background:#e1f5ee;color:#0f6e56}
50
+ .pct-mid{background:#faeeda;color:#854f0b}
51
+ .pct-lo{background:#fcebeb;color:#a32d2d}
52
+ /* Detail pages */
53
+ .detail-page{padding:32px 40px}
54
+ .dp-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:12px;border-bottom:2px solid #00AEEF}
55
+ .dp-header h2{font-size:18px;font-weight:700;color:#1a1a2e}
56
+ .dp-score{font-size:15px;font-weight:700;color:#00AEEF}
57
+ .q-row{display:flex;gap:12px;margin-bottom:14px;padding:12px;border-radius:8px;background:transparent}
58
+ .q-num{font-size:12px;font-weight:700;color:#000;min-width:22px}
59
+ .q-body{flex:1}
60
+ .q-text{font-size:13px;color:#444;margin-bottom:4px}
61
+ .q-ans{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:600;padding:2px 8px;border-radius:12px}
62
+ .ans-yes{background:#e1f5ee;color:#0f6e56}
63
+ .ans-no{background:#fcebeb;color:#a32d2d}
64
+ .flag-badge{background:#faeeda;color:#854f0b;font-size:10px;font-weight:600;padding:1px 6px;border-radius:8px;margin-left:6px}
65
+ .q-answer-list{margin-top:6px}
66
+ .q-answer-item{margin-top:6px;padding:0;background:transparent;border:none;border-radius:0}
67
+ .q-answer-text{font-size:12px;color:#1a1a1a;line-height:1.5}
68
+ .q-answer-text.flagged{color:#a32d2d}
69
+ .q-answer-media{margin-top:8px}
70
+ .q-answer-media img,.q-answer-media video{display:block;max-width:220px;max-height:180px;border-radius:6px}
71
+ .q-answer-link{font-size:12px;color:#0085D2;text-decoration:underline;word-break:break-all}
72
+ .q-answer-caption{font-size:11px;color:#666;margin-bottom:4px}
73
+ .q-answer-remarks{font-size:11px;color:#666;margin-top:6px}
74
+ /* Footer */
75
+ .page-footer{position:absolute;bottom:20px;left:40px;right:40px;display:flex;justify-content:space-between;align-items:center;font-size:11px;color:#999;border-top:1px solid #d9d9d9;padding-top:10px}
76
+ .footer-brand{display:flex;align-items:center;gap:8px;font-weight:600;color:#0066CC;font-size:11px}
77
+ .footer-gen-by{color:#666;font-weight:400}
78
+ .cover-footer-gen .footer-gen-by{color:#1a1a1a}
79
+ .footer-tangoye-logo{display:block;flex-shrink:0}
80
+ @page{size:A4;margin:0}
81
+ </style>
82
+ </head>
83
+ <body>
84
+
85
+ {{!-- PAGE 1: COVER --}}
86
+ <div class="page cover-wrap">
87
+ <svg class="cover-deco" width="493" height="1043" viewBox="0 0 398 842" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMaxYMin meet" aria-hidden="true">
88
+ <path opacity="0.8" d="M397.199 842V586L334.199 292L222.199 842H397.199Z" fill="#99DAFF"/>
89
+ <path opacity="0.7" d="M125.199 0H142.544L397.199 204.045V380L125.199 0Z" fill="#51C1FF"/>
90
+ <path opacity="0.7" d="M84.7003 -0.00271425L125.197 -0.00675424L334.347 292.188L298.195 469L84.7003 -0.00271425Z" fill="#99DAFF"/>
91
+ <path opacity="0.7" d="M397.199 360.707L334.199 292L397.199 586V360.707Z" fill="#6BCAFF"/>
92
+ <path opacity="0.6" d="M397.199 220L125.199 0H397.199V220Z" fill="#009BF3"/>
93
+ </svg>
94
+
95
+ <div class="cover-brand">
96
+ <img src="{{brandLogo}}" width="100px" height="100px" />
97
+ </div>
98
+
99
+ <div class="cover-title-block">
100
+ <div class="cover-title-line1">{{#if titleLine1}}{{titleLine1}}{{else}}{{checklistType}}{{/if}}</div>
101
+ </div>
102
+
103
+ <div class="cover-meta-block">
104
+ <div class="cover-ref">{{referenceId}}</div>
105
+ <div class="cover-datetime">{{date}} | {{time}}</div>
106
+ </div>
107
+
108
+ <div class="cover-summary">
109
+ <div class="cover-sum-row"><span class="cover-sum-label">No. of questions</span><span class="cover-sum-colon">:</span><span class="cover-sum-val">{{numQuestions}}</span></div>
110
+ <div class="cover-sum-row"><span class="cover-sum-label">No. of flags</span><span class="cover-sum-colon">:</span><span class="cover-sum-val">{{numFlags}}</span></div>
111
+ <div class="cover-sum-row"><span class="cover-sum-label">AI Breached</span><span class="cover-sum-colon">:</span><span class="cover-sum-val">{{aiBreached}}</span></div>
112
+ <div class="cover-sum-row"><span class="cover-sum-label">Submitted By</span><span class="cover-sum-colon">:</span><span class="cover-sum-val">{{submittedBy}}</span></div>
113
+ <div class="cover-sum-row"><span class="cover-sum-label">Country</span><span class="cover-sum-colon">:</span><span class="cover-sum-val">{{country}}</span></div>
114
+ </div>
115
+
116
+ <div class="cover-footer">
117
+ <span class="cover-footer-page">Page 1 of {{totalPages}}</span>
118
+ <div class="cover-footer-gen">
119
+ <span class="footer-gen-by">Generated by</span>
120
+ {{> tangoyeFooterLogo gid="cover"}}
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ {{!-- PAGE 2: SCORE SUMMARY --}}
126
+ {{#if hasCompliancePage}}
127
+ <div class="page">
128
+ <div class="score-page">
129
+ <div class="score-hero">
130
+ <div class="score-pct">{{totalPercentage}}%</div>
131
+ <div class="score-sub">Total: <strong>{{totalScore}}</strong> out of <strong>{{maxScore}}</strong></div>
132
+ <div class="score-date">{{reportDate}}</div>
133
+ </div>
134
+
135
+ {{#if historyData}}
136
+ <div class="section-title">History — Last 7 Days</div>
137
+ <div style="display:flex;flex-direction:column;margin-bottom:36px">
138
+ <div class="history-bars">
139
+ {{#each historyData}}
140
+ <div class="bar-wrap">
141
+ <div class="bar" style="height:{{this.barHeight}}px"><span class="bar-pct">{{this.value}}%</span></div>
142
+ <span class="bar-date">{{this.date}}</span>
143
+ </div>
144
+ {{/each}}
145
+ </div>
146
+ <div class="bar-axis"></div>
147
+ </div>
148
+ {{/if}}
149
+
150
+ <div class="section-title">Section Wise Insights</div>
151
+ <table class="sw-table">
152
+ <thead><tr><th>Sections</th><th>Target Score</th><th>Actual Scrore</th><th>%</th></tr></thead>
153
+ <tbody>
154
+ {{#each sectionInsights}}
155
+ <tr>
156
+ <td>{{this.sectionName}}</td>
157
+ <td>{{this.questionsCount}}</td>
158
+ <td>{{this.passedCount}}</td>
159
+ <td><span class="pct-pill {{#gte this.percentage 90}}pct-hi{{else}}{{#gte this.percentage 70}}pct-mid{{else}}pct-lo{{/gte}}{{/gte}}">{{this.percentage}}%</span></td>
160
+ </tr>
161
+ {{/each}}
162
+ </tbody>
163
+ </table>
164
+ </div>
165
+ <div class="page-footer">
166
+ <span>Page 2 of {{totalPages}}</span>
167
+ <span class="footer-brand"><span class="footer-gen-by">Generated by</span>{{> tangoyeFooterLogo gid="p2"}}</span>
168
+ </div>
169
+ </div>
170
+ {{/if}}
171
+
172
+ {{!-- PAGES 3+: DETAIL - Question sections --}}
173
+ {{#each detailPageGroups}}
174
+ <div class="page">
175
+ <div class="detail-page">
176
+ {{#each this.sections}}
177
+ <div class="dp-header" {{#unless @first}}style="margin-top:20px"{{/unless}}><h2>{{this.sectionName}}</h2><span class="dp-score">{{this.currentScore}}/{{this.maxScore}} · {{this.percentage}}%</span></div>
178
+ <div class="sec-questions">
179
+ {{#each this.questions}}
180
+ <div class="q-row">
181
+ <span class="q-num">{{this.qno}}</span>
182
+ <div class="q-body">
183
+ <div class="q-text">{{this.qname}}{{#if this.isNo}}<span class="flag-badge">FLAG</span>{{/if}}</div>
184
+ {{!-- <span class="q-ans {{#if this.isYes}}ans-yes{{else}}{{#if this.isNo}}ans-no{{/if}}{{/if}}">{{#if this.isYes}}✓ Yes{{else}}{{#if this.isNo}}✗ No{{else}}{{this.answerDisplay}}{{/if}}{{/if}}</span> --}}
185
+ {{#if this.userAnswer.length}}
186
+ <div class="q-answer-list">
187
+ {{#each this.userAnswer}}
188
+ <div class="q-answer-item">
189
+ {{#if this.answer}}
190
+ {{#eq this.answerType 'image'}}
191
+ <div class="q-answer-media">
192
+ {{#if this.referenceImage}}
193
+ <div class="q-answer-caption">Reference Image</div>
194
+ <img src="{{this.referenceImage}}" alt="Reference Image" />
195
+ {{/if}}
196
+ <div class="q-answer-caption">Uploaded Image</div>
197
+ <img src="{{this.answer}}" alt="Uploaded Image" />
198
+ </div>
199
+ {{/eq}}
200
+ {{#eq this.answerType 'video'}}
201
+ <div class="q-answer-media">
202
+ <div class="q-answer-caption">Uploaded Video</div>
203
+ <a class="q-answer-link" href="{{this.answer}}" target="_blank">{{this.answer}}</a>
204
+ </div>
205
+ {{/eq}}
206
+ {{#eq this.answerType 'text'}}
207
+ <div class="q-answer-text {{#if this.sopFlag}}flagged{{/if}}">{{this.answer}}</div>
208
+ {{/eq}}
209
+ {{/if}}
210
+
211
+ {{#if this.validation}}
212
+ {{#if this.validationAnswer}}
213
+ {{#eq this.validationDisplayType 'image'}}
214
+ <div class="q-answer-media">
215
+ <div class="q-answer-caption">Validation Image</div>
216
+ <img src="{{this.validationAnswer}}" alt="Validation Image" />
217
+ </div>
218
+ {{/eq}}
219
+ {{#eq this.validationDisplayType 'video'}}
220
+ <div class="q-answer-media">
221
+ <div class="q-answer-caption">Validation Video</div>
222
+ <a class="q-answer-link" href="{{this.validationAnswer}}" target="_blank">{{this.validationAnswer}}</a>
223
+ </div>
224
+ {{/eq}}
225
+ {{#eq this.validationDisplayType 'text'}}
226
+ <div class="q-answer-text">{{this.validationAnswer}}</div>
227
+ {{/eq}}
228
+ {{/if}}
229
+ {{/if}}
230
+
231
+ {{#if this.remarks}}
232
+ <div class="q-answer-remarks">Remarks: {{this.remarks}}</div>
233
+ {{/if}}
234
+ </div>
235
+ {{/each}}
236
+ </div>
237
+ {{/if}}
238
+ </div>
239
+ </div>
240
+ {{/each}}
241
+ </div>
242
+ {{/each}}
243
+
244
+ {{#if this.isLastGroup}}
245
+ {{#each ../flags}}
246
+ <div style="margin-top:12px;padding:12px;background:#faeeda;border-radius:8px;border-left:4px solid #ef9f27">
247
+ <strong style="font-size:13px;color:#854f0b">⚠ Flag: {{this.sectionName}} — {{this.qname}}</strong>
248
+ <p style="font-size:12px;color:#854f0b;margin-top:4px">Q{{this.qno}} ({{this.sectionName}}): "{{this.qname}}" — Answered: <strong>{{this.answer}}</strong>. Action required.</p>
249
+ </div>
250
+ {{/each}}
251
+ {{/if}}
252
+ </div>
253
+ <div class="page-footer">
254
+ <span>Page {{this.pageNumber}} of {{../totalPages}}</span>
255
+ <span class="footer-brand"><span class="footer-gen-by">Generated by</span>{{> tangoyeFooterLogo gid=(strConcat 'd' @index)}}</span>
256
+ </div>
257
+ </div>
258
+ {{/each}}
259
+
260
+ </body>
261
+ </html>
@@ -36,6 +36,7 @@ internalTraxRouter
36
36
  .post( '/checklistCreation', isAllowedInternalAPIHandler, internalController.checklistCreation )
37
37
  .post( '/getSubmissionDetails', isAllowedInternalAPIHandler, internalController.checklistTaskSubmissionDetails )
38
38
  .post( '/posblock', isAllowedInternalAPIHandler, internalController.getStoreTaskDetails )
39
+ .post( '/runAIFlag', isAllowedInternalAPIHandler, internalController.runAIFlag )
39
40
  ;
40
41
 
41
42