@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,806 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onBeforeMount, onMounted, ref } from "vue";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import api from "@/api/api";
|
|
5
|
+
import { customAlphabet } from "nanoid";
|
|
6
|
+
import { PinInput, PinInputGroup, PinInputInput } from "@/components/ui/pin-input";
|
|
7
|
+
import BtnPrimary from "@/components/button/BtnPrimary.vue";
|
|
8
|
+
import BtnSecondary from "@/components/button/BtnSecondary.vue";
|
|
9
|
+
import { LucideX, Eye, EyeOff, LucideArrowLeft, LucideOctagonAlert } from "lucide-vue-next";
|
|
10
|
+
import BtnCircle from "@/components/button/BtnCircle.vue";
|
|
11
|
+
import PwdScore from "@/components/forms/auth/PwdScore.vue";
|
|
12
|
+
import { useRoute } from "vue-router";
|
|
13
|
+
import LoadingIndicator from "@/components/loadings/LoadingIndicator.vue";
|
|
14
|
+
import { useAuthStore } from "@/stores/auth";
|
|
15
|
+
import { useAppConfig } from "@/composables/useAppConfig";
|
|
16
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
|
|
17
|
+
import PrivacyPolicy from "@/components/helper/PrivacyPolicy.vue";
|
|
18
|
+
import { Slide } from "go-captcha-vue";
|
|
19
|
+
import "go-captcha-vue/dist/style.css";
|
|
20
|
+
|
|
21
|
+
const route = useRoute();
|
|
22
|
+
const showPassword = ref(false);
|
|
23
|
+
|
|
24
|
+
// Initialize stores and configuration
|
|
25
|
+
const authStore = useAuthStore();
|
|
26
|
+
const { tokenKey, userKey, organizationKey, apiEndpoints } = useAppConfig();
|
|
27
|
+
const loginError = ref(null);
|
|
28
|
+
const isLoading = ref(false);
|
|
29
|
+
const isOtpLoading = ref(false);
|
|
30
|
+
const loginEmail = ref("");
|
|
31
|
+
const loginPwd = ref("");
|
|
32
|
+
const grecaptchaSiteKey = ref("");
|
|
33
|
+
const state = ref("login");
|
|
34
|
+
const changePwdType = ref("default");
|
|
35
|
+
const ssoUrl = ref("");
|
|
36
|
+
const initLoading = ref(true);
|
|
37
|
+
const initError = ref(false);
|
|
38
|
+
const stopingAllSession = ref(false);
|
|
39
|
+
const allSessionStoped = ref(false);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Soft lockout password
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
const lockoutInterval = ref(0);
|
|
46
|
+
const loginAttemp = ref(0);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Change pwd
|
|
50
|
+
*
|
|
51
|
+
*/
|
|
52
|
+
const showPwd1 = ref(false);
|
|
53
|
+
const showPwd2 = ref(false);
|
|
54
|
+
const changePwdErr = ref<string | null>(null);
|
|
55
|
+
const isLoadingChangePwd = ref(false);
|
|
56
|
+
const pwd1Str = ref("");
|
|
57
|
+
const pwdScore = ref(0);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Forgot pwd
|
|
61
|
+
*
|
|
62
|
+
*/
|
|
63
|
+
const forgotPwdErr = ref<string | null>(null);
|
|
64
|
+
const forgotPwdEmail = ref("");
|
|
65
|
+
const forgotPwdPwd = ref("");
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* OTP
|
|
69
|
+
*
|
|
70
|
+
*/
|
|
71
|
+
const otp = ref<string[]>([]);
|
|
72
|
+
const resendInterval = ref(0);
|
|
73
|
+
const resendTried = ref(0);
|
|
74
|
+
const sendingOtpEmail = ref(false);
|
|
75
|
+
const otpEmailSent = ref(false);
|
|
76
|
+
const otpCompleted = () => {
|
|
77
|
+
sendOtp();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function sendOtp() {
|
|
81
|
+
isOtpLoading.value = true;
|
|
82
|
+
let uri = apiEndpoints.value.auth.login + "/otp";
|
|
83
|
+
let email = loginEmail.value;
|
|
84
|
+
if (state.value === "forgot_pwd_otp") {
|
|
85
|
+
uri = apiEndpoints.value.auth.forgotPassword + "/otp";
|
|
86
|
+
email = forgotPwdEmail.value;
|
|
87
|
+
}
|
|
88
|
+
api
|
|
89
|
+
.post(uri, {
|
|
90
|
+
email,
|
|
91
|
+
code: otp.value.join("")
|
|
92
|
+
})
|
|
93
|
+
.then(r => {
|
|
94
|
+
if (state.value === "forgot_pwd_otp") {
|
|
95
|
+
state.value = "change_pwd";
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Login successfull, redirect to home
|
|
100
|
+
if (r.data.auth_token) localStorage.setItem(tokenKey.value, r.data.auth_token);
|
|
101
|
+
localStorage.setItem(userKey.value, r.data.user.name);
|
|
102
|
+
localStorage.setItem("app.user.default_app", r.data.user.defaultApp);
|
|
103
|
+
|
|
104
|
+
if (r.data.user.organization) localStorage.setItem(organizationKey.value, r.data.user.organization.name);
|
|
105
|
+
if (r.data.user.organization && r.data.user.organization.accessLevel) {
|
|
106
|
+
localStorage.setItem("app.user.organization.level", r.data.user.organization.accessLevel.code);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Initialize WebSocket connection after successful login
|
|
110
|
+
// try {
|
|
111
|
+
// websocketStore.connect();
|
|
112
|
+
// } catch (error) {
|
|
113
|
+
// console.warn("Failed to initialize WebSocket connection:", error);
|
|
114
|
+
// }
|
|
115
|
+
|
|
116
|
+
const nextUri = r.data.user.defaultApp === "app1" ? "/dashboard/profile-sentral" : "/apk2/overview";
|
|
117
|
+
window.location.href =
|
|
118
|
+
route.query.next && String(route.query.next) !== "/" && String(route.query.next).substring(0, 1) === "/" && String(route.query.next).substring(0, 2) !== "//"
|
|
119
|
+
? String(route.query.next)
|
|
120
|
+
: nextUri;
|
|
121
|
+
})
|
|
122
|
+
.catch(err => {
|
|
123
|
+
if (err.response && err.response.status === 406) {
|
|
124
|
+
changePwdType.value = err.response.data.type;
|
|
125
|
+
state.value = "change_pwd_default";
|
|
126
|
+
} else {
|
|
127
|
+
loginError.value = err.message;
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
.finally(() => {
|
|
131
|
+
isOtpLoading.value = false;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function loginSso() {
|
|
136
|
+
/**
|
|
137
|
+
* Save next routes
|
|
138
|
+
*
|
|
139
|
+
*/
|
|
140
|
+
const afterLogin = route.query.next && String(route.query.next) !== "/" ? String(route.query.next) : "/";
|
|
141
|
+
sessionStorage.setItem("app.next", afterLogin);
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Redirect to oauth login
|
|
145
|
+
*
|
|
146
|
+
*/
|
|
147
|
+
window.location.href = ssoUrl.value;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function doLogin(e: any) {
|
|
151
|
+
// openCaptcha();
|
|
152
|
+
// privacyPolicyOpen.value = true;
|
|
153
|
+
// return;
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
isLoading.value = true;
|
|
157
|
+
loginError.value = null;
|
|
158
|
+
sendingOtpEmail.value = true;
|
|
159
|
+
otpEmailSent.value = false;
|
|
160
|
+
captchaX.value = e.x;
|
|
161
|
+
captchaY.value = e.y;
|
|
162
|
+
|
|
163
|
+
api
|
|
164
|
+
.post(apiEndpoints.value.auth.login, {
|
|
165
|
+
email: loginEmail.value,
|
|
166
|
+
password: loginPwd.value,
|
|
167
|
+
captchaKey: captchaData.value.captKey,
|
|
168
|
+
captchaX: e.x,
|
|
169
|
+
captchaY: e.y
|
|
170
|
+
})
|
|
171
|
+
.then(r => {
|
|
172
|
+
/**
|
|
173
|
+
* User requried to verify email
|
|
174
|
+
*
|
|
175
|
+
*/
|
|
176
|
+
if (!r.data.user) {
|
|
177
|
+
otp.value = [];
|
|
178
|
+
state.value = "login_otp";
|
|
179
|
+
resendTried.value += 1;
|
|
180
|
+
resendInterval.value = 15 * resendTried.value + 1;
|
|
181
|
+
otpEmailSent.value = true;
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
otpEmailSent.value = false;
|
|
184
|
+
updateInterval();
|
|
185
|
+
}, 2400);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Login successfull, redirect to home
|
|
191
|
+
*
|
|
192
|
+
*/
|
|
193
|
+
if (r.data.auth_token) localStorage.setItem(tokenKey.value, r.data.auth_token);
|
|
194
|
+
localStorage.setItem(userKey.value, r.data.user.name);
|
|
195
|
+
localStorage.setItem("app.user.default_app", r.data.user.defaultApp);
|
|
196
|
+
|
|
197
|
+
if (r.data.user.organization) localStorage.setItem(organizationKey.value, r.data.user.organization.name);
|
|
198
|
+
if (r.data.user.organization && r.data.user.organization.accessLevel) {
|
|
199
|
+
localStorage.setItem("app.user.organization.level", r.data.user.organization.accessLevel.code);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const nextUri = r.data.user.defaultApp === "app1" ? "/" : "/";
|
|
203
|
+
window.location.href =
|
|
204
|
+
route.query.next && String(route.query.next) !== "/" && String(route.query.next).substring(0, 1) === "/" && String(route.query.next).substring(0, 2) !== "//"
|
|
205
|
+
? String(route.query.next)
|
|
206
|
+
: nextUri;
|
|
207
|
+
})
|
|
208
|
+
.catch(err => {
|
|
209
|
+
if (err.response && err.response.status === 406) {
|
|
210
|
+
changePwdType.value = err.response.data.type;
|
|
211
|
+
state.value = "change_pwd_default";
|
|
212
|
+
} else {
|
|
213
|
+
loginError.value = err.message;
|
|
214
|
+
loginAttemp.value += 1;
|
|
215
|
+
if (loginAttemp.value >= 3) {
|
|
216
|
+
lockoutInterval.value = 5 * loginAttemp.value + 1;
|
|
217
|
+
updateLockoutInterval();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
.finally(() => {
|
|
222
|
+
isLoading.value = false;
|
|
223
|
+
sendingOtpEmail.value = false;
|
|
224
|
+
});
|
|
225
|
+
} catch (err: any) {
|
|
226
|
+
console.error(err);
|
|
227
|
+
isLoading.value = false;
|
|
228
|
+
loginError.value = err.message;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function login(_: FormData, form$: any) {
|
|
233
|
+
loginEmail.value = form$.data.email.toLowerCase();
|
|
234
|
+
loginPwd.value = form$.data.password;
|
|
235
|
+
openCaptcha();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function resendOtp() {
|
|
239
|
+
if (state.value === "forgot_pwd_otp") doSendForgotPwdEmail();
|
|
240
|
+
else login(new FormData(), { data: { email: loginEmail.value, password: loginPwd.value } });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function updateInterval() {
|
|
244
|
+
if (!resendInterval.value) return;
|
|
245
|
+
resendInterval.value -= 1;
|
|
246
|
+
setTimeout(() => {
|
|
247
|
+
updateInterval();
|
|
248
|
+
}, 1000);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function updateLockoutInterval() {
|
|
252
|
+
if (!lockoutInterval.value) return;
|
|
253
|
+
lockoutInterval.value -= 1;
|
|
254
|
+
setTimeout(() => {
|
|
255
|
+
updateLockoutInterval();
|
|
256
|
+
}, 1000);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function forgotPwd(formData: FormData, form$: any) {
|
|
260
|
+
forgotPwdEmail.value = form$.data.email.toLowerCase();
|
|
261
|
+
doSendForgotPwdEmail();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function doSendForgotPwdEmail() {
|
|
265
|
+
sendingOtpEmail.value = true;
|
|
266
|
+
otpEmailSent.value = false;
|
|
267
|
+
api
|
|
268
|
+
.post(apiEndpoints.value.auth.forgotPassword, {
|
|
269
|
+
email: forgotPwdEmail.value
|
|
270
|
+
})
|
|
271
|
+
.then(r => {
|
|
272
|
+
state.value = "forgot_pwd_otp";
|
|
273
|
+
resendTried.value += 1;
|
|
274
|
+
resendInterval.value = 15 * resendTried.value + 1;
|
|
275
|
+
otpEmailSent.value = true;
|
|
276
|
+
setTimeout(() => {
|
|
277
|
+
otpEmailSent.value = false;
|
|
278
|
+
updateInterval();
|
|
279
|
+
}, 2400);
|
|
280
|
+
})
|
|
281
|
+
.catch(err => {
|
|
282
|
+
forgotPwdErr.value = err.message;
|
|
283
|
+
})
|
|
284
|
+
.finally(() => {
|
|
285
|
+
sendingOtpEmail.value = false;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function stopAllSession() {
|
|
290
|
+
if (allSessionStoped.value) return;
|
|
291
|
+
stopingAllSession.value = true;
|
|
292
|
+
api
|
|
293
|
+
.post(apiEndpoints.value.auth.changePassword + "/stop-all-session", {
|
|
294
|
+
email: forgotPwdEmail.value,
|
|
295
|
+
password: forgotPwdPwd.value
|
|
296
|
+
})
|
|
297
|
+
.then(r => {
|
|
298
|
+
allSessionStoped.value = true;
|
|
299
|
+
})
|
|
300
|
+
.finally(() => {
|
|
301
|
+
stopingAllSession.value = false;
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function changePwd(formData: FormData, form$: any) {
|
|
306
|
+
if (pwdScore.value < 4) {
|
|
307
|
+
changePwdErr.value = "Mohon gunakan password yang lebih sulit untuk ditebak";
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (form$.data.password1 !== form$.data.password2) {
|
|
311
|
+
changePwdErr.value = "Kata sandi dan ulangi kata sandi tidak sama";
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
isLoadingChangePwd.value = true;
|
|
315
|
+
let uri = apiEndpoints.value.auth.changePassword + "/default";
|
|
316
|
+
let email = loginEmail.value;
|
|
317
|
+
if (state.value === "change_pwd") {
|
|
318
|
+
uri = apiEndpoints.value.auth.changePassword + "/otp";
|
|
319
|
+
email = forgotPwdEmail.value;
|
|
320
|
+
}
|
|
321
|
+
forgotPwdPwd.value = form$.data.password1;
|
|
322
|
+
api
|
|
323
|
+
.post(uri, {
|
|
324
|
+
email,
|
|
325
|
+
code: otp.value.join(""),
|
|
326
|
+
password: forgotPwdPwd.value
|
|
327
|
+
})
|
|
328
|
+
.then(r => {
|
|
329
|
+
if (state.value === "change_pwd") {
|
|
330
|
+
state.value = "change_pwd_success";
|
|
331
|
+
allSessionStoped.value = false;
|
|
332
|
+
stopingAllSession.value = false;
|
|
333
|
+
loginError.value = null;
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Login successfull, redirect to home
|
|
338
|
+
if (r.data.auth_token) localStorage.setItem(tokenKey.value, r.data.auth_token);
|
|
339
|
+
localStorage.setItem(userKey.value, r.data.user.name);
|
|
340
|
+
localStorage.setItem("app.user.default_app", r.data.user.defaultApp);
|
|
341
|
+
|
|
342
|
+
if (r.data.user.organization) localStorage.setItem(organizationKey.value, r.data.user.organization.name);
|
|
343
|
+
if (r.data.user.organization && r.data.user.organization.accessLevel) {
|
|
344
|
+
localStorage.setItem("app.user.organization.level", r.data.user.organization.accessLevel.code);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Initialize WebSocket connection after successful login
|
|
348
|
+
// try {
|
|
349
|
+
// websocketStore.connect();
|
|
350
|
+
// } catch (error) {
|
|
351
|
+
// console.warn("Failed to initialize WebSocket connection:", error);
|
|
352
|
+
// }
|
|
353
|
+
|
|
354
|
+
const nextUri = r.data.user.defaultApp === "app1" ? "/" : "/";
|
|
355
|
+
window.location.href =
|
|
356
|
+
route.query.next && String(route.query.next) !== "/" && String(route.query.next).substring(0, 1) === "/" && String(route.query.next).substring(0, 2) !== "//"
|
|
357
|
+
? String(route.query.next)
|
|
358
|
+
: nextUri;
|
|
359
|
+
})
|
|
360
|
+
.catch(err => {
|
|
361
|
+
changePwdErr.value = err.message;
|
|
362
|
+
})
|
|
363
|
+
.finally(() => {
|
|
364
|
+
isLoadingChangePwd.value = false;
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function pwd1Inputed(e: any) {
|
|
369
|
+
changePwdErr.value = null;
|
|
370
|
+
pwd1Str.value = e.target.value;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function openForgotPwd() {
|
|
374
|
+
state.value = "forgot_pwd";
|
|
375
|
+
otp.value = [];
|
|
376
|
+
loginError.value = null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Captcha
|
|
381
|
+
*
|
|
382
|
+
*/
|
|
383
|
+
const captchaOpen = ref(false);
|
|
384
|
+
const captchaX = ref(0);
|
|
385
|
+
const captchaY = ref(0);
|
|
386
|
+
const captchaData = ref({
|
|
387
|
+
image: "",
|
|
388
|
+
thumb: "",
|
|
389
|
+
captKey: "",
|
|
390
|
+
thumbX: 0,
|
|
391
|
+
thumbY: 0,
|
|
392
|
+
thumbWidth: 0,
|
|
393
|
+
thumbHeight: 0
|
|
394
|
+
});
|
|
395
|
+
const captchaEvents = {
|
|
396
|
+
close: () => {
|
|
397
|
+
captchaOpen.value = false;
|
|
398
|
+
},
|
|
399
|
+
refresh: () => {
|
|
400
|
+
openCaptcha();
|
|
401
|
+
},
|
|
402
|
+
confirm: (e: any) => {
|
|
403
|
+
captchaOpen.value = false;
|
|
404
|
+
doLogin(e);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
function openCaptcha() {
|
|
409
|
+
captchaOpen.value = true;
|
|
410
|
+
api.get(apiEndpoints.value.auth.captcha).then(r => {
|
|
411
|
+
captchaData.value = {
|
|
412
|
+
image: r.data.data.image_base64 || "",
|
|
413
|
+
thumb: r.data.data.tile_base64 || "",
|
|
414
|
+
captKey: r.data.data.captcha_key || "",
|
|
415
|
+
thumbX: r.data.data.tile_x || 0,
|
|
416
|
+
thumbY: r.data.data.tile_y || 0,
|
|
417
|
+
thumbWidth: r.data.data.tile_width || 0,
|
|
418
|
+
thumbHeight: r.data.data.tile_height || 0
|
|
419
|
+
};
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Privacy policy
|
|
425
|
+
*
|
|
426
|
+
*/
|
|
427
|
+
const privacyPolicyOpen = ref(false);
|
|
428
|
+
const privacyToken = ref<string | null>(null);
|
|
429
|
+
const privacyPolicyCanAgree = ref(false);
|
|
430
|
+
|
|
431
|
+
function privacyPolicyScrolled(e: any) {
|
|
432
|
+
// Hitung jika sudah mencapai bagian bawah elemen
|
|
433
|
+
const isAtBottom = e.target.scrollHeight - e.target.scrollTop <= e.target.clientHeight + 200;
|
|
434
|
+
if (isAtBottom) privacyPolicyCanAgree.value = true;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function agreePrivacy() {
|
|
438
|
+
initLoading.value = true;
|
|
439
|
+
// api.post('/auth/login/privacy/accept', {
|
|
440
|
+
// email: loginEmail.value,
|
|
441
|
+
// password: loginPwd.value,
|
|
442
|
+
// token: privacyToken.value,
|
|
443
|
+
// }).then(r => {
|
|
444
|
+
// if (state.value === 'forgot_pwd_otp') {
|
|
445
|
+
// otpToken.value = r.data.token
|
|
446
|
+
// state.value = 'change_pwd'
|
|
447
|
+
// return
|
|
448
|
+
// }
|
|
449
|
+
|
|
450
|
+
// /**
|
|
451
|
+
// * Login successful, set auth data and redirect to /pemilik
|
|
452
|
+
// *
|
|
453
|
+
// */
|
|
454
|
+
// localStorage.setItem('biomassa.user.name', r.data.nama)
|
|
455
|
+
// localStorage.setItem('biomassa.user.type', r.data.tipe_user)
|
|
456
|
+
|
|
457
|
+
// let path = '/';
|
|
458
|
+
// switch (r.data.tipe_user) {
|
|
459
|
+
// case 'SUPER_ADMIN':
|
|
460
|
+
// case 'ADMIN':
|
|
461
|
+
// path = '/master-user';
|
|
462
|
+
// break;
|
|
463
|
+
// case 'PEMETAAN_LAHAN':
|
|
464
|
+
// case 'MONITORING':
|
|
465
|
+
// path = '/peta-sebaran'; break;
|
|
466
|
+
// default: break;
|
|
467
|
+
// };
|
|
468
|
+
// router.push({ path });
|
|
469
|
+
// console.log('Login successful')
|
|
470
|
+
// }).catch(err => {
|
|
471
|
+
// handleLoginError(err);
|
|
472
|
+
// }).finally(() => {
|
|
473
|
+
// initLoading.value = false
|
|
474
|
+
// })
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function disagreePrivacy() {
|
|
478
|
+
initLoading.value = true;
|
|
479
|
+
api
|
|
480
|
+
.post("/auth/login/privacy/not-accept", {
|
|
481
|
+
email: loginEmail.value,
|
|
482
|
+
password: loginPwd.value,
|
|
483
|
+
token: privacyToken.value
|
|
484
|
+
})
|
|
485
|
+
.finally(() => {
|
|
486
|
+
privacyToken.value = null;
|
|
487
|
+
initLoading.value = false;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function initLogin() {
|
|
492
|
+
initLoading.value = true;
|
|
493
|
+
initError.value = false;
|
|
494
|
+
api
|
|
495
|
+
.get(apiEndpoints.value.auth.init)
|
|
496
|
+
.then(r => {
|
|
497
|
+
/**
|
|
498
|
+
* Used to prevent CSRF attacks by
|
|
499
|
+
* ensuring the response matches the initial request
|
|
500
|
+
*
|
|
501
|
+
*/
|
|
502
|
+
const { state } = r.data;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Save one-time only state
|
|
506
|
+
*
|
|
507
|
+
*/
|
|
508
|
+
sessionStorage.setItem("oauth_state", state);
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Save sso authorize url
|
|
512
|
+
*
|
|
513
|
+
*/
|
|
514
|
+
ssoUrl.value = r.data.ssoUrl;
|
|
515
|
+
})
|
|
516
|
+
.catch(err => {
|
|
517
|
+
initError.value = true;
|
|
518
|
+
})
|
|
519
|
+
.finally(() => {
|
|
520
|
+
initLoading.value = false;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
onMounted(() => {
|
|
525
|
+
initLogin();
|
|
526
|
+
});
|
|
527
|
+
</script>
|
|
528
|
+
|
|
529
|
+
<template>
|
|
530
|
+
<section v-if="initLoading" class="flex h-[440px] items-center justify-center">
|
|
531
|
+
<LoadingIndicator class="scale-90" />
|
|
532
|
+
</section>
|
|
533
|
+
<section v-else-if="initError" class="flex h-[440px] items-center justify-center">
|
|
534
|
+
<div class="text-center text-red-500">
|
|
535
|
+
<LucideOctagonAlert :size="40" :stroke-width="1.5" class="mx-auto mb-3" />
|
|
536
|
+
<h4 class="text-lg font-medium">Login Initilization Failed</h4>
|
|
537
|
+
<p class="mb-4 text-sm">Can not connect to Server, please check again your internet connection</p>
|
|
538
|
+
<BtnPrimary class="h-9 rounded-full py-0" v-on:click="initLogin">Coba Lagi</BtnPrimary>
|
|
539
|
+
</div>
|
|
540
|
+
</section>
|
|
541
|
+
<section v-else-if="['change_pwd_default', 'change_pwd'].includes(state)">
|
|
542
|
+
<div class="mb-4 flex flex-col space-y-2 text-left">
|
|
543
|
+
<h1 class="mb-[2px] text-2xl font-semibold leading-none">Ganti Kata Sandi</h1>
|
|
544
|
+
<p class="!mt-1 mb-4 text-[15px] leading-snug text-muted-foreground">
|
|
545
|
+
<template v-if="state === 'change_pwd_default'">
|
|
546
|
+
<template v-if="changePwdType === 'expired'"> Kata sandi Anda sudah kadaluarsa, anda harus mengganti kata sandi dengan kata sandi baru untuk masuk ke aplikasi. </template>
|
|
547
|
+
<template v-else>Kata sandi awal hanya dapat digunakan sekali. Silahkan masukan kata sandi baru.</template>
|
|
548
|
+
</template>
|
|
549
|
+
<template v-else>Silahkan masukan kata sandi baru.</template>
|
|
550
|
+
</p>
|
|
551
|
+
</div>
|
|
552
|
+
<div :class="cn('grid gap-6', $attrs.class ?? '')">
|
|
553
|
+
<div class="relative -mb-1 rounded-sm border-l-4 border-red-400 bg-red-50 px-4 py-2 pr-16 text-[15px] leading-tight text-red-500" v-if="changePwdErr">
|
|
554
|
+
<span>{{ changePwdErr }}</span>
|
|
555
|
+
<BtnCircle class="absolute right-2 top-1/2 h-6 w-6 -translate-y-1/2 bg-gray-200 opacity-70 transition hover:bg-slate-300 hover:opacity-100" v-on:click="changePwdErr = null">
|
|
556
|
+
<LucideX :size="16"></LucideX>
|
|
557
|
+
</BtnCircle>
|
|
558
|
+
</div>
|
|
559
|
+
<Vueform :endpoint="changePwd">
|
|
560
|
+
<TextElement
|
|
561
|
+
name="password1"
|
|
562
|
+
:input-type="showPwd1 ? 'text' : 'password'"
|
|
563
|
+
label="Kata Sandi Baru"
|
|
564
|
+
placeholder="Masukkan kata sandi..."
|
|
565
|
+
:floating="false"
|
|
566
|
+
:rules="['required']"
|
|
567
|
+
v-on:input="pwd1Inputed"
|
|
568
|
+
onpaste="return false;">
|
|
569
|
+
<template #addon-after>
|
|
570
|
+
<EyeOff :size="22" v-if="showPwd1" class="cursor-pointer text-slate-400" @click="showPwd1 = false" />
|
|
571
|
+
<Eye :size="22" v-else class="cursor-pointer text-slate-400" @click="showPwd1 = true" />
|
|
572
|
+
</template>
|
|
573
|
+
</TextElement>
|
|
574
|
+
<div class="col-span-12 -mt-2.5 px-1">
|
|
575
|
+
<PwdScore v-model="pwdScore" :password="pwd1Str" />
|
|
576
|
+
</div>
|
|
577
|
+
<TextElement
|
|
578
|
+
name="password2"
|
|
579
|
+
:input-type="showPwd2 ? 'text' : 'password'"
|
|
580
|
+
label="Ulangi Kata Sandi"
|
|
581
|
+
placeholder="Masukkan kata sandi..."
|
|
582
|
+
:floating="false"
|
|
583
|
+
:rules="['required']"
|
|
584
|
+
v-on:input="changePwdErr = null"
|
|
585
|
+
onpaste="return false;">
|
|
586
|
+
<template #addon-after>
|
|
587
|
+
<EyeOff :size="22" v-if="showPwd2" class="cursor-pointer text-slate-400" @click="showPwd2 = false" />
|
|
588
|
+
<Eye :size="22" v-else class="cursor-pointer text-slate-400" @click="showPwd2 = true" />
|
|
589
|
+
</template>
|
|
590
|
+
</TextElement>
|
|
591
|
+
<div class="relative col-span-12 mt-1 h-12 cursor-default overflow-hidden rounded-md !border-gray-300 !bg-gray-300 px-6 !text-gray-300 transition" v-if="isLoadingChangePwd">
|
|
592
|
+
<div class="bottom-0 left-0 right-0 top-0 bg-gray-300">
|
|
593
|
+
<svg class="absolute bottom-0 left-0 right-0 top-0 m-auto h-7 w-7 animate-spin text-black" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
594
|
+
<circle class="opacity-15" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
|
|
595
|
+
<path class="opacity-15" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
|
596
|
+
</svg>
|
|
597
|
+
</div>
|
|
598
|
+
</div>
|
|
599
|
+
<ButtonElement size="lg" name="submit" button-class="mt-1 font-medium h-12 text-md" button-label="Tetapkan Kata Sandi" :submits="true" :full="true" v-else />
|
|
600
|
+
</Vueform>
|
|
601
|
+
</div>
|
|
602
|
+
</section>
|
|
603
|
+
<section v-else-if="['forgot_pwd'].includes(state)">
|
|
604
|
+
<div class="mb-4 flex flex-col space-y-2 text-left">
|
|
605
|
+
<h1 class="mb-[2px] text-2xl font-semibold leading-none">Lupa Kata Sandi</h1>
|
|
606
|
+
<p class="!mt-1 mb-4 text-[15px] leading-snug text-muted-foreground">Masukan alamat email Anda yang terdaftar pada aplikasi.</p>
|
|
607
|
+
</div>
|
|
608
|
+
<button class="-ml-[3px] mb-5 flex items-center px-0 py-1 text-[15px]" v-on:click="state = 'login'">
|
|
609
|
+
<LucideArrowLeft class="mr-2" :size="22" />
|
|
610
|
+
Kembali ke Login
|
|
611
|
+
</button>
|
|
612
|
+
<div :class="cn('grid gap-6', $attrs.class ?? '')">
|
|
613
|
+
<div class="relative -mb-1 rounded-sm border-l-4 border-red-400 bg-red-50 px-4 py-2 pr-16 text-[15px] leading-tight text-red-500" v-if="forgotPwdErr">
|
|
614
|
+
<span>{{ forgotPwdErr }}</span>
|
|
615
|
+
<BtnCircle class="absolute right-2 top-1/2 h-6 w-6 -translate-y-1/2 bg-gray-200 opacity-70 transition hover:bg-slate-300 hover:opacity-100" v-on:click="forgotPwdErr = null">
|
|
616
|
+
<LucideX :size="16"></LucideX>
|
|
617
|
+
</BtnCircle>
|
|
618
|
+
</div>
|
|
619
|
+
<Vueform :endpoint="forgotPwd">
|
|
620
|
+
<TextElement name="email" input-type="email" :rules="['required']" label="Email" placeholder="Masukkan email..." :floating="false" v-on:input="forgotPwdErr = null" />
|
|
621
|
+
<div class="relative col-span-12 mt-1 h-12 cursor-default overflow-hidden rounded-md !border-gray-300 !bg-gray-300 px-6 !text-gray-300 transition" v-if="sendingOtpEmail">
|
|
622
|
+
<div class="bottom-0 left-0 right-0 top-0 bg-gray-300">
|
|
623
|
+
<svg class="absolute bottom-0 left-0 right-0 top-0 m-auto h-7 w-7 animate-spin text-black" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
624
|
+
<circle class="opacity-15" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
|
|
625
|
+
<path class="opacity-15" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
|
626
|
+
</svg>
|
|
627
|
+
</div>
|
|
628
|
+
</div>
|
|
629
|
+
<ButtonElement size="lg" name="submit" button-class="mt-1 font-medium h-12 text-md" button-label="Kirimkan Email" :submits="true" :full="true" v-else />
|
|
630
|
+
</Vueform>
|
|
631
|
+
</div>
|
|
632
|
+
</section>
|
|
633
|
+
<section v-else-if="['change_pwd_success'].includes(state)">
|
|
634
|
+
<div class="mb-4 flex flex-col space-y-2 text-left">
|
|
635
|
+
<h1 class="mb-2.5 text-xl font-semibold leading-none">Kata Sandi Sukses Dirubah</h1>
|
|
636
|
+
<div class="!mt-1 mb-4 text-[15px] text-muted-foreground">
|
|
637
|
+
<p>Kata sandi berhasil di rubah, sekarang Anda dapat masuk menggunakan kata sandi baru Anda.</p>
|
|
638
|
+
<br />
|
|
639
|
+
<p>
|
|
640
|
+
Apakah Anda ingin menghentikan semua sesi aktif?<br />
|
|
641
|
+
Perangkat yang sedang aktif akan diminta untuk masuk kembali dengan password baru Anda.
|
|
642
|
+
</p>
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
<BtnPrimary class="mb-5 w-full text-[16px]" :loading="stopingAllSession" :disabled="allSessionStoped" v-on:click="stopAllSession">
|
|
646
|
+
<template v-if="allSessionStoped">Semua Sesi Dihentikan</template>
|
|
647
|
+
<template v-else>Hentikan Semua Sesi</template>
|
|
648
|
+
</BtnPrimary>
|
|
649
|
+
<button class="-ml-[3px] mb-5 flex items-center px-0 py-1 text-[15px]" v-on:click="state = 'login'">
|
|
650
|
+
<LucideArrowLeft class="mr-2" :size="22" />
|
|
651
|
+
Kembali ke Login
|
|
652
|
+
</button>
|
|
653
|
+
</section>
|
|
654
|
+
<section v-else-if="['login_otp', 'forgot_pwd_otp'].includes(state)">
|
|
655
|
+
<div class="mb-3 flex flex-col space-y-2 text-left">
|
|
656
|
+
<h1 class="mb-[2px] text-2xl font-semibold leading-none">Verifikasi</h1>
|
|
657
|
+
<p class="!mt-1 mb-4 text-[15px] text-muted-foreground">
|
|
658
|
+
Masukan 8 digit kode verifikasi yang dikirimkan ke email Anda
|
|
659
|
+
<b>
|
|
660
|
+
<template v-if="state === 'login_otp'"> {{ loginEmail.split("@")[0].substring(0, 2) }}***@{{ loginEmail.split("@")[1] }} </template>
|
|
661
|
+
<template v-if="state === 'forgot_pwd_otp'"> {{ forgotPwdEmail.split("@")[0].substring(0, 2) }}***@{{ forgotPwdEmail.split("@")[1] }} </template> </b
|
|
662
|
+
>.
|
|
663
|
+
</p>
|
|
664
|
+
</div>
|
|
665
|
+
<div :class="cn('grid gap-6', $attrs.class ?? '')">
|
|
666
|
+
<div class="relative -mb-1 rounded-sm border-l-4 border-red-400 bg-red-50 px-4 py-2 text-[15px] text-red-500" v-if="loginError">
|
|
667
|
+
<span>{{ loginError }}</span>
|
|
668
|
+
<BtnCircle class="absolute right-2 top-1/2 h-6 w-6 -translate-y-1/2 bg-gray-200 opacity-70 transition hover:bg-slate-300 hover:opacity-100" v-on:click="loginError = null">
|
|
669
|
+
<LucideX :size="16"></LucideX>
|
|
670
|
+
</BtnCircle>
|
|
671
|
+
</div>
|
|
672
|
+
<PinInput id="otp-input" v-model="otp" placeholder="○" @complete="otpCompleted" :otp="true">
|
|
673
|
+
<PinInputGroup class="gap-1.5">
|
|
674
|
+
<template v-for="(id, index) in 8" :key="id">
|
|
675
|
+
<PinInputInput class="w-full rounded-md border py-3 text-xl" :index="index" />
|
|
676
|
+
</template>
|
|
677
|
+
</PinInputGroup>
|
|
678
|
+
</PinInput>
|
|
679
|
+
<div class="-mt-4 pl-2">
|
|
680
|
+
<div class="py-1 text-sm text-gray-400" v-if="sendingOtpEmail">Mengirimkan email...</div>
|
|
681
|
+
<div class="py-1 text-sm text-gray-400" v-else-if="otpEmailSent">Email terkirim!</div>
|
|
682
|
+
<button class="hover:text-primary_main_hover px-0 py-1 text-sm font-medium text-primary_main" v-else-if="!resendInterval" v-on:click="resendOtp">Kirim ulang email</button>
|
|
683
|
+
<div class="py-1 text-sm text-gray-400" v-else>Kirimkan ulang dalam {{ resendInterval }}</div>
|
|
684
|
+
</div>
|
|
685
|
+
<BtnPrimary class="text-md h-12 w-full" v-on:click="sendOtp" :loading="isOtpLoading"> Verifikasi Kode </BtnPrimary>
|
|
686
|
+
</div>
|
|
687
|
+
</section>
|
|
688
|
+
<section v-else>
|
|
689
|
+
<div class="mb-3 flex flex-col space-y-2 text-left">
|
|
690
|
+
<h1 class="mb-[2px] text-2xl font-semibold leading-none">Login</h1>
|
|
691
|
+
<p class="!mt-1 mb-4 text-[15px] text-muted-foreground">Silakan login terlebih dahulu untuk masuk aplikasi.</p>
|
|
692
|
+
</div>
|
|
693
|
+
<div :class="cn('grid gap-6', $attrs.class ?? '')">
|
|
694
|
+
<div class="relative -mb-1 rounded-sm border-l-4 border-red-400 bg-red-50 px-4 py-2 text-[15px] text-red-500" v-if="loginError">
|
|
695
|
+
<span>{{ loginError }}</span>
|
|
696
|
+
<BtnCircle class="absolute right-2 top-1/2 h-6 w-6 -translate-y-1/2 bg-gray-200 opacity-70 transition hover:bg-slate-300 hover:opacity-100" v-on:click="loginError = null">
|
|
697
|
+
<LucideX :size="16"></LucideX>
|
|
698
|
+
</BtnCircle>
|
|
699
|
+
</div>
|
|
700
|
+
<Vueform :endpoint="login">
|
|
701
|
+
<TextElement name="email" input-type="email" :rules="['required']" label="Email" placeholder="Masukkan email..." :floating="false" v-on:input="loginError = null" />
|
|
702
|
+
<TextElement
|
|
703
|
+
name="password"
|
|
704
|
+
:input-type="showPassword ? 'text' : 'password'"
|
|
705
|
+
label="Kata Sandi"
|
|
706
|
+
placeholder="Masukkan kata sandi..."
|
|
707
|
+
:floating="false"
|
|
708
|
+
:rules="['required']"
|
|
709
|
+
v-on:input="loginError = null"
|
|
710
|
+
onpaste="return false;">
|
|
711
|
+
<template #addon-after>
|
|
712
|
+
<EyeOff :size="22" v-if="showPassword" class="cursor-pointer text-slate-400" @click="showPassword = false" />
|
|
713
|
+
<Eye :size="22" v-else class="cursor-pointer text-slate-400" @click="showPassword = true" />
|
|
714
|
+
</template>
|
|
715
|
+
</TextElement>
|
|
716
|
+
<div class="col-span-12 -mt-2 mb-5">
|
|
717
|
+
<button class="hover:text-primary_main_hover ml-1 text-sm font-semibold text-primary_main" type="button" v-on:click="openForgotPwd">Lupa Kata Sandi?</button>
|
|
718
|
+
</div>
|
|
719
|
+
<div class="relative col-span-12 mt-1 h-12 cursor-default overflow-hidden rounded-md !border-gray-300 !bg-gray-300 px-6 !text-gray-300 transition" v-if="isLoading">
|
|
720
|
+
<div class="absolute bottom-0 left-0 right-0 top-0 bg-gray-300">
|
|
721
|
+
<svg class="absolute bottom-0 left-0 right-0 top-0 m-auto h-7 w-7 animate-spin text-black" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
722
|
+
<circle class="opacity-15" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" />
|
|
723
|
+
<path class="opacity-15" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
|
|
724
|
+
</svg>
|
|
725
|
+
</div>
|
|
726
|
+
</div>
|
|
727
|
+
<div class="relative col-span-12 mt-1 h-12 cursor-default overflow-hidden rounded-md !border-gray-300 !bg-gray-300 px-6 !text-gray-300 transition" v-else-if="lockoutInterval">
|
|
728
|
+
<div class="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-gray-200 leading-tight text-gray-400">
|
|
729
|
+
<div class="text-center">
|
|
730
|
+
<h4 class="text-[16px] font-medium">Akun terkunci</h4>
|
|
731
|
+
<p class="text-xs">Anda dapat login kembali dalam {{ lockoutInterval }}</p>
|
|
732
|
+
</div>
|
|
733
|
+
</div>
|
|
734
|
+
</div>
|
|
735
|
+
<ButtonElement
|
|
736
|
+
size="lg"
|
|
737
|
+
name="submit"
|
|
738
|
+
button-class="mt-1 font-medium h-11 !py-0 text-md !bg-blue-500 hover:!bg-blue-600 !transition !border-none"
|
|
739
|
+
button-label="Login Non-SSO"
|
|
740
|
+
:submits="true"
|
|
741
|
+
:full="true"
|
|
742
|
+
v-else />
|
|
743
|
+
</Vueform>
|
|
744
|
+
<div class="relative -mb-3 -mt-5">
|
|
745
|
+
<div class="absolute inset-0 flex items-center">
|
|
746
|
+
<span class="w-full border-t border-slate-300 dark:border-dark_border2"></span>
|
|
747
|
+
</div>
|
|
748
|
+
<div class="relative flex justify-center pt-1.5 text-sm">
|
|
749
|
+
<span class="bg-slate-100 px-2 text-muted-foreground text-slate-400 dark:bg-dark_bg dark:text-gray-500"> Atau login dengan </span>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
<BtnSecondary
|
|
753
|
+
class="text-md h-11 border border-gray-200 bg-white !py-0 hover:shadow-sm dark:border-none dark:bg-dark_bg4 dark:text-dark_text dark:hover:bg-dark_bg6"
|
|
754
|
+
type="button"
|
|
755
|
+
v-on:click="loginSso">
|
|
756
|
+
Login SSO
|
|
757
|
+
</BtnSecondary>
|
|
758
|
+
</div>
|
|
759
|
+
</section>
|
|
760
|
+
<div :data-sitekey="grecaptchaSiteKey" class="g-recaptcha" data-size="invisible"></div>
|
|
761
|
+
|
|
762
|
+
<div class="fixed bottom-0 left-0 right-0 top-0 z-[99] !m-0 flex items-center justify-center bg-black/60" v-if="captchaOpen">
|
|
763
|
+
<Slide
|
|
764
|
+
:config="{
|
|
765
|
+
title: 'Verifikasi bukan robot',
|
|
766
|
+
buttonText: 'Verifikasi'
|
|
767
|
+
}"
|
|
768
|
+
:data="captchaData"
|
|
769
|
+
:events="captchaEvents"
|
|
770
|
+
ref="domRef" />
|
|
771
|
+
</div>
|
|
772
|
+
|
|
773
|
+
<!-- Privacy policy -->
|
|
774
|
+
<AlertDialog v-model:open="privacyPolicyOpen">
|
|
775
|
+
<AlertDialogContent class="w-full max-w-[940px]">
|
|
776
|
+
<AlertDialogHeader>
|
|
777
|
+
<AlertDialogTitle>Setujui Privacy Policy</AlertDialogTitle>
|
|
778
|
+
<AlertDialogDescription>
|
|
779
|
+
<div class="-mx-6">
|
|
780
|
+
<section class="h-[80vh] w-full overflow-auto border-b border-t" v-on:scroll="privacyPolicyScrolled">
|
|
781
|
+
<div class="px-6 pb-10 pt-4">
|
|
782
|
+
<PrivacyPolicy />
|
|
783
|
+
</div>
|
|
784
|
+
</section>
|
|
785
|
+
</div>
|
|
786
|
+
</AlertDialogDescription>
|
|
787
|
+
</AlertDialogHeader>
|
|
788
|
+
<AlertDialogFooter>
|
|
789
|
+
<AlertDialogCancel
|
|
790
|
+
class="h-10 border-none px-5 text-base font-medium text-gray-500 shadow-none hover:bg-slate-100 hover:text-slate-600"
|
|
791
|
+
:class="{ '!text-gray-300 hover:!bg-white': !privacyPolicyCanAgree }"
|
|
792
|
+
v-on:click="disagreePrivacy"
|
|
793
|
+
:disabled="!privacyPolicyCanAgree">
|
|
794
|
+
Tidak Setuju
|
|
795
|
+
</AlertDialogCancel>
|
|
796
|
+
<AlertDialogAction
|
|
797
|
+
class="h-10 border-none px-5 text-base font-medium shadow-none"
|
|
798
|
+
:class="{ '!bg-gray-200 !text-gray-400': !privacyPolicyCanAgree }"
|
|
799
|
+
v-on:click="agreePrivacy"
|
|
800
|
+
:disabled="!privacyPolicyCanAgree">
|
|
801
|
+
Setuju
|
|
802
|
+
</AlertDialogAction>
|
|
803
|
+
</AlertDialogFooter>
|
|
804
|
+
</AlertDialogContent>
|
|
805
|
+
</AlertDialog>
|
|
806
|
+
</template>
|