tango-app-api-trax 3.7.97 → 3.7.99

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tango-app-api-trax",
3
- "version": "3.7.97",
3
+ "version": "3.7.99",
4
4
  "description": "Trax",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "nodemon": "^3.1.4",
30
30
  "path": "^0.12.7",
31
31
  "puppeteer": "^24.39.1",
32
- "tango-api-schema": "^2.5.70",
32
+ "tango-api-schema": "^2.5.68",
33
33
  "tango-app-api-middleware": "^3.5.2",
34
34
  "url": "^0.11.4",
35
35
  "winston": "^3.13.1",
@@ -3585,16 +3585,9 @@ export const downloadInsertPdf = async ( req, res ) => {
3585
3585
  pdfBuffer :
3586
3586
  Buffer.from( pdfBuffer );
3587
3587
 
3588
- let pdfName;
3589
- if ( doc.store_id ) {
3590
- pdfName = `${safeName(
3591
- doc.store_id + '_' + ( doc.storeName || 'store' ),
3592
- )}.pdf`;
3593
- } else {
3594
- pdfName = `${safeName(
3595
- doc.userName + '_' + ( doc.sourceCheckList_id || 'store' ),
3596
- )}.pdf`;
3597
- }
3588
+ const pdfName = `${safeName(
3589
+ doc.store_id + '_' + ( doc.storeName || 'store' ),
3590
+ )}.pdf`;
3598
3591
 
3599
3592
  res.set( {
3600
3593
  'Content-Type': 'application/pdf',
@@ -3822,7 +3822,6 @@ export async function taskQuestionList( req, res ) {
3822
3822
  rawImageUpload: { $ifNull: [ '$rawImageUpload', false ] },
3823
3823
  rawVideoUpload: { $ifNull: [ '$rawVideoUpload', false ] },
3824
3824
  videoUploadTimeLimit: { $ifNull: [ '$videoUploadTimeLimit', 0 ] },
3825
- aiType: 1,
3826
3825
  },
3827
3826
  } );
3828
3827
 
@@ -608,8 +608,6 @@ export const zoneList = async ( req, res ) => {
608
608
  'Mobile usage detection',
609
609
  'Store TV Compliance',
610
610
  'Queue Wait Time Breach',
611
- 'Uniform detection',
612
- 'Store Hygiene Monitoring',
613
611
  ];
614
612
  const allowedChecklistsStreams = [
615
613
  'Camera Angle Change Compliance',
@@ -5165,14 +5163,3 @@ export async function downloadQuestionTemplate( req, res ) {
5165
5163
  return res.sendError( e, 500 );
5166
5164
  }
5167
5165
  }
5168
-
5169
-
5170
- export async function getTeamList( req, res ) {
5171
- try {
5172
- let teamsDetails = await teamsServices.findteams( { clientId: req.query.clientId, status: 'active' } );
5173
- return res.sendSuccess( teamsDetails );
5174
- } catch ( e ) {
5175
- logger.error( { functionName: 'getTeamList', error: e } );
5176
- return res.sendError( e, 500 );
5177
- }
5178
- }
@@ -1,244 +1,244 @@
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;background:#fff;padding:0;overflow:hidden;position:relative;page-break-after:always}
11
- .cover-wrap{position:relative;width:794px;height:284mm;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;bottom:0;left:auto;width:450px;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:400px;z-index:1}
18
- .cover-title-line1,.cover-title-line2{font-size:40px;font-weight:600;color:#00AEEF;line-height:1.15;letter-spacing:-.5px;word-wrap:break-word;overflow-wrap:break-word}
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{margin-bottom:40px;padding-bottom:20px;border-bottom:1px solid #e0e0e0}
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:30px;padding-bottom:10px;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
- .q-row{break-inside:auto}
55
- .q-answer-item{break-inside:auto}
56
- .dp-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:12px;border-bottom:2px solid #00AEEF}
57
- .dp-header h2{font-size:18px;font-weight:700;color:#1a1a2e}
58
- .dp-score{font-size:15px;font-weight:700;color:#000000}
59
- .q-row{display:flex;gap:12px;margin-bottom:14px;padding:12px;border-radius:8px;background:transparent}
60
- .q-num{font-size:12px;font-weight:700;color:#000;min-width:22px}
61
- .q-body{flex:1}
62
- .q-text{font-size:13px;color:#444;margin-bottom:4px}
63
- .q-ans{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:600;padding:2px 8px;border-radius:12px}
64
- .ans-yes{background:#e1f5ee;color:#0f6e56}
65
- .ans-no{background:#fcebeb;color:#a32d2d}
66
- .flag-badge{background:#faeeda;color:#854f0b;font-size:10px;font-weight:600;padding:1px 6px;border-radius:8px;margin-left:6px}
67
- .q-answer-list{margin-top:6px}
68
- .q-answer-item{margin-top:6px;padding:0;background:transparent;border:none;border-radius:0}
69
- .q-answer-text{font-size:12px;color:#1a1a1a;line-height:1.5}
70
- .q-answer-text.flagged{color:#a32d2d}
71
- .q-answer-media{margin-top:8px}
72
- .q-answer-media img,.q-answer-media video{display:block;max-width:220px;max-height:180px;border-radius:6px}
73
- .q-answer-link{font-size:12px;color:#0085D2;text-decoration:underline;word-break:break-all}
74
- .q-answer-caption{font-size:11px;color:#666;margin-bottom:4px}
75
- .q-answer-remarks{font-size:11px;color:#666;margin-top:6px}
76
- /* Footer */
77
- .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}
78
- .footer-brand{display:flex;align-items:center;gap:8px;font-weight:600;color:#0066CC;font-size:11px}
79
- .footer-gen-by{color:#666;font-weight:400}
80
- .cover-footer-gen .footer-gen-by{color:#1a1a1a}
81
- .footer-tangoye-logo{display:block;flex-shrink:0}
82
- @page{size:A4;margin:5mm 0mm 15mm 0mm}
83
- @page:first{margin:0}
84
- </style>
85
- </head>
86
- <body>
87
-
88
- {{!-- PAGE 1: COVER --}}
89
- <div class="page cover-wrap">
90
- <svg xmlns="http://www.w3.org/2000/svg" class="cover-deco" viewBox="0 0 650 2000" fill="none">
91
- <path opacity="0.8" d="M711.5 2000V1391.92L568.063 693.586L313.062 2000H711.5Z" fill="#99DAFF" />
92
- <path opacity="0.7" d="M92.2148 0.0078125H131.706L711.501 484.677V902.622L92.2148 0.0078125Z" fill="#51C1FF" />
93
- <path opacity="0.7" d="M0 0.00959645L92.203 0L568.392 694.051L486.082 1114.03L0 0.00959645Z" fill="#99DAFF" />
94
- <path opacity="0.7" d="M711.5 856.786L568.062 693.586L711.5 1391.92V856.786Z" fill="#6BCAFF" />
95
- <path opacity="0.6" d="M711.501 522.574L92.2148 0.0078125H711.501V522.574Z" fill="#009BF3" />
96
- </svg>
97
-
98
- <div class="cover-brand">
99
- <img src="{{brandLogo}}" width="100px" height="100px" />
100
- </div>
101
-
102
- <div class="cover-title-block">
103
- <div class="cover-title-line1">{{#if titleLine1}}{{titleLine1}}{{else}}{{checklistType}}{{/if}}</div>
104
- </div>
105
-
106
- <div class="cover-meta-block">
107
- <div class="cover-ref">{{referenceId}}</div>
108
- <div class="cover-datetime">{{date}} | {{time}}</div>
109
- </div>
110
-
111
- <div class="cover-summary">
112
- <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>
113
- <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>
114
- <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>
115
- <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>
116
- <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>
117
- </div>
118
-
119
- {{!-- <div class="cover-footer">
120
- <span class="cover-footer-page"></span>
121
- <div class="cover-footer-gen">
122
- <span class="footer-gen-by">Generated by</span>
123
- {{> tangoyeFooterLogo gid="cover"}}
124
- </div>
125
- </div> --}}
126
- </div>
127
-
128
- {{!-- SCORE SUMMARY + DETAIL (continuous flow) --}}
129
- <div class="detail-page">
130
- {{#if hasCompliancePage}}
131
- <div class="score-page">
132
- <div class="score-hero">
133
- <div class="score-pct">{{totalPercentage}}%</div>
134
- <div class="score-sub">Total: <strong>{{totalScore}}</strong> out of <strong>{{maxScore}}</strong></div>
135
- <div class="score-date">{{reportDate}}</div>
136
- </div>
137
-
138
- {{#if historyData}}
139
- <div class="section-title">History — Last 7 Days</div>
140
- <div style="display:flex;flex-direction:column;margin-bottom:36px">
141
- <div class="history-bars">
142
- {{#each historyData}}
143
- <div class="bar-wrap">
144
- <div class="bar" style="height:{{this.barHeight}}px"><span class="bar-pct">{{this.value}}%</span></div>
145
- <span class="bar-date">{{this.date}}</span>
146
- </div>
147
- {{/each}}
148
- </div>
149
- <div class="bar-axis"></div>
150
- </div>
151
- {{/if}}
152
-
153
- <div class="section-title">Section Wise Insights</div>
154
- <table class="sw-table">
155
- <thead><tr><th>Sections</th><th>Target Score</th><th>Actual Scrore</th><th>%</th></tr></thead>
156
- <tbody>
157
- {{#each sectionInsights}}
158
- <tr>
159
- <td>{{this.sectionName}}</td>
160
- <td>{{this.targetScore}}</td>
161
- <td>{{this.actualScore}}</td>
162
- <td>{{this.percentage}}%</td>
163
- </tr>
164
- {{/each}}
165
- </tbody>
166
- </table>
167
- </div>
168
- {{/if}}
169
- {{#each sections}}
170
- <div class="dp-header" {{#unless @first}}style="margin-top:20px"{{/unless}}><h2>{{this.sectionName}}</h2>{{#if this.maxScore}}<span class="dp-score">{{this.currentScore}}/{{this.maxScore}}</span>{{/if}}</div>
171
- <div class="sec-questions">
172
- {{#each this.questions}}
173
- <div class="q-row">
174
- <span class="q-num">{{this.qno}}</span>
175
- <div class="q-body">
176
- <div class="q-text" style="display:flex;justify-content:space-between">
177
- <div>{{this.qname}}</div>
178
- {{#if this.compliance}}
179
- <div>Score:{{this.score}}</div>
180
- {{/if}}
181
- </div>
182
- {{!-- <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> --}}
183
- {{#if this.userAnswer.length}}
184
- <div class="q-answer-list">
185
- {{#each this.userAnswer}}
186
- <div class="q-answer-item">
187
- {{#if this.answer}}
188
- {{#eq this.answerType 'image'}}
189
- <div class="q-answer-media">
190
- {{#if this.referenceImage}}
191
- <div class="q-answer-caption">Reference Image</div>
192
- <img src="{{this.referenceImage}}" alt="Reference Image" />
193
- {{/if}}
194
- <div class="q-answer-caption">Uploaded Image</div>
195
- <img src="{{this.answer}}" alt="Uploaded Image" />
196
- </div>
197
- {{/eq}}
198
- {{#eq this.answerType 'video'}}
199
- <div class="q-answer-media">
200
- <div class="q-answer-caption">Uploaded Video</div>
201
- <a class="q-answer-link" href="{{this.answer}}" target="_blank">{{this.answer}}</a>
202
- </div>
203
- {{/eq}}
204
- {{#eq this.answerType 'text'}}
205
- <div class="q-answer-text {{#if this.sopFlag}}flagged{{/if}}">{{this.answer}}</div>
206
- {{/eq}}
207
- {{/if}}
208
-
209
- {{#if this.validation}}
210
- {{#if this.validationAnswer}}
211
- {{#eq this.validationDisplayType 'image'}}
212
- <div class="q-answer-media">
213
- <div class="q-answer-caption">Validation Image</div>
214
- <img src="{{this.validationAnswer}}" alt="Validation Image" />
215
- </div>
216
- {{/eq}}
217
- {{#eq this.validationDisplayType 'video'}}
218
- <div class="q-answer-media">
219
- <div class="q-answer-caption">Validation Video</div>
220
- <a class="q-answer-link" href="{{this.validationAnswer}}" target="_blank">{{this.validationAnswer}}</a>
221
- </div>
222
- {{/eq}}
223
- {{#eq this.validationDisplayType 'text'}}
224
- <div class="q-answer-text">{{this.validationAnswer}}</div>
225
- {{/eq}}
226
- {{/if}}
227
- {{/if}}
228
-
229
- {{#if this.remarks}}
230
- <div class="q-answer-remarks">Remarks: {{this.remarks}}</div>
231
- {{/if}}
232
- </div>
233
- {{/each}}
234
- </div>
235
- {{/if}}
236
- </div>
237
- </div>
238
- {{/each}}
239
- </div>
240
- {{/each}}
241
- </div>
242
-
243
- </body>
244
- </html>
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;background:#fff;padding:0;overflow:hidden;position:relative;page-break-after:always}
11
+ .cover-wrap{position:relative;width:794px;height:284mm;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;bottom:0;left:auto;width:450px;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:400px;z-index:1}
18
+ .cover-title-line1,.cover-title-line2{font-size:40px;font-weight:600;color:#00AEEF;line-height:1.15;letter-spacing:-.5px;word-wrap:break-word;overflow-wrap:break-word}
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{margin-bottom:40px;padding-bottom:20px;border-bottom:1px solid #e0e0e0}
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:30px;padding-bottom:10px;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
+ .q-row{break-inside:auto}
55
+ .q-answer-item{break-inside:auto}
56
+ .dp-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;padding-bottom:12px;border-bottom:2px solid #00AEEF}
57
+ .dp-header h2{font-size:18px;font-weight:700;color:#1a1a2e}
58
+ .dp-score{font-size:15px;font-weight:700;color:#000000}
59
+ .q-row{display:flex;gap:12px;margin-bottom:14px;padding:12px;border-radius:8px;background:transparent}
60
+ .q-num{font-size:12px;font-weight:700;color:#000;min-width:22px}
61
+ .q-body{flex:1}
62
+ .q-text{font-size:13px;color:#444;margin-bottom:4px}
63
+ .q-ans{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:600;padding:2px 8px;border-radius:12px}
64
+ .ans-yes{background:#e1f5ee;color:#0f6e56}
65
+ .ans-no{background:#fcebeb;color:#a32d2d}
66
+ .flag-badge{background:#faeeda;color:#854f0b;font-size:10px;font-weight:600;padding:1px 6px;border-radius:8px;margin-left:6px}
67
+ .q-answer-list{margin-top:6px}
68
+ .q-answer-item{margin-top:6px;padding:0;background:transparent;border:none;border-radius:0}
69
+ .q-answer-text{font-size:12px;color:#1a1a1a;line-height:1.5}
70
+ .q-answer-text.flagged{color:#a32d2d}
71
+ .q-answer-media{margin-top:8px}
72
+ .q-answer-media img,.q-answer-media video{display:block;max-width:220px;max-height:180px;border-radius:6px}
73
+ .q-answer-link{font-size:12px;color:#0085D2;text-decoration:underline;word-break:break-all}
74
+ .q-answer-caption{font-size:11px;color:#666;margin-bottom:4px}
75
+ .q-answer-remarks{font-size:11px;color:#666;margin-top:6px}
76
+ /* Footer */
77
+ .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}
78
+ .footer-brand{display:flex;align-items:center;gap:8px;font-weight:600;color:#0066CC;font-size:11px}
79
+ .footer-gen-by{color:#666;font-weight:400}
80
+ .cover-footer-gen .footer-gen-by{color:#1a1a1a}
81
+ .footer-tangoye-logo{display:block;flex-shrink:0}
82
+ @page{size:A4;margin:5mm 0mm 15mm 0mm}
83
+ @page:first{margin:0}
84
+ </style>
85
+ </head>
86
+ <body>
87
+
88
+ {{!-- PAGE 1: COVER --}}
89
+ <div class="page cover-wrap">
90
+ <svg xmlns="http://www.w3.org/2000/svg" class="cover-deco" viewBox="0 0 650 2000" fill="none">
91
+ <path opacity="0.8" d="M711.5 2000V1391.92L568.063 693.586L313.062 2000H711.5Z" fill="#99DAFF" />
92
+ <path opacity="0.7" d="M92.2148 0.0078125H131.706L711.501 484.677V902.622L92.2148 0.0078125Z" fill="#51C1FF" />
93
+ <path opacity="0.7" d="M0 0.00959645L92.203 0L568.392 694.051L486.082 1114.03L0 0.00959645Z" fill="#99DAFF" />
94
+ <path opacity="0.7" d="M711.5 856.786L568.062 693.586L711.5 1391.92V856.786Z" fill="#6BCAFF" />
95
+ <path opacity="0.6" d="M711.501 522.574L92.2148 0.0078125H711.501V522.574Z" fill="#009BF3" />
96
+ </svg>
97
+
98
+ <div class="cover-brand">
99
+ <img src="{{brandLogo}}" width="100px" height="100px" />
100
+ </div>
101
+
102
+ <div class="cover-title-block">
103
+ <div class="cover-title-line1">{{#if titleLine1}}{{titleLine1}}{{else}}{{checklistType}}{{/if}}</div>
104
+ </div>
105
+
106
+ <div class="cover-meta-block">
107
+ <div class="cover-ref">{{referenceId}}</div>
108
+ <div class="cover-datetime">{{date}} | {{time}}</div>
109
+ </div>
110
+
111
+ <div class="cover-summary">
112
+ <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>
113
+ <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>
114
+ <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>
115
+ <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>
116
+ <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>
117
+ </div>
118
+
119
+ {{!-- <div class="cover-footer">
120
+ <span class="cover-footer-page"></span>
121
+ <div class="cover-footer-gen">
122
+ <span class="footer-gen-by">Generated by</span>
123
+ {{> tangoyeFooterLogo gid="cover"}}
124
+ </div>
125
+ </div> --}}
126
+ </div>
127
+
128
+ {{!-- SCORE SUMMARY + DETAIL (continuous flow) --}}
129
+ <div class="detail-page">
130
+ {{#if hasCompliancePage}}
131
+ <div class="score-page">
132
+ <div class="score-hero">
133
+ <div class="score-pct">{{totalPercentage}}%</div>
134
+ <div class="score-sub">Total: <strong>{{totalScore}}</strong> out of <strong>{{maxScore}}</strong></div>
135
+ <div class="score-date">{{reportDate}}</div>
136
+ </div>
137
+
138
+ {{#if historyData}}
139
+ <div class="section-title">History — Last 7 Days</div>
140
+ <div style="display:flex;flex-direction:column;margin-bottom:36px">
141
+ <div class="history-bars">
142
+ {{#each historyData}}
143
+ <div class="bar-wrap">
144
+ <div class="bar" style="height:{{this.barHeight}}px"><span class="bar-pct">{{this.value}}%</span></div>
145
+ <span class="bar-date">{{this.date}}</span>
146
+ </div>
147
+ {{/each}}
148
+ </div>
149
+ <div class="bar-axis"></div>
150
+ </div>
151
+ {{/if}}
152
+
153
+ <div class="section-title">Section Wise Insights</div>
154
+ <table class="sw-table">
155
+ <thead><tr><th>Sections</th><th>Target Score</th><th>Actual Scrore</th><th>%</th></tr></thead>
156
+ <tbody>
157
+ {{#each sectionInsights}}
158
+ <tr>
159
+ <td>{{this.sectionName}}</td>
160
+ <td>{{this.targetScore}}</td>
161
+ <td>{{this.actualScore}}</td>
162
+ <td>{{this.percentage}}%</td>
163
+ </tr>
164
+ {{/each}}
165
+ </tbody>
166
+ </table>
167
+ </div>
168
+ {{/if}}
169
+ {{#each sections}}
170
+ <div class="dp-header" {{#unless @first}}style="margin-top:20px"{{/unless}}><h2>{{this.sectionName}}</h2>{{#if this.maxScore}}<span class="dp-score">{{this.currentScore}}/{{this.maxScore}}</span>{{/if}}</div>
171
+ <div class="sec-questions">
172
+ {{#each this.questions}}
173
+ <div class="q-row">
174
+ <span class="q-num">{{this.qno}}</span>
175
+ <div class="q-body">
176
+ <div class="q-text" style="display:flex;justify-content:space-between">
177
+ <div>{{this.qname}}</div>
178
+ {{#if this.compliance}}
179
+ <div>Score:{{this.score}}</div>
180
+ {{/if}}
181
+ </div>
182
+ {{!-- <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> --}}
183
+ {{#if this.userAnswer.length}}
184
+ <div class="q-answer-list">
185
+ {{#each this.userAnswer}}
186
+ <div class="q-answer-item">
187
+ {{#if this.answer}}
188
+ {{#eq this.answerType 'image'}}
189
+ <div class="q-answer-media">
190
+ {{#if this.referenceImage}}
191
+ <div class="q-answer-caption">Reference Image</div>
192
+ <img src="{{this.referenceImage}}" alt="Reference Image" />
193
+ {{/if}}
194
+ <div class="q-answer-caption">Uploaded Image</div>
195
+ <img src="{{this.answer}}" alt="Uploaded Image" />
196
+ </div>
197
+ {{/eq}}
198
+ {{#eq this.answerType 'video'}}
199
+ <div class="q-answer-media">
200
+ <div class="q-answer-caption">Uploaded Video</div>
201
+ <a class="q-answer-link" href="{{this.answer}}" target="_blank">{{this.answer}}</a>
202
+ </div>
203
+ {{/eq}}
204
+ {{#eq this.answerType 'text'}}
205
+ <div class="q-answer-text {{#if this.sopFlag}}flagged{{/if}}">{{this.answer}}</div>
206
+ {{/eq}}
207
+ {{/if}}
208
+
209
+ {{#if this.validation}}
210
+ {{#if this.validationAnswer}}
211
+ {{#eq this.validationDisplayType 'image'}}
212
+ <div class="q-answer-media">
213
+ <div class="q-answer-caption">Validation Image</div>
214
+ <img src="{{this.validationAnswer}}" alt="Validation Image" />
215
+ </div>
216
+ {{/eq}}
217
+ {{#eq this.validationDisplayType 'video'}}
218
+ <div class="q-answer-media">
219
+ <div class="q-answer-caption">Validation Video</div>
220
+ <a class="q-answer-link" href="{{this.validationAnswer}}" target="_blank">{{this.validationAnswer}}</a>
221
+ </div>
222
+ {{/eq}}
223
+ {{#eq this.validationDisplayType 'text'}}
224
+ <div class="q-answer-text">{{this.validationAnswer}}</div>
225
+ {{/eq}}
226
+ {{/if}}
227
+ {{/if}}
228
+
229
+ {{#if this.remarks}}
230
+ <div class="q-answer-remarks">Remarks: {{this.remarks}}</div>
231
+ {{/if}}
232
+ </div>
233
+ {{/each}}
234
+ </div>
235
+ {{/if}}
236
+ </div>
237
+ </div>
238
+ {{/each}}
239
+ </div>
240
+ {{/each}}
241
+ </div>
242
+
243
+ </body>
244
+ </html>
@@ -36,8 +36,6 @@ traxRouter
36
36
  .post( '/updateRunAIRequest', isAllowedSessionHandler, validate( runAIRequestValidation ), traxController.updateRunAIRequest )
37
37
  .post( '/createChecklistName', isAllowedSessionHandler, validate( createChecklistNameValidation ), traxController.createChecklistName )
38
38
  .post( '/updateOSProcessedData', isAllowedInternalAPIHandler, validate( updateOSDataValidation ), traxController.updateOSProcessedData )
39
- .post( '/exportQuestions', isAllowedSessionHandler, traxController.downloadQuestionTemplate )
40
- .get( '/getTeamList', isAllowedSessionHandler, traxController.getTeamList )
41
- ;
39
+ .post( '/exportQuestions', isAllowedSessionHandler, traxController.downloadQuestionTemplate );
42
40
 
43
41
  // isAllowedSessionHandler, isAllowedClient, accessVerification( { userType: [ 'tango', 'client' ], access: [ { featureName: 'TangoTrax', name: 'checklist', permissions: [ ] } ] } ),
@@ -447,6 +447,7 @@ export function buildVisitChecklistTemplateDataFromProcessed( processedDoc, bran
447
447
 
448
448
  let referenceId = doc.coverage == 'store' ? doc?.storeName : doc?.userName;
449
449
 
450
+
450
451
  return {
451
452
 
452
453