@7365admin1/layer-common 3.2.2-staging.85 → 3.2.2-staging.87

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.
@@ -3,10 +3,8 @@
3
3
  <v-col cols="12" class="mb-2">
4
4
  <v-row no-gutters>
5
5
  <v-btn
6
- class="text-none mr-2"
7
- rounded="pill"
8
- variant="tonal"
9
- size="large"
6
+ class="text-none mr-2 screen-btn-primary"
7
+ variant="flat"
10
8
  @click="inviteMember()"
11
9
  v-if="props.inviteMember"
12
10
  >
@@ -15,8 +13,12 @@
15
13
  </v-row>
16
14
  </v-col>
17
15
  <v-col cols="12">
18
- <v-card width="100%" variant="outlined" border="thin" rounded="lg">
19
- <v-toolbar density="compact" color="grey-lighten-4">
16
+ <v-card width="100%" variant="flat" class="table-card">
17
+ <v-toolbar
18
+ density="compact"
19
+ color="transparent"
20
+ class="table-card__toolbar"
21
+ >
20
22
  <template #prepend>
21
23
  <v-btn
22
24
  fab
@@ -30,7 +32,7 @@
30
32
 
31
33
  <template #append>
32
34
  <v-row no-gutters justify="end" align="center">
33
- <span class="mr-2 text-caption text-fontgray">
35
+ <span class="mr-2 table-card__range">
34
36
  {{ pageRange }}
35
37
  </span>
36
38
  <local-pagination
@@ -77,7 +79,7 @@
77
79
  <span class="text-caption font-weight-bold text-capitalize">
78
80
  permissions
79
81
  </span>
80
- <v-chip>{{ value.length }}</v-chip>
82
+ <StatusChip :dot="false" tone="info" :label="String(value.length)" />
81
83
  </template>
82
84
  <template #item.createdAt="{ item }">
83
85
  {{ item.createdAt ? formatDate(item.createdAt) : "" }}
@@ -10,10 +10,10 @@
10
10
  </v-col>
11
11
  <v-spacer />
12
12
  <v-col v-if="isScheduleClosed" cols="auto" class="d-flex align-center">
13
- <v-chip color="error" variant="tonal" class="text-capitalize">
14
- <v-icon start>mdi-lock</v-icon>
13
+ <StatusChip status="Closed" class="text-capitalize">
14
+ <v-icon size="14">mdi-lock</v-icon>
15
15
  Closed – View Only
16
- </v-chip>
16
+ </StatusChip>
17
17
  </v-col>
18
18
  </v-row>
19
19
  <TableHygiene
@@ -85,7 +85,7 @@
85
85
  <v-sheet
86
86
  border
87
87
  rounded="lg"
88
- class="d-inline-flex flex-column pa-3 bg-grey-lighten-5"
88
+ class="d-inline-flex flex-column pa-3"
89
89
  style="max-width: 420px"
90
90
  >
91
91
  <div class="d-flex align-center ga-2 mb-2">
@@ -93,9 +93,7 @@
93
93
  <span class="text-caption font-weight-bold">
94
94
  Rejection details
95
95
  </span>
96
- <v-chip size="x-small" color="error" variant="tonal">
97
- Rejected
98
- </v-chip>
96
+ <StatusChip status="Rejected" :dot="false" />
99
97
  </div>
100
98
  <div
101
99
  v-if="item.remarks"
@@ -173,22 +171,24 @@
173
171
  <template #group-header-append="{ group }">
174
172
  <v-row no-gutters align="center" class="ga-2">
175
173
  <v-col v-if="isGroupAnyApproved(group)" cols="auto">
176
- <v-chip
177
- size="x-small"
178
- :color="isGroupComplete(group) ? 'success' : 'warning'"
179
- variant="tonal"
180
- :prepend-icon="
181
- isGroupComplete(group)
182
- ? 'mdi-check-circle-outline'
183
- : 'mdi-progress-clock'
184
- "
174
+ <StatusChip
175
+ :status="isGroupComplete(group) ? 'Completed' : 'Ongoing'"
176
+ :tone="isGroupComplete(group) ? 'ok' : 'warn'"
177
+ :dot="false"
185
178
  class="text-none"
