@7365admin1/layer-common 3.2.2-staging.158 → 3.2.2-staging.159

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.
@@ -1,8 +1,8 @@
1
1
  <template>
2
- <v-card width="100%">
3
- <v-toolbar>
2
+ <v-card width="100%" class="screen-modal">
3
+ <v-toolbar class="screen-dialog-bar">
4
4
  <v-row no-gutters class="fill-height px-6" align="center" justify="space-between">
5
- <span class="font-weight-bold text-h5 text-capitalize">
5
+ <span class="screen-card-title text-capitalize">
6
6
  {{ prop.mode }} Access Card
7
7
  </span>
8
8
  <v-btn-toggle
@@ -19,7 +19,10 @@
19
19
  </v-btn-toggle>
20
20
  </v-row>
21
21
  </v-toolbar>
22
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-0">
22
+ <!-- The height cap stays ON THE BODY. `.screen-modal` caps the CARD, which
23
+ only reaches the glass inside a dialog's flex column; mounted on its own
24
+ the footer would fall below the fold. -->
25
+ <v-card-text class="screen-modal__body pa-0" style="max-height: 100vh">
23
26
  <!-- Bulk Upload Mode -->
24
27
  <template v-if="uploadMode === 'bulk'">
25
28
  <v-row no-gutters class="px-6 pt-4 pb-2">
@@ -63,12 +66,12 @@
63
66
 
64
67
  <!-- Column Guide -->
65
68
  <div class="mt-3">
66
- <p class="text-caption font-weight-bold text-grey-darken-2 mb-1 text-uppercase">
69
+ <p class="text-caption font-weight-bold text-fontgray mb-1 text-uppercase">
67
70
  Template Column Guide
68
71
  </p>
69
72
  <v-table density="compact" class="text-caption rounded border">
70
73
  <thead>
71
- <tr class="bg-grey-lighten-4">
74
+ <tr class="template-guide-head">
72
75
  <th class="text-left text-caption font-weight-bold py-1 px-2">Column</th>
73
76
  <th class="text-left text-caption font-weight-bold py-1 px-2">Format / Accepted Values</th>
74
77
  <th class="text-left text-caption font-weight-bold py-1 px-2">Example</th>
@@ -77,8 +80,8 @@
77
80
  <tbody>
78
81
  <tr v-for="col in templateColumnGuide" :key="col.name">
79
82
  <td class="py-1 px-2 font-weight-medium" style="white-space: nowrap">{{ col.name }}</td>
80
- <td class="py-1 px-2 text-grey-darken-1">{{ col.format }}</td>
81
- <td class="py-1 px-2 text-grey-darken-2">{{ col.example }}</td>
83
+ <td class="py-1 px-2 text-fontgray">{{ col.format }}</td>
84
+ <td class="py-1 px-2 text-fontgray">{{ col.example }}</td>
82
85
  </tr>
83
86
  </tbody>
84
87
  </v-table>
@@ -306,7 +309,7 @@
306
309
  ></span>
307
310
  <span class="d-flex align-center">
308
311
  Anti Pass Back
309
- <v-icon class="ml-1" color="grey" size="small"
312
+ <v-icon class="ml-1 text-fontgray" size="small"
310
313
  >mdi-help-circle</v-icon
311
314
  >
312
315
  <v-checkbox
@@ -382,39 +385,25 @@
382
385
  </v-row>
383
386
  </v-form>
384
387
  </v-card-text>
385
- <v-toolbar density="compact">
386
- <v-row no-gutters>
387
- <v-col cols="6">
388
- <v-btn
389
- tile
390
- block
391
- variant="text"
392
- class="text-none"
393
- size="48"
394
- @click="cancel"
395
- :disabled="disable"
396
- >
397
- Cancel
398
- </v-btn>
399
- </v-col>
400
-
401
- <v-col cols="6">
402
- <v-btn
403
- tile
404
- block
405
- variant="flat"
406
- color="black"
407
- class="text-none"
408
- size="48"
409
- :disabled="(uploadMode === 'single' ? !validForm : !bulkFile || !entryPassTemplate.id || templateLoading) || disable"
410
- @click="submit"
411
- :loading="disable"
412
- >
413
- Submit
414
- </v-btn>
415
- </v-col>
416
- </v-row>
417
- </v-toolbar>
388
+ <v-card-actions class="screen-modal__footer">
389
+ <v-btn
390
+ variant="flat"
391
+ class="text-none screen-btn-ghost"
392
+ :disabled="disable"
393
+ @click="cancel"
394
+ >
395
+ Cancel
396
+ </v-btn>
397
+ <v-btn
398
+ variant="flat"
399
+ class="text-none screen-btn-primary"
400
+ :disabled="(uploadMode === 'single' ? !validForm : !bulkFile || !entryPassTemplate.id || templateLoading) || disable"
401
+ :loading="disable"
402
+ @click="submit"
403
+ >
404
+ Submit
405
+ </v-btn>
406
+ </v-card-actions>
418
407
  </v-card>
419
408
  </template>
420
409
  <script setup lang="ts">
@@ -813,3 +802,14 @@ async function submit() {
813
802
  }
