@dasidev/dasi-ui 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 (450) hide show
  1. package/README.md +346 -0
  2. package/bin/dasi-cli.cjs +184 -0
  3. package/dist/date-selector-test-BlukYeWl.js +91 -0
  4. package/dist/favicon.ico +0 -0
  5. package/dist/html2canvas.esm-CKxSAI8P.js +4886 -0
  6. package/dist/img/brand/ic_pln.svg +12 -0
  7. package/dist/img/brand/mapp_power_logo.svg +21 -0
  8. package/dist/img/common/pltu_ulumbu_flores_ntt.jpeg +0 -0
  9. package/dist/index-BQSA2aPs.js +126556 -0
  10. package/dist/index.es-DQWt-PZn.js +5769 -0
  11. package/dist/index.es.js +11 -0
  12. package/dist/index.umd.js +8564 -0
  13. package/dist/informasi-gudang-BmoEy2RL.js +164 -0
  14. package/dist/informasi-gudang-DXfS46Nh.js +50 -0
  15. package/dist/purify.es-C-9oolON.js +546 -0
  16. package/dist/scripts/pdf.worker.min.js +29 -0
  17. package/dist/scripts/pdf.worker.min.mjs +29 -0
  18. package/dist/scripts/pdf.worker.mjs +57722 -0
  19. package/dist/scripts/pdf.worker.mjs.map +1 -0
  20. package/dist/style.css +1 -0
  21. package/dist/test-schema-JFghGc0_.js +8 -0
  22. package/dist/test-schema-uusFsJe4.js +438 -0
  23. package/dist/types-l0sNRNKZ.js +1 -0
  24. package/package.json +178 -0
  25. package/src/App.vue +18 -0
  26. package/src/__tests__/index.test.ts +9 -0
  27. package/src/api/api.ts +117 -0
  28. package/src/assets/app-selector.svg +3 -0
  29. package/src/assets/dasi.png +0 -0
  30. package/src/assets/foto_ss.svg +21 -0
  31. package/src/assets/icons/circle-blue.svg +4 -0
  32. package/src/assets/icons/circle-gray.svg +15 -0
  33. package/src/assets/icons/circle-green.svg +4 -0
  34. package/src/assets/icons/circle-orange.svg +4 -0
  35. package/src/assets/icons/circle-purple.svg +4 -0
  36. package/src/assets/icons/circle-red.svg +15 -0
  37. package/src/assets/icons/harbor.svg +12 -0
  38. package/src/assets/icons/ic-box-red.svg +8 -0
  39. package/src/assets/icons/ic-chevron-right.svg +1 -0
  40. package/src/assets/icons/ic-loading.svg +9 -0
  41. package/src/assets/icons/ic-reset.svg +16 -0
  42. package/src/assets/icons/ic-sailing.svg +5 -0
  43. package/src/assets/icons/icon-app-selector.svg +3 -0
  44. package/src/assets/icons/icon-browser-check.svg +4 -0
  45. package/src/assets/icons/icon-calendar.svg +3 -0
  46. package/src/assets/icons/icon-chart-bar.svg +3 -0
  47. package/src/assets/icons/icon-chart-doc.svg +16 -0
  48. package/src/assets/icons/icon-chart-line.svg +10 -0
  49. package/src/assets/icons/icon-chart-mix.svg +15 -0
  50. package/src/assets/icons/icon-chart-pie.svg +11 -0
  51. package/src/assets/icons/icon-continue.svg +12 -0
  52. package/src/assets/icons/icon-dashboard-2.svg +17 -0
  53. package/src/assets/icons/icon-dashboard.svg +3 -0
  54. package/src/assets/icons/icon-data-kelistrikan.svg +19 -0
  55. package/src/assets/icons/icon-data-sentral.svg +11 -0
  56. package/src/assets/icons/icon-database.svg +5 -0
  57. package/src/assets/icons/icon-desktop.svg +3 -0
  58. package/src/assets/icons/icon-download.svg +13 -0
  59. package/src/assets/icons/icon-energi-primer.svg +12 -0
  60. package/src/assets/icons/icon-faba-apk2.svg +11 -0
  61. package/src/assets/icons/icon-faba.svg +11 -0
  62. package/src/assets/icons/icon-factory.svg +14 -0
  63. package/src/assets/icons/icon-globe-doc.svg +19 -0
  64. package/src/assets/icons/icon-ikk.svg +10 -0
  65. package/src/assets/icons/icon-kbb.svg +13 -0
  66. package/src/assets/icons/icon-kos.svg +16 -0
  67. package/src/assets/icons/icon-kpi-bod.svg +15 -0
  68. package/src/assets/icons/icon-kss.svg +14 -0
  69. package/src/assets/icons/icon-map.svg +12 -0
  70. package/src/assets/icons/icon-monitoring-harian.svg +13 -0
  71. package/src/assets/icons/icon-notification.svg +4 -0
  72. package/src/assets/icons/icon-overview.svg +17 -0
  73. package/src/assets/icons/icon-pltu.svg +13 -0
  74. package/src/assets/icons/icon-sebaran-sentral.svg +12 -0
  75. package/src/assets/icons/icon-select-data-kelistrikan.svg +19 -0
  76. package/src/assets/icons/icon-select-data-sentral.svg +11 -0
  77. package/src/assets/icons/icon-select-energi-primer.svg +12 -0
  78. package/src/assets/icons/icon-select-faba-apk2.svg +11 -0
  79. package/src/assets/icons/icon-select-ikk.svg +10 -0
  80. package/src/assets/icons/icon-select-kbb.svg +13 -0
  81. package/src/assets/icons/icon-select-kos.svg +16 -0
  82. package/src/assets/icons/icon-select-kpi-bod.svg +15 -0
  83. package/src/assets/icons/icon-select-kss.svg +14 -0
  84. package/src/assets/icons/icon-select-monitoring-harian.svg +13 -0
  85. package/src/assets/icons/icon-select-overview.svg +17 -0
  86. package/src/assets/icons/icon-select-sebaran-sentral.svg +12 -0
  87. package/src/assets/icons/icon-sentral-white.svg +13 -0
  88. package/src/assets/icons/icon-shipping.svg +5 -0
  89. package/src/assets/icons/icon-sort.svg +5 -0
  90. package/src/assets/icons/icon-tree-box.svg +14 -0
  91. package/src/assets/icons/icon-warehouse.svg +12 -0
  92. package/src/assets/icons/pin-green.svg +3 -0
  93. package/src/assets/icons/pin-orange.svg +3 -0
  94. package/src/assets/icons/pin-purple.svg +3 -0
  95. package/src/assets/icons/ship.svg +3 -0
  96. package/src/assets/icons/shipment/icon-antri.svg +15 -0
  97. package/src/assets/icons/shipment/icon-bongkar.svg +4 -0
  98. package/src/assets/icons/shipment/icon-invoice.svg +6 -0
  99. package/src/assets/icons/shipment/icon-loading.svg +8 -0
  100. package/src/assets/icons/shipment/icon-pembayaran.svg +13 -0
  101. package/src/assets/icons/shipment/icon-pengiriman.svg +4 -0
  102. package/src/assets/icons/shipment/icon-sailing.svg +4 -0
  103. package/src/assets/icons/shipment/icon-shipment-completed.svg +6 -0
  104. package/src/assets/icons/shipment/icon-shipment-in-progress.svg +6 -0
  105. package/src/assets/icons/shipment/icon-shipment-over-sla.svg +6 -0
  106. package/src/assets/icons/shipment/icon-spt.svg +4 -0
  107. package/src/assets/icons/shipment/icon-total-shipment.svg +4 -0
  108. package/src/assets/icons/upload_doc_icon.svg +42 -0
  109. package/src/assets/icons/upload_icon_blue.svg +14 -0
  110. package/src/assets/login-bg-day-min.jpg +0 -0
  111. package/src/assets/login-bg-night-min.jpg +0 -0
  112. package/src/assets/login-bg.jpg +0 -0
  113. package/src/assets/login-day.png +0 -0
  114. package/src/assets/login-night.png +0 -0
  115. package/src/assets/lucide-circle-plus-blue.svg +1 -0
  116. package/src/assets/pdf-logo.svg +11 -0
  117. package/src/assets/pemasok-card-bg.svg +6 -0
  118. package/src/assets/success_animation.gif +0 -0
  119. package/src/assets/success_animation.mp4 +0 -0
  120. package/src/assets/success_animation.webm +0 -0
  121. package/src/components/button/BtnAddOutline.vue +14 -0
  122. package/src/components/button/BtnCircle.vue +10 -0
  123. package/src/components/button/BtnOutline.vue +15 -0
  124. package/src/components/button/BtnPrimary.vue +25 -0
  125. package/src/components/button/BtnSecondary.vue +26 -0
  126. package/src/components/detail/AccountDetailTimeline.vue +144 -0
  127. package/src/components/detail/ApprovalInfo.vue +288 -0
  128. package/src/components/detail/DCI2.vue +164 -0
  129. package/src/components/detail/DetailContentHeader.vue +83 -0
  130. package/src/components/detail/DetailContentItem.vue +186 -0
  131. package/src/components/detail/DetailContentItems.vue +388 -0
  132. package/src/components/detail/DetailContentLoading.vue +12 -0
  133. package/src/components/detail/DetailContentTablet.vue +10 -0
  134. package/src/components/detail/DetailSheet.vue +294 -0
  135. package/src/components/detail/DetailTimeline.vue +191 -0
  136. package/src/components/detail/DocApprovalDialog.vue +29 -0
  137. package/src/components/detail/DocViewerContent.vue +991 -0
  138. package/src/components/dialog/ConfirmDialog.vue +96 -0
  139. package/src/components/dialog/DialogBase.vue +53 -0
  140. package/src/components/dialog/DialogSelect.vue +212 -0
  141. package/src/components/dialog/ErrorDialog.vue +63 -0
  142. package/src/components/dialog/FormDialog.vue +141 -0
  143. package/src/components/dialog/FormInputerDialog.vue +91 -0
  144. package/src/components/dialog/InfoDialog.vue +74 -0
  145. package/src/components/dialog/SuccessDialog.vue +51 -0
  146. package/src/components/examples/TestSchemaExample.vue +288 -0
  147. package/src/components/forms/auth/LoginForm.vue +806 -0
  148. package/src/components/forms/auth/PwdScore.vue +68 -0
  149. package/src/components/helper/ApiTester.vue +153 -0
  150. package/src/components/helper/ChangePwd.vue +150 -0
  151. package/src/components/helper/CheckboxElement.vue +43 -0
  152. package/src/components/helper/ConfigSwitcher.vue +54 -0
  153. package/src/components/helper/Copyright.vue +10 -0
  154. package/src/components/helper/ErrorScreen.vue +40 -0
  155. package/src/components/helper/LucideIcon.vue +27 -0
  156. package/src/components/helper/PdfViewer.vue +103 -0
  157. package/src/components/helper/PinInputer.vue +205 -0
  158. package/src/components/helper/PrivacyPolicy.vue +122 -0
  159. package/src/components/layout/PageActivityHeader.vue +48 -0
  160. package/src/components/layout/PageHeader.vue +70 -0
  161. package/src/components/loadings/LoadingDialog.vue +29 -0
  162. package/src/components/loadings/LoadingDialogSpin.vue +25 -0
  163. package/src/components/loadings/LoadingIndicator.vue +38 -0
  164. package/src/components/loadings/LoadingScreen.vue +23 -0
  165. package/src/components/notif/Notif.vue +103 -0
  166. package/src/components/notif/NotifItem.vue +41 -0
  167. package/src/components/pages/Header.vue +431 -0
  168. package/src/components/pages/Leftbar.vue +417 -0
  169. package/src/components/pages/PageActivity.vue +108 -0
  170. package/src/components/pages/PageActivityContent.vue +597 -0
  171. package/src/components/pages/PageContentTable.vue +589 -0
  172. package/src/components/pages/PageTab.vue +84 -0
  173. package/src/components/selector/BaseSelector.vue +1136 -0
  174. package/src/components/selector/ConfigDataSelector.vue +136 -0
  175. package/src/components/settings/SettingsItem.vue +38 -0
  176. package/src/components/tab/TabView.vue +11 -0
  177. package/src/components/tab/TabViewItem.vue +18 -0
  178. package/src/components/tab/TabViewItemBar.vue +9 -0
  179. package/src/components/tables/CellHover.vue +65 -0
  180. package/src/components/tables/DashboardDataTable.vue +707 -0
  181. package/src/components/tables/DataStatusTag.vue +52 -0
  182. package/src/components/tables/DataTable.vue +156 -0
  183. package/src/components/tables/DataTableAccordion.vue +249 -0
  184. package/src/components/tables/DataTableActionRow.vue +64 -0
  185. package/src/components/tables/DataTableCell.vue +272 -0
  186. package/src/components/tables/DataTableHeader.vue +60 -0
  187. package/src/components/tables/DataTableRow.vue +213 -0
  188. package/src/components/tables/ExpandedTable.vue +259 -0
  189. package/src/components/tables/PageTable.vue +73 -0
  190. package/src/components/tables/Pagination.vue +98 -0
  191. package/src/components/tables/dropdown/BaseDropdownTable.vue +140 -0
  192. package/src/components/tables/dropdown/DropdownTableActivity.vue +33 -0
  193. package/src/components/tables/dropdown/DropdownTableAsset.vue +30 -0
  194. package/src/components/tables/dropdown/DropdownTableConfig.vue +30 -0
  195. package/src/components/tables/dropdown/DropdownTableDataKonektor.vue +31 -0
  196. package/src/components/tables/dropdown/DropdownTableDataLabel.vue +30 -0
  197. package/src/components/tables/dropdown/DropdownTableDataSchema.vue +31 -0
  198. package/src/components/tables/dropdown/DropdownTableFabaPemanfaat.vue +30 -0
  199. package/src/components/tables/dropdown/DropdownTableGroup.vue +36 -0
  200. package/src/components/tables/dropdown/DropdownTableHalaman.vue +33 -0
  201. package/src/components/tables/dropdown/DropdownTableLevel.vue +66 -0
  202. package/src/components/tables/dropdown/DropdownTableOrganization.vue +47 -0
  203. package/src/components/tables/dropdown/DropdownTablePengelola.vue +28 -0
  204. package/src/components/tables/dropdown/DropdownTableQueryLayer.vue +29 -0
  205. package/src/components/tables/dropdown/DropdownTableSentral.vue +33 -0
  206. package/src/components/tables/dropdown/DropdownTableWarehouse.vue +30 -0
  207. package/src/components/tables/dropdown/TableDropdown.vue +52 -0
  208. package/src/components/ui/accordion/Accordion.vue +19 -0
  209. package/src/components/ui/accordion/AccordionContent.vue +24 -0
  210. package/src/components/ui/accordion/AccordionItem.vue +24 -0
  211. package/src/components/ui/accordion/AccordionTrigger.vue +42 -0
  212. package/src/components/ui/accordion/index.ts +4 -0
  213. package/src/components/ui/alert-dialog/AlertDialog.vue +14 -0
  214. package/src/components/ui/alert-dialog/AlertDialogAction.vue +20 -0
  215. package/src/components/ui/alert-dialog/AlertDialogCancel.vue +20 -0
  216. package/src/components/ui/alert-dialog/AlertDialogContent.vue +42 -0
  217. package/src/components/ui/alert-dialog/AlertDialogDescription.vue +25 -0
  218. package/src/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
  219. package/src/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
  220. package/src/components/ui/alert-dialog/AlertDialogTitle.vue +22 -0
  221. package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
  222. package/src/components/ui/alert-dialog/index.ts +9 -0
  223. package/src/components/ui/avatar/Avatar.vue +24 -0
  224. package/src/components/ui/avatar/AvatarFallback.vue +11 -0
  225. package/src/components/ui/avatar/AvatarImage.vue +9 -0
  226. package/src/components/ui/avatar/UsersAvatar.vue +28 -0
  227. package/src/components/ui/avatar/index.ts +24 -0
  228. package/src/components/ui/button/Button.vue +27 -0
  229. package/src/components/ui/button/index.ts +34 -0
  230. package/src/components/ui/calendar/Calendar.vue +325 -0
  231. package/src/components/ui/calendar/index.ts +22 -0
  232. package/src/components/ui/checkbox/Checkbox.vue +33 -0
  233. package/src/components/ui/checkbox/index.ts +1 -0
  234. package/src/components/ui/command/Command.vue +30 -0
  235. package/src/components/ui/command/CommandDialog.vue +21 -0
  236. package/src/components/ui/command/CommandEmpty.vue +20 -0
  237. package/src/components/ui/command/CommandGroup.vue +29 -0
  238. package/src/components/ui/command/CommandInput.vue +33 -0
  239. package/src/components/ui/command/CommandItem.vue +26 -0
  240. package/src/components/ui/command/CommandList.vue +27 -0
  241. package/src/components/ui/command/CommandSeparator.vue +23 -0
  242. package/src/components/ui/command/CommandShortcut.vue +14 -0
  243. package/src/components/ui/command/index.ts +9 -0
  244. package/src/components/ui/context-menu/ContextMenu.vue +15 -0
  245. package/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +40 -0
  246. package/src/components/ui/context-menu/ContextMenuContent.vue +36 -0
  247. package/src/components/ui/context-menu/ContextMenuGroup.vue +11 -0
  248. package/src/components/ui/context-menu/ContextMenuItem.vue +34 -0
  249. package/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
  250. package/src/components/ui/context-menu/ContextMenuPortal.vue +11 -0
  251. package/src/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
  252. package/src/components/ui/context-menu/ContextMenuRadioItem.vue +40 -0
  253. package/src/components/ui/context-menu/ContextMenuSeparator.vue +20 -0
  254. package/src/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
  255. package/src/components/ui/context-menu/ContextMenuSub.vue +19 -0
  256. package/src/components/ui/context-menu/ContextMenuSubContent.vue +35 -0
  257. package/src/components/ui/context-menu/ContextMenuSubTrigger.vue +34 -0
  258. package/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
  259. package/src/components/ui/context-menu/index.ts +14 -0
  260. package/src/components/ui/datetime/DatetimeRangeComponent.vue +52 -0
  261. package/src/components/ui/dialog/Dialog.vue +14 -0
  262. package/src/components/ui/dialog/DialogClose.vue +11 -0
  263. package/src/components/ui/dialog/DialogContent.vue +53 -0
  264. package/src/components/ui/dialog/DialogDescription.vue +24 -0
  265. package/src/components/ui/dialog/DialogFooter.vue +19 -0
  266. package/src/components/ui/dialog/DialogHeader.vue +16 -0
  267. package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  268. package/src/components/ui/dialog/DialogTitle.vue +29 -0
  269. package/src/components/ui/dialog/DialogTrigger.vue +11 -0
  270. package/src/components/ui/dialog/index.ts +9 -0
  271. package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  272. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  273. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
  274. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  275. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
  276. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
  277. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  278. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
  279. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
  280. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  281. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  282. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  283. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
  284. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  285. package/src/components/ui/dropdown-menu/index.ts +16 -0
  286. package/src/components/ui/form/FormControl.vue +16 -0
  287. package/src/components/ui/form/FormDescription.vue +20 -0
  288. package/src/components/ui/form/FormItem.vue +25 -0
  289. package/src/components/ui/form/FormLabel.vue +23 -0
  290. package/src/components/ui/form/FormMessage.vue +16 -0
  291. package/src/components/ui/form/index.ts +6 -0
  292. package/src/components/ui/form/useFormField.ts +30 -0
  293. package/src/components/ui/hover-card/HoverCard.vue +14 -0
  294. package/src/components/ui/hover-card/HoverCardContent.vue +41 -0
  295. package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
  296. package/src/components/ui/hover-card/index.ts +3 -0
  297. package/src/components/ui/input/Input.vue +24 -0
  298. package/src/components/ui/input/index.ts +1 -0
  299. package/src/components/ui/label/Label.vue +27 -0
  300. package/src/components/ui/label/index.ts +1 -0
  301. package/src/components/ui/pagination/PaginationEllipsis.vue +22 -0
  302. package/src/components/ui/pagination/PaginationFirst.vue +29 -0
  303. package/src/components/ui/pagination/PaginationLast.vue +29 -0
  304. package/src/components/ui/pagination/PaginationNext.vue +29 -0
  305. package/src/components/ui/pagination/PaginationPrev.vue +29 -0
  306. package/src/components/ui/pagination/index.ts +10 -0
  307. package/src/components/ui/pin-input/PinInput.vue +23 -0
  308. package/src/components/ui/pin-input/PinInputGroup.vue +18 -0
  309. package/src/components/ui/pin-input/PinInputInput.vue +18 -0
  310. package/src/components/ui/pin-input/PinInputSeparator.vue +15 -0
  311. package/src/components/ui/pin-input/index.ts +4 -0
  312. package/src/components/ui/popover/Popover.vue +15 -0
  313. package/src/components/ui/popover/PopoverContent.vue +48 -0
  314. package/src/components/ui/popover/PopoverTrigger.vue +11 -0
  315. package/src/components/ui/popover/index.ts +4 -0
  316. package/src/components/ui/preview/PreviewPdf.vue +118 -0
  317. package/src/components/ui/progress/ProgressCircle.vue +27 -0
  318. package/src/components/ui/progress/SemiCircularProgressBar.vue +83 -0
  319. package/src/components/ui/progress/TotalCalories.vue +31 -0
  320. package/src/components/ui/radio-group/RadioGroup.vue +25 -0
  321. package/src/components/ui/radio-group/RadioGroupItem.vue +37 -0
  322. package/src/components/ui/radio-group/index.ts +2 -0
  323. package/src/components/ui/scroll-area/ScrollArea.vue +29 -0
  324. package/src/components/ui/scroll-area/ScrollBar.vue +30 -0
  325. package/src/components/ui/scroll-area/index.ts +2 -0
  326. package/src/components/ui/select/Select.vue +15 -0
  327. package/src/components/ui/select/SelectContent.vue +52 -0
  328. package/src/components/ui/select/SelectGroup.vue +19 -0
  329. package/src/components/ui/select/SelectInline.vue +84 -0
  330. package/src/components/ui/select/SelectItem.vue +44 -0
  331. package/src/components/ui/select/SelectItemText.vue +11 -0
  332. package/src/components/ui/select/SelectLabel.vue +13 -0
  333. package/src/components/ui/select/SelectScrollDownButton.vue +24 -0
  334. package/src/components/ui/select/SelectScrollUpButton.vue +24 -0
  335. package/src/components/ui/select/SelectSeparator.vue +17 -0
  336. package/src/components/ui/select/SelectTrigger.vue +31 -0
  337. package/src/components/ui/select/SelectTriggerCustom.vue +23 -0
  338. package/src/components/ui/select/SelectValue.vue +11 -0
  339. package/src/components/ui/select/index.ts +12 -0
  340. package/src/components/ui/separator/Separator.vue +20 -0
  341. package/src/components/ui/separator/index.ts +1 -0
  342. package/src/components/ui/sheet/Sheet.vue +14 -0
  343. package/src/components/ui/sheet/SheetClose.vue +11 -0
  344. package/src/components/ui/sheet/SheetContent.vue +48 -0
  345. package/src/components/ui/sheet/SheetDescription.vue +22 -0
  346. package/src/components/ui/sheet/SheetFooter.vue +19 -0
  347. package/src/components/ui/sheet/SheetHeader.vue +16 -0
  348. package/src/components/ui/sheet/SheetTitle.vue +22 -0
  349. package/src/components/ui/sheet/SheetTrigger.vue +11 -0
  350. package/src/components/ui/sheet/index.ts +31 -0
  351. package/src/components/ui/skeleton/Skeleton.vue +28 -0
  352. package/src/components/ui/skeleton/index.ts +1 -0
  353. package/src/components/ui/sonner/Sonner.vue +22 -0
  354. package/src/components/ui/sonner/index.ts +1 -0
  355. package/src/components/ui/star/StarRating.vue +19 -0
  356. package/src/components/ui/switch/Switch.vue +37 -0
  357. package/src/components/ui/switch/index.ts +1 -0
  358. package/src/components/ui/table/Table.vue +16 -0
  359. package/src/components/ui/table/TableBody.vue +14 -0
  360. package/src/components/ui/table/TableCaption.vue +14 -0
  361. package/src/components/ui/table/TableCell.vue +21 -0
  362. package/src/components/ui/table/TableEmpty.vue +37 -0
  363. package/src/components/ui/table/TableFooter.vue +14 -0
  364. package/src/components/ui/table/TableHead.vue +14 -0
  365. package/src/components/ui/table/TableHeader.vue +14 -0
  366. package/src/components/ui/table/TableRow.vue +14 -0
  367. package/src/components/ui/table/index.ts +8 -0
  368. package/src/components/ui/tabs/Tabs.vue +15 -0
  369. package/src/components/ui/tabs/TabsContent.vue +22 -0
  370. package/src/components/ui/tabs/TabsList.vue +25 -0
  371. package/src/components/ui/tabs/TabsTrigger.vue +27 -0
  372. package/src/components/ui/tabs/index.ts +4 -0
  373. package/src/components/ui/tags-input/TagsInput.vue +22 -0
  374. package/src/components/ui/tags-input/TagsInputInput.vue +19 -0
  375. package/src/components/ui/tags-input/TagsInputItem.vue +22 -0
  376. package/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
  377. package/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
  378. package/src/components/ui/tags-input/index.ts +5 -0
  379. package/src/components/ui/textarea/Textarea.vue +24 -0
  380. package/src/components/ui/textarea/index.ts +1 -0
  381. package/src/components/ui/tooltip/Tooltip.vue +14 -0
  382. package/src/components/ui/tooltip/TooltipContent.vue +31 -0
  383. package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  384. package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  385. package/src/components/ui/tooltip/index.ts +4 -0
  386. package/src/composables/useAppConfig.ts +332 -0
  387. package/src/composables/useDarkMode.ts +71 -0
  388. package/src/config/app.config.ts +318 -0
  389. package/src/config/examples/ecommerce.config.ts +132 -0
  390. package/src/config/examples/generic.config.ts +132 -0
  391. package/src/config/menu.config.ts +149 -0
  392. package/src/config/my-app.config.ts +134 -0
  393. package/src/config/test-config.ts +32 -0
  394. package/src/config/theme.config.ts +250 -0
  395. package/src/docs/index.ts +21 -0
  396. package/src/docs.scss +403 -0
  397. package/src/index.d.ts +5 -0
  398. package/src/index.ts +20 -0
  399. package/src/layouts/AuthLayout.vue +68 -0
  400. package/src/layouts/DefaultLayout.vue +119 -0
  401. package/src/layouts/DocsLayout.vue +681 -0
  402. package/src/layouts/FormGlobal.vue +50 -0
  403. package/src/layouts/GlobalDialog.vue +122 -0
  404. package/src/layouts/RakorConfirmDialog.vue +95 -0
  405. package/src/layouts/SettingsLayout.vue +115 -0
  406. package/src/lib/constants.ts +2 -0
  407. package/src/lib/detail.utils.ts +213 -0
  408. package/src/lib/form.utils.ts +1009 -0
  409. package/src/lib/page.flow.utils.ts +81 -0
  410. package/src/lib/page.utils.ts +865 -0
  411. package/src/lib/performance.utils.ts +302 -0
  412. package/src/lib/tablerow.utils.ts +51 -0
  413. package/src/lib/utils.ts +643 -0
  414. package/src/main.scss +717 -0
  415. package/src/main.ts +74 -0
  416. package/src/menu.ts +78 -0
  417. package/src/nestedlist_color.scss +161 -0
  418. package/src/router/index.ts +92 -0
  419. package/src/stores/auth.ts +117 -0
  420. package/src/stores/counter.ts +12 -0
  421. package/src/stores/dialog.ts +168 -0
  422. package/src/stores/form.ts +103 -0
  423. package/src/stores/tabs.ts +52 -0
  424. package/src/tw.scss +419 -0
  425. package/src/types/form.types.ts +348 -0
  426. package/src/types/types.ts +7 -0
  427. package/src/utils/config.utils.ts +149 -0
  428. package/src/views/NotFound.vue +30 -0
  429. package/src/views/PageActivity.vue +15 -0
  430. package/src/views/auth/LoginView.vue +7 -0
  431. package/src/views/auth/OauthCallback.vue +101 -0
  432. package/src/views/dashboard/index.vue +16 -0
  433. package/src/views/settings/AccountSettingsView.vue +70 -0
  434. package/src/views/settings/AuditLogsSettingsView.vue +116 -0
  435. package/src/views/settings/DeviceSettingsView.vue +70 -0
  436. package/src/views/settings/MainSettingsView.vue +12 -0
  437. package/src/views/settings/ProfileSettingsView.vue +104 -0
  438. package/src/vueform/config/informasi-gudang.ts +47 -0
  439. package/src/vueform/config/test-schema.ts +8 -0
  440. package/src/vueform/config/types.ts +768 -0
  441. package/src/vueform/customization/classes.js +46 -0
  442. package/src/vueform/customization/tailwind.classes.js +2117 -0
  443. package/src/vueform/elements/ConfigDataSelectorElement.vue +50 -0
  444. package/src/vueform/elements/DateSelectorElement.vue +323 -0
  445. package/src/vueform/elements/SelectorElement.vue +153 -0
  446. package/src/vueform/schemas/date-selector-test.ts +103 -0
  447. package/src/vueform/schemas/informasi-gudang.ts +160 -0
  448. package/src/vueform/schemas/test-schema.ts +483 -0
  449. package/src/vueform.config.js +77 -0
  450. package/src/vueform.validator.ts +77 -0
