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

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,24 +1,21 @@
1
1
  <template>
2
- <v-card width="100%" :loading="processing">
3
- <v-toolbar>
4
- <v-row
5
- no-gutters
6
- class="fill-height px-6 d-flex justify-space-between align-center"
7
- align="center"
8
- >
9
- <span class="font-weight-bold text-subtitle-1"
10
- >{{ isEditMode ? "Edit" : "Assign" }} Pass &amp; Keys</span
11
- >
12
- <ButtonClose @click="emit('close')" />
13
- </v-row>
14
- </v-toolbar>
15
-
16
- <v-card-text>
17
- <v-row no-gutters class="ga-1">
2
+ <v-card width="100%" class="screen-modal passkey" :loading="processing">
3
+ <div class="passkey__head">
4
+ <v-card-title>{{ isEditMode ? "Edit" : "Assign" }} Pass &amp; Keys</v-card-title>
5
+ <AppButton
6
+ variant="icon"
7
+ icon="mdi-close"
8
+ aria-label="Close"
9
+ @click="emit('close')"
10
+ />
11
+ </div>
12
+
13
+ <div class="screen-modal__body passkey__body">
14
+ <!-- `.filter-field` is the design's input, and it is a descendant
15
+ selector, so both autocompletes get it from this one class. -->
16
+ <v-row no-gutters class="ga-1 filter-field">
18
17
  <v-col cols="12">
19
- <span class="text-subtitle-2 text-medium-emphasis">
20
- Name: {{ prop.visitor.name }}
21
- </span>
18
+ <span class="passkey__name">Name: {{ prop.visitor.name }}</span>
22
19
  </v-col>
23
20
 
24
21
  <!-- Pass section -->
@@ -27,15 +24,11 @@
27
24
 
28
25
  <!-- Existing pass -->
29
26
  <div v-if="existingPass" class="d-flex align-center ga-2 mb-2">
30
- <v-chip
31
- prepend-icon="mdi-card-bulleted-outline"
32
- color="blue"
33
- variant="tonal"
34
- size="small"
35
- >
27
+ <StatusChip tone="info" :dot="false">
28
+ <v-icon icon="mdi-card-bulleted-outline" size="13" />
36
29
  {{ existingPass.prefixAndName }}
37
- </v-chip>
38
- <span class="text-caption text-medium-emphasis">(current)</span>
30
+ </StatusChip>
31
+ <span class="passkey__current">(current)</span>
39
32
  </div>
40
33
 
41
34
  <!-- New pass selector -->
@@ -79,21 +72,26 @@
79
72
  v-if="existingKeys.length > 0"
80
73
  class="d-flex flex-wrap ga-1 mb-2"
81
74
  >
82
- <v-chip
75
+ <!-- The design's tag chip, keeping the remove control the product
76
+ already had: the tone and the shape are the shared ones, only
77
+ the close button is drawn inside rather than by Vuetify. -->
78
+ <StatusChip
83
79
  v-for="key in existingKeys.filter((k) => k.status != 'Removed')"
84
80
  :key="key.keyId"
85
- prepend-icon="mdi-key"
86
- color="orange"
87
- variant="tonal"
88
- size="small"
89
- closable
90
- @click:close="removeExistingKey(key)"
81
+ tone="warn"
82
+ :dot="false"
91
83
  >
84
+ <v-icon icon="mdi-key" size="13" />
92
85
  {{ key.prefixAndName }}
93
- </v-chip>
94
- <span class="text-caption text-medium-emphasis align-self-center">
95
- (current)
96
- </span>
86
+ <button
87
+ class="passkey__remove"
88
+ :aria-label="`Remove ${key.prefixAndName}`"
89
+ @click="removeExistingKey(key)"
90
+ >
91
+ <v-icon icon="mdi-close-circle" size="14" />
92
+ </button>
93
+ </StatusChip>
94
+ <span class="passkey__current align-self-center">(current)</span>
97
95
  </div>
98
96
 
99
97
  <!-- New keys selector -->
@@ -132,41 +130,16 @@
132
130
  </v-row>
133
131
 
134
132
  <v-row v-if="errorMessage" no-gutters class="mt-2">