814
803
  }
815
804
  </script>
805
+
806
+ <style scoped>
807
+ /*
808
+ * The template guide's header row. `bg-grey-lighten-4` was a fixed near-white,
809
+ * i.e. a bright band across a dark card; `--thead` is the design's own table
810
+ * head wash and is defined per theme.
811
+ */
812
+ .template-guide-head {
813
+ background: var(--thead);
814
+ }
815
+ </style>
@@ -9,16 +9,16 @@
9
9
 
10
10
  <!-- Assign to Person Dialog -->
11
11
  <v-dialog :model-value="showAssignForm" width="420" persistent>
12
- <v-card width="100%">
13
- <v-toolbar density="compact" color="surface">
12
+ <v-card width="100%" class="screen-modal">
13
+ <v-toolbar density="compact" class="screen-dialog-bar">
14
14
  <v-row no-gutters class="fill-height px-4" align="center">
15
15
  <span class="font-weight-bold">Assign Card to Person</span>
16
16
  </v-row>
17
17
  </v-toolbar>
18
18
 
19
19
  <v-card-text class="pa-4">
20
- <div class="text-caption text-grey mb-4">
21
- Card: <strong class="text-body-2 text-black">{{ selectedCardInUnit?.cardNo }}</strong>
20
+ <div class="text-caption text-fontgray mb-4">
21
+ Card: <strong class="text-body-2">{{ selectedCardInUnit?.cardNo }}</strong>
22
22
  </div>
23
23
 
24
24
  <!-- Person Type Filter -->
@@ -38,9 +38,7 @@
38
38
  </v-btn-toggle> -->
39
39
 
40
40
  <!-- Person Selector -->
41
- <div class="text-caption font-weight-bold mb-1 text-uppercase text-grey-darken-1">
42
- Person <span class="text-error">*</span>
43
- </div>
41
+ <InputLabel title="Person" required class="mb-1" />
44
42
  <v-select
45
43
  v-model="assignPerson"
46
44
  :items="filteredPeopleItems"
@@ -59,7 +57,7 @@
59
57
  </template>
60
58
  <template #selection="{ item }">
61
59
  <span>{{ item.raw.name }}</span>
62
- <v-chip size="x-small" class="ml-2" color="grey" variant="tonal">
60
+ <v-chip size="x-small" class="ml-2" variant="tonal">
63
61
  {{ personTypeLabel(item.raw) }}
64
62
  </v-chip>
65
63
  </template>
@@ -67,41 +65,30 @@
67
65
  <p v-if="assignError" class="text-error text-caption mt-2">{{ assignError }}</p>
68
66
  </v-card-text>
69
67
 
70
- <v-toolbar density="compact">
71
- <v-row no-gutters>
72
- <v-col cols="6" class="pa-0">
73
- <v-btn
74
- block
75
- variant="text"
76
- class="text-none"
77
- height="48"
78
- @click="cancelAssign"
79
- >
80
- Cancel
81
- </v-btn>
82
- </v-col>
83
- <v-col cols="6" class="pa-0">
84
- <v-btn
85
- block
86
- variant="flat"
87
- color="black"
88
- class="text-none"
89
- height="48"
90
- :disabled="!assignPerson || assignLoading"
91
- :loading="assignLoading"
92
- @click="confirmAssign"
93
- >
94
- Assign
95
- </v-btn>
96
- </v-col>
97
- </v-row>
98
- </v-toolbar>
68
+ <v-card-actions class="screen-modal__footer">
69
+ <v-btn
70
+ variant="flat"
71
+ class="text-none screen-btn-ghost"
72
+ @click="cancelAssign"
73
+ >
74
+ Cancel
75
+ </v-btn>
76
+ <v-btn
77
+ variant="flat"
78
+ class="text-none screen-btn-primary"
79
+ :disabled="!assignPerson || assignLoading"
80
+ :loading="assignLoading"
81
+ @click="confirmAssign"
82
+ >
83
+ Assign
84
+ </v-btn>
85
+ </v-card-actions>
99
86
  </v-card>
100
87
  </v-dialog>
101
88
 
102
89
  <v-dialog :model-value="modelValue" width="450" persistent>
103
- <v-card width="100%">
104
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
90
+ <v-card width="100%" class="screen-modal">
91
+ <v-card-text class="screen-modal__body pb-0">
105
92
  <v-row no-gutters class="mb-4">
106
93
  <v-col cols="12">
107
94
  <strong>Building:</strong> {{ unit?.block?.name ?? "N/A" }}
@@ -130,7 +117,7 @@
130
117
  {{ card.cardNo }}
131
118
  </v-chip>
132
119
  </div>
133
- <span v-else class="text-caption text-grey ml-1">None</span>
120
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
134
121
  </v-col>
135
122
 
136
123
  <!-- Damage Physical -->
@@ -142,7 +129,7 @@
142
129
  :key="card._id"
143
130
  size="small"
144
131
  class="mr-1 mb-1"
145
- color="deep-orange"
132
+ color="warning"
146
133
  :variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
147
134
  style="cursor: pointer"
