@7365admin1/layer-common 3.2.2-staging.114 → 3.2.2-staging.118

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.
@@ -312,6 +312,25 @@
312
312
  font-size: 19px;
313
313
  }
314
314
 
315
+ /**
316
+ * A DIALOG'S OWN HEADER/FOOTER BAR - OPT-IN, DELIBERATELY.
317
+ *
318
+ * Some dialogs draw their title row and their Cancel/Submit row as a
319
+ * `v-toolbar`. Vuetify paints that from its own `surface`, which in dark mode
320
+ * is a visible grey slab sitting on the card. The obvious fix - one blanket
321
+ * `.v-overlay__content .v-toolbar` rule - was measured and REJECTED: sixty-odd
322
+ * dialog components draw such a bar, and several set `color="black"` or
323
+ * `color="grey-darken-3"` ON PURPOSE. A blanket rule would flatten those too,
324
+ * unrendered and unverified.
325
+ *
326
+ * So this is a class a converted dialog opts into. Background and text only -
327
+ * it moves no control and changes no button.
328
+ */
329
+ .screen-dialog-bar.v-toolbar {
330
+ background: var(--card) !important;
331
+ color: var(--text) !important;
332
+ }
333
+
315
334
  /**
316
335
  * The design's two buttons, for the dialogs and toolbars that draw their own.
317
336
  *
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <v-card width="100%" :loading="getUnitPeoplePending || loading.ownerProcessing" :disabled="loading.ownerProcessing">
3
- <v-toolbar>
3
+ <v-toolbar class="screen-dialog-bar">
4
4
  <v-row no-gutters class="fill-height px-6" align="center">
5
5
  <span class="font-weight-bold text-h5"> Unit Info ( {{ buildingUnit.name }} ) </span>
6
6
  </v-row>
7
7
  </v-toolbar>
8
- <v-toolbar density="compact">
8
+ <v-toolbar class="screen-dialog-bar" density="compact">
9
9
  <v-tabs v-model="tab" class="mt-0" active-class="bg-success">
10
10
  <v-tab value="general">General</v-tab>
11
11
  <v-tab value="residents">Residents/Tenants</v-tab>
@@ -253,7 +253,7 @@
253
253
  </v-row>
254
254
  </v-col>
255
255
 
256
- <v-toolbar class="pa-0" density="compact">
256
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact">
257
257
  <v-row no-gutters>
258
258
  <v-col :cols="canUpdateUnit || canDeleteUnit ? 6 : 12" class="pa-0">
259
259
  <v-btn block variant="text" class="text-none" size="large" @click="emit('cancel')" height="48">
@@ -1,14 +1,17 @@
1
1
  <template>
2
- <v-card width="100%" :loading="processing">
2
+ <v-card width="100%" class="screen-modal" :loading="processing">
3
3
  <v-toolbar>
4
4
  <v-row no-gutters class="fill-height px-6" align="center">
5
- <span class="font-weight-bold text-subtitle-1 text-capitalize">
5
+ <span class="screen-card-title text-capitalize">
6
6
  Preview Announcement
7
7
  </span>
8
8
  </v-row>
9
9
  </v-toolbar>
10
10
 
11
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0 my-3">
11
+ <v-card-text
12
+ style="max-height: 100vh; overflow-y: auto"
13
+ class="screen-modal__body pb-0 my-3"
14
+ >
12
15
  <v-row no-gutters>
13
16
  <template v-for="(label, key) in formattedFields" :key="key">
14
17
  <v-col cols="12" class="mb-5">
@@ -39,7 +42,7 @@
39
42
  <v-col class="font-weight-bold">Attachments:</v-col>
40
43
  <v-col cols="9" class="px-10">
41
44
  <template v-if="videosArray.length > 0">
42
- <div class="text-caption text-medium-emphasis mb-1">
45
+ <div class="text-caption screen-hint mb-1">
43
46
  Videos ({{ videosArray.length }})
44
47
  </div>
45
48
  <v-list density="compact" class="pa-0 rounded-lg border mb-3">
@@ -71,7 +74,7 @@
71
74
 
72
75
  <template v-if="photosArray.length > 0">
73
76
  <div
74
- class="text-caption text-medium-emphasis mb-1"
77
+ class="text-caption screen-hint mb-1"
75
78
  :class="{ 'mt-3': videosArray.length > 0 }"
76
79
  >
77
80
  Photos ({{ photosArray.length }})
@@ -110,7 +113,7 @@
110
113
 
111
114
  <template v-if="filesArray.length > 0">
112
115
  <div
113
- class="text-caption text-medium-emphasis mb-1"
116
+ class="text-caption screen-hint mb-1"
114
117
  :class="{
115
118
  'mt-3': videosArray.length > 0 || photosArray.length > 0,
116
119
  }"
@@ -1,8 +1,17 @@
1
1
  <template>
2
- <v-chip
3
- size="small"
4
- :color="value ? 'green' : 'red'"
5
- :text="value ? 'Yes' : 'No'"
2
+ <!--
3
+ The design's status pill rather than a raw v-chip. Vuetify's `green` and
4
+ `red` are fixed hues that are in no token file: the red one printed
5
+ `rgb(244,67,54)` and measured 3.4:1 against the surface behind it, below AA
6
+ on the word people actually read, and the green one measured 2.78:1.
7
+ `approved` and `rejected` are the shared tone words, so this chip now takes
8
+ `--ok` / `--err` and their paired `--ok-bg` / `--err-bg` - the handoff's own
9
+ values - and carries its own background instead of borrowing whatever it
10
+ happens to sit on.
11
+ -->
12
+ <StatusChip
13
+ :status="value ? 'approved' : 'rejected'"
14
+ :label="value ? 'Yes' : 'No'"
6
15
  />
7
16
  </template>
8
17
 
@@ -1,57 +1,45 @@
1
1
  <template>
2
2
  <v-row no-gutters>
3
3
  <v-col cols="12">
4
- <v-card width="100%" variant="outlined" border="thin" rounded="lg">
5
- <v-toolbar density="compact" color="grey-lighten-4 pl-2 pr-4">
6
- <template #prepend>
7
- <v-btn fab icon density="comfortable" @click="getCameraRefresh()">
8
- <v-icon>mdi-refresh</v-icon>
9
- </v-btn>
10
- </template>
11
-
12
- <template #append>
13
- <v-btn
14
- v-if="!prop.readOnly"
15
- variant="flat"
16
- color="primary"
17
- class="text-none"
18
- @click="dialogAdd = true"
19
- >
4
+ <!-- Two `grey-lighten-4` bars - one above the table, one below - are one
5
+ CardToolbar on the card's own surface. The literal grey stayed white
6
+ on the dark theme's card; measured as four 48px white slabs. -->
7
+ <AppCard class="table-card">
8
+ <CardToolbar :count="pageRange">
9
+ <template #left>
10
+ <AppButton
11
+ variant="icon"
12
+ icon="mdi-refresh"
13
+ aria-label="Refresh"
14
+ @click="getCameraRefresh()"
15
+ />
16
+ <AppButton v-if="!prop.readOnly" @click="dialogAdd = true">
20
17
  Add
21
- </v-btn>
18
+ </AppButton>
22
19
  </template>
23
- </v-toolbar>
24
-
25
- <v-card-text class="pa-0 bg-red">
26
- <v-data-table
27
- :headers="computedHeaders"
28
- :items="items"
29
- fixed-header
30
- hide-default-footer
31
- @click:row="handleRowClick"
32
- style="max-height: 300px"
33
- >
34
- <template #item.host="{ value }">
35
- {{ maskHostUrl(value) }}
36
- </template>
37
- </v-data-table>
38
- </v-card-text>
39
20
 
40
- <v-toolbar density="compact" color="grey-lighten-4">
41
- <template #append>
42
- <v-row no-gutters justify="end" align="center">
43
- <span class="mr-2 text-caption text-font gray">
44
- {{ pageRange }}
45
- </span>
46
- <local-pagination
47
- v-model="page"
48
- :length="pages"
49
- @update:value="$emit('update:value', $event)"
50
- />
51
- </v-row>
21
+ <template #right>
22
+ <local-pagination
23
+ v-model="page"
24
+ :length="pages"
25
+ @update:value="$emit('update:value', $event)"
26
+ />
52
27
  </template>
53
- </v-toolbar>
54
- </v-card>
28
+ </CardToolbar>
29
+
30
+ <v-data-table
31
+ :headers="computedHeaders"
32
+ :items="items"
33
+ fixed-header
34
+ hide-default-footer
35
+ @click:row="handleRowClick"
36
+ style="max-height: 300px"
37
+ >
38
+ <template #item.host="{ value }">
39
+ {{ maskHostUrl(value) }}
40
+ </template>
41
+ </v-data-table>
42
+ </AppCard>
55
43
  </v-col>
56
44
 
57
45
  <!-- dialog -->
@@ -1,22 +1,27 @@
1
1
  <template>
2
2
  <v-row no-gutters class="pa-3">
3
3
  <v-col cols="12">
4
- <v-card width="100%" variant="outlined" border="thin" rounded="lg" max-width="700" max-height="500"
5
- style="overflow-y: auto;">
6
- <v-toolbar density="compact" color="grey-lighten-4 pl-2 pr-4">
7
- <v-row v-if="!hideTitle" no-gutters class="px-3 font-weight-bold">
8
- Delivery Companies
9
- </v-row>
4
+ <AppCard class="delivery-company__card">
5
+ <!--
6
+ The one toolbar the design puts on top of the card. It was a
7
+ hardcoded grey-lighten-4 bar, which stays light in dark mode
8
+ and painted as a white slab there.
9
+ -->
10
+ <CardToolbar>
11
+ <template #left>
12
+ <span v-if="!hideTitle" class="screen-card-title">
13
+ Delivery Companies
14
+ </span>
15
+ </template>
10
16
 
11
- <template #append>
12
- <v-btn v-if="!props.readOnly" variant="flat" color="primary" class="text-none"
13
- @click="handleAdd">
17
+ <template #right>
18
+ <AppButton v-if="!props.readOnly" @click="handleAdd">
14
19
  Add
15
- </v-btn>
20
+ </AppButton>
16
21
  </template>
17
- </v-toolbar>
22
+ </CardToolbar>
18
23
 
19
- <v-card-text class="pa-0" style="min-height: 100px;">
24
+ <div class="pa-0" style="min-height: 100px;">
20
25
  <template v-if="companies.length > 0">
21
26
  <draggable :list="companies" item-key="index" class="drag-area"
22
27
  :disabled="editingIndex !== null">
@@ -60,11 +65,11 @@
60
65
  </draggable>
61
66
  </template>
62
67
 
63
- <div v-else class="text-center py-5">
68
+ <div v-else class="screen-empty text-center py-5">
64
69
  No delivery companies added yet.
65
70
  </div>
66
- </v-card-text>
67
- </v-card>
71
+ </div>
72
+ </AppCard>
68
73
  </v-col>
69
74
 
70
75
  <v-dialog v-model="dialog.add" persistent width="450">
@@ -82,12 +87,13 @@
82
87
  </v-card-text>
83
88
 
84
89
  <v-toolbar>
85
- <v-row no-gutters justify="end" align="center" class="px-5">
86
- <v-btn variant="text" text="Cancel" @click="dialog.add = false" />
87
- <v-btn variant="flat" color="primary" class="text-none ml-2"
88
- @click="saveEdit(companies.length)">
90
+ <v-row no-gutters justify="end" align="center" class="px-5 ga-2">
91
+ <AppButton variant="ghost" @click="dialog.add = false">
92
+ Cancel
93
+ </AppButton>
94
+ <AppButton @click="saveEdit(companies.length)">
89
95
  Add
90
- </v-btn>
96
+ </AppButton>
91
97
  </v-row>
92
98
  </v-toolbar>
93
99
  </v-card>
@@ -237,4 +243,12 @@ watch(initialCompanies, (val) => {
237
243
  .drag-handle {
238
244
  cursor: grab;
239
245
  }
246
+
247
+ /* The size cap the v-card carried as max-width/max-height attributes, kept
248
+ verbatim so the panel does not grow to the full page width. */
249
+ .delivery-company__card {
250
+ max-width: 700px;
251
+ max-height: 500px;
252
+ overflow-y: auto;
253
+ }
240
254
  </style>