135
- <p class="text-error text-subtitle-2 w-100 text-center">
136
- {{ errorMessage }}
137
- </p>
138
- </v-row>
139
- </v-card-text>
140
-
141
- <v-toolbar density="compact">
142
- <v-row no-gutters>
143
- <v-col cols="6">
144
- <v-btn
145
- tile
146
- block
147
- variant="text"
148
- class="text-none"
149
- size="48"
150
- text="Cancel"
151
- @click="emit('close')"
152
- />
153
- </v-col>
154
- <v-col cols="6">
155
- <v-btn
156
- tile
157
- block
158
- variant="flat"
159
- color="black"
160
- class="text-none"
161
- size="48"
162
- :text="isEditMode ? 'Save' : 'Assign'"
163
- :disabled="!canSubmit"
164
- :loading="processing"
165
- @click="handleSubmit"
166
- />
167
- </v-col>
133
+ <p class="passkey__error">{{ errorMessage }}</p>
168
134
  </v-row>
169
- </v-toolbar>
135
+ </div>
136
+
137
+ <div class="passkey__footer">
138
+ <AppButton variant="ghost" @click="emit('close')">Cancel</AppButton>
139
+ <AppButton :disabled="!canSubmit" @click="handleSubmit">
140
+ {{ isEditMode ? "Save" : "Assign" }}
141
+ </AppButton>
142
+ </div>
170
143
  </v-card>
171
144
  </template>
172
145
 
@@ -448,4 +421,53 @@ async function handleSubmit() {
448
421
  }
449
422
  </script>
450
423
 
451
- <style scoped></style>
424
+ <style scoped>
425
+ .passkey__head {
426
+ display: flex;
427
+ align-items: center;
428
+ justify-content: space-between;
429
+ padding-right: 12px;
430
+ }
431
+
432
+ .passkey__body {
433
+ padding: 4px 20px 0;
434
+ }
435
+
436
+ .passkey__name,
437
+ .passkey__current {
438
+ font-size: var(--fs-cell);
439
+ color: var(--text2);
440
+ }
441
+
442
+ .passkey__error {
443
+ width: 100%;
444
+ margin: 0;
445
+ text-align: center;
446
+ font-size: var(--fs-cell);
447
+ color: var(--err);
448
+ }
449
+
450
+ /* The chip's own remove control - `currentColor`, so it stays on whatever
451
+ tone the chip carries rather than picking a second colour. */
452
+ .passkey__remove {
453
+ display: inline-flex;
454
+ margin-left: 2px;
455
+ padding: 0;
456
+ border: none;
457
+ background: none;
458
+ color: inherit;
459
+ cursor: pointer;
460
+ opacity: 0.75;
461
+ }
462
+
463
+ .passkey__remove:hover {
464
+ opacity: 1;
465
+ }
466
+
467
+ .passkey__footer {
468
+ display: flex;
469
+ justify-content: flex-end;
470
+ gap: 8px;
471
+ padding: 16px 20px 20px;
472
+ }
473
+ </style>
@@ -2,37 +2,39 @@
2
2
  <v-row no-gutters class="px-5 pt-4">
3
3
  <!-- Authorities (Police/SCDF/Ambulance called in at the scene) -->
4
4
  <v-col cols="12" class="border-b pb-5 mb-5 mt-1">
5
- <p class="mb-2" style="font-size: 17px; font-weight: 600">
5
+ <p class="screen-card-title mb-2">
6
6
  Authorities (Police/SCDF/Ambulance called in at the scene)?
7
7
  </p>
8
8
  <p
9
9
  v-if="authorities?.authoritiesValue == 'no'"
10
- class="mt-2 text-h6 text-capitalize"
10
+ class="report-answer mt-2 text-capitalize"
11
11
  >
12
12
  {{ authorities?.authoritiesValue }}
13
13
  </p>
14
14
 
15
- <v-data-table
16
- v-else
17
- :headers="authoritiesTableHeader"
18
- :items="authorities?.authoritiesCalled"
19
- fixed-header
20
- hide-default-footer
21
- :hide-default-header="false"
22
- items-per-page="100"
23
- style="max-height: calc(100vh - (200px))"
24
- class="border mt-5"
25
- >
26
- </v-data-table>
15
+ <AppCard v-else class="table-card mt-5">
16
+ <v-data-table
17
+ :headers="authoritiesTableHeader"
18
+ :items="authorities?.authoritiesCalled"
19
+ fixed-header
20
+ hide-default-footer
21
+ :hide-default-header="false"
22
+ items-per-page="100"
23
+ style="max-height: calc(100vh - (200px))"
24
+ >
25
+ </v-data-table>
26
+ </AppCard>
27
27
  </v-col>
