@7365admin1/layer-common 3.0.21 → 3.0.23
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/CHANGELOG.md +12 -0
- package/components/DashboardMain.vue +211 -58
- package/components/InvitationMain.vue +32 -3
- package/components/MemberMain.vue +1 -1
- package/components/Nfc/NFCPatrolReportMain.vue +48 -541
- package/components/Nfc/PatrolReport/DailyReportTab.vue +59 -0
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +59 -0
- package/components/Nfc/PatrolReport/PatrolActivityTable.vue +81 -0
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +73 -0
- package/components/Nfc/PatrolReport/PatrolRouteSummary.vue +63 -0
- package/components/Nfc/PatrolReport/RemarksDialog.vue +37 -0
- package/components/Nfc/PatrolReport/ReportEmptyState.vue +24 -0
- package/components/Nfc/PatrolReport/ReportFilters.vue +88 -0
- package/components/Nfc/PatrolReport/ReportLocationHeader.vue +17 -0
- package/components/Nfc/PatrolReport/SummaryReportTable.vue +51 -0
- package/components/ScheduleTaskMain.vue +47 -12
- package/components/ServiceProviderMain.vue +182 -184
- package/components/UnitMain.vue +8 -1
- package/components/VisitorForm.vue +2 -0
- package/components/VisitorManagement.vue +31 -0
- package/components/VisitorSocketPopUp.vue +292 -0
- package/composables/useNFCPatrolDailyReport.ts +27 -0
- package/composables/useNFCPatrolMonthlyReport.ts +27 -0
- package/composables/useNFCPatrolReport.ts +38 -0
- package/composables/useNFCPatrolReportExport.ts +31 -0
- package/composables/useNFCPatrolReportFilters.ts +39 -0
- package/composables/useVisitor.ts +3 -0
- package/composables/useVisitorSocket.ts +25 -0
- package/package.json +2 -1
- package/services/nfcPatrolReport.ts +172 -0
- package/types/nfc-patrol-report.ts +73 -0
- package/types/verification.d.ts +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -350,6 +350,15 @@
|
|
|
350
350
|
</v-list-item>
|
|
351
351
|
</v-list>
|
|
352
352
|
</v-menu>
|
|
353
|
+
|
|
354
|
+
<button
|
|
355
|
+
v-if="card.key === 'facilityBookings'"
|
|
356
|
+
class="figma-panel-action"
|
|
357
|
+
type="button"
|
|
358
|
+
@click="openFacilityBookingDialog"
|
|
359
|
+
>
|
|
360
|
+
View All
|
|
361
|
+
</button>
|
|
353
362
|
</div>
|
|
354
363
|
|
|
355
364
|
<div class="mt-6 w-100">
|
|
@@ -824,7 +833,6 @@
|
|
|
824
833
|
<div class="dashboard-card dashboard-panel figma-panel">
|
|
825
834
|
<div class="figma-panel-header">
|
|
826
835
|
<h2>Today's Attentions</h2>
|
|
827
|
-
|
|
828
836
|
</div>
|
|
829
837
|
<div class="figma-panel-body">
|
|
830
838
|
<div v-if="todayAttentions.length" class="figma-list">
|
|
@@ -1318,6 +1326,57 @@
|
|
|
1318
1326
|
</v-card>
|
|
1319
1327
|
</v-dialog>
|
|
1320
1328
|
|
|
1329
|
+
<v-dialog
|
|
1330
|
+
v-model="facilityBookingDialog"
|
|
1331
|
+
max-width="650"
|
|
1332
|
+
persistent
|
|
1333
|
+
scrollable
|
|
1334
|
+
>
|
|
1335
|
+
<v-card rounded="lg" class="facility-booking-modal">
|
|
1336
|
+
<v-card-title
|
|
1337
|
+
class="d-flex align-center justify-space-between pa-6 pb-3"
|
|
1338
|
+
>
|
|
1339
|
+
<div class="text-body-1 font-weight-black text-blue-grey-darken-4">
|
|
1340
|
+
Facility Booking
|
|
1341
|
+
</div>
|
|
1342
|
+
<v-btn
|
|
1343
|
+
icon="mdi-close"
|
|
1344
|
+
variant="text"
|
|
1345
|
+
density="comfortable"
|
|
1346
|
+
aria-label="Close facility booking summary"
|
|
1347
|
+
@click="facilityBookingDialog = false"
|
|
1348
|
+
/>
|
|
1349
|
+
</v-card-title>
|
|
1350
|
+
|
|
1351
|
+
<v-card-text class="px-6 pb-6 pt-3">
|
|
1352
|
+
<div class="facility-booking-summary-list">
|
|
1353
|
+
<div
|
|
1354
|
+
v-for="item in facilityBookingBreakdown"
|
|
1355
|
+
:key="item.status"
|
|
1356
|
+
class="facility-booking-summary-row"
|
|
1357
|
+
>
|
|
1358
|
+
<span class="facility-booking-summary-label">
|
|
1359
|
+
{{ item.status }}
|
|
1360
|
+
</span>
|
|
1361
|
+
<span class="facility-booking-summary-dots" />
|
|
1362
|
+
<strong class="facility-booking-summary-value">
|
|
1363
|
+
{{ formatNumber(item.count) }}
|
|
1364
|
+
</strong>
|
|
1365
|
+
</div>
|
|
1366
|
+
</div>
|
|
1367
|
+
|
|
1368
|
+
<v-divider class="my-5" />
|
|
1369
|
+
|
|
1370
|
+
<div class="facility-booking-summary-row facility-booking-total-row">
|
|
1371
|
+
<strong class="facility-booking-total-label">Total</strong>
|
|
1372
|
+
<strong class="facility-booking-summary-value">
|
|
1373
|
+
{{ formatNumber(facilityBookingTotal) }}
|
|
1374
|
+
</strong>
|
|
1375
|
+
</div>
|
|
1376
|
+
</v-card-text>
|
|
1377
|
+
</v-card>
|
|
1378
|
+
</v-dialog>
|
|
1379
|
+
|
|
1321
1380
|
<v-snackbar
|
|
1322
1381
|
v-model="snackbar.visible"
|
|
1323
1382
|
:timeout="2200"
|
|
@@ -1347,6 +1406,8 @@ type DashboardMetric = {
|
|
|
1347
1406
|
outOfStock?: number;
|
|
1348
1407
|
completed?: number;
|
|
1349
1408
|
total?: number;
|
|
1409
|
+
byStatus?: Record<string, number>;
|
|
1410
|
+
statusCounts?: Record<string, number>;
|
|
1350
1411
|
items?: { name: string; qty: number }[];
|
|
1351
1412
|
};
|
|
1352
1413
|
|
|
@@ -1558,7 +1619,7 @@ const initialPeriod = (
|
|
|
1558
1619
|
) as TDashboardValues;
|
|
1559
1620
|
const selectedRange = ref(periodLabelValue[initialPeriod]);
|
|
1560
1621
|
const visitorType = ref("All");
|
|
1561
|
-
const
|
|
1622
|
+
const facilityBookingDialog = ref(false);
|
|
1562
1623
|
const visibleWidgetKeys = ref<string[]>([]);
|
|
1563
1624
|
const draftVisibleWidgetKeys = ref<string[]>([]);
|
|
1564
1625
|
const filterMenus = reactive<Record<string, boolean>>({});
|
|
@@ -2190,7 +2251,6 @@ const visitorOptions = computed(() =>
|
|
|
2190
2251
|
)
|
|
2191
2252
|
);
|
|
2192
2253
|
|
|
2193
|
-
// Property-specific: facility booking metric with client-side filter
|
|
2194
2254
|
const facilityBookingItems = computed(() =>
|
|
2195
2255
|
getDashboardArray([
|
|
2196
2256
|
"facilityBookingItems",
|
|
@@ -2198,20 +2258,47 @@ const facilityBookingItems = computed(() =>
|
|
|
2198
2258
|
"bookingsList",
|
|
2199
2259
|
])
|
|
2200
2260
|
);
|
|
2201
|
-
|
|
2202
|
-
const
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2261
|
+
|
|
2262
|
+
const facilityBookingStatuses = [
|
|
2263
|
+
"Pending",
|
|
2264
|
+
"Approved",
|
|
2265
|
+
"Ongoing",
|
|
2266
|
+
"For Review",
|
|
2267
|
+
"With Balance",
|
|
2268
|
+
"With Refund",
|
|
2269
|
+
"Completed",
|
|
2270
|
+
"Rejected",
|
|
2271
|
+
"Cancelled",
|
|
2272
|
+
];
|
|
2273
|
+
|
|
2274
|
+
const facilityBookingBreakdown = computed(() => {
|
|
2275
|
+
const metric = getMetric(["facilityBooking", "facilityBookings", "bookings"]);
|
|
2276
|
+
const sourceCounts = metric.byStatus ?? metric.statusCounts ?? {};
|
|
2277
|
+
const itemCounts: Record<string, number> = {};
|
|
2278
|
+
facilityBookingItems.value.forEach((item: any) => {
|
|
2279
|
+
const status = normalizeFacilityBookingStatus(item.status);
|
|
2280
|
+
if (status) itemCounts[status] = (itemCounts[status] || 0) + 1;
|
|
2281
|
+
});
|
|
2282
|
+
|
|
2283
|
+
return facilityBookingStatuses.map((status) => ({
|
|
2284
|
+
status,
|
|
2285
|
+
count: toNumber(sourceCounts[status] ?? itemCounts[status]),
|
|
2286
|
+
}));
|
|
2287
|
+
});
|
|
2288
|
+
|
|
2289
|
+
const facilityBookingTotal = computed(() =>
|
|
2290
|
+
facilityBookingBreakdown.value.reduce((total, item) => total + item.count, 0)
|
|
2213
2291
|
);
|
|
2214
2292
|
|
|
2293
|
+
function openFacilityBookingDialog() {
|
|
2294
|
+
facilityBookingDialog.value = true;
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
function normalizeFacilityBookingStatus(status: unknown) {
|
|
2298
|
+
const value = String(status || "").trim();
|
|
2299
|
+
return value === "For Refund" ? "With Refund" : value;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2215
2302
|
function getPropertyKpiCards() {
|
|
2216
2303
|
const workOrderMetric = getMetric([
|
|
2217
2304
|
"openWorkOrder",
|
|
@@ -2281,53 +2368,13 @@ function getPropertyKpiCards() {
|
|
|
2281
2368
|
percentage: toNumber(facilityMetric?.percentage),
|
|
2282
2369
|
meta: getMetricMeta(facilityMetric),
|
|
2283
2370
|
raw: facilityMetric,
|
|
2284
|
-
filter:
|
|
2285
|
-
model: facilityType.value,
|
|
2286
|
-
options: facilityOptions.value,
|
|
2287
|
-
set: (v: string) => {
|
|
2288
|
-
facilityType.value = v;
|
|
2289
|
-
filterMenus.facilityBookings = false;
|
|
2290
|
-
},
|
|
2291
|
-
},
|
|
2371
|
+
filter: undefined,
|
|
2292
2372
|
},
|
|
2293
2373
|
];
|
|
2294
2374
|
}
|
|
2295
2375
|
|
|
2296
2376
|
function computeFacilityMetric(): DashboardMetric {
|
|
2297
|
-
|
|
2298
|
-
const selected = facilityType.value;
|
|
2299
|
-
if (selected === "All") return metric;
|
|
2300
|
-
const items = facilityBookingItems.value.filter((item: any) => {
|
|
2301
|
-
const val = String(
|
|
2302
|
-
item.facilityName ||
|
|
2303
|
-
item.facility?.name ||
|
|
2304
|
-
item.facilityInfo?.name ||
|
|
2305
|
-
item.name ||
|
|
2306
|
-
""
|
|
2307
|
-
).toLowerCase();
|
|
2308
|
-
return val === selected.toLowerCase();
|
|
2309
|
-
});
|
|
2310
|
-
const ongoing = items.filter((i: any) => {
|
|
2311
|
-
const s = String(i.status || "").toLowerCase();
|
|
2312
|
-
return (
|
|
2313
|
-
s.includes("ongoing") ||
|
|
2314
|
-
s.includes("approved") ||
|
|
2315
|
-
s.includes("in-progress")
|
|
2316
|
-
);
|
|
2317
|
-
}).length;
|
|
2318
|
-
const waitingApproval = items.filter((i: any) => {
|
|
2319
|
-
const s = String(i.status || "").toLowerCase();
|
|
2320
|
-
return (
|
|
2321
|
-
s.includes("pending") || s.includes("review") || s.includes("approval")
|
|
2322
|
-
);
|
|
2323
|
-
}).length;
|
|
2324
|
-
|
|
2325
|
-
return {
|
|
2326
|
-
...metric,
|
|
2327
|
-
count: ongoing + waitingApproval,
|
|
2328
|
-
ongoing,
|
|
2329
|
-
waitingApproval,
|
|
2330
|
-
};
|
|
2377
|
+
return getMetric(["facilityBooking", "facilityBookings", "bookings"]);
|
|
2331
2378
|
}
|
|
2332
2379
|
|
|
2333
2380
|
function getSecurityKpiCards() {
|
|
@@ -2472,7 +2519,14 @@ const primaryListConfig = computed(() =>
|
|
|
2472
2519
|
const activityTitle = computed(() => {
|
|
2473
2520
|
if (selectedRange.value === "Today") return "Today's Activity";
|
|
2474
2521
|
if (selectedRange.value === "This Month") return "This Month Activity";
|
|
2475
|
-
return
|
|
2522
|
+
return `This Week Activity (${currentWeekRangeLabel.value})`;
|
|
2523
|
+
});
|
|
2524
|
+
|
|
2525
|
+
const currentWeekRangeLabel = computed(() => {
|
|
2526
|
+
const today = new Date();
|
|
2527
|
+
const start = getMondayWeekStart(today);
|
|
2528
|
+
const end = addDays(start, 6);
|
|
2529
|
+
return `Week ${getWeekOfMonth(today)}: ${formatWeekRange(start, end)}`;
|
|
2476
2530
|
});
|
|
2477
2531
|
|
|
2478
2532
|
const activityChart = computed(() =>
|
|
@@ -2509,6 +2563,50 @@ const hasChartData = computed(
|
|
|
2509
2563
|
);
|
|
2510
2564
|
const chartTicks = [28, 66.4, 104.8, 143.2, 181.6, 220];
|
|
2511
2565
|
|
|
2566
|
+
function getMondayWeekStart(date: Date) {
|
|
2567
|
+
const start = new Date(date);
|
|
2568
|
+
start.setHours(0, 0, 0, 0);
|
|
2569
|
+
start.setDate(start.getDate() - ((start.getDay() + 6) % 7));
|
|
2570
|
+
return start;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
function addDays(date: Date, days: number) {
|
|
2574
|
+
const next = new Date(date);
|
|
2575
|
+
next.setDate(next.getDate() + days);
|
|
2576
|
+
return next;
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
function getWeekOfMonth(date: Date) {
|
|
2580
|
+
const monthStart = new Date(date.getFullYear(), date.getMonth(), 1);
|
|
2581
|
+
const firstWeekStart = getMondayWeekStart(monthStart);
|
|
2582
|
+
const currentWeekStart = getMondayWeekStart(date);
|
|
2583
|
+
const diffMs = currentWeekStart.getTime() - firstWeekStart.getTime();
|
|
2584
|
+
return Math.floor(diffMs / (7 * 24 * 60 * 60 * 1000)) + 1;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
function formatWeekRange(start: Date, end: Date) {
|
|
2588
|
+
const sameMonth = start.getMonth() === end.getMonth();
|
|
2589
|
+
const sameYear = start.getFullYear() === end.getFullYear();
|
|
2590
|
+
const monthDayFormatter = new Intl.DateTimeFormat("en-US", {
|
|
2591
|
+
month: "long",
|
|
2592
|
+
day: "numeric",
|
|
2593
|
+
});
|
|
2594
|
+
const dayFormatter = new Intl.DateTimeFormat("en-US", { day: "numeric" });
|
|
2595
|
+
const fullFormatter = new Intl.DateTimeFormat("en-US", {
|
|
2596
|
+
month: "long",
|
|
2597
|
+
day: "numeric",
|
|
2598
|
+
year: "numeric",
|
|
2599
|
+
});
|
|
2600
|
+
|
|
2601
|
+
if (sameMonth && sameYear) {
|
|
2602
|
+
return `${monthDayFormatter.format(start)} - ${dayFormatter.format(
|
|
2603
|
+
end
|
|
2604
|
+
)}, ${end.getFullYear()}`;
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
return `${fullFormatter.format(start)} - ${fullFormatter.format(end)}`;
|
|
2608
|
+
}
|
|
2609
|
+
|
|
2512
2610
|
const chartYLabels = computed(() => {
|
|
2513
2611
|
const max = chartMax.value;
|
|
2514
2612
|
return [
|
|
@@ -4107,6 +4205,54 @@ function formatDashboardTime(value?: string) {
|
|
|
4107
4205
|
white-space: nowrap;
|
|
4108
4206
|
}
|
|
4109
4207
|
|
|
4208
|
+
.facility-booking-modal {
|
|
4209
|
+
border: 1px solid #d9e0e7;
|
|
4210
|
+
box-shadow: 0 18px 48px rgba(15, 35, 54, 0.18);
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
.facility-booking-summary-list {
|
|
4214
|
+
display: grid;
|
|
4215
|
+
gap: 24px;
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
.facility-booking-summary-row {
|
|
4219
|
+
align-items: center;
|
|
4220
|
+
display: grid;
|
|
4221
|
+
gap: 16px;
|
|
4222
|
+
grid-template-columns: minmax(112px, max-content) minmax(40px, 1fr) minmax(
|
|
4223
|
+
32px,
|
|
4224
|
+
max-content
|
|
4225
|
+
);
|
|
4226
|
+
min-height: 22px;
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4229
|
+
.facility-booking-summary-label {
|
|
4230
|
+
color: #1565c0;
|
|
4231
|
+
font-size: 16px;
|
|
4232
|
+
font-weight: 500;
|
|
4233
|
+
line-height: 1.25;
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4236
|
+
.facility-booking-summary-dots {
|
|
4237
|
+
border-bottom: 2px dotted #9aa3ad;
|
|
4238
|
+
display: block;
|
|
4239
|
+
height: 1px;
|
|
4240
|
+
min-width: 32px;
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
.facility-booking-summary-value,
|
|
4244
|
+
.facility-booking-total-label {
|
|
4245
|
+
color: #0b2f47;
|
|
4246
|
+
font-size: 16px;
|
|
4247
|
+
font-weight: 800;
|
|
4248
|
+
line-height: 1.25;
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
.facility-booking-total-row {
|
|
4252
|
+
grid-template-columns: minmax(112px, max-content) minmax(32px, max-content);
|
|
4253
|
+
justify-content: space-between;
|
|
4254
|
+
}
|
|
4255
|
+
|
|
4110
4256
|
.figma-panel-body {
|
|
4111
4257
|
flex: 1;
|
|
4112
4258
|
margin-top: 20px;
|
|
@@ -4209,18 +4355,22 @@ function formatDashboardTime(value?: string) {
|
|
|
4209
4355
|
background: #ffe0de;
|
|
4210
4356
|
color: #d72f2f;
|
|
4211
4357
|
}
|
|
4358
|
+
|
|
4212
4359
|
.figma-icon-badge-info {
|
|
4213
4360
|
background: #e8e2ff;
|
|
4214
4361
|
color: #6d4bd8;
|
|
4215
4362
|
}
|
|
4363
|
+
|
|
4216
4364
|
.figma-icon-badge-success {
|
|
4217
4365
|
background: #ddf7e6;
|
|
4218
4366
|
color: #229852;
|
|
4219
4367
|
}
|
|
4368
|
+
|
|
4220
4369
|
.figma-icon-badge-warning {
|
|
4221
4370
|
background: #ffeed4;
|
|
4222
4371
|
color: #c57916;
|
|
4223
4372
|
}
|
|
4373
|
+
|
|
4224
4374
|
.figma-icon-badge-neutral {
|
|
4225
4375
|
background: #edf2f6;
|
|
4226
4376
|
color: #607386;
|
|
@@ -4356,14 +4506,17 @@ function formatDashboardTime(value?: string) {
|
|
|
4356
4506
|
background: #72e3a1;
|
|
4357
4507
|
color: #0f5132;
|
|
4358
4508
|
}
|
|
4509
|
+
|
|
4359
4510
|
.feedback-status-pill-progress {
|
|
4360
4511
|
background: #fde68a;
|
|
4361
4512
|
color: #92400e;
|
|
4362
4513
|
}
|
|
4514
|
+
|
|
4363
4515
|
.feedback-status-pill-danger {
|
|
4364
4516
|
background: #fecaca;
|
|
4365
4517
|
color: #b91c1c;
|
|
4366
4518
|
}
|
|
4519
|
+
|
|
4367
4520
|
.feedback-status-pill-todo {
|
|
4368
4521
|
background: #e2e8f0;
|
|
4369
4522
|
color: #64748b;
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
v-if="props.cancelInvitation"
|
|
91
91
|
>
|
|
92
92
|
<template v-slot:activator="{ props }">
|
|
93
|
-
<v-icon v-bind="props">mdi-dots-
|
|
93
|
+
<v-icon v-bind="props">mdi-dots-vertical</v-icon>
|
|
94
94
|
</template>
|
|
95
95
|
<v-list>
|
|
96
96
|
<v-list-item @click="openConfirmDialog(item._id ?? '')" v-if="item.status === 'pending'">
|
|
@@ -99,6 +99,9 @@
|
|
|
99
99
|
</v-list>
|
|
100
100
|
</v-menu>
|
|
101
101
|
</template>
|
|
102
|
+
<template #item.status="{value}">
|
|
103
|
+
{{ formatStatus(value) }}
|
|
104
|
+
</template>
|
|
102
105
|
</v-data-table>
|
|
103
106
|
</v-card>
|
|
104
107
|
</v-col>
|
|
@@ -198,14 +201,27 @@ authenticate();
|
|
|
198
201
|
|
|
199
202
|
const headers = computed(() => {
|
|
200
203
|
const baseHeaders = [
|
|
204
|
+
{
|
|
205
|
+
title: "E-mail",
|
|
206
|
+
value: "email",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
title: "Roles and Permission",
|
|
210
|
+
value: "roleName",
|
|
211
|
+
},
|
|
201
212
|
{
|
|
202
213
|
title: "Date",
|
|
203
214
|
value: "createdAt",
|
|
204
215
|
},
|
|
205
216
|
{
|
|
206
|
-
title: "
|
|
207
|
-
value: "
|
|
217
|
+
title: "Site Invited To",
|
|
218
|
+
value: "metadata.siteName",
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
title: "Status",
|
|
222
|
+
value: "status",
|
|
208
223
|
},
|
|
224
|
+
|
|
209
225
|
];
|
|
210
226
|
|
|
211
227
|
if (props.status === "pending" && props.cancelInvitation) {
|
|
@@ -318,6 +334,19 @@ watchEffect(() => {
|
|
|
318
334
|
}
|
|
319
335
|
});
|
|
320
336
|
|
|
337
|
+
const formatStatus = (status: string) => {
|
|
338
|
+
switch (status) {
|
|
339
|
+
case "pending":
|
|
340
|
+
return "Pending Invite";
|
|
341
|
+
case "expired":
|
|
342
|
+
return "Invitation expired";
|
|
343
|
+
case "accepted":
|
|
344
|
+
return "Accepted";
|
|
345
|
+
default:
|
|
346
|
+
return status?.[0]?.toUpperCase() + status?.slice(1) || "";
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
321
350
|
const dialogMember = ref(false);
|
|
322
351
|
|
|
323
352
|
function inviteMember() {
|