@iservice365/layer-common 1.4.1 → 1.4.2
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 +6 -0
- package/components/FacilityForm.vue +226 -0
- package/components/FacilityFormAvailability.vue +13 -0
- package/components/FacilityFormBookingFee.vue +13 -0
- package/components/FacilityFormBookingPolicy.vue +13 -0
- package/components/FacilityFormDepositFee.vue +13 -0
- package/components/FacilityFormDescription.vue +13 -0
- package/components/FacilityFormInformation.vue +40 -0
- package/components/FacilityFormRefund.vue +13 -0
- package/components/FacilityFormRulesAndPolicies.vue +13 -0
- package/components/FacilityFormSecurityChecklist.vue +13 -0
- package/components/FeedbackMain.vue +143 -59
- package/components/InvitationForm.vue +27 -0
- package/components/TableMain.vue +26 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-card width="100%" :loading="processing">
|
|
3
|
+
<v-toolbar>
|
|
4
|
+
<v-row no-gutters class="fill-height px-6" align="center">
|
|
5
|
+
<span class="font-weight-bold text-h5 text-capitalize">
|
|
6
|
+
{{ prop.mode }} Facility
|
|
7
|
+
</span>
|
|
8
|
+
</v-row>
|
|
9
|
+
</v-toolbar>
|
|
10
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pa-5 my-3">
|
|
11
|
+
<v-form ref="formRef" v-model="validForm" :disabled="processing" @click="errorMessage = ''">
|
|
12
|
+
<v-row no-gutters class="pt-4">
|
|
13
|
+
|
|
14
|
+
<v-col cols="12">
|
|
15
|
+
<v-expansion-panels v-model="panels">
|
|
16
|
+
<template v-for="section in sections" :key="section.value">
|
|
17
|
+
<v-expansion-panel :value="section.value" :color="panels.includes(section.value) ? 'primary-button' : 'grey-lighten-3'" elevation="3" >
|
|
18
|
+
<v-expansion-panel-title>
|
|
19
|
+
<span class="font-weight-bold">{{ section.label }}</span>
|
|
20
|
+
</v-expansion-panel-title>
|
|
21
|
+
<v-expansion-panel-text>
|
|
22
|
+
<component :is="section.component" class="" />
|
|
23
|
+
<!-- v-model="form[section.value]" -->
|
|
24
|
+
</v-expansion-panel-text>
|
|
25
|
+
</v-expansion-panel>
|
|
26
|
+
</template>
|
|
27
|
+
</v-expansion-panels>
|
|
28
|
+
</v-col>
|
|
29
|
+
|
|
30
|
+
<v-col v-if="prop.mode === 'add'" cols="12" class="mt-2">
|
|
31
|
+
<v-checkbox v-model="createMore" density="comfortable" hide-details>
|
|
32
|
+
<template #label>
|
|
33
|
+
<span class="text-subtitle-2 font-weight-bold">
|
|
34
|
+
Create more
|
|
35
|
+
</span>
|
|
36
|
+
</template>
|
|
37
|
+
</v-checkbox>
|
|
38
|
+
</v-col>
|
|
39
|
+
|
|
40
|
+
</v-row>
|
|
41
|
+
</v-form>
|
|
42
|
+
</v-card-text>
|
|
43
|
+
|
|
44
|
+
<v-row no-gutters class="w-100" v-if="errorMessage">
|
|
45
|
+
<p class="text-error w-100 text-center text-subtitle-2">{{ errorMessage }}</p>
|
|
46
|
+
</v-row>
|
|
47
|
+
<v-toolbar density="compact">
|
|
48
|
+
<v-row no-gutters>
|
|
49
|
+
<v-col cols="6">
|
|
50
|
+
<v-btn tile block variant="text" class="text-none" size="48" @click="close" text="Close" />
|
|
51
|
+
</v-col>
|
|
52
|
+
<v-col cols="6">
|
|
53
|
+
<v-btn tile block variant="flat" color="primary-button" class="text-none" size="48" :disabled="processing || !validForm" text="Submit" />
|
|
54
|
+
</v-col>
|
|
55
|
+
</v-row>
|
|
56
|
+
</v-toolbar>
|
|
57
|
+
</v-card>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<script setup lang="ts">
|
|
61
|
+
import FacilityFormInformation from './FacilityFormInformation.vue';
|
|
62
|
+
import FacilityFormAvailability from './FacilityFormAvailability.vue';
|
|
63
|
+
import FacilityFormDescription from './FacilityFormDescription.vue';
|
|
64
|
+
import FacilityFormRefund from './FacilityFormRefund.vue';
|
|
65
|
+
import FacilityFormBookingFee from './FacilityFormBookingFee.vue';
|
|
66
|
+
import FacilityFormDepositFee from './FacilityFormDepositFee.vue';
|
|
67
|
+
import FacilityFormBookingPolicy from './FacilityFormBookingPolicy.vue';
|
|
68
|
+
import FacilityFormSecurityChecklist from './FacilityFormSecurityChecklist.vue';
|
|
69
|
+
import FacilityFormRulesAndPolicies from './FacilityFormRulesAndPolicies.vue';
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
const prop = defineProps({
|
|
74
|
+
site: {
|
|
75
|
+
type: String,
|
|
76
|
+
required: true
|
|
77
|
+
},
|
|
78
|
+
mode: {
|
|
79
|
+
type: String as PropType<'add' | 'edit'>,
|
|
80
|
+
default: 'add'
|
|
81
|
+
},
|
|
82
|
+
activeId: {
|
|
83
|
+
type: String as PropType<string | null>, // id of person you are trying to update
|
|
84
|
+
default: null
|
|
85
|
+
},
|
|
86
|
+
people: {
|
|
87
|
+
type: Object as PropType<TPeople>,
|
|
88
|
+
required: false
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { requiredRule, formatDateISO8601 } = useUtils();
|
|
93
|
+
const { getSiteById, getSiteLevels, getSiteUnits } = useSiteSettings();
|
|
94
|
+
const { create, updateById } = usePeople();
|
|
95
|
+
|
|
96
|
+
const emit = defineEmits(['back', 'select', 'done', 'done:more', 'error', 'close']);
|
|
97
|
+
const panels = ref<string[]>(['facilityInformation'])
|
|
98
|
+
|
|
99
|
+
const sections = [
|
|
100
|
+
{ label: "Facility Information", value: "facilityInformation", component: FacilityFormInformation },
|
|
101
|
+
{ label: "Facility Availability", value: "facilityAvailability", component: FacilityFormAvailability },
|
|
102
|
+
{ label: "Facility Description", value: "facilityDescription", component: FacilityFormDescription },
|
|
103
|
+
{ label: "Refund", value: "refund", component: FacilityFormRefund },
|
|
104
|
+
{ label: "Booking Fee", value: "bookingFee", component: FacilityFormBookingFee },
|
|
105
|
+
{ label: "Deposit Fee", value: "depositFee", component: FacilityFormDepositFee },
|
|
106
|
+
{ label: "Booking Policy", value: "bookingPolicy", component: FacilityFormBookingPolicy },
|
|
107
|
+
{ label: "Security Checklist", value: "securityChecklist", component: FacilityFormSecurityChecklist },
|
|
108
|
+
{ label: "Facility Rules and Policies", value: "facilityRulesAndPolicies", component: FacilityFormRulesAndPolicies },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const form = reactive<Partial<TPeoplePayload>>({})
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const validForm = ref(false);
|
|
115
|
+
const formRef = ref<HTMLFormElement | null>(null);
|
|
116
|
+
const processing = ref(false);
|
|
117
|
+
const message = ref('');
|
|
118
|
+
const errorMessage = ref('');
|
|
119
|
+
const createMore = ref(false)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const step = ref(1)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
function dateToday() {
|
|
127
|
+
const today = new Date()
|
|
128
|
+
return today.toISOString()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
function close(){
|
|
134
|
+
emit('close')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
function resetForm() {
|
|
139
|
+
formRef.value?.resetValidation();
|
|
140
|
+
Object.assign(form, {
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
validForm.value = false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
async function submit() {
|
|
149
|
+
formRef.value!.validate()
|
|
150
|
+
errorMessage.value = '';
|
|
151
|
+
processing.value = true;
|
|
152
|
+
|
|
153
|
+
let payload: Partial<TPeoplePayload> = {}
|
|
154
|
+
|
|
155
|
+
if (prop.mode === 'add') {
|
|
156
|
+
payload = {
|
|
157
|
+
...payload,
|
|
158
|
+
site: prop.site,
|
|
159
|
+
...form,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
} else if (prop.mode === 'edit') {
|
|
163
|
+
const { type, ...rest } = form
|
|
164
|
+
payload = {
|
|
165
|
+
...payload,
|
|
166
|
+
...rest
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
if (prop.mode === 'add') {
|
|
172
|
+
await create(payload)
|
|
173
|
+
} else if (prop.mode === 'edit') {
|
|
174
|
+
const userId = prop.activeId
|
|
175
|
+
if (!userId) {
|
|
176
|
+
throw new Error('User Id prop is not defined')
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
await updateById(userId, payload)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (createMore.value) {
|
|
183
|
+
resetForm()
|
|
184
|
+
step.value = 1;
|
|
185
|
+
errorMessage.value = ""
|
|
186
|
+
emit("done:more")
|
|
187
|
+
createMore.value = false
|
|
188
|
+
} else emit("done")
|
|
189
|
+
|
|
190
|
+
} catch (error: any) {
|
|
191
|
+
const err = error?.data?.message
|
|
192
|
+
errorMessage.value = err || `Failed to ${prop.mode === 'add' ? 'add' : 'update'}. Please try again.`;
|
|
193
|
+
} finally {
|
|
194
|
+
processing.value = false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async function mountExistingData() {
|
|
200
|
+
setTimeout(() => {
|
|
201
|
+
const people = prop.people
|
|
202
|
+
if (!people) return
|
|
203
|
+
|
|
204
|
+
(Object.keys(form) as (keyof typeof form)[]).forEach((key) => {
|
|
205
|
+
if (key in people) {
|
|
206
|
+
form[key] = people[key as keyof TPeople]
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
}, 100)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
onMounted(() => {
|
|
213
|
+
createMore.value = false;
|
|
214
|
+
if (prop.mode === 'edit') {
|
|
215
|
+
mountExistingData()
|
|
216
|
+
} else {
|
|
217
|
+
form.start = dateToday()
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
</script>
|
|
222
|
+
<style scoped>
|
|
223
|
+
.button-outline-class {
|
|
224
|
+
border: 1px solid rgba(var(--v-theme-primary));
|
|
225
|
+
}
|
|
226
|
+
</style>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-row no-gutters>
|
|
3
|
+
<v-col cols="12">
|
|
4
|
+
<InputLabel class="text-capitalize" title="Facility Name" required />
|
|
5
|
+
<v-text-field v-model.trim="form.name" density="compact" :rules="[requiredRule]" />
|
|
6
|
+
</v-col>
|
|
7
|
+
|
|
8
|
+
<v-col cols="12">
|
|
9
|
+
<InputLabel class="text-capitalize" title="Select Icon" required />
|
|
10
|
+
<v-select v-model="form.icon" :items="iconsArray" density="comfortable"
|
|
11
|
+
@update:model-value="handleChangeLevel" :rules="[requiredRule]" />
|
|
12
|
+
</v-col>
|
|
13
|
+
|
|
14
|
+
<v-col cols="12">
|
|
15
|
+
<InputLabel class="text-capitalize" title="Attach Image" />
|
|
16
|
+
<InputFileV2 v-model="form.gallery" multiple :max-length="3" />
|
|
17
|
+
</v-col>
|
|
18
|
+
</v-row>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
const { requiredRule } = useUtils()
|
|
23
|
+
|
|
24
|
+
const form = defineModel({
|
|
25
|
+
default: {
|
|
26
|
+
name: "",
|
|
27
|
+
icon: "",
|
|
28
|
+
gallery: [] as string[]
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const iconsArray = ref([])
|
|
33
|
+
|
|
34
|
+
function handleChangeLevel(){
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<style scoped></style>
|
|
@@ -1,78 +1,73 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<v-row no-gutters>
|
|
3
3
|
<v-col cols="12" class="mb-2">
|
|
4
|
-
<v-row no-gutters>
|
|
4
|
+
<v-row no-gutters align="center" justify="space-between">
|
|
5
5
|
<v-btn
|
|
6
6
|
class="text-none text-capitalize"
|
|
7
7
|
rounded="pill"
|
|
8
8
|
variant="tonal"
|
|
9
|
-
@click="showCreateDialog = true"
|
|
10
9
|
size="large"
|
|
10
|
+
@click="showCreateDialog = true"
|
|
11
11
|
v-if="canCreateFeedback"
|
|
12
12
|
>
|
|
13
13
|
Create Feedback
|
|
14
14
|
</v-btn>
|
|
15
|
+
|
|
16
|
+
<v-text-field
|
|
17
|
+
v-model="searchText"
|
|
18
|
+
placeholder="Search feedback..."
|
|
19
|
+
variant="outlined"
|
|
20
|
+
density="comfortable"
|
|
21
|
+
clearable
|
|
22
|
+
hide-details
|
|
23
|
+
class="ml-2"
|
|
24
|
+
style="max-width: 250px"
|
|
25
|
+
/>
|
|
15
26
|
</v-row>
|
|
16
27
|
</v-col>
|
|
17
28
|
|
|
18
29
|
<v-col cols="12">
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
:loading="loading
|
|
25
|
-
:height="'calc(100vh - 175px)'"
|
|
26
|
-
v-model:page="page"
|
|
27
|
-
:selected="selected"
|
|
28
|
-
@update:value="getAllReqRefresh"
|
|
29
|
-
@update:selected="onSelectedUpdate"
|
|
30
|
-
@click:create="showCreateDialog = true"
|
|
31
|
-
:viewPage="{ name: 'org-site-feedbacks-id' }"
|
|
32
|
-
:clickable-rows="true"
|
|
33
|
-
:length="pages"
|
|
34
|
-
@update:pagination="updatePage"
|
|
30
|
+
<v-card
|
|
31
|
+
width="100%"
|
|
32
|
+
variant="outlined"
|
|
33
|
+
border="thin"
|
|
34
|
+
rounded="lg"
|
|
35
|
+
:loading="loading"
|
|
35
36
|
>
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
>Delete</v-list-item
|
|
71
|
-
>
|
|
72
|
-
</v-list>
|
|
73
|
-
</v-menu>
|
|
74
|
-
</template>
|
|
75
|
-
</ListView>
|
|
37
|
+
<v-toolbar density="compact" color="grey-lighten-4">
|
|
38
|
+
<template #prepend>
|
|
39
|
+
<v-btn fab icon density="comfortable" @click="updatePage">
|
|
40
|
+
<v-icon>mdi-refresh</v-icon>
|
|
41
|
+
</v-btn>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<template #append>
|
|
45
|
+
<v-row no-gutters justify="end" align="center">
|
|
46
|
+
<span class="mr-2 text-caption text-fontgray">
|
|
47
|
+
{{ pageRange }}
|
|
48
|
+
</span>
|
|
49
|
+
<local-pagination
|
|
50
|
+
v-model="page"
|
|
51
|
+
:length="pages"
|
|
52
|
+
@update:value="updatePage"
|
|
53
|
+
/>
|
|
54
|
+
</v-row>
|
|
55
|
+
</template>
|
|
56
|
+
</v-toolbar>
|
|
57
|
+
|
|
58
|
+
<v-data-table
|
|
59
|
+
:headers="headers"
|
|
60
|
+
:items="items"
|
|
61
|
+
item-value="_id"
|
|
62
|
+
items-per-page="20"
|
|
63
|
+
fixed-header
|
|
64
|
+
hide-default-footer
|
|
65
|
+
hide-default-header
|
|
66
|
+
@click:row="tableRowClickHandler"
|
|
67
|
+
style="max-height: calc(100vh - (200px))"
|
|
68
|
+
>
|
|
69
|
+
</v-data-table>
|
|
70
|
+
</v-card>
|
|
76
71
|
</v-col>
|
|
77
72
|
</v-row>
|
|
78
73
|
|
|
@@ -123,6 +118,82 @@
|
|
|
123
118
|
</ConfirmDialog>
|
|
124
119
|
|
|
125
120
|
<Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
|
|
121
|
+
|
|
122
|
+
<!-- Preview Dialog -->
|
|
123
|
+
<v-dialog v-model="dialogPreview" width="450" persistent>
|
|
124
|
+
<v-card width="100%">
|
|
125
|
+
<v-card-text style="max-height: 100vh; overflow-y: auto" class="pb-0">
|
|
126
|
+
<v-row no-gutters v-if="selectedFeedback" class="mb-4">
|
|
127
|
+
<v-col cols="12">
|
|
128
|
+
<strong>Subject:</strong> {{ selectedFeedback.subject }}
|
|
129
|
+
</v-col>
|
|
130
|
+
<v-col cols="12">
|
|
131
|
+
<strong>Category:</strong>
|
|
132
|
+
{{ selectedFeedback.category }}
|
|
133
|
+
</v-col>
|
|
134
|
+
<v-col cols="12">
|
|
135
|
+
<strong>Status:</strong>
|
|
136
|
+
{{ selectedFeedback.status }}
|
|
137
|
+
</v-col>
|
|
138
|
+
</v-row>
|
|
139
|
+
</v-card-text>
|
|
140
|
+
<v-toolbar class="pa-0" density="compact">
|
|
141
|
+
<v-row no-gutters>
|
|
142
|
+
<v-col cols="6" class="pa-0">
|
|
143
|
+
<v-btn
|
|
144
|
+
block
|
|
145
|
+
variant="text"
|
|
146
|
+
class="text-none"
|
|
147
|
+
size="large"
|
|
148
|
+
@click="dialogPreview = false"
|
|
149
|
+
height="48"
|
|
150
|
+
>
|
|
151
|
+
Close
|
|
152
|
+
</v-btn>
|
|
153
|
+
</v-col>
|
|
154
|
+
<v-col cols="6" class="pa-0">
|
|
155
|
+
<v-menu>
|
|
156
|
+
<template #activator="{ props }">
|
|
157
|
+
<v-btn
|
|
158
|
+
block
|
|
159
|
+
variant="flat"
|
|
160
|
+
color="black"
|
|
161
|
+
class="text-none"
|
|
162
|
+
height="48"
|
|
163
|
+
v-bind="props"
|
|
164
|
+
tile
|
|
165
|
+
>
|
|
166
|
+
More actions
|
|
167
|
+
</v-btn>
|
|
168
|
+
</template>
|
|
169
|
+
|
|
170
|
+
<v-list class="pa-0">
|
|
171
|
+
<v-list-item @click="onViewFeedback(selectedFeedback)">
|
|
172
|
+
<v-list-item-title class="text-subtitle-2">
|
|
173
|
+
View
|
|
174
|
+
</v-list-item-title>
|
|
175
|
+
</v-list-item>
|
|
176
|
+
<v-list-item @click="editFeedback(selectedFeedback)">
|
|
177
|
+
<v-list-item-title class="text-subtitle-2">
|
|
178
|
+
Edit
|
|
179
|
+
</v-list-item-title>
|
|
180
|
+
</v-list-item>
|
|
181
|
+
|
|
182
|
+
<v-list-item
|
|
183
|
+
@click="confirmDeleteFeedback(selectedFeedback)"
|
|
184
|
+
class="text-red"
|
|
185
|
+
>
|
|
186
|
+
<v-list-item-title class="text-subtitle-2">
|
|
187
|
+
Delete
|
|
188
|
+
</v-list-item-title>
|
|
189
|
+
</v-list-item>
|
|
190
|
+
</v-list>
|
|
191
|
+
</v-menu>
|
|
192
|
+
</v-col>
|
|
193
|
+
</v-row>
|
|
194
|
+
</v-toolbar>
|
|
195
|
+
</v-card></v-dialog
|
|
196
|
+
>
|
|
126
197
|
</template>
|
|
127
198
|
|
|
128
199
|
<script setup lang="ts">
|
|
@@ -225,7 +296,7 @@ const selected = ref<string[]>([]);
|
|
|
225
296
|
|
|
226
297
|
const { getColorStatus } = useUtils();
|
|
227
298
|
|
|
228
|
-
const headers = [
|
|
299
|
+
const headers: Array<Record<string, any>> = [
|
|
229
300
|
{ title: "Name", value: "createdByName", align: "start" },
|
|
230
301
|
{ title: "Subject", value: "subject", align: "start" },
|
|
231
302
|
{ title: "Category", value: "category", align: "start" },
|
|
@@ -311,6 +382,7 @@ async function editFeedback(item: any) {
|
|
|
311
382
|
_feedbackId.value = item._id;
|
|
312
383
|
isEditMode.value = true;
|
|
313
384
|
showCreateDialog.value = true;
|
|
385
|
+
dialogPreview.value = false;
|
|
314
386
|
} catch (error) {
|
|
315
387
|
showMessage("Failed to load full feedback", "error");
|
|
316
388
|
}
|
|
@@ -326,6 +398,7 @@ function onViewFeedback(item: any) {
|
|
|
326
398
|
name: props.detailRoute,
|
|
327
399
|
params: { org, site, id },
|
|
328
400
|
});
|
|
401
|
+
dialogPreview.value = false;
|
|
329
402
|
}
|
|
330
403
|
|
|
331
404
|
function confirmDeleteFeedback(item: any) {
|
|
@@ -349,6 +422,7 @@ async function submitDelete() {
|
|
|
349
422
|
submitting.value = false;
|
|
350
423
|
showDeleteDialog.value = false;
|
|
351
424
|
feedbackToDelete.value = null;
|
|
425
|
+
dialogPreview.value = false;
|
|
352
426
|
}
|
|
353
427
|
}
|
|
354
428
|
|
|
@@ -483,5 +557,15 @@ const categories = computed(() =>
|
|
|
483
557
|
}))
|
|
484
558
|
);
|
|
485
559
|
|
|
560
|
+
function tableRowClickHandler(_: any, data: any) {
|
|
561
|
+
console.log(data.item);
|
|
562
|
+
selectedFeedback.value = data.item;
|
|
563
|
+
dialogPreview.value = true;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const dialogPreview = ref(false);
|
|
567
|
+
const selectedFeedback = ref<TFeedback | null>(null);
|
|
568
|
+
const searchText = ref("")
|
|
569
|
+
|
|
486
570
|
getServiceProviderCategories();
|
|
487
571
|
</script>
|
|
@@ -235,6 +235,33 @@ const apps = computed(() => {
|
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
const _pestControl = "pest_control_services";
|
|
239
|
+
|
|
240
|
+
if (props.app === _pestControl || orgNature.value === _pestControl) {
|
|
241
|
+
items.push({
|
|
242
|
+
title: "Pest Control Services",
|
|
243
|
+
value: _pestControl,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const _landscaping = "landscaping_services";
|
|
248
|
+
|
|
249
|
+
if (props.app === _landscaping || orgNature.value === _landscaping) {
|
|
250
|
+
items.push({
|
|
251
|
+
title: "Landscaping Services",
|
|
252
|
+
value: _landscaping,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const _poolMaintenance = "pool_maintenance_services";
|
|
257
|
+
|
|
258
|
+
if (props.app === _poolMaintenance || orgNature.value === _poolMaintenance) {
|
|
259
|
+
items.push({
|
|
260
|
+
title: "Pool Maintenance Services",
|
|
261
|
+
value: _poolMaintenance,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
238
265
|
return items;
|
|
239
266
|
});
|
|
240
267
|
|
package/components/TableMain.vue
CHANGED
|
@@ -4,11 +4,18 @@
|
|
|
4
4
|
<v-col cols="12" class="mb-2" v-if="(canCreate || $slots.actions)">
|
|
5
5
|
<v-row no-gutters>
|
|
6
6
|
<slot name="actions">
|
|
7
|
-
<v-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
<v-col cols="12">
|
|
8
|
+
<v-row no-gutters justify="space-between">
|
|
9
|
+
<v-btn v-if="canCreate" class="text-none" rounded="pill" variant="tonal" size="large"
|
|
10
|
+
@click="emits('create')">
|
|
11
|
+
{{ createLabel }}
|
|
12
|
+
</v-btn>
|
|
13
|
+
<v-text-field v-if="props.canSearch" v-model="searchInput" density="compact" placeholder="Search" clearable max-width="300"
|
|
14
|
+
append-inner-icon="mdi-magnify" hide-details />
|
|
15
|
+
</v-row>
|
|
16
|
+
</v-col>
|
|
11
17
|
</slot>
|
|
18
|
+
|
|
12
19
|
</v-row>
|
|
13
20
|
</v-col>
|
|
14
21
|
|
|
@@ -35,7 +42,7 @@
|
|
|
35
42
|
</template>
|
|
36
43
|
|
|
37
44
|
<template v-if="$slots.extension" #extension>
|
|
38
|
-
<slot name="extension"/>
|
|
45
|
+
<slot name="extension" />
|
|
39
46
|
</template>
|
|
40
47
|
</v-toolbar>
|
|
41
48
|
|
|
@@ -43,12 +50,13 @@
|
|
|
43
50
|
<!-- Data Table -->
|
|
44
51
|
<v-data-table :headers="headers" :items="items" :item-value="itemValue" :items-per-page="itemsPerPage"
|
|
45
52
|
fixed-header hide-default-footer :hide-default-header="!showHeader"
|
|
46
|
-
@click:row="(_: any, data: any) => emits('row-click', data)"
|
|
53
|
+
@click:row="(_: any, data: any) => emits('row-click', data)"
|
|
54
|
+
:style="`max-height: calc(100vh - (${offset}px))`">
|
|
47
55
|
<template v-for="(_, slotName) in $slots" #[slotName]="slotProps">
|
|
48
56
|
<slot :name="slotName" v-bind="slotProps" />
|
|
49
57
|
</template>
|
|
50
58
|
</v-data-table>
|
|
51
|
-
<slot
|
|
59
|
+
<slot name="footer" />
|
|
52
60
|
</v-card>
|
|
53
61
|
</v-col>
|
|
54
62
|
</v-row>
|
|
@@ -72,6 +80,10 @@ const props = defineProps({
|
|
|
72
80
|
type: Boolean,
|
|
73
81
|
default: false,
|
|
74
82
|
},
|
|
83
|
+
canSearch: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: false,
|
|
86
|
+
},
|
|
75
87
|
createLabel: {
|
|
76
88
|
type: String,
|
|
77
89
|
default: "Add",
|
|
@@ -112,6 +124,8 @@ const props = defineProps({
|
|
|
112
124
|
|
|
113
125
|
const emits = defineEmits(["create", "refresh", "update:page", "row-click"]);
|
|
114
126
|
|
|
127
|
+
const searchInput = defineModel('search', { default: "" })
|
|
128
|
+
|
|
115
129
|
const internalPage = ref(props.page);
|
|
116
130
|
watch(
|
|
117
131
|
() => props.page,
|
|
@@ -121,4 +135,8 @@ watch(
|
|
|
121
135
|
);
|
|
122
136
|
</script>
|
|
123
137
|
|
|
124
|
-
<style scoped
|
|
138
|
+
<style scoped>
|
|
139
|
+
.v-data-table :deep(thead th) {
|
|
140
|
+
font-weight: bold !important;
|
|
141
|
+
}
|
|
142
|
+
</style>
|