28
- <div class="w-100 my-8 mx-2">
29
- <v-table class="responsive-table border elevation-0">
28
+ <!-- `w-100` + `mx-2` made the card 16px wider than its column, so its right
29
+ corner was clipped off. The card supplies its own edge now. -->
30
+ <AppCard class="table-card w-100 my-8">
31
+ <v-table class="responsive-table elevation-0">
30
32
  <thead>
31
33
  <tr>
32
34
  <th
33
35
  v-for="(item, index) in concernHeader"
34
36
  :key="index"
35
- class="text-left font-weight-bold text-black border-e"
37
+ class="text-left border-e"
36
38
  >
37
39
  {{ item }}
38
40
  </th>
@@ -196,10 +198,20 @@
196
198
  </tr>
197
199
  </tbody>
198
200
  </v-table>
199
- </div>
201
+ </AppCard>
200
202
  </v-row>
201
203
  </template>
202
204
 
205
+ <style scoped>
206
+ /* The prototype states no size for a plain answer line, so it takes the body
207
+ row's own type rather than Vuetify's `text-h6`. */
208
+ .report-answer {
209
+ font-size: var(--fs-cell);
210
+ font-weight: var(--fw-cell);
211
+ color: var(--text);
212
+ }
213
+ </style>
214
+
203
215
  <script lang="ts" setup>
204
216
  definePageMeta({
205
217
  middleware: ["01-auth", "02-org"],
@@ -9,36 +9,27 @@
9
9
  >
10
10
  <v-container class="d-flex justify-center" max-height="90vh">
11
11
  <!-- QR code reader container -->
12
- <v-card
13
- elevation="2"
14
- class="d-flex flex-column align-center pa-2 w-100 h-100"
15
- >
16
- <v-toolbar>
17
- <v-card-title class="text-h5"> Scan QR Code </v-card-title>
18
- <v-spacer />
19
- <v-btn
20
- color="grey-darken-1"
21
- icon="mdi-close"
22
- @click="closeDialog()"
23
- />
24
- </v-toolbar>
25
-
26
- <div
27
- id="reader"
28
- class="d-flex justify-center align-center w-100 h-100"
29
- style="height: calc(100vh - 64px)"
30
- >
31
- <!-- The QR code scanner box -->
32
- <!-- This is where the QR code scanner will be displayed -->
12
+ <v-card class="screen-modal qr-scanner">
13
+ <div class="qr-scanner__head">
14
+ <v-card-title>Scan QR Code</v-card-title>
15
+ <AppButton variant="icon" icon="mdi-close" @click="closeDialog()" />
33
16
  </div>
34
- <!-- Show Error Messages -->
35
- <div v-if="showNotFoundMessage" class="text-error mt-4 text-h5">
36
- <p>{{ errorMessage }}</p>
17
+
18
+ <div class="screen-modal__body qr-scanner__body">
19
+ <div id="reader" class="qr-scanner__reader">
20
+ <!-- The QR code scanner box -->
21
+ <!-- This is where the QR code scanner will be displayed -->
22
+ </div>
23
+ <!-- Show Error Messages -->
24
+ <p v-if="showNotFoundMessage" class="qr-scanner__error">{{ errorMessage }}</p>
25
+ <!-- Switch camera button inside the reader box -->
26
+ <AppButton
27
+ icon="mdi-camera-switch"
28
+ class="qr-scanner__switch"
29
+ aria-label="Switch camera"
30
+ @click="switchCamera()"
31
+ />
37
32
  </div>
38
- <!-- Switch camera button inside the reader box -->
39
- <v-btn color="primary" icon class="mt-4" @click="switchCamera()">
40
- <v-icon icon="mdi-camera-switch" large />
41
- </v-btn>
42
33
  </v-card>
43
34
  </v-container>
44
35
  </v-dialog>
@@ -225,3 +216,48 @@ const stopScanner = () => {
225
216
  });
226
217
  };