@@ -204,7 +204,7 @@
204
204
  <!-- Create Folder Dialog -->
205
205
  <v-dialog v-model="createFolderDialog" width="450" persistent>
206
206
  <v-card width="100%">
207
- <v-toolbar class="pa-0" density="compact">
207
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact">
208
208
  <v-row no-gutters class="w-100">
209
209
  <v-col cols="12" class="pa-4">
210
210
  <span class="font-weight-medium text-h6">Create Folder</span>
@@ -234,7 +234,7 @@
234
234
  </v-form>
235
235
  </v-card-text>
236
236
 
237
- <v-toolbar class="pa-0" density="compact">
237
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact">
238
238
  <v-row no-gutters class="w-100">
239
239
  <v-col cols="6" class="pa-0">
240
240
  <v-btn
@@ -271,7 +271,7 @@
271
271
  <!-- Edit Folder Dialog -->
272
272
  <v-dialog v-model="editFolderDialog" width="450" persistent>
273
273
  <v-card width="100%" class="folder-dialog-card">
274
- <v-toolbar class="pa-0 folder-dialog-toolbar" density="compact">
274
+ <v-toolbar class="pa-0 folder-dialog-toolbar screen-dialog-bar" density="compact">
275
275
  <v-row no-gutters class="w-100">
