@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,643 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ import moment from "moment";
4
+ import { saveAs } from "file-saver";
5
+ import jsPDF from "jspdf";
6
+ import autoTable from "jspdf-autotable";
7
+ import * as XLSX from "xlsx";
8
+ import menu from "@/menu";
9
+
10
+ export const monthNames = ["-", "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"];
11
+
12
+ export function cn(...inputs: ClassValue[]) {
13
+ return twMerge(clsx(inputs));
14
+ }
15
+
16
+ export function clearFormSchema(schema: any[]) {
17
+ for (const [_, item] of schema) {
18
+ item.default = item.nullValue;
19
+ if (item.disabledValue) item.disabled = item.disabledValue;
20
+ if (item.schema) clearFormSchema(Object.entries(item.schema));
21
+ }
22
+ }
23
+
24
+ // Helper function to check if a value is meaningful
25
+ export function isValidValue(value: any): boolean {
26
+ if (value === null || value === undefined || value === false) return false;
27
+ if (typeof value === "string" && value.trim() === "") return false;
28
+ if (typeof value === "number" && String(value).trim() === "") return false;
29
+ if (value === "0001-01-01") return false; // Invalid date placeholder
30
+ if (Array.isArray(value) && value.length === 0) return false;
31
+ return true;
32
+ }
33
+
34
+ // Helper function to check if a value is meaningful
35
+ function isValidFormValue(value: any): boolean {
36
+ if (value === null || value === undefined) return false;
37
+ if (typeof value === "string" && value.trim() === "") return false;
38
+ if (typeof value === "number" && String(value).trim() === "") return false;
39
+ if (value === "0001-01-01") return false; // Invalid date placeholder
40
+ if (Array.isArray(value) && value.length === 0) return false;
41
+ return true;
42
+ }
43
+
44
+ export function fillFormSchema(schema: any, items: any) {
45
+ /**
46
+ * Clear schema before filling new data
47
+ *
48
+ */
49
+ clearFormSchema(schema);
50
+
51
+ /**
52
+ * Now fill the schema with data
53
+ *
54
+ */
55
+ for (const [key, item] of schema) {
56
+ // Handle array items with nested object structure
57
+ // Generic pattern: if key ends with "Items" and is an array, transform to selector format
58
+ if (key.endsWith("Items") && Array.isArray(items[key]) && items[key].length > 0) {
59
+ const transformedData = items[key]
60
+ .filter((item: any) => item && item !== null && item !== undefined)
61
+ .map((item: any) => {
62
+ if (!item) return null;
63
+
64
+ const id = item.id || item[`${key.replace("Items", "")}Id`];
65
+ const nameKey = key.replace("Items", "");
66
+ const name = item[nameKey]?.name || item[nameKey]?.nama || item.name || item.nama || `ID: ${id}`;
67
+
68
+ if (id) {
69
+ return { id, name };
70
+ }
71
+ return null;
72
+ })
73
+ .filter((item: any) => item !== null);
74
+
75
+ if (transformedData.length > 0) {
76
+ item.default = transformedData;
77
+ continue;
78
+ }
79
+ }
80
+
81
+ // Handle dasi_v2_date_range type specifically
82
+ if (item.type === "dasi_v2_date_range") {
83
+ const keyAwal = `${key}Awal`;
84
+ const keyAkhir = `${key}Akhir`;
85
+
86
+ const awalValue = items[keyAwal];
87
+ const akhirValue = items[keyAkhir];
88
+
89
+ // Only set if both dates are valid and not placeholder dates
90
+ if (isValidFormValue(awalValue) && isValidFormValue(akhirValue) && awalValue !== "0001-01-01" && akhirValue !== "0001-01-01") {
91
+ item.default = [new Date(awalValue), new Date(akhirValue)];
92
+ }
93
+ // If invalid, keep the original default value from schema
94
+ continue;
95
+ }
96
+
97
+ if (item.type === "dasi_v2_selector_single_v2") {
98
+ const theKey = key.substring(key.length - 2, key.length) === "Id" ? key.substring(0, key.length - 2) : key;
99
+ const value: any = items[theKey];
100
+ if (value && item.subItem) {
101
+ if (item.subItem.fillFromFunc) value.subItemSelected = item.subItem.fillFromFunc(items);
102
+ else value.subItemSelected = items[item.subItem.fillFrom];
103
+ }
104
+ item.default = { value };
105
+ continue;
106
+ }
107
+
108
+ for (const [key2, item2] of Object.entries(items)) {
109
+ if (key.substring(key.length - 2, key.length) === "Id") {
110
+ // Handle ID fields
111
+ if (key.substring(0, key.length - 2) === key2) {
112
+ // Skip if already processed by custom field mapping
113
+ if (item._processed) {
114
+ continue;
115
+ }
116
+ if (isValidFormValue(item2)) {
117
+ if (item2 && (item2 as any).mimetype) {
118
+ item.default = item2;
119
+ } else {
120
+ item.default = [item2];
121
+ }
122
+ }
123
+ // If invalid, keep the original default value from schema
124
+ }
125
+
126
+ /**
127
+ * @deprecated
128
+ * ___Code no need to pass object,
129
+ * this is normal dropdown
130
+ *
131
+ */
132
+ // } else if (key.substring(key.length - 4, key.length) === "Code") {
133
+ // // Handle ID fields
134
+ // if (key.substring(0, key.length - 4) === key2) {
135
+ // if (isValidFormValue(item2)) {
136
+ // if (item2 && (item2 as any).mimetype) {
137
+ // item.default = item2;
138
+ // } else {
139
+ // item.default = [item2];
140
+ // }
141
+ // }
142
+ // // If invalid, keep the original default value from schema
143
+ // }
144
+ } else if (key.substring(key.length - 3, key.length) === "Ids") {
145
+ // Handle multiple selector
146
+ if (key.substring(0, key.length - 3) === key2) {
147
+ if (isValidFormValue(item2)) item.default = item2;
148
+ }
149
+ } else {
150
+ // Handle regular fields
151
+ if (key === key2 && key.substring(key.length - 2, key.length) !== "Id") {
152
+ if (isValidFormValue(item2)) item.default = item2;
153
+ // If invalid, keep the original default value from schema
154
+ }
155
+ }
156
+ }
157
+
158
+ // Recursively handle nested schemas
159
+ if (item.schema) {
160
+ fillFormSchema(Object.entries(item.schema), items);
161
+ }
162
+ }
163
+ }
164
+
165
+ export function validateFormSilent(el: any, schema: any, path: string = ""): any {
166
+ let isValid = true;
167
+ for (const [key, item] of Object.entries(schema) as any) {
168
+ let conditionMeet = true;
169
+ if (item.conditions && item.conditions.length > 0) {
170
+ for (const condition of item.conditions) {
171
+ if (condition[1] === "==") {
172
+ const val = el.el$(condition[0]).value;
173
+ if (val !== condition[2]) {
174
+ conditionMeet = false;
175
+ break;
176
+ }
177
+ } else if (condition[1] === "in") {
178
+ const val = el.el$(condition[0]).value;
179
+ if (!condition[2].includes(val)) {
180
+ conditionMeet = false;
181
+ break;
182
+ }
183
+ }
184
+ }
185
+ }
186
+ if (!conditionMeet) continue;
187
+ if (item.rules && item.rules.length > 0 && !el.el$(path + key).value) {
188
+ isValid = false;
189
+ break;
190
+ }
191
+ if (item.schema) {
192
+ isValid = validateFormSilent(el, item.schema, key + ".");
193
+ if (!isValid) break;
194
+ }
195
+ }
196
+ console.log("Validation result", isValid);
197
+ return isValid;
198
+ }
199
+
200
+ export function formatNumber(number: Number): string {
201
+ return Number(number || 0).toLocaleString("id", { maximumFractionDigits: 1 });
202
+ }
203
+
204
+ export function formatNumberIntl(number: number | undefined, minFraction = 0, maxFraction = 3): string {
205
+ return Number(number || 0).toLocaleString("us", {
206
+ maximumFractionDigits: maxFraction,
207
+ minimumFractionDigits: minFraction
208
+ });
209
+ }
210
+
211
+ export function displayNumberFormatedIntl(number: number, before: string, after: string) {
212
+ if (!number) return "-";
213
+ return `${before} <b>${formatNumberIntl(number || 0)}</b> ${after}`;
214
+ }
215
+
216
+ export function intlFormatedToNumber(v: string): number | null {
217
+ return v ? Number(String(v).replace(/\,/g, "")) : null;
218
+ }
219
+
220
+ export function formatToCommaFloat(value: number): string {
221
+ return value
222
+ .toFixed(0) // Round to 2 decimal places
223
+ .replace(",", ".") // Replace dot with comma
224
+ .replace(/\B(?=(\d{3})+(?!\d))/g, ","); // Add thousand separators
225
+ }
226
+
227
+ export function getMenuItemByUrl(url: string) {
228
+ for (const item of menu ?? []) {
229
+ for (const submenu of item.submenu ?? []) {
230
+ if (submenu.url === url) {
231
+ return submenu;
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ export function numberToWords(n: any) {
238
+ // If input is a string, remove commas
239
+ if (typeof n === "string") {
240
+ n = n.replace(/,/g, "");
241
+ }
242
+
243
+ // Validate input and convert to string
244
+ if (typeof n !== "number" && typeof n !== "string") {
245
+ return "Input must be a number";
246
+ }
247
+ if (isNaN(Number(n))) {
248
+ return "Input must be a number";
249
+ }
250
+
251
+ // Convert input to string for splitting on the decimal point.
252
+ let numStr = n.toString();
253
+ let result = "";
254
+
255
+ // Handle negative numbers
256
+ if (numStr[0] === "-") {
257
+ result = "minus ";
258
+ numStr = numStr.slice(1);
259
+ }
260
+
261
+ // Split the number by the decimal point.
262
+ let parts = numStr.split(".");
263
+ let integerPart = parseInt(parts[0]);
264
+ let fractionalPart = parts[1]; // undefined if no decimal
265
+
266
+ // Convert the integer part
267
+ result += convertInteger(integerPart);
268
+
269
+ // If there is a fractional part, convert each digit individually.
270
+ if (fractionalPart !== undefined && fractionalPart.length > 0) {
271
+ result += " koma";
272
+ for (let i = 0; i < fractionalPart.length; i++) {
273
+ let digit = parseInt(fractionalPart[i]);
274
+ result += " " + digitToWord(digit);
275
+ }
276
+ }
277
+
278
+ return result;
279
+ }
280
+
281
+ /**
282
+ * Number to month name start with 1,
283
+ * 1 = Januari,
284
+ * 2 = Februari,
285
+ * ...
286
+ *
287
+ */
288
+ export function numberToMonth(n: number = 0) {
289
+ return monthNames[n];
290
+ }
291
+
292
+ export function formatMonthYear(monthYear: string | Date): string {
293
+ if (!monthYear) return "";
294
+ return `${numberToMonth(moment(monthYear).month() + 1)} ${moment(monthYear).year()}`;
295
+ }
296
+
297
+ function convertInteger(n: number): any {
298
+ // Special case for zero
299
+ if (n === 0) return "nol";
300
+
301
+ const angka = ["", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan", "sepuluh", "sebelas"];
302
+
303
+ if (n < 12) {
304
+ return angka[n];
305
+ } else if (n < 20) {
306
+ return convertInteger(n - 10) + " belas";
307
+ } else if (n < 100) {
308
+ return convertInteger(Math.floor(n / 10)) + " puluh" + (n % 10 !== 0 ? " " + convertInteger(n % 10) : "");
309
+ } else if (n < 200) {
310
+ return "seratus" + (n % 100 !== 0 ? " " + convertInteger(n - 100) : "");
311
+ } else if (n < 1000) {
312
+ return convertInteger(Math.floor(n / 100)) + " ratus" + (n % 100 !== 0 ? " " + convertInteger(n % 100) : "");
313
+ } else if (n < 2000) {
314
+ return "seribu" + (n % 1000 !== 0 ? " " + convertInteger(n - 1000) : "");
315
+ } else if (n < 1000000) {
316
+ return convertInteger(Math.floor(n / 1000)) + " ribu" + (n % 1000 !== 0 ? " " + convertInteger(n % 1000) : "");
317
+ } else if (n < 1000000000) {
318
+ return convertInteger(Math.floor(n / 1000000)) + " juta" + (n % 1000000 !== 0 ? " " + convertInteger(n % 1000000) : "");
319
+ } else if (n < 1000000000000) {
320
+ return convertInteger(Math.floor(n / 1000000000)) + " milyar" + (n % 1000000000 !== 0 ? " " + convertInteger(n % 1000000000) : "");
321
+ } else if (n < 1000000000000000) {
322
+ return convertInteger(Math.floor(n / 1000000000000)) + " triliun" + (n % 1000000000000 !== 0 ? " " + convertInteger(n % 1000000000000) : "");
323
+ } else {
324
+ return "Number too large";
325
+ }
326
+ }
327
+
328
+ function digitToWord(digit: number) {
329
+ const angka = ["nol", "satu", "dua", "tiga", "empat", "lima", "enam", "tujuh", "delapan", "sembilan"];
330
+ return angka[digit];
331
+ }
332
+
333
+ export function isValidDate(value: string) {
334
+ const parsedDate = moment(new Date(value));
335
+
336
+ return parsedDate.isValid();
337
+ }
338
+
339
+ export function upFirst(str: string) {
340
+ return `${str.substring(0, 1).toUpperCase()}${str.substring(1)}`;
341
+ }
342
+
343
+ export function convertFormatDate(value: string): string | null {
344
+ if (!value) return null;
345
+
346
+ // Try to detect common date patterns using regex
347
+ const dateRegex = /\b\d{1,4}[-/]\d{1,2}[-/]\d{1,4}\b/;
348
+
349
+ if (dateRegex.test(value)) {
350
+ const parsedDate = moment(value, ["YYYY-MM-DD", "DD-MM-YYYY", "MM-DD-YYYY", "YYYY/MM/DD", "DD/MM/YYYY", "MM/DD/YYYY"], true); // 'true' = strict parsing
351
+
352
+ if (parsedDate.isValid()) {
353
+ return parsedDate.format("DD/MM/YYYY");
354
+ }
355
+ }
356
+
357
+ return null;
358
+ }
359
+
360
+ export function parseDate(dateString: string) {
361
+ if (!dateString) {
362
+ return null;
363
+ }
364
+ const formats = [moment.ISO_8601, "YYYY-MM"];
365
+
366
+ const parsedMoment = moment(dateString, formats);
367
+
368
+ return parsedMoment.isValid() ? parsedMoment : null;
369
+ }
370
+
371
+ // Helper function to get nested property value
372
+ export function getNestedValue(obj: any, path: string): any {
373
+ return path.split(".").reduce((current, key) => current?.[key], obj);
374
+ }
375
+
376
+
377
+ export function isValidVariable(variable: string) {
378
+ const regex = /^[a-zA-Z][a-zA-Z0-9_]*$/;
379
+ const disallowedVariables = [
380
+ "null",
381
+ "undefined",
382
+ "var",
383
+ "const",
384
+ "let",
385
+ "type",
386
+ "struct",
387
+ "func",
388
+ "function",
389
+ "package",
390
+ "return",
391
+ "panic",
392
+ "log",
393
+ "error",
394
+ "open",
395
+ "db",
396
+ "nil",
397
+ "err",
398
+ "new",
399
+ "string",
400
+ "int",
401
+ "number",
402
+ "float"
403
+ ];
404
+ if (!variable) return false;
405
+ if (disallowedVariables.includes(variable.toLowerCase())) return false;
406
+ return regex.test(variable);
407
+ }
408
+
409
+ export function escapeRegex(str: string): string {
410
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
411
+ }
412
+
413
+ export function exportToCSV(data: any[], filename: string, columns?: { key: string; label: string }[]) {
414
+ // Handle empty data
415
+ if (!data || !data.length) {
416
+ console.warn("No data to export");
417
+ return;
418
+ }
419
+
420
+ try {
421
+ // If columns are not specified, use object keys
422
+ const headers = columns ? columns.map(col => col.label) : Object.keys(data[0]);
423
+
424
+ // Create CSV content
425
+ const csvContent = [
426
+ // Add headers
427
+ headers.join(","),
428
+ // Add data rows
429
+ ...data.map(row => {
430
+ return columns
431
+ ? columns.map(col => formatCSVCell(row[col.key])).join(",")
432
+ : Object.values(row)
433
+ .map(cell => formatCSVCell(cell))
434
+ .join(",");
435
+ })
436
+ ].join("\n");
437
+
438
+ // Create Blob and download
439
+ const blob = new Blob([`\uFEFF${csvContent}`], {
440
+ type: "text/csv;charset=utf-8"
441
+ });
442
+ saveAs(blob, `${filename}.csv`);
443
+ } catch (error) {
444
+ console.error("Error exporting CSV:", error);
445
+ }
446
+ }
447
+
448
+ function formatCSVCell(value: any): string {
449
+ if (value === null || value === undefined) {
450
+ return "";
451
+ }
452
+
453
+ const stringValue = String(value);
454
+
455
+ // If value contains comma, quotes, or newline, wrap in quotes
456
+ if (/[,"\n]/.test(stringValue)) {
457
+ return `"${stringValue.replace(/"/g, '""')}"`;
458
+ }
459
+
460
+ return stringValue;
461
+ }
462
+
463
+ export function exportToPDF(data: any[], filename: string, columns?: { key: string; label: string }[], title?: string, pltuName?: string, periode?: string) {
464
+ if (!data || !data.length) {
465
+ console.warn("No data to export");
466
+ return;
467
+ }
468
+
469
+ try {
470
+ const doc = new jsPDF();
471
+ let currentY = 15;
472
+
473
+ // Add PLTU Name as main title
474
+ if (pltuName) {
475
+ doc.setFontSize(16);
476
+ doc.setFont("helvetica", "bold");
477
+ doc.text(pltuName, 14, currentY);
478
+ currentY += 10;
479
+ }
480
+
481
+ // Add Periode as subtitle
482
+ if (periode) {
483
+ doc.setFontSize(12);
484
+ doc.setFont("helvetica", "normal");
485
+ doc.text(periode, 14, currentY);
486
+ currentY += 10;
487
+ }
488
+
489
+ // Add additional title if provided
490
+ if (title) {
491
+ doc.setFontSize(14);
492
+ doc.setFont("helvetica", "bold");
493
+ doc.text(title, 14, currentY);
494
+ currentY += 10;
495
+ }
496
+
497
+ const headers = columns ? columns.map(col => col.label) : Object.keys(data[0]);
498
+ const rows = data.map(row => {
499
+ return columns ? columns.map(col => formatPDFCell(row[col.key])) : Object.values(row).map(cell => formatPDFCell(cell));
500
+ });
501
+
502
+ autoTable(doc, {
503
+ head: [headers],
504
+ body: rows,
505
+ startY: currentY + 5,
506
+ styles: {
507
+ fontSize: 8,
508
+ cellPadding: 2
509
+ },
510
+ headStyles: {
511
+ fillColor: [66, 139, 202],
512
+ textColor: 255,
513
+ fontStyle: "bold"
514
+ },
515
+ alternateRowStyles: {
516
+ fillColor: [245, 245, 245]
517
+ },
518
+ margin: { top: currentY + 5, left: 10, right: 10 }
519
+ });
520
+
521
+ doc.save(`${filename}.pdf`);
522
+ } catch (error) {
523
+ console.error("Error exporting PDF:", error);
524
+ }
525
+ }
526
+
527
+ export function exportToExcel(data: any[], filename: string, columns?: { key: string; label: string }[], sheetName: string = "Sheet1", pltuName?: string, periode?: string) {
528
+ if (!data || !data.length) {
529
+ console.warn("No data to export");
530
+ return;
531
+ }
532
+
533
+ try {
534
+ let exportData: any[];
535
+ let headerRowsCount = 0;
536
+
537
+ // Prepare title and subtitle rows
538
+ const titleRows: any[] = [];
539
+
540
+ if (pltuName) {
541
+ titleRows.push({ A: pltuName });
542
+ headerRowsCount++;
543
+ }
544
+
545
+ if (periode) {
546
+ titleRows.push({ A: periode });
547
+ headerRowsCount++;
548
+ }
549
+
550
+ // Add empty row if we have title/subtitle
551
+ if (headerRowsCount > 0) {
552
+ titleRows.push({});
553
+ headerRowsCount++;
554
+ }
555
+
556
+ if (columns) {
557
+ const headers = columns.reduce((acc, col) => {
558
+ acc[col.key] = col.label;
559
+ return acc;
560
+ }, {} as any);
561
+
562
+ exportData = [
563
+ ...titleRows,
564
+ headers,
565
+ ...data.map(row => {
566
+ return columns.reduce((acc, col) => {
567
+ acc[col.key] = formatExcelCell(row[col.key]);
568
+ return acc;
569
+ }, {} as any);
570
+ })
571
+ ];
572
+ } else {
573
+ exportData = [
574
+ ...titleRows,
575
+ ...data.map(row => {
576
+ return Object.keys(row).reduce((acc, key) => {
577
+ acc[key] = formatExcelCell(row[key]);
578
+ return acc;
579
+ }, {} as any);
580
+ })
581
+ ];
582
+ }
583
+
584
+ const ws = XLSX.utils.json_to_sheet(exportData, { skipHeader: !!columns });
585
+
586
+ // Style the title and subtitle rows
587
+ if (pltuName && ws['A1']) {
588
+ ws['A1'].s = {
589
+ font: { bold: true, sz: 16 },
590
+ alignment: { horizontal: 'left' }
591
+ };
592
+ }
593
+
594
+ if (periode && ws['A2']) {
595
+ ws['A2'].s = {
596
+ font: { sz: 12 },
597
+ alignment: { horizontal: 'left' }
598
+ };
599
+ }
600
+
601
+ const wb = XLSX.utils.book_new();
602
+ XLSX.utils.book_append_sheet(wb, ws, sheetName);
603
+
604
+ const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" });
605
+ const blob = new Blob([excelBuffer], {
606
+ type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
607
+ });
608
+
609
+ saveAs(blob, `${filename}.xlsx`);
610
+ } catch (error) {
611
+ console.error("Error exporting Excel:", error);
612
+ }
613
+ }
614
+
615
+ function formatPDFCell(value: any): string {
616
+ if (value === null || value === undefined) {
617
+ return "";
618
+ }
619
+ return String(value);
620
+ }
621
+
622
+ function formatExcelCell(value: any): any {
623
+ if (value === null || value === undefined) {
624
+ return "";
625
+ }
626
+
627
+ if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value)) {
628
+ return new Date(value);
629
+ }
630
+
631
+ return value;
632
+ }
633
+
634
+ export function convertToUtf8(inputString: string) {
635
+ const encoder = new TextEncoder();
636
+ const utf8Bytes = encoder.encode(inputString);
637
+
638
+ const hexString = Array.from(utf8Bytes)
639
+ .map(byte => byte.toString(16).padStart(2, "0"))
640
+ .join("");
641
+
642
+ return `%${hexString}`;
643
+ }