186
179
  >
180
+ <v-icon size="12">
181
+ {{
182
+ isGroupComplete(group)
183
+ ? "mdi-check-circle-outline"
184
+ : "mdi-progress-clock"
185
+ }}
186
+ </v-icon>
187
187
  {{ isGroupComplete(group) ? "Completed" : "Ongoing" }}
188
188
  <template v-if="getGroupCompletedByName(group)">
189
189
  · {{ getGroupCompletedByName(group) }}
190
190
  </template>
191
- </v-chip>
191
+ </StatusChip>
192
192
  </v-col>
193
193
  <v-col
194
194
  v-if="group.attachments && group.attachments.length > 0"
@@ -4,9 +4,8 @@
4
4
  <v-row no-gutters>
5
5
  <v-btn
6
6
  v-if="props.seatManagement !== 'index'"
7
- class="text-none"
8
- rounded="pill"
9
- variant="tonal"
7
+ class="text-none screen-btn-primary"
8
+ variant="flat"
10
9
  :to="{
11
10
  name: props.seatManagement,
12
11
  params: { organization: props.orgId },
@@ -19,8 +18,12 @@
19
18
  </v-col>
20
19
 
21
20
  <v-col cols="12">
22
- <v-card width="100%" variant="outlined" border="thin" rounded="lg">
23
- <v-toolbar density="compact" color="grey-lighten-4">
21
+ <v-card width="100%" variant="flat" class="table-card">
22
+ <v-toolbar
23
+ density="compact"
24
+ color="transparent"
25
+ class="table-card__toolbar"
26
+ >
24
27
  <template #prepend>
25
28
  <v-btn fab icon density="comfortable" @click="getAll()">
26
29
  <v-icon>mdi-refresh</v-icon>
@@ -29,7 +32,7 @@
29
32
 
30
33
  <template #append>
31
34
  <v-row no-gutters justify="end" align="center">
32
- <span class="mr-2 text-caption text-font gray">
35
+ <span class="mr-2 table-card__range">
33
36
  {{ pageRange }}
34
37
  </span>
35
38
  <local-pagination
@@ -17,10 +17,8 @@
17
17
  <v-row no-gutters align="center" class="w-100">
18
18
  <v-col cols="auto" v-if="canCheckInOut">
19
19
  <v-btn
20
- class="text-none"
21
- rounded="pill"
22
- variant="tonal"
23
- size="large"
20
+ class="text-none screen-btn-primary"
21
+ variant="flat"
24
22
  @click="onCreateItem"
25
23
  >
26
24
  {{ hasCheckedInToday ? "Check Out" : "Check In" }}
@@ -28,7 +26,7 @@
28
26
  </v-col>
29
27
  <v-spacer />
30
28
 
31
- <v-col cols="auto">
29
+ <v-col cols="auto" class="filter-field">
32
30
  <v-text-field
33
31
  v-model="searchInput"
34
32
  density="compact"
@@ -3,11 +3,9 @@
3
3
  <v-col cols="12" class="mb-2">
4
4
  <v-row no-gutters>
5
5
  <v-btn
6
- class="text-none"
7
- rounded="pill"
8
- variant="tonal"
6
+ class="text-none screen-btn-primary"
7
+ variant="flat"
9
8
  @click="createDialog = true"
10
- size="large"
11
9
  v-if="canCreateRole"
12
10
  >
13
11
  Create role
@@ -17,12 +15,15 @@
17
15
  <v-col cols="12">
18
16
  <v-card
19
17
  width="100%"
20
- variant="outlined"
21
- border="thin"
22
- rounded="lg"
18
+ variant="flat"
19
+ class="table-card"
23
20
  :loading="loading"
24
21
  >