276
276
  <v-col cols="12" class="pa-4">
277
277
  <span class="font-weight-medium text-h6">Edit Folder</span>
@@ -306,7 +306,7 @@
306
306
  </v-form>
307
307
  </v-card-text>
308
308
 
309
- <v-toolbar class="pa-0" density="compact">
309
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact">
310
310
  <v-row no-gutters class="w-100">
311
311
  <v-col cols="6" class="pa-0">
312
312
  <v-btn
@@ -343,7 +343,7 @@
343
343
  <!-- Delete Folder Dialog -->
344
344
  <v-dialog v-model="deleteFolderDialog" width="450" persistent>
345
345
  <v-card width="100%" class="folder-dialog-card">
346
- <v-toolbar density="compact" class="pl-4 folder-dialog-toolbar">
346
+ <v-toolbar density="compact" class="pl-4 folder-dialog-toolbar screen-dialog-bar">
347
347
  <span class="font-weight-medium text-h6">Delete Folder</span>
348
348
  </v-toolbar>
349
349
 
@@ -357,7 +357,7 @@
357
357
  </p>
358
358
  </v-card-text>
359
359
 
360
- <v-toolbar density="compact" class="pa-0">
360
+ <v-toolbar density="compact" class="pa-0 screen-dialog-bar">
361
361
  <v-row no-gutters class="w-100">
