@7365admin1/layer-common 1.8.0
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.editorconfig +12 -0
- package/.github/workflows/main.yml +17 -0
- package/.github/workflows/publish.yml +39 -0
- package/.nuxtrc +1 -0
- package/.playground/app.vue +41 -0
- package/.playground/eslint.config.mjs +6 -0
- package/.playground/nuxt.config.ts +22 -0
- package/.playground/pages/feedback.vue +30 -0
- package/CHANGELOG.md +263 -0
- package/README.md +73 -0
- package/app.vue +3 -0
- package/components/AccessCardAddForm.vue +363 -0
- package/components/AccessManagement.vue +420 -0
- package/components/Avatar/Main.vue +68 -0
- package/components/BillingMain.vue +66 -0
- package/components/BtnUploadFile.vue +139 -0
- package/components/BuildingForm.vue +303 -0
- package/components/BuildingManagement/buildings.vue +335 -0
- package/components/BuildingManagement/units.vue +350 -0
- package/components/BuildingUnitFormAdd.vue +441 -0
- package/components/BuildingUnitFormEdit.vue +429 -0
- package/components/CameraForm.vue +264 -0
- package/components/CameraMain.vue +352 -0
- package/components/Card/DeleteConfirmation.vue +51 -0
- package/components/Card/MemberInfoSummary.vue +44 -0
- package/components/Card/Toggle.vue +25 -0
- package/components/Chat/Bubbles.vue +53 -0
- package/components/Chat/Information.vue +416 -0
- package/components/Chat/ListCard.vue +62 -0
- package/components/Chat/Message.vue +158 -0
- package/components/Chat/Navigation.vue +150 -0
- package/components/ConfirmDialog.vue +66 -0
- package/components/Container/Standard.vue +33 -0
- package/components/DashboardPlaceholder.vue +1524 -0
- package/components/Dialog/DeleteConfirmation.vue +51 -0
- package/components/Dialog/ReplaceAutofillPrompt.vue +49 -0
- package/components/Dialog/UpdateMoreAction.vue +103 -0
- package/components/DocumentForm.vue +187 -0
- package/components/DocumentManagement.vue +376 -0
- package/components/Editor.vue +95 -0
- package/components/EntryPassMain.vue +518 -0
- package/components/Feedback/Form.vue +173 -0
- package/components/FeedbackDetail.vue +599 -0
- package/components/FeedbackMain.vue +588 -0
- package/components/FormDialog.vue +65 -0
- package/components/ImageCarousel.vue +138 -0
- package/components/Input/Date.vue +177 -0
- package/components/Input/DateTimePicker.vue +131 -0
- package/components/Input/File.vue +236 -0
- package/components/Input/FileV2.vue +234 -0
- package/components/Input/InputPhoneNumberV2.vue +164 -0
- package/components/Input/ListGroupSelection.vue +96 -0
- package/components/Input/NRICNumber.vue +53 -0
- package/components/Input/NewDate.vue +123 -0
- package/components/Input/Number.vue +124 -0
- package/components/Input/Password.vue +22 -0
- package/components/Input/PhoneNumber.vue +188 -0
- package/components/Input/VehicleNumber.vue +49 -0
- package/components/InputLabel.vue +22 -0
- package/components/InvitationForm.vue +359 -0
- package/components/InvitationMain.vue +310 -0
- package/components/Layout/Header.vue +129 -0
- package/components/Layout/NavigationDrawer.vue +44 -0
- package/components/ListItem.vue +35 -0
- package/components/ListView.vue +87 -0
- package/components/LocalPagination.vue +31 -0
- package/components/MemberMain.vue +459 -0
- package/components/NFC/NFCPatrolReportMain.vue +591 -0
- package/components/NFC/NFCPatrolRouteForm.vue +596 -0
- package/components/NFC/NFCPatrolRouteMain.vue +539 -0
- package/components/NFC/NFCTagForm.vue +236 -0
- package/components/NFC/NFCTagMain.vue +337 -0
- package/components/NFC/PatrolSettings.vue +130 -0
- package/components/NavigationItem.vue +83 -0
- package/components/NumberSettingField.vue +107 -0
- package/components/OnlineFormConfigurationForm.vue +290 -0
- package/components/OnlineFormsConfiguration.vue +429 -0
- package/components/PeopleForm.vue +452 -0
- package/components/PlaceholderComponent.vue +34 -0
- package/components/RolePermissionFormCreate.vue +161 -0
- package/components/RolePermissionFormPreviewUpdate.vue +183 -0
- package/components/RolePermissionMain.vue +361 -0
- package/components/SearchVehicleNumberUser.vue +91 -0
- package/components/ServiceProviderFormCreate.vue +154 -0
- package/components/ServiceProviderMain.vue +547 -0
- package/components/SignaturePad.vue +73 -0
- package/components/Snackbar.vue +23 -0
- package/components/SpecificAttr.vue +53 -0
- package/components/SupplyManagement.vue +292 -0
- package/components/SwitchContext.vue +108 -0
- package/components/TableList.vue +150 -0
- package/components/TableListSecondary.vue +164 -0
- package/components/TableMain.vue +142 -0
- package/components/TableWithButton.vue +94 -0
- package/components/VehicleUpdateMoreAction.vue +84 -0
- package/components/VideoPlayer.vue +125 -0
- package/components/VisitorForm.vue +659 -0
- package/components/VisitorFormSelection.vue +53 -0
- package/components/VisitorManagement.vue +490 -0
- package/components/WorkOrder/Create.vue +284 -0
- package/components/WorkOrder/Detail.vue +71 -0
- package/components/WorkOrder/ListView.vue +96 -0
- package/components/WorkOrder/Main.vue +489 -0
- package/components/Workorder.vue +1 -0
- package/composables/useAddress.ts +107 -0
- package/composables/useBuilding.ts +250 -0
- package/composables/useBuildingUnit.ts +116 -0
- package/composables/useCard.ts +46 -0
- package/composables/useCommonPermission.ts +207 -0
- package/composables/useCustomer.ts +113 -0
- package/composables/useCustomerSite.ts +56 -0
- package/composables/useDashboard.ts +31 -0
- package/composables/useDashboardData.ts +425 -0
- package/composables/useDocument.ts +57 -0
- package/composables/useFacility.ts +246 -0
- package/composables/useFeedback.ts +119 -0
- package/composables/useFile.ts +55 -0
- package/composables/useInvoice.ts +18 -0
- package/composables/useLocal.ts +131 -0
- package/composables/useLocalAuth.ts +137 -0
- package/composables/useLocalSetup.ts +13 -0
- package/composables/useMember.ts +111 -0
- package/composables/useNFCPatrolRoute.ts +77 -0
- package/composables/useNFCPatrolSettings.ts +19 -0
- package/composables/useNFCPatrolTag.ts +53 -0
- package/composables/useOnlineForm.ts +67 -0
- package/composables/useOrg.ts +129 -0
- package/composables/usePDFDownload.ts +25 -0
- package/composables/usePaymentMethod.ts +101 -0
- package/composables/usePeople.ts +81 -0
- package/composables/usePermission.ts +54 -0
- package/composables/usePhoneCountries.ts +561 -0
- package/composables/usePrice.ts +15 -0
- package/composables/usePromoCode.ts +36 -0
- package/composables/useRecapPermission.ts +26 -0
- package/composables/useRole.ts +104 -0
- package/composables/useSecurityUtils.ts +18 -0
- package/composables/useServiceProvider.ts +224 -0
- package/composables/useSite.ts +109 -0
- package/composables/useSiteEntryPassSettings.ts +46 -0
- package/composables/useSiteSettings.ts +123 -0
- package/composables/useSubscription.ts +150 -0
- package/composables/useUser.ts +132 -0
- package/composables/useUtils.ts +445 -0
- package/composables/useVerification.ts +34 -0
- package/composables/useVisitor.ts +120 -0
- package/composables/useWorkOrder.ts +85 -0
- package/error.vue +41 -0
- package/layouts/plain.vue +7 -0
- package/middleware/01.auth.ts +20 -0
- package/middleware/02.org.ts +21 -0
- package/middleware/03.customer.ts +13 -0
- package/middleware/member.ts +4 -0
- package/nuxt.config.ts +54 -0
- package/package.json +39 -0
- package/pages/index.vue +3 -0
- package/pages/payment-method-linked.vue +31 -0
- package/pages/require-customer.vue +56 -0
- package/pages/require-organization-membership.vue +47 -0
- package/pages/unauthorized.vue +29 -0
- package/plugins/API.ts +21 -0
- package/plugins/iconify.client.ts +5 -0
- package/plugins/secure-member.client.ts +86 -0
- package/plugins/vuetify.ts +62 -0
- package/public/bg-camera.jpg +0 -0
- package/public/bg-city.jpg +0 -0
- package/public/bg-condo.jpg +0 -0
- package/public/images/icons/delete-icon.png +0 -0
- package/public/sprite.svg +1 -0
- package/tsconfig.json +3 -0
- package/types/address.d.ts +13 -0
- package/types/building.d.ts +27 -0
- package/types/camera.d.ts +31 -0
- package/types/card.d.ts +22 -0
- package/types/customer.d.ts +27 -0
- package/types/document.d.ts +6 -0
- package/types/feedback.d.ts +68 -0
- package/types/local.d.ts +74 -0
- package/types/member.d.ts +21 -0
- package/types/online-form.d.ts +15 -0
- package/types/org.d.ts +13 -0
- package/types/people.d.ts +24 -0
- package/types/permission.d.ts +25 -0
- package/types/phone-number.d.ts +10 -0
- package/types/price.d.ts +17 -0
- package/types/promo-code.d.ts +19 -0
- package/types/role.d.ts +11 -0
- package/types/select.d.ts +4 -0
- package/types/service-provider.d.ts +15 -0
- package/types/site.d.ts +20 -0
- package/types/subscription.d.ts +23 -0
- package/types/user.d.ts +19 -0
- package/types/verification.d.ts +20 -0
- package/types/visitor.d.ts +42 -0
- package/types/work-order.d.ts +42 -0
- package/utils/phoneMasks.ts +1703 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-skeleton-loader
|
|
3
|
+
type="card"
|
|
4
|
+
:width="'100%'"
|
|
5
|
+
:height="'200px'"
|
|
6
|
+
v-if="loading"
|
|
7
|
+
/>
|
|
8
|
+
<v-row no-gutters class="" v-if="!loading">
|
|
9
|
+
<v-col cols="12" elevation="3" class="border">
|
|
10
|
+
<v-row no-gutters class="px-6 pt-4">
|
|
11
|
+
<div class="d-flex mt-7 pb-5">
|
|
12
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
13
|
+
Physical / Key Pass
|
|
14
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
15
|
+
A Physical Pass Card is a tangible identification or access card
|
|
16
|
+
used for entry and verification purposes at a specific site or
|
|
17
|
+
property. Its primary functions include granting authorized
|
|
18
|
+
access, enhancing security, and tracking attendance or movement.
|
|
19
|
+
</span>
|
|
20
|
+
</p>
|
|
21
|
+
<v-switch
|
|
22
|
+
color="success"
|
|
23
|
+
hide-details
|
|
24
|
+
v-model="currentEntryPassSettings.physicalPass"
|
|
25
|
+
@update:modelValue="updateEntryPassSettingsPhysicalPass()"
|
|
26
|
+
></v-switch>
|
|
27
|
+
</div>
|
|
28
|
+
<v-divider thickness="1"></v-divider>
|
|
29
|
+
<div class="d-flex mt-7 pb-5">
|
|
30
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
31
|
+
NFC / QR Code Pass
|
|
32
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
33
|
+
NFC Card Pass is a type of access card that uses Near Field
|
|
34
|
+
Communication (NFC) technology to enable secure and convenient
|
|
35
|
+
entry to a site or property. This technology facilitates wireless
|
|
36
|
+
communication between the card and an NFC reader when they are
|
|
37
|
+
placed in close proximity (typically within 4 cm).
|
|
38
|
+
</span>
|
|
39
|
+
</p>
|
|
40
|
+
<v-switch
|
|
41
|
+
color="success"
|
|
42
|
+
hide-details
|
|
43
|
+
v-model="currentEntryPassSettings.nfcPass"
|
|
44
|
+
@update:modelValue="updateEntryPassSettingsNfcPass()"
|
|
45
|
+
></v-switch>
|
|
46
|
+
</div>
|
|
47
|
+
<v-divider thickness="1"></v-divider>
|
|
48
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
49
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
50
|
+
Upload Access Cards Template
|
|
51
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
52
|
+
<a
|
|
53
|
+
target="_blank"
|
|
54
|
+
class="text-truncate d-flex items-center text-decoration-none"
|
|
55
|
+
href=""
|
|
56
|
+
>
|
|
57
|
+
<v-icon class="mr-2" size="24px"> mdi-paperclip </v-icon>
|
|
58
|
+
template
|
|
59
|
+
</a>
|
|
60
|
+
</span>
|
|
61
|
+
</p>
|
|
62
|
+
<v-btn
|
|
63
|
+
variant="flat"
|
|
64
|
+
color="error"
|
|
65
|
+
size="small"
|
|
66
|
+
style="height: 40px; margin-left: auto"
|
|
67
|
+
prepend-icon="mdi-file-document-remove-outline"
|
|
68
|
+
>
|
|
69
|
+
Remove
|
|
70
|
+
</v-btn>
|
|
71
|
+
</div>
|
|
72
|
+
<v-divider thickness="1"></v-divider>
|
|
73
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
74
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
75
|
+
Printer Setup
|
|
76
|
+
<v-col cols="12">
|
|
77
|
+
<v-row>
|
|
78
|
+
<v-col cols="3">
|
|
79
|
+
<v-text-field
|
|
80
|
+
label="Vendor ID"
|
|
81
|
+
hide-details
|
|
82
|
+
clearable
|
|
83
|
+
v-model="currentEntryPassSettings.printerVendorId"
|
|
84
|
+
></v-text-field>
|
|
85
|
+
</v-col>
|
|
86
|
+
<v-col cols="3">
|
|
87
|
+
<v-text-field
|
|
88
|
+
label="Product ID"
|
|
89
|
+
hide-details
|
|
90
|
+
clearable
|
|
91
|
+
v-model="currentEntryPassSettings.printerProductId"
|
|
92
|
+
></v-text-field>
|
|
93
|
+
</v-col>
|
|
94
|
+
<v-col cols="3">
|
|
95
|
+
<v-btn
|
|
96
|
+
color="primary"
|
|
97
|
+
variant="outlined"
|
|
98
|
+
prepend-icon="mdi-magnify"
|
|
99
|
+
block
|
|
100
|
+
>
|
|
101
|
+
Scan Printer
|
|
102
|
+
</v-btn>
|
|
103
|
+
</v-col>
|
|
104
|
+
<v-col cols="3">
|
|
105
|
+
<v-btn
|
|
106
|
+
color="success"
|
|
107
|
+
variant="outlined"
|
|
108
|
+
prepend-icon="mdi-printer-check"
|
|
109
|
+
block
|
|
110
|
+
>
|
|
111
|
+
Test & Print
|
|
112
|
+
</v-btn>
|
|
113
|
+
</v-col>
|
|
114
|
+
</v-row>
|
|
115
|
+
<v-row class="mt-4">
|
|
116
|
+
<v-col cols="12" sm="6" md="4">
|
|
117
|
+
<v-btn
|
|
118
|
+
color="primary"
|
|
119
|
+
variant="flat"
|
|
120
|
+
prepend-icon="mdi-content-save"
|
|
121
|
+
block
|
|
122
|
+
@click="savePrinterSettings()"
|
|
123
|
+
>
|
|
124
|
+
Save Settings
|
|
125
|
+
</v-btn>
|
|
126
|
+
</v-col>
|
|
127
|
+
</v-row>
|
|
128
|
+
</v-col>
|
|
129
|
+
</p>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<v-divider thickness="1"></v-divider>
|
|
133
|
+
|
|
134
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
135
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
136
|
+
QR Code Template
|
|
137
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
138
|
+
<v-col cols="12">
|
|
139
|
+
<v-row>
|
|
140
|
+
<v-col cols="12">
|
|
141
|
+
<v-text-field
|
|
142
|
+
label="Header"
|
|
143
|
+
placeholder="Enter qr code header eg. Welcome to Company Name"
|
|
144
|
+
hide-details
|
|
145
|
+
density="comfortable"
|
|
146
|
+
clearable
|
|
147
|
+
v-model="currentEntryPassSettings.qrCodeTemplateHeader"
|
|
148
|
+
></v-text-field>
|
|
149
|
+
</v-col>
|
|
150
|
+
<v-col cols="12">
|
|
151
|
+
<v-text-field
|
|
152
|
+
label="Subtext"
|
|
153
|
+
placeholder="Enter qr code sub header"
|
|
154
|
+
hide-details
|
|
155
|
+
density="comfortable"
|
|
156
|
+
clearable
|
|
157
|
+
class="mb-2"
|
|
158
|
+
v-model="
|
|
159
|
+
currentEntryPassSettings.qrCodeTemplateHeaderSubText
|
|
160
|
+
"
|
|
161
|
+
></v-text-field>
|
|
162
|
+
</v-col>
|
|
163
|
+
<v-row class="mt-3">
|
|
164
|
+
<v-col cols="12" md="2">
|
|
165
|
+
<v-btn color="primary" variant="flat" block>
|
|
166
|
+
Preview
|
|
167
|
+
</v-btn>
|
|
168
|
+
</v-col>
|
|
169
|
+
<v-col cols="12" md="2">
|
|
170
|
+
<v-btn
|
|
171
|
+
color="primary"
|
|
172
|
+
variant="flat"
|
|
173
|
+
block
|
|
174
|
+
@click="saveQrCodeTemplate()"
|
|
175
|
+
>
|
|
176
|
+
Save
|
|
177
|
+
</v-btn>
|
|
178
|
+
</v-col>
|
|
179
|
+
</v-row>
|
|
180
|
+
</v-row>
|
|
181
|
+
</v-col>
|
|
182
|
+
</span>
|
|
183
|
+
</p>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<v-divider thickness="1"></v-divider>
|
|
187
|
+
|
|
188
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
189
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
190
|
+
Resident-app Disclaimer Message
|
|
191
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
192
|
+
<v-col cols="12">
|
|
193
|
+
<v-row no-gutters>
|
|
194
|
+
<v-col cols="12" class="mb-5">
|
|
195
|
+
<v-textarea
|
|
196
|
+
label="Disclaimer Message"
|
|
197
|
+
placeholder="Enter disclaimer message for resident app"
|
|
198
|
+
hide-details
|
|
199
|
+
density="comfortable"
|
|
200
|
+
clearable
|
|
201
|
+
rows="5"
|
|
202
|
+
auto-grow
|
|
203
|
+
v-model="currentEntryPassSettings.disclaimerMessage"
|
|
204
|
+
></v-textarea>
|
|
205
|
+
</v-col>
|
|
206
|
+
<v-row class="mt-3">
|
|
207
|
+
<v-col cols="12" md="2">
|
|
208
|
+
<v-btn
|
|
209
|
+
color="primary"
|
|
210
|
+
variant="flat"
|
|
211
|
+
block
|
|
212
|
+
@click="saveResidentAppDisclaimerMsg()"
|
|
213
|
+
>
|
|
214
|
+
Save
|
|
215
|
+
</v-btn>
|
|
216
|
+
</v-col>
|
|
217
|
+
</v-row>
|
|
218
|
+
</v-row>
|
|
219
|
+
</v-col>
|
|
220
|
+
</span>
|
|
221
|
+
</p>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<v-divider thickness="1"></v-divider>
|
|
225
|
+
|
|
226
|
+
<div class="d-flex w-100 mt-7 pb-10">
|
|
227
|
+
<p class="mr-6 font-weight-medium flex-grow-1">
|
|
228
|
+
Entrypass URL
|
|
229
|
+
<span class="d-block text-caption text-grey-darken-1 mt-1">
|
|
230
|
+
<v-col>
|
|
231
|
+
<v-text-field
|
|
232
|
+
label="Enter entrypass URL"
|
|
233
|
+
placeholder="https://example.com"
|
|
234
|
+
outlined
|
|
235
|
+
clearable
|
|
236
|
+
hide-details
|
|
237
|
+
v-model="currentEntryPassSettings.url"
|
|
238
|
+
/>
|
|
239
|
+
</v-col>
|
|
240
|
+
<v-col>
|
|
241
|
+
<v-btn color="primary" @click="saveEntryPassUrl()">Save</v-btn>
|
|
242
|
+
</v-col>
|
|
243
|
+
</span>
|
|
244
|
+
</p>
|
|
245
|
+
</div>
|
|
246
|
+
</v-row>
|
|
247
|
+
</v-col>
|
|
248
|
+
|
|
249
|
+
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
250
|
+
</v-row>
|
|
251
|
+
</template>
|
|
252
|
+
<script lang="ts" setup>
|
|
253
|
+
definePageMeta({
|
|
254
|
+
middleware: ["01-auth", "02-org"],
|
|
255
|
+
memberOnly: true,
|
|
256
|
+
});
|
|
257
|
+
const prop = defineProps({
|
|
258
|
+
site: {
|
|
259
|
+
type: String,
|
|
260
|
+
required: true,
|
|
261
|
+
},
|
|
262
|
+
siteName: {
|
|
263
|
+
type: String,
|
|
264
|
+
required: true,
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
orgId: {
|
|
268
|
+
type: String,
|
|
269
|
+
required: true,
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const currentEntryPassSettings = ref<Record<string, any>>({
|
|
274
|
+
_id: "",
|
|
275
|
+
site: "",
|
|
276
|
+
org: "",
|
|
277
|
+
isEnabled: true,
|
|
278
|
+
physicalPass: false,
|
|
279
|
+
nfcPass: false,
|
|
280
|
+
printerVendorId: "",
|
|
281
|
+
printerProductId: "",
|
|
282
|
+
qrCodeTemplateHeader: "",
|
|
283
|
+
qrCodeTemplateHeaderSubText: "",
|
|
284
|
+
qrCodeTemplateDate: "",
|
|
285
|
+
disclaimerMessage: "",
|
|
286
|
+
url: "",
|
|
287
|
+
status: "",
|
|
288
|
+
createdBy: "",
|
|
289
|
+
updatedBy: "",
|
|
290
|
+
createdAt: "",
|
|
291
|
+
updatedAt: "",
|
|
292
|
+
deletedAt: "",
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const entryPassSettingsPayload = ref<Record<string, any>>({
|
|
296
|
+
site: "",
|
|
297
|
+
org: "",
|
|
298
|
+
isEnabled: true,
|
|
299
|
+
physicalPass: false,
|
|
300
|
+
nfcPass: false,
|
|
301
|
+
printerVendorId: "",
|
|
302
|
+
printerProductId: "",
|
|
303
|
+
qrCodeTemplateHeader: "",
|
|
304
|
+
qrCodeTemplateHeaderSubText: "",
|
|
305
|
+
qrCodeTemplateDate: "",
|
|
306
|
+
disclaimerMessage: "",
|
|
307
|
+
url: "",
|
|
308
|
+
status: "",
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const {
|
|
312
|
+
getBySiteId: _getSiteEntryPassSettings,
|
|
313
|
+
add: _add,
|
|
314
|
+
updateBySiteId: _updateBySiteId,
|
|
315
|
+
} = useSiteEntryPassSettings();
|
|
316
|
+
|
|
317
|
+
const route = useRoute();
|
|
318
|
+
const siteId = route.params.site as string;
|
|
319
|
+
const orgId = route.params.org as string;
|
|
320
|
+
|
|
321
|
+
const message = ref("");
|
|
322
|
+
const messageSnackbar = ref(false);
|
|
323
|
+
const messageColor = ref("");
|
|
324
|
+
|
|
325
|
+
const {
|
|
326
|
+
data: getSiteEntryPassSettingsReq,
|
|
327
|
+
refresh: getSiteEntryPassSettings,
|
|
328
|
+
status: getSiteEntryPassSettingsReqStatus,
|
|
329
|
+
} = useLazyAsyncData("get-site-entry-pass-settings", () =>
|
|
330
|
+
_getSiteEntryPassSettings(prop.site as string)
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const loading = computed(
|
|
334
|
+
() => getSiteEntryPassSettingsReqStatus.value === "pending"
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
watchEffect(() => {
|
|
338
|
+
if (getSiteEntryPassSettingsReq.value) {
|
|
339
|
+
currentEntryPassSettings.value = getSiteEntryPassSettingsReq.value;
|
|
340
|
+
// console.log("currentEntryPassSettings", currentEntryPassSettings.value);
|
|
341
|
+
// console.log(currentEntryPassSettings.value._id);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
async function addPayload() {
|
|
346
|
+
const payload = {
|
|
347
|
+
site: siteId,
|
|
348
|
+
org: orgId,
|
|
349
|
+
isEnabled: true,
|
|
350
|
+
physicalPass: currentEntryPassSettings.value.physicalPass,
|
|
351
|
+
nfcPass: currentEntryPassSettings.value.nfcPass,
|
|
352
|
+
printerVendorId: currentEntryPassSettings.value.printerVendorId,
|
|
353
|
+
printerProductId: currentEntryPassSettings.value.printerProductId,
|
|
354
|
+
qrCodeTemplateHeader: currentEntryPassSettings.value.qrCodeTemplateHeader,
|
|
355
|
+
qrCodeTemplateHeaderSubText:
|
|
356
|
+
currentEntryPassSettings.value.qrCodeTemplateHeaderSubText,
|
|
357
|
+
qrCodeTemplateDate: currentEntryPassSettings.value.qrCodeTemplateDate,
|
|
358
|
+
disclaimerMessage: currentEntryPassSettings.value.disclaimerMessage,
|
|
359
|
+
url: currentEntryPassSettings.value.url,
|
|
360
|
+
status: "Active",
|
|
361
|
+
};
|
|
362
|
+
entryPassSettingsPayload.value = payload;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async function updatePayload() {
|
|
366
|
+
const payload = {
|
|
367
|
+
isEnabled: true,
|
|
368
|
+
physicalPass: currentEntryPassSettings.value.physicalPass,
|
|
369
|
+
nfcPass: currentEntryPassSettings.value.nfcPass,
|
|
370
|
+
printerVendorId: currentEntryPassSettings.value.printerVendorId,
|
|
371
|
+
printerProductId: currentEntryPassSettings.value.printerProductId,
|
|
372
|
+
qrCodeTemplateHeader: currentEntryPassSettings.value.qrCodeTemplateHeader,
|
|
373
|
+
qrCodeTemplateHeaderSubText:
|
|
374
|
+
currentEntryPassSettings.value.qrCodeTemplateHeaderSubText,
|
|
375
|
+
qrCodeTemplateDate: currentEntryPassSettings.value.qrCodeTemplateDate,
|
|
376
|
+
disclaimerMessage: currentEntryPassSettings.value.disclaimerMessage,
|
|
377
|
+
url: currentEntryPassSettings.value.url,
|
|
378
|
+
status: "Active",
|
|
379
|
+
};
|
|
380
|
+
entryPassSettingsPayload.value = payload;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function updateEntryPassSettingsPhysicalPass() {
|
|
384
|
+
if (!currentEntryPassSettings.value._id) {
|
|
385
|
+
addPayload();
|
|
386
|
+
entryPassSettingsPayload.value.physicalPass =
|
|
387
|
+
currentEntryPassSettings.value.physicalPass;
|
|
388
|
+
await _add(entryPassSettingsPayload.value);
|
|
389
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
390
|
+
} else {
|
|
391
|
+
updatePayload();
|
|
392
|
+
entryPassSettingsPayload.value.physicalPass =
|
|
393
|
+
currentEntryPassSettings.value.physicalPass;
|
|
394
|
+
await _updateBySiteId(
|
|
395
|
+
entryPassSettingsPayload.value,
|
|
396
|
+
currentEntryPassSettings.value.site
|
|
397
|
+
);
|
|
398
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
399
|
+
}
|
|
400
|
+
getSiteEntryPassSettings();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
async function updateEntryPassSettingsNfcPass() {
|
|
404
|
+
if (!currentEntryPassSettings.value._id) {
|
|
405
|
+
addPayload();
|
|
406
|
+
entryPassSettingsPayload.value.nfcPass =
|
|
407
|
+
currentEntryPassSettings.value.nfcPass;
|
|
408
|
+
await _add(entryPassSettingsPayload.value);
|
|
409
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
410
|
+
} else {
|
|
411
|
+
updatePayload();
|
|
412
|
+
entryPassSettingsPayload.value.nfcPass =
|
|
413
|
+
currentEntryPassSettings.value.nfcPass;
|
|
414
|
+
await _updateBySiteId(
|
|
415
|
+
entryPassSettingsPayload.value,
|
|
416
|
+
currentEntryPassSettings.value.site
|
|
417
|
+
);
|
|
418
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
419
|
+
}
|
|
420
|
+
getSiteEntryPassSettings();
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
async function savePrinterSettings() {
|
|
424
|
+
if (!currentEntryPassSettings.value._id) {
|
|
425
|
+
addPayload();
|
|
426
|
+
entryPassSettingsPayload.value.printerVendorId =
|
|
427
|
+
currentEntryPassSettings.value.printerVendorId;
|
|
428
|
+
entryPassSettingsPayload.value.printerProductId =
|
|
429
|
+
currentEntryPassSettings.value.printerProductId;
|
|
430
|
+
await _add(entryPassSettingsPayload.value);
|
|
431
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
432
|
+
} else {
|
|
433
|
+
updatePayload();
|
|
434
|
+
entryPassSettingsPayload.value.printerVendorId =
|
|
435
|
+
currentEntryPassSettings.value.printerVendorId;
|
|
436
|
+
entryPassSettingsPayload.value.printerProductId =
|
|
437
|
+
currentEntryPassSettings.value.printerProductId;
|
|
438
|
+
console.log(
|
|
439
|
+
"entryPassSettingsPayload.value",
|
|
440
|
+
entryPassSettingsPayload.value
|
|
441
|
+
);
|
|
442
|
+
await _updateBySiteId(
|
|
443
|
+
entryPassSettingsPayload.value,
|
|
444
|
+
currentEntryPassSettings.value.site
|
|
445
|
+
);
|
|
446
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
447
|
+
}
|
|
448
|
+
getSiteEntryPassSettings();
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async function saveQrCodeTemplate() {
|
|
452
|
+
if (!currentEntryPassSettings.value._id) {
|
|
453
|
+
addPayload();
|
|
454
|
+
entryPassSettingsPayload.value.qrCodeTemplateHeader =
|
|
455
|
+
currentEntryPassSettings.value.qrCodeTemplateHeader;
|
|
456
|
+
entryPassSettingsPayload.value.qrCodeTemplateHeaderSubText =
|
|
457
|
+
currentEntryPassSettings.value.qrCodeTemplateHeaderSubText;
|
|
458
|
+
await _add(entryPassSettingsPayload.value);
|
|
459
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
460
|
+
} else {
|
|
461
|
+
updatePayload();
|
|
462
|
+
entryPassSettingsPayload.value.qrCodeTemplateHeader =
|
|
463
|
+
currentEntryPassSettings.value.qrCodeTemplateHeader;
|
|
464
|
+
entryPassSettingsPayload.value.qrCodeTemplateHeaderSubText =
|
|
465
|
+
currentEntryPassSettings.value.qrCodeTemplateHeaderSubText;
|
|
466
|
+
await _updateBySiteId(
|
|
467
|
+
entryPassSettingsPayload.value,
|
|
468
|
+
currentEntryPassSettings.value.site
|
|
469
|
+
);
|
|
470
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
471
|
+
}
|
|
472
|
+
getSiteEntryPassSettings();
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function saveResidentAppDisclaimerMsg() {
|
|
476
|
+
if (!currentEntryPassSettings.value._id) {
|
|
477
|
+
addPayload();
|
|
478
|
+
entryPassSettingsPayload.value.disclaimerMessage =
|
|
479
|
+
currentEntryPassSettings.value.disclaimerMessage;
|
|
480
|
+
await _add(entryPassSettingsPayload.value);
|
|
481
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
482
|
+
} else {
|
|
483
|
+
updatePayload();
|
|
484
|
+
entryPassSettingsPayload.value.disclaimerMessage =
|
|
485
|
+
currentEntryPassSettings.value.disclaimerMessage;
|
|
486
|
+
await _updateBySiteId(
|
|
487
|
+
entryPassSettingsPayload.value,
|
|
488
|
+
currentEntryPassSettings.value.site
|
|
489
|
+
);
|
|
490
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
491
|
+
}
|
|
492
|
+
getSiteEntryPassSettings();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
async function saveEntryPassUrl() {
|
|
496
|
+
if (!currentEntryPassSettings.value._id) {
|
|
497
|
+
addPayload();
|
|
498
|
+
entryPassSettingsPayload.value.url = currentEntryPassSettings.value.url;
|
|
499
|
+
await _add(entryPassSettingsPayload.value);
|
|
500
|
+
showMessage("Entry Pass Settings added successfully!", "success");
|
|
501
|
+
} else {
|
|
502
|
+
updatePayload();
|
|
503
|
+
entryPassSettingsPayload.value.url = currentEntryPassSettings.value.url;
|
|
504
|
+
await _updateBySiteId(
|
|
505
|
+
entryPassSettingsPayload.value,
|
|
506
|
+
currentEntryPassSettings.value.site
|
|
507
|
+
);
|
|
508
|
+
showMessage("Entry Pass Settings updated successfully!", "success");
|
|
509
|
+
}
|
|
510
|
+
getSiteEntryPassSettings();
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function showMessage(msg: string, color: string) {
|
|
514
|
+
message.value = msg;
|
|
515
|
+
messageColor.value = color;
|
|
516
|
+
messageSnackbar.value = true;
|
|
517
|
+
}
|
|
518
|
+
</script>
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FormDialog v-model="dialog" @close="closeDialog">
|
|
3
|
+
<template #title>
|
|
4
|
+
<span class="text-h6 font-weight-medium pt-1 text-capitalize">
|
|
5
|
+
{{ isEditMode ? "Edit Feedback" : "Create Feedback" }}
|
|
6
|
+
</span>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<InputFile
|
|
10
|
+
:attachments="displayedAttachments"
|
|
11
|
+
:errored-images="localErroredImages"
|
|
12
|
+
:max-files="maxFiles"
|
|
13
|
+
@add="handleFileAdded"
|
|
14
|
+
@delete="deleteFile"
|
|
15
|
+
@errored="onImageError"
|
|
16
|
+
/>
|
|
17
|
+
|
|
18
|
+
<v-autocomplete
|
|
19
|
+
v-model="localFeedback.subject"
|
|
20
|
+
:items="subjects"
|
|
21
|
+
item-title="title"
|
|
22
|
+
item-value="value"
|
|
23
|
+
item-props
|
|
24
|
+
variant="outlined"
|
|
25
|
+
density="compact"
|
|
26
|
+
class="mb-2"
|
|
27
|
+
clearable
|
|
28
|
+
:custom-filter="customFilter"
|
|
29
|
+
:rules="[requiredRule]"
|
|
30
|
+
>
|
|
31
|
+
<template #label> Subject <span class="text-red">*</span> </template>
|
|
32
|
+
</v-autocomplete>
|
|
33
|
+
|
|
34
|
+
<v-autocomplete
|
|
35
|
+
v-model="localFeedback.category"
|
|
36
|
+
:items="categories"
|
|
37
|
+
item-title="title"
|
|
38
|
+
item-value="value"
|
|
39
|
+
item-props
|
|
40
|
+
label="Category"
|
|
41
|
+
variant="outlined"
|
|
42
|
+
density="compact"
|
|
43
|
+
class="mb-2"
|
|
44
|
+
clearable
|
|
45
|
+
:rules="[requiredRule]"
|
|
46
|
+
>
|
|
47
|
+
<template #label> Category <span class="text-red">*</span> </template>
|
|
48
|
+
</v-autocomplete>
|
|
49
|
+
|
|
50
|
+
<v-text-field
|
|
51
|
+
label="Location"
|
|
52
|
+
variant="outlined"
|
|
53
|
+
density="compact"
|
|
54
|
+
v-model="localFeedback.location"
|
|
55
|
+
:rules="[requiredRule]"
|
|
56
|
+
>
|
|
57
|
+
<template #label> Location <span class="text-red">*</span> </template>
|
|
58
|
+
</v-text-field>
|
|
59
|
+
|
|
60
|
+
<v-textarea
|
|
61
|
+
label="Description"
|
|
62
|
+
variant="outlined"
|
|
63
|
+
density="compact"
|
|
64
|
+
auto-grow
|
|
65
|
+
rows="4"
|
|
66
|
+
v-model="localFeedback.description"
|
|
67
|
+
:rules="[requiredRule]"
|
|
68
|
+
>
|
|
69
|
+
<template #label> Description <span class="text-red">*</span> </template>
|
|
70
|
+
</v-textarea>
|
|
71
|
+
|
|
72
|
+
<template #footer>
|
|
73
|
+
<v-btn
|
|
74
|
+
color="primary-button"
|
|
75
|
+
class="text-capitalize mb-4"
|
|
76
|
+
block
|
|
77
|
+
height="40"
|
|
78
|
+
:loading="loading"
|
|
79
|
+
:disabled="loading || !isFormValid"
|
|
80
|
+
@click="submitFeedback"
|
|
81
|
+
>
|
|
82
|
+
Submit
|
|
83
|
+
</v-btn>
|
|
84
|
+
</template>
|
|
85
|
+
</FormDialog>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script setup lang="ts">
|
|
89
|
+
const props = defineProps<{
|
|
90
|
+
modelValue: boolean;
|
|
91
|
+
feedback: TFeedbackCreate;
|
|
92
|
+
isEditMode: boolean;
|
|
93
|
+
loading: boolean;
|
|
94
|
+
categories: { title: string; value: string }[];
|
|
95
|
+
erroredImages?: string[];
|
|
96
|
+
maxFiles?: number;
|
|
97
|
+
}>();
|
|
98
|
+
|
|
99
|
+
const emit = defineEmits<{
|
|
100
|
+
(e: "update:modelValue", value: boolean): void;
|
|
101
|
+
(e: "update:feedback", value: TFeedbackCreate): void;
|
|
102
|
+
(e: "close"): void;
|
|
103
|
+
(e: "submit", payload: TFeedbackCreate): void;
|
|
104
|
+
(e: "fileAdded", file: File): void;
|
|
105
|
+
(e: "fileDeleted", url: string): void;
|
|
106
|
+
}>();
|
|
107
|
+
|
|
108
|
+
const dialog = computed({
|
|
109
|
+
get: () => props.modelValue,
|
|
110
|
+
set: (val) => emit("update:modelValue", val),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const localFeedback = computed({
|
|
114
|
+
get: () => props.feedback,
|
|
115
|
+
set: (val) => emit("update:feedback", val),
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const localErroredImages = ref<string[]>(props.erroredImages || []);
|
|
119
|
+
|
|
120
|
+
watch(
|
|
121
|
+
() => props.erroredImages,
|
|
122
|
+
(val) => {
|
|
123
|
+
if (val) localErroredImages.value = val;
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const displayedAttachments = computed(() => {
|
|
128
|
+
return localFeedback.value.attachments || [];
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const { requiredRule } = useUtils();
|
|
132
|
+
|
|
133
|
+
const isFormValid = computed(() => {
|
|
134
|
+
return (
|
|
135
|
+
localFeedback.value.subject &&
|
|
136
|
+
localFeedback.value.category &&
|
|
137
|
+
localFeedback.value.location &&
|
|
138
|
+
localFeedback.value.description
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
function handleFileAdded(file: File) {
|
|
143
|
+
emit("fileAdded", file);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function deleteFile(url: string) {
|
|
147
|
+
emit("fileDeleted", url);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function onImageError(file: string) {
|
|
151
|
+
if (!localErroredImages.value.includes(file)) {
|
|
152
|
+
localErroredImages.value.push(file);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function closeDialog() {
|
|
157
|
+
dialog.value = false;
|
|
158
|
+
emit("close");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function submitFeedback() {
|
|
162
|
+
emit("submit", { ...localFeedback.value });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const { subjects } = useLocal();
|
|
166
|
+
|
|
167
|
+
const customFilter = (value: string, query: string, item: any) => {
|
|
168
|
+
const title = item?.raw?.title?.toLowerCase() || "";
|
|
169
|
+
const subtitle = item?.raw?.subtitle?.toLowerCase() || "";
|
|
170
|
+
const search = query.toLowerCase();
|
|
171
|
+
return title.includes(search) || subtitle.includes(search);
|
|
172
|
+
};
|
|
173
|
+
</script>
|