una-nuxt-module 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +84 -0
  2. package/dist/module.cjs +5 -0
  3. package/dist/module.d.mts +6 -0
  4. package/dist/module.d.ts +6 -0
  5. package/dist/module.json +9 -0
  6. package/dist/module.mjs +105 -0
  7. package/dist/runtime/assets/scss/styles.css +1249 -0
  8. package/dist/runtime/classes/FetchClient.d.ts +61 -0
  9. package/dist/runtime/classes/FetchClient.js +71 -0
  10. package/dist/runtime/components/layout/footer/Footer.vue +16 -0
  11. package/dist/runtime/components/layout/header/BtnExtendMenu.vue +29 -0
  12. package/dist/runtime/components/layout/header/Header.vue +7 -0
  13. package/dist/runtime/components/layout/header/HeaderMenu.vue +41 -0
  14. package/dist/runtime/components/layout/header/HeaderMenuTabs.vue +102 -0
  15. package/dist/runtime/components/layout/sidebar/NavCollapse.vue +38 -0
  16. package/dist/runtime/components/layout/sidebar/NavGroup.vue +9 -0
  17. package/dist/runtime/components/layout/sidebar/NavItem.vue +25 -0
  18. package/dist/runtime/components/layout/sidebar/SideBar.vue +74 -0
  19. package/dist/runtime/components/layout/sidebar/SideBarFooter.vue +69 -0
  20. package/dist/runtime/components/layout/sidebar/TopSideBarLogo.vue +25 -0
  21. package/dist/runtime/components/shared/authorization/AuthorizedRenderer.vue +41 -0
  22. package/dist/runtime/components/shared/buttons/BtnBack.vue +19 -0
  23. package/dist/runtime/components/shared/buttons/BtnCancel.vue +13 -0
  24. package/dist/runtime/components/shared/buttons/BtnConfirm.vue +14 -0
  25. package/dist/runtime/components/shared/containers/JsonViewer.vue +13 -0
  26. package/dist/runtime/components/shared/dates/DatePicker.vue +91 -0
  27. package/dist/runtime/components/shared/dialogs/DialogConfirmDelete.vue +32 -0
  28. package/dist/runtime/components/shared/dialogs/DialogExportTable.vue +42 -0
  29. package/dist/runtime/components/shared/feedback/LoadingSession.vue +17 -0
  30. package/dist/runtime/components/shared/feedback/SnackBar.vue +36 -0
  31. package/dist/runtime/components/shared/forms/FormBuilder/FieldBuilder.vue +251 -0
  32. package/dist/runtime/components/shared/forms/FormBuilder/FieldSlotMissed.vue +20 -0
  33. package/dist/runtime/components/shared/forms/FormBuilder/FormBuilder.vue +213 -0
  34. package/dist/runtime/components/shared/forms/FormBuilder/SteppersBuilder.vue +32 -0
  35. package/dist/runtime/components/shared/forms/FormBuilder/TabsBuilder.vue +30 -0
  36. package/dist/runtime/components/shared/forms/FormDialogWrapper.vue +48 -0
  37. package/dist/runtime/components/shared/forms/FormPageWrapper.vue +19 -0
  38. package/dist/runtime/components/shared/forms/FormSubmitSection.vue +48 -0
  39. package/dist/runtime/components/shared/navigation/BreadCrumbs.vue +21 -0
  40. package/dist/runtime/components/shared/tables/CustomTable.vue +261 -0
  41. package/dist/runtime/components/shared/tables/CustomTableHeader.vue +25 -0
  42. package/dist/runtime/components/shared/tables/NoDataMessage.vue +12 -0
  43. package/dist/runtime/components/shared/tables/TableSearchBar.vue +22 -0
  44. package/dist/runtime/components/shared/tables/buttons/BtnAdd.vue +25 -0
  45. package/dist/runtime/components/shared/tables/buttons/BtnDelete.vue +32 -0
  46. package/dist/runtime/components/shared/tables/buttons/BtnEdit.vue +30 -0
  47. package/dist/runtime/components/shared/tables/buttons/BtnExport.vue +17 -0
  48. package/dist/runtime/components/shared/tables/buttons/BtnFilter.vue +21 -0
  49. package/dist/runtime/components/shared/tables/pagination/ItemsPerPageCombo.vue +24 -0
  50. package/dist/runtime/components/shared/tables/pagination/ItemsPerPageLabel.vue +5 -0
  51. package/dist/runtime/components/shared/tables/pagination/PageSelector.vue +16 -0
  52. package/dist/runtime/components/shared/tables/pagination/PaginationInfo.vue +31 -0
  53. package/dist/runtime/composables/useAuthorization.d.ts +32 -0
  54. package/dist/runtime/composables/useAuthorization.js +95 -0
  55. package/dist/runtime/constants/form.d.ts +44 -0
  56. package/dist/runtime/constants/form.js +58 -0
  57. package/dist/runtime/constants/index.d.ts +4 -0
  58. package/dist/runtime/constants/index.js +4 -0
  59. package/dist/runtime/constants/pagination.d.ts +13 -0
  60. package/dist/runtime/constants/pagination.js +8 -0
  61. package/dist/runtime/constants/request.d.ts +5 -0
  62. package/dist/runtime/constants/request.js +6 -0
  63. package/dist/runtime/constants/tables.d.ts +4 -0
  64. package/dist/runtime/constants/tables.js +15 -0
  65. package/dist/runtime/enums/EAsyncDataRequestStatus.d.ts +9 -0
  66. package/dist/runtime/enums/EAsyncDataRequestStatus.js +7 -0
  67. package/dist/runtime/enums/EAuthorization.d.ts +8 -0
  68. package/dist/runtime/enums/EAuthorization.js +6 -0
  69. package/dist/runtime/enums/EFormField.d.ts +14 -0
  70. package/dist/runtime/enums/EFormField.js +12 -0
  71. package/dist/runtime/enums/EFormMode.d.ts +7 -0
  72. package/dist/runtime/enums/EFormMode.js +5 -0
  73. package/dist/runtime/enums/ERequestMethod.d.ts +9 -0
  74. package/dist/runtime/enums/ERequestMethod.js +7 -0
  75. package/dist/runtime/enums/ETheme.d.ts +7 -0
  76. package/dist/runtime/enums/ETheme.js +5 -0
  77. package/dist/runtime/enums/EVuetifyDateFormats.d.ts +32 -0
  78. package/dist/runtime/enums/EVuetifyDateFormats.js +30 -0
  79. package/dist/runtime/enums/index.d.ts +6 -0
  80. package/dist/runtime/enums/index.js +6 -0
  81. package/dist/runtime/i18n/config.d.ts +61 -0
  82. package/dist/runtime/i18n/config.js +10 -0
  83. package/dist/runtime/i18n/locales/es.json +55 -0
  84. package/dist/runtime/i18n/service.d.ts +72 -0
  85. package/dist/runtime/i18n/service.js +3 -0
  86. package/dist/runtime/i18n/vueI18n.d.ts +5 -0
  87. package/dist/runtime/i18n/vueI18n.js +3 -0
  88. package/dist/runtime/index.d.ts +9 -0
  89. package/dist/runtime/layouts/default.vue +31 -0
  90. package/dist/runtime/layouts/empty.vue +12 -0
  91. package/dist/runtime/middleware/authentication.d.ts +10 -0
  92. package/dist/runtime/middleware/authentication.js +30 -0
  93. package/dist/runtime/middleware/authorization.d.ts +7 -0
  94. package/dist/runtime/middleware/authorization.js +39 -0
  95. package/dist/runtime/pages/401.vue +34 -0
  96. package/dist/runtime/pages/403.vue +35 -0
  97. package/dist/runtime/pages/ssoCallback.vue +14 -0
  98. package/dist/runtime/plugins/auth.d.ts +12 -0
  99. package/dist/runtime/plugins/auth.js +83 -0
  100. package/dist/runtime/plugins/vue-json.d.ts +12 -0
  101. package/dist/runtime/plugins/vue-json.js +5 -0
  102. package/dist/runtime/public/images/logos/UNA_LogoMark_Black.png +0 -0
  103. package/dist/runtime/public/images/logos/UNA_LogoType_LogoMark_Red.png +0 -0
  104. package/dist/runtime/server/tsconfig.json +3 -0
  105. package/dist/runtime/stores/UiCustomizer.d.ts +22 -0
  106. package/dist/runtime/stores/UiCustomizer.js +34 -0
  107. package/dist/runtime/stores/appStatus.d.ts +63 -0
  108. package/dist/runtime/stores/appStatus.js +101 -0
  109. package/dist/runtime/stores/auth.d.ts +76 -0
  110. package/dist/runtime/stores/auth.js +66 -0
  111. package/dist/runtime/stores/formModeTracker.d.ts +14 -0
  112. package/dist/runtime/stores/formModeTracker.js +10 -0
  113. package/dist/runtime/types/index.d.ts +584 -0
  114. package/dist/runtime/types/index.js +1 -0
  115. package/dist/runtime/utils/buildSortQueryParams.d.ts +10 -0
  116. package/dist/runtime/utils/buildSortQueryParams.js +3 -0
  117. package/dist/runtime/utils/getCurrentPath.d.ts +7 -0
  118. package/dist/runtime/utils/getCurrentPath.js +4 -0
  119. package/dist/runtime/utils/getDateTimeInISO8601.d.ts +11 -0
  120. package/dist/runtime/utils/getDateTimeInISO8601.js +3 -0
  121. package/dist/runtime/utils/getFromLocalStorage.d.ts +9 -0
  122. package/dist/runtime/utils/getFromLocalStorage.js +6 -0
  123. package/dist/runtime/utils/isNumberInRange.d.ts +11 -0
  124. package/dist/runtime/utils/isNumberInRange.js +5 -0
  125. package/dist/runtime/utils/onlyNumbers.d.ts +9 -0
  126. package/dist/runtime/utils/onlyNumbers.js +3 -0
  127. package/dist/runtime/utils/stringToBoolean.d.ts +9 -0
  128. package/dist/runtime/utils/stringToBoolean.js +3 -0
  129. package/dist/types.d.mts +7 -0
  130. package/dist/types.d.ts +7 -0
  131. package/package.json +69 -0