362
362
  <v-col cols="6" class="pa-0">
363
363
  <v-btn
@@ -485,7 +485,7 @@
485
485
  </v-col>
486
486
  </v-row>
487
487
  </v-card-text>
488
- <v-toolbar class="pa-0" density="compact">
488
+ <v-toolbar class="pa-0 screen-dialog-bar" density="compact">
489
489
  <v-row no-gutters>
490
490
  <v-col cols="6" class="pa-0">
491
491
  <v-btn
@@ -549,7 +549,7 @@
549
549
  persistent
550
550
  >
551
551
  <v-card width="100%">
552
- <v-toolbar density="compact" class="pl-4">
552
+ <v-toolbar density="compact" class="pl-4 screen-dialog-bar">
553
553
  <span class="font-weight-medium text-h5">Delete Document</span>
554
554
  </v-toolbar>
555
555
  <v-card-text>
@@ -559,7 +559,7 @@
559
559
  </p>
560
560
  </v-card-text>
561
561
 
562
- <v-toolbar density="compact">
562
+ <v-toolbar class="screen-dialog-bar" density="compact">
563
563
  <v-row no-gutters>
564
564
  <v-col cols="6">
565
565
  <v-btn
@@ -1,9 +1,12 @@
1
1
  <template>
2
2
  <v-row no-gutters class="w-100">
