pgo-uiux2 1.0.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/.env +1 -0
- package/.env.production +1 -0
- package/.prettierrc +13 -0
- package/.vscode/extensions.json +3 -0
- package/BUTTON_GUIDE.md +257 -0
- package/README.md +49 -0
- package/THEME_REFERENCE.md +310 -0
- package/eslint.config.ts +27 -0
- package/index.html +13 -0
- package/package.json +85 -0
- package/public/favicon.ico +0 -0
- package/src/App.vue +368 -0
- package/src/assets/fonts/Faruma.ttf +0 -0
- package/src/components/examples/AppBarExample.vue +101 -0
- package/src/components/examples/AvatarExample.vue +47 -0
- package/src/components/examples/BannerExample.vue +287 -0
- package/src/components/examples/BaseInputExample.vue +25 -0
- package/src/components/examples/BreadcrumbExample.vue +53 -0
- package/src/components/examples/CardExample.vue +77 -0
- package/src/components/examples/ChipExample.vue +225 -0
- package/src/components/examples/DatePickerExample.vue +31 -0
- package/src/components/examples/DropdownExample.vue +84 -0
- package/src/components/examples/EditorExample.vue +200 -0
- package/src/components/examples/ExpansionPanelExample.vue +42 -0
- package/src/components/examples/FileUploadExample.vue +40 -0
- package/src/components/examples/FormExample.vue +121 -0
- package/src/components/examples/HugeTest.vue +8 -0
- package/src/components/examples/LayoutContainerExample.vue +80 -0
- package/src/components/examples/ModalExample.vue +82 -0
- package/src/components/examples/NavDrawerExample.vue +170 -0
- package/src/components/examples/NumberFieldExample.vue +145 -0
- package/src/components/examples/RadioButtonExample.vue +161 -0
- package/src/components/examples/SearchExample.vue +322 -0
- package/src/components/examples/SelectExample.vue +121 -0
- package/src/components/examples/StackedTableViewExample.vue +53 -0
- package/src/components/examples/TabExample.vue +336 -0
- package/src/components/examples/TableExample.vue +228 -0
- package/src/components/examples/TextFieldExample.vue +181 -0
- package/src/components/examples/TextareaExample.vue +173 -0
- package/src/components/examples/ThemeToggle.vue +50 -0
- package/src/components/examples/TimelineExample.vue +66 -0
- package/src/components/examples/TipTapEditorExample.vue +20 -0
- package/src/components/examples/TooltipExample.vue +53 -0
- package/src/components/examples/VueDatePickerShowcase.vue +214 -0
- package/src/components/examples/_DatePickerExample.vue +33 -0
- package/src/components/examples/__FormExample.vue +77 -0
- package/src/components/index.ts +25 -0
- package/src/components/pgo/AppBar.vue +347 -0
- package/src/components/pgo/Avatar.vue +139 -0
- package/src/components/pgo/Banner.vue +300 -0
- package/src/components/pgo/Breadcrumb.vue +101 -0
- package/src/components/pgo/Button.vue +171 -0
- package/src/components/pgo/Card.vue +178 -0
- package/src/components/pgo/ConfirmationModel.vue +32 -0
- package/src/components/pgo/DataTable.vue +845 -0
- package/src/components/pgo/DatePicker/CalendarPanel.vue +43 -0
- package/src/components/pgo/DatePicker/__DatePicker.vue +122 -0
- package/src/components/pgo/DatePicker/types.ts +11 -0
- package/src/components/pgo/DatePicker/useCalendar.ts +39 -0
- package/src/components/pgo/DatePicker/useDatePicker.ts +31 -0
- package/src/components/pgo/Deprecated/ToastContainer.vue +51 -0
- package/src/components/pgo/Deprecated/ToastItem.vue +55 -0
- package/src/components/pgo/Dropdown.vue +296 -0
- package/src/components/pgo/DropdownItem.vue +40 -0
- package/src/components/pgo/Editor.vue +511 -0
- package/src/components/pgo/ExpansionPanel.vue +185 -0
- package/src/components/pgo/Footer.vue +39 -0
- package/src/components/pgo/HeroIcon.vue +124 -0
- package/src/components/pgo/InputSearch.vue +194 -0
- package/src/components/pgo/LayoutContainer.vue +104 -0
- package/src/components/pgo/Main.vue +37 -0
- package/src/components/pgo/Modal.vue +273 -0
- package/src/components/pgo/NavDrawer.vue +127 -0
- package/src/components/pgo/NavDrawerItem.vue +161 -0
- package/src/components/pgo/NavigationDrawer.vue +849 -0
- package/src/components/pgo/OLDNavDrawer.vue +661 -0
- package/src/components/pgo/OldAppBar.vue +223 -0
- package/src/components/pgo/PApp.vue +102 -0
- package/src/components/pgo/Pagination.vue +242 -0
- package/src/components/pgo/Search copy.vue +310 -0
- package/src/components/pgo/Search.vue +411 -0
- package/src/components/pgo/StackedTableView.vue +167 -0
- package/src/components/pgo/Tab.vue +617 -0
- package/src/components/pgo/TestInput.vue +395 -0
- package/src/components/pgo/Timeline.vue +367 -0
- package/src/components/pgo/TimelineItem.vue +80 -0
- package/src/components/pgo/TipTapEditor.vue +315 -0
- package/src/components/pgo/Tooltip.NOTES.md +12 -0
- package/src/components/pgo/Tooltip.PROPS.md +21 -0
- package/src/components/pgo/Tooltip.vue +281 -0
- package/src/components/pgo/base/Base.vue +444 -0
- package/src/components/pgo/buttons/Chip.vue +324 -0
- package/src/components/pgo/buttons/ChipGroup.vue +224 -0
- package/src/components/pgo/buttons/Radio.vue +424 -0
- package/src/components/pgo/filters/FilterSection.vue +188 -0
- package/src/components/pgo/filters/Searchbar.vue +216 -0
- package/src/components/pgo/forms/DynamicForm.vue +45 -0
- package/src/components/pgo/forms/Form.vue +132 -0
- package/src/components/pgo/index.ts +15 -0
- package/src/components/pgo/inputs/Checkbox.vue +320 -0
- package/src/components/pgo/inputs/DatePicker.vue +395 -0
- package/src/components/pgo/inputs/FileUpload.vue +326 -0
- package/src/components/pgo/inputs/NumberField.vue +243 -0
- package/src/components/pgo/inputs/Radio.vue +162 -0
- package/src/components/pgo/inputs/RadioGroup.vue +188 -0
- package/src/components/pgo/inputs/Select.vue +535 -0
- package/src/components/pgo/inputs/TextField.vue +194 -0
- package/src/components/pgo/inputs/Textarea.vue +181 -0
- package/src/main.js +12 -0
- package/src/pgo-components/_index.js +31 -0
- package/src/pgo-components/assets/fonts/Faruma.ttf +0 -0
- package/src/pgo-components/assets/fonts/logo.png +0 -0
- package/src/pgo-components/composables/useTheme.js +10 -0
- package/src/pgo-components/directives/tooltip-directive.ts +393 -0
- package/src/pgo-components/index.js +96 -0
- package/src/pgo-components/lib/componentConfig.js +147 -0
- package/src/pgo-components/lib/core/composables/_useCalendar.ts +127 -0
- package/src/pgo-components/lib/core/composables/useDefaults.ts +15 -0
- package/src/pgo-components/lib/core/composables/useLanguageSelect.js +0 -0
- package/src/pgo-components/lib/core/composables/useRtl.ts +12 -0
- package/src/pgo-components/lib/core/defaults/createDefaults.ts +5 -0
- package/src/pgo-components/lib/core/defaults/defaults.ts +7 -0
- package/src/pgo-components/lib/core/rtl/rtl.ts +3 -0
- package/src/pgo-components/lib/core/rtl/setRtl.ts +19 -0
- package/src/pgo-components/lib/drawerState.ts +3 -0
- package/src/pgo-components/lib/i18n/defaultLables.js +71 -0
- package/src/pgo-components/lib/i18n/i18nPlugin.js +52 -0
- package/src/pgo-components/lib/i18n/useI18n.js +35 -0
- package/src/pgo-components/lib/index.ts +38 -0
- package/src/pgo-components/pages/Component.vue +7 -0
- package/src/pgo-components/pages/ComponentRenderer.vue +85 -0
- package/src/pgo-components/pages/Home.vue +130 -0
- package/src/pgo-components/pages/ListView.vue +370 -0
- package/src/pgo-components/pages/Page1.vue +296 -0
- package/src/pgo-components/pages/_Page1.vue +180 -0
- package/src/pgo-components/plugins/SnackBar.vue +251 -0
- package/src/pgo-components/plugins/SnackBarContainer.vue +53 -0
- package/src/pgo-components/plugins/SnackBarPlugin.ts +136 -0
- package/src/pgo-components/plugins/theme-plugin.js +114 -0
- package/src/pgo-components/plugins/types.ts +46 -0
- package/src/pgo-components/plugins/useSnackBar.js +11 -0
- package/src/pgo-components/plugins/useSnackBar.ts +21 -0
- package/src/pgo-components/plugins/validation-plugin.js +11 -0
- package/src/pgo-components/services/Entry.json +813 -0
- package/src/pgo-components/services/axios.js +54 -0
- package/src/pgo-components/services/data.json +90 -0
- package/src/pgo-components/services/person.json +260 -0
- package/src/pgo-components/services/toast.ts +44 -0
- package/src/pgo-components/styles/global.css +234 -0
- package/src/pgo-components/styles/reset.css +96 -0
- package/src/pgo-components/styles/tokens.css +18 -0
- package/src/pgo-components/styles/utilities/border-radius.css +57 -0
- package/src/pgo-components/styles/utilities/borders.css +85 -0
- package/src/pgo-components/styles/utilities/colors.css +38 -0
- package/src/pgo-components/styles/utilities/cursor.css +19 -0
- package/src/pgo-components/styles/utilities/display.css +78 -0
- package/src/pgo-components/styles/utilities/elevation.css +33 -0
- package/src/pgo-components/styles/utilities/flex.css +403 -0
- package/src/pgo-components/styles/utilities/float.css +41 -0
- package/src/pgo-components/styles/utilities/hover.css +9 -0
- package/src/pgo-components/styles/utilities/index.css +18 -0
- package/src/pgo-components/styles/utilities/opacity.css +27 -0
- package/src/pgo-components/styles/utilities/overflow.css +26 -0
- package/src/pgo-components/styles/utilities/palette.css +515 -0
- package/src/pgo-components/styles/utilities/position.css +14 -0
- package/src/pgo-components/styles/utilities/sizing.css +70 -0
- package/src/pgo-components/styles/utilities/spacing.css +578 -0
- package/src/pgo-components/styles/utilities/transitions.css +58 -0
- package/src/pgo-components/styles/utilities/typography.css +91 -0
- package/src/pgo-components/styles/utilities/z-index.css +11 -0
- package/src/pgo-components/tokens/index.js +337 -0
- package/src/router/index.js +88 -0
- package/src/shims-vue.d.ts +14 -0
- package/src/validations/validationRules.js +50 -0
- package/tailwind.config.js +73 -0
- package/test.php +5 -0
- package/tsconfig.json +25 -0
- package/ui +31 -0
- package/ui.pgo.mv.conf +18 -0
- package/vite.config.js +42 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mx-auto m-4">
|
|
3
|
+
<template v-if="items">
|
|
4
|
+
|
|
5
|
+
<!-- <hr class="border-input-border my-2" /> -->
|
|
6
|
+
<Card
|
|
7
|
+
card-class="border-none"
|
|
8
|
+
bg="vts-bg-surface-elevated"
|
|
9
|
+
padding="p-3"
|
|
10
|
+
margin="mb-4"
|
|
11
|
+
shadow="shadow-lg"
|
|
12
|
+
>
|
|
13
|
+
<Searchbar
|
|
14
|
+
v-if="searchbars"
|
|
15
|
+
:elevation="false"
|
|
16
|
+
color="none"
|
|
17
|
+
variant="contained"
|
|
18
|
+
:title="searchbars.title"
|
|
19
|
+
:quick-filters="searchbars.quickFilters"
|
|
20
|
+
:filter-section="items.componentSettings?.FilterSection ? true : false"
|
|
21
|
+
:filter-values="quickFilterValues"
|
|
22
|
+
@update:filter-values="quickFilterValues = $event"
|
|
23
|
+
@show-filter-section="showFilters = !showFilters"
|
|
24
|
+
@search="handleQuickSearch"
|
|
25
|
+
@refresh=""
|
|
26
|
+
@create-button="handleCreateButton"
|
|
27
|
+
/>
|
|
28
|
+
<Transition
|
|
29
|
+
enter-active-class="transition-all duration-300 ease-out"
|
|
30
|
+
enter-from-class="transform -translate-y-4 opacity-0"
|
|
31
|
+
enter-to-class="transform translate-y-0 opacity-100"
|
|
32
|
+
leave-active-class="transition-all duration-200 ease-in"
|
|
33
|
+
leave-from-class="transform translate-y-0 opacity-100"
|
|
34
|
+
leave-to-class="transform -translate-y-4 opacity-0"
|
|
35
|
+
>
|
|
36
|
+
|
|
37
|
+
<Card
|
|
38
|
+
v-if="items.componentSettings.FilterSection && showFilters"
|
|
39
|
+
card-class="border-dashed"
|
|
40
|
+
rounded="lg"
|
|
41
|
+
bg=""
|
|
42
|
+
margin="mt-2"
|
|
43
|
+
>
|
|
44
|
+
<FilterSection
|
|
45
|
+
|
|
46
|
+
dir=""
|
|
47
|
+
grid
|
|
48
|
+
:grid-columns="2"
|
|
49
|
+
v-model="searchbar"
|
|
50
|
+
rounded=""
|
|
51
|
+
:filters="items.componentSettings.FilterSection.filters"
|
|
52
|
+
:buttons="items.componentSettings.FilterSection.buttons"
|
|
53
|
+
@search="handleSearch"
|
|
54
|
+
@submit="handleSearch"
|
|
55
|
+
@close="showFilters = false"
|
|
56
|
+
/>
|
|
57
|
+
|
|
58
|
+
</Card>
|
|
59
|
+
</Transition>
|
|
60
|
+
</Card>
|
|
61
|
+
<DataTable
|
|
62
|
+
v-if="headers.length > 0"
|
|
63
|
+
dir=""
|
|
64
|
+
:items="tableData.data"
|
|
65
|
+
:headers="headers"
|
|
66
|
+
:server-side-options="options"
|
|
67
|
+
:loading="tableLoading"
|
|
68
|
+
title=""
|
|
69
|
+
@update:options="handleOptionsUpdate"
|
|
70
|
+
:showActions="true"
|
|
71
|
+
:inline-edit="true"
|
|
72
|
+
@inline-update="handleInlineUpdate"
|
|
73
|
+
@view="handleView"
|
|
74
|
+
@edit="handleEdit"
|
|
75
|
+
@delete="handleDelete"
|
|
76
|
+
/>
|
|
77
|
+
<div v-else class="p-8">
|
|
78
|
+
<p>No headers found</p>
|
|
79
|
+
<pre>{{ JSON.stringify(items.componentSettings, null, 2) }}</pre>
|
|
80
|
+
</div>
|
|
81
|
+
</template>
|
|
82
|
+
<div v-else class="flex items-center justify-center p-8">
|
|
83
|
+
<p>No data</p>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script setup>
|
|
89
|
+
import { ref, computed, watch, inject } from 'vue'
|
|
90
|
+
import { useRoute } from 'vue-router'
|
|
91
|
+
import DataTable from '../../components/pgo/DataTable.vue'
|
|
92
|
+
import FilterSection from '../../components/pgo/filters/FilterSection.vue'
|
|
93
|
+
import Card from '../../components/pgo/Card.vue'
|
|
94
|
+
import Searchbar from '../../components/pgo/filters/Searchbar.vue'
|
|
95
|
+
|
|
96
|
+
const api = inject('api')
|
|
97
|
+
const route = useRoute()
|
|
98
|
+
|
|
99
|
+
const props = defineProps({
|
|
100
|
+
items: {
|
|
101
|
+
type: Object,
|
|
102
|
+
required: true
|
|
103
|
+
},
|
|
104
|
+
loading: {
|
|
105
|
+
type: Boolean,
|
|
106
|
+
default: false
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const searchbars = ref({
|
|
111
|
+
title: "މީހުންގެ ލިސްޓް",
|
|
112
|
+
quickFilters: [
|
|
113
|
+
{
|
|
114
|
+
type: "ChipGroup",
|
|
115
|
+
key: "status",
|
|
116
|
+
chips: [
|
|
117
|
+
{ value: "all", label: "All" },
|
|
118
|
+
{ value: "active", label: "Active" },
|
|
119
|
+
{ value: "pending", label: "Pending" },
|
|
120
|
+
{ value: "completed", label: "Completed" }
|
|
121
|
+
],
|
|
122
|
+
color: "primary",
|
|
123
|
+
size: "small",
|
|
124
|
+
clickable: true
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
type: "ChipGroup",
|
|
128
|
+
key: "priority",
|
|
129
|
+
chips: [
|
|
130
|
+
{ value: "all", label: "All Priority" },
|
|
131
|
+
{ value: "high", label: "High" },
|
|
132
|
+
{ value: "medium", label: "Medium" },
|
|
133
|
+
{ value: "low", label: "Low" }
|
|
134
|
+
],
|
|
135
|
+
color: "secondary",
|
|
136
|
+
size: "small",
|
|
137
|
+
clickable: true
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
type: "InputSearch",
|
|
141
|
+
key: "search",
|
|
142
|
+
placeholder: "Search...",
|
|
143
|
+
size: "md"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: "DatePicker",
|
|
147
|
+
key: "dob",
|
|
148
|
+
placeholder: "DoB...",
|
|
149
|
+
size: "md"
|
|
150
|
+
}
|
|
151
|
+
],
|
|
152
|
+
buttons: [
|
|
153
|
+
{
|
|
154
|
+
type: "search",
|
|
155
|
+
color: "primary",
|
|
156
|
+
icon: "magnifying-glass",
|
|
157
|
+
variant: "contained"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: "Clear",
|
|
161
|
+
label: "Clear",
|
|
162
|
+
color: "secondary"
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const tableLoading = ref(props.loading)
|
|
168
|
+
|
|
169
|
+
const emit = defineEmits(['update:queryParams'])
|
|
170
|
+
|
|
171
|
+
const showFilters = ref(true)
|
|
172
|
+
const searchbar = ref({})
|
|
173
|
+
const quickFilterValues = ref({})
|
|
174
|
+
const tableData = ref({})
|
|
175
|
+
const createForm = ref(false)
|
|
176
|
+
|
|
177
|
+
// Manage options internally
|
|
178
|
+
const options = ref({
|
|
179
|
+
page: 1,
|
|
180
|
+
itemsPerPage: 10,
|
|
181
|
+
sortBy: [],
|
|
182
|
+
sortDesc: [],
|
|
183
|
+
itemsLength: 0
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
const fetchData = async (queryParams = {}) => {
|
|
187
|
+
try {
|
|
188
|
+
tableLoading.value = true
|
|
189
|
+
|
|
190
|
+
// Build query string from params
|
|
191
|
+
const params = new URLSearchParams({
|
|
192
|
+
...queryParams
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
console.log('Table Fetching with params:', params.toString())
|
|
196
|
+
|
|
197
|
+
const response = await api.get(`${props.items.componentSettings.table.datalink}` + (params.toString() ? '&' + params.toString() : '')) // uncomment this line to use real API)
|
|
198
|
+
// const response = person // comment this line to use real API
|
|
199
|
+
tableData.value = response
|
|
200
|
+
if (response?.pagination) {
|
|
201
|
+
options.value = {
|
|
202
|
+
...options.value,
|
|
203
|
+
page: response.pagination.current_page,
|
|
204
|
+
itemsPerPage: response.pagination.per_page,
|
|
205
|
+
itemsLength: response?.pagination.total
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
console.log('Table Fetched data:', tableData.value)
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error('Error fetching data:', error)
|
|
212
|
+
} finally {
|
|
213
|
+
tableLoading.value = false
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Update options from server response
|
|
218
|
+
watch(() => props.items, (newItems) => {
|
|
219
|
+
console.log('Items updated:', newItems)
|
|
220
|
+
console.log('Headers from API:', newItems?.componentSettings?.table?.headers)
|
|
221
|
+
fetchData()
|
|
222
|
+
if (newItems?.componentSettings?.table?.pagination) {
|
|
223
|
+
options.value = {
|
|
224
|
+
...options.value,
|
|
225
|
+
page: newItems.componentSettings.table.pagination.current_page,
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}, { immediate: true, deep: true })
|
|
229
|
+
|
|
230
|
+
const headers = computed(() => {
|
|
231
|
+
// Check different possible paths
|
|
232
|
+
const headersFromTable = props.items?.componentSettings?.table?.headers
|
|
233
|
+
const headersFromSettings = props.items?.componentSettings?.headers
|
|
234
|
+
|
|
235
|
+
console.log('Headers from table:', headersFromTable)
|
|
236
|
+
console.log('Headers from settings:', headersFromSettings)
|
|
237
|
+
console.log('Full componentSettings:', props.items?.componentSettings)
|
|
238
|
+
|
|
239
|
+
const rawHeaders = headersFromTable || headersFromSettings
|
|
240
|
+
|
|
241
|
+
if (!rawHeaders || !Array.isArray(rawHeaders)) {
|
|
242
|
+
console.warn('No valid headers array found')
|
|
243
|
+
return []
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const processedHeaders = rawHeaders
|
|
247
|
+
.filter(h => {
|
|
248
|
+
if (!h.key && !h.value) {
|
|
249
|
+
console.warn('Header missing key and value:', h)
|
|
250
|
+
return false
|
|
251
|
+
}
|
|
252
|
+
return true
|
|
253
|
+
})
|
|
254
|
+
.map(h => {
|
|
255
|
+
const header = {
|
|
256
|
+
value: h.key || h.value || '',
|
|
257
|
+
title: h.title || '',
|
|
258
|
+
sortable: h.sortable !== false,
|
|
259
|
+
lang: h.lang,
|
|
260
|
+
displayType: h.displayType || 'text',
|
|
261
|
+
displayProps: h.displayProps || {},
|
|
262
|
+
inlineEditable: h.inlineEditable || false
|
|
263
|
+
}
|
|
264
|
+
// console.log('Processed header:', header)
|
|
265
|
+
return header
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
// console.log('Final headers:', processedHeaders)
|
|
269
|
+
return processedHeaders
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
// Handle options update from DataTable
|
|
273
|
+
const handleOptionsUpdate = (newOptions) => {
|
|
274
|
+
// console.log('Options updated:', newOptions)
|
|
275
|
+
|
|
276
|
+
// Update local options
|
|
277
|
+
options.value = { ...options.value, ...newOptions }
|
|
278
|
+
|
|
279
|
+
// Build query params
|
|
280
|
+
const queryParams = {
|
|
281
|
+
page: newOptions.page,
|
|
282
|
+
per_page: newOptions.itemsPerPage
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Add sorting if exists
|
|
286
|
+
if (newOptions.sortBy && newOptions.sortBy.length > 0) {
|
|
287
|
+
const sortParams = newOptions.sortBy.map((field, index) => {
|
|
288
|
+
const isDesc = newOptions.sortDesc[index]
|
|
289
|
+
return isDesc ? `-${field}` : field
|
|
290
|
+
})
|
|
291
|
+
queryParams.sort = sortParams.join(',')
|
|
292
|
+
}
|
|
293
|
+
fetchData(queryParams)
|
|
294
|
+
// Emit to parent ComponentRenderer
|
|
295
|
+
// emit('update:queryParams', queryParams)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const handleInlineUpdate = async ({ item, key, value, updateData }) => {
|
|
299
|
+
console.log('Inline update:', { item, key, value, updateData })
|
|
300
|
+
// Optionally refetch data after update
|
|
301
|
+
// await fetchData()
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const handleSearch = (filters) => {
|
|
305
|
+
// Transform filters object into filter=key:value,key:value format
|
|
306
|
+
let filterString = ''
|
|
307
|
+
if (filters && typeof filters === 'object') {
|
|
308
|
+
const filterPairs = []
|
|
309
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
310
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
311
|
+
filterPairs.push(`${key}:${value}`)
|
|
312
|
+
}
|
|
313
|
+
})
|
|
314
|
+
if (filterPairs.length > 0) {
|
|
315
|
+
filterString = filterPairs.join(',')
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Build query params
|
|
320
|
+
const queryParams = {
|
|
321
|
+
page: 1,
|
|
322
|
+
per_page: options.value.itemsPerPage
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (filterString) {
|
|
326
|
+
queryParams.filter = filterString
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Update options and emit
|
|
330
|
+
options.value = { ...options.value, page: 1 }
|
|
331
|
+
fetchData(queryParams)
|
|
332
|
+
// emit('update:queryParams', queryParams)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Handle quick search from searchbar
|
|
336
|
+
const handleQuickSearch = (filters) => {
|
|
337
|
+
console.log('Quick search triggered:', filters)
|
|
338
|
+
// Transform filters object into filter={columnName}:{value} format
|
|
339
|
+
const filterParams = {}
|
|
340
|
+
if (filters && typeof filters === 'object') {
|
|
341
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
342
|
+
if (value !== null && value !== undefined && value !== '') {
|
|
343
|
+
filterParams[`filter[${key}]`] = value
|
|
344
|
+
}
|
|
345
|
+
})
|
|
346
|
+
}
|
|
347
|
+
// Reset to page 1 and fetch with filters
|
|
348
|
+
const newOptions = { ...options.value, ...filters, page: 1 }
|
|
349
|
+
options.value = newOptions
|
|
350
|
+
// emit('update:queryParams', newOptions)
|
|
351
|
+
fetchData(newOptions)
|
|
352
|
+
}
|
|
353
|
+
const handleCreateButton = () => {
|
|
354
|
+
console.log('Create button clicked')
|
|
355
|
+
createForm.value = !createForm.value
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const handleView = (item) => {
|
|
359
|
+
console.log('View item:', item)
|
|
360
|
+
// Navigate to detail view or open modal
|
|
361
|
+
}
|
|
362
|
+
const handleEdit = (item) => {
|
|
363
|
+
console.log('Edit item:', item)
|
|
364
|
+
// Navigate to detail view or open modal
|
|
365
|
+
}
|
|
366
|
+
const handleDelete = (item) => {
|
|
367
|
+
console.log('Delete item:', item)
|
|
368
|
+
// Navigate to detail view or open modal
|
|
369
|
+
}
|
|
370
|
+
</script>
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mx-auto m-4">
|
|
3
|
+
<!-- <ChipExample /> -->
|
|
4
|
+
<!-- <DynamicForm v-model="createForm" /> -->
|
|
5
|
+
<template v-if="items">
|
|
6
|
+
<Searchbar
|
|
7
|
+
:elevation="false"
|
|
8
|
+
:title="items.componentSettings.table.Searchbar.title"
|
|
9
|
+
:quick-filters="items.componentSettings.table.Searchbar.quickFilters"
|
|
10
|
+
:filter-section="items.componentSettings.table.FilterSection ? true : false"
|
|
11
|
+
:filter-values="quickFilterValues"
|
|
12
|
+
@update:filter-values="quickFilterValues = $event"
|
|
13
|
+
@show-filter-section="showFilters = !showFilters"
|
|
14
|
+
@search="handleQuickSearch"
|
|
15
|
+
@refresh=""
|
|
16
|
+
@create-button="handleCreateButton"
|
|
17
|
+
/>
|
|
18
|
+
<Card
|
|
19
|
+
card-class="border-none"
|
|
20
|
+
bg="bg-gray-50"
|
|
21
|
+
padding="p-3"
|
|
22
|
+
shadow="shadow"
|
|
23
|
+
>
|
|
24
|
+
<Card
|
|
25
|
+
card-class="border-dashed"
|
|
26
|
+
rounded="lg"
|
|
27
|
+
bg="bg-gray-50"
|
|
28
|
+
margin="m-0"
|
|
29
|
+
>
|
|
30
|
+
<FilterSection
|
|
31
|
+
v-if="items.componentSettings.FilterSection && showFilters"
|
|
32
|
+
dir=""
|
|
33
|
+
grid
|
|
34
|
+
:grid-columns="2"
|
|
35
|
+
v-model="searchbar"
|
|
36
|
+
rounded=""
|
|
37
|
+
:filters="items.componentSettings.FilterSection.filters"
|
|
38
|
+
:buttons="items.componentSettings.FilterSection.buttons"
|
|
39
|
+
@search="handleSearch"
|
|
40
|
+
@submit="handleSearch"
|
|
41
|
+
@close="showFilters = false"
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
</Card>
|
|
45
|
+
</Card>
|
|
46
|
+
|
|
47
|
+
<DataTable
|
|
48
|
+
dir=""
|
|
49
|
+
:items="items.data"
|
|
50
|
+
:headers="headers"
|
|
51
|
+
:server-side-options="options"
|
|
52
|
+
:loading="loading"
|
|
53
|
+
title=""
|
|
54
|
+
:showActions="true"
|
|
55
|
+
:inline-edit="true"
|
|
56
|
+
@update:options="handleOptionsUpdate"
|
|
57
|
+
@inline-update="handleInlineUpdate"
|
|
58
|
+
@view="handleView"
|
|
59
|
+
@edit="handleEdit"
|
|
60
|
+
@delete="handleDelete"
|
|
61
|
+
/>
|
|
62
|
+
</template>
|
|
63
|
+
<div v-else class="flex items-center justify-center p-8">
|
|
64
|
+
<p>No data</p>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script setup>
|
|
70
|
+
import { ref, computed, watch, inject } from 'vue'
|
|
71
|
+
import Searchbar from '../../components/pgo/filters/Searchbar.vue'
|
|
72
|
+
import FilterSection from '../../components/pgo/filters/FilterSection.vue'
|
|
73
|
+
import DataTable from '../../components/pgo/DataTable.vue'
|
|
74
|
+
import entryData from '../../pgo-components/services/person.json'
|
|
75
|
+
import DynamicForm from '../../components/pgo/forms/DynamicForm.vue'
|
|
76
|
+
import Card from '../../components/pgo/Card.vue'
|
|
77
|
+
const { language } = inject('i18n')
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
const api = inject('api')
|
|
81
|
+
|
|
82
|
+
const newheaders = [
|
|
83
|
+
// {
|
|
84
|
+
// "title": "\u078a\u07aa\u0783\u07a6\u078c\u07a6\u0789\u07a6 \u0782\u07a6\u0782\u07b0",
|
|
85
|
+
// "key": "first_name_eng",
|
|
86
|
+
// "sortable": true,
|
|
87
|
+
// "hidden": false,
|
|
88
|
+
// "lang": "en",
|
|
89
|
+
// "displayType": "text",
|
|
90
|
+
|
|
91
|
+
// },
|
|
92
|
+
{
|
|
93
|
+
"title": "\u078a\u07aa\u0783\u07a6\u078c\u07a6\u0789\u07a6 \u0782\u07a6\u0782\u07b0",
|
|
94
|
+
"key": "first_name_div",
|
|
95
|
+
"sortable": true,
|
|
96
|
+
"hidden": false,
|
|
97
|
+
"lang": "dv",
|
|
98
|
+
"displayType": "text",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"title": "\u078e\u07a6\u0787\u07aa\u0789\u07aa",
|
|
102
|
+
"key": "country.name_eng",
|
|
103
|
+
"sortable": true,
|
|
104
|
+
"hidden": false,
|
|
105
|
+
"displayType": "text",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"title": "\u0796\u07a8\u0782\u07b0\u0790\u07aa",
|
|
109
|
+
"key": "gender",
|
|
110
|
+
"sortable": false,
|
|
111
|
+
"hidden": false,
|
|
112
|
+
"displayType": "chip",
|
|
113
|
+
"displayProps": {
|
|
114
|
+
"M": {
|
|
115
|
+
"label":"Male",
|
|
116
|
+
"color": "primary",
|
|
117
|
+
"prependIcon": "user"
|
|
118
|
+
},
|
|
119
|
+
"F": {
|
|
120
|
+
"label" : "Female",
|
|
121
|
+
"color": "success",
|
|
122
|
+
"prependIcon": "users"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"title": "\u0796\u07a8\u0782\u07b0\u0790\u07aa",
|
|
128
|
+
"key": "gender",
|
|
129
|
+
"sortable": false,
|
|
130
|
+
"hidden": false,
|
|
131
|
+
"displayType": "select",
|
|
132
|
+
"inlineEditable": true,
|
|
133
|
+
"displayProps": {
|
|
134
|
+
"items": [
|
|
135
|
+
{ "title":"Male", "value":"M" },
|
|
136
|
+
{ "title": "Female", "value": "F" }
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"title": "\u0780\u07aa\u0783\u07a9 \u0780\u07a6\u0787\u07b0\u0794\u07a6\u0783\u07aa\u078e\u07a6",
|
|
142
|
+
"key": "is_in_custody",
|
|
143
|
+
"sortable": true,
|
|
144
|
+
"hidden": false,
|
|
145
|
+
"type": "boolean",
|
|
146
|
+
"lang": "en",
|
|
147
|
+
"displayType": "checkbox",
|
|
148
|
+
"inlineEditable": true,
|
|
149
|
+
"displayProps": {
|
|
150
|
+
"label": " ",
|
|
151
|
+
"color": "primary"
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"title": "\u0787\u07aa\u078a\u07a6\u0782\u07b0 \u078b\u07aa\u0788\u07a6\u0790\u07b0",
|
|
156
|
+
"key": "date_of_birth",
|
|
157
|
+
"sortable": true,
|
|
158
|
+
"hidden": false,
|
|
159
|
+
"displayType": "englishText",
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
const loading = ref(false)
|
|
164
|
+
const createForm = ref(false)
|
|
165
|
+
const showFilters = ref(true)
|
|
166
|
+
const searchbar = ref({})
|
|
167
|
+
// const items = ref({}) // Initialize as empty object instead of array
|
|
168
|
+
const items = ref(entryData) // Initialize as empty object instead of array
|
|
169
|
+
const quickFilterValues = ref({})
|
|
170
|
+
|
|
171
|
+
const options = ref({
|
|
172
|
+
page: 1,
|
|
173
|
+
itemsPerPage: 15,
|
|
174
|
+
sortBy: [],
|
|
175
|
+
sortDesc: [],
|
|
176
|
+
itemsLength: 0
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
// const fetchData = async (queryOptions = null) => {
|
|
180
|
+
// try {
|
|
181
|
+
// loading.value = true
|
|
182
|
+
|
|
183
|
+
// // Use provided options or fallback to current options
|
|
184
|
+
// const currentOptions = queryOptions || options.value
|
|
185
|
+
|
|
186
|
+
// // Build query string from options
|
|
187
|
+
// const queryParams = new URLSearchParams({
|
|
188
|
+
// page: currentOptions.page,
|
|
189
|
+
// per_page: currentOptions.itemsPerPage,
|
|
190
|
+
// component: 'listView',
|
|
191
|
+
// lang: language.value || 'dv'
|
|
192
|
+
// })
|
|
193
|
+
|
|
194
|
+
// // Add sorting if exists - using your API's format
|
|
195
|
+
// if (currentOptions.sortBy && currentOptions.sortBy.length > 0) {
|
|
196
|
+
// // For each sort field, prefix with - for descending
|
|
197
|
+
// const sortParams = currentOptions.sortBy.map((field, index) => {
|
|
198
|
+
// const isDesc = currentOptions.sortDesc[index]
|
|
199
|
+
// return isDesc ? `-${field}` : field
|
|
200
|
+
// })
|
|
201
|
+
|
|
202
|
+
// // Join multiple sorts with comma (if you support multiple sorts)
|
|
203
|
+
// queryParams.append('sort', sortParams.join(','))
|
|
204
|
+
// }
|
|
205
|
+
|
|
206
|
+
// console.log('Fetching with params:', queryParams.toString())
|
|
207
|
+
|
|
208
|
+
// const response = await api.get(`/Person?${queryParams}`)
|
|
209
|
+
// items.value = response
|
|
210
|
+
|
|
211
|
+
// // Update options with server response
|
|
212
|
+
// if (response.componentSettings?.table?.pagination) {
|
|
213
|
+
// options.value = {
|
|
214
|
+
// ...options.value,
|
|
215
|
+
// page: response.componentSettings.table.pagination.current_page,
|
|
216
|
+
// itemsPerPage: response.componentSettings.table.pagination.per_page,
|
|
217
|
+
// itemsLength: response.componentSettings.table.pagination.total,
|
|
218
|
+
// sortBy: currentOptions.sortBy,
|
|
219
|
+
// sortDesc: currentOptions.sortDesc
|
|
220
|
+
// }
|
|
221
|
+
// }
|
|
222
|
+
|
|
223
|
+
// console.log('Fetched data:', items.value)
|
|
224
|
+
// } catch (error) {
|
|
225
|
+
// console.error('Error fetching data:', error)
|
|
226
|
+
// } finally {
|
|
227
|
+
// loading.value = false
|
|
228
|
+
// }
|
|
229
|
+
// }
|
|
230
|
+
|
|
231
|
+
// fetchData()
|
|
232
|
+
|
|
233
|
+
const headers = computed(() => {
|
|
234
|
+
if (!items.value.componentSettings?.table?.headers) {
|
|
235
|
+
return []
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return items.value.componentSettings.table.headers
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
// Handle options update from DataTable
|
|
242
|
+
const handleOptionsUpdate = (newOptions) => {
|
|
243
|
+
console.log('=== handleOptionsUpdate called ===')
|
|
244
|
+
console.log('New options received:', newOptions)
|
|
245
|
+
console.log('Current options:', options.value)
|
|
246
|
+
|
|
247
|
+
// Update local options first
|
|
248
|
+
options.value = { ...options.value, ...newOptions }
|
|
249
|
+
|
|
250
|
+
console.log('Merged options:', options.value)
|
|
251
|
+
|
|
252
|
+
// Fetch new data with updated options
|
|
253
|
+
// fetchData(newOptions)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Handle quick search from searchbar
|
|
257
|
+
const handleQuickSearch = (filters) => {
|
|
258
|
+
console.log('Quick search triggered:', filters)
|
|
259
|
+
// Reset to page 1 and fetch with filters
|
|
260
|
+
const newOptions = { ...options.value, ...filters, page: 1 }
|
|
261
|
+
options.value = newOptions
|
|
262
|
+
// fetchData(newOptions)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Handle search event from FilterSection
|
|
266
|
+
const handleSearch = (filters) => {
|
|
267
|
+
console.log('Search triggered:', filters)
|
|
268
|
+
const newOptions = { ...options.value, ...filters, page: 1 }
|
|
269
|
+
options.value = newOptions
|
|
270
|
+
// fetchData(newOptions)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const handleCreateButton = () => {
|
|
274
|
+
console.log('Create button clicked')
|
|
275
|
+
createForm.value = !createForm.value
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const handleInlineUpdate = async ({ item, key, value, updateData }) => {
|
|
279
|
+
console.log('Inline update:', { item, key, value, updateData })
|
|
280
|
+
// Optionally refetch data after update
|
|
281
|
+
// await fetchData()
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const handleView = (item) => {
|
|
285
|
+
console.log('View item:', item)
|
|
286
|
+
// Navigate to detail view or open modal
|
|
287
|
+
}
|
|
288
|
+
const handleEdit = (item) => {
|
|
289
|
+
console.log('Edit item:', item)
|
|
290
|
+
// Navigate to detail view or open modal
|
|
291
|
+
}
|
|
292
|
+
const handleDelete = (item) => {
|
|
293
|
+
console.log('Delete item:', item)
|
|
294
|
+
// Navigate to detail view or open modal
|
|
295
|
+
}
|
|
296
|
+
</script>
|