25
- <v-toolbar density="compact" color="grey-lighten-4">
22
+ <v-toolbar
23
+ density="compact"
24
+ color="transparent"
25
+ class="table-card__toolbar"
26
+ >
26
27
  <template #prepend>
27
28
  <v-btn fab icon density="comfortable" @click="getRoles()">
28
29
  <v-icon>mdi-refresh</v-icon>
@@ -31,7 +32,7 @@
31
32
 
32
33
  <template #append>
33
34
  <v-row no-gutters justify="end" align="center">
34
- <span class="mr-2 text-caption text-fontgray">
35
+ <span class="mr-2 table-card__range">
35
36
  {{ pageRange }}
36
37
  </span>
37
38
  <local-pagination
@@ -58,7 +59,11 @@
58
59
  <span class="text-caption font-weight-bold text-capitalize">
59
60
  permissions
60
61
  </span>
61
- <v-chip>{{ getPermissionCount(value) }}</v-chip>
62
+ <StatusChip
63
+ :dot="false"
64
+ tone="info"
65
+ :label="String(getPermissionCount(value))"
66
+ />
62
67
  </template>
63
68
 
64
69
  <template #item.action-table="{ item }" v-if="canDeleteRole">
@@ -21,7 +21,7 @@
21
21
  <template #extension>
22
22
  <v-row no-gutters class="w-100 d-flex flex-column">
23
23
  <v-card
24
- class="w-100 px-3 d-flex align-center ga-5 py-2"
24
+ class="w-100 filter-bar d-flex align-center ga-5"
25
25
  flat
26
26
  :height="60"
27
27
  >
@@ -68,20 +68,18 @@
68
68
  <v-spacer />
69
69
 
70
70
  <v-col cols="auto">
71
- <v-chip
71
+ <StatusChip
72
72
  v-if="isScheduleClosed"
73
- color="error"
74
- variant="tonal"
73
+ status="Closed"
75
74
  class="text-capitalize mr-2"
76
75
  >
77
- <v-icon start>mdi-lock</v-icon>
76
+ <v-icon size="14">mdi-lock</v-icon>
78
77
  Closed – View Only
79
- </v-chip>
78
+ </StatusChip>
80
79
  <v-btn
81
80
  v-if="canViewHistory"
82
- class="text-none mr-2"
83
- size="large"
84
- color="primary"
81
+ class="text-none mr-2 screen-btn-primary"
82
+ variant="flat"
85
83
  aria-label="History"
86
84
  @click="openHistory"
87
85
  >
@@ -89,9 +87,8 @@
89
87
  </v-btn>
90
88
  <v-btn
91
89
  v-if="canGenerateChecklist"
92
- class="text-none"
93
- size="large"
94
- color="primary"
90
+ class="text-none screen-btn-primary"
91
+ variant="flat"
95
92
  aria-label="Generate"
96
93
  @click="_generateChecklist"
97
94
  :loading="submitting"
@@ -114,20 +111,13 @@
114
111
  </span>
115
112
  </div>
116
113
  <div v-else-if="isScheduleClosed">
117
- <v-chip
118
- size="small"
119
- color="error"
120
- variant="tonal"
121
- class="text-capitalize"
122
- >Closed</v-chip
123
- >
114
+ <StatusChip status="Closed" class="text-capitalize" />
124
115
  </div>
125
116
  <div v-else>
126
117
  <v-btn
127
118
  v-if="canManageScheduleTasks"
128
119
  variant="outlined"
129
- size="medium"
130
- class="text-capitalize px-4 py-2"
120
+ class="text-capitalize screen-btn-ghost"
131
121
  @click.stop="() => _acceptAreaChecklist(item._id)"
132
122
  >
133
123
  Accept
@@ -146,14 +136,11 @@
146
136
  </template>
147
137
 
148
138
  <template #item.status="{ value }">
149
- <v-chip
139
+ <StatusChip
150
140
  class="text-capitalize"
151
- :color="getStatusColor(value)"
152
- variant="flat"
153
- pill
154
- >
155
- {{ value || "No Status" }}
156
- </v-chip>
141
+ :status="value"
142
+ :label="value || 'No Status'"
143
+ />
157
144
  </template>
