From d438fb0f5f6a8c023565a2791eb3241ab54ee3f4 Mon Sep 17 00:00:00 2001 From: Yusron alamsyah Date: Tue, 31 Mar 2026 11:11:39 +0700 Subject: [PATCH] integrate login page wih api and keycloak --- components/auth/LoginForm.vue | 185 ++++++++++++++++ components/layout/full/Main.vue | 22 +- .../layout/full/vertical-header/ProfileDD.vue | 143 +++--------- .../full/vertical-sidebar/sidebarItem.ts | 50 ++--- components/setting/pages/listPages.vue | 2 + components/shared/AppSnackbar.vue | 21 ++ components/shared/UiChildCard.vue | 3 +- composables/useAuth.ts | 89 ++++++++ composables/useAuthInfo.ts | 49 +++++ middleware/auth.ts | 24 +++ nuxt.config.ts | 14 +- pages/apps/dashboard/index.vue | 7 +- pages/apps/setting/pages/index.vue | 70 ++++++ pages/auth/Login.vue | 53 +---- pages/index.vue | 4 + pages/{ => template}/Icons.vue | 0 pages/{ => template}/Sample-Page.vue | 0 .../shared-components/AppBaseCard.vue | 0 .../shared-components/BaseBreadcrumb.vue | 0 .../shared-components/CardComponents.vue | 0 .../shared-components/UiParentCard.vue | 0 .../shared-components/UiTextfieldPrimary.vue | 0 .../shared-components/WidgetCards.vue | 0 .../shared-components/index.vue | 0 .../style-components/Shadow.vue | 0 .../style-components/Typography.vue | 0 pages/{ => template}/ui-components/Alerts.vue | 0 pages/{ => template}/ui-components/Avatar.vue | 0 .../{ => template}/ui-components/Buttons.vue | 0 pages/{ => template}/ui-components/Cards.vue | 0 pages/{ => template}/ui-components/Chip.vue | 0 .../{ => template}/ui-components/Dialogs.vue | 0 .../ui-components/ExpansionPanel.vue | 0 pages/{ => template}/ui-components/List.vue | 0 pages/{ => template}/ui-components/Menus.vue | 0 .../{ => template}/ui-components/Ratting.vue | 0 pages/{ => template}/ui-components/Tables.vue | 0 pages/{ => template}/ui-components/Tabs.vue | 0 .../{ => template}/ui-components/Tooltip.vue | 0 pages/{ => template}/ui/Shadow.vue | 0 pages/{ => template}/ui/Typography.vue | 0 pages/{ => template}/ui/tables/TableBasic.vue | 0 pages/{ => template}/ui/tables/TableDark.vue | 0 .../{ => template}/ui/tables/TableDensity.vue | 0 .../ui/tables/TableEditable.vue | 0 .../ui/tables/TableHeaderFixed.vue | 0 .../{ => template}/ui/tables/TableHeight.vue | 0 .../ui/tables/datatables/BasicTable.vue | 0 .../ui/tables/datatables/CrudTable.vue | 0 .../ui/tables/datatables/Filtering.vue | 0 .../ui/tables/datatables/Grouping.vue | 0 .../ui/tables/datatables/HeaderTables.vue | 0 .../ui/tables/datatables/Pagination.vue | 0 .../ui/tables/datatables/Selectable.vue | 0 .../ui/tables/datatables/Slots.vue | 0 .../ui/tables/datatables/SortingTable.vue | 0 pages/{ => template}/widgets/Banners.vue | 0 pages/{ => template}/widgets/Cards.vue | 0 pages/{ => template}/widgets/Charts.vue | 0 server/api/auth/keycloak-callback.get.ts | 203 ++++++++++++++++++ server/api/auth/keycloak-login.ts | 70 ++++++ server/api/auth/logout.post.ts | 82 +++++++ server/api/auth/sessionUser.get.ts | 58 +++++ server/api/auth/sessionUserStore.post.ts | 119 ++++++++++ server/utils/sessionStore.ts | 75 +++++++ store/snackbar.ts | 32 +++ types/auth.ts | 39 ++++ utils/api.ts | 11 + 68 files changed, 1213 insertions(+), 212 deletions(-) create mode 100644 components/auth/LoginForm.vue create mode 100644 components/setting/pages/listPages.vue create mode 100644 components/shared/AppSnackbar.vue create mode 100644 composables/useAuth.ts create mode 100644 composables/useAuthInfo.ts create mode 100644 middleware/auth.ts create mode 100644 pages/apps/setting/pages/index.vue rename pages/{ => template}/Icons.vue (100%) rename pages/{ => template}/Sample-Page.vue (100%) rename pages/{ => template}/shared-components/AppBaseCard.vue (100%) rename pages/{ => template}/shared-components/BaseBreadcrumb.vue (100%) rename pages/{ => template}/shared-components/CardComponents.vue (100%) rename pages/{ => template}/shared-components/UiParentCard.vue (100%) rename pages/{ => template}/shared-components/UiTextfieldPrimary.vue (100%) rename pages/{ => template}/shared-components/WidgetCards.vue (100%) rename pages/{ => template}/shared-components/index.vue (100%) rename pages/{ => template}/style-components/Shadow.vue (100%) rename pages/{ => template}/style-components/Typography.vue (100%) rename pages/{ => template}/ui-components/Alerts.vue (100%) rename pages/{ => template}/ui-components/Avatar.vue (100%) rename pages/{ => template}/ui-components/Buttons.vue (100%) rename pages/{ => template}/ui-components/Cards.vue (100%) rename pages/{ => template}/ui-components/Chip.vue (100%) rename pages/{ => template}/ui-components/Dialogs.vue (100%) rename pages/{ => template}/ui-components/ExpansionPanel.vue (100%) rename pages/{ => template}/ui-components/List.vue (100%) rename pages/{ => template}/ui-components/Menus.vue (100%) rename pages/{ => template}/ui-components/Ratting.vue (100%) rename pages/{ => template}/ui-components/Tables.vue (100%) rename pages/{ => template}/ui-components/Tabs.vue (100%) rename pages/{ => template}/ui-components/Tooltip.vue (100%) rename pages/{ => template}/ui/Shadow.vue (100%) rename pages/{ => template}/ui/Typography.vue (100%) rename pages/{ => template}/ui/tables/TableBasic.vue (100%) rename pages/{ => template}/ui/tables/TableDark.vue (100%) rename pages/{ => template}/ui/tables/TableDensity.vue (100%) rename pages/{ => template}/ui/tables/TableEditable.vue (100%) rename pages/{ => template}/ui/tables/TableHeaderFixed.vue (100%) rename pages/{ => template}/ui/tables/TableHeight.vue (100%) rename pages/{ => template}/ui/tables/datatables/BasicTable.vue (100%) rename pages/{ => template}/ui/tables/datatables/CrudTable.vue (100%) rename pages/{ => template}/ui/tables/datatables/Filtering.vue (100%) rename pages/{ => template}/ui/tables/datatables/Grouping.vue (100%) rename pages/{ => template}/ui/tables/datatables/HeaderTables.vue (100%) rename pages/{ => template}/ui/tables/datatables/Pagination.vue (100%) rename pages/{ => template}/ui/tables/datatables/Selectable.vue (100%) rename pages/{ => template}/ui/tables/datatables/Slots.vue (100%) rename pages/{ => template}/ui/tables/datatables/SortingTable.vue (100%) rename pages/{ => template}/widgets/Banners.vue (100%) rename pages/{ => template}/widgets/Cards.vue (100%) rename pages/{ => template}/widgets/Charts.vue (100%) create mode 100644 server/api/auth/keycloak-callback.get.ts create mode 100644 server/api/auth/keycloak-login.ts create mode 100644 server/api/auth/logout.post.ts create mode 100644 server/api/auth/sessionUser.get.ts create mode 100644 server/api/auth/sessionUserStore.post.ts create mode 100644 server/utils/sessionStore.ts create mode 100644 store/snackbar.ts create mode 100644 utils/api.ts diff --git a/components/auth/LoginForm.vue b/components/auth/LoginForm.vue new file mode 100644 index 0000000..565497d --- /dev/null +++ b/components/auth/LoginForm.vue @@ -0,0 +1,185 @@ + + + diff --git a/components/layout/full/Main.vue b/components/layout/full/Main.vue index b79beb4..84b4b0c 100644 --- a/components/layout/full/Main.vue +++ b/components/layout/full/Main.vue @@ -4,6 +4,8 @@ import { useDisplay } from "vuetify"; import sidebarItems from "~/components/layout/full/vertical-sidebar/sidebarItem"; import { Menu2Icon } from "vue-tabler-icons"; import { useCustomizerStore } from "~/store/customizer"; +import AppSnackbar from '~/components/shared/AppSnackbar.vue'; + const sidebarMenu = shallowRef(sidebarItems); const customizer = useCustomizerStore(); const { mdAndDown } = useDisplay(); @@ -46,19 +48,13 @@ watch(mdAndDown, (val) => { - -
- -
-
- -
-
-
-
+ + +
+ + +
+
diff --git a/components/layout/full/vertical-header/ProfileDD.vue b/components/layout/full/vertical-header/ProfileDD.vue index 24b7958..6a78c1e 100644 --- a/components/layout/full/vertical-header/ProfileDD.vue +++ b/components/layout/full/vertical-header/ProfileDD.vue @@ -1,105 +1,66 @@ @@ -127,10 +88,10 @@ const sessionInfo = computed(() => {
{{ displayInfo.name }}
- + +
{
- - - - - -
-
- {{ item.title }} -
-
-

- {{ item.subtitle }} -

-
-
-
- -
+
{ { > Full Logout - - -
- - Full logout akan menghapus semua sesi dan data lokal - -
diff --git a/components/layout/full/vertical-sidebar/sidebarItem.ts b/components/layout/full/vertical-sidebar/sidebarItem.ts index e4f01a9..0350f09 100644 --- a/components/layout/full/vertical-sidebar/sidebarItem.ts +++ b/components/layout/full/vertical-sidebar/sidebarItem.ts @@ -214,17 +214,17 @@ const sidebarItem: menu[] = [ { title: 'Banners', icon: 'gallery-wide-line-duotone', - to: '/widgets/banners' + to: '/template/widgets/banners' }, { title: 'Cards', icon: 'layers-minimalistic-line-duotone', - to: '/widgets/cards' + to: '/template/widgets/cards' }, { title: 'Charts', icon: 'chart-line-duotone', - to: '/widgets/charts' + to: '/template/widgets/charts' }, ] }, @@ -236,67 +236,67 @@ const sidebarItem: menu[] = [ { title: 'Alerts', icon: 'danger-triangle-line-duotone', - to: '/ui-components/alerts' + to: '/template/ui-components/alerts' }, { title: 'Avatar', icon: 'user-circle-line-duotone', - to: '/ui-components/avatar' + to: '/template/ui-components/avatar' }, { title: 'Buttons', icon: 'ghost-line-duotone', - to: '/ui-components/buttons' + to: '/template/ui-components/buttons' }, { title: 'Cards', icon: 'layers-minimalistic-line-duotone', - to: '/ui-components/cards' + to: '/template/ui-components/cards' }, { title: 'Chip', icon: 'tag-horizontal-line-duotone', - to: '/ui-components/chip' + to: '/template/ui-components/chip' }, { title: 'Dialogs', icon: 'window-frame-line-duotone', - to: '/ui-components/dialogs' + to: '/template/ui-components/dialogs' }, { title: 'Expansion Panel', icon: 'hamburger-menu-line-duotone', - to: '/ui-components/expansionPanel' + to: '/template/ui-components/expansionPanel' }, { title: 'List', icon: 'list-line-duotone', - to: '/ui-components/list' + to: '/template/ui-components/list' }, { title: 'Menus', icon: 'menu-dots-line-duotone', - to: '/ui-components/menus' + to: '/template/ui-components/menus' }, { title: 'Ratting', icon: 'star-line-duotone', - to: '/ui-components/ratting' + to: '/template/ui-components/ratting' }, { title: 'Tables', icon: 'tablet-line-duotone', - to: '/ui-components/tables' + to: '/template/ui-components/tables' }, { title: 'Tabs', icon: 'notebook-line-duotone', - to: '/ui-components/tabs' + to: '/template/ui-components/tabs' }, { title: 'Tooltip', icon: 'chat-round-dots-line-duotone', - to: '/ui-components/tooltip' + to: '/template/ui-components/tooltip' } ] }, @@ -307,12 +307,12 @@ const sidebarItem: menu[] = [ { title: 'Shadow', icon: 'copy-line-duotone', - to: '/style-components/shadow' + to: '/template/style-components/shadow' }, { title: 'Typography', icon: 'text-bold-circle-line-duotone', - to: '/style-components/typography' + to: '/template/style-components/typography' } ] }, @@ -324,37 +324,37 @@ const sidebarItem: menu[] = [ { title: 'Overview', icon: 'widget-5-line-duotone', - to: '/shared-components' + to: '/template/shared-components' }, { title: 'UiParentCard & UiChildCard', icon: 'layers-minimalistic-line-duotone', - to: '/shared-components/UiParentCard' + to: '/template/shared-components/UiParentCard' }, { title: 'WidgetCard & WidgetCardv2', icon: 'chart-square-line-duotone', - to: '/shared-components/WidgetCards' + to: '/template/shared-components/WidgetCards' }, { title: 'Card Components', icon: 'card-2-line-duotone', - to: '/shared-components/CardComponents' + to: '/template/shared-components/CardComponents' }, { title: 'BaseBreadcrumb', icon: 'route-line-duotone', - to: '/shared-components/BaseBreadcrumb' + to: '/template/shared-components/BaseBreadcrumb' }, { title: 'UiTextfieldPrimary', icon: 'text-field-line-duotone', - to: '/shared-components/UiTextfieldPrimary' + to: '/template/shared-components/UiTextfieldPrimary' }, { title: 'AppBaseCard', icon: 'sidebar-minimalistic-line-duotone', - to: '/shared-components/AppBaseCard' + to: '/template/shared-components/AppBaseCard' }, ] }, diff --git a/components/setting/pages/listPages.vue b/components/setting/pages/listPages.vue new file mode 100644 index 0000000..ba53413 --- /dev/null +++ b/components/setting/pages/listPages.vue @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/components/shared/AppSnackbar.vue b/components/shared/AppSnackbar.vue new file mode 100644 index 0000000..dbdb8e1 --- /dev/null +++ b/components/shared/AppSnackbar.vue @@ -0,0 +1,21 @@ + + + diff --git a/components/shared/UiChildCard.vue b/components/shared/UiChildCard.vue index a61b3e6..3271f12 100644 --- a/components/shared/UiChildCard.vue +++ b/components/shared/UiChildCard.vue @@ -5,11 +5,10 @@ const props = defineProps({