diff --git a/components/Master/CardList.vue b/components/Master/CardList.vue new file mode 100644 index 0000000..047cbf8 --- /dev/null +++ b/components/Master/CardList.vue @@ -0,0 +1,98 @@ + + \ No newline at end of file diff --git a/components/Master/Table.vue b/components/Master/Table.vue new file mode 100644 index 0000000..3d8927b --- /dev/null +++ b/components/Master/Table.vue @@ -0,0 +1,46 @@ + + diff --git a/components/auth/LoginForm.vue b/components/auth/LoginForm.vue index c79cc2d..8f55a28 100644 --- a/components/auth/LoginForm.vue +++ b/components/auth/LoginForm.vue @@ -1,32 +1,48 @@ diff --git a/components/layout/full/Main.vue b/components/layout/full/Main.vue index 2734e1e..fdcae13 100644 --- a/components/layout/full/Main.vue +++ b/components/layout/full/Main.vue @@ -3,16 +3,18 @@ import { onMounted, ref, shallowRef, watch } from 'vue'; import { useDisplay } from "vuetify"; import sidebarItems from "@/components/layout/full/vertical-sidebar/sidebarItem"; import { Menu2Icon } from "vue-tabler-icons"; +const props = defineProps({ items: { type: Object } }) +const sidebarMenu = ref(''); -const sidebarMenu = shallowRef(sidebarItems); const { mdAndDown } = useDisplay(); const sDrawer = ref(true); onMounted(() => { sDrawer.value = !mdAndDown.value; // hide on mobile, show on desktop }); -watch(mdAndDown, (val) => { - sDrawer.value = !val; +watch([mdAndDown, () => props.items], ([mdVal, items]) => { + sDrawer.value = !mdVal; + sidebarMenu.value = items; }); diff --git a/components/layout/full/vertical-header/ProfileDD.vue b/components/layout/full/vertical-header/ProfileDD.vue index 0f2d04c..63ae659 100644 --- a/components/layout/full/vertical-header/ProfileDD.vue +++ b/components/layout/full/vertical-header/ProfileDD.vue @@ -1,5 +1,15 @@ - + My Profile - My Account + My Account - + My Task
- Logout + Logout
diff --git a/components/layout/full/vertical-sidebar/sidebarItem.ts b/components/layout/full/vertical-sidebar/sidebarItem.ts index b245d1c..4dfa520 100644 --- a/components/layout/full/vertical-sidebar/sidebarItem.ts +++ b/components/layout/full/vertical-sidebar/sidebarItem.ts @@ -1,3 +1,5 @@ +const { $decodeBase64 } = useNuxtApp(); + export interface menu { header?: string; title?: string; @@ -14,6 +16,7 @@ export interface menu { type?: string; subCaption?: string; external?: boolean; + requiredGroups?: string[]; } const sidebarItem: menu[] = [ @@ -44,16 +47,19 @@ const sidebarItem: menu[] = [ title: "Front Pages", icon: "home-angle-linear", to: "/front", + requiredGroups: ["/Bidang Pelayanan Medik"], children: [ { title: "Coba VueForm", to: "/coba", external: false, + requiredGroups: ["/Bidang Pelayanan Medik"] }, { title: "Coba VueForm2", to: "/coba2", external: false, + requiredGroups: ["/Bidang Diklit/Staff"] }, { title: "Homepage", @@ -68,6 +74,8 @@ const sidebarItem: menu[] = [ title: "Typography", icon: "text-circle-outline", to: "/ui/typography", + requiredGroups: ['/Instalasi Bedah Sentral', '/Instalasi Rawat Jalan'], + }, { title: "Shadow", @@ -124,4 +132,7 @@ const sidebarItem: menu[] = [ }, ]; + + + export default sidebarItem; diff --git a/data/dummy/keuangan.menu.json b/data/dummy/keuangan.menu.json new file mode 100644 index 0000000..cf9f06d --- /dev/null +++ b/data/dummy/keuangan.menu.json @@ -0,0 +1,66 @@ +[{ + "_id": { + "$oid": "683d582ebccc67d467a9e114" + }, + "display": "Setting", + "child": "", + "ordered": 9, + "parent": null, + "icon": "", + "link": "/setting" +}, +{ + "_id": { + "$oid": "683d99fe1b8c132fda4b32cb" + }, + "display": "Tipe Pengguna", + "child": "", + "ordered": 9, + "parent": "683d582ebccc67d467a9e114", + "icon": "", + "link": "/setting/typeUser" +}, +{ + "_id": { + "$oid": "683d9d561b8c132fda4b32e1" + }, + "display": "Hak Akses", + "child": "", + "ordered": 9, + "parent": "683d582ebccc67d467a9e114", + "icon": "", + "link": "/setting/typeUser/hakAkses" +}, +{ + "_id": { + "$oid": "683d9ebc1b8c132fda4b32e2" + }, + "display": "Profile", + "child": "", + "ordered": 3, + "parent": null, + "icon": "", + "link": "/profile" +}, +{ + "_id": { + "$oid": "683d9f071b8c132fda4b32e3" + }, + "display": "Dashboard", + "child": "", + "ordered": 1, + "parent": null, + "icon": "", + "link": "/" +}, +{ + "_id": { + "$oid": "683da1491b8c132fda4b32e7" + }, + "display": "Sample Page", + "child": "", + "ordered": 2, + "parent": null, + "icon": "", + "link": "/sample" +}] \ No newline at end of file diff --git a/data/dummy/keuangan.role_menu.json b/data/dummy/keuangan.role_menu.json new file mode 100644 index 0000000..be99ea3 --- /dev/null +++ b/data/dummy/keuangan.role_menu.json @@ -0,0 +1,126 @@ +[{ + "_id": { + "$oid": "683da37c1b8c132fda4b32f7" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683d582ebccc67d467a9e114", + "access": [ + { + "add": 0 + }, + { + "update": 0 + }, + { + "read": 0 + }, + { + "delete": 0 + } + ] +}, +{ + "_id": { + "$oid": "683da7481b8c132fda4b3302" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683d99fe1b8c132fda4b32cb", + "access": [ + { + "add": 1 + }, + { + "update": 1 + }, + { + "read": 1 + }, + { + "delete": 1 + } + ] +}, +{ + "_id": { + "$oid": "683da81a1b8c132fda4b3308" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683d9d561b8c132fda4b32e1", + "access": [ + { + "add": 1 + }, + { + "update": 1 + }, + { + "read": 1 + }, + { + "delete": 0 + } + ] +}, +{ + "_id": { + "$oid": "683da9791b8c132fda4b3314" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683d9ebc1b8c132fda4b32e2", + "access": [ + { + "add": 1 + }, + { + "update": 1 + }, + { + "read": 1 + }, + { + "delete": 0 + } + ] +}, +{ + "_id": { + "$oid": "683daa6f1b8c132fda4b3319" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683d9f071b8c132fda4b32e3", + "access": [ + { + "add": 1 + }, + { + "update": 1 + }, + { + "read": 1 + }, + { + "delete": 1 + } + ] +}, +{ + "_id": { + "$oid": "683daaf71b8c132fda4b3322" + }, + "type_user_id": "683d57b2bccc67d467a9e10f", + "menu_id": "683da1491b8c132fda4b32e7", + "access": [ + { + "add": 1 + }, + { + "update": 1 + }, + { + "read": 1 + }, + { + "delete": 0 + } + ] +}] \ No newline at end of file diff --git a/data/dummy/keuangan.type_user.json b/data/dummy/keuangan.type_user.json new file mode 100644 index 0000000..e13483f --- /dev/null +++ b/data/dummy/keuangan.type_user.json @@ -0,0 +1,28 @@ +[{ + "_id": { + "$oid": "683d57b2bccc67d467a9e10f" + }, + "display": "Super Admin", + "status": true +}, +{ + "_id": { + "$oid": "683d5805bccc67d467a9e110" + }, + "display": "Admin", + "status": true +}, +{ + "_id": { + "$oid": "683d5811bccc67d467a9e111" + }, + "display": "Staf", + "status": true +}, +{ + "_id": { + "$oid": "683d5825bccc67d467a9e112" + }, + "display": "PJA / Koordinator", + "status": true +}] \ No newline at end of file diff --git a/layouts/default.vue b/layouts/default.vue index 233ad09..b0e02c2 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -12,13 +12,77 @@ useHead({ : "Matdash - Nuxt3 Typescript based Free Admin Dashboard Template"; }, }); + + +const { $encodeBase64, $decodeBase64 } = useNuxtApp(); +const sidebarMenu = ref(''); +const sessionState = ref(''); +const issuer = ref(''); +const code = ref(''); +const cobaSetProfile = ref([]); +const runtimeconfig = useRuntimeConfig(); +const url = window.location.href; +const urlParams = new URL(url).searchParams; +sessionState.value = urlParams.get('session_state') || ''; +issuer.value = urlParams.get('iss') || ''; +code.value = urlParams.get('code') || ''; + +const response = $fetch(`${issuer.value}/protocol/openid-connect/token`, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, + body: new URLSearchParams({ + grant_type: 'authorization_code', + client_id: runtimeconfig.public.keycloakClient, // Ganti dengan client ID Anda + client_secret: runtimeconfig.public.keycloakSecretKey, + code: code.value, + redirect_uri: `${window.location.origin}`, // Ganti dengan redirect URI Anda + }) +}).then((response) => { + const reUserInfo = $fetch(`${issuer.value}/protocol/openid-connect/userinfo`, { + headers: { + Authorization: `Bearer ${response.access_token}`, + } + }) + .then((response) => { + const idMongose = response.idMongose + const encodeProfile = $encodeBase64(JSON.stringify(response)) + localStorage.setItem('userProfile', encodeProfile) + cobaSetProfile.value.push(encodeProfile) + $fetch(`/api/sidebarItem`, { + method: 'POST', + body: { key: idMongose } + }) + .then((response) => { + localStorage.setItem('sidebarItems', $encodeBase64(JSON.stringify(response))) + sidebarMenu.value = response.items + }).catch((err) => { + loadSidebarItemLocalStorage() + }) + // $fetch(`http://10.10.150.131:8080/api/login/${idMongose}`, { + // headers: { 'Content-Type': 'application/json', }, + // mode: 'no-cors' + // }) + // .then((response) => { + // console.log(response) + // }) + }).catch((err) => { + loadSidebarItemLocalStorage() + }) +}).catch((err) => { + loadSidebarItemLocalStorage() +}) + +function loadSidebarItemLocalStorage() { + const as = JSON.parse($decodeBase64(localStorage.getItem('sidebarItems'))) + sidebarMenu.value = as.items +}