@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.
- package/README.md +346 -0
- package/bin/dasi-cli.cjs +184 -0
- package/dist/date-selector-test-BlukYeWl.js +91 -0
- package/dist/favicon.ico +0 -0
- package/dist/html2canvas.esm-CKxSAI8P.js +4886 -0
- package/dist/img/brand/ic_pln.svg +12 -0
- package/dist/img/brand/mapp_power_logo.svg +21 -0
- package/dist/img/common/pltu_ulumbu_flores_ntt.jpeg +0 -0
- package/dist/index-BQSA2aPs.js +126556 -0
- package/dist/index.es-DQWt-PZn.js +5769 -0
- package/dist/index.es.js +11 -0
- package/dist/index.umd.js +8564 -0
- package/dist/informasi-gudang-BmoEy2RL.js +164 -0
- package/dist/informasi-gudang-DXfS46Nh.js +50 -0
- package/dist/purify.es-C-9oolON.js +546 -0
- package/dist/scripts/pdf.worker.min.js +29 -0
- package/dist/scripts/pdf.worker.min.mjs +29 -0
- package/dist/scripts/pdf.worker.mjs +57722 -0
- package/dist/scripts/pdf.worker.mjs.map +1 -0
- package/dist/style.css +1 -0
- package/dist/test-schema-JFghGc0_.js +8 -0
- package/dist/test-schema-uusFsJe4.js +438 -0
- package/dist/types-l0sNRNKZ.js +1 -0
- package/package.json +178 -0
- package/src/App.vue +18 -0
- package/src/__tests__/index.test.ts +9 -0
- package/src/api/api.ts +117 -0
- package/src/assets/app-selector.svg +3 -0
- package/src/assets/dasi.png +0 -0
- package/src/assets/foto_ss.svg +21 -0
- package/src/assets/icons/circle-blue.svg +4 -0
- package/src/assets/icons/circle-gray.svg +15 -0
- package/src/assets/icons/circle-green.svg +4 -0
- package/src/assets/icons/circle-orange.svg +4 -0
- package/src/assets/icons/circle-purple.svg +4 -0
- package/src/assets/icons/circle-red.svg +15 -0
- package/src/assets/icons/harbor.svg +12 -0
- package/src/assets/icons/ic-box-red.svg +8 -0
- package/src/assets/icons/ic-chevron-right.svg +1 -0
- package/src/assets/icons/ic-loading.svg +9 -0
- package/src/assets/icons/ic-reset.svg +16 -0
- package/src/assets/icons/ic-sailing.svg +5 -0
- package/src/assets/icons/icon-app-selector.svg +3 -0
- package/src/assets/icons/icon-browser-check.svg +4 -0
- package/src/assets/icons/icon-calendar.svg +3 -0
- package/src/assets/icons/icon-chart-bar.svg +3 -0
- package/src/assets/icons/icon-chart-doc.svg +16 -0
- package/src/assets/icons/icon-chart-line.svg +10 -0
- package/src/assets/icons/icon-chart-mix.svg +15 -0
- package/src/assets/icons/icon-chart-pie.svg +11 -0
- package/src/assets/icons/icon-continue.svg +12 -0
- package/src/assets/icons/icon-dashboard-2.svg +17 -0
- package/src/assets/icons/icon-dashboard.svg +3 -0
- package/src/assets/icons/icon-data-kelistrikan.svg +19 -0
- package/src/assets/icons/icon-data-sentral.svg +11 -0
- package/src/assets/icons/icon-database.svg +5 -0
- package/src/assets/icons/icon-desktop.svg +3 -0
- package/src/assets/icons/icon-download.svg +13 -0
- package/src/assets/icons/icon-energi-primer.svg +12 -0
- package/src/assets/icons/icon-faba-apk2.svg +11 -0
- package/src/assets/icons/icon-faba.svg +11 -0
- package/src/assets/icons/icon-factory.svg +14 -0
- package/src/assets/icons/icon-globe-doc.svg +19 -0
- package/src/assets/icons/icon-ikk.svg +10 -0
- package/src/assets/icons/icon-kbb.svg +13 -0
- package/src/assets/icons/icon-kos.svg +16 -0
- package/src/assets/icons/icon-kpi-bod.svg +15 -0
- package/src/assets/icons/icon-kss.svg +14 -0
- package/src/assets/icons/icon-map.svg +12 -0
- package/src/assets/icons/icon-monitoring-harian.svg +13 -0
- package/src/assets/icons/icon-notification.svg +4 -0
- package/src/assets/icons/icon-overview.svg +17 -0
- package/src/assets/icons/icon-pltu.svg +13 -0
- package/src/assets/icons/icon-sebaran-sentral.svg +12 -0
- package/src/assets/icons/icon-select-data-kelistrikan.svg +19 -0
- package/src/assets/icons/icon-select-data-sentral.svg +11 -0
- package/src/assets/icons/icon-select-energi-primer.svg +12 -0
- package/src/assets/icons/icon-select-faba-apk2.svg +11 -0
- package/src/assets/icons/icon-select-ikk.svg +10 -0
- package/src/assets/icons/icon-select-kbb.svg +13 -0
- package/src/assets/icons/icon-select-kos.svg +16 -0
- package/src/assets/icons/icon-select-kpi-bod.svg +15 -0
- package/src/assets/icons/icon-select-kss.svg +14 -0
- package/src/assets/icons/icon-select-monitoring-harian.svg +13 -0
- package/src/assets/icons/icon-select-overview.svg +17 -0
- package/src/assets/icons/icon-select-sebaran-sentral.svg +12 -0
- package/src/assets/icons/icon-sentral-white.svg +13 -0
- package/src/assets/icons/icon-shipping.svg +5 -0
- package/src/assets/icons/icon-sort.svg +5 -0
- package/src/assets/icons/icon-tree-box.svg +14 -0
- package/src/assets/icons/icon-warehouse.svg +12 -0
- package/src/assets/icons/pin-green.svg +3 -0
- package/src/assets/icons/pin-orange.svg +3 -0
- package/src/assets/icons/pin-purple.svg +3 -0
- package/src/assets/icons/ship.svg +3 -0
- package/src/assets/icons/shipment/icon-antri.svg +15 -0
- package/src/assets/icons/shipment/icon-bongkar.svg +4 -0
- package/src/assets/icons/shipment/icon-invoice.svg +6 -0
- package/src/assets/icons/shipment/icon-loading.svg +8 -0
- package/src/assets/icons/shipment/icon-pembayaran.svg +13 -0
- package/src/assets/icons/shipment/icon-pengiriman.svg +4 -0
- package/src/assets/icons/shipment/icon-sailing.svg +4 -0
- package/src/assets/icons/shipment/icon-shipment-completed.svg +6 -0
- package/src/assets/icons/shipment/icon-shipment-in-progress.svg +6 -0
- package/src/assets/icons/shipment/icon-shipment-over-sla.svg +6 -0
- package/src/assets/icons/shipment/icon-spt.svg +4 -0
- package/src/assets/icons/shipment/icon-total-shipment.svg +4 -0
- package/src/assets/icons/upload_doc_icon.svg +42 -0
- package/src/assets/icons/upload_icon_blue.svg +14 -0
- package/src/assets/login-bg-day-min.jpg +0 -0
- package/src/assets/login-bg-night-min.jpg +0 -0
- package/src/assets/login-bg.jpg +0 -0
- package/src/assets/login-day.png +0 -0
- package/src/assets/login-night.png +0 -0
- package/src/assets/lucide-circle-plus-blue.svg +1 -0
- package/src/assets/pdf-logo.svg +11 -0
- package/src/assets/pemasok-card-bg.svg +6 -0
- package/src/assets/success_animation.gif +0 -0
- package/src/assets/success_animation.mp4 +0 -0
- package/src/assets/success_animation.webm +0 -0
- package/src/components/button/BtnAddOutline.vue +14 -0
- package/src/components/button/BtnCircle.vue +10 -0
- package/src/components/button/BtnOutline.vue +15 -0
- package/src/components/button/BtnPrimary.vue +25 -0
- package/src/components/button/BtnSecondary.vue +26 -0
- package/src/components/detail/AccountDetailTimeline.vue +144 -0
- package/src/components/detail/ApprovalInfo.vue +288 -0
- package/src/components/detail/DCI2.vue +164 -0
- package/src/components/detail/DetailContentHeader.vue +83 -0
- package/src/components/detail/DetailContentItem.vue +186 -0
- package/src/components/detail/DetailContentItems.vue +388 -0
- package/src/components/detail/DetailContentLoading.vue +12 -0
- package/src/components/detail/DetailContentTablet.vue +10 -0
- package/src/components/detail/DetailSheet.vue +294 -0
- package/src/components/detail/DetailTimeline.vue +191 -0
- package/src/components/detail/DocApprovalDialog.vue +29 -0
- package/src/components/detail/DocViewerContent.vue +991 -0
- package/src/components/dialog/ConfirmDialog.vue +96 -0
- package/src/components/dialog/DialogBase.vue +53 -0
- package/src/components/dialog/DialogSelect.vue +212 -0
- package/src/components/dialog/ErrorDialog.vue +63 -0
- package/src/components/dialog/FormDialog.vue +141 -0
- package/src/components/dialog/FormInputerDialog.vue +91 -0
- package/src/components/dialog/InfoDialog.vue +74 -0
- package/src/components/dialog/SuccessDialog.vue +51 -0
- package/src/components/examples/TestSchemaExample.vue +288 -0
- package/src/components/forms/auth/LoginForm.vue +806 -0
- package/src/components/forms/auth/PwdScore.vue +68 -0
- package/src/components/helper/ApiTester.vue +153 -0
- package/src/components/helper/ChangePwd.vue +150 -0
- package/src/components/helper/CheckboxElement.vue +43 -0
- package/src/components/helper/ConfigSwitcher.vue +54 -0
- package/src/components/helper/Copyright.vue +10 -0
- package/src/components/helper/ErrorScreen.vue +40 -0
- package/src/components/helper/LucideIcon.vue +27 -0
- package/src/components/helper/PdfViewer.vue +103 -0
- package/src/components/helper/PinInputer.vue +205 -0
- package/src/components/helper/PrivacyPolicy.vue +122 -0
- package/src/components/layout/PageActivityHeader.vue +48 -0
- package/src/components/layout/PageHeader.vue +70 -0
- package/src/components/loadings/LoadingDialog.vue +29 -0
- package/src/components/loadings/LoadingDialogSpin.vue +25 -0
- package/src/components/loadings/LoadingIndicator.vue +38 -0
- package/src/components/loadings/LoadingScreen.vue +23 -0
- package/src/components/notif/Notif.vue +103 -0
- package/src/components/notif/NotifItem.vue +41 -0
- package/src/components/pages/Header.vue +431 -0
- package/src/components/pages/Leftbar.vue +417 -0
- package/src/components/pages/PageActivity.vue +108 -0
- package/src/components/pages/PageActivityContent.vue +597 -0
- package/src/components/pages/PageContentTable.vue +589 -0
- package/src/components/pages/PageTab.vue +84 -0
- package/src/components/selector/BaseSelector.vue +1136 -0
- package/src/components/selector/ConfigDataSelector.vue +136 -0
- package/src/components/settings/SettingsItem.vue +38 -0
- package/src/components/tab/TabView.vue +11 -0
- package/src/components/tab/TabViewItem.vue +18 -0
- package/src/components/tab/TabViewItemBar.vue +9 -0
- package/src/components/tables/CellHover.vue +65 -0
- package/src/components/tables/DashboardDataTable.vue +707 -0
- package/src/components/tables/DataStatusTag.vue +52 -0
- package/src/components/tables/DataTable.vue +156 -0
- package/src/components/tables/DataTableAccordion.vue +249 -0
- package/src/components/tables/DataTableActionRow.vue +64 -0
- package/src/components/tables/DataTableCell.vue +272 -0
- package/src/components/tables/DataTableHeader.vue +60 -0
- package/src/components/tables/DataTableRow.vue +213 -0
- package/src/components/tables/ExpandedTable.vue +259 -0
- package/src/components/tables/PageTable.vue +73 -0
- package/src/components/tables/Pagination.vue +98 -0
- package/src/components/tables/dropdown/BaseDropdownTable.vue +140 -0
- package/src/components/tables/dropdown/DropdownTableActivity.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableAsset.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableConfig.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableDataKonektor.vue +31 -0
- package/src/components/tables/dropdown/DropdownTableDataLabel.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableDataSchema.vue +31 -0
- package/src/components/tables/dropdown/DropdownTableFabaPemanfaat.vue +30 -0
- package/src/components/tables/dropdown/DropdownTableGroup.vue +36 -0
- package/src/components/tables/dropdown/DropdownTableHalaman.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableLevel.vue +66 -0
- package/src/components/tables/dropdown/DropdownTableOrganization.vue +47 -0
- package/src/components/tables/dropdown/DropdownTablePengelola.vue +28 -0
- package/src/components/tables/dropdown/DropdownTableQueryLayer.vue +29 -0
- package/src/components/tables/dropdown/DropdownTableSentral.vue +33 -0
- package/src/components/tables/dropdown/DropdownTableWarehouse.vue +30 -0
- package/src/components/tables/dropdown/TableDropdown.vue +52 -0
- package/src/components/ui/accordion/Accordion.vue +19 -0
- package/src/components/ui/accordion/AccordionContent.vue +24 -0
- package/src/components/ui/accordion/AccordionItem.vue +24 -0
- package/src/components/ui/accordion/AccordionTrigger.vue +42 -0
- package/src/components/ui/accordion/index.ts +4 -0
- package/src/components/ui/alert-dialog/AlertDialog.vue +14 -0
- package/src/components/ui/alert-dialog/AlertDialogAction.vue +20 -0
- package/src/components/ui/alert-dialog/AlertDialogCancel.vue +20 -0
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +42 -0
- package/src/components/ui/alert-dialog/AlertDialogDescription.vue +25 -0
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +21 -0
- package/src/components/ui/alert-dialog/AlertDialogHeader.vue +16 -0
- package/src/components/ui/alert-dialog/AlertDialogTitle.vue +22 -0
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
- package/src/components/ui/alert-dialog/index.ts +9 -0
- package/src/components/ui/avatar/Avatar.vue +24 -0
- package/src/components/ui/avatar/AvatarFallback.vue +11 -0
- package/src/components/ui/avatar/AvatarImage.vue +9 -0
- package/src/components/ui/avatar/UsersAvatar.vue +28 -0
- package/src/components/ui/avatar/index.ts +24 -0
- package/src/components/ui/button/Button.vue +27 -0
- package/src/components/ui/button/index.ts +34 -0
- package/src/components/ui/calendar/Calendar.vue +325 -0
- package/src/components/ui/calendar/index.ts +22 -0
- package/src/components/ui/checkbox/Checkbox.vue +33 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/command/Command.vue +30 -0
- package/src/components/ui/command/CommandDialog.vue +21 -0
- package/src/components/ui/command/CommandEmpty.vue +20 -0
- package/src/components/ui/command/CommandGroup.vue +29 -0
- package/src/components/ui/command/CommandInput.vue +33 -0
- package/src/components/ui/command/CommandItem.vue +26 -0
- package/src/components/ui/command/CommandList.vue +27 -0
- package/src/components/ui/command/CommandSeparator.vue +23 -0
- package/src/components/ui/command/CommandShortcut.vue +14 -0
- package/src/components/ui/command/index.ts +9 -0
- package/src/components/ui/context-menu/ContextMenu.vue +15 -0
- package/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +40 -0
- package/src/components/ui/context-menu/ContextMenuContent.vue +36 -0
- package/src/components/ui/context-menu/ContextMenuGroup.vue +11 -0
- package/src/components/ui/context-menu/ContextMenuItem.vue +34 -0
- package/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
- package/src/components/ui/context-menu/ContextMenuPortal.vue +11 -0
- package/src/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
- package/src/components/ui/context-menu/ContextMenuRadioItem.vue +40 -0
- package/src/components/ui/context-menu/ContextMenuSeparator.vue +20 -0
- package/src/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
- package/src/components/ui/context-menu/ContextMenuSub.vue +19 -0
- package/src/components/ui/context-menu/ContextMenuSubContent.vue +35 -0
- package/src/components/ui/context-menu/ContextMenuSubTrigger.vue +34 -0
- package/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
- package/src/components/ui/context-menu/index.ts +14 -0
- package/src/components/ui/datetime/DatetimeRangeComponent.vue +52 -0
- package/src/components/ui/dialog/Dialog.vue +14 -0
- package/src/components/ui/dialog/DialogClose.vue +11 -0
- package/src/components/ui/dialog/DialogContent.vue +53 -0
- package/src/components/ui/dialog/DialogDescription.vue +24 -0
- package/src/components/ui/dialog/DialogFooter.vue +19 -0
- package/src/components/ui/dialog/DialogHeader.vue +16 -0
- package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
- package/src/components/ui/dialog/DialogTitle.vue +29 -0
- package/src/components/ui/dialog/DialogTrigger.vue +11 -0
- package/src/components/ui/dialog/index.ts +9 -0
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +38 -0
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +41 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
- package/src/components/ui/dropdown-menu/index.ts +16 -0
- package/src/components/ui/form/FormControl.vue +16 -0
- package/src/components/ui/form/FormDescription.vue +20 -0
- package/src/components/ui/form/FormItem.vue +25 -0
- package/src/components/ui/form/FormLabel.vue +23 -0
- package/src/components/ui/form/FormMessage.vue +16 -0
- package/src/components/ui/form/index.ts +6 -0
- package/src/components/ui/form/useFormField.ts +30 -0
- package/src/components/ui/hover-card/HoverCard.vue +14 -0
- package/src/components/ui/hover-card/HoverCardContent.vue +41 -0
- package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
- package/src/components/ui/hover-card/index.ts +3 -0
- package/src/components/ui/input/Input.vue +24 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/label/Label.vue +27 -0
- package/src/components/ui/label/index.ts +1 -0
- package/src/components/ui/pagination/PaginationEllipsis.vue +22 -0
- package/src/components/ui/pagination/PaginationFirst.vue +29 -0
- package/src/components/ui/pagination/PaginationLast.vue +29 -0
- package/src/components/ui/pagination/PaginationNext.vue +29 -0
- package/src/components/ui/pagination/PaginationPrev.vue +29 -0
- package/src/components/ui/pagination/index.ts +10 -0
- package/src/components/ui/pin-input/PinInput.vue +23 -0
- package/src/components/ui/pin-input/PinInputGroup.vue +18 -0
- package/src/components/ui/pin-input/PinInputInput.vue +18 -0
- package/src/components/ui/pin-input/PinInputSeparator.vue +15 -0
- package/src/components/ui/pin-input/index.ts +4 -0
- package/src/components/ui/popover/Popover.vue +15 -0
- package/src/components/ui/popover/PopoverContent.vue +48 -0
- package/src/components/ui/popover/PopoverTrigger.vue +11 -0
- package/src/components/ui/popover/index.ts +4 -0
- package/src/components/ui/preview/PreviewPdf.vue +118 -0
- package/src/components/ui/progress/ProgressCircle.vue +27 -0
- package/src/components/ui/progress/SemiCircularProgressBar.vue +83 -0
- package/src/components/ui/progress/TotalCalories.vue +31 -0
- package/src/components/ui/radio-group/RadioGroup.vue +25 -0
- package/src/components/ui/radio-group/RadioGroupItem.vue +37 -0
- package/src/components/ui/radio-group/index.ts +2 -0
- package/src/components/ui/scroll-area/ScrollArea.vue +29 -0
- package/src/components/ui/scroll-area/ScrollBar.vue +30 -0
- package/src/components/ui/scroll-area/index.ts +2 -0
- package/src/components/ui/select/Select.vue +15 -0
- package/src/components/ui/select/SelectContent.vue +52 -0
- package/src/components/ui/select/SelectGroup.vue +19 -0
- package/src/components/ui/select/SelectInline.vue +84 -0
- package/src/components/ui/select/SelectItem.vue +44 -0
- package/src/components/ui/select/SelectItemText.vue +11 -0
- package/src/components/ui/select/SelectLabel.vue +13 -0
- package/src/components/ui/select/SelectScrollDownButton.vue +24 -0
- package/src/components/ui/select/SelectScrollUpButton.vue +24 -0
- package/src/components/ui/select/SelectSeparator.vue +17 -0
- package/src/components/ui/select/SelectTrigger.vue +31 -0
- package/src/components/ui/select/SelectTriggerCustom.vue +23 -0
- package/src/components/ui/select/SelectValue.vue +11 -0
- package/src/components/ui/select/index.ts +12 -0
- package/src/components/ui/separator/Separator.vue +20 -0
- package/src/components/ui/separator/index.ts +1 -0
- package/src/components/ui/sheet/Sheet.vue +14 -0
- package/src/components/ui/sheet/SheetClose.vue +11 -0
- package/src/components/ui/sheet/SheetContent.vue +48 -0
- package/src/components/ui/sheet/SheetDescription.vue +22 -0
- package/src/components/ui/sheet/SheetFooter.vue +19 -0
- package/src/components/ui/sheet/SheetHeader.vue +16 -0
- package/src/components/ui/sheet/SheetTitle.vue +22 -0
- package/src/components/ui/sheet/SheetTrigger.vue +11 -0
- package/src/components/ui/sheet/index.ts +31 -0
- package/src/components/ui/skeleton/Skeleton.vue +28 -0
- package/src/components/ui/skeleton/index.ts +1 -0
- package/src/components/ui/sonner/Sonner.vue +22 -0
- package/src/components/ui/sonner/index.ts +1 -0
- package/src/components/ui/star/StarRating.vue +19 -0
- package/src/components/ui/switch/Switch.vue +37 -0
- package/src/components/ui/switch/index.ts +1 -0
- package/src/components/ui/table/Table.vue +16 -0
- package/src/components/ui/table/TableBody.vue +14 -0
- package/src/components/ui/table/TableCaption.vue +14 -0
- package/src/components/ui/table/TableCell.vue +21 -0
- package/src/components/ui/table/TableEmpty.vue +37 -0
- package/src/components/ui/table/TableFooter.vue +14 -0
- package/src/components/ui/table/TableHead.vue +14 -0
- package/src/components/ui/table/TableHeader.vue +14 -0
- package/src/components/ui/table/TableRow.vue +14 -0
- package/src/components/ui/table/index.ts +8 -0
- package/src/components/ui/tabs/Tabs.vue +15 -0
- package/src/components/ui/tabs/TabsContent.vue +22 -0
- package/src/components/ui/tabs/TabsList.vue +25 -0
- package/src/components/ui/tabs/TabsTrigger.vue +27 -0
- package/src/components/ui/tabs/index.ts +4 -0
- package/src/components/ui/tags-input/TagsInput.vue +22 -0
- package/src/components/ui/tags-input/TagsInputInput.vue +19 -0
- package/src/components/ui/tags-input/TagsInputItem.vue +22 -0
- package/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
- package/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
- package/src/components/ui/tags-input/index.ts +5 -0
- package/src/components/ui/textarea/Textarea.vue +24 -0
- package/src/components/ui/textarea/index.ts +1 -0
- package/src/components/ui/tooltip/Tooltip.vue +14 -0
- package/src/components/ui/tooltip/TooltipContent.vue +31 -0
- package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
- package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
- package/src/components/ui/tooltip/index.ts +4 -0
- package/src/composables/useAppConfig.ts +332 -0
- package/src/composables/useDarkMode.ts +71 -0
- package/src/config/app.config.ts +318 -0
- package/src/config/examples/ecommerce.config.ts +132 -0
- package/src/config/examples/generic.config.ts +132 -0
- package/src/config/menu.config.ts +149 -0
- package/src/config/my-app.config.ts +134 -0
- package/src/config/test-config.ts +32 -0
- package/src/config/theme.config.ts +250 -0
- package/src/docs/index.ts +21 -0
- package/src/docs.scss +403 -0
- package/src/index.d.ts +5 -0
- package/src/index.ts +20 -0
- package/src/layouts/AuthLayout.vue +68 -0
- package/src/layouts/DefaultLayout.vue +119 -0
- package/src/layouts/DocsLayout.vue +681 -0
- package/src/layouts/FormGlobal.vue +50 -0
- package/src/layouts/GlobalDialog.vue +122 -0
- package/src/layouts/RakorConfirmDialog.vue +95 -0
- package/src/layouts/SettingsLayout.vue +115 -0
- package/src/lib/constants.ts +2 -0
- package/src/lib/detail.utils.ts +213 -0
- package/src/lib/form.utils.ts +1009 -0
- package/src/lib/page.flow.utils.ts +81 -0
- package/src/lib/page.utils.ts +865 -0
- package/src/lib/performance.utils.ts +302 -0
- package/src/lib/tablerow.utils.ts +51 -0
- package/src/lib/utils.ts +643 -0
- package/src/main.scss +717 -0
- package/src/main.ts +74 -0
- package/src/menu.ts +78 -0
- package/src/nestedlist_color.scss +161 -0
- package/src/router/index.ts +92 -0
- package/src/stores/auth.ts +117 -0
- package/src/stores/counter.ts +12 -0
- package/src/stores/dialog.ts +168 -0
- package/src/stores/form.ts +103 -0
- package/src/stores/tabs.ts +52 -0
- package/src/tw.scss +419 -0
- package/src/types/form.types.ts +348 -0
- package/src/types/types.ts +7 -0
- package/src/utils/config.utils.ts +149 -0
- package/src/views/NotFound.vue +30 -0
- package/src/views/PageActivity.vue +15 -0
- package/src/views/auth/LoginView.vue +7 -0
- package/src/views/auth/OauthCallback.vue +101 -0
- package/src/views/dashboard/index.vue +16 -0
- package/src/views/settings/AccountSettingsView.vue +70 -0
- package/src/views/settings/AuditLogsSettingsView.vue +116 -0
- package/src/views/settings/DeviceSettingsView.vue +70 -0
- package/src/views/settings/MainSettingsView.vue +12 -0
- package/src/views/settings/ProfileSettingsView.vue +104 -0
- package/src/vueform/config/informasi-gudang.ts +47 -0
- package/src/vueform/config/test-schema.ts +8 -0
- package/src/vueform/config/types.ts +768 -0
- package/src/vueform/customization/classes.js +46 -0
- package/src/vueform/customization/tailwind.classes.js +2117 -0
- package/src/vueform/elements/ConfigDataSelectorElement.vue +50 -0
- package/src/vueform/elements/DateSelectorElement.vue +323 -0
- package/src/vueform/elements/SelectorElement.vue +153 -0
- package/src/vueform/schemas/date-selector-test.ts +103 -0
- package/src/vueform/schemas/informasi-gudang.ts +160 -0
- package/src/vueform/schemas/test-schema.ts +483 -0
- package/src/vueform.config.js +77 -0
- 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 : "" }} • {{ 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 : "" }} • {{ 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>
|