158
145
  </TableMain></v-col
159
146
  >
@@ -262,27 +249,6 @@ watchEffect(() => {
262
249
  }
263
250
  });
264
251
 
265
- const getStatusColor = (status: unknown): string => {
266
- if (!status) return "grey";
267
-
268
- const normalized = String(status).toLowerCase();
269
-
270
- switch (normalized) {
271
- case "open":
272
- return "grey";
273
- case "ongoing":
274
- return "primary";
275
- case "completed":
276
- case "accepted":
277
- return "success";
278
- case "closed":
279
- case "rejected":
280
- return "error";
281
- default:
282
- return "secondary";
283
- }
284
- };
285
-
286
252
  function showMessage(msg: string, color: string = "error") {
287
253
  message.value = msg;
288
254
  messageColor.value = color;
@@ -21,10 +21,8 @@
21
21
  <v-row no-gutters align="center" class="w-100">
22
22
  <v-col cols="auto" v-if="canCreateScheduleTask">
23
23
  <v-btn
24
- class="text-none"
25
- rounded="pill"
26
- variant="tonal"
27
- size="large"
24
+ class="text-none screen-btn-primary"
25
+ variant="flat"
28
26
  @click="openFormDialog"
29
27
  >
30
28
  Create Schedule Task
@@ -33,7 +31,7 @@
33
31
 
34
32
  <v-spacer />
35
33
 
36
- <v-col cols="auto">
34
+ <v-col cols="auto" class="filter-field">
37
35
  <v-text-field
38
36
  v-model="searchInput"
39
37
  density="compact"
@@ -49,28 +47,31 @@
49
47
 
50
48
  <template #item.areas="{ value }">
51
49
  <div v-if="value && value.length > 0">
52
- <v-chip
50
+ <StatusChip
53
51
  v-for="(area, idx) in value.slice(0, 2)"
54
52
  :key="idx"
55
- size="small"
56
53
  class="mr-1 mb-1"
57
- >
58
- {{ area.name }}
59
- </v-chip>
60
- <v-chip v-if="value.length > 2" size="small" class="mb-1">
61
- +{{ value.length - 2 }} more
62
- </v-chip>
54
+ :dot="false"
55
+ tone="neutral"
56
+ :label="area.name"
57
+ />
58
+ <StatusChip
59
+ v-if="value.length > 2"
60
+ class="mb-1"
61
+ :dot="false"
62
+ tone="neutral"
63
+ :label="`+${value.length - 2} more`"
64
+ />
63
65
  </div>
64
66
  <span v-else>N/A</span>
65
67
  </template>
66
68
 
67
69
  <template #item.status="{ value }">
68
- <v-chip
69
- :color="value === 'active' ? 'success' : 'default'"
70
+ <StatusChip
70
71
  class="text-capitalize"
71
- >
72
- {{ value || "N/A" }}
73
- </v-chip>
72
+ :status="value"
73
+ :label="value || 'N/A'"
74
+ />
74
75
  </template>
75
76
  </TableMain>
76
77
 
@@ -270,15 +271,11 @@
270
271
  Status:
271
272
  </v-col>
272
273
  <v-col cols="7" class="text-subtitle-2">
273
- <v-chip
274
- :color="
275
- selectedTask.status === 'active' ? 'success' : 'default'
276
- "
277
- size="small"
274
+ <StatusChip
278
275
  class="text-capitalize"
279
- >
280
- {{ selectedTask.status || "N/A" }}
281
- </v-chip>
276
+ :status="selectedTask.status"
277
+ :label="selectedTask.status || 'N/A'"
278
+ />
282
279
  </v-col>
283
280
  </v-row>
284
281
 
@@ -47,13 +47,7 @@
47
47
  </template>
48
48
 
49
49
  <template #item.status="{ value }">
50
- <v-chip
51
- :color="getStatusColor(value)"
52
- class="font-weight-bold"
53
- style="background: #ffe6c2; color: #ff9800"
54
- >
55
- {{ value || "To-Do" }}
56
- </v-chip>
50
+ <StatusChip :status="value || 'To-Do'" :label="value || 'To-Do'" />
57
51
  </template>
58
52
  <!-- Completion Date/Time -->
59
53
  <template #item.completionDate="{ value }">
@@ -61,7 +55,11 @@
61
55
  </template>
62
56
  <!-- Action (Accept button) -->
63
57
  <template #item.action="{ item }">
64
- <v-btn outlined class="accept-btn" @click.stop="acceptTask(item)">
58
+ <v-btn
59
+ variant="outlined"
60
+ class="text-none screen-btn-ghost"
61
+ @click.stop="acceptTask(item)"
62
+ >
65
63
  Accept
66
64
  </v-btn>
67
65
  </template>
@@ -146,11 +144,6 @@ function getAvatarColor(name: string) {
146
144
  if (name === "Hygiene SP") return "blue";
147
145
  return "grey";
148
146
  }
149
- function getStatusColor(status: string) {
150
- if (status === "To-Do") return "orange";
151
- if (status === "Completed") return "green";
152
- return "grey";
153
- }
154
147
  function acceptTask(item: any) {
155
148
  selectedTask.value = item;
156
149
  showAcceptDialog.value = true;
@@ -170,13 +163,3 @@ function onRowClick(data: any) {
170
163
  }
171
164
  }
172
165
  </script>
173
-
174
- <style scoped>
175
- .accept-btn {
176
- border: 1px solid #333;
177
- background: #fff;
178
- border-radius: 4px;
179
- cursor: pointer;
180
- min-width: 80px;
181
- }
182
- </style>
@@ -5,20 +5,16 @@
5
5
  <div class="d-flex flex-wrap align-center">
6
6
  <v-btn
7
7
  v-if="showAddButton && canAddServiceProvider"
8
- class="text-none mr-2"
9
- rounded="pill"
10
- variant="tonal"
11
- size="large"
8
+ class="text-none mr-2 screen-btn-primary"
9
+ variant="flat"
12
10
  @click="(createDialog = true), setServiceProvider({ mode: 'add' })"
13
11
  >
14
12
  Add
15
13
  </v-btn>
16
14
  <v-btn
17
15
  v-if="canInviteServiceProvider"
18
- class="text-none mr-2"
19
- rounded="pill"
20
- variant="tonal"
21
- size="large"
16
+ class="text-none mr-2 screen-btn-primary"
17
+ variant="flat"
22
18
  @click="
23
19
  (createInviteDialog = true),
24
20
  setServiceProvider({ mode: 'invite' })
@@ -28,10 +24,8 @@
28
24
  </v-btn>
29
25
  <v-btn
30
26
  v-if="showBillingButton"
31
- class="text-none mr-2"
32
- rounded="pill"
33
- variant="tonal"
34
- size="large"
27
+ class="text-none mr-2 screen-btn-primary"
28
+ variant="flat"
35
29
  @click="
36
30
  useRouter().push({
37
31
  name: 'org-site-service-provider-mgmt-billing',
@@ -59,9 +53,8 @@
59
53
  <v-col cols="12">
60
54
  <v-card
61
55
  width="100%"
62
- variant="outlined"
63
- border="thin"
64
- rounded="lg"
56
+ variant="flat"
57
+ class="table-card"
65
58
  :loading="loading"
66
59
  >
67
60
  <div class="sp-table-header">
@@ -101,7 +94,7 @@
101
94
  v-model="listTab"
102
95
  color="primary"
103
96
  density="comfortable"
104
- class="sp-tabs"
97
+ class="sp-tabs screen-tabs"
105
98
  align-tabs="start"
106
99
  >
107
100
  <v-tab value="active" class="text-none">Service Providers</v-tab>
@@ -147,14 +140,11 @@
147
140
  4.5:1 a 12px label needs. Filled puts the colour in the
148
141
  background and lets Vuetify pick a readable foreground for it.
149
142
  -->
150
- <v-chip
151
- :color="statusChipColor(item.status, item.statusRaw)"
152
- size="small"
153
- :variant="item.source === 'invite' ? 'flat' : 'tonal'"
143
+ <StatusChip
154
144
  class="text-none"
155
- >
156
- {{ item.status }}
157
- </v-chip>
145
+ :status="item.statusRaw || item.status"
146
+ :label="item.status"
147
+ />
158
148
  <div
159
149
  v-if="item.rejectionReason"
160
150
  class="text-caption text-medium-emphasis mt-1 sp-reject-reason"
@@ -520,7 +510,7 @@
520
510
 
521
511
  <v-dialog v-model="createInviteDialog" width="580" persistent>
522
512
  <v-card width="100%" rounded="lg" class="sp-invite-card">
523
- <v-toolbar flat color="grey-lighten-4" height="76">
513
+ <v-toolbar flat color="transparent" class="table-card__toolbar" height="76">
524
514
  <v-row no-gutters class="fill-height px-6" align="center">
525
515
  <span class="font-weight-bold text-h5">
526
516
  Invite Service Provider
@@ -1147,24 +1137,9 @@ function statusDisplay(raw: string, source: TableRow["source"]) {
1147
1137
  return raw.charAt(0).toUpperCase() + raw.slice(1).toLowerCase();
1148
1138
  }
1149
1139
 
1150
- const INVITE_STATUS_COLOURS: Record<string, string> = {
1151
- "awaiting-approval": "warning",
1152
- pending: "info",
1153
- complete: "success",
1154
- rejected: "error",
1155
- declined: "default",
1156
- cancelled: "default",
1157
- expired: "default",
1158
- };
1159
-
1160
- function statusChipColor(statusLabel: string, statusRaw?: string) {
1161
- if (statusRaw) return INVITE_STATUS_COLOURS[statusRaw] ?? "primary";
1162
- const s = statusLabel.toLowerCase();
1163
- if (s === "active") return "success";
1164
- if (s === "pending") return "warning";
1165
- if (s === "in-active" || s === "inactive") return "default";
1166
- return "primary";
1167
- }
1140
+ /* The status chips read their tone from the shared mapping in
1141
+ `utils/status.ts` now - which carries every raw invitation status this map
1142
+ carried, with the same tone. */
1168
1143
 
1169
1144
  // async function loadInviteRoles() {
1170
1145
  // loadingInviteRoles.value = true;
@@ -12,7 +12,10 @@
12
12
  <template>
13
13
  <span class="status-chip" :class="[toneClass, { 'status-chip--plain': !dot }]">
14
14
  <span v-if="dot" class="status-chip__dot" />
15
- {{ label ?? status }}
15
+ <!-- The slot is for the chips that already carried an icon next to their
16
+ word - a padlock on "Closed - View Only" - so adopting the design's
17
+ pill does not quietly drop it. -->
18
+ <slot>{{ label ?? status }}</slot>
16
19
  </span>
17
20
  </template>
18
21
 
@@ -26,9 +29,20 @@ const props = defineProps({
26
29
  label: { type: String, default: undefined },
27
30
  /** The design's tag chips (pass IDs, role names) carry no leading dot. */
28
31
  dot: { type: Boolean, default: true },
32
+ /**
33
+ * For the chips that are not a status WORD at all - a countdown, a rating, a
34
+ * count - where the screen has already worked out the meaning and only needs
35
+ * the design's tone. Given, it wins over the word mapping.
36
+ */
37
+ tone: {
38
+ type: String as PropType<"ok" | "warn" | "err" | "info" | "neutral" | "">,
39
+ default: "",
40
+ },
29
41
  });
30
42
 
31
- const toneClass = computed(() => statusToneClass(props.status));
43
+ const toneClass = computed(() =>
44
+ props.tone ? `tone-${props.tone}` : statusToneClass(props.status)
45
+ );
32
46
  </script>
33
47
 
34
48
  <style scoped>