@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,991 @@
1
+ <script setup lang="ts">
2
+ import { computed, nextTick, onMounted, ref } from "vue";
3
+ import {
4
+ LucideCheckCheck,
5
+ LucideX,
6
+ LucideFile,
7
+ LucideDownload,
8
+ LucideFileArchive,
9
+ LucideCheck,
10
+ LucidePencilLine,
11
+ LucideFileWarning,
12
+ LucideFilePenLine,
13
+ LucideMinus,
14
+ LucidePlus,
15
+ LucideChevronUp,
16
+ LucideNotebookPen,
17
+ LucideArrowDown,
18
+ LucideArrowUp,
19
+ LucideLogs,
20
+ LucideLoaderCircle,
21
+ LucideRotateCcw
22
+ } from "lucide-vue-next";
23
+ import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from "@/components/ui/sheet";
24
+ import { cn, isValidValue } from "@/lib/utils";
25
+ import { type ErrorDialogOptions } from "@/components/dialog/ErrorDialog.vue";
26
+ import pdfLogo from "@/assets/pdf-logo.svg";
27
+ import ConfirmDialog from "@/components/dialog/ConfirmDialog.vue";
28
+ import api from "@/api/api";
29
+ import moment from "moment";
30
+ import FormInputerDialog from "@/components/dialog/FormInputerDialog.vue";
31
+ import { DialogDescription, DialogTitle } from "@/components/ui/dialog";
32
+ import PdfViewer from "@/components/helper/PdfViewer.vue";
33
+ import BtnCircle from "@/components/button/BtnCircle.vue";
34
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
35
+ import LoadingIndicator from "@/components/loadings/LoadingIndicator.vue";
36
+ import { useConfirmDialog, useErrorDialog, useInfoDialog, useLoadingDialog, useSuccessDialog } from "@/stores/dialog";
37
+ import type { DasiV2FormSchema } from "@/types/form.types";
38
+ import DetailContentLoading from "@/components/detail/DetailContentLoading.vue";
39
+ import DetailContentHeader from "@/components/detail/DetailContentHeader.vue";
40
+ import ApprovalInfo from "./ApprovalInfo.vue";
41
+ import { InternalServerError } from "@/lib/constants";
42
+ import type { ColumnRef, PageConfig } from "@/vueform/config/types";
43
+ import { getPageDataDetail } from "@/lib/page.utils";
44
+ import { ScrollArea } from "@/components/ui/scroll-area";
45
+ import DCI2 from "@/components/detail/DCI2.vue";
46
+
47
+ export interface DocViewerOptions {
48
+ title?: string;
49
+ item: any;
50
+ file?: any;
51
+ }
52
+
53
+ interface Props {
54
+ formSchema: DasiV2FormSchema;
55
+ detailEndpoint: string;
56
+ docsEndpoint: string;
57
+ columns?: ColumnRef[];
58
+ pageConfig?: PageConfig;
59
+ showFooter?: boolean;
60
+ title?: string;
61
+ class?: string;
62
+ approvalDisabled?: boolean;
63
+ }
64
+ const props = withDefaults(defineProps<Props>(), {
65
+ title: "Data Detail"
66
+ });
67
+ const emits = defineEmits(["close"]);
68
+
69
+ const data = defineModel<any>("data", { default: {} });
70
+ const loadingDetail = ref(true);
71
+ const sheetOpen = ref(false);
72
+ const loading = ref(false);
73
+ const file = ref<any>(null);
74
+ const detailSelected = ref(true);
75
+ const approvalStatus = ref<any>(null);
76
+ const dialogTitle = ref(props.title);
77
+ let resolveFn: (value: boolean) => void;
78
+
79
+ /**
80
+ * For shipment and payment flow
81
+ * when displaying parent and child data
82
+ *
83
+ */
84
+ const parentData = ref<any>(null);
85
+ const loadingParent = ref(false);
86
+
87
+ /**
88
+ * Used to set loading on button
89
+ *
90
+ */
91
+ const saving = ref(false);
92
+ const generatingDocs = ref(false);
93
+
94
+ const inputerDialogType = ref("");
95
+ const selectedFiles = ref<string[]>([]);
96
+ const isApprovalDisabled = computed(() => {
97
+ /**
98
+ * Approval disabled if
99
+ * User can not approve this doc, or
100
+ * document already approved
101
+ *
102
+ */
103
+ return loading.value || !myApproval.value || myApproval.value.approvalStatus !== "WAITING_APPROVAL";
104
+ });
105
+
106
+ /**
107
+ * Pdf viewer
108
+ *
109
+ */
110
+ const pdfScale = ref(1.4);
111
+ const zoomType = ref<string>("zoom");
112
+
113
+ /**
114
+ * Documents
115
+ *
116
+ */
117
+ const docs = defineModel<any[]>("docs", { default: [] });
118
+ const showDocActions = ref(true);
119
+ const allReviewed = computed(() => {
120
+ for (const item of docs.value) {
121
+ if (item.type === "divider" || item.notes) continue;
122
+ if (!item.diperiksa) return false;
123
+ }
124
+ return true;
125
+ });
126
+ const notesCount = computed(() => {
127
+ return docs.value.filter((r: any) => r.type !== "divider" && !!r.notes).length;
128
+ });
129
+ const notes = computed(() => {
130
+ return docs.value.filter((r: any) => r.notes) ?? [];
131
+ });
132
+
133
+ /**
134
+ * Approval strategy
135
+ *
136
+ */
137
+ const approvalStrategy = ref<any>();
138
+ const approvals = ref<any[]>([]);
139
+ const myApproval = ref<any>();
140
+ const approvalRequester = ref<any>();
141
+
142
+ /**
143
+ * Approval history
144
+ *
145
+ */
146
+ const approvalHistory = ref<any[]>([]);
147
+ const viewAllHistory = ref(false);
148
+ const approvalHistoryView = computed(() => {
149
+ return viewAllHistory.value ? approvalHistory.value : approvalHistory.value.slice(0, 3);
150
+ });
151
+
152
+ /**
153
+ * El
154
+ *
155
+ */
156
+ const confirmDialog = useConfirmDialog();
157
+ const errorDialog = useErrorDialog();
158
+ const successDialog = useSuccessDialog();
159
+ const formInputerDialog = ref<any>(null);
160
+ const infoDialog = useInfoDialog();
161
+ const tidakSetujuiDialog = ref<any>(null);
162
+
163
+ async function open(options: DocViewerOptions) {
164
+ dialogTitle.value = options.title ?? props.title;
165
+ sheetOpen.value = true;
166
+ loading.value = true;
167
+ loadingDetail.value = true;
168
+ file.value = options.file;
169
+ detailSelected.value = !options.file;
170
+ await nextTick();
171
+
172
+ getDetail(options.item);
173
+ getDocs(options.item);
174
+
175
+ return new Promise(resolve => {
176
+ resolveFn = resolve;
177
+ });
178
+ }
179
+
180
+ function getDocs(item: any) {
181
+ const base = `${props.docsEndpoint}/${item.id}`;
182
+
183
+ const extractList = (r: any) => (Array.isArray(r?.data?.data) ? r.data.data : []);
184
+
185
+ // Prefer singular endpoint first; if empty/null, fallback to plural
186
+ api
187
+ .get(`${base}/document`)
188
+ .then(r => {
189
+ const list = extractList(r);
190
+ if (list && list.length > 0) {
191
+ docs.value = list;
192
+ return;
193
+ }
194
+ // Fallback when document returns empty or null
195
+ return api.get(`${base}/documents`).then(r2 => {
196
+ docs.value = extractList(r2);
197
+ });
198
+ })
199
+ .catch(() => {
200
+ // If singular fails (404 or other), try plural
201
+ return api.get(`${base}/documents`).then(r2 => {
202
+ docs.value = extractList(r2);
203
+ });
204
+ })
205
+ .finally(() => {
206
+ loading.value = false;
207
+ });
208
+ }
209
+
210
+ async function getDetail(item: any) {
211
+ /**
212
+ * This is flow page,
213
+ * used on shipment and payment
214
+ *
215
+ */
216
+ if (props.pageConfig?.parentField && props.pageConfig.nextDataField && props.pageConfig.endpoint && isValidValue(item?.[props.pageConfig.nextDataField])) {
217
+ loadingParent.value = true;
218
+ getPageDataDetail({
219
+ endpoint: props.pageConfig.endpoint ?? "",
220
+ pageConfig: props.pageConfig,
221
+ item: { id: item.id },
222
+ formSchema: {}
223
+ })
224
+ .then(r => {
225
+ if (!r || !r.data) return;
226
+ parentData.value = r.data.data || r.data;
227
+ })
228
+ .finally(() => {
229
+ loadingParent.value = false;
230
+ });
231
+ }
232
+
233
+ const detailEndpoint =
234
+ props.detailEndpoint || props.pageConfig?.viewDetailEndpoint || props.pageConfig?.viewDocsEndpoint || props.pageConfig?.savePath || props.pageConfig?.endpoint || props.docsEndpoint || "";
235
+
236
+ getPageDataDetail({
237
+ item: item,
238
+ endpoint: props.pageConfig?.viewDetailEndpoint ?? props.pageConfig?.viewDocsEndpoint ?? props.pageConfig?.savePath ?? props.pageConfig?.endpoint ?? "",
239
+ pageConfig: props.pageConfig,
240
+ formSchema: props.formSchema,
241
+ includeExtras: false
242
+ })
243
+ .then(r => {
244
+ if (!r) return;
245
+ data.value = r.data.data;
246
+ approvalStrategy.value = r.data.approvalStrategy;
247
+ approvals.value = r.data.approvals;
248
+ myApproval.value = r.data.myApproval;
249
+ approvalRequester.value = r.data.requester;
250
+ approvalHistory.value = r.data.approvalHistory ?? [];
251
+ })
252
+ .finally(() => {
253
+ loadingDetail.value = false;
254
+ });
255
+ }
256
+
257
+ function close() {
258
+ const b = !!myApproval.value;
259
+ emits("close", b);
260
+ sheetOpen.value = false;
261
+ resolveFn(b);
262
+ }
263
+
264
+ function checkAllReviewed(): boolean {
265
+ if (!allReviewed.value) {
266
+ infoDialog.open({
267
+ title: "Dokumen belum diperiksa",
268
+ description: "Mohon untuk periksa semua dokumen dan pastikan informasi sudah benar untuk melanjutkan.",
269
+ actionLabel: "Tutup"
270
+ });
271
+ return false;
272
+ }
273
+ return true;
274
+ }
275
+
276
+ function setujui() {
277
+ if (!checkAllReviewed()) return;
278
+ if (notesCount.value) {
279
+ infoDialog.open({
280
+ title: "Terdapat catatan perbaikan",
281
+ description: "Untuk menyetujui dokumen ini, mohon pastikan sudah tidak ada catatan perbaikan.",
282
+ actionLabel: "Tutup"
283
+ });
284
+ return;
285
+ }
286
+
287
+ inputerDialogType.value = "setujui";
288
+ confirmDialog
289
+ .open({
290
+ title: "Setujui Data",
291
+ description: `Apakah Anda yakin ingin menyetujui dokumen <b class="text-blue-500">${dialogTitle.value}</b> ini?`,
292
+ actionLabel: "Setujui Dokumen",
293
+ cancelLabel: "Batal",
294
+ negative: false
295
+ })
296
+ .then((b: boolean) => {
297
+ if (!b) return;
298
+ const noteItems = [];
299
+ for (const item of docs.value.filter((r: any) => r.type !== "divider") ?? []) {
300
+ noteItems.push({
301
+ diperiksa: item.diperiksa,
302
+ idDokumen: item.id,
303
+ namaDokumen: item.name,
304
+ mediaId: item.mediaId,
305
+ keterangan: item.notes,
306
+ tipeDokumen: item.id
307
+ });
308
+ }
309
+ saving.value = true;
310
+ api
311
+ .post(`${props.docsEndpoint}/${data.value.id}/approve`, {
312
+ items: noteItems
313
+ })
314
+ .then(r => {
315
+ getDetail(data.value);
316
+ successDialog.open();
317
+ })
318
+ .finally(() => {
319
+ saving.value = false;
320
+ });
321
+ });
322
+ }
323
+
324
+ function tidakSetujui() {
325
+ if (!checkAllReviewed()) return;
326
+
327
+ if (!notesCount.value && docs.value.length > 0) {
328
+ infoDialog.open({
329
+ title: "Tidak ada catatan",
330
+ description: "Mohon untuk mengisi catatan pada satu atau beberapa dokumen perbaikan untuk melanjutkan.",
331
+ actionLabel: "Tutup"
332
+ });
333
+ return;
334
+ }
335
+
336
+ const msg = notesCount.value
337
+ ? "Dokumen tidak disetujui dengan catatan yang akan ditujukan ke masing - masing penanggun jawab, dengan catatan sebagai berikut:"
338
+ : "Apakah Anda yakin untuk tidak menyetujui Data ini? Data akan dikembalikan ke pengaju approval untuk perbaikan ulang.";
339
+ tidakSetujuiDialog.value.open(
340
+ {
341
+ title: "Tidak Setujui Dokumen",
342
+ description: msg,
343
+ cancelLabel: "Batal",
344
+ actionLabel: "Tidak Setujui",
345
+ negative: true
346
+ },
347
+ (b: boolean) => {
348
+ if (!b) return;
349
+ const noteItems = [];
350
+ for (const item of docs.value.filter((r: any) => r.type !== "divider") ?? []) {
351
+ noteItems.push({
352
+ diperiksa: item.diperiksa,
353
+ idDokumen: item.id,
354
+ namaDokumen: item.name,
355
+ mediaId: item.mediaId,
356
+ keterangan: item.notes,
357
+ tipeDokumen: item.id
358
+ });
359
+ }
360
+ saving.value = true;
361
+ api
362
+ .post(`${props.docsEndpoint}/${data.value.id}/reject`, {
363
+ items: noteItems
364
+ })
365
+ .then(r => {
366
+ successDialog.open();
367
+ getDetail(data.value);
368
+ })
369
+ .catch(err => {
370
+ const options: ErrorDialogOptions = {
371
+ title: "Tidak Setujui Gagal",
372
+ description: err.message || "Internal server error"
373
+ };
374
+ errorDialog.open(options);
375
+ })
376
+ .finally(() => {
377
+ saving.value = false;
378
+ });
379
+ }
380
+ );
381
+ }
382
+
383
+ function reviewAllFile() {
384
+ confirmDialog
385
+ .open({
386
+ title: "Periksa Semua File",
387
+ description: `Apakah Anda sudah memeriksa semua file dokumen?`,
388
+ cancelLabel: "Batal",
389
+ actionLabel: "Sudah Diperiksa",
390
+ negative: false
391
+ })
392
+ .then((b: any) => {
393
+ if (!b) return;
394
+ for (const r of docs.value) {
395
+ if (r.type === "divider" || r.notes || !r.url) continue;
396
+ r.diperiksa = true;
397
+ }
398
+ });
399
+ }
400
+
401
+ function selectItem(item: any) {
402
+ file.value = item;
403
+ document.getElementById(`pdf-container-${item.id}`)?.scrollIntoView();
404
+ }
405
+
406
+ function selectFile(item: any) {
407
+ if (!selectedFiles.value.includes(item.id)) selectedFiles.value.push(item.id);
408
+ else selectedFiles.value.splice(selectedFiles.value.indexOf(item.id), 1);
409
+ }
410
+
411
+ function selectAllFile() {
412
+ if (selectedFiles.value.length === docs.value.filter((r: any) => r.type !== "divider").length) {
413
+ selectedFiles.value = [];
414
+ } else {
415
+ selectedFiles.value = docs.value.filter((r: any) => r.type !== "divider").map((r: any) => r.id);
416
+ }
417
+ }
418
+
419
+ function toggleReviewed(item: any) {
420
+ if (isApprovalDisabled.value) return;
421
+ if (item.notes || !item.url) return;
422
+ item.diperiksa = !item.diperiksa;
423
+ }
424
+
425
+ function tulisCatatan(item: any) {
426
+ if (isApprovalDisabled.value) return;
427
+ inputerDialogType.value = "catatan";
428
+ formInputerDialog.value.open(
429
+ {
430
+ keterangan: {
431
+ type: "textarea",
432
+ label: "Catatan",
433
+ placeholder: "Tulis catatan....",
434
+ default: item.notes,
435
+ disabled: approvalStatus.value && approvalStatus.value.status === false && !approvalStatus.value.submitUlang
436
+ }
437
+ },
438
+ (formData: any) => {
439
+ item.notes = formData.keterangan;
440
+ }
441
+ );
442
+ }
443
+
444
+ function submitApproval() {
445
+ if (saving.value) return;
446
+ confirmDialog
447
+ .open({
448
+ title: "Submit Approval",
449
+ description: `Apakah Anda yakin untuk submit data ini untuk proses Approval?<br /><br />` + "Setelah data disubmit untuk proses approval, data sudah tidak dapat melakukan perubahan lagi.",
450
+ cancelLabel: "Batal",
451
+ actionLabel: "Submit Approval",
452
+ negative: false
453
+ })
454
+ .then((b: any) => {
455
+ if (!b) return;
456
+ saving.value = true;
457
+ api
458
+ .post(`${props.docsEndpoint}/${data.value.id}/approval`)
459
+ .then(r => {
460
+ getDetail(data.value);
461
+ successDialog.open();
462
+ })
463
+ .catch(err => {
464
+ errorDialog.open({
465
+ title: "Submit Approval Gagal",
466
+ description: err.message ?? InternalServerError
467
+ });
468
+ })
469
+ .finally(() => {
470
+ saving.value = false;
471
+ });
472
+ });
473
+ }
474
+
475
+ function onInteractOutside(e: any) {
476
+ e.preventDefault();
477
+ }
478
+
479
+ function onScrolled(e: any) {
480
+ detailSelected.value = e.target.scrollTop < (document.getElementById("pdf-sc-top-helper")?.offsetTop ?? 0);
481
+ for (const item of docs.value) {
482
+ if (item.type === "divider") continue;
483
+ const elOffsetTop = document.getElementById(`pdf-container-${item.id}`)?.offsetTop || 0;
484
+ if (e.target.scrollTop >= elOffsetTop) {
485
+ file.value = item;
486
+ }
487
+ }
488
+ }
489
+
490
+ function reloadData() {
491
+ if (!data.value) return;
492
+ getDocs(data.value);
493
+ getDetail(data.value);
494
+ }
495
+
496
+ onMounted(() => {});
497
+
498
+ defineExpose({ open, close, getDocs, reloadData });
499
+ </script>
500
+
501
+ <template>
502
+ <Sheet v-model:open="sheetOpen">
503
+ <SheetContent
504
+ :class="cn('w-[calc(100vw-80px)] !max-w-[calc(100vw-80px)] bg-white px-8 pt-3 dark:border-dark_bg2 dark:bg-dark_bg2', props.class)"
505
+ v-on:escape-key-down="onInteractOutside"
506
+ v-on:pointer-down-outside="onInteractOutside">
507
+ <SheetHeader class="relative gap-y-0.5 pl-6">
508
+ <button
509
+ v-on:click="close"
510
+ class="absolute -left-4 top-0 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full text-gray-500 transition hover:bg-hover_main hover:text-primary_main">
511
+ <LucideX class="h-6 w-6"></LucideX>
512
+ </button>
513
+ <SheetTitle>{{ dialogTitle }}</SheetTitle>
514
+ </SheetHeader>
515
+ <section class="absolute bottom-0 left-0 right-0 top-14 flex w-full border-t dark:border-dark_border3" :class="{ '!bottom-14': props.showFooter }">
516
+ <div class="h-full w-full flex-1 basis-auto">
517
+ <section v-if="loading" class="flex h-full items-center justify-center">
518
+ <LoadingIndicator class="scale-90" />
519
+ </section>
520
+ <div class="flex h-full w-full" v-else>
521
+ <!-- leftbar -->
522
+ <div class="flex h-full w-[260px] flex-none flex-col overflow-hidden border-r bg-white dark:border-dark_border3 dark:bg-dark_bg2">
523
+ <div class="h-full">
524
+ <div class="p-1">
525
+ <div
526
+ class="group relative flex cursor-pointer items-center gap-2 rounded-sm border px-2 py-2 hover:bg-accent dark:border-dark_bg5 dark:bg-dark_bg5"
527
+ :class="{ '!border-blue-500 !bg-blue-100 !text-blue-500 dark:!bg-blue-500 dark:!text-white': detailSelected }">
528
+ <LucideLogs :size="20" :stroke-width="2" class="mr-px" />
529
+ <span class="text-[13px] font-medium leading-tight"> Informasi Detail </span>
530
+ </div>
531
+ </div>
532
+
533
+ <div class="mb-1 flex h-[36px] items-center border-b px-4 dark:border-dark_border3" v-if="docs.length > 0">
534
+ <div class="flex items-center gap-1.5 text-sm font-medium">
535
+ <button class="group -ml-[5px] rounded-full p-1.5 hover:bg-blue-100" v-on:click="selectAllFile">
536
+ <button
537
+ class="flex size-4 items-center justify-center rounded-sm border-2 border-slate-400 group-hover:border-blue-500 dark:border-dark_bg2"
538
+ :class="{ '!border-blue-500 !bg-blue-500 !text-white': selectedFiles.length > 0 }">
539
+ <LucideCheck :stroke-width="3" v-if="selectedFiles.length === docs.filter((r: any) => r.type !== 'divider').length" />
540
+ <LucideMinus :stroke-width="3" v-else-if="selectedFiles.length > 0" />
541
+ </button>
542
+ </button>
543
+ List Dokumen
544
+ </div>
545
+ </div>
546
+
547
+ <ScrollArea class="h-[calc(100vh-143px)]">
548
+ <div class="space-y-1 px-1 pb-16">
549
+ <template v-for="(item, i) in docs" :key="i">
550
+ <div class="!mt-5 px-2.5 text-sm font-medium opacity-65" v-if="item.type === 'divider'">
551
+ {{ item.name }}
552
+ </div>
553
+ <div
554
+ class="group relative flex cursor-pointer items-center gap-2 rounded-sm border px-2 py-1.5 hover:bg-accent dark:border-dark_bg4 dark:bg-dark_bg4"
555
+ :class="{
556
+ 'border-green-500 bg-green-100 text-green-600': item.diperiksa,
557
+ 'border-orange-400 bg-orange-100 text-orange-500': item.notes,
558
+ '!border-blue-500 !bg-blue-100 !text-blue-500 dark:!bg-blue-500 dark:!text-white': !detailSelected && file && file.id === item.id
559
+ }"
560
+ v-on:click="selectItem(item)"
561
+ v-else>
562
+ <div class="group relative w-6" v-if="!item.url">
563
+ <LucideFileWarning :size="22" :stroke-width="1.5" class="text-red-500" />
564
+ <div class="absolute left-0 top-full z-9 hidden w-[130px] rounded-md bg-black/75 px-2.5 py-1.5 text-[11px] leading-tight text-white group-hover:block">
565
+ Dokumen {{ item.name }} tidak tersedia
566
+ </div>
567
+ </div>
568
+ <img :src="pdfLogo" class="h-6 flex-none" v-else />
569
+ <button
570
+ class="absolute left-2 top-1.5 hidden rounded-md bg-white p-1 group-hover:block group-hover:bg-accent"
571
+ :class="{ '!bg-blue-100': file && file.id === item.id, '!block': selectedFiles.includes(item.id) }"
572
+ v-on:click="selectFile(item)">
573
+ <div
574
+ class="flex size-4 items-center justify-center rounded-sm border-2 border-slate-400 bg-white hover:border-blue-500"
575
+ :class="{ '!border-blue-500 !bg-blue-500 !text-white': selectedFiles.includes(item.id) }">
576
+ <LucideCheck v-if="selectedFiles.includes(item.id)" :stroke-width="3" />
577
+ </div>
578
+ </button>
579
+ <span class="text-[13px] font-medium leading-tight">{{ item.name }}</span>
580
+ <div class="ml-auto flex size-4 flex-none items-center justify-center" v-if="item.diperiksa || item.notes">
581
+ <LucideFilePenLine v-if="item.notes" />
582
+ <LucideCheck v-else />
583
+ </div>
584
+ </div>
585
+ <div class="!mt-5 px-2.5 text-sm font-medium opacity-65" v-if="item.id === 'dokBastCif'">Dokumen Pendukung</div>
586
+ </template>
587
+ <a
588
+ :href="''"
589
+ target="_blank"
590
+ download
591
+ class="flex w-full items-center gap-2 rounded-sm border border-blue-500 px-3 py-1.5 text-[13px] font-medium text-blue-500 transition hover:bg-blue-100"
592
+ v-if="selectedFiles.length > 0">
593
+ <LucideFileArchive :size="20" class="-ml-0.5 mr-0.5" />
594
+ Unduh File Terpilih
595
+ </a>
596
+ </div>
597
+ </ScrollArea>
598
+ </div>
599
+ </div>
600
+
601
+ <!-- Main Content -->
602
+ <div class="flex h-full w-full flex-col">
603
+ <div class="relative flex-1 bg-accent/10">
604
+ <div class="absolute bottom-2 left-2 right-2 z-[50] flex items-center gap-1.5 px-4 py-1" v-if="isValidValue(docs) && showDocActions">
605
+ <BtnCircle class="border bg-white shadow-lg dark:border-dark_bg7 dark:bg-dark_bg7 dark:text-white dark:hover:bg-dark_bg8" @click="reloadData">
606
+ <LucideRotateCcw :size="18" />
607
+ </BtnCircle>
608
+ <BtnCircle
609
+ class="border bg-white shadow-lg dark:border-dark_bg7 dark:bg-dark_bg7 dark:text-white dark:hover:bg-dark_bg8"
610
+ v-on:click="
611
+ pdfScale -= 0.1;
612
+ zoomType = 'zoom';
613
+ ">
614
+ <LucideMinus :size="18" />
615
+ </BtnCircle>
616
+ <DropdownMenu>
617
+ <DropdownMenuTrigger as-child>
618
+ <BtnCircle class="!w-auto gap-2 border bg-white px-4 shadow-lg dark:border-dark_bg7 dark:bg-dark_bg7 dark:text-white dark:hover:bg-dark_bg8">
619
+ <template v-if="zoomType === 'page-fit'"> Page Fit </template>
620
+ <template v-else-if="zoomType === 'page-width'"> Page Width </template>
621
+ <template v-else> {{ (pdfScale * 100).toFixed(0) }}% </template>
622
+ <LucideChevronUp :size="18" />
623
+ </BtnCircle>
624
+ </DropdownMenuTrigger>
625
+ <DropdownMenuContent class="w-56">
626
+ <DropdownMenuLabel>PDF Viewer Zoom</DropdownMenuLabel>
627
+ <DropdownMenuSeparator />
628
+ <DropdownMenuItem v-on:click="pdfScale = 0.5">
629
+ <span>50%</span>
630
+ </DropdownMenuItem>
631
+ <DropdownMenuItem v-on:click="pdfScale = 0.75">
632
+ <span>75%</span>
633
+ </DropdownMenuItem>
634
+ <DropdownMenuItem v-on:click="pdfScale = 1">
635
+ <span>100%</span>
636
+ </DropdownMenuItem>
637
+ <DropdownMenuItem v-on:click="pdfScale = 1.2">
638
+ <span>120%</span>
639
+ </DropdownMenuItem>
640
+ <DropdownMenuItem v-on:click="pdfScale = 1.5">
641
+ <span>150%</span>
642
+ </DropdownMenuItem>
643
+ <DropdownMenuItem v-on:click="pdfScale = 2">
644
+ <span>200%</span>
645
+ </DropdownMenuItem>
646
+ <DropdownMenuItem v-on:click="pdfScale = 3">
647
+ <span>300%</span>
648
+ </DropdownMenuItem>
649
+ <DropdownMenuItem v-on:click="pdfScale = 4">
650
+ <span>400%</span>
651
+ </DropdownMenuItem>
652
+ </DropdownMenuContent>
653
+ </DropdownMenu>
654
+ <BtnCircle
655
+ class="border bg-white shadow-lg dark:border-dark_bg7 dark:bg-dark_bg7 dark:text-white dark:hover:bg-dark_bg8"
656
+ v-on:click="
657
+ pdfScale += 0.1;
658
+ zoomType = 'zoom';
659
+ ">
660
+ <LucidePlus :size="18" />
661
+ </BtnCircle>
662
+
663
+ <BtnCircle class="ml-auto !w-auto gap-2 border bg-white px-4 shadow-lg dark:border-none dark:bg-blue-500 dark:text-white dark:hover:bg-blue-600" v-on:click="reviewAllFile">
664
+ <LucideCheckCheck :size="18" class="text-blue-600 dark:text-white" />
665
+ Periksa Semua Dokumen
666
+ </BtnCircle>
667
+ </div>
668
+ <div class="flex h-8 items-center gap-2 bg-slate-100 px-5 text-xs text-gray-600 dark:bg-dark_bg dark:text-gray-500" v-if="generatingDocs">
669
+ <LucideLoaderCircle class="animate-spin" :size="18" />
670
+ Generating document...
671
+ </div>
672
+ <div class="absolute bottom-0 left-0 right-0 top-0" :class="{ 'top-8': generatingDocs }">
673
+ <div class="h-full overflow-auto" id="pdf-sc-area" v-on:scroll="onScrolled">
674
+ <!-- view detail data -->
675
+ <section>
676
+ <DetailContentLoading v-if="loadingDetail || loadingParent" />
677
+ <div class="bg-white py-5 dark:bg-dark_bg2" v-else-if="data">
678
+ <DetailContentHeader :data="data" :endpoint="detailEndpoint" :pageConfig="pageConfig" />
679
+ <template v-if="columns && parentData">
680
+ <section class="detail-items px-6 pt-4">
681
+ <div class="vueform-divider"><span>Informasi General</span></div>
682
+ </section>
683
+ <DCI2 :columns="columns" :data="parentData" />
684
+ <div class="border-t py-1"></div>
685
+ </template>
686
+ <DCI2 :schema="formSchema" :data="data" v-if="formSchema" />
687
+ <!-- <DetailContentItems :data="data" :schema="props.formSchema"/> -->
688
+ </div>
689
+ </section>
690
+
691
+ <!-- documents viewer -->
692
+ <div id="pdf-sc-top-helper"></div>
693
+ <div v-for="(item, i) in docs">
694
+ <div class="bg-gray-600 px-4 pb-1 pt-8 text-sm font-medium text-white/50" v-if="item.type === 'divider'">
695
+ {{ item.name }}
696
+ </div>
697
+ <div :id="`pdf-container-${item.id}`" v-else>
698
+ <div class="sticky top-0 z-10 flex items-center bg-gray-700 px-4 py-1.5 shadow-md dark:bg-dark_bg4">
699
+ <h4 class="text-sm font-medium text-white">
700
+ {{ item.name }}
701
+ </h4>
702
+ <div class="ml-auto flex items-center gap-1.5">
703
+ <a
704
+ :href="item.downloadUrl"
705
+ target="_blank"
706
+ v-if="item.downloadUrl"
707
+ class="mr-2 flex cursor-pointer items-center gap-1 rounded-md bg-slate-800 py-1.5 pl-1.5 pr-3 text-sm font-medium text-white/90 transition hover:bg-slate-600 hover:shadow-sm">
708
+ <LucideDownload class="h-4" />
709
+ Download
710
+ </a>
711
+ <template v-if="myApproval">
712
+ <div class="mr-2 flex items-center gap-1.5 text-sm text-green-400" v-if="item.sudahDiperbaiki">
713
+ <LucideCheckCheck :size="22" />
714
+ Sudah diperbaiki
715
+ </div>
716
+ <button
717
+ class="flex cursor-pointer items-center gap-1 rounded-md bg-slate-800 py-1.5 pl-1.5 pr-3 text-sm font-medium text-white/90 transition hover:bg-slate-600 hover:shadow-sm"
718
+ :class="{
719
+ '!border-orange-400 !bg-orange-50 !text-orange-400': item.notes,
720
+ '!cursor-default !bg-slate-300 !text-slate-500': isApprovalDisabled && !item.notes
721
+ }"
722
+ v-on:click="tulisCatatan(item)">
723
+ <LucidePencilLine class="h-4" />
724
+ Catatan Perbaikan
725
+ </button>
726
+ <button
727
+ class="flex cursor-pointer items-center gap-2 rounded-md bg-slate-800 px-3 py-1.5 text-sm font-medium text-white/90 transition hover:bg-slate-600 hover:shadow-sm"
728
+ :class="{
729
+ '!border-green-500 !bg-green-50 !text-green-500': item.diperiksa && !item.notes && item.url,
730
+ '!cursor-default !bg-slate-300 !text-slate-500': item.notes || !item.url,
731
+ '!cursor-default': isApprovalDisabled
732
+ }"
733
+ v-on:click="toggleReviewed(item)">
734
+ Diperiksa
735
+ <div
736
+ class="flex size-4 items-center justify-center rounded-sm border-2 border-slate-300"
737
+ :class="{
738
+ '!border-green-500 !bg-green-500 !text-white': item.diperiksa && !item.notes && item.url,
739
+ '!border-slate-400 !bg-slate-400 text-black': item.notes || !item.url
740
+ }">
741
+ <LucideCheck v-if="item.diperiksa || item.notes" />
742
+ </div>
743
+ </button>
744
+ </template>
745
+ </div>
746
+ </div>
747
+ <div class="flex items-center justify-center bg-slate-100 py-[300px]" v-if="!item.url">
748
+ <div class="mx-auto w-full max-w-[500px] px-5 text-center">
749
+ <LucideFileWarning class="mx-auto mb-3" :size="46" :stroke-width="1" />
750
+ <h4 class="font-medium">File Tidak Tersedia</h4>
751
+ <p class="text-sm">Maaf untuk saat ini file dokumen tidak tersedia, mungkin terjadi kesalahan ketika proses upload file.</p>
752
+ </div>
753
+ </div>
754
+ <div class="bg-gray-600 dark:bg-dark_bg" v-else>
755
+ <div class="mx-auto w-fit max-w-full overflow-auto px-5 pb-16 pt-4">
756
+ <slot name="pdf-item" :item="item">
757
+ <PdfViewer :url="item.url + '?v=' + new Date().getTime()" :index="i" :scale="pdfScale" :zoom-type="zoomType" />
758
+ </slot>
759
+ </div>
760
+ </div>
761
+ </div>
762
+ <div class="bg-gray-600 px-4 pb-1 pt-8 text-sm font-medium text-white/50" v-if="item.id === 'dokBastCif'">Dokumen Pendukung</div>
763
+ </div>
764
+ </div>
765
+ </div>
766
+ </div>
767
+ </div>
768
+
769
+ <!-- Right Sidebar -->
770
+ <ScrollArea class="h-full w-[340px] flex-none border-l bg-white dark:border-dark_border3 dark:bg-dark_bg2">
771
+ <div class="pb-10">
772
+ <ApprovalInfo
773
+ v-if="data.status && !['DRAFT', 'PUBLISHED'].includes(data.status) && !props.approvalDisabled"
774
+ :data="data"
775
+ :loading="loadingDetail"
776
+ :saving="saving"
777
+ :approvals="approvals"
778
+ :approval-strategy="approvalStrategy"
779
+ :my-approval="myApproval"
780
+ :requester="approvalRequester"
781
+ @submit="submitApproval"
782
+ @approve="setujui"
783
+ @reject="tidakSetujui" />
784
+
785
+ <div class="mb-5 px-4 pt-4" v-if="approvalHistory && approvalHistory.length > 0">
786
+ <h4 class="mb-2 font-semibold">Riwayat Approval</h4>
787
+ <div class="space-y-3">
788
+ <div class="flex" v-for="(item, i) in approvalHistoryView" :key="i">
789
+ <template v-if="['SETUJUI', 'TOLAK', 'BUAT', 'EDIT', 'PERBAIKAN'].includes(item.tipe)">
790
+ <div class="flex h-8 w-8 flex-none items-center justify-center rounded-full bg-blue-500 text-sm uppercase text-white">
791
+ {{ item.account ? item.account.name.substring(0, 1) : "?" }}
792
+ </div>
793
+ <div class="ml-3">
794
+ <p class="max-w-[170px] overflow-hidden text-ellipsis whitespace-nowrap text-sm font-medium">
795
+ {{ item.account ? item.account.name : "-" }}
796
+ </p>
797
+ <div class="text-xs">{{ moment(item.createdAt).utc().format("DD/MM/YYYY HH:mm") }}</div>
798
+ <p class="text-xs text-muted-foreground">
799
+ {{ item && item.accessLevel ? item.accessLevel.name : "" }} &bull; {{ item.organization ? item.organization.name : "" }}<br />
800
+ <span class="font-medium text-blue-500" v-if="item.tipe === 'BUAT'"> Membuat dokumen </span>
801
+ <span class="font-medium text-red-500" v-if="item.tipe === 'TOLAK'"> Menolak persetujuan dokumen </span>
802
+ <span class="font-medium text-green-500" v-if="item.tipe === 'SETUJUI'"> Menyetujui persetujuan dokumen </span>
803
+ <span class="font-medium text-orange-500" v-if="item.tipe === 'EDIT'"> Melakukan perubahan </span>
804
+ <template v-if="item.tipe === 'PERBAIKAN'">
805
+ <span class="font-medium text-orange-400"> Melakukan perbaikan </span>
806
+ pada dokumen
807
+ <b class="font-medium">{{ item.namaDokumen }}</b>
808
+ </template>
809
+ </p>
810
+ </div>
811
+ </template>
812
+ <template v-else>
813
+ <div class="ml-3 size-3 flex-none rounded-full border-2 border-blue-500 bg-white"></div>
814
+ <div class="pl-5 text-sm leading-[1.2]">
815
+ <b>{{ item.account ? item.account.name : "-" }}</b>
816
+ <div class="text-[13px] text-gray-500">
817
+ <template v-if="item.tipe === 'PERIKSA'">
818
+ <span class="font-medium text-green-500">Memeriksa</span>
819
+ dokumen
820
+ </template>
821
+ <template v-if="item.tipe === 'CATATAN'">
822
+ Menambahkan
823
+ <span class="font-medium text-orange-500"> catatan </span>
824
+ pada dokumen
825
+ </template>
826
+ <b class="font-medium">{{ item.namaDokumen }}</b>
827
+ </div>
828
+ <div class="mt-1 rounded-sm bg-yellow-100 px-1.5 py-0.5 text-[13px] text-yellow-900" v-if="item.keterangan">
829
+ <div class="-mx-1.5 mb-0.5 flex items-center gap-1 border-b border-yellow-300 px-1.5 py-0.5 text-xs font-medium">
830
+ <LucideNotebookPen :size="14" />
831
+ Catatan Perbaikan
832
+ </div>
833
+ {{ item.keterangan }}
834
+ </div>
835
+ </div>
836
+ </template>
837
+ </div>
838
+ </div>
839
+ <BtnCircle class="mt-3 !h-7 !w-auto gap-1 border border-blue-500 pl-2 pr-3 text-sm text-blue-500" v-if="approvalHistory.length > 3" v-on:click="viewAllHistory = !viewAllHistory">
840
+ <template v-if="viewAllHistory"> <LucideArrowUp :size="18" /> Lihat lebih sedikit </template>
841
+ <template v-else> <LucideArrowDown :size="18" /> Lihat semua riwayat ({{ approvalHistory.length }}) </template>
842
+ </BtnCircle>
843
+ </div>
844
+
845
+ <div v-if="file && !detailSelected">
846
+ <div class="mb-4 border-b px-4 pb-2 pt-3">
847
+ <h2 class="flex items-center text-sm font-medium">
848
+ <LucideFile class="mr-2 size-4 flex-none" />
849
+ Detail File
850
+ </h2>
851
+ </div>
852
+
853
+ <div class="mb-6 px-4" v-if="file.url">
854
+ <div class="mb-6 flex justify-center">
855
+ <img :src="pdfLogo" alt="PDF Logo" class="h-32 w-32" />
856
+ </div>
857
+
858
+ <div class="space-y-4">
859
+ <div>
860
+ <label class="text-sm font-light text-[#3C3C4399]"> Nama File </label>
861
+ <p class="text-sm font-semibold text-[#333333]">
862
+ {{ file.name }}
863
+ </p>
864
+ </div>
865
+ <div class="flex flex-row justify-between">
866
+ <div class="w-full">
867
+ <label class="text-sm font-light text-[#3C3C4399]"> Tanggal Pembuatan </label>
868
+ <p class="text-sm font-semibold text-[#333333]">
869
+ {{ moment(file.createdAt).utc().format("DD/MM/YYYY") }}
870
+ </p>
871
+ </div>
872
+ <div v-if="1 > 2">
873
+ <label class="text-sm font-light text-[#3C3C4399]"> Jumlah File </label>
874
+ <p class="text-sm font-semibold text-[#333333]">
875
+ {{ docs.length }}
876
+ </p>
877
+ </div>
878
+ </div>
879
+ </div>
880
+ </div>
881
+
882
+ <div class="mb-5 px-4" v-if="file && file.dokumenKolaborator && file.dokumenKolaborator.length > 0">
883
+ <h3 class="mb-2 text-sm font-medium">Collaborations</h3>
884
+ <div class="space-y-3">
885
+ <div class="flex" v-for="(item, i) in file.dokumenKolaborator" :key="i">
886
+ <div class="flex h-8 w-8 flex-none items-center justify-center rounded-full bg-blue-500 text-sm uppercase text-white">
887
+ {{ item.account ? item.account.name.substring(0, 1) : "?" }}
888
+ </div>
889
+ <div class="ml-3">
890
+ <p class="max-w-[170px] overflow-hidden text-ellipsis whitespace-nowrap text-sm font-medium">
891
+ {{ item.account ? item.account.name : "-" }}
892
+ </p>
893
+ <p class="text-xs text-muted-foreground">
894
+ <template v-if="item.tipeKolaborasi === 'MAKER'"> Maker </template>
895
+ <template v-else> Checker </template>
896
+ ({{ item && item.accessLevel ? item.accessLevel.name : "" }} &bull; {{ item.organization ? item.organization.name : "" }})
897
+ </p>
898
+ </div>
899
+ </div>
900
+ </div>
901
+ </div>
902
+ </div>
903
+ </div>
904
+ </ScrollArea>
905
+ </div>
906
+ </div>
907
+ </section>
908
+ <SheetFooter v-if="props.showFooter" class="border-t dark:border-none dark:bg-dark_bg4">
909
+ <slot name="footer">
910
+ <!-- <template v-if="['APPROVAL_REQUIRED'].includes(data.status)">
911
+ <BtnPrimary class="pl-4 pr-6 h-10 flex items-center cursor-pointer rounded-md transition bg-blue-500 text-white hover:bg-blue-600"
912
+ :class="{'!text-gray-400 !bg-gray-300 !shadow-none hover:!bg-gray-300 !cursor-default': !allReviewed}"
913
+ :loading="saving"
914
+ v-on:click="submitApproval">
915
+ <LucideCheckCheck class="mr-2.5" :size="20" />
916
+ Submit Approval
917
+ </BtnPrimary>
918
+ </template>
919
+ <template v-else-if="approvalStatus?.myApproval?.disetujui == null || approvalStatus?.myApproval?.submitUlang">
920
+ <button class="px-4 h-10 text-red-500 cursor-pointer hover:bg-red-100 rounded-md transition"
921
+ :class="{'!text-gray-400 !bg-none hover:!bg-transparent !cursor-default': !allReviewed}"
922
+ v-on:click="tidakSetujui">
923
+ Tolak
924
+ </button>
925
+ <button class="pl-4 pr-6 h-10 flex items-center cursor-pointer rounded-md transition bg-blue-500 text-white hover:bg-blue-600"
926
+ v-on:click="setujui"
927
+ :class="{'!text-gray-400 !bg-gray-300 !shadow-none hover:!bg-gray-300 !cursor-default': !allReviewed}">
928
+ <LucideCheckCheck class="mr-2.5" :size="20" />
929
+ Setujui
930
+ </button>
931
+ </template>
932
+ <div class="text-right text-sm leading-[1.3] text-gray-500"
933
+ v-else-if="approvalStatus.myApproval">
934
+ Dokumen
935
+ <b class="text-green-500 font-medium" v-if="approvalStatus.myApproval.disetujui">Disetujui</b>
936
+ <b class="text-red-500 font-medium" v-else>Ditolak</b>
937
+ <br />
938
+ oleh <b class="text-gray-600 font-medium">{{ approvalStatus.myApproval.account?.name }}</b> pada
939
+ <b class="text-gray-600 font-medium">{{ moment(approvalStatus.myApproval.createdAt).format('DD/MM/YYYY HH:mm') }}</b>
940
+ </div> -->
941
+ </slot>
942
+ </SheetFooter>
943
+ </SheetContent>
944
+ </Sheet>
945
+ <!-- @NOTES : REMOVE REF COMPONENT -->
946
+ <!-- <ErrorDialog ref="errorDialog" />
947
+ <ConfirmDialog ref="confirmDialog"/>
948
+ <LoadingDialog ref="loadingDialog"/>
949
+ <InfoDialog ref="infoDialog"/> -->
950
+ <ConfirmDialog ref="tidakSetujuiDialog">
951
+ <template #content>
952
+ <div class="-mx-6 -mb-4 max-h-[56vh] overflow-auto border-b border-t px-6 pb-3" v-if="notes.length > 0">
953
+ <div class="space-y-2 pt-3">
954
+ <div class="rounded-sm border" v-for="(item, i2) in notes" :key="i2">
955
+ <div class="flex items-center gap-2 border-b px-2 py-1.5">
956
+ <div class="group relative w-6" v-if="!item.url">
957
+ <LucideFileWarning :size="22" :stroke-width="1.5" class="text-red-500" />
958
+ <div class="absolute left-0 top-full z-9 hidden w-[130px] rounded-md bg-black/75 px-2.5 py-1.5 text-[11px] leading-tight text-white group-hover:block">
959
+ Dokumen {{ item.name }} tidak tersedia
960
+ </div>
961
+ </div>
962
+ <img :src="pdfLogo" class="h-6 flex-none" v-else />
963
+ <span class="text-[13px] font-semibold leading-tight">{{ item.name }}</span>
964
+ </div>
965
+ <div class="bg-yellow-50 px-3 py-2 text-[13px] leading-tight text-yellow-950 opacity-85">
966
+ {{ item.notes }}
967
+ </div>
968
+ </div>
969
+ </div>
970
+ </div>
971
+ </template>
972
+ </ConfirmDialog>
973
+ <FormInputerDialog ref="formInputerDialog" :class="{ 'max-w-[640px]': inputerDialogType === 'setujui' }">
974
+ <template #header v-if="inputerDialogType === 'catatan'">
975
+ <DialogTitle>Catatan</DialogTitle>
976
+ <DialogDescription> Silahkan masukkan catatan untuk perubahan, catatan ini akan ditujukan kepada pihak yg bertanggung jawab terhadap file ini untuk dilakukan perubahan. </DialogDescription>
977
+ </template>
978
+ <template #header v-else-if="inputerDialogType === 'setujui'">
979
+ <DialogTitle>Setujui Dokumen</DialogTitle>
980
+ <DialogDescription> Silahkan masukkan informasi tambahan untuk menyetujui dokumen ini. </DialogDescription>
981
+ </template>
982
+ <template #button-label v-if="inputerDialogType === 'setujui'">
983
+ <LucideCheckCheck class="-ml-2 mr-3" />
984
+ Setujui
985
+ </template>
986
+ </FormInputerDialog>
987
+ </template>
988
+
989
+ <style>
990
+ @import "vue3-perfect-scrollbar/style.css";
991
+ </style>