148
135
  @click="toggleCard(card)"
@@ -150,7 +137,7 @@
150
137
  {{ card.cardNo }}
151
138
  </v-chip>
152
139
  </div>
153
- <span v-else class="text-caption text-grey ml-1">None</span>
140
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
154
141
  </v-col>
155
142
 
156
143
  <!-- Available Non-Physical -->
@@ -170,7 +157,7 @@
170
157
  {{ card.cardNo }}
171
158
  </v-chip>
172
159
  </div>
173
- <span v-else class="text-caption text-grey ml-1">None</span>
160
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
174
161
  </v-col>
175
162
 
176
163
  <!-- Assigned Physical -->
@@ -190,7 +177,7 @@
190
177
  {{ card.cardNo }}
191
178
  </v-chip>
192
179
  </div>
193
- <span v-else class="text-caption text-grey ml-1">None</span>
180
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
194
181
  </v-col>
195
182
 
196
183
  <!-- Assigned Non-Physical -->
@@ -210,7 +197,7 @@
210
197
  {{ card.cardNo }}
211
198
  </v-chip>
212
199
  </div>
213
- <span v-else class="text-caption text-grey ml-1">None</span>
200
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
214
201
  </v-col>
215
202
 
216
203
  <!-- Replaced Physical -->
@@ -222,7 +209,7 @@
222
209
  :key="card._id"
223
210
  size="small"
224
211
  class="mr-1 mb-1"
225
- :color="selectedCardInUnit?._id === card._id ? 'orange' : 'orange'"
212
+ color="warning"
226
213
  :variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
227
214
  style="cursor: pointer"
228
215
  @click="toggleCard(card)"
@@ -230,7 +217,7 @@
230
217
  {{ card.cardNo }}
231
218
  </v-chip>
232
219
  </div>
233
- <span v-else class="text-caption text-grey ml-1">None</span>
220
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
234
221
  </v-col>
235
222
 
236
223
  <!-- Replaced Non-Physical -->
@@ -242,7 +229,7 @@
242
229
  :key="card._id"
243
230
  size="small"
244
231
  class="mr-1 mb-1"
245
- :color="selectedCardInUnit?._id === card._id ? 'orange' : 'orange'"
232
+ color="warning"
246
233
  :variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
247
234
  style="cursor: pointer"
248
235
  @click="toggleCard(card)"
@@ -250,7 +237,7 @@
250
237
  {{ card.cardNo }}
251
238
  </v-chip>
252
239
  </div>
253
- <span v-else class="text-caption text-grey ml-1">None</span>
240
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
254
241
  </v-col>
255
242
 
256
243
  <!-- Deleted Physical -->
@@ -262,7 +249,7 @@
262
249
  :key="card._id"
263
250
  size="small"
264
251
  class="mr-1 mb-1"
265
- :color="selectedCardInUnit?._id === card._id ? 'red' : 'red'"
252
+ color="error"
266
253
  :variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
267
254
  style="cursor: pointer"
268
255
  @click="toggleCard(card)"
@@ -270,7 +257,7 @@
270
257
  {{ card.cardNo }}
271
258
  </v-chip>
272
259
  </div>
273
- <span v-else class="text-caption text-grey ml-1">None</span>
260
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
274
261
  </v-col>
275
262
 
276
263
  <!-- Deleted Non-Physical -->
@@ -282,7 +269,7 @@
282
269
  :key="card._id"
283
270
  size="small"
284
271
  class="mr-1 mb-1"
285
- :color="selectedCardInUnit?._id === card._id ? 'red' : 'red'"
272
+ color="error"
286
273
  :variant="selectedCardInUnit?._id === card._id ? 'flat' : 'tonal'"
287
274
  style="cursor: pointer"
288
275
  @click="toggleCard(card)"
@@ -290,40 +277,29 @@
290
277
  {{ card.cardNo }}
291
278
  </v-chip>
292
279
  </div>
293
- <span v-else class="text-caption text-grey ml-1">None</span>
280
+ <span v-else class="text-caption text-fontgray ml-1">None</span>
294
281
  </v-col>
295
282
  </v-row>
296
283
  </v-card-text>
297
284
 
298
- <v-toolbar class="pa-0" density="compact">
299
- <v-row no-gutters>
300
- <v-col cols="6" class="pa-0">
285
+ <v-card-actions class="screen-modal__footer">
286
+ <v-btn
287
+ variant="flat"
288
+ class="text-none screen-btn-ghost"
289
+ @click="emit('update:modelValue', false)"
290
+ >
291
+ Close
292
+ </v-btn>
293
+ <v-menu>
294
+ <template #activator="{ props }">
301
295
  <v-btn
302
- block
303
- variant="text"
304
- class="text-none"
305
- size="large"
306
- height="48"
307
- @click="emit('update:modelValue', false)"
296
+ variant="flat"
297
+ class="text-none screen-btn-primary"
298
+ v-bind="props"
308
299
  >
309
- Close
300
+ More actions
310
301
  </v-btn>