@@ -0,0 +1,61 @@
1
+ import type { IFetchParams } from "#imports";
2
+ import type { $Fetch } from "ofetch";
3
+ /**
4
+ * Clase que gestiona las peticiones HTTP .
5
+ * Proporciona una forma sencilla de realizar llamadas a APIs con configuración opcional.
6
+ */
7
+ export declare class FetchClient {
8
+ /** Instancia de $fetch utilizada para realizar las peticiones HTTP. */
9
+ private $fetch;
10
+ /**
11
+ * Constructor de la clase `FetchClient`.
12
+ *
13
+ * @param fetcher Instancia de `$fetch` que se utilizará para realizar las peticiones.
14
+ */
15
+ constructor(fetcher: $Fetch);
16
+ /**
17
+ * Realiza una llamada HTTP .
18
+ *
19
+ * @template T Tipo de los datos esperados en la respuesta.
20
+ * @param params Objeto que contiene los parámetros de la petición (método, URL, opciones, etc.).
21
+ * @returns Una promesa que resuelve con los datos obtenidos de la respuesta.
22
+ */
23
+ /**
24
+ * Realiza una llamada HTTP y devuelve los datos de la respuesta en un formato esperado.
25
+ *
26
+ * @template T Tipo de los datos esperados en la respuesta.
27
+ * @param params Objeto que contiene los parámetros necesarios para realizar la petición.
28
+ * @param params.method Método HTTP de la petición (GET, POST, PUT, DELETE, etc.). Por defecto, se utiliza `GET`.
29
+ * @param params.url URL o endpoint al cual se realizará la petición.
30
+ * @param params.fetchOptions Opciones adicionales para configurar la petición, como encabezados, credenciales o parámetros.
31
+ * @returns Una promesa que resuelve con los datos obtenidos de la respuesta, envueltos en el composable [`useAsyncData`](https://nuxt.com/docs/api/composables/use-async-data).
32
+ *
33
+ * @example
34
+ * // Ejemplo de uso para obtener datos con un GET:
35
+ * class UserModule extends FetchClient {
36
+ *
37
+ * async getAll() {
38
+ * return await this.call<IRequestResponse<IUser>>({
39
+ * url: "/api/users",
40
+ * fetchOptions: {
41
+ * headers: { Authorization: 'Bearer token' },
42
+ * query: { page: 1 },
43
+ * },
44
+ * });
45
+ * }
46
+ *
47
+ * * @example
48
+ * // Ejemplo de uso para enviar datos con un POST:
49
+ * class UserModule extends FetchClient {
50
+ *
51
+ * async create(user: IUser) {
52
+ * return await this.call<IRequestResponse<IUser>>({
53
+ * method: 'POST',
54
+ * url: "/api/user/create",
55
+ * fetchOptions: { body: JSON.stringify(user) },
56
+ * });
57
+ * }
58
+ * }
59
+ */
60
+ call<T>({ method, url, body, fetchOptions, }: IFetchParams): Promise<any>;
61
+ }
@@ -0,0 +1,71 @@
1
+ import { ERequestMethod, useAsyncData } from "#imports";
2
+ export class FetchClient {
3
+ /** Instancia de $fetch utilizada para realizar las peticiones HTTP. */
4
+ $fetch;
5
+ /**
6
+ * Constructor de la clase `FetchClient`.
7
+ *
8
+ * @param fetcher Instancia de `$fetch` que se utilizará para realizar las peticiones.
9
+ */
10
+ constructor(fetcher) {
11
+ this.$fetch = fetcher;
12
+ }
13
+ /**
14
+ * Realiza una llamada HTTP .
15
+ *
16
+ * @template T Tipo de los datos esperados en la respuesta.
17
+ * @param params Objeto que contiene los parámetros de la petición (método, URL, opciones, etc.).
18
+ * @returns Una promesa que resuelve con los datos obtenidos de la respuesta.
19
+ */
20
+ /**
21
+ * Realiza una llamada HTTP y devuelve los datos de la respuesta en un formato esperado.
22
+ *
23
+ * @template T Tipo de los datos esperados en la respuesta.
24
+ * @param params Objeto que contiene los parámetros necesarios para realizar la petición.
25
+ * @param params.method Método HTTP de la petición (GET, POST, PUT, DELETE, etc.). Por defecto, se utiliza `GET`.
26
+ * @param params.url URL o endpoint al cual se realizará la petición.
27
+ * @param params.fetchOptions Opciones adicionales para configurar la petición, como encabezados, credenciales o parámetros.
28
+ * @returns Una promesa que resuelve con los datos obtenidos de la respuesta, envueltos en el composable [`useAsyncData`](https://nuxt.com/docs/api/composables/use-async-data).
29
+ *
30
+ * @example
31
+ * // Ejemplo de uso para obtener datos con un GET:
32
+ * class UserModule extends FetchClient {
33
+ *
34
+ * async getAll() {
35
+ * return await this.call<IRequestResponse<IUser>>({
36
+ * url: "/api/users",
37
+ * fetchOptions: {
38
+ * headers: { Authorization: 'Bearer token' },
39
+ * query: { page: 1 },
40
+ * },
41
+ * });
42
+ * }
43
+ *
44
+ * * @example
45
+ * // Ejemplo de uso para enviar datos con un POST:
46
+ * class UserModule extends FetchClient {
47
+ *
48
+ * async create(user: IUser) {
49
+ * return await this.call<IRequestResponse<IUser>>({
50
+ * method: 'POST',
51
+ * url: "/api/user/create",
52
+ * fetchOptions: { body: JSON.stringify(user) },
53
+ * });
54
+ * }
55
+ * }
56
+ */
57
+ async call({
58
+ method = ERequestMethod.GET,
59
+ url,
60
+ body,
61
+ fetchOptions
62
+ }) {
63
+ return useAsyncData(() => {
64
+ return this.$fetch(url, {
65
+ method,
66
+ body,
67
+ ...fetchOptions
68
+ });
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <div>
3
+ <v-footer color="gray100" rounded class="mx-12">
4
+ <v-row justify="center">
5
+ <v-col cols="6">
6
+ <p class="text-caption text-center">
7
+ {{ $t("Components.Footer.Info[0]") }}
8
+ </p>
9
+ <p class="text-caption text-center">
10
+ {{ $t("Components.Footer.Info[1]") }}
11
+ </p>
12
+ </v-col>
13
+ </v-row>
14
+ </v-footer>
15
+ </div>
16
+ </template>
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <v-btn
3
+ :icon="extendMenuIcon"
4
+ @click.stop="handleClick"
5
+ class="btnExtendMenu"
6
+ density="compact"
7
+ rounded="lg"
8
+ size="large"
9
+ />
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import { computed } from "vue";
14
+ import { useUiCustomizerStore } from "../../../stores/UiCustomizer";
15
+
16
+ const uiCustomizer = useUiCustomizerStore();
17
+
18
+ const extendMenuIcon = computed(() => {
19
+ return uiCustomizer.isSidebarMini ? "mdi-menu-close" : "mdi-menu-open";
20
+ });
21
+
22
+ const handleClick = () => {
23
+ uiCustomizer.SET_IS_SIDEBAR_MINI(!uiCustomizer.isSidebarMini);
24
+ };
25
+ </script>
26
+
27
+ <style>
28
+ .btnExtendMenu{color:rgb(var(--v-theme-darkText),.75)}
29
+ </style>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <v-app-bar elevation="0" height="60" color="containerBg">
3
+ <BtnExtendMenu />
4
+ <v-spacer />
5
+ <HeaderMenu />
6
+ </v-app-bar>
7
+ </template>
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <v-menu :close-on-content-click="false" offset="8, 0">
3
+ <template v-slot:activator="{ props }">
4
+ <v-btn
5
+ append-icon="mdi-chevron-down"
6
+ class="profileBtn"
7
+ color="secondary"
8
+ rounded="lg"
9
+ v-bind="props"
10
+ variant="tonal"
11
+ >
12
+ <div class="d-flex align-center">
13
+ <v-avatar class="mr-sm-2 mr-0 py-2">
14
+ <img :src="photoUrl" />
15
+ </v-avatar>
16
+ <span class="text-subtitle-1 mb-0 d-sm-block d-none">
17
+ {{ fullName }}
18
+ </span>
19
+ </div>
20
+ </v-btn>
21
+ </template>
22
+ <v-sheet rounded="md" width="340">
23
+ <HeaderMenuTabs />
24
+ </v-sheet>
25
+ </v-menu>
26
+ </template>
27
+
28
+ <script lang="ts" setup>
29
+ import { ref, onMounted } from "vue";
30
+ import { useAuthStore } from "#imports";
31
+
32
+ const authStore = useAuthStore();
33
+
34
+ const photoUrl = ref("");
35
+ const fullName = ref("");
36
+
37
+ onMounted(() => {
38
+ photoUrl.value = authStore.user?.photoUrl as string;
39
+ fullName.value = authStore.user?.fullName as string;
40
+ });
41
+ </script>
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div>
3
+ <div class="d-flex align-center pa-5">
4
+ <v-avatar size="50" class="mr-4">
5
+ <img :src="photoUrl" width="50" alt="User" />
6
+ </v-avatar>
7
+ <div>
8
+ <span class="text-h6 mb-0">{{ fullName }}</span>
9
+ <p class="text-caption mb-0">{{ email }}</p>
10
+ <p class="text-caption mb-0">{{ role }}</p>
11
+ </div>
12
+ </div>
13
+ <v-tabs v-model="tabSelected" color="primary" grow>
14
+ <v-tab value="tabProfile" prepend-icon="mdi-account" class="v-text-field">
15
+ Perfil
16
+ </v-tab>
17
+ <v-tab value="tabConfig" prepend-icon="mdi-cog" class="v-text-field">
18
+ Configuración
19
+ </v-tab>
20
+ </v-tabs>
21
+ <perfect-scrollbar>
22
+ <v-window v-model="tabSelected">
23
+ <v-window-item value="tabProfile">
24
+ <v-list class="py-0" aria-label="profile list" aria-busy="true">
25
+ <v-list-item
26
+ @click.stop="navigateTo('/profile')"
27
+ color="primary"
28
+ prepend-icon="mdi-account"
29
+ rounded="0"
30
+ value="View Profile"
31
+ >
32
+ <v-list-item-title class="text-subtitle-2">
33
+ Ver Perfil
34
+ </v-list-item-title>
35
+ </v-list-item>
36
+
37
+ <v-list-item
38
+ @click.stop="authStore.logout()"
39
+ color="primary"
40
+ prepend-icon="mdi-logout"
41
+ rounded="0"
42
+ >
43
+ <v-list-item-title class="text-subtitle-2">
44
+ {{ $t("Actions.CloseSession") }}
45
+ </v-list-item-title>
46
+ </v-list-item>
47
+ </v-list>
48
+ </v-window-item>
49
+
50
+ <v-window-item value="tabConfig">
51
+ <v-list class="py-0" aria-label="profile list" aria-busy="true">
52
+ <v-list-item
53
+ @click.stop="navigateTo('/configuration/preferences')"
54
+ color="primary"
55
+ prepend-icon="mdi-account-cog"
56
+ rounded="0"
57
+ value="Preferencias"
58
+ >
59
+ <v-list-item-title class="text-subtitle-2">
60
+ Preferencias de la cuenta
61
+ </v-list-item-title>
62
+ </v-list-item>
63
+
64
+ <v-list-item
65
+ @click.stop="navigateTo('/configuration/support')"
66
+ color="primary"
67
+ prepend-icon="mdi-help-circle"
68
+ rounded="0"
69
+ value="Soporte"
70
+ >
71
+ <v-list-item-title class="text-subtitle-2">
72
+ Soporte
73
+ </v-list-item-title>
74
+ </v-list-item>
75
+ </v-list>
76
+ </v-window-item>
77
+ </v-window>
78
+ </perfect-scrollbar>
79
+ </div>
80
+ </template>
81
+
82
+ <script lang="ts" setup>
83
+ import { navigateTo } from "#imports";
84
+ import { ref, onMounted } from "vue";
85
+ import { useAuthStore } from "#imports";
86
+
87
+ const authStore = useAuthStore();
88
+
89
+ const tabSelected = ref(null);
90
+
91
+ const photoUrl = ref("");
92
+ const fullName = ref("");
93
+ const email = ref("");
94
+ const role = ref("");
95
+
96
+ onMounted(() => {
97
+ photoUrl.value = authStore.user?.photoUrl as string;
98
+ fullName.value = authStore.user?.fullName as string;
99
+ email.value = authStore.user?.email as string;
100
+ role.value = authStore.user?.mainRole as string;
101
+ });
102
+ </script>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <v-list-group no-action>
3
+ <!-- El combo padre -->
4
+ <template v-slot:activator="{ props }">
5
+ <v-list-item
6
+ v-bind="props"
7
+ :value="item?.title"
8
+ rounded
9
+ class="mb-1"
10
+ color="primary"
11
+ :prepend-icon="item?.icon"
12
+ >
13
+ <v-list-item-title class="mr-auto">{{ item?.title }}</v-list-item-title>
14
+
15
+ <v-list-item-subtitle
16
+ v-if="item?.description"
17
+ class="text-caption mt-n1 hide-menu"
18
+ >
19
+ {{ item.description }}
20
+ </v-list-item-subtitle>
21
+ </v-list-item>
22
+ </template>
23
+
24
+ <!-- Se renderizan los elementos hijos -->
25
+ <template v-for="(subitem, i) in item?.children" :key="i">
26
+ <NavCollapse
27
+ v-if="subitem.children"
28
+ :item="subitem"
29
+ :level="(props?.level) as number + 1"
30
+ />
31
+ <NavItem v-else :item="subitem" :level="(props?.level) as number + 1" />
32
+ </template>
33
+ </v-list-group>
34
+ </template>
35
+
36
+ <script lang="ts" setup>
37
+ const props = defineProps({ item: Object, level: Number });
38
+ </script>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <v-list-subheader color="lightText" class="smallCap text-subtitle-2">
3
+ {{ props.item?.header }}
4
+ </v-list-subheader>
5
+ </template>
6
+
7
+ <script lang="ts" setup>
8
+ const props = defineProps({ item: Object });
9
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <v-list-item
3
+ :to="item?.to"
4
+ rounded
5
+ color="primary"
6
+ :disabled="item?.disabled"
7
+ >
8
+ <template v-slot:prepend>
9
+ <v-icon v-if="props.item?.icon" :icon="props.item.icon" />
10
+ </template>
11
+
12
+ <v-list-item-title>{{ item?.title }}</v-list-item-title>
13
+
14
+ <v-list-item-subtitle
15
+ v-if="item?.description"
16
+ class="text-caption mt-n1 hide-menu"
17
+ >
18
+ {{ item.description }}
19
+ </v-list-item-subtitle>
20
+ </v-list-item>
21
+ </template>
22
+
23
+ <script lang="ts" setup>
24
+ const props = defineProps({ item: Object, level: Number });
25
+ </script>
@@ -0,0 +1,74 @@
1
+ <template>
2
+ <div>
3
+ <v-navigation-drawer
4
+ :rail="uiCustomizer.isSidebarMini"
5
+ @mouseleave="isHoveringSideBar = false"
6
+ @mouseover="isHoveringSideBar = true"
7
+ app
8
+ border="darkText"
9
+ class="leftSidebar"
10
+ color="containerBg"
11
+ elevation="0"
12
+ expand-on-hover
13
+ left
14
+ mobile-breakpoint="lg"
15
+ rail-width="60"
16
+ v-model="uiCustomizer.drawSidebar"
17
+ >
18
+ <template v-slot:prepend>
19
+ <div class="d-flex align-center justify-center" style="height: 60px">
20
+ <TopSideBarLogo v-model:open-sidebar="isHoveringSideBar" />
21
+ </div>
22
+ <v-divider :thickness="1" />
23
+ </template>
24
+
25
+ <perfect-scrollbar class="scrollnavbar">
26
+ <v-list
27
+ aria-busy="true"
28
+ aria-label="menu list"
29
+ v-model:opened="openedMenus"
30
+ >
31
+ <template v-for="(item, i) in menuItems" :key="i">
32
+ <NavGroup :item v-if="item?.header" :key="item.title" />
33
+
34
+ <v-divider class="my-3" v-else-if="item?.divider" />
35
+
36
+ <NavCollapse
37
+ :item
38
+ :level="0"
39
+ class="leftPadding"
40
+ v-else-if="item?.children"
41
+ />
42
+
43
+ <NavItem :item v-else />
44
+ </template>
45
+ </v-list>
46
+ </perfect-scrollbar>
47
+
48
+ <template v-slot:append>
49
+ <SideBarFooter v-model:open-sidebar="isHoveringSideBar" />
50
+ </template>
51
+ </v-navigation-drawer>
52
+ </div>
53
+ </template>
54
+
55
+ <script lang="ts" setup>
56
+ import { ref, shallowRef, watch } from "vue";
57
+ import { storeToRefs } from "pinia";
58
+ import { useAuthorization } from "../../../composables/useAuthorization";
59
+ import { useUiCustomizerStore } from "../../../stores/UiCustomizer";
60
+
61
+ const authorization = useAuthorization();
62
+ const uiCustomizer = useUiCustomizerStore();
63
+
64
+ const isHoveringSideBar = ref(false);
65
+ const openedMenus = ref([]);
66
+
67
+ const menuItems = shallowRef(authorization.getAuthorizedPaths());
68
+
69
+ const uiCustomizerRef = storeToRefs(uiCustomizer);
70
+
71
+ watch(uiCustomizerRef.isSidebarMini, (newValue, oldValue) => {
72
+ if (newValue) openedMenus.value = [];
73
+ });
74
+ </script>
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <div class="SideBarFooter pb-4">
3
+ <v-spacer />
4
+
5
+ <v-divider :thickness="1" />
6
+
7
+ <v-list aria-busy="true" aria-label="sidebar footer">
8
+ <!-- Toogle Theme Switcher -->
9
+ <v-list-item rounded>
10
+ <template v-slot:prepend>
11
+ <v-icon :icon="toggleThemeIcon" />
12
+ </template>
13
+ <template v-slot:append>
14
+ <v-switch
15
+ :false-value="ETheme.LIGHT"
16
+ :true-value="ETheme.DARK"
17
+ color="primary"
18
+ hide-details
19
+ v-if="!uiCustomizer.isSidebarMini || openSidebar"
20
+ v-model="currentTheme"
21
+ />
22
+ </template>
23
+ <v-list-item-title>{{ toggleThemeTitle }}</v-list-item-title>
24
+ </v-list-item>
25
+
26
+ <!-- Close Session Button -->
27
+ <v-list-item rounded @click="authStore.logout()">
28
+ <template v-slot:prepend>
29
+ <v-icon icon="mdi-logout" />
30
+ </template>
31
+ <v-list-item-title> {{ $t("Actions.CloseSession") }}</v-list-item-title>
32
+ </v-list-item>
33
+ </v-list>
34
+ </div>
35
+ </template>
36
+
37
+ <script lang="ts" setup>
38
+ import { computed, ref, watch } from "vue";
39
+ import { ETheme } from "../../../enums";
40
+ import { useAuthStore, useI18n } from "#imports";
41
+ import { useUiCustomizerStore } from "../../../stores/UiCustomizer";
42
+
43
+ import { useTheme } from "vuetify";
44
+
45
+ const { t } = useI18n();
46
+ const theme = useTheme();
47
+ const authStore = useAuthStore();
48
+ const uiCustomizer = useUiCustomizerStore();
49
+
50
+ const openSidebar = defineModel<boolean>("openSidebar", { required: true });
51
+
52
+ const currentTheme = ref(ETheme.LIGHT);
53
+
54
+ const toggleThemeTitle = computed(() => {
55
+ return currentTheme.value == ETheme.DARK
56
+ ? t("Components.SideBar.SideBarFooter.DarkTheme")
57
+ : t("Components.SideBar.SideBarFooter.LightTheme");
58
+ });
59
+
60
+ const toggleThemeIcon = computed(() => {
61
+ return currentTheme.value == ETheme.DARK
62
+ ? "mdi-moon-waning-crescent"
63
+ : "mdi-white-balance-sunny";
64
+ });
65
+
66
+ watch(currentTheme, (newValue, oldValue) => {
67
+ theme.global.name.value = newValue;
68
+ });
69
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <div class="d-flex justify-center">
3
+ <NuxtLink to="/" style="text-decoration: none; color: inherit">
4
+ <img
5
+ v-if="!uiCustomizer.isSidebarMini || openSidebar"
6
+ alt=""
7
+ height="40"
8
+ src="/images/logos/UNA_LogoType_LogoMark_Red.png"
9
+ />
10
+ <img
11
+ v-else
12
+ alt=""
13
+ height="25"
14
+ src="/images/logos/UNA_LogoMark_Black.png"
15
+ />
16
+ </NuxtLink>
17
+ </div>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import { useUiCustomizerStore } from "../../../stores/UiCustomizer";
22
+
23
+ const uiCustomizer = useUiCustomizerStore();
24
+ const openSidebar = defineModel<boolean>("openSidebar", { required: true });
25
+ </script>
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <template v-if="renderContent()">
3
+ <slot />
4
+ <div>{{ props }}</div>
5
+ </template>
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import type { PropType } from "vue";
10
+ import { useAuthorization } from "../../../composables/useAuthorization";
11
+ import type { TAuthorization } from "../../../types";
12
+
13
+ const props = defineProps({
14
+ /** Renderiza si el usuario no tiene la autorización en el recurso. */
15
+ renderIfUnauthorized: { type: Boolean, required: false, default: false },
16
+ /** Autorización a validar en el recurso. */
17
+ authorization: { type: String as PropType<TAuthorization>, required: true },
18
+ /** Recurso a validar. */
19
+ resource: { type: String, required: false },
20
+ });
21
+
22
+ /**
23
+ * Método que valida si el contenido se debe renderizar.
24
+ */
25
+ const renderContent = (): boolean => {
26
+ // Si el recurso no esta definido por props toma la ruta actual como recurso
27
+ const resource = props.resource ?? useAuthorization().currentResource.value;
28
+
29
+ // Valida si el usuario tiene la autorización en el recurso
30
+ const hasAuthorization = useAuthorization().hasAuthorizationIn({
31
+ authorization: props.authorization,
32
+ resource,
33
+ });
34
+
35
+ if (props.renderIfUnauthorized) {
36
+ return !hasAuthorization;
37
+ }
38
+
39
+ return hasAuthorization;
40
+ };
41
+ </script>
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <v-btn
3
+ :text="$t('Actions.Back')"
4
+ :to="props.to"
5
+ class="text-none text-subtitle-1"
6
+ color="primary"
7
+ variant="outlined"
8
+ >
9
+ <template v-slot:prepend>
10
+ <v-icon icon="mdi-arrow-left" start size="x-large" class="mx-0" />
11
+ </template>
12
+ </v-btn>
13
+ </template>
14
+
15
+ <script lang="ts" setup>
16
+ const props = defineProps({
17
+ to: { type: String, required: true },
18
+ });
19
+ </script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <v-btn
3
+ :text="$t('Actions.Cancel')"
4
+ @click="emit('on-cancel')"
5
+ color="primary"
6
+ elevation="0"
7
+ variant="text"
8
+ />
9
+ </template>
10
+
11
+ <script lang="ts" setup>
12
+ const emit = defineEmits(["on-cancel"]);
13
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <v-btn
3
+ :text="$t('Actions.Confirm')"
4
+ @click="emit('on-confirm')"
5
+ color="primary"
6
+ elevation="1"
7
+ prepend-icon="mdi-check"
8
+ variant="flat"
9
+ />
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ const emit = defineEmits(["on-confirm"]);
14
+ </script>