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.
Files changed (180) hide show
  1. package/.env +1 -0
  2. package/.env.production +1 -0
  3. package/.prettierrc +13 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/BUTTON_GUIDE.md +257 -0
  6. package/README.md +49 -0
  7. package/THEME_REFERENCE.md +310 -0
  8. package/eslint.config.ts +27 -0
  9. package/index.html +13 -0
  10. package/package.json +85 -0
  11. package/public/favicon.ico +0 -0
  12. package/src/App.vue +368 -0
  13. package/src/assets/fonts/Faruma.ttf +0 -0
  14. package/src/components/examples/AppBarExample.vue +101 -0
  15. package/src/components/examples/AvatarExample.vue +47 -0
  16. package/src/components/examples/BannerExample.vue +287 -0
  17. package/src/components/examples/BaseInputExample.vue +25 -0
  18. package/src/components/examples/BreadcrumbExample.vue +53 -0
  19. package/src/components/examples/CardExample.vue +77 -0
  20. package/src/components/examples/ChipExample.vue +225 -0
  21. package/src/components/examples/DatePickerExample.vue +31 -0
  22. package/src/components/examples/DropdownExample.vue +84 -0
  23. package/src/components/examples/EditorExample.vue +200 -0
  24. package/src/components/examples/ExpansionPanelExample.vue +42 -0
  25. package/src/components/examples/FileUploadExample.vue +40 -0
  26. package/src/components/examples/FormExample.vue +121 -0
  27. package/src/components/examples/HugeTest.vue +8 -0
  28. package/src/components/examples/LayoutContainerExample.vue +80 -0
  29. package/src/components/examples/ModalExample.vue +82 -0
  30. package/src/components/examples/NavDrawerExample.vue +170 -0
  31. package/src/components/examples/NumberFieldExample.vue +145 -0
  32. package/src/components/examples/RadioButtonExample.vue +161 -0
  33. package/src/components/examples/SearchExample.vue +322 -0
  34. package/src/components/examples/SelectExample.vue +121 -0
  35. package/src/components/examples/StackedTableViewExample.vue +53 -0
  36. package/src/components/examples/TabExample.vue +336 -0
  37. package/src/components/examples/TableExample.vue +228 -0
  38. package/src/components/examples/TextFieldExample.vue +181 -0
  39. package/src/components/examples/TextareaExample.vue +173 -0
  40. package/src/components/examples/ThemeToggle.vue +50 -0
  41. package/src/components/examples/TimelineExample.vue +66 -0
  42. package/src/components/examples/TipTapEditorExample.vue +20 -0
  43. package/src/components/examples/TooltipExample.vue +53 -0
  44. package/src/components/examples/VueDatePickerShowcase.vue +214 -0
  45. package/src/components/examples/_DatePickerExample.vue +33 -0
  46. package/src/components/examples/__FormExample.vue +77 -0
  47. package/src/components/index.ts +25 -0
  48. package/src/components/pgo/AppBar.vue +347 -0
  49. package/src/components/pgo/Avatar.vue +139 -0
  50. package/src/components/pgo/Banner.vue +300 -0
  51. package/src/components/pgo/Breadcrumb.vue +101 -0
  52. package/src/components/pgo/Button.vue +171 -0
  53. package/src/components/pgo/Card.vue +178 -0
  54. package/src/components/pgo/ConfirmationModel.vue +32 -0
  55. package/src/components/pgo/DataTable.vue +845 -0
  56. package/src/components/pgo/DatePicker/CalendarPanel.vue +43 -0
  57. package/src/components/pgo/DatePicker/__DatePicker.vue +122 -0
  58. package/src/components/pgo/DatePicker/types.ts +11 -0
  59. package/src/components/pgo/DatePicker/useCalendar.ts +39 -0
  60. package/src/components/pgo/DatePicker/useDatePicker.ts +31 -0
  61. package/src/components/pgo/Deprecated/ToastContainer.vue +51 -0
  62. package/src/components/pgo/Deprecated/ToastItem.vue +55 -0
  63. package/src/components/pgo/Dropdown.vue +296 -0
  64. package/src/components/pgo/DropdownItem.vue +40 -0
  65. package/src/components/pgo/Editor.vue +511 -0
  66. package/src/components/pgo/ExpansionPanel.vue +185 -0
  67. package/src/components/pgo/Footer.vue +39 -0
  68. package/src/components/pgo/HeroIcon.vue +124 -0
  69. package/src/components/pgo/InputSearch.vue +194 -0
  70. package/src/components/pgo/LayoutContainer.vue +104 -0
  71. package/src/components/pgo/Main.vue +37 -0
  72. package/src/components/pgo/Modal.vue +273 -0
  73. package/src/components/pgo/NavDrawer.vue +127 -0
  74. package/src/components/pgo/NavDrawerItem.vue +161 -0
  75. package/src/components/pgo/NavigationDrawer.vue +849 -0
  76. package/src/components/pgo/OLDNavDrawer.vue +661 -0
  77. package/src/components/pgo/OldAppBar.vue +223 -0
  78. package/src/components/pgo/PApp.vue +102 -0
  79. package/src/components/pgo/Pagination.vue +242 -0
  80. package/src/components/pgo/Search copy.vue +310 -0
  81. package/src/components/pgo/Search.vue +411 -0
  82. package/src/components/pgo/StackedTableView.vue +167 -0
  83. package/src/components/pgo/Tab.vue +617 -0
  84. package/src/components/pgo/TestInput.vue +395 -0
  85. package/src/components/pgo/Timeline.vue +367 -0
  86. package/src/components/pgo/TimelineItem.vue +80 -0
  87. package/src/components/pgo/TipTapEditor.vue +315 -0
  88. package/src/components/pgo/Tooltip.NOTES.md +12 -0
  89. package/src/components/pgo/Tooltip.PROPS.md +21 -0
  90. package/src/components/pgo/Tooltip.vue +281 -0
  91. package/src/components/pgo/base/Base.vue +444 -0
  92. package/src/components/pgo/buttons/Chip.vue +324 -0
  93. package/src/components/pgo/buttons/ChipGroup.vue +224 -0
  94. package/src/components/pgo/buttons/Radio.vue +424 -0
  95. package/src/components/pgo/filters/FilterSection.vue +188 -0
  96. package/src/components/pgo/filters/Searchbar.vue +216 -0
  97. package/src/components/pgo/forms/DynamicForm.vue +45 -0
  98. package/src/components/pgo/forms/Form.vue +132 -0
  99. package/src/components/pgo/index.ts +15 -0
  100. package/src/components/pgo/inputs/Checkbox.vue +320 -0
  101. package/src/components/pgo/inputs/DatePicker.vue +395 -0
  102. package/src/components/pgo/inputs/FileUpload.vue +326 -0
  103. package/src/components/pgo/inputs/NumberField.vue +243 -0
  104. package/src/components/pgo/inputs/Radio.vue +162 -0
  105. package/src/components/pgo/inputs/RadioGroup.vue +188 -0
  106. package/src/components/pgo/inputs/Select.vue +535 -0
  107. package/src/components/pgo/inputs/TextField.vue +194 -0
  108. package/src/components/pgo/inputs/Textarea.vue +181 -0
  109. package/src/main.js +12 -0
  110. package/src/pgo-components/_index.js +31 -0
  111. package/src/pgo-components/assets/fonts/Faruma.ttf +0 -0
  112. package/src/pgo-components/assets/fonts/logo.png +0 -0
  113. package/src/pgo-components/composables/useTheme.js +10 -0
  114. package/src/pgo-components/directives/tooltip-directive.ts +393 -0
  115. package/src/pgo-components/index.js +96 -0
  116. package/src/pgo-components/lib/componentConfig.js +147 -0
  117. package/src/pgo-components/lib/core/composables/_useCalendar.ts +127 -0
  118. package/src/pgo-components/lib/core/composables/useDefaults.ts +15 -0
  119. package/src/pgo-components/lib/core/composables/useLanguageSelect.js +0 -0
  120. package/src/pgo-components/lib/core/composables/useRtl.ts +12 -0
  121. package/src/pgo-components/lib/core/defaults/createDefaults.ts +5 -0
  122. package/src/pgo-components/lib/core/defaults/defaults.ts +7 -0
  123. package/src/pgo-components/lib/core/rtl/rtl.ts +3 -0
  124. package/src/pgo-components/lib/core/rtl/setRtl.ts +19 -0
  125. package/src/pgo-components/lib/drawerState.ts +3 -0
  126. package/src/pgo-components/lib/i18n/defaultLables.js +71 -0
  127. package/src/pgo-components/lib/i18n/i18nPlugin.js +52 -0
  128. package/src/pgo-components/lib/i18n/useI18n.js +35 -0
  129. package/src/pgo-components/lib/index.ts +38 -0
  130. package/src/pgo-components/pages/Component.vue +7 -0
  131. package/src/pgo-components/pages/ComponentRenderer.vue +85 -0
  132. package/src/pgo-components/pages/Home.vue +130 -0
  133. package/src/pgo-components/pages/ListView.vue +370 -0
  134. package/src/pgo-components/pages/Page1.vue +296 -0
  135. package/src/pgo-components/pages/_Page1.vue +180 -0
  136. package/src/pgo-components/plugins/SnackBar.vue +251 -0
  137. package/src/pgo-components/plugins/SnackBarContainer.vue +53 -0
  138. package/src/pgo-components/plugins/SnackBarPlugin.ts +136 -0
  139. package/src/pgo-components/plugins/theme-plugin.js +114 -0
  140. package/src/pgo-components/plugins/types.ts +46 -0
  141. package/src/pgo-components/plugins/useSnackBar.js +11 -0
  142. package/src/pgo-components/plugins/useSnackBar.ts +21 -0
  143. package/src/pgo-components/plugins/validation-plugin.js +11 -0
  144. package/src/pgo-components/services/Entry.json +813 -0
  145. package/src/pgo-components/services/axios.js +54 -0
  146. package/src/pgo-components/services/data.json +90 -0
  147. package/src/pgo-components/services/person.json +260 -0
  148. package/src/pgo-components/services/toast.ts +44 -0
  149. package/src/pgo-components/styles/global.css +234 -0
  150. package/src/pgo-components/styles/reset.css +96 -0
  151. package/src/pgo-components/styles/tokens.css +18 -0
  152. package/src/pgo-components/styles/utilities/border-radius.css +57 -0
  153. package/src/pgo-components/styles/utilities/borders.css +85 -0
  154. package/src/pgo-components/styles/utilities/colors.css +38 -0
  155. package/src/pgo-components/styles/utilities/cursor.css +19 -0
  156. package/src/pgo-components/styles/utilities/display.css +78 -0
  157. package/src/pgo-components/styles/utilities/elevation.css +33 -0
  158. package/src/pgo-components/styles/utilities/flex.css +403 -0
  159. package/src/pgo-components/styles/utilities/float.css +41 -0
  160. package/src/pgo-components/styles/utilities/hover.css +9 -0
  161. package/src/pgo-components/styles/utilities/index.css +18 -0
  162. package/src/pgo-components/styles/utilities/opacity.css +27 -0
  163. package/src/pgo-components/styles/utilities/overflow.css +26 -0
  164. package/src/pgo-components/styles/utilities/palette.css +515 -0
  165. package/src/pgo-components/styles/utilities/position.css +14 -0
  166. package/src/pgo-components/styles/utilities/sizing.css +70 -0
  167. package/src/pgo-components/styles/utilities/spacing.css +578 -0
  168. package/src/pgo-components/styles/utilities/transitions.css +58 -0
  169. package/src/pgo-components/styles/utilities/typography.css +91 -0
  170. package/src/pgo-components/styles/utilities/z-index.css +11 -0
  171. package/src/pgo-components/tokens/index.js +337 -0
  172. package/src/router/index.js +88 -0
  173. package/src/shims-vue.d.ts +14 -0
  174. package/src/validations/validationRules.js +50 -0
  175. package/tailwind.config.js +73 -0
  176. package/test.php +5 -0
  177. package/tsconfig.json +25 -0
  178. package/ui +31 -0
  179. package/ui.pgo.mv.conf +18 -0
  180. 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>