311
- </v-col>
312
- <v-col cols="6" class="pa-0">
313
- <v-menu>
314
- <template #activator="{ props }">
315
- <v-btn
316
- block
317
- variant="flat"
318
- color="black"
319
- class="text-none"
320
- height="48"
321
- v-bind="props"
322
- tile
323
- >
324
- More actions
325
- </v-btn>
326
- </template>
302
+ </template>
327
303
  <v-list class="pa-0">
328
304
  <v-list-item
329
305
  v-if="canAssignToPerson && isSelectedCardAvailable"
@@ -349,7 +325,7 @@
349
325
  </v-list-item>
350
326
  <v-list-item
351
327
  @click="emit('delete')"
352
- class="text-red"
328
+ class="text-error"
353
329
  :disabled="!isSelectedCardDeletable"
354
330
  v-if="canDeleteAccessCard"
355
331
  >
@@ -358,10 +334,8 @@
358
334
  </v-list-item-title>
359
335
  </v-list-item>
360
336
  </v-list>
361
- </v-menu>
362
- </v-col>
363
- </v-row>
364
- </v-toolbar>
337
+ </v-menu>
338
+ </v-card-actions>
365
339
  </v-card>
366
340
  </v-dialog>
367
341
  </template>
@@ -85,7 +85,7 @@
85
85
  <svg class="chevron" viewBox="0 0 10 6" fill="none">
86
86
  <path
87
87
  d="M1 1l4 4 4-4"
88
- stroke="#6B7280"
88
+ stroke="currentColor"
89
89
  stroke-width="1.4"
90
90
  stroke-linecap="round"
91
91
  />
@@ -107,7 +107,7 @@
107
107
  <svg class="chevron" viewBox="0 0 10 6" fill="none">
108
108
  <path
109
109
  d="M1 1l4 4 4-4"
110
- stroke="#6B7280"
110
+ stroke="currentColor"
111
111
  stroke-width="1.4"
112
112
  stroke-linecap="round"
113
113
  />
@@ -132,7 +132,7 @@
132
132
  <svg class="chevron" viewBox="0 0 10 6" fill="none">
133
133
  <path
134
134
  d="M1 1l4 4 4-4"
135
- stroke="#6B7280"
135
+ stroke="currentColor"
136
136
  stroke-width="1.4"
137
137
  stroke-linecap="round"
138
138
  />
@@ -150,7 +150,7 @@
150
150
  <svg class="chevron" viewBox="0 0 10 6" fill="none">
151
151
  <path
152
152
  d="M1 1l4 4 4-4"
153
- stroke="#6B7280"
153
+ stroke="currentColor"
154
154
  stroke-width="1.4"
155
155
  stroke-linecap="round"
156
156
  />
@@ -175,7 +175,7 @@
175
175
  <svg class="chevron" viewBox="0 0 10 6" fill="none">
176
176
  <path
177
177
  d="M1 1l4 4 4-4"
178
- stroke="#6B7280"
178
+ stroke="currentColor"
179
179
  stroke-width="1.4"
180
180
  stroke-linecap="round"
181
181
  />
@@ -200,13 +200,13 @@
200
200
  width="14"
201
201
  height="12"
202
202
  rx="2"
203
- stroke="#9CA3AF"
203
+ stroke="currentColor"
204
204
  stroke-width="1.3"
205
205
  />
206
- <path d="M1 7h14" stroke="#9CA3AF" stroke-width="1.3" />
206
+ <path d="M1 7h14" stroke="currentColor" stroke-width="1.3" />
207
207
  <path
208
208
  d="M5 1v3M11 1v3"
209
- stroke="#9CA3AF"
209
+ stroke="currentColor"
210
210
  stroke-width="1.3"
211
211
  stroke-linecap="round"
212
212
  />
@@ -224,13 +224,13 @@
224
224
  width="14"
225
225
  height="12"
226
226
  rx="2"
227
- stroke="#9CA3AF"
227
+ stroke="currentColor"
228
228
  stroke-width="1.3"
229
229
  />
230
- <path d="M1 7h14" stroke="#9CA3AF" stroke-width="1.3" />
230
+ <path d="M1 7h14" stroke="currentColor" stroke-width="1.3" />
231
231
  <path
232
232
  d="M5 1v3M11 1v3"
233
- stroke="#9CA3AF"
233
+ stroke="currentColor"
234
234
  stroke-width="1.3"
235
235
  stroke-linecap="round"
236
236
  />
@@ -581,12 +581,12 @@ watch(
581
581
  }
582
582
 
583
583
  .form-wrap {
584
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
584
+ font-family: var(--font-sans);
585
585
  font-size: 14px;
586
- color: #111827;
587
- background: #fff;
588
- border: 1px solid #e5e7eb;
589
- border-radius: 10px;
586
+ color: var(--text);
587
+ background: var(--card);
588
+ border: 1px solid var(--border);
589
+ border-radius: var(--r-card);
590
590
  padding: 24px 28px 32px;
591
591
  }
592
592
 
@@ -596,17 +596,17 @@ watch(
596
596
  align-items: flex-start;
597
597
  justify-content: space-between;
598
598
  padding-bottom: 18px;
599
- border-bottom: 1px solid #e5e7eb;
599
+ border-bottom: 1px solid var(--border);
600
600
  margin-bottom: 22px;
601
601
  }