227
218
  </script>
219
+
220
+ <style scoped>
221
+ /* Same scanner frame as the pass-key scanner: the card used to be `w-100`
222
+ inside the centring container, so keep that width. */
223
+ .qr-scanner {
224
+ width: 100%;
225
+ }
226
+
227
+ .qr-scanner__head {
228
+ display: flex;
229
+ align-items: center;
230
+ justify-content: space-between;
231
+ padding-right: 12px;
232
+ }
233
+
234
+ .qr-scanner__body {
235
+ display: flex;
236
+ flex-direction: column;
237
+ align-items: center;
238
+ gap: 16px;
239
+ padding: 4px 20px 20px;
240
+ }
241
+
242
+ .qr-scanner__reader {
243
+ display: flex;
244
+ align-items: center;
245
+ justify-content: center;
246
+ width: 100%;
247
+ min-height: 320px;
248
+ border: 1px solid var(--border);
249
+ border-radius: var(--r-inner);
250
+ background: var(--thead);
251
+ }
252
+
253
+ .qr-scanner__error {
254
+ margin: 0;
255
+ font-size: var(--fs-cell);
256
+ color: var(--err);
257
+ }
258
+
259
+ .qr-scanner__switch {
260
+ width: var(--btn-h);
261
+ padding: 0;
262
+ }
263
+ </style>
@@ -1,44 +1,35 @@
1
1
  <template>
2
- <v-card width="100%">
3
- <v-toolbar>
4
- <v-row no-gutters>
5
- <v-col cols="12" class="text-h6 font-weight-bold px-3">Vehicle Number ({{ vehicleNumber }})</v-col>
6
- </v-row>
7
- </v-toolbar>
2
+ <v-card width="100%" class="screen-modal search-vehicle-user">
3
+ <v-card-title>Vehicle Number ({{ vehicleNumber }})</v-card-title>
8
4
 
9
- <v-card-text style="max-height: 100vh; overflow-y: auto">
10
- <v-data-table :items="prop.vehicleNumberUsersList" hide-default-footer :headers="headers" density="comfortable"
11
- item-key="_id ">
12
- <template #item.name="{ item }">
13
- <span class="d-flex align-center ga-2">
14
- <span>
15
- <AvatarMain :name="item?.name" :size="20" :id="item?._id" />
5
+ <div class="screen-modal__body search-vehicle-user__body">
6
+ <!-- `table-card` is the shared table card's own class, so the header
7
+ type, the cell padding and the row rule are the design's - without
8
+ TableMain's page toolbar, which a two-row picker inside a dialog
9
+ has nothing to put in. -->
10
+ <AppCard class="table-card">
11
+ <v-data-table :items="prop.vehicleNumberUsersList" hide-default-footer :headers="headers" density="comfortable"
12
+ item-key="_id ">
13
+ <template #item.name="{ item }">
14
+ <span class="d-flex align-center ga-2">
15
+ <span>
16
+ <AvatarMain :name="item?.name" :size="20" :id="item?._id" />
17
+ </span>
18
+ <span class="text-capitalize">{{ item?.name }}</span>
16
19
  </span>
17
- <span class="text-capitalize">{{ item?.name }}</span>
18
- </span>
19
- </template>
20
+ </template>
20
21
 
21
- <template #item.actions="{ item }">
22
- <v-btn text="Select" rounded="md" flat color="blue" density="comfortable" :ripple="false" @click="handleSelectUser(item)" />
23
- </template>
24
- </v-data-table>
25
- </v-card-text>
22
+ <template #item.actions="{ item }">
23
+ <AppButton variant="ghost" @click="handleSelectUser(item)">Select</AppButton>
24
+ </template>
25
+ </v-data-table>
26
+ </AppCard>
27
+ </div>
26
28
 