3
- <v-card class="w-100">
4
- <v-card-text>
5
- <v-btn block color="primary-button" :height="40" text="Scan QR Code" class="text-capitalize"
6
- prepend-icon="mdi-qrcode" @click="handleScanQRPass" />
3
+ <AppCard class="w-100 pa-4">
4
+ <!-- GHOST, not primary: the handoff names "Scan QR Code" in its
5
+ ghost/secondary list, alongside Bulk Upload, Download Report and
6
+ Export. Stays a `v-btn` because `block` has no AppButton
7
+ equivalent, so the design's button is applied as a class. -->
8
+ <v-btn block :height="38" text="Scan QR Code" variant="outlined"
9
+ class="screen-btn-ghost" prepend-icon="mdi-qrcode" @click="handleScanQRPass" />
7
10
  <v-form ref="formRef" v-model="validForm" :disabled="processing" @click="errorScanPassMessage = ''">
8
11
  <v-row no-gutters class="pt-5 ga-2">
9
12
  <v-col cols="12">
@@ -81,22 +84,26 @@
81
84
 
82
85
  <v-row class="pt-3" justify="space-between">
83
86
  <v-col cols="6">
84
- <v-btn text="Add Member" :disabled="!validForm" prepend-icon="mdi-plus" color="primary-button"
85
- class="text-capitalize" @click="handleAddMember" />
87
+ <!-- The primitive rather than a class on a v-btn: these two
88
+ need nothing Vuetify owns, and AppButton is the only way
89
+ they draw at the handoff's 40px / 38px. -->
90
+ <AppButton icon="mdi-plus" :disabled="!validForm" @click="handleAddMember">
91
+ Add Member
92
+ </AppButton>
86
93
  </v-col>
87
94
  <v-col cols="6" align="end">
88
- <v-btn text="Clear Form" prepend-icon="mdi-refresh" color="primary-button" class="text-capitalize"
89
- @click.stop="handleClearForm" />
95
+ <AppButton variant="ghost" icon="mdi-refresh" @click.stop="handleClearForm">
96
+ Clear Form
97
+ </AppButton>
90
98
  </v-col>
91
99
  </v-row>
92
100
  </v-row>
93
101
  </v-form>
94
- </v-card-text>
95
- </v-card>
102
+ </AppCard>
96
103
  <visitor-pass-key-q-r-scanner :dialog="dialog.scanQRCode" v-model:scannedValue="scannedPassValue"
97
104
  @close-dialog="dialog.scanQRCode = false" />
98
105
  <v-dialog v-model="dialog.memberAutofillOptions" max-width="430">
99
- <v-card v-if="memberSelectedSearchResult" class="nric-options-card">
106
+ <v-card v-if="memberSelectedSearchResult" class="nric-options-card screen-modal">
100
107
  <v-card-actions class="justify-end pa-1">
101
108
  <v-btn icon="mdi-close" variant="text" size="small" @click="memberCloseAutofillOptions" />
102
109
  </v-card-actions>
@@ -127,10 +134,10 @@
127
134
  </v-card-text>
128
135
 
129
136
  <v-card-actions class="justify-end px-4 pb-4">
130
- <v-btn variant="text" class="text-none" size="small" @click="memberCloseAutofillOptions">
137
+ <v-btn variant="outlined" class="screen-btn-ghost" size="small" @click="memberCloseAutofillOptions">
131
138
  Cancel
132
139
  </v-btn>
133
- <v-btn color="primary-button" variant="flat" class="text-none px-5" size="small"
140
+ <v-btn variant="flat" class="screen-btn-primary px-5" size="small"
134
141
  @click="memberConfirmAutofillOptions">
135
142
  Select
136
143
  </v-btn>
@@ -626,13 +633,13 @@ function handleRemoveMember(index: number) {
626
633
  }
627
634
 
628
635
  .nric-options-title {
629
- color: #06253b;
636
+ color: var(--text);
630
637
  font-size: 1.45rem;
631
638
  line-height: 1.2;
632
639
  }
633
640
 
634
641
  .nric-options-section-title {
635
- color: #06253b;
642
+ color: var(--text);
636
643
  font-size: 1.05rem;
637
644
  line-height: 1.25;
638
645
  }