602
602
  .header h2 {
603
603
  font-size: 20px;
604
604
  font-weight: 700;
605
- color: #111827;
605
+ color: var(--text);
606
606
  }
607
607
  .header p {
608
608
  font-size: 13px;
609
- color: #2563eb;
609
+ color: var(--accent-text);
610
610
  margin-top: 2px;
611
611
  }
612
612
  .actions {
@@ -618,7 +618,7 @@ watch(
618
618
  .btn-cancel,
619
619
  .btn-submit {
620
620
  border: none;
621
- border-radius: 20px;
621
+ border-radius: var(--r-pill);
622
622
  padding: 9px 22px;
623
623
  font-size: 13px;
624
624
  font-weight: 600;
@@ -626,15 +626,18 @@ watch(
626
626
  transition: opacity 0.15s;
627
627
  }
628
628
  .btn-cancel {
629
- background: #e5e7eb;
630
- color: #374151;
629
+ background: var(--border);
630
+ color: var(--text2);
631
631
  }
632
632
  .btn-cancel:hover {
633
633
  opacity: 0.85;
634
634
  }
635
+ /* `.btn-submit` was an exact copy of `.btn-cancel` - same grey fill, same ink -
636
+ so the form's primary action was indistinguishable from the one that throws
637
+ the edit away. It takes the design's accent fill and its white-safe pair. */
635
638
  .btn-submit {
636
- background: #e5e7eb;
637
- color: #374151;
639
+ background: var(--accent-strong);
640
+ color: var(--on-accent-strong);
638
641
  }
639
642
  .btn-submit:hover {
640
643
  opacity: 0.85;
@@ -647,7 +650,7 @@ watch(
647
650
  .section h3 {
648
651
  font-size: 15px;
649
652
  font-weight: 700;
650
- color: #111827;
653
+ color: var(--text);
651
654
  margin-bottom: 14px;
652
655
  }
653
656
 
@@ -669,29 +672,29 @@ watch(
669
672
  }
670
673
  .field label {
671
674
  font-size: 12px;
672
- color: #6b7280;
675
+ color: var(--text2);
673
676
  }
674
677
 
675
678
  .field input[type='text'],
676
679
  .field input[type='email'] {
677
680
  height: 38px;
678
- border: 1px solid #e5e7eb;
679
- border-radius: 8px;
681
+ border: 1px solid var(--border);
682
+ border-radius: var(--r-inner);
680
683
  padding: 0 12px;
681
684
  font-size: 13px;
682
- color: #111827;
683
- background: #fff;
685
+ color: var(--text);
686
+ background: var(--card);
684
687
  outline: none;
685
688
  }
686
689
  .field input:focus {
687
- border-color: #9ca3af;
690
+ border-color: var(--muted);
688
691
  }
689
692
  .field input::placeholder {
690
- color: #9ca3af;
693
+ color: var(--muted);
691
694
  }
692
695
  .field input:disabled {
693
- background: #f9fafb;
694
- color: #6b7280;
696
+ background: var(--bg);
697
+ color: var(--text2);
695
698
  }
696
699
 
697
700
  /* ===== SELECT ===== */
@@ -701,18 +704,18 @@ watch(
701
704
  .select-wrap select {
702
705
  width: 100%;
703
706
  height: 38px;
704
- border: 1px solid #e5e7eb;
705
- border-radius: 8px;
707
+ border: 1px solid var(--border);
708
+ border-radius: var(--r-inner);
706
709
  padding: 0 30px 0 12px;
707
710
  font-size: 13px;
708
- color: #111827;
709
- background: #fff;
711
+ color: var(--text);
712
+ background: var(--card);
710
713
  appearance: none;
711
714
  cursor: pointer;
712
715
  outline: none;
713
716
  }
714
717
  .select-wrap select:focus {
715
- border-color: #9ca3af;
718
+ border-color: var(--muted);
716
719
  }
717
720
  .select-wrap .chevron {
718
721
  position: absolute;
@@ -733,12 +736,12 @@ watch(
733
736
  .date-input input {
734
737
  width: 100%;
735
738
  height: 38px;
736
- border: 1px solid #e5e7eb;
737
- border-radius: 8px;
739
+ border: 1px solid var(--border);
740
+ border-radius: var(--r-inner);
738
741
  padding: 0 34px 0 12px;
739
742
  font-size: 13px;
740
- color: #6b7280;
741
- background: #f9fafb;
743
+ color: var(--text2);
744
+ background: var(--bg);
742
745
  outline: none;
743
746
  }
744
747
  .date-input svg {
@@ -750,7 +753,7 @@ watch(
750
753
  /* ===== HINT ===== */
751
754
  .hint {
752
755
  font-size: 11px;
753
- color: #9ca3af;
756
+ color: var(--text2);
754
757
  line-height: 1.4;
755
758
  }
756
759
  .hint-below {
@@ -766,13 +769,13 @@ watch(
766
769
  }
767
770
  .app-list li {
768
771
  font-size: 13px;
769
- color: #374151;
772
+ color: var(--text2);
770
773
  }
771
774
 
772
775
  /* ===== SITE TABLE ===== */
773
776
  .site-table {
774
- border: 1px solid #e5e7eb;
775
- border-radius: 8px;
777
+ border: 1px solid var(--border);
778
+ border-radius: var(--r-inner);
776
779
  overflow: hidden;
777
780
  }
778
781
  .site-table table {
@@ -784,12 +787,12 @@ watch(
784
787
  padding: 10px 16px;
785
788
  text-align: left;
786
789
  font-weight: 600;
787
- color: #374151;
788
- background: #f9fafb;
789
- border-bottom: 1px solid #e5e7eb;
790
+ color: var(--text2);
791
+ background: var(--bg);
792
+ border-bottom: 1px solid var(--border);
790
793
  }
791
794
  .site-table tbody tr {
792
- border-bottom: 1px solid #f3f4f6;
795
+ border-bottom: 1px solid var(--border);
793
796
  }
794
797
  .site-table tbody tr:last-child {
795
798
  border-bottom: none;
@@ -799,14 +802,14 @@ watch(
799
802
  }
800
803
  .site-table .td-name {
801
804
  font-weight: 500;
802
- color: #111827;
805
+ color: var(--text);
803
806
  }
804
807
  .site-table .td-muted {
805
- color: #6b7280;
808
+ color: var(--text2);
806
809
  }
807
810
  .site-table .empty {
808
811
  text-align: center;
809
- color: #9ca3af;
812
+ color: var(--text2);
810
813
  padding: 24px 0 !important;
811
814
  }
812
815
  .phone-input {
@@ -816,7 +819,7 @@ watch(
816
819
 
817
820
  .phone-input .prefix {
818
821
  width: 80px;
819
- background: #f3f4f6;
822
+ background: var(--bg);
820
823
  }
821
824
 
822
825
  .phone-input .number {
@@ -826,6 +829,28 @@ watch(
826
829
  .error {
827
830
  margin-top: 4px;
828
831
  font-size: 12px;
829
- color: #ef4444;
832
+ color: var(--err);
833
+ }
834
+
835
+ /*
836
+ * MEASURED at 360: the form overflowed the viewport by 147px in both themes.
837
+ * Its two-column grid, its 28px side padding and its header row are all fixed,
838
+ * and the component carries no media query at all - so on a phone the right
839
+ * column, the Submit button and half the site table sat off screen. One
840
+ * breakpoint, matching the shell's own mobile padding.
841
+ */
842
+ @media (max-width: 600px) {
843
+ .form-wrap {
844
+ padding: 16px 14px 22px;
845
+ }
846
+
847
+ .row {
848
+ grid-template-columns: 1fr;
849
+ }
850
+
851
+ .header {
852
+ flex-direction: column;
853
+ gap: 12px;
854
+ }
830
855
  }
831
856
  </style>
@@ -60,8 +60,8 @@
60
60
  </v-alert>
61
61
  <template v-else>
62
62
  <!-- Generating / loading state -->
63
- <div v-if="generating || cardsLoading" class="d-flex align-center ga-2 mt-3 text-caption text-grey-darken-1">
64
- <v-progress-circular size="14" width="2" indeterminate color="grey" />
63
+ <div v-if="generating || cardsLoading" class="d-flex align-center ga-2 mt-3 text-caption text-fontgray">
64
+ <v-progress-circular size="14" width="2" indeterminate />
65
65
  <span>{{ generating ? 'Generating QR passes...' : 'Checking availability...' }}</span>
66
66
  </div>
67
67
  <!-- 0 available after all loading -->
@@ -79,7 +79,7 @@
79
79
  <template v-else>
80
80
  <div class="d-flex align-center justify-space-between mt-3">
81
81
  <InputLabel title="Quantity" />
82
- <span v-if="availableCount !== null" class="text-caption text-grey">
82
+ <span v-if="availableCount !== null" class="text-caption text-fontgray">
83
83
  {{ availableCount }} available
84
84
  </span>
85
85
  </div>
@@ -133,6 +133,7 @@
133
133
  :color="isBarcodeScanningActive ? 'success' : 'primary'"
134
134
  variant="outlined"
135
135
  block
136
+ class="text-none"
136
137
  prepend-icon="mdi-barcode-scan"
137
138
  @click="toggleBarcodeScanning"
138
139
  >
@@ -145,6 +146,7 @@
145
146
  variant="outlined"
146
147
  color="primary"
147
148
  block
149
+ class="text-none"
148
150
  prepend-icon="mdi-camera"
149
151
  @click="openCameraDialog"
150
152
  >
@@ -224,11 +226,11 @@
224
226
  @after-leave="stopCamera"
225
227
  >
226
228
  <v-container class="d-flex justify-center" style="max-height: 90vh">
227
- <v-card elevation="2" class="d-flex flex-column align-center pa-2 w-100">
229
+ <v-card class="screen-modal d-flex flex-column align-center pa-2 w-100">
228
230
  <v-toolbar color="transparent">
229
- <v-card-title class="text-h5">Scan Card</v-card-title>
231
+ <v-card-title>Scan Card</v-card-title>
230
232
  <v-spacer />
231
- <v-btn icon="mdi-close" color="grey-darken-1" @click="closeCameraDialog" />
233
+ <v-btn icon="mdi-close" class="screen-modal__close" @click="closeCameraDialog" />
232
234
  </v-toolbar>
233
235
 
234
236
  <div class="position-relative w-100" style="aspect-ratio: 4/3; background: #000">
@@ -1,12 +1,12 @@
1
1
  <template>
2
2
  <v-dialog v-model="dialogModel" max-width="430" persistent>
3
- <v-card class="hid-reader-form" rounded="lg">
3
+ <v-card class="hid-reader-form screen-modal">
4
4
  <v-card-title class="form-title">
5
5
  {{ mode === "edit" ? "Edit Reader" : "Add Reader" }}
6
6
  </v-card-title>
7
7
 
8
- <v-card-text class="form-body">
9
- <div class="field-label">HID Reader Name <span>*</span></div>
8
+ <v-card-text class="form-body screen-modal__body">
9
+ <InputLabel title="HID Reader Name" required class="mb-1" />
10
10
  <v-text-field
11
11
  v-model="draft.name"
12
12
  aria-label="HID Reader Name"
@@ -17,7 +17,7 @@
17
17
  class="mb-3"
18
18
  />
19
19
 
20
- <div class="field-label">Base URL / IP address <span>*</span></div>
20
+ <InputLabel title="Base URL / IP address" required class="mb-1" />
21
21
  <v-text-field
22
22
  v-model="draft.baseUrl"
23
23
  aria-label="Base URL / IP address"
@@ -28,7 +28,7 @@
28
28
  class="mb-3"
29
29
  />
30
30
 
31
- <div class="field-label">Location <span>*</span></div>
31
+ <InputLabel title="Location" required class="mb-1" />
32
32
  <v-text-field
33
33
  v-model="draft.location"
34
34
  aria-label="Location"
@@ -39,13 +39,13 @@
39
39
  class="mb-3"
40
40
  />
41
41
 
42
- <div class="field-label">Monitor Path <span>*</span></div>
42
+ <InputLabel title="Monitor Path" required class="mb-1" />
43
43
  <v-btn-toggle v-model="monitorEnabled" mandatory divided class="monitor-toggle mb-3">
44
44
  <v-btn :value="true" class="text-none">Enable</v-btn>
45
45
  <v-btn :value="false" class="text-none">Disable</v-btn>
46
46
  </v-btn-toggle>
47
47
 
48
- <div class="field-label">Username <span>*</span></div>
48
+ <InputLabel title="Username" required class="mb-1" />
49
49
  <v-text-field
50
50
  v-model="draft.username"
51
51
  aria-label="Username"
@@ -56,7 +56,7 @@
56
56
  class="mb-3"
57
57
  />
58
58
 
59
- <div class="field-label">Confirm Password <span>*</span></div>
59
+ <InputLabel title="Confirm Password" required class="mb-1" />
60
60
  <v-text-field
61
61
  v-model="draft.password"
62
62
  :type="showPassword ? 'text' : 'password'"
@@ -86,7 +86,7 @@
86
86
  {{ discoveryError }}
87
87
  </v-alert>
88
88
 
89
- <div class="field-label mt-3">Device ID <span>*</span></div>
89
+ <InputLabel title="Device ID" required class="mt-3 mb-1" />
90
90
  <v-text-field
91
91
  v-model="draft.deviceId"
92
92
  aria-label="Device ID"
@@ -98,7 +98,7 @@
98
98
  readonly
99
99
  />
100
100
 
101
- <div class="field-label">HID Portal <span>*</span></div>
101
+ <InputLabel title="HID Portal" required class="mb-1" />
102
102
  <v-select
103
103
  v-model="draft.portalId"
104
104
  :items="portals"
@@ -113,19 +113,17 @@
113
113
  />
114
114
  </v-card-text>
115
115
 
116
- <v-card-actions class="form-actions pa-0">
116
+ <v-card-actions class="screen-modal__footer">
117
117
  <v-btn
118
- class="text-none action-cancel"
118
+ class="text-none screen-btn-ghost"
119
119
  variant="flat"
120
- height="48"
121
120
  @click="close"
122
121
  >
123
122
  Cancel
124
123
  </v-btn>
125
124
  <v-btn
126
- class="text-none action-submit"
125
+ class="text-none screen-btn-primary"
127
126
  variant="flat"
128
- height="48"
129
127
  :loading="loading"
130
128
  :disabled="mode === 'add' && (!draft.deviceId || !draft.portalId)"
131
129
  @click="submit"
@@ -290,28 +288,18 @@ function submit() {
290
288
  overflow: hidden;
291
289
  }
292
290
 
291
+ /* Type comes from `.screen-modal .v-card-title`; only the header strip's own
292
+ padding and rule stay here. `#ececec` was a fixed near-white line, i.e.
293
+ invisible on a light card and a bright scratch across a dark one. */
293
294
  .form-title {
294
- font-size: 14px;
295
- font-weight: 700;
296
295
  padding: 12px 16px;
297
- border-bottom: 1px solid #ececec;
296
+ border-bottom: 1px solid var(--border);
298
297
  }
299
298
 
300
299
  .form-body {
301
300
  padding: 18px 16px 20px;
302
301
  }
303
302
 
304
- .field-label {
305
- color: #4f5a66;
306
- font-size: 12px;
307
- font-weight: 600;
308
- margin-bottom: 6px;
309
- }
310
-
311
- .field-label span {
312
- color: #e53935;
313
- }
314
-
315
303
  .monitor-toggle {
316
304
  display: grid;
317
305
  grid-template-columns: 1fr 1fr;
@@ -322,32 +310,11 @@ function submit() {
322
310
  height: 36px;
323
311
  }
324
312
 
325
- .form-actions {
326
- display: grid;
327
- grid-template-columns: 1fr 1fr;
328
- }
329
-
330
- .action-cancel {
331
- background: #ffffff;
332
- color: #111827;
333
- border-radius: 0;
334
- }
335
-
336
- .action-submit {
337
- background: #062d42;
338
- color: #ffffff;
339
- border-radius: 0;
340
- }
341
-
342
313
  @media (max-width: 600px) {
343
314
  .form-body {
344
315
  padding: 14px 12px 16px;
345
316
  }
346
317
 
347
- .form-actions {
348
- grid-template-columns: 1fr;
349
- }
350
-
351
318
  :global(.v-dialog > .v-overlay__content) {
352
319
  max-width: calc(100vw - 24px) !important;
353
320
  margin: 12px !important;
@@ -2,7 +2,7 @@
2
2
  <v-row no-gutters class="px-5 pt-4">
3
3
  <!-- Site Information -->
4
4
  <v-col cols="12" class="border-b pb-3 mb-5">
5
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
5
+ <p class="mb-2 screen-card-title">
6
6
  Site Information
7
7
  </p>
8
8
  <v-row no-gutters class="mt-5">
@@ -36,7 +36,7 @@
36
36
 
37
37
  <!-- Place of Incident -->
38
38
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
39
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
39
+ <p class="mb-2 screen-card-title">
40
40
  Place of Incident
41
41
  </p>
42
42
  <p class="my-1 text-h6 text-capitalize">
@@ -46,7 +46,7 @@
46
46
 
47
47
  <!-- Incident Type / Time -->
48
48
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
49
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
49
+ <p class="mb-2 screen-card-title">
50
50
  Incident Type / Time
51
51
  </p>
52
52
  <v-row no-gutters class="mt-5">
@@ -106,7 +106,7 @@
106
106
 
107
107
  <!-- Response/Submission From (1st Contact) -->
108
108
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
109
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
109
+ <p class="mb-2 screen-card-title">
110
110
  Response/Submission From (1st Contact)
111
111
  </p>
112
112
  <v-row no-gutters class="mt-5">
@@ -130,7 +130,7 @@
130
130
 
131
131
  <!-- Name of Informant/Complainant Information -->
132
132
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
133
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
133
+ <p class="mb-2 screen-card-title">
134
134
  Name of Informant/Complainant Information
135
135
  </p>
136
136
  <v-row no-gutters class="d-flex align-center mt-5">
@@ -146,7 +146,7 @@
146
146
  <v-icon
147
147
  v-if="incidentInformation?.complaintInfo?.nric"
148
148
  size="small"
149
- color="blue"
149
+ color="primary"
150
150
  class="cursor-pointer"
151
151
  @click="toggleNRICComplainant"
152
152
  >
@@ -172,7 +172,7 @@
172
172
 
173
173
  <!-- Name of Recipient of Complaint (1st Contact) -->
174
174
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
175
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
175
+ <p class="mb-2 screen-card-title">
176
176
  Name of Recipient of Complaint (1st Contact)
177
177
  </p>
178
178
  <v-row no-gutters class="d-flex align-center mt-5">
@@ -188,7 +188,7 @@
188
188
  <v-icon
189
189
  v-if="incidentInformation?.recipientOfComplaint?.nric"
190
190
  size="small"
191
- color="blue"
191
+ color="primary"
192
192
  class="cursor-pointer"
193
193
  @click="toggleNRICRecipient"
194
194
  >
@@ -214,7 +214,7 @@
214
214
 
215
215
  <!-- Complaint Received through -->
216
216
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
217
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
217
+ <p class="mb-2 screen-card-title">
218
218
  Complaint Received through
219
219
  </p>
220
220
  <v-col cols="12">
@@ -238,7 +238,7 @@
238
238
 
239
239
  <!-- Brief Description -->
240
240
  <v-col cols="12" class="mb-10">
241
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
241
+ <p class="mb-2 screen-card-title">
242
242
  Brief Description
243
243
  </p>
244
244
  <p class="mt-5 text-h6 text-capitalize">
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@7365admin1/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "3.2.2-staging.158",
5
+ "version": "3.2.2-staging.159",
6
6
  "author": "7365admin1",
7
7
  "main": "./nuxt.config.ts",
8
8
  "//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",