27
- <v-toolbar class="pa-0" density="compact">
28
- <v-row no-gutters>
29
- <v-col cols="6" class="pa-0">
30
- <v-btn block variant="text" class="text-none" size="large" @click="emit('close')" height="48">
31
- Close
32
- </v-btn>
33
- </v-col>
34
-
35
- <v-col cols="6" class="pa-0">
36
- <v-btn block variant="flat" color="black" class="text-none" height="48" tile @click="emit('close')">
37
- Add Different User
38
- </v-btn>
39
- </v-col>
40
- </v-row>
41
- </v-toolbar>
29
+ <div class="search-vehicle-user__footer">
30
+ <AppButton variant="ghost" @click="emit('close')">Close</AppButton>
31
+ <AppButton @click="emit('close')">Add Different User</AppButton>
32
+ </div>
42
33
  <v-dialog v-model="confirmAction" persistent max-width="450">
43
34
  <DialogReplaceAutofillPrompt @close="confirmAction = false" @proceed="handleUpdateUserDetails"/>
44
35
  </v-dialog>
@@ -89,4 +80,15 @@ onMounted(() => {
89
80
  })
90
81
  </script>
91
82
 
92
- <style scoped></style>
83
+ <style scoped>
84
+ .search-vehicle-user__body {
85
+ padding: 4px 20px 0;
86
+ }
87
+
88
+ .search-vehicle-user__footer {
89
+ display: flex;
90
+ justify-content: flex-end;
91
+ gap: 8px;
92
+ padding: 16px 20px 20px;
93
+ }
94
+ </style>
@@ -1,36 +1,24 @@
1
1
  <template>
2
- <v-card width="100%">
3
- <v-toolbar>
4
- <v-row no-gutters class="fill-height px-6" align="center">
5
- <span class="font-weight-bold text-h5 text-capitalize">
6
- Add Vehicle
7
- </span>
8
- </v-row>
9
- </v-toolbar>
10
-
11
- <v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-5">
12
- <span class="text-subtitle-2 w-100 font-weight-medium d-flex justify-center mb-3">Please Select Status</span>
13
- <template v-for="item in selection" :key="item.value">
14
- <v-btn color="primary-button" block variant="flat" rounded="md" size="48" :text="item.label" @click="select(item.value)" class="my-2 text-capitalize text-subtitle-2" />
15
- </template>
16
- </v-card-text>
17
-
18
- <v-toolbar density="compact">
19
- <v-row no-gutters>
20
- <v-col cols="12">
21
- <v-btn
22
- tile
23
- block
24
- variant="text"
25
- class="text-none"
26
- size="48"
27
- @click="cancel"
28
- >
29
- Cancel
30
- </v-btn>
31
- </v-col>
32
- </v-row>
33
- </v-toolbar>
2
+ <v-card width="100%" class="screen-modal vehicle-add">
3
+ <v-card-title>Add Vehicle</v-card-title>
4
+
5
+ <div class="screen-modal__body vehicle-add__body">
6
+ <p class="vehicle-add__hint">Please Select Status</p>
7
+ <AppButton
8
+ v-for="item in selection"
9
+ :key="item.value"
10
+ class="vehicle-add__option"
11
+ @click="select(item.value)"
12
+ >
13
+ {{ item.label }}
14
+ </AppButton>
15
+ </div>
16
+
17
+ <div class="vehicle-add__footer">
18
+ <AppButton variant="ghost" class="vehicle-add__cancel" @click="cancel">
19
+ Cancel
20
+ </AppButton>
21
+ </div>
34
22
  </v-card>
35
23
  </template>
36
24
 
@@ -56,3 +44,31 @@ function select(value: TVehicleType | 'seasonpass') {
56
44
  emit("select", value);
57
45
  }
58
46
  </script>
47
+
48
+ <style scoped>
49
+ /* The three choices are full-width by the screen's own design, so the only
50
+ thing said here is the width and the stack - the button itself is AppButton. */
51
+ .vehicle-add__body {
52
+ padding: 20px;
53
+ }
54
+
55
+ .vehicle-add__hint {
56
+ margin: 0 0 14px;
57
+ text-align: center;
58
+ font-size: var(--fs-cell);
59
+ color: var(--muted);
60
+ }
61
+
62
+ .vehicle-add__option {
63
+ display: flex;
64
+ width: 100%;
65
+ margin-bottom: 10px;
66
+ }
67
+
68
+ .vehicle-add__footer {
69
+ display: flex;
70
+ justify-content: flex-end;
71
+ gap: 8px;
72
+ padding: 0 20px 20px;
73
+ }
74
+ </style>