@@ -0,0 +1,589 @@
1
+ <script setup lang="ts">
2
+ import DataTable from "@/components/tables/DataTable.vue";
3
+ import Copyright from "@/components/helper/Copyright.vue";
4
+ import api from "@/api/api";
5
+ import moment from "moment";
6
+ import {
7
+ Search,
8
+ LucideChevronRight,
9
+ LucideChevronLeft,
10
+ LucideListTodo,
11
+ LucideCheck,
12
+ LucideMinus,
13
+ LucideSearch,
14
+ LucideEye,
15
+ LucideEyeOff,
16
+ LucideFilter,
17
+ LucideFileSpreadsheet,
18
+ LucideFileType2
19
+ } from "lucide-vue-next";
20
+ import { Input } from "@/components/ui/input";
21
+ import BtnCircle from "@/components/button/BtnCircle.vue";
22
+ import Pagination from "@/components/tables/Pagination.vue";
23
+ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
24
+ import ScrollArea from "@/components/ui/scroll-area/ScrollArea.vue";
25
+ import { computed, onMounted, ref } from "vue";
26
+ import { cn, exportToCSV, exportToExcel, exportToPDF, fillFormSchema } from "@/lib/utils";
27
+ import { Switch } from "@/components/ui/switch";
28
+ import type { ColumnRef, PageConfig, SortBy, ToggleConfig } from "@/vueform/config/types";
29
+ import { useConfirmDialog } from "@/stores/dialog";
30
+ import CheckboxElement from "@/components/helper/CheckboxElement.vue";
31
+ import LucideIcon from "@/components/helper/LucideIcon.vue";
32
+ import { parseDate } from "@/lib/utils";
33
+
34
+ interface Props {
35
+ title: string;
36
+ displaySearch?: boolean;
37
+ searchPlaceholder?: string;
38
+ loading?: boolean;
39
+ error: string | null;
40
+ totalData: number;
41
+ totalFilteredData: number;
42
+ formSchema?: any;
43
+ formHooks?: any;
44
+ endpoint?: string;
45
+ class?: string;
46
+ showCopyright: boolean;
47
+ filter?: any;
48
+ pageConfig?: PageConfig;
49
+ // Optional overrides for document viewer behavior per page
50
+ showViewDocumentBtn?: boolean;
51
+ viewDocsEndpoint?: string;
52
+ // Force remount filter form to reflect cleared defaults on reset
53
+ filterKey?: string | number;
54
+ }
55
+
56
+ const emits = defineEmits(["searchInput", "addClick", "getData", "filterChange", "resetFilter", "openDetail", "downloadDoc", "editItem", "checkActionClick", "toggleChange", "reloadDataByIds"]);
57
+
58
+ const props = withDefaults(defineProps<Props>(), {
59
+ title: "",
60
+ displaySearch: true,
61
+ searchPlaceholder: "Pencarian...",
62
+ loading: true,
63
+ error: null,
64
+ totalData: 0,
65
+ totalFilteredData: 0,
66
+ showCopyright: true,
67
+ filter: null
68
+ });
69
+ const data = defineModel<any[]>("data", { default: [] });
70
+ const currentPage = defineModel("currentPage", { default: 0 });
71
+ const itemsPerPage = defineModel("itemsPerPage", { default: 25 });
72
+ const sortBy = defineModel<SortBy>("sortBy");
73
+ const toggleChecked = ref(true);
74
+ const q: any = defineModel("search");
75
+ const selectedId = ref("");
76
+ const pembangkitName = ref("");
77
+ const pembangkitId = ref("");
78
+ const periode = ref("");
79
+ const accessLevel = ref(localStorage.getItem("dasi.user.organization.level"));
80
+
81
+ /**
82
+ * Column settings
83
+ *
84
+ */
85
+ const columns = defineModel<ColumnRef[]>("columns", { default: [] });
86
+ const columnSearch = ref("");
87
+ const columnsFiltered = computed(() => {
88
+ return columns.value.filter(r => r.type !== "action");
89
+ });
90
+ const columnsSearchResult = computed(() => {
91
+ return columnsFiltered.value.filter(r => r.header && r.header.toLowerCase().indexOf(columnSearch.value.toLowerCase()) >= 0);
92
+ });
93
+ const allColumnsSelected = computed(() => {
94
+ return columnsFiltered.value.length > 0 && !columnsFiltered.value.some(r => !r.visible);
95
+ });
96
+ const allColumnsIndeterminate = computed(() => {
97
+ return columnsFiltered.value.some(r => r.visible);
98
+ });
99
+
100
+ /**
101
+ * El
102
+ *
103
+ */
104
+ const confirmDialog = useConfirmDialog();
105
+
106
+ function searchCanged(e: Event) {
107
+ emits("searchInput", (e.target as HTMLInputElement).value);
108
+ }
109
+
110
+ /**
111
+ * Columns selector visible not visible
112
+ *
113
+ */
114
+ function selectAllColumns() {
115
+ const isSelected = !allColumnsSelected.value;
116
+ for (const column of columns.value) {
117
+ if (!column.header || column.type === "action") continue;
118
+ column.visible = isSelected;
119
+ }
120
+ saveColumnsFilter();
121
+ }
122
+
123
+ function getPageId(): string {
124
+ let pageId = props.pageConfig?.id ?? props.pageConfig?.savePath ?? props.endpoint ?? props.pageConfig?.endpoint ?? "__";
125
+ if (!pageId.startsWith("/")) pageId = "/" + pageId;
126
+ return pageId.replace(/[^a-zA-Z0-9_]/g, "_");
127
+ }
128
+
129
+ /**
130
+ * Toggle functionality
131
+ */
132
+ function getToggleConfig(): ToggleConfig | null {
133
+ // Support both new toggleConfig and legacy toggle/toggleOptions
134
+ if (props.pageConfig?.toggleConfig) {
135
+ return props.pageConfig.toggleConfig;
136
+ }
137
+
138
+ // Legacy support for backward compatibility
139
+ if (props.pageConfig?.toggle && props.pageConfig?.toggleOptions) {
140
+ return {
141
+ show: true,
142
+ options: props.pageConfig.toggleOptions,
143
+ defaultChecked: true
144
+ };
145
+ }
146
+
147
+ return null;
148
+ }
149
+
150
+ function initializeToggleState() {
151
+ const toggleConfig = getToggleConfig();
152
+ if (!toggleConfig) return;
153
+
154
+ toggleChecked.value = toggleConfig.defaultChecked ?? true;
155
+ }
156
+
157
+ function toggleChanged() {
158
+ const toggleConfig = getToggleConfig();
159
+ if (!toggleConfig) return;
160
+
161
+ // Simply emit the toggle change event and let parent handle data fetching
162
+ emits("toggleChange", {
163
+ checked: toggleChecked.value,
164
+ config: toggleConfig
165
+ });
166
+ }
167
+
168
+ function colVisibilityKey(): string {
169
+ return `dasi.column_visibility.${getPageId()}`;
170
+ }
171
+
172
+ function toggleShowHideColumn(item: any) {
173
+ item.visible = !item.visible;
174
+ saveColumnsFilter();
175
+ }
176
+
177
+ function saveColumnsFilter() {
178
+ setTimeout(() => {
179
+ const dataToSave: any[] = [];
180
+ for (const item of columns.value) {
181
+ if (item.type === "action") continue;
182
+ dataToSave.push({
183
+ key: item.key,
184
+ visible: item.visible
185
+ });
186
+ }
187
+ const dataStr = JSON.stringify(dataToSave);
188
+ if (!dataStr) return;
189
+ localStorage.setItem(colVisibilityKey(), dataStr);
190
+ });
191
+ }
192
+
193
+ function restoreColumnsFilter() {
194
+ const dataStr = localStorage.getItem(colVisibilityKey());
195
+ if (!dataStr) return;
196
+ try {
197
+ const colJsonData = JSON.parse(dataStr);
198
+ for (const item of colJsonData ?? []) {
199
+ for (const column of columns.value) {
200
+ if (item.key === column.key) {
201
+ column.visible = !!item.visible;
202
+ break;
203
+ }
204
+ }
205
+ }
206
+ } catch (err) {
207
+ console.error("Failed to parse columns visibilty data", err);
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Export
213
+ */
214
+ const exportTo = async (type: "pdf" | "excel") => {
215
+ if (accessLevel.value === "pembangkit") {
216
+ pembangkitName.value = localStorage.getItem("dasi.user.name") || "";
217
+ } else {
218
+ if (pembangkitId.value) {
219
+ await api
220
+ .get(`/organization/${pembangkitId.value}`)
221
+ .then(r => {
222
+ pembangkitName.value = r.data.data?.pembangkit?.nama;
223
+ })
224
+ .catch(err => {
225
+ console.error("Error fetching pembangkit data:", err);
226
+ });
227
+ }
228
+ }
229
+
230
+ if (sessionStorage.getItem("dasiv2.filter.tanggal")) {
231
+ periode.value = sessionStorage.getItem("dasiv2.filter.tanggal") || "";
232
+ }
233
+
234
+ const tanggal = sessionStorage.getItem("dasiv2.filter.tanggal");
235
+
236
+ const namaPembangkit = pembangkitName.value || "";
237
+ const periodeValue = tanggal
238
+ ? (() => {
239
+ try {
240
+ const tempDate = parseDate(tanggal);
241
+ if (tempDate) {
242
+ return tempDate.format("MM/YYYY");
243
+ }
244
+ } catch (e) {
245
+ console.error("Error formatting date:", tanggal, e);
246
+ }
247
+ return "";
248
+ })()
249
+ : "";
250
+
251
+ const exportColumns: { key: string; label: string }[] = [];
252
+ columns.value?.map((item: any) => {
253
+ if (item.type === "action" || item.visible !== true) return; // Skip action columns
254
+ item.label = item.header?.replace("<br />", " ");
255
+ exportColumns.push({
256
+ key: item.key,
257
+ label: item.label?.replace("<br />", " ")
258
+ });
259
+ });
260
+
261
+ // Process export data using fillFormSchema if formSchema is available
262
+ let exportData = data.value.map((item: any) => ({ ...item }));
263
+
264
+ if (props.formSchema) {
265
+ // Create a schema entries array for fillFormSchema
266
+ Object.entries(props.formSchema);
267
+
268
+ // Process each data item through fillFormSchema
269
+ exportData = data.value.map((item: any) => {
270
+ // Create a copy of the schema to avoid modifying the original
271
+ const tempSchema = JSON.parse(JSON.stringify(props.formSchema));
272
+ const tempSchemaEntries = Object.entries(tempSchema);
273
+
274
+ // Use fillFormSchema to process the item
275
+ fillFormSchema(tempSchemaEntries, item);
276
+
277
+ // Extract the processed values from the schema
278
+ const processedItem: any = { ...item };
279
+ tempSchemaEntries.forEach(([key, schemaItem]: [string, any]) => {
280
+ if (schemaItem.default !== undefined && schemaItem.default !== null) {
281
+ // Handle different data types returned by fillFormSchema
282
+ if (Array.isArray(schemaItem.default)) {
283
+ // For arrays, try to extract meaningful values
284
+ if (schemaItem.default.length > 0) {
285
+ const firstItem = schemaItem.default[0];
286
+ if (typeof firstItem === "object" && firstItem !== null) {
287
+ // Extract name, nama, or other display properties
288
+ processedItem[key] = firstItem.name || firstItem.nama || firstItem.label || firstItem.id || JSON.stringify(firstItem);
289
+ } else {
290
+ processedItem[key] = firstItem;
291
+ }
292
+ } else {
293
+ processedItem[key] = "";
294
+ }
295
+ } else if (typeof schemaItem.default === "object" && schemaItem.default !== null) {
296
+ // For objects, extract meaningful display value
297
+ if (schemaItem.default.value && typeof schemaItem.default.value === "object") {
298
+ const valueObj = schemaItem.default.value;
299
+ processedItem[key] = valueObj.name || valueObj.nama || valueObj.label || valueObj.id || JSON.stringify(valueObj);
300
+ } else {
301
+ processedItem[key] = schemaItem.default.name || schemaItem.default.nama || schemaItem.default.label || schemaItem.default.id || JSON.stringify(schemaItem.default);
302
+ }
303
+ } else {
304
+ processedItem[key] = schemaItem.default;
305
+ }
306
+ }
307
+ });
308
+
309
+ return processedItem;
310
+ });
311
+ }
312
+
313
+ if (type == "pdf") {
314
+ exportToPDF(exportData, props.title, exportColumns, props.title, namaPembangkit, periodeValue);
315
+ } else if (type == "excel") {
316
+ exportToExcel(exportData, props.title, exportColumns, "Sheet1", namaPembangkit, periodeValue);
317
+ }
318
+ };
319
+
320
+ /**
321
+ * Filter
322
+ *
323
+ */
324
+ function handleFilterChange(filterData: any) {
325
+ if (filterData.pembangkit_id && filterData.pembangkit_id.length > 0) {
326
+ pembangkitId.value = filterData.pembangkit_id;
327
+ }
328
+
329
+ // Emit the original filterChange event
330
+ emits("filterChange", filterData);
331
+ }
332
+
333
+ function resetFilter() {
334
+ confirmDialog
335
+ .open({
336
+ title: "Reset Filter",
337
+ description: "Apakah Anda yakin ingin reset semua filter terpilih?",
338
+ negative: false,
339
+ cancelLabel: "Batal",
340
+ actionLabel: "Reset Filter"
341
+ })
342
+ .then((b: boolean) => {
343
+ if (!b) return;
344
+ emits("resetFilter");
345
+ });
346
+ }
347
+
348
+ /**
349
+ * Checkbox per rows
350
+ *
351
+ */
352
+ const checkedItems = computed(() => {
353
+ return data.value.filter(r => r.checked);
354
+ });
355
+ const checkedAll = computed(() => {
356
+ if (!data.value || data.value.length < 1) return false;
357
+ return checkedItems.value.length === data.value.length;
358
+ });
359
+ const indeterminate = computed(() => {
360
+ for (const item of data.value) {
361
+ if (item.checked) return true;
362
+ }
363
+ return false;
364
+ });
365
+ const checkDisabled = computed(() => {
366
+ if (!props.pageConfig?.showCheckboxItem || !props.pageConfig.checkDisabled) {
367
+ return false;
368
+ }
369
+ let isDisabled = true;
370
+ for (const item of data.value) {
371
+ if (!props.pageConfig.checkDisabled(item, data.value)) {
372
+ isDisabled = false;
373
+ break;
374
+ }
375
+ }
376
+ return isDisabled;
377
+ });
378
+ function checkAllData() {
379
+ const checked = !checkedAll.value;
380
+ for (const item of data.value) {
381
+ if (props.pageConfig?.checkDisabled && props.pageConfig?.checkDisabled(item, data.value) === true) continue;
382
+ item.checked = checked;
383
+ }
384
+ }
385
+
386
+ function checkActionClicked(i: number, action: any) {
387
+ emits("checkActionClick", checkedItems.value, action.id);
388
+ }
389
+
390
+ function pageInitialized() {
391
+ restoreColumnsFilter();
392
+ initializeToggleState();
393
+ }
394
+
395
+ defineExpose({ pageInitialized });
396
+
397
+ onMounted(() => {
398
+ restoreColumnsFilter();
399
+ initializeToggleState();
400
+ });
401
+
402
+ // Merge optional props overrides into a derived pageConfig
403
+ const effectivePageConfig = computed<PageConfig | undefined>(() => {
404
+ const base = props.pageConfig ? ({ ...props.pageConfig } as PageConfig) : ({} as PageConfig);
405
+ if (typeof props.showViewDocumentBtn !== "undefined") {
406
+ (base as any).showViewDocButton = props.showViewDocumentBtn;
407
+ }
408
+ if (props.viewDocsEndpoint) {
409
+ (base as any).viewDocsEndpoint = props.viewDocsEndpoint;
410
+ }
411
+ return Object.keys(base).length ? base : undefined;
412
+ });
413
+ </script>
414
+
415
+ <template>
416
+ <main class="p-3 pb-2 2xl:p-4">
417
+ <section :class="cn('rounded-md border bg-white py-2.5 dark:border-dark_bg2 dark:bg-dark_bg2 2xl:py-3', props.class)" style="transform-origin: left">
418
+ <div class="mb-2.5 flex items-center justify-between px-4 2xl:mb-3">
419
+ <div class="flex w-full items-center">
420
+ <div class="mr-4 flex flex-none items-center gap-3 pl-1" v-if="pageConfig?.showCheckboxItem">
421
+ <CheckboxElement :indeterminate="indeterminate" :checked="checkedAll" :ignore-model="true" v-on:click="checkAllData" :disabled="checkDisabled" />
422
+ <div class="text-xs opacity-65" v-if="checkedItems.length > 0">{{ checkedItems.length }} terpilih</div>
423
+ <div class="flex items-center" v-if="checkedItems.length > 0">
424
+ <button
425
+ :class="
426
+ cn(
427
+ 'mr-2 flex h-8 cursor-pointer items-center justify-center rounded-full border border-blue-500 pl-2.5 pr-3 text-[13px] leading-none text-blue-500 transition hover:bg-blue-100 2xl:text-[14px]',
428
+ action.class
429
+ )
430
+ "
431
+ v-for="(action, i) in pageConfig?.checkboxActionBtn ?? []"
432
+ @click.stop="checkActionClicked(i, action)">
433
+ <LucideIcon :name="action.icon" :class="cn('mr-1.5', action.iconClass)" :size="action.iconSize ?? 20" :stroke-width="action.iconStrokeWidth ?? 1.6" />
434
+ {{ action.label }}
435
+ </button>
436
+ </div>
437
+ </div>
438
+ <slot name="left-action"></slot>
439
+ <div class="relative w-full max-w-96" v-if="displaySearch !== false">
440
+ <Input
441
+ type="text"
442
+ :placeholder="props.searchPlaceholder"
443
+ class="!h-9 w-full rounded-full !border-2 !border-solid !border-transparent bg-[#eee] px-4 leading-none hover:bg-slate-100 focus:!border-2 focus:!border-solid focus:!border-blue-500 focus:bg-white dark:border-dark_bg4 dark:bg-dark_bg4 dark:hover:bg-dark_bg dark:focus:bg-dark_bg"
444
+ @input="searchCanged"
445
+ v-model="q" />
446
+ <span class="absolute right-0 top-0 flex items-center justify-center pr-3 pt-2">
447
+ <Search class="size-5 text-muted-foreground" />
448
+ </span>
449
+ </div>
450
+ <div class="pl-1 font-medium" v-else-if="pageConfig?.pageTitle">
451
+ {{ pageConfig?.pageTitle }}
452
+ </div>
453
+ </div>
454
+
455
+ <div class="pct-action-cnt flex flex-none items-center justify-end">
456
+ <slot name="right-action"></slot>
457
+
458
+ <div class="ml-5 mr-6 flex items-center gap-2 border-r px-2 py-2 pr-5" v-if="getToggleConfig()?.show">
459
+ <span class="text-[12px] opacity-75">{{ toggleChecked ? getToggleConfig()?.options.checked : getToggleConfig()?.options.unchecked }}</span>
460
+ <Switch class="!bg-green-500 data-[state=checked]:!bg-blue-500" v-model:checked="toggleChecked" v-on:update:checked="toggleChanged" />
461
+ </div>
462
+
463
+ <section class="flex items-center gap-2 2xl:gap-3">
464
+ <template v-if="pageConfig?.showPagination !== false">
465
+ <div class="mr-2 text-xs text-gray-500 dark:text-gray-400 2xl:mr-3 2xl:text-[13px]">
466
+ {{ (currentPage - 1) * itemsPerPage + 1 }} - {{ Math.min(currentPage * itemsPerPage, props.totalData) }} dari
467
+ {{ props.totalData }}
468
+ </div>
469
+ <BtnCircle :class="{ 'cursor-not-allowed opacity-30': currentPage <= 1 }" @click="currentPage > 1 && (currentPage--, emits('getData'))">
470
+ <LucideChevronLeft :stroke-width="1.5" class="size-[20px] 2xl:size-[24px]" />
471
+ </BtnCircle>
472
+ <BtnCircle
473
+ :class="{ 'cursor-not-allowed opacity-30': currentPage >= Math.ceil(props.totalData / itemsPerPage) }"
474
+ @click="currentPage < Math.ceil(props.totalData / itemsPerPage) && (currentPage++, emits('getData'))">
475
+ <LucideChevronRight :stroke-width="1.5" class="size-[20px] 2xl:size-[24px]" />
476
+ </BtnCircle>
477
+ </template>
478
+
479
+ <template v-if="props.pageConfig?.showExportButton === true">
480
+ <BtnCircle @click="exportTo('excel')" title="Export Excel">
481
+ <LucideFileSpreadsheet :stroke-width="1.5" class="size-[20px] 2xl:size-[24px]" />
482
+ </BtnCircle>
483
+ <BtnCircle @click="exportTo('pdf')" title="Export PDF">
484
+ <LucideFileType2 :stroke-width="1.5" class="size-[20px] 2xl:size-[24px]" />
485
+ </BtnCircle>
486
+ </template>
487
+
488
+ <Popover>
489
+ <PopoverTrigger>
490
+ <BtnCircle>
491
+ <LucideListTodo :size="22" class="size-[20px] 2xl:size-[24px]" />
492
+ </BtnCircle>
493
+ </PopoverTrigger>
494
+ <PopoverContent class="mr-20 w-[360px] p-0">
495
+ <h1 class="flex w-full items-center border-b px-5 pb-2 pt-3 text-left font-medium text-gray-500">
496
+ <LucideListTodo :size="20" class="mr-2" />
497
+ Tampilan Kolom
498
+ </h1>
499
+ <li class="flex cursor-pointer list-none items-center border-b px-5 py-1.5 text-sm transition hover:bg-slate-100 dark:hover:bg-slate-700" v-on:click="selectAllColumns">
500
+ <div
501
+ class="ml-px mr-[13px] flex size-[16px] flex-none items-center justify-center rounded-sm border border-gray-400 bg-white text-white shadow-none"
502
+ :class="{
503
+ '!border-blue-500 !bg-blue-500': allColumnsSelected || allColumnsIndeterminate
504
+ }">
505
+ <LucideCheck v-if="allColumnsSelected" :stroke-width="3" />
506
+ <LucideMinus v-else-if="allColumnsIndeterminate" :stroke-width="3" />
507
+ </div>
508
+ <template v-if="allColumnsSelected">Sembunyikan</template>
509
+ <template v-else>Tampilkan</template>
510
+ Semua Kolom
511
+ </li>
512
+ <li class="relative list-none border-b bg-slate-100 px-4 py-1.5 dark:bg-transparent">
513
+ <input type="text" placeholder="Cari kolom..." class="w-full rounded-full border border-white bg-white py-1 pl-[33px] pr-3 text-sm dark:bg-slate-700" v-model="columnSearch" />
514
+ <LucideSearch :size="16" class="absolute left-[23px] top-1/2 -translate-y-1/2 text-gray-400" />
515
+ </li>
516
+ <ScrollArea class="h-[380px] max-w-[60vh] pb-2">
517
+ <li
518
+ class="flex cursor-pointer list-none items-start px-5 py-1.5 text-sm transition hover:bg-blue-100 hover:text-blue-500 hover:dark:bg-slate-700"
519
+ :class="{ 'bg-slate-50 text-[#888] dark:bg-slate-700 dark:text-white': !item.visible }"
520
+ v-for="(item, i) in columnsSearchResult"
521
+ :key="i"
522
+ v-on:click="toggleShowHideColumn(item)">
523
+ <LucideEye :stroke-width="1.5" :size="18" class="mr-3 mt-px flex-none" v-if="item.visible" />
524
+ <LucideEyeOff :stroke-width="1.5" :size="18" class="mr-3 mt-px flex-none" v-else />
525
+ <div v-html="item.header"></div>
526
+ </li>
527
+ </ScrollArea>
528
+ </PopoverContent>
529
+ </Popover>
530
+ <Popover v-if="props.filter && Object.keys(props.filter).length > 0">
531
+ <PopoverTrigger>
532
+ <BtnCircle class="ml-2 2xl:ml-3">
533
+ <LucideFilter class="size-[18px] 2xl:size-[21px]" />
534
+ </BtnCircle>
535
+ </PopoverTrigger>
536
+ <PopoverContent class="mr-20 p-0 dark:bg-dark_bg3" :class="pageConfig?.width ? `w-[${pageConfig.width}px]` : 'w-[360px]'">
537
+ <div class="flex w-full items-center border-b px-5 pb-2 pt-3 text-left font-medium text-gray-500">
538
+ <LucideFilter :size="20" class="mr-2" />
539
+ Filter
540
+ <button class="-mr-2 ml-auto rounded-full px-2.5 py-0.5 text-sm text-red-500 transition hover:bg-red-100" v-on:click="resetFilter">Reset filter</button>
541
+ </div>
542
+ <div class="px-5 py-2.5">
543
+ <Vueform :schema="props.filter" :key="props.filterKey" v-on:change="handleFilterChange" />
544
+ </div>
545
+ </PopoverContent>
546
+ </Popover>
547
+ </section>
548
+ </div>
549
+ </div>
550
+ <div class="min-h-[calc(100vh-360px)]">
551
+ <slot name="table">
552
+ <DataTable
553
+ v-model:data="data"
554
+ :title="props.title"
555
+ :columns="columns"
556
+ :loading="props.loading"
557
+ :error="props.error"
558
+ :form-hooks="props.formHooks"
559
+ :form-schema="props.formSchema"
560
+ :endpoint="props.endpoint"
561
+ :page-config="effectivePageConfig ?? pageConfig"
562
+ v-model:sort-by="sortBy"
563
+ v-model:selected-id="selectedId"
564
+ v-on:get-data="emits('getData')"
565
+ v-on:open-detail="(...e) => emits('openDetail', ...e)"
566
+ @reload-data-by-ids="(...e) => emits('reloadDataByIds', ...e)"
567
+ @edit="(...e) => emits('editItem', ...e)">
568
+ <template #detail="detail">
569
+ <slot name="detail" :detail="detail"></slot>
570
+ </template>
571
+ </DataTable>
572
+ </slot>
573
+ </div>
574
+ <slot name="legend"></slot>
575
+ <div class="mt-5 flex justify-end" v-if="pageConfig?.showPagination === false">
576
+ <section class="flex w-full items-center px-5">
577
+ <div class="mr-auto text-sm text-gray-500">Menampilkan {{ props.totalData }} data</div>
578
+ </section>
579
+ </div>
580
+ <div class="mt-5 flex justify-end" v-else>
581
+ <Pagination v-model:current-page="currentPage" v-model:items-per-page="itemsPerPage" :total-data="props.totalData" v-on:get-data="emits('getData')" :loading="props.loading" />
582
+ </div>
583
+ </section>
584
+ <div class="px-2 pb-10 pt-2 text-left text-xs text-slate-400 2xl:text-sm" v-if="props.showCopyright">
585
+ <Copyright />
586
+ </div>
587
+ <slot></slot>
588
+ </main>
589
+ </template>
@@ -0,0 +1,84 @@
1
+ <script setup lang="ts">
2
+ import TabViewItem from '@/components/tab/TabViewItem.vue'
3
+ import TabView from '@/components/tab/TabView.vue'
4
+ import { LucideList, LucideStar, LucideTrash } from 'lucide-vue-next';
5
+ import TabViewItemBar from '@/components/tab/TabViewItemBar.vue';
6
+ import LucideIcon from '@/components/helper/LucideIcon.vue';
7
+
8
+ export interface CustomTab {
9
+ name: string
10
+ code: string
11
+ icon: string
12
+ count?: number
13
+ color?: string
14
+ }
15
+
16
+ interface PageTabProp {
17
+ showDeleted?: boolean
18
+ showFavorite?: boolean
19
+ showAll?: boolean
20
+ customTabs?: CustomTab[]
21
+ }
22
+
23
+ const props = withDefaults(defineProps<PageTabProp>(), {
24
+ showAll: true,
25
+ showDeleted: true,
26
+ showFavorite: false,
27
+ });
28
+
29
+ const tab = defineModel<string>({ default: 'all' });
30
+ const emits = defineEmits(['change']);
31
+
32
+ function selectTab(selectedTab: string) {
33
+ tab.value = selectedTab;
34
+ emits('change', selectTab);
35
+ }
36
+ </script>
37
+
38
+ <template>
39
+ <div class="bg-white dark:bg-dark_bg">
40
+ <TabView>
41
+ <TabViewItem :active="tab === 'all'" v-on:click="selectTab('all')" v-if="showAll">
42
+ <div class="flex items-center">
43
+ <LucideList class="2xl:size-[20px] size-[16px] mr-2" :stroke-width="3"/>
44
+ All Data
45
+ </div>
46
+ </TabViewItem>
47
+ <TabViewItem :active="tab === 'starred'" v-on:click="selectTab('starred')"
48
+ v-if="props.showFavorite">
49
+ <div class="flex items-center"
50
+ :class="{'text-orange-400': tab === 'starred'}">
51
+ <LucideStar class="2xl:size-[20px] size-[16px] mr-2" :stroke-width="2.2"/>
52
+ Starred
53
+ </div>
54
+ <template #bar>
55
+ <TabViewItemBar :class="{'!bg-orange-400': tab === 'starred'}"></TabViewItemBar>
56
+ </template>
57
+ </TabViewItem>
58
+ <template v-if="props.customTabs && props.customTabs.length > 0">
59
+ <TabViewItem :active="tab === item.code" v-on:click="selectTab(item.code)"
60
+ v-for="(item, i) in props.customTabs" :key="i">
61
+ <div class="flex items-center" :class="tab === item.code ? `text-${item.color}` : ''">
62
+ <LucideIcon class="2xl:size-[20px] size-[16px] mr-2" :stroke-width="2.2" :name="item.icon" v-if="item.icon"/>
63
+ {{ item.name }}
64
+ <div class="bg-red-500 h-[19px] min-w-[19px] px-1.5 text-center pt-[3px] leading-none text-[13px] rounded-full text-white ml-1.5" v-if="item.count">{{ item.count }}</div>
65
+ </div>
66
+ <template #bar v-if="item.color">
67
+ <TabViewItemBar :class="tab === item.code ? `!bg-${item.color}` : ''"></TabViewItemBar>
68
+ </template>
69
+ </TabViewItem>
70
+ </template>
71
+ <TabViewItem :active="tab === 'deleted'" v-on:click="selectTab('deleted')"
72
+ v-if="props.showDeleted !== false">
73
+ <div class="flex items-center"
74
+ :class="{'text-red-600': tab === 'deleted'}">
75
+ <LucideTrash :stroke-width="2.2" class="2xl:size-[20px] size-[16px] mr-2"/>
76
+ Deleted
77
+ </div>
78
+ <template #bar>
79
+ <TabViewItemBar :class="{'!bg-red-600': tab === 'deleted'}"></TabViewItemBar>
80
+ </template>
81
+ </TabViewItem>
82
+ </TabView>
83
+ </div>
84
+ </template>