@@ -640,7 +647,7 @@ function handleRemoveMember(index: number) {
640
647
  .nric-selected-person {
641
648
  border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
642
649
  border-radius: 12px;
643
- color: #06253b;
650
+ color: var(--text);
644
651
  font-size: 0.95rem;
645
652
  min-height: 52px;
646
653
  padding: 10px 14px;
@@ -1,39 +1,46 @@
1
1
  <template>
2
- <v-row no-gutters class="border-thin pa-6 rounded-lg">
2
+ <v-row no-gutters>
3
3
  <v-col cols="12">
4
- <v-row no-gutters class="mb-4" align="center">
5
- <v-col cols="12" md="6">
6
- <v-btn
7
- variant="text"
8
- prepend-icon="mdi-chevron-left"
9
- class="text-none"
10
- @click="goBack"
11
- >
4
+ <!--
5
+ The screen had no page name at all - it opened on a bare back button.
6
+ The design opens every screen with its name; the back link keeps its
7
+ own `router.back()` and moves onto that row as the ghost action.
8
+ -->
9
+ <PageHeader title="Patrol Report">
10
+ <template #actions>
11
+ <AppButton variant="ghost" icon="mdi-chevron-left" @click="goBack">
12
12
  Patrol Report Log
13
- </v-btn>
14
- </v-col>
15
- </v-row>
16
-
17
- <v-tabs
18
- v-model="activeTab"
19
- class="mb-6"
20
- bg-color="transparent"
21
- grow
22
- >
23
- <v-tab value="patrol" class="text-none border-thin">
24
- Patrol Report
25
- </v-tab>
26
-
27
- <v-tab value="daily" class="text-none border-thin">
28
- Daily Report
29
- </v-tab>
30
-
31
- <v-tab value="monthly" class="text-none border-thin">
32
- Monthly Report
33
- </v-tab>
34
- </v-tabs>
35
-
36
- <v-window v-model="activeTab" class="pt-4">
13
+ </AppButton>
14
+ </template>
15
+ </PageHeader>
16
+ </v-col>
17
+
18
+ <v-col cols="12">
19
+ <!--
20
+ The three report tabs were a `grow` `v-tabs` strip floating above the
21
+ content with its own `border-thin` boxes. The design makes the tabs the
22
+ card's own first row, so they become the ONE `CardToolbar`'s tabs. Same
23
+ `activeTab` model, same three values, same `v-window`.
24
+ -->
25
+ <AppCard>
26
+ <CardToolbar>
27
+ <template #tabs>
28
+ <button
29
+ v-for="tab in reportTabs"
30
+ :key="tab.value"
31
+ type="button"
32
+ role="tab"
33
+ class="app-tab"
34
+ :class="{ 'app-tab--active': activeTab === tab.value }"
35
+ :aria-selected="activeTab === tab.value"
36
+ @click="activeTab = tab.value"
37
+ >
38
+ {{ tab.label }}
39
+ </button>
40
+ </template>
41
+ </CardToolbar>
42
+
43
+ <v-window v-model="activeTab" class="pt-4 px-6 pb-6">
37
44
  <v-window-item value="patrol">
38
45
  <div v-if="activeTab === 'patrol'">
39
46
  <PatrolReportTab
@@ -73,6 +80,7 @@
73
80
  </div>
74
81
  </v-window-item>
75
82
  </v-window>
83
+ </AppCard>
76
84
  </v-col>
77
85
  </v-row>
78
86
  </template>
@@ -103,6 +111,12 @@ const router = useRouter();
103
111
 
104
112
  const activeTab = ref<NFCPatrolReportTab>("patrol");
105
113
 
114
+ const reportTabs: Array<{ value: NFCPatrolReportTab; label: string }> = [
115
+ { value: "patrol", label: "Patrol Report" },
116
+ { value: "daily", label: "Daily Report" },
117
+ { value: "monthly", label: "Monthly Report" },
118
+ ];
119
+
106
120
  const { filters, options, fetchOptions } =
107
121
  useNFCPatrolReportFilters(props.site);
108
122