@7365admin1/layer-common 3.2.7 → 3.2.8-staging.201
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/assets/css/primitives.css +1113 -0
- package/assets/css/screens.css +1097 -0
- package/assets/css/shell.css +258 -0
- package/assets/css/tokens.css +236 -0
- package/components/AcceptDialog.vue +17 -18
- package/components/AccessCard/AvailableStats.vue +24 -16
- package/components/AccessCardAddForm.vue +42 -42
- package/components/AccessCardAssignToUnitForm.vue +13 -21
- package/components/AccessCardDeleteDialog.vue +41 -39
- package/components/AccessCardDetailsDialog.vue +125 -79
- package/components/AccessCardPreviewDialog.vue +58 -84
- package/components/AccessCardQrTagging.vue +60 -63
- package/components/AccessCardReplaceForm.vue +27 -23
- package/components/AccessManagement.vue +86 -85
- package/components/AddEqupmentForm.vue +18 -22
- package/components/AddPassKeyToVisitor.vue +95 -73
- package/components/AppButton.vue +62 -0
- package/components/AppCard.vue +20 -0
- package/components/AppDateField.vue +49 -0
- package/components/AppField.vue +76 -0
- package/components/AppKpiTile.vue +65 -0
- package/components/AppSegmented.vue +38 -0
- package/components/AppSelect.vue +247 -0
- package/components/AreaChecklistHistoryLogs.vue +51 -44
- package/components/AreaChecklistHistoryMain.vue +14 -7
- package/components/AreaFormDialog.vue +71 -59
- package/components/AreaMain.vue +73 -107
- package/components/AttachmentsViewer.vue +84 -22
- package/components/AttendanceCheckInOutDialog.vue +85 -88
- package/components/AttendanceDetailsDialog.vue +57 -63
- package/components/AttendanceMain.vue +4 -3
- package/components/AttendanceMapSearchDialog.vue +42 -44
- package/components/AttendanceSettingsDialog.vue +79 -63
- package/components/Avatar/Main.vue +54 -2
- package/components/BillingMain.vue +26 -30
- package/components/BtnUploadFile.vue +53 -11
- package/components/BuildingForm.vue +34 -27
- package/components/BuildingManagement/buildings.vue +39 -39
- package/components/BuildingManagement/units.vue +26 -42
- package/components/BuildingUnitFormAdd.vue +20 -23
- package/components/BuildingUnitFormEdit.vue +8 -4
- package/components/BulletinBoardForm.vue +19 -24
- package/components/BulletinBoardManagement.vue +49 -57
- package/components/BulletinBoardView.vue +9 -6
- package/components/BulletinExpirationChip.vue +13 -4
- package/components/Button/Close.vue +2 -2
- package/components/CameraForm.vue +21 -22
- package/components/CameraMain.vue +50 -49
- package/components/Card/DeleteConfirmation.vue +24 -22
- package/components/Card/MemberInfoSummary.vue +28 -3
- package/components/Card/Toggle.vue +15 -3
- package/components/CardToolbar.vue +37 -0
- package/components/Carousel.vue +56 -36
- package/components/Chat/Bubbles.vue +43 -14
- package/components/Chat/Information.vue +49 -32
- package/components/Chat/ListCard.vue +38 -9
- package/components/Chat/Message.vue +41 -15
- package/components/Chat/Navigation.vue +27 -15
- package/components/Chat/SkeletonLoader.vue +9 -2
- package/components/ChecklistItemRow.vue +25 -1
- package/components/CleaningScheduleMain.vue +44 -49
- package/components/ClientDetailForm.vue +81 -56
- package/components/ClientMain.vue +92 -82
- package/components/ConfirmDialog.vue +14 -8
- package/components/Container/Standard.vue +9 -7
- package/components/CreateSubsciptionPlan.vue +148 -89
- package/components/DashboardEmptyState.vue +48 -3
- package/components/DashboardMain.vue +924 -676
- package/components/DashboardPanel.vue +84 -21
- package/components/DeliveryCompany.vue +34 -20
- package/components/Dialog/DeleteConfirmation.vue +20 -21
- package/components/Dialog/ReplaceAutofillPrompt.vue +19 -26
- package/components/Dialog/ReusablePrompt.vue +30 -29
- package/components/Dialog/UpdateMoreAction.vue +62 -59
- package/components/DocumentForm.vue +14 -21
- package/components/DocumentManagement.vue +162 -108
- package/components/DocumentViewer.vue +29 -12
- package/components/DrawImage.vue +29 -21
- package/components/EntryPass/QrTemplatePreview.vue +27 -16
- package/components/EntryPassInformation.vue +40 -10
- package/components/EntryPassMain.vue +49 -27
- package/components/EquipmentItemMain.vue +84 -97
- package/components/EquipmentManagementMain.vue +81 -103
- package/components/Facility/BookingSetup.vue +43 -52
- package/components/Feedback/Form.vue +26 -12
- package/components/FeedbackMain.vue +35 -49
- package/components/FileInput.vue +75 -58
- package/components/FileInputWithList.vue +59 -12
- package/components/FormDialog.vue +60 -21
- package/components/HidAccessLogDashboard.vue +512 -490
- package/components/HidCameraCaptureDialog.vue +216 -0
- package/components/HidEnabledGate.vue +67 -9
- package/components/HidIntercomManagement.vue +1322 -653
- package/components/HidQrCodeConfiguration.vue +1030 -258
- package/components/HidReaderForm.vue +142 -59
- package/components/HidReaderManagement.vue +211 -323
- package/components/HidServiceSettingsPanel.vue +44 -13
- package/components/HidUserEnrollment.vue +1185 -412
- package/components/HygieneUpdateMoreAction.vue +44 -44
- package/components/IncidentReport/Authorities.vue +30 -18
- package/components/IncidentReport/IncidentInformation.vue +10 -10
- package/components/IncidentReport/IncidentInformationDownload.vue +3 -4
- package/components/IncidentReport/affectedEntities.vue +41 -20
- package/components/Input/Date.vue +3 -0
- package/components/Input/DatePicker.vue +1 -2
- package/components/Input/DateTimePicker.vue +1 -1
- package/components/Input/File.vue +55 -10
- package/components/Input/FileV2.vue +39 -6
- package/components/Input/InputPhoneNumberV2.vue +2 -1
- package/components/Input/ListGroupSelection.vue +56 -8
- package/components/Input/NRICNumber.vue +1 -0
- package/components/Input/NewDate.vue +1 -0
- package/components/Input/Number.vue +1 -0
- package/components/Input/Password.vue +1 -0
- package/components/Input/PhoneNumber.vue +21 -1
- package/components/Input/VehicleNumber.vue +1 -0
- package/components/InputLabel.vue +2 -2
- package/components/InvitationClientForm.vue +21 -19
- package/components/InvitationForm.vue +15 -21
- package/components/InvitationMain.vue +46 -61
- package/components/Layout/Header.vue +263 -36
- package/components/Layout/NavigationDrawer.vue +300 -30
- package/components/ListItem.vue +33 -3
- package/components/LocalPagination.vue +27 -3
- package/components/ManageChecklistMain.vue +136 -86
- package/components/MemberInformation.vue +32 -16
- package/components/MemberMain.vue +113 -93
- package/components/MyAttendanceMain.vue +3 -5
- package/components/NavigationItem.vue +83 -3
- package/components/Nfc/NFCPatrolReportMain.vue +47 -33
- package/components/Nfc/NFCPatrolRouteForm.vue +18 -20
- package/components/Nfc/NFCPatrolRouteMain.vue +116 -103
- package/components/Nfc/NFCPatrolSettings.vue +14 -4
- package/components/Nfc/NFCTagForm.vue +22 -8
- package/components/Nfc/NFCTagMain.vue +41 -43
- package/components/Nfc/PatrolReport/DailyReportTab.vue +8 -1
- package/components/Nfc/PatrolReport/MonthlyReportTab.vue +8 -1
- package/components/Nfc/PatrolReport/MonthlyReportTable.vue +5 -3
- package/components/Nfc/PatrolReport/PatrolActivityTable.vue +26 -6
- package/components/Nfc/PatrolReport/PatrolReportTab.vue +8 -0
- package/components/Nfc/PatrolReport/PatrolRouteSummary.vue +41 -9
- package/components/Nfc/PatrolReport/RemarksDialog.vue +39 -9
- package/components/Nfc/PatrolReport/ReportEmptyState.vue +29 -9
- package/components/Nfc/PatrolReport/ReportFilters.vue +19 -10
- package/components/Nfc/PatrolReport/ReportLocationHeader.vue +32 -6
- package/components/Nfc/PatrolReport/SummaryReportTable.vue +28 -6
- package/components/NotificationSettings.vue +373 -0
- package/components/NumberSettingField.vue +9 -2
- package/components/OnlineFormConfigurationForm.vue +725 -237
- package/components/OnlineFormFill.vue +213 -106
- package/components/OnlineFormRenderPreview.vue +25 -30
- package/components/OnlineFormsConfiguration.vue +113 -109
- package/components/OrgViewDialog.vue +34 -16
- package/components/OvernightParkingAvailability.vue +49 -26
- package/components/OvernightParkingManagement.vue +78 -18
- package/components/PageHeader.vue +43 -0
- package/components/PassInformation.vue +109 -53
- package/components/PasswordConfirmation.vue +44 -26
- package/components/PeopleForm.vue +41 -20
- package/components/PhotoUpload.vue +110 -48
- package/components/PlaceholderComponent.vue +35 -19
- package/components/PlanActionsMenu.vue +12 -2
- package/components/PlanStatusBadge.vue +7 -8
- package/components/PlateNumberDisplay.vue +9 -6
- package/components/QrTemplate/PrintDialog.vue +66 -43
- package/components/RolePermissionFormCreate.vue +104 -79
- package/components/RolePermissionFormPreviewUpdate.vue +111 -109
- package/components/RolePermissionMain.vue +183 -81
- package/components/ScanVisitorQRCode.vue +99 -35
- package/components/ScheduleAreaMain.vue +34 -59
- package/components/ScheduleTaskForm.vue +61 -42
- package/components/ScheduleTaskMain.vue +56 -69
- package/components/SearchVehicleNumberUser.vue +39 -37
- package/components/ServiceProviderFormCreate.vue +29 -20
- package/components/ServiceProviderInvitationPrompt.vue +155 -0
- package/components/ServiceProviderMain.vue +601 -432
- package/components/Signature.vue +40 -34
- package/components/SignaturePad.vue +5 -29
- package/components/SiteSettings.vue +41 -11
- package/components/SiteSettingsWorkOrder.vue +61 -30
- package/components/SlideCardGroup.vue +35 -11
- package/components/Snackbar.vue +36 -3
- package/components/SpecificAttr.vue +18 -8
- package/components/StatusChip.vue +156 -0
- package/components/StockCard.vue +17 -12
- package/components/SubscriptionPlanTable.vue +207 -140
- package/components/SwitchContext.vue +201 -9
- package/components/TableHygiene.vue +36 -46
- package/components/TableList.vue +10 -10
- package/components/TableListSecondary.vue +105 -54
- package/components/TableMain.vue +251 -78
- package/components/TableV3.vue +61 -70
- package/components/TiptapEditor.vue +33 -40
- package/components/TiptapEditorQr.vue +5 -2
- package/components/Tooltip/Info.vue +69 -24
- package/components/UnitMain.vue +40 -60
- package/components/UnitPersonCard.vue +42 -13
- package/components/VehicleAddSelection.vue +48 -32
- package/components/VehicleForm.vue +112 -129
- package/components/VehicleManagement.vue +26 -12
- package/components/VehicleUpdateMoreAction.vue +59 -46
- package/components/VisitorDataFromScannedQRCodeForm.vue +90 -65
- package/components/VisitorForm.vue +774 -210
- package/components/VisitorFormSelection.vue +40 -37
- package/components/VisitorManagement.vue +239 -82
- package/components/VisitorPassKeyQRScanner.vue +65 -18
- package/components/VisitorSearchResultSummary.vue +60 -16
- package/components/VisitorSocketPopUp.vue +22 -14
- package/components/VisitorsReportPreview.vue +44 -29
- package/components/WorkOrder/Create.vue +26 -17
- package/components/WorkOrder/ListView.vue +38 -7
- package/components/WorkOrder/Main.vue +62 -59
- package/composables/useFeedback.ts +3 -3
- package/composables/useHidAmico.ts +269 -0
- package/composables/useHidNavigation.ts +2 -9
- package/composables/useMember.ts +3 -3
- package/composables/useNFCPatrolDailyReport.ts +13 -0
- package/composables/useNFCPatrolMonthlyReport.ts +22 -56
- package/composables/useNFCPatrolReport.ts +13 -0
- package/composables/useNotificationPreference.ts +87 -0
- package/composables/useOnlineFormPages.ts +2 -0
- package/composables/useRole.ts +22 -0
- package/composables/useServiceProvider.ts +3 -3
- package/composables/useServiceProviderInvitation.ts +145 -0
- package/composables/useSipWebPhone.ts +336 -0
- package/composables/useSubscriptionPlan.ts +62 -0
- package/composables/useThemePreference.ts +63 -0
- package/composables/useVisitor.ts +6 -1
- package/composables/useWebUsb.ts +127 -37
- package/composables/useWorkOrder.ts +17 -3
- package/error.vue +30 -6
- package/nuxt.config.ts +36 -0
- package/package.json +25 -4
- package/pages/[org]/[site]/access-mgmt/administrator/index.vue +2 -2
- package/pages/[org]/[site]/access-mgmt/{identity-mapping → hid-cards}/index.vue +2 -2
- package/pages/[org]/[site]/access-mgmt/intercom/index.vue +1 -1
- package/pages/notification-settings.vue +19 -0
- package/pages/payment-method-linked.vue +34 -10
- package/pages/require-customer.vue +48 -10
- package/pages/require-organization-membership.vue +32 -8
- package/pages/unauthorized.vue +29 -4
- package/plugins/secure-member.client.ts +21 -56
- package/plugins/vuetify.ts +69 -2
- package/types/nfc-patrol-report.ts +3 -2
- package/types/site.d.ts +71 -0
- package/types/subscription.ts +18 -11
- package/utils/breadcrumb.test.ts +108 -0
- package/utils/breadcrumb.ts +82 -0
- package/utils/dashboard.test.ts +118 -0
- package/utils/dashboard.ts +53 -0
- package/utils/data.test.ts +95 -0
- package/utils/data.ts +40 -2
- package/utils/hid-discover.test.ts +102 -0
- package/utils/list-page.test.ts +60 -0
- package/utils/list-page.ts +38 -0
- package/utils/materialSymbols.ts +363 -0
- package/utils/nav-sections.test.ts +190 -0
- package/utils/nav-sections.ts +151 -0
- package/utils/nfc-patrol-report.test.ts +130 -0
- package/utils/nfc-patrol-report.ts +101 -0
- package/utils/role.test.ts +69 -0
- package/utils/role.ts +10 -0
- package/utils/route-name.test.ts +85 -0
- package/utils/route-name.ts +24 -0
- package/utils/status.test.ts +110 -0
- package/utils/status.ts +135 -0
- package/utils/table-card.test.ts +84 -0
- package/utils/theme-aa-ledger.ts +148 -0
- package/utils/theme.test.ts +485 -7
- package/utils/theme.ts +295 -110
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.editorconfig +0 -12
- package/.github/workflows/main.yml +0 -17
- package/.github/workflows/publish-staging.yml +0 -47
- package/.github/workflows/publish.yml +0 -39
- package/PUBLISHING.md +0 -269
- package/components/HidIdentityMapping.vue +0 -975
- package/components/ScheduleTaskAreaFormDialog.vue +0 -144
- package/components/ScheduleTaskAreaUpdateMoreAction.vue +0 -109
- package/components/ScheduleTastTicketMain.vue +0 -182
- package/components/TableWithButton.vue +0 -94
- package/test/visitor-socket.test.mjs +0 -36
|
@@ -1,88 +1,80 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
3
|
<v-col cols="12">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class="text-none px-8"
|
|
4
|
+
<!-- Title row; nav calls this screen "Routes". The Add pill moves onto it
|
|
5
|
+
and the search onto the card's toolbar, where the design draws them. -->
|
|
6
|
+
<PageHeader title="Routes">
|
|
7
|
+
<template #actions>
|
|
8
|
+
<AppButton
|
|
9
|
+
v-if="props.canCreateNfcPatrol"
|
|
10
|
+
icon="mdi-plus"
|
|
12
11
|
@click="dialogAdd = true"
|
|
13
12
|
>
|
|
14
13
|
Add Route
|
|
15
|
-
</
|
|
16
|
-
</
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
</AppButton>
|
|
15
|
+
</template>
|
|
16
|
+
</PageHeader>
|
|
17
|
+
|
|
18
|
+
<!--
|
|
19
|
+
Was `v-card` + `v-data-table` + a `grey-lighten-4` `v-toolbar` BELOW the
|
|
20
|
+
table holding the page range and pager (a white slab that stayed white in
|
|
21
|
+
dark mode). `TableMain` draws the same card with that row on top, which
|
|
22
|
+
is where the design puts it. Same headers, items, page size, row click
|
|
23
|
+
and item slots; the refresh button is wired to the refresh this screen
|
|
24
|
+
already calls after add/edit.
|
|
25
|
+
-->
|
|
26
|
+
<TableMain
|
|
27
|
+
:headers="headers"
|
|
28
|
+
:items="items"
|
|
29
|
+
:page="page"
|
|
30
|
+
:pages="pages"
|
|
31
|
+
:pageRange="pageRange"
|
|
32
|
+
show-header
|
|
33
|
+
@refresh="getRoutesRefresh()"
|
|
34
|
+
@update:page="page = $event"
|
|
35
|
+
@row-click="(data: any) => handleRowClick(null, data)"
|
|
36
|
+
>
|
|
37
|
+
<template #prepend-additional>
|
|
38
|
+
<AppField
|
|
19
39
|
v-model="searchInput"
|
|
20
|
-
|
|
40
|
+
search
|
|
41
|
+
compact
|
|
21
42
|
placeholder="Search"
|
|
22
|
-
|
|
23
|
-
append-inner-icon="mdi-magnify"
|
|
24
|
-
hide-details
|
|
25
|
-
variant="outlined"
|
|
26
|
-
rounded="lg"
|
|
27
|
-
style="max-width: 400px"
|
|
28
|
-
bg-color="white"
|
|
43
|
+
klass="app-toolbar__search"
|
|
29
44
|
/>
|
|
30
|
-
</
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
>
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
<div class="text-grey">{{ item.totalTravelTime ? `${item.totalTravelTime} mins` : "--" }}</div>
|
|
55
|
-
</div>
|
|
56
|
-
</template>
|
|
57
|
-
|
|
58
|
-
<template #item.schedules="{ value }">
|
|
59
|
-
<span v-if="Array.isArray(value) && value.length > 0">
|
|
60
|
-
{{ value.map(s => `${s.start}-${s.end}`).join(", ") }}
|
|
61
|
-
</span>
|
|
62
|
-
<span v-else>--</span>
|
|
63
|
-
</template>
|
|
64
|
-
|
|
65
|
-
<template #item.repeatDays="{ value }">
|
|
66
|
-
<span>{{ value || "--" }} </span>
|
|
67
|
-
</template>
|
|
68
|
-
</v-data-table>
|
|
69
|
-
</v-card-text>
|
|
70
|
-
|
|
71
|
-
<v-toolbar density="compact" color="grey-lighten-4">
|
|
72
|
-
<template #append>
|
|
73
|
-
<v-row no-gutters justify="end" align="center">
|
|
74
|
-
<span class="mr-2 text-caption text-fontgray">
|
|
75
|
-
{{ pageRange }}
|
|
76
|
-
</span>
|
|
77
|
-
<local-pagination v-model="page" :length="pages" />
|
|
78
|
-
</v-row>
|
|
79
|
-
</template>
|
|
80
|
-
</v-toolbar>
|
|
81
|
-
</v-card>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<template #item.numberOfCheckpoints="{ value }">
|
|
48
|
+
<div class="text-center">{{ value || "--" }}</div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<template #item.tolerance="{ item }">
|
|
52
|
+
<div class="text-center">
|
|
53
|
+
<div>{{ item.tolerance ? `${item.tolerance} mins` : "--" }}</div>
|
|
54
|
+
<div class="text-grey">{{ item.totalTravelTime ? `${item.totalTravelTime} mins` : "--" }}</div>
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<template #item.schedules="{ value }">
|
|
59
|
+
<span v-if="Array.isArray(value) && value.length > 0">
|
|
60
|
+
{{ value.map((s: any) => `${s.start}-${s.end}`).join(", ") }}
|
|
61
|
+
</span>
|
|
62
|
+
<span v-else>--</span>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<template #item.repeatDays="{ value }">
|
|
66
|
+
<span>{{ value || "--" }} </span>
|
|
67
|
+
</template>
|
|
68
|
+
</TableMain>
|
|
82
69
|
</v-col>
|
|
83
70
|
|
|
84
71
|
<!-- Add Dialog -->
|
|
85
|
-
<v-dialog
|
|
72
|
+
<v-dialog
|
|
73
|
+
v-if="props.canCreateNfcPatrol"
|
|
74
|
+
v-model="dialogAdd"
|
|
75
|
+
persistent
|
|
76
|
+
max-width="900"
|
|
77
|
+
>
|
|
86
78
|
<NFCPatrolRouteForm
|
|
87
79
|
title="Add Route"
|
|
88
80
|
:site="props.site"
|
|
@@ -94,7 +86,12 @@
|
|
|
94
86
|
</v-dialog>
|
|
95
87
|
|
|
96
88
|
<!-- Edit Dialog -->
|
|
97
|
-
<v-dialog
|
|
89
|
+
<v-dialog
|
|
90
|
+
v-if="props.canUpdateNfcPatrol"
|
|
91
|
+
v-model="dialogEdit"
|
|
92
|
+
persistent
|
|
93
|
+
max-width="900"
|
|
94
|
+
>
|
|
98
95
|
<NFCPatrolRouteForm
|
|
99
96
|
title="Edit Route"
|
|
100
97
|
:site="props.site"
|
|
@@ -190,7 +187,10 @@
|
|
|
190
187
|
|
|
191
188
|
<v-toolbar class="pa-0" density="compact">
|
|
192
189
|
<v-row no-gutters>
|
|
193
|
-
<v-col
|
|
190
|
+
<v-col
|
|
191
|
+
:cols="props.canUpdateNfcPatrol || props.canDeleteNfcPatrol ? 6 : 12"
|
|
192
|
+
class="pa-0"
|
|
193
|
+
>
|
|
194
194
|
<v-btn
|
|
195
195
|
block
|
|
196
196
|
variant="text"
|
|
@@ -203,7 +203,11 @@
|
|
|
203
203
|
</v-btn>
|
|
204
204
|
</v-col>
|
|
205
205
|
|
|
206
|
-
<v-col
|
|
206
|
+
<v-col
|
|
207
|
+
v-if="props.canUpdateNfcPatrol || props.canDeleteNfcPatrol"
|
|
208
|
+
cols="6"
|
|
209
|
+
class="pa-0"
|
|
210
|
+
>
|
|
207
211
|
<v-menu>
|
|
208
212
|
<template #activator="{ props }">
|
|
209
213
|
<v-btn
|
|
@@ -220,13 +224,17 @@
|
|
|
220
224
|
</template>
|
|
221
225
|
|
|
222
226
|
<v-list class="pa-0">
|
|
223
|
-
<v-list-item @click="openDialogEdit()">
|
|
227
|
+
<v-list-item v-if="props.canUpdateNfcPatrol" @click="openDialogEdit()">
|
|
224
228
|
<v-list-item-title class="text-subtitle-2">
|
|
225
229
|
Edit Route
|
|
226
230
|
</v-list-item-title>
|
|
227
231
|
</v-list-item>
|
|
228
232
|
|
|
229
|
-
<v-list-item
|
|
233
|
+
<v-list-item
|
|
234
|
+
v-if="props.canDeleteNfcPatrol"
|
|
235
|
+
@click="openDialogDelete()"
|
|
236
|
+
class="text-red"
|
|
237
|
+
>
|
|
230
238
|
<v-list-item-title class="text-subtitle-2">
|
|
231
239
|
Delete Route
|
|
232
240
|
</v-list-item-title>
|
|
@@ -240,7 +248,12 @@
|
|
|
240
248
|
</v-dialog>
|
|
241
249
|
|
|
242
250
|
<!-- Delete Dialog -->
|
|
243
|
-
<v-dialog
|
|
251
|
+
<v-dialog
|
|
252
|
+
v-if="props.canDeleteNfcPatrol"
|
|
253
|
+
v-model="dialogDelete"
|
|
254
|
+
persistent
|
|
255
|
+
width="540"
|
|
256
|
+
>
|
|
244
257
|
<v-card width="100%">
|
|
245
258
|
<v-card-text
|
|
246
259
|
style="max-height: 100vh; overflow-y: auto"
|
|
@@ -304,6 +317,18 @@ const props = defineProps({
|
|
|
304
317
|
type: String,
|
|
305
318
|
required: true,
|
|
306
319
|
},
|
|
320
|
+
canCreateNfcPatrol: {
|
|
321
|
+
type: Boolean,
|
|
322
|
+
default: false,
|
|
323
|
+
},
|
|
324
|
+
canUpdateNfcPatrol: {
|
|
325
|
+
type: Boolean,
|
|
326
|
+
default: false,
|
|
327
|
+
},
|
|
328
|
+
canDeleteNfcPatrol: {
|
|
329
|
+
type: Boolean,
|
|
330
|
+
default: false,
|
|
331
|
+
},
|
|
307
332
|
headers: {
|
|
308
333
|
type: Array as PropType<Array<any>>,
|
|
309
334
|
default: () => [
|
|
@@ -406,6 +431,8 @@ const messageSnackbar = ref(false);
|
|
|
406
431
|
const messageColor = ref("");
|
|
407
432
|
|
|
408
433
|
async function openDialogEdit() {
|
|
434
|
+
if (!props.canUpdateNfcPatrol) return;
|
|
435
|
+
|
|
409
436
|
try {
|
|
410
437
|
// Fetch the full route details from the API
|
|
411
438
|
const response = await getRouteById(selectedRoute.value._id);
|
|
@@ -431,6 +458,8 @@ async function openDialogEdit() {
|
|
|
431
458
|
}
|
|
432
459
|
|
|
433
460
|
function openDialogDelete() {
|
|
461
|
+
if (!props.canDeleteNfcPatrol) return;
|
|
462
|
+
|
|
434
463
|
dialogDelete.value = true;
|
|
435
464
|
|
|
436
465
|
if (dialogPreview.value) dialogPreview.value = false;
|
|
@@ -502,6 +531,8 @@ function handleRowClick(_: any, data: any) {
|
|
|
502
531
|
}
|
|
503
532
|
|
|
504
533
|
async function submitDelete() {
|
|
534
|
+
if (!props.canDeleteNfcPatrol) return;
|
|
535
|
+
|
|
505
536
|
try {
|
|
506
537
|
await deleteRouteById(selectedRoute.value._id ?? "");
|
|
507
538
|
await getRoutesRefresh();
|
|
@@ -513,27 +544,9 @@ async function submitDelete() {
|
|
|
513
544
|
}
|
|
514
545
|
}
|
|
515
546
|
</script>
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
padding: 16px 12px !important;
|
|
523
|
-
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
.nfc-route-table :deep(.v-data-table__td) {
|
|
527
|
-
padding: 16px 12px !important;
|
|
528
|
-
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
.nfc-route-table :deep(tbody tr:hover) {
|
|
532
|
-
background-color: rgba(0, 0, 0, 0.02) !important;
|
|
533
|
-
cursor: pointer;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
.nfc-route-table :deep(.v-data-table__tr) {
|
|
537
|
-
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
|
538
|
-
}
|
|
539
|
-
</style>
|
|
547
|
+
<!--
|
|
548
|
+
The screen's own table CSS is gone with the `v-data-table` it styled: it
|
|
549
|
+
hardcoded an `rgb(250,250,250)` header fill and black-alpha borders, which
|
|
550
|
+
stay light in dark mode. `TableMain` draws the design's header row and
|
|
551
|
+
borders from the theme tokens instead.
|
|
552
|
+
-->
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
3
|
<v-col cols="12">
|
|
4
|
-
|
|
4
|
+
<!--
|
|
5
|
+
`AppCard` for the outlined card. This mounts inside PM `settings.vue`'s
|
|
6
|
+
"NFC Patrol Settings" expansion panel, which already draws that
|
|
7
|
+
heading - so NO `PageHeader`, or the panel would name itself twice.
|
|
8
|
+
-->
|
|
9
|
+
<AppCard>
|
|
5
10
|
<v-row no-gutters class="pa-6" align="center">
|
|
6
11
|
<v-col cols="12" md="7" class="pr-md-8">
|
|
7
12
|
<div class="text-subtitle-1 font-weight-medium">
|
|
@@ -36,10 +41,15 @@
|
|
|
36
41
|
|
|
37
42
|
<v-row no-gutters class="pa-6 pt-0">
|
|
38
43
|
<v-col cols="12" class="d-flex justify-end">
|
|
44
|
+
<!--
|
|
45
|
+
Stays a `v-btn`: `AppButton` has no `loading`, and dropping the
|
|
46
|
+
spinner would lose the only signal this save is in flight. The
|
|
47
|
+
design's fill comes from `.screen-btn-primary` instead of
|
|
48
|
+
Vuetify's `color="primary"` - same click, same `loading` gate.
|
|
49
|
+
-->
|
|
39
50
|
<v-btn
|
|
40
51
|
text="Save"
|
|
41
|
-
|
|
42
|
-
class="text-none"
|
|
52
|
+
class="screen-btn-primary"
|
|
43
53
|
size="large"
|
|
44
54
|
variant="flat"
|
|
45
55
|
@click="submit"
|
|
@@ -47,7 +57,7 @@
|
|
|
47
57
|
/>
|
|
48
58
|
</v-col>
|
|
49
59
|
</v-row>
|
|
50
|
-
</
|
|
60
|
+
</AppCard>
|
|
51
61
|
</v-col>
|
|
52
62
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
53
63
|
</v-row>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-card width="100%">
|
|
3
|
-
<v-toolbar>
|
|
3
|
+
<v-toolbar class="screen-dialog-bar">
|
|
4
4
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
-
<span class="
|
|
5
|
+
<span class="screen-card-title text-capitalize">
|
|
6
6
|
{{ title }}
|
|
7
7
|
</span>
|
|
8
8
|
</v-row>
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
<v-form ref="formRef" v-model="valid" @submit.prevent="submit">
|
|
16
16
|
<v-row no-gutters>
|
|
17
17
|
<v-col cols="12" class="mb-4">
|
|
18
|
-
<label class="
|
|
19
|
-
Name <span class="text-
|
|
18
|
+
<label class="nfc-tag__label mb-2">
|
|
19
|
+
Name <span class="text-error">*</span>
|
|
20
20
|
</label>
|
|
21
21
|
<v-text-field
|
|
22
22
|
v-model="form.name"
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
</v-col>
|
|
30
30
|
|
|
31
31
|
<v-col cols="12" class="mb-4">
|
|
32
|
-
<label class="
|
|
33
|
-
Tag ID <span class="text-
|
|
32
|
+
<label class="nfc-tag__label mb-2">
|
|
33
|
+
Tag ID <span class="text-error">*</span>
|
|
34
34
|
</label>
|
|
35
35
|
<v-text-field
|
|
36
36
|
v-model="form.tagID"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
</v-form>
|
|
48
48
|
</v-card-text>
|
|
49
49
|
|
|
50
|
-
<v-toolbar class="pa-0" density="compact">
|
|
50
|
+
<v-toolbar class="pa-0 screen-dialog-bar" density="compact">
|
|
51
51
|
<v-row no-gutters>
|
|
52
52
|
<v-col cols="6" class="pa-0">
|
|
53
53
|
<v-btn
|
|
@@ -64,6 +64,10 @@
|
|
|
64
64
|
</v-col>
|
|
65
65
|
|
|
66
66
|
<v-col cols="6" class="pa-0">
|
|
67
|
+
<!-- Was `color="black"`: a fixed slab that stayed black on the dark
|
|
68
|
+
card. `primary-button` is the theme's FILL token, and its pair
|
|
69
|
+
`on-primary-button` supplies the white label - unlike `primary`,
|
|
70
|
+
which is a FOREGROUND here (links, icons, text buttons). -->
|
|
67
71
|
<v-btn
|
|
68
72
|
block
|
|
69
73
|
tile
|
|
@@ -71,7 +75,7 @@
|
|
|
71
75
|
class="text-none"
|
|
72
76
|
size="large"
|
|
73
77
|
height="48"
|
|
74
|
-
color="
|
|
78
|
+
color="primary-button"
|
|
75
79
|
@click="submit"
|
|
76
80
|
:loading="loading"
|
|
77
81
|
:disabled="!valid || loading || !hasChanges"
|
|
@@ -234,3 +238,13 @@ async function submit() {
|
|
|
234
238
|
}
|
|
235
239
|
}
|
|
236
240
|
</script>
|
|
241
|
+
|
|
242
|
+
<style scoped>
|
|
243
|
+
/* Was `text-subtitle-2`, Vuetify's 14px. The required asterisk beside it
|
|
244
|
+
keeps `text-error`; only the label's size and ink move. */
|
|
245
|
+
.nfc-tag__label {
|
|
246
|
+
font-size: var(--fs-cell);
|
|
247
|
+
font-weight: 500;
|
|
248
|
+
color: var(--text);
|
|
249
|
+
}
|
|
250
|
+
</style>
|
|
@@ -1,53 +1,51 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
3
|
<v-col cols="12">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
<!--
|
|
5
|
+
Two `grey-lighten-4` `v-toolbar`s - one above the table for refresh and
|
|
6
|
+
Add, one below it for the page range and the pager - become the ONE
|
|
7
|
+
`CardToolbar` the design draws. The range is the toolbar's own count
|
|
8
|
+
rather than a `text-font gray` caption; the pager keeps its model and
|
|
9
|
+
its `@update:value` emit, and Add keeps opening the same dialog.
|
|
10
|
+
|
|
11
|
+
This component mounts inside PM `settings.vue`'s "NFC Management"
|
|
12
|
+
expansion panel, which already draws that heading - so NO `PageHeader`
|
|
13
|
+
here, or the panel would read its name twice.
|
|
14
|
+
-->
|
|
15
|
+
<AppCard class="table-card">
|
|
16
|
+
<CardToolbar :count="pageRange">
|
|
17
|
+
<template #left>
|
|
7
18
|
<v-btn fab icon density="comfortable" @click="getNFCTagRefresh()">
|
|
8
19
|
<v-icon>mdi-refresh</v-icon>
|
|
9
20
|
</v-btn>
|
|
10
21
|
</template>
|
|
11
22
|
|
|
12
|
-
<template #
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
>
|
|
19
|
-
Add
|
|
20
|
-
</v-btn>
|
|
23
|
+
<template #right>
|
|
24
|
+
<local-pagination
|
|
25
|
+
v-model="page"
|
|
26
|
+
:length="pages"
|
|
27
|
+
@update:value="$emit('update:value', $event)"
|
|
28
|
+
/>
|
|
29
|
+
<AppButton @click="dialogAdd = true">Add</AppButton>
|
|
21
30
|
</template>
|
|
22
|
-
</
|
|
23
|
-
|
|
24
|
-
<v-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<template #append>
|
|
38
|
-
<v-row no-gutters justify="end" align="center">
|
|
39
|
-
<span class="mr-2 text-caption text-font gray">
|
|
40
|
-
{{ pageRange }}
|
|
41
|
-
</span>
|
|
42
|
-
<local-pagination
|
|
43
|
-
v-model="page"
|
|
44
|
-
:length="pages"
|
|
45
|
-
@update:value="$emit('update:value', $event)"
|
|
46
|
-
/>
|
|
47
|
-
</v-row>
|
|
31
|
+
</CardToolbar>
|
|
32
|
+
|
|
33
|
+
<v-data-table
|
|
34
|
+
:headers="headers"
|
|
35
|
+
:items="items"
|
|
36
|
+
fixed-header
|
|
37
|
+
hide-default-footer
|
|
38
|
+
@click:row="handleRowClick"
|
|
39
|
+
style="max-height: 300px"
|
|
40
|
+
>
|
|
41
|
+
<!-- The status column printed the raw word as plain text. `StatusChip`
|
|
42
|
+
prints the SAME word - it is given the item's own value - and
|
|
43
|
+
only adds the design's tone from the shared map. -->
|
|
44
|
+
<template #item.status="{ item }">
|
|
45
|
+
<StatusChip :status="(item as any).status" />
|
|
48
46
|
</template>
|
|
49
|
-
</v-
|
|
50
|
-
</
|
|
47
|
+
</v-data-table>
|
|
48
|
+
</AppCard>
|
|
51
49
|
</v-col>
|
|
52
50
|
|
|
53
51
|
<!-- Add Dialog -->
|
|
@@ -79,7 +77,7 @@
|
|
|
79
77
|
<!-- Preview Dialog -->
|
|
80
78
|
<v-dialog v-model="dialogPreview" persistent width="540">
|
|
81
79
|
<v-card width="100%">
|
|
82
|
-
<v-toolbar>
|
|
80
|
+
<v-toolbar class="screen-dialog-bar">
|
|
83
81
|
<v-row no-gutters class="fill-height px-6" align="center">
|
|
84
82
|
<span class="font-weight-bold text-h5 text-capitalize">
|
|
85
83
|
NFC Tag Details
|
|
@@ -110,7 +108,7 @@
|
|
|
110
108
|
</v-row>
|
|
111
109
|
</v-card-text>
|
|
112
110
|
|
|
113
|
-
<v-toolbar class="pa-0" density="compact">
|
|
111
|
+
<v-toolbar class="pa-0 screen-dialog-bar" density="compact">
|
|
114
112
|
<v-row no-gutters>
|
|
115
113
|
<v-col cols="6" class="pa-0">
|
|
116
114
|
<v-btn
|
|
@@ -171,7 +169,7 @@
|
|
|
171
169
|
Are you sure you want to delete this NFC Tag?
|
|
172
170
|
</v-card-text>
|
|
173
171
|
|
|
174
|
-
<v-toolbar class="pa-0" density="compact">
|
|
172
|
+
<v-toolbar class="pa-0 screen-dialog-bar" density="compact">
|
|
175
173
|
<v-row no-gutters>
|
|
176
174
|
<v-col cols="6" class="pa-0">
|
|
177
175
|
<v-btn
|
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
</template>
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
<!-- A failed request is not an empty result. Saying "no patrol log found"
|
|
21
|
+
for a 500 states something about the data the server never said. -->
|
|
22
|
+
<ReportEmptyState
|
|
23
|
+
v-else-if="!loading && failed"
|
|
24
|
+
title="Report unavailable"
|
|
25
|
+
message="The patrol logs could not be loaded. Please try again."
|
|
26
|
+
/>
|
|
20
27
|
<ReportEmptyState
|
|
21
28
|
v-else-if="!loading && notFound"
|
|
22
29
|
title="No Daily Report"
|
|
@@ -51,7 +58,7 @@ defineEmits<{
|
|
|
51
58
|
export: [type: "pdf" | "csv"];
|
|
52
59
|
}>();
|
|
53
60
|
|
|
54
|
-
const { report, loading, notFound, fetchReport } = useNFCPatrolDailyReport(
|
|
61
|
+
const { report, loading, notFound, failed, fetchReport } = useNFCPatrolDailyReport(
|
|
55
62
|
props.filters,
|
|
56
63
|
props.site,
|
|
57
64
|
);
|
|
@@ -21,6 +21,13 @@
|
|
|
21
21
|
/>
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
|
+
<!-- A failed request is not an empty result. Saying "no patrol log found"
|
|
25
|
+
for a 500 states something about the data the server never said. -->
|
|
26
|
+
<ReportEmptyState
|
|
27
|
+
v-else-if="!loading && failed"
|
|
28
|
+
title="Report unavailable"
|
|
29
|
+
message="The patrol logs could not be loaded. Please try again."
|
|
30
|
+
/>
|
|
24
31
|
<ReportEmptyState
|
|
25
32
|
v-else-if="!loading"
|
|
26
33
|
title="No Monthly Report"
|
|
@@ -55,7 +62,7 @@ defineEmits<{
|
|
|
55
62
|
export: [type: "pdf" | "csv"];
|
|
56
63
|
}>();
|
|
57
64
|
|
|
58
|
-
const { report, loading, notFound, fetchReport } =
|
|
65
|
+
const { report, loading, notFound, failed, fetchReport } =
|
|
59
66
|
useNFCPatrolMonthlyReport(props.filters, props.site);
|
|
60
67
|
|
|
61
68
|
watch(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="mt-6">
|
|
3
|
-
<div class="
|
|
3
|
+
<div class="screen-card-title mb-4">
|
|
4
4
|
{{ title }}
|
|
5
5
|
</div>
|
|
6
6
|
|
|
@@ -26,8 +26,10 @@
|
|
|
26
26
|
{{ row.checked }}
|
|
27
27
|
</td>
|
|
28
28
|
|
|
29
|
+
<!-- A month with no checkpoint due has no rate. "0%" there reads as
|
|
30
|
+
total failure, so it says nothing instead. -->
|
|
29
31
|
<td class="text-center">
|
|
30
|
-
{{ row.checkedPercentage }}
|
|
32
|
+
{{ row.checkedPercentage === null ? "—" : `${row.checkedPercentage}%` }}
|
|
31
33
|
</td>
|
|
32
34
|
|
|
33
35
|
<td class="text-center">
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
</td>
|
|
36
38
|
|
|
37
39
|
<td class="text-center">
|
|
38
|
-
{{ row.missedPercentage }}
|
|
40
|
+
{{ row.missedPercentage === null ? "—" : `${row.missedPercentage}%` }}
|
|
39
41
|
</td>
|
|
40
42
|
</tr>
|
|
41
43
|
</tbody>
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
The checkpoint-by-checkpoint rows of a patrol report.
|
|
3
|
+
|
|
4
|
+
Same change as the two tables beside it: off `variant="flat"` (no border on
|
|
5
|
+
either theme) and `border-thin` (a hairline the theme does not own) onto
|
|
6
|
+
`.table-card`, which is the design's table surface and styles the raw
|
|
7
|
+
`v-table`'s header row and cells.
|
|
8
|
+
|
|
9
|
+
`statusColor()` keeps returning `success`/`error`: those are the design
|
|
10
|
+
tokens by way of `utils/theme.ts`, and `utils/status.ts` does not name
|
|
11
|
+
"Skipped", so routing this through `StatusChip` would turn a red skipped
|
|
12
|
+
checkpoint neutral. That is a design decision, not a conversion.
|
|
13
|
+
-->
|
|
1
14
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
15
|
+
<div class="table-card table-card__shrink">
|
|
16
|
+
<div class="activity-table__head">
|
|
17
|
+
<span class="screen-card-title">Patrol Activity</span>
|
|
18
|
+
</div>
|
|
4
19
|
|
|
5
|
-
<
|
|
6
|
-
<v-table
|
|
20
|
+
<div>
|
|
21
|
+
<v-table>
|
|
7
22
|
<thead>
|
|
8
23
|
<tr>
|
|
9
24
|
<th>Checkpoints</th>
|
|
@@ -58,8 +73,8 @@
|
|
|
58
73
|
</tr>
|
|
59
74
|
</tbody>
|
|
60
75
|
</v-table>
|
|
61
|
-
</
|
|
62
|
-
</
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
63
78
|
</template>
|
|
64
79
|
|
|
65
80
|
<script setup lang="ts">
|
|
@@ -90,6 +105,11 @@ function handleActivityClick(activity: NFCPatrolActivity) {
|
|
|
90
105
|
</script>
|
|
91
106
|
|
|
92
107
|
<style scoped>
|
|
108
|
+
.activity-table__head {
|
|
109
|
+
padding: 14px var(--cellpad-x);
|
|
110
|
+
border-bottom: 1px solid var(--border);
|
|
111
|
+
}
|
|
112
|
+
|
|
93
113
|
.cursor-pointer {
|
|
94
114
|
cursor: pointer;
|
|
95
115
|
}
|