change layout and add component
This commit is contained in:
parent
46b84b1535
commit
9662587eda
4140
assets/img/logo/logo-imigresen.svg
Normal file
4140
assets/img/logo/logo-imigresen.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 353 KiB |
9
assets/img/logo/niise-logo.svg
Normal file
9
assets/img/logo/niise-logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 13 KiB |
9
assets/img/logo/niise-text.svg
Normal file
9
assets/img/logo/niise-text.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 16 KiB |
7126
assets/json/iconamoon.json
Normal file
7126
assets/json/iconamoon.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
html[data-theme="default"] {
|
html[data-theme="default"] {
|
||||||
--color-primary: 13, 27, 42;
|
--color-primary: 0, 165, 154;
|
||||||
--color-secondary: 97, 176, 183;
|
--color-secondary: 97, 176, 183;
|
||||||
--color-accent: 243, 244, 246;
|
--color-accent: 243, 244, 246;
|
||||||
--color-success: 79, 192, 103;
|
--color-success: 79, 192, 103;
|
||||||
@ -10,6 +10,11 @@ html[data-theme="default"] {
|
|||||||
--border-color: 228, 228, 231;
|
--border-color: 228, 228, 231;
|
||||||
--bg-1: 243, 244, 246;
|
--bg-1: 243, 244, 246;
|
||||||
--bg-2: 255, 255, 255;
|
--bg-2: 255, 255, 255;
|
||||||
|
--sidebar: 38, 50, 55;
|
||||||
|
--sidebar-menu: 26, 35, 38;
|
||||||
|
--sidebar-text: 255, 255, 255;
|
||||||
|
--header: 49, 65, 71;
|
||||||
|
--header-text: 255, 255, 255;
|
||||||
--scroll-color: 170, 170, 170;
|
--scroll-color: 170, 170, 170;
|
||||||
--scroll-hover-color: 155, 155, 155;
|
--scroll-hover-color: 155, 155, 155;
|
||||||
--fk-border-color: 228, 228, 231;
|
--fk-border-color: 228, 228, 231;
|
||||||
|
@ -26,3 +26,7 @@
|
|||||||
.badge.badge-danger {
|
.badge.badge-danger {
|
||||||
@apply bg-danger text-white;
|
@apply bg-danger text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.badge.badge-disabled {
|
||||||
|
@apply bg-gray-300 text-gray-600;
|
||||||
|
}
|
||||||
|
@ -5,7 +5,8 @@ body {
|
|||||||
|
|
||||||
.w-header {
|
.w-header {
|
||||||
@apply z-20 fixed top-0 right-0 px-5 py-3 duration-300 shadow-md;
|
@apply z-20 fixed top-0 right-0 px-5 py-3 duration-300 shadow-md;
|
||||||
background-color: rgb(var(--bg-2));
|
background-color: rgb(var(--header));
|
||||||
|
color: rgb(var(--header-text));
|
||||||
box-shadow: var(--box-shadow);
|
box-shadow: var(--box-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,7 +17,8 @@ body {
|
|||||||
|
|
||||||
.vertical-menu {
|
.vertical-menu {
|
||||||
@apply text-base h-screen fixed w-64 top-0 z-50 duration-300 border-l-0 shadow-md;
|
@apply text-base h-screen fixed w-64 top-0 z-50 duration-300 border-l-0 shadow-md;
|
||||||
background-color: rgb(var(--bg-2));
|
background-color: rgb(var(--sidebar));
|
||||||
|
color: rgb(var(--sidebar-text));
|
||||||
box-shadow: var(--box-shadow);
|
box-shadow: var(--box-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,17 +28,13 @@ body {
|
|||||||
justify-center
|
justify-center
|
||||||
transition-colors
|
transition-colors
|
||||||
duration-300;
|
duration-300;
|
||||||
color: rgb(var(--text-color));
|
color: rgb(var(--header-text));
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-btn.profile {
|
.icon-btn.profile {
|
||||||
@apply border;
|
color: rgb(var(--header-text));
|
||||||
border-radius: var(--rounded-box);
|
|
||||||
border: 1px solid rgb(var(--border-color));
|
|
||||||
color: rgb(var(--text-color));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-btn:hover {
|
.icon-btn:hover {
|
||||||
color: rgb(var(--text-color));
|
background-color: rgb(var(--sidebar));
|
||||||
background-color: rgb(var(--bg-1));
|
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,18 @@
|
|||||||
Notes: This file is the main entry point for the SCSS stylesheet.
|
Notes: This file is the main entry point for the SCSS stylesheet.
|
||||||
================================================================================*/
|
================================================================================*/
|
||||||
|
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300..700&display=swap");
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#__nuxt {
|
#__nuxt {
|
||||||
font-family: "Space Grotesk", sans-serif;
|
font-family: "Roboto", sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,12 +15,9 @@ const refreshPage = () => {
|
|||||||
<div class="rs-loading bg-white absolute z-50 top-0 left-0 w-full h-full">
|
<div class="rs-loading bg-white absolute z-50 top-0 left-0 w-full h-full">
|
||||||
<div class="flex justify-center text-center items-center h-screen">
|
<div class="flex justify-center text-center items-center h-screen">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex justify-center items-center">
|
<div class="img-container flex justify-center items-center mb-5">
|
||||||
<img
|
<img src="@/assets/img/logo/niise-logo.svg" class="max-w-[60px]" />
|
||||||
src="@/assets/img/logo/logo-nobg.svg"
|
<img src="@/assets/img/logo/niise-text.svg" class="max-w-[120px]" />
|
||||||
class="w-[50px] mb-5"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -25,6 +25,7 @@ const props = defineProps({
|
|||||||
'badge-success': variant === 'success',
|
'badge-success': variant === 'success',
|
||||||
'badge-warning': variant === 'warning',
|
'badge-warning': variant === 'warning',
|
||||||
'badge-danger': variant === 'danger',
|
'badge-danger': variant === 'danger',
|
||||||
|
'badge-disabled': variant === 'disabled',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Icon v-if="icon" :name="icon" :size="iconSize"></Icon>
|
<Icon v-if="icon" :name="icon" :size="iconSize"></Icon>
|
||||||
|
@ -12,12 +12,17 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: "md",
|
default: "md",
|
||||||
},
|
},
|
||||||
|
btnType: {
|
||||||
|
type: String,
|
||||||
|
default: "button",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="button"
|
class="button"
|
||||||
|
:type="btnType"
|
||||||
:class="{
|
:class="{
|
||||||
'button-sm': size === 'sm',
|
'button-sm': size === 'sm',
|
||||||
'button-md': size === 'md',
|
'button-md': size === 'md',
|
||||||
|
@ -1,17 +1,39 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
// Get breadcrumb from page meta
|
||||||
const breadcrumb = computed(() => {
|
const breadcrumb = computed(() => {
|
||||||
|
let breadcrumb = null;
|
||||||
const matched = route.matched;
|
const matched = route.matched;
|
||||||
const breadcrumb = matched.map((item) => {
|
|
||||||
|
if (matched[matched.length - 1].meta?.breadcrumb) {
|
||||||
|
breadcrumb = matched[matched.length - 1].meta.breadcrumb;
|
||||||
|
} else {
|
||||||
|
// if no breadcrumb in page meta, get breadcrumb from route matched
|
||||||
|
breadcrumb = matched.map((item) => {
|
||||||
return {
|
return {
|
||||||
name: item.meta.title,
|
name: item.meta.title,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return breadcrumb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if type current overwrite path to its own path
|
||||||
|
if (breadcrumb) {
|
||||||
|
breadcrumb.forEach((item) => {
|
||||||
|
if (item.type == "current") {
|
||||||
|
item.path = route.path;
|
||||||
|
} else if (item.type == "parent") {
|
||||||
|
item.path = route.path.split("/").slice(0, -item.parentNo).join("/");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return breadcrumb;
|
return breadcrumb;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get title from page meta
|
||||||
const title = computed(() => {
|
const title = computed(() => {
|
||||||
const matched = route.matched;
|
const matched = route.matched;
|
||||||
const title = matched[matched.length - 1].meta.title;
|
const title = matched[matched.length - 1].meta.title;
|
||||||
@ -28,32 +50,43 @@ async function navigateMenu(path) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div v-if="breadcrumb" class="mb-6">
|
||||||
v-if="breadcrumb && title"
|
<nav aria-label="Breadcrumb" class="mb-4">
|
||||||
class="flex flex-col md:flex-row items-stretch justify-between pb-5"
|
<ol class="flex items-center text-sm">
|
||||||
>
|
<li class="flex items-center">
|
||||||
<span class="text-xl font-semibold">{{ title }}</span>
|
<NuxtLink to="/" class="text-gray-500 hover:text-gray-700">
|
||||||
<div
|
<Icon name="mdi:home" size="16" />
|
||||||
class="flex items-center text-sm"
|
</NuxtLink>
|
||||||
v-if="breadcrumb && breadcrumb.length != 0"
|
</li>
|
||||||
>
|
<li
|
||||||
<span
|
|
||||||
v-for="(item, index) in breadcrumb"
|
v-for="(item, index) in breadcrumb"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="flex items-center text-primary"
|
class="flex items-center"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="index != 0"
|
name="mdi:chevron-right"
|
||||||
name="ic:round-chevron-right"
|
size="16"
|
||||||
size="14"
|
class="mx-2 text-gray-400"
|
||||||
class="pr-1"
|
aria-hidden="true"
|
||||||
></Icon>
|
/>
|
||||||
<a
|
<a
|
||||||
@click="navigateMenu(item.path)"
|
@click="navigateMenu(item.path)"
|
||||||
class="underline cursor-pointer hover:text-primary/90 pr-1"
|
:class="{
|
||||||
>{{ item.name }}</a
|
'text-gray-500 hover:text-gray-700':
|
||||||
|
index !== breadcrumb.length - 1,
|
||||||
|
'text-primary font-medium': index === breadcrumb.length - 1,
|
||||||
|
}"
|
||||||
|
:aria-current="index === breadcrumb.length - 1 ? 'page' : undefined"
|
||||||
>
|
>
|
||||||
</span>
|
{{ item.name }}
|
||||||
</div>
|
</a>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- <div class="flex justify-between items-center">
|
||||||
|
<h1 class="text-2xl font-semibold text-gray-800">{{ title }}</h1>
|
||||||
|
<slot name="right"></slot>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -85,60 +85,6 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex gap-2 item-center justify-items-end">
|
<div class="flex gap-2 item-center justify-items-end">
|
||||||
<VDropdown placement="bottom-end" distance="13" name="language">
|
|
||||||
<button class="icon-btn h-10 w-10 rounded-full">
|
|
||||||
<country-flag :country="languageNow.flagCode" />
|
|
||||||
</button>
|
|
||||||
<template #popper>
|
|
||||||
<ul class="header-dropdown w-full md:w-32">
|
|
||||||
<li
|
|
||||||
v-for="lang in langList"
|
|
||||||
class="flex items-center justify-center hover:bg-[rgb(var(--bg-1))]"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
@click="changeLanguage(lang.value)"
|
|
||||||
class="w-full py-2 px-2 flex justify-center items-center h-10"
|
|
||||||
>
|
|
||||||
<div class="ml-3 flex justify-center items-center">
|
|
||||||
<country-flag :country="lang.flagCode" />
|
|
||||||
</div>
|
|
||||||
<span class="grow">{{ lang.name }}</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</VDropdown>
|
|
||||||
<VDropdown placement="bottom-end" distance="13" name="theme">
|
|
||||||
<button class="icon-btn h-10 w-10 rounded-full">
|
|
||||||
<Icon size="22px" name="material-symbols:format-paint-rounded" />
|
|
||||||
</button>
|
|
||||||
<template #popper>
|
|
||||||
<ul class="header-dropdown w-full md:w-52">
|
|
||||||
<li v-for="(val, index) in themes">
|
|
||||||
<a
|
|
||||||
@click="setTheme(val.theme)"
|
|
||||||
class="flex justify-between items-center cursor-pointer py-2 px-4 hover:bg-[rgb(var(--bg-1))]"
|
|
||||||
>
|
|
||||||
<span class="capitalize"> {{ val.theme }} </span>
|
|
||||||
<div class="flex items-center gap-x-1">
|
|
||||||
<div
|
|
||||||
v-for="(color, index) in val.colors"
|
|
||||||
class="h-[25px] w-[10px] rounded-lg"
|
|
||||||
:style="{
|
|
||||||
backgroundColor: rgbToHex(color.value),
|
|
||||||
}"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
</VDropdown>
|
|
||||||
|
|
||||||
<button @click="toggleSearch" class="icon-btn h-10 w-10 rounded-full">
|
|
||||||
<Icon name="ic:round-search" class="" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<VDropdown placement="bottom-end" distance="13" name="notification">
|
<VDropdown placement="bottom-end" distance="13" name="notification">
|
||||||
<button class="relative icon-btn h-10 w-10 rounded-full">
|
<button class="relative icon-btn h-10 w-10 rounded-full">
|
||||||
<span
|
<span
|
||||||
@ -202,7 +148,12 @@ onMounted(() => {
|
|||||||
</template>
|
</template>
|
||||||
</VDropdown>
|
</VDropdown>
|
||||||
|
|
||||||
<VDropdown placement="bottom-end" distance="13" name="profile">
|
<VDropdown
|
||||||
|
placement="bottom-end"
|
||||||
|
distance="13"
|
||||||
|
name="profile"
|
||||||
|
class="flex justify-center item-center"
|
||||||
|
>
|
||||||
<button class="icon-btn profile px-2">
|
<button class="icon-btn profile px-2">
|
||||||
<img
|
<img
|
||||||
class="w-8 h-8 object-cover rounded-full"
|
class="w-8 h-8 object-cover rounded-full"
|
||||||
@ -212,10 +163,7 @@ onMounted(() => {
|
|||||||
v-if="isDesktop"
|
v-if="isDesktop"
|
||||||
class="grid grid-cols-1 text-left ml-3 flex-none"
|
class="grid grid-cols-1 text-left ml-3 flex-none"
|
||||||
>
|
>
|
||||||
<p class="font-semibold text-sm truncate w-24 mb-0">John Doe</p>
|
<p class="font-semibold text-sm truncate w-24 mb-0">Johan</p>
|
||||||
<span class="font-medium text-xs truncate w-24"
|
|
||||||
>RM 10,000.00</span
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<Icon name="ic:outline-keyboard-arrow-down" class="ml-3" />
|
<Icon name="ic:outline-keyboard-arrow-down" class="ml-3" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -62,15 +62,8 @@ function openMenu(event) {
|
|||||||
// Active menu
|
// Active menu
|
||||||
function activeMenu(routePath) {
|
function activeMenu(routePath) {
|
||||||
return route.path == routePath
|
return route.path == routePath
|
||||||
? ` shadow-lg
|
? `bg-[rgb(var(--color-primary))] font-normal text-white active-menu`
|
||||||
shadow-primary/50
|
: `font-light text-white/90 md:transition-all md:duration-200 hover:md:ml-2`;
|
||||||
dark:shadow-primary/10
|
|
||||||
text-white
|
|
||||||
bg-gradient-to-r
|
|
||||||
from-primary
|
|
||||||
to-primary/90
|
|
||||||
active-menu`
|
|
||||||
: `transition-all duration-300 hover:ml-4`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMenu() {
|
function toggleMenu() {
|
||||||
@ -98,10 +91,10 @@ function navigationPage(path, external) {
|
|||||||
v-if="item.header"
|
v-if="item.header"
|
||||||
class="text-left font-normal text-xs mx-6 mt-5 mb-2"
|
class="text-left font-normal text-xs mx-6 mt-5 mb-2"
|
||||||
>
|
>
|
||||||
<span class="uppercase text-primary dark:text-primary">
|
<span class="uppercase text-gray-400">
|
||||||
{{ item.header ? item.header : "" }}
|
{{ item.header ? item.header : "" }}
|
||||||
</span>
|
</span>
|
||||||
<p class="text-gray-500 dark:text-gray-500">
|
<p class="text-gray-400">
|
||||||
{{ item.description ? item.description : "" }}
|
{{ item.description ? item.description : "" }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -130,7 +123,7 @@ function navigationPage(path, external) {
|
|||||||
item2.child === undefined ||
|
item2.child === undefined ||
|
||||||
(item2.child && item2.child.length === 0)
|
(item2.child && item2.child.length === 0)
|
||||||
"
|
"
|
||||||
class="flex items-center px-4 py-3 mx-3 rounded-lg cursor-pointer"
|
class="flex items-center px-6 py-3 cursor-pointer"
|
||||||
@click="navigationPage(item2.path, item2.external)"
|
@click="navigationPage(item2.path, item2.external)"
|
||||||
:class="activeMenu(item2.path)"
|
:class="activeMenu(item2.path)"
|
||||||
>
|
>
|
||||||
@ -146,7 +139,7 @@ function navigationPage(path, external) {
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<a
|
<a
|
||||||
v-else
|
v-else
|
||||||
class="flex items-center px-4 py-3 mx-3 rounded-lg cursor-pointer"
|
class="flex items-center px-6 py-3 rounded-lg cursor-pointer"
|
||||||
:class="activeMenu(item2.path)"
|
:class="activeMenu(item2.path)"
|
||||||
>
|
>
|
||||||
<Icon v-if="item2.icon" :name="item2.icon" size="18"></Icon>
|
<Icon v-if="item2.icon" :name="item2.icon" size="18"></Icon>
|
||||||
|
@ -17,7 +17,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
indent: {
|
indent: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 0.2,
|
default: 0.5,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const emit = defineEmits(["openMenu"]);
|
const emit = defineEmits(["openMenu"]);
|
||||||
@ -61,15 +61,8 @@ function openMenu(event) {
|
|||||||
// Active menu
|
// Active menu
|
||||||
function activeMenu(routePath) {
|
function activeMenu(routePath) {
|
||||||
return route.path == routePath
|
return route.path == routePath
|
||||||
? ` shadow-lg
|
? `bg-[rgb(var(--color-primary))] font-normal text-white active-menu`
|
||||||
shadow-primary/50
|
: `font-light text-white/90 md:transition-all md:duration-200 hover:md:ml-2`;
|
||||||
dark:shadow-primary/10
|
|
||||||
text-white
|
|
||||||
bg-gradient-to-r
|
|
||||||
from-primary
|
|
||||||
to-primary/90
|
|
||||||
active-menu`
|
|
||||||
: `transition-all duration-300 hover:ml-4`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleMenu() {
|
function toggleMenu() {
|
||||||
@ -85,7 +78,7 @@ function navigationPage(path, external) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const indentStyle = computed(() => {
|
const indentStyle = computed(() => {
|
||||||
return { "background-color": `rgba(var(--bg-1), ${indent.value})` };
|
return { "background-color": `rgba(var(--sidebar-menu), ${indent.value})` };
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -113,7 +106,7 @@ const indentStyle = computed(() => {
|
|||||||
v-if="
|
v-if="
|
||||||
item.child === undefined || (item.child && item.child.length === 0)
|
item.child === undefined || (item.child && item.child.length === 0)
|
||||||
"
|
"
|
||||||
class="flex items-center px-4 py-3 mx-3 rounded-lg cursor-pointer"
|
class="flex items-center px-6 py-3 cursor-pointer"
|
||||||
@click="navigationPage(item.path, item.external)"
|
@click="navigationPage(item.path, item.external)"
|
||||||
:class="activeMenu(item.path)"
|
:class="activeMenu(item.path)"
|
||||||
>
|
>
|
||||||
@ -128,7 +121,7 @@ const indentStyle = computed(() => {
|
|||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<a
|
<a
|
||||||
v-else
|
v-else
|
||||||
class="flex items-center px-4 py-3 mx-3 rounded-lg cursor-pointer"
|
class="flex items-center px-6 py-3 rounded-lg cursor-pointer"
|
||||||
:class="activeMenu(item.path)"
|
:class="activeMenu(item.path)"
|
||||||
>
|
>
|
||||||
<span class="mx-3 font-normal">{{ item.title }}</span>
|
<span class="mx-3 font-normal">{{ item.title }}</span>
|
||||||
|
@ -31,14 +31,15 @@ onMounted(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="vertical-menu">
|
<div class="vertical-menu">
|
||||||
<div class="py-2 px-4">
|
<div class="py-2 px-4 bg-[rgb(var(--header))]">
|
||||||
<nuxt-link to="/">
|
<nuxt-link to="/">
|
||||||
<div class="flex flex-auto gap-3 justify-center items-center h-[48px]">
|
<div class="flex flex-auto gap-3 justify-center items-center h-[48px]">
|
||||||
<img
|
<img
|
||||||
class="h-10 block"
|
class="h-8 block"
|
||||||
src="@/assets/img/logo/logo-word-black.svg"
|
src="@/assets/img/logo/logo-imigresen.svg"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
|
<span class="text-xs">Jabatan Imigresen Malaysia</span>
|
||||||
</div>
|
</div>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
header: "",
|
header: "Utama",
|
||||||
description: "",
|
description: "",
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
@ -10,11 +10,64 @@ export default [
|
|||||||
child: [],
|
child: [],
|
||||||
meta: {},
|
meta: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Carian",
|
||||||
|
path: "/carian",
|
||||||
|
icon: "ph:magnifying-glass",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Laporan",
|
||||||
|
path: "/laporan",
|
||||||
|
icon: "ph:chart-bar-fill",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Fungsi",
|
||||||
|
description: "",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
title: "Komponen",
|
||||||
|
icon: "ph:gear-fine",
|
||||||
|
child: [
|
||||||
|
{
|
||||||
|
title: "Butang",
|
||||||
|
path: "/komponen/butang",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Modal",
|
||||||
|
path: "/komponen/modal",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Data Table",
|
||||||
|
path: "/komponen/datatable",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Ikon",
|
||||||
|
path: "/ikon",
|
||||||
|
icon: "iconamoon:slightly-smiling-face",
|
||||||
|
child: [],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
meta: {},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
header: "Administration",
|
header: "Administration",
|
||||||
description: "Manage your application",
|
description: "",
|
||||||
child: [
|
child: [
|
||||||
{
|
{
|
||||||
title: "Configuration",
|
title: "Configuration",
|
||||||
@ -78,27 +131,4 @@ export default [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
header: "Help",
|
|
||||||
description: "Help and documentation",
|
|
||||||
child: [
|
|
||||||
{
|
|
||||||
title: "Documentation",
|
|
||||||
icon: "solar:book-bookmark-minimalistic-bold",
|
|
||||||
path: "https://mawar-cms-docs.vercel.app",
|
|
||||||
external: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "UI Components",
|
|
||||||
icon: "material-symbols:settings-input-component-outline-rounded",
|
|
||||||
path: "https://corradui.datasc.dev",
|
|
||||||
external: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
meta: {
|
|
||||||
auth: {
|
|
||||||
role: ["Developer"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"vue3-apexcharts": "^1.4.1",
|
"vue3-apexcharts": "^1.4.1",
|
||||||
"vue3-click-away": "^1.2.4",
|
"vue3-click-away": "^1.2.4",
|
||||||
"vue3-dropzone": "^2.0.1",
|
"vue3-dropzone": "^2.0.1",
|
||||||
|
"vue3-recaptcha-v2": "^2.0.2",
|
||||||
"vuedraggable": "^4.1.0"
|
"vuedraggable": "^4.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
122
pages/carian/index.vue
Normal file
122
pages/carian/index.vue
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
title: "Carian",
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Carian",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const categories = ref([
|
||||||
|
"Semua Kategori",
|
||||||
|
"Kategori 1",
|
||||||
|
"Kategori 2",
|
||||||
|
"Kategori 3",
|
||||||
|
]);
|
||||||
|
const selectedCategory = ref("Semua Kategori");
|
||||||
|
|
||||||
|
const criteria = ref([
|
||||||
|
{ label: "Kriteria 1", options: ["Pilihan 1", "Pilihan 2", "Pilihan 3"] },
|
||||||
|
{ label: "Kriteria 2", options: ["Pilihan A", "Pilihan B", "Pilihan C"] },
|
||||||
|
{ label: "Kriteria 3", options: ["Pilihan X", "Pilihan Y", "Pilihan Z"] },
|
||||||
|
{ label: "Kriteria 4", options: ["Pilihan 1", "Pilihan 2", "Pilihan 3"] },
|
||||||
|
{
|
||||||
|
label: "Kriteria 5",
|
||||||
|
options: ["Pilihan A", "Pilihan B", "Pilihan C"],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const searchQuery = ref("");
|
||||||
|
|
||||||
|
const performSearch = () => {
|
||||||
|
// Implement search logic here
|
||||||
|
console.log("Performing search with:", searchQuery.value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Carian laman </template>
|
||||||
|
<template #body>
|
||||||
|
<FormKit type="form" @submit="performSearch" submit-label="Search">
|
||||||
|
<div class="flex items-center space-x-2 mb-4">
|
||||||
|
<FormKit
|
||||||
|
v-model="searchQuery"
|
||||||
|
type="text"
|
||||||
|
name="search"
|
||||||
|
placeholder="Carian..."
|
||||||
|
:classes="{
|
||||||
|
outer: 'flex-grow',
|
||||||
|
input: 'w-full',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:magnifying-glass"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
<FormKit
|
||||||
|
type="select"
|
||||||
|
v-model="selectedCategory"
|
||||||
|
:options="categories"
|
||||||
|
placeholder="Semua Kategori"
|
||||||
|
:classes="{
|
||||||
|
outer: 'w-48',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-lg font-medium text-gray-700 mb-4">
|
||||||
|
Carian Terperinci
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||||
|
<FormKit
|
||||||
|
v-for="(item, index) in criteria.slice(0, 2)"
|
||||||
|
:key="index"
|
||||||
|
type="select"
|
||||||
|
:name="item.label.toLowerCase().replace(' ', '_')"
|
||||||
|
:label="item.label"
|
||||||
|
:options="item.options"
|
||||||
|
placeholder="Pilih pilihan"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<label
|
||||||
|
class="formkit-label text-gray-700 dark:text-gray-200 block mb-2 font-semibold text-sm formkit-invalid:text-red-500"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-3 gap-4">
|
||||||
|
<FormKit
|
||||||
|
v-for="(item, index) in criteria.slice(2)"
|
||||||
|
:key="index"
|
||||||
|
type="select"
|
||||||
|
:name="item.label.toLowerCase().replace(' ', '_')"
|
||||||
|
:label="item.label"
|
||||||
|
:options="item.options"
|
||||||
|
placeholder="Pilih pilihan"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<label
|
||||||
|
class="formkit-label text-gray-700 dark:text-gray-200 block mb-2 font-semibold text-sm formkit-invalid:text-red-500"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
</FormKit>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -3,6 +3,12 @@ definePageMeta({
|
|||||||
title: "Dashboard",
|
title: "Dashboard",
|
||||||
middleware: ["auth"],
|
middleware: ["auth"],
|
||||||
requiresAuth: true,
|
requiresAuth: true,
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Dashboard",
|
||||||
|
path: "/",
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const data1 = ref([]);
|
const data1 = ref([]);
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
title: "Forgot Password",
|
title: "Reset Password",
|
||||||
layout: "empty",
|
layout: "empty",
|
||||||
middleware: ["dashboard"],
|
middleware: ["dashboard"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const email = ref("");
|
||||||
|
|
||||||
|
const changePassword = () => {
|
||||||
|
// Simulate password change request without API call
|
||||||
|
console.log("Password change requested for email:", email.value);
|
||||||
|
// Add your password change logic here
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -12,31 +20,55 @@ definePageMeta({
|
|||||||
>
|
>
|
||||||
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
||||||
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
||||||
<div
|
<div class="text-center mb-8">
|
||||||
class="absolute -bottom-3 left-3 img-container flex justify-start items-center mb-5"
|
<div class="img-container flex justify-center items-center mb-5">
|
||||||
>
|
<img src="@/assets/img/logo/niise-logo.svg" class="max-w-[60px]" />
|
||||||
<img
|
<img src="@/assets/img/logo/niise-text.svg" class="max-w-[120px]" />
|
||||||
src="@/assets/img/logo/logo-word-black.svg"
|
|
||||||
class="max-w-[90px]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4">Forgot Password</h3>
|
<h2 class="mt-4 text-2xl font-bold text-gray-700">
|
||||||
<p class="text-slate-500 mb-6">
|
Tukar kata laluan
|
||||||
Please input the correct email to reset the password.
|
</h2>
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
Kata laluan sementara akan dihantar ke emel anda.
|
||||||
</p>
|
</p>
|
||||||
<div class="grid grid-cols-1">
|
|
||||||
<FormKit label="Email" type="email" outer-class="text-left" />
|
|
||||||
<NuxtLink to="/reset-password">
|
|
||||||
<FormKit type="button" input-class="w-full">Validate Email</FormKit>
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-3 text-center text-slate-500">
|
|
||||||
Already have an account?
|
<FormKit type="form" :actions="false" @submit="changePassword">
|
||||||
<NuxtLink to="/login" class="text-primary hover:underline"
|
<FormKit
|
||||||
>Login</NuxtLink
|
type="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="Sila masukkan emel anda"
|
||||||
|
validation="required|email"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Emel wajib diisi',
|
||||||
|
email: 'Format emel tidak sah',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
</p>
|
<template #prefix>
|
||||||
|
<Icon
|
||||||
|
name="ph:envelope"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</FormKit>
|
||||||
|
|
||||||
|
<rs-button @click="navigateTo('reset-password')" class="w-full mt-6">
|
||||||
|
<Icon name="ph:lock-fill" class="mr-2" />
|
||||||
|
Tukar kata laluan
|
||||||
|
</rs-button>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
Kembali ke
|
||||||
|
<nuxt-link to="/login" class="text-sm text-blue-500">
|
||||||
|
log masuk
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
</rs-card>
|
</rs-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Add any additional component-specific styles here */
|
||||||
|
</style>
|
||||||
|
117
pages/ikon/index.vue
Normal file
117
pages/ikon/index.vue
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<script setup>
|
||||||
|
import iconJson from "@/assets/json/iconamoon.json";
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
title: "Set Ikons",
|
||||||
|
middleware: ["auth"],
|
||||||
|
requiresAuth: true,
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Set Ikons",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const copyToClipboard = (text) => {
|
||||||
|
let tagHtml = '<i class="icon-' + text + '"></i>';
|
||||||
|
navigator.clipboard.writeText(tagHtml);
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchQuery = ref("");
|
||||||
|
const displayedIcons = ref([]);
|
||||||
|
const containerRef = ref(null);
|
||||||
|
const batchSize = 50;
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
const filteredIcons = computed(() => {
|
||||||
|
if (!searchQuery.value) return iconJson;
|
||||||
|
return iconJson.filter((icon) =>
|
||||||
|
icon.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadMoreIcons = () => {
|
||||||
|
const newIcons = filteredIcons.value.slice(
|
||||||
|
currentIndex,
|
||||||
|
currentIndex + batchSize
|
||||||
|
);
|
||||||
|
displayedIcons.value.push(...newIcons);
|
||||||
|
currentIndex += batchSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetIconDisplay = () => {
|
||||||
|
displayedIcons.value = [];
|
||||||
|
currentIndex = 0;
|
||||||
|
loadMoreIcons();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(searchQuery, () => {
|
||||||
|
resetIconDisplay();
|
||||||
|
nextTick(() => {
|
||||||
|
if (containerRef.value) {
|
||||||
|
containerRef.value.scrollTop = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resetIconDisplay();
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!containerRef.value) return;
|
||||||
|
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = containerRef.value;
|
||||||
|
if (scrollHeight - scrollTop <= clientHeight + 1) {
|
||||||
|
loadMoreIcons();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header>
|
||||||
|
Set Ikon Icomoon (Jumlah: {{ filteredIcons.length }})
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<FormKit
|
||||||
|
type="text"
|
||||||
|
v-model="searchQuery"
|
||||||
|
placeholder="Search icons..."
|
||||||
|
class="mb-4"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
ref="containerRef"
|
||||||
|
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-8 max-h-[70vh] overflow-y-auto"
|
||||||
|
@scroll="handleScroll"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="icon in displayedIcons"
|
||||||
|
:key="icon.name"
|
||||||
|
class="flex items-center"
|
||||||
|
>
|
||||||
|
<Icon :name="icon.name" class="!w-10 !h-10 mr-4"></Icon>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="text-sm">{{ icon.name }}</div>
|
||||||
|
<rs-button
|
||||||
|
@click="copyToClipboard(icon.name)"
|
||||||
|
class="!text-xs !py-1 !px-2 !mt-1"
|
||||||
|
>
|
||||||
|
<Icon name="ph:copy" class="!w-4 !h-4 mr-1"></Icon>
|
||||||
|
Copy
|
||||||
|
</rs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="displayedIcons.length === 0" class="text-center mt-4">
|
||||||
|
No icons found matching your search.
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
289
pages/komponen/butang/index.vue
Normal file
289
pages/komponen/butang/index.vue
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
title: "Butang",
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Komponen",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const showCode1 = ref(false);
|
||||||
|
const showCode2 = ref(false);
|
||||||
|
const showCode3 = ref(false);
|
||||||
|
const showCode4 = ref(false);
|
||||||
|
|
||||||
|
const copyCode = (codeId) => {
|
||||||
|
const codeElement = document.getElementById(codeId);
|
||||||
|
if (codeElement) {
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(codeElement.textContent)
|
||||||
|
.then(() => {
|
||||||
|
// You can add a notification here if you want to inform the user that the code was copied
|
||||||
|
console.log("Code copied to clipboard");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Failed to copy code: ", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Default </template>
|
||||||
|
<template #body>
|
||||||
|
<p class="mb-4">Use the <code>rs-button</code> to show badges.</p>
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button> Button </rs-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button
|
||||||
|
class="text-sm border border-slate-200 py-1 px-3 rounded-lg my-2"
|
||||||
|
@click="showCode1 ? (showCode1 = false) : (showCode1 = true)"
|
||||||
|
>
|
||||||
|
Show Code
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ClientOnly>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-show="showCode1" v-highlight>
|
||||||
|
<div class="relative">
|
||||||
|
<button
|
||||||
|
@click="copyCode('code1')"
|
||||||
|
class="absolute top-4 right-2 text-sm bg-gray-300 hover:bg-gray-300 py-1 px-3 rounded z-10"
|
||||||
|
>
|
||||||
|
Copy
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<NuxtScrollbar style="max-height: 300px">
|
||||||
|
<pre class="language-html shadow-none">
|
||||||
|
<code id="code1">
|
||||||
|
<template>
|
||||||
|
<rs-button>Button</rs-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
</code>
|
||||||
|
</pre>
|
||||||
|
</NuxtScrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</ClientOnly>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Variant </template>
|
||||||
|
<template #body>
|
||||||
|
<p class="mb-4">
|
||||||
|
Button variant uses props <code>variant</code> to change the color of
|
||||||
|
the button. There are 6 variants: <code>primary</code>,
|
||||||
|
<code>info</code>, <code>success</code>, <code>warning</code> and
|
||||||
|
<code>danger</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button variant="primary"> Primary </rs-button>
|
||||||
|
<rs-button variant="secondary"> Secondary </rs-button>
|
||||||
|
<rs-button variant="info"> Info </rs-button>
|
||||||
|
<rs-button variant="success"> Success </rs-button>
|
||||||
|
<rs-button variant="warning"> Warning </rs-button>
|
||||||
|
<rs-button variant="danger"> Danger </rs-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button
|
||||||
|
class="text-sm border border-slate-200 py-1 px-3 rounded-lg my-2"
|
||||||
|
@click="showCode2 ? (showCode2 = false) : (showCode2 = true)"
|
||||||
|
>
|
||||||
|
Show Code
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ClientOnly>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-show="showCode2" v-highlight>
|
||||||
|
<NuxtScrollbar style="max-height: 300px">
|
||||||
|
<pre class="language-html shadow-none">
|
||||||
|
<code>
|
||||||
|
<template>
|
||||||
|
<rs-button variant="primary">Primary</rs-button>
|
||||||
|
<rs-button variant="secondary">Secondary</rs-button>
|
||||||
|
<rs-button variant="info">Info</rs-button>
|
||||||
|
<rs-button variant="success">Success</rs-button>
|
||||||
|
<rs-button variant="warning">Warning</rs-button>
|
||||||
|
<rs-button variant="danger">Danger</rs-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
</code>
|
||||||
|
</pre>
|
||||||
|
</NuxtScrollbar>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</ClientOnly>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Variant Type </template>
|
||||||
|
<template #body>
|
||||||
|
<p class="mb-4">
|
||||||
|
Button variant type uses props <code>variant</code> to change the
|
||||||
|
shape of the button. There are 3 variant types: <code>fill</code>,
|
||||||
|
<code>outline</code> and <code>text</code>. <code>fill</code> is the
|
||||||
|
default. <code>outline</code> is used to create a button with a
|
||||||
|
border. <code>text</code> is used to create a button with no border
|
||||||
|
and no background.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Fill Button -->
|
||||||
|
<div class="my-6">
|
||||||
|
<div
|
||||||
|
class="font-semibold text-lg bg-[rgb(var(--bg-1))] w-full mb-4 pl-2"
|
||||||
|
>
|
||||||
|
Fill
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button variant="primary"> Primary </rs-button>
|
||||||
|
<rs-button variant="secondary"> Secondary </rs-button>
|
||||||
|
<rs-button variant="info"> Info </rs-button>
|
||||||
|
<rs-button variant="success"> Success </rs-button>
|
||||||
|
<rs-button variant="warning"> Warning </rs-button>
|
||||||
|
<rs-button variant="danger"> Danger </rs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Outline Button -->
|
||||||
|
<div class="my-6">
|
||||||
|
<div
|
||||||
|
class="font-semibold text-lg bg-[rgb(var(--bg-1))] w-full mb-4 pl-2"
|
||||||
|
>
|
||||||
|
Outline
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button variant="primary-outline"> Primary </rs-button>
|
||||||
|
<rs-button variant="secondary-outline"> Secondary </rs-button>
|
||||||
|
<rs-button variant="info-outline"> Info </rs-button>
|
||||||
|
<rs-button variant="success-outline"> Success </rs-button>
|
||||||
|
<rs-button variant="warning-outline"> Warning </rs-button>
|
||||||
|
<rs-button variant="danger-outline"> Danger </rs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Text Button -->
|
||||||
|
<div class="my-6">
|
||||||
|
<div
|
||||||
|
class="font-semibold text-lg bg-[rgb(var(--bg-1))] w-full mb-4 pl-2"
|
||||||
|
>
|
||||||
|
Text
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button variant="primary-text"> Primary </rs-button>
|
||||||
|
<rs-button variant="secondary-text"> Secondary </rs-button>
|
||||||
|
<rs-button variant="info-text"> Info </rs-button>
|
||||||
|
<rs-button variant="success-text"> Success </rs-button>
|
||||||
|
<rs-button variant="warning-text"> Warning </rs-button>
|
||||||
|
<rs-button variant="danger-text"> Danger </rs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button
|
||||||
|
class="text-sm border border-slate-200 py-1 px-3 rounded-lg my-2"
|
||||||
|
@click="showCode3 ? (showCode3 = false) : (showCode3 = true)"
|
||||||
|
>
|
||||||
|
Show Code
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ClientOnly>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-show="showCode3" v-highlight>
|
||||||
|
<NuxtScrollbar style="max-height: 300px">
|
||||||
|
<pre class="language-html shadow-none">
|
||||||
|
<code>
|
||||||
|
<template>
|
||||||
|
<!-- Fill Button -->
|
||||||
|
<rs-button variant="primary">Primary</rs-button>
|
||||||
|
<rs-button variant="secondary">Secondary</rs-button>
|
||||||
|
<rs-button variant="info">Info</rs-button>
|
||||||
|
<rs-button variant="success">Success</rs-button>
|
||||||
|
<rs-button variant="warning">Warning</rs-button>
|
||||||
|
<rs-button variant="danger">Danger</rs-button>
|
||||||
|
|
||||||
|
<!-- Outline Button -->
|
||||||
|
<rs-button variant="primary-outline">Primary</rs-button>
|
||||||
|
<rs-button variant="secondary-outline">Secondary</rs-button>
|
||||||
|
<rs-button variant="info-outline">Info</rs-button>
|
||||||
|
<rs-button variant="success-outline">Success</rs-button>
|
||||||
|
<rs-button variant="warning-outline">Warning</rs-button>
|
||||||
|
<rs-button variant="danger-outline">Danger</rs-button>
|
||||||
|
|
||||||
|
<!-- Text Button -->
|
||||||
|
<rs-button variant="primary-text">Primary</rs-button>
|
||||||
|
<rs-button variant="secondary-text">Secondary</rs-button>
|
||||||
|
<rs-button variant="info-text">Info</rs-button>
|
||||||
|
<rs-button variant="success-text">Success</rs-button>
|
||||||
|
<rs-button variant="warning-text">Warning</rs-button>
|
||||||
|
<rs-button variant="danger-text">Danger</rs-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
</code>
|
||||||
|
</pre>
|
||||||
|
</NuxtScrollbar>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</ClientOnly>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Size </template>
|
||||||
|
<template #body>
|
||||||
|
<p class="mb-4">
|
||||||
|
Button size uses props <code>size</code> to change the size of button.
|
||||||
|
There are 3 sizes: <code>small</code>, <code>medium</code> and
|
||||||
|
<code>large</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="flex flex-wrap items-center justify-start gap-x-6">
|
||||||
|
<rs-button size="sm"> Small </rs-button>
|
||||||
|
<rs-button size="md"> Medium </rs-button>
|
||||||
|
<rs-button size="lg"> Large </rs-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<button
|
||||||
|
class="text-sm border border-slate-200 py-1 px-3 rounded-lg my-2"
|
||||||
|
@click="showCode4 ? (showCode4 = false) : (showCode4 = true)"
|
||||||
|
>
|
||||||
|
Show Code
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ClientOnly>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-show="showCode4" v-highlight>
|
||||||
|
<NuxtScrollbar style="max-height: 300px">
|
||||||
|
<pre class="language-html shadow-none">
|
||||||
|
<code>
|
||||||
|
<template>
|
||||||
|
<rs-button size="sm">Small</rs-button>
|
||||||
|
<rs-button size="md">Medium</rs-button>
|
||||||
|
<rs-button size="lg">Large</rs-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup></script>
|
||||||
|
</code>
|
||||||
|
</pre>
|
||||||
|
</NuxtScrollbar>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</ClientOnly>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
17
pages/komponen/datatable/index.vue
Normal file
17
pages/komponen/datatable/index.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
title: "Data Table",
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Data Table",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
17
pages/komponen/modal/index.vue
Normal file
17
pages/komponen/modal/index.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
title: "Modal",
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Modal",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
335
pages/laporan/index.vue
Normal file
335
pages/laporan/index.vue
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
title: "Laporan",
|
||||||
|
breadcrumb: [
|
||||||
|
{
|
||||||
|
name: "Laporan",
|
||||||
|
type: "current",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = ref([
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Aura",
|
||||||
|
kedua: "Hard",
|
||||||
|
ketiga: "Business Services Sales Representative",
|
||||||
|
keempat: "1969-04-19",
|
||||||
|
status: "Digantung",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Chantal",
|
||||||
|
kedua: "Nailor",
|
||||||
|
ketiga: "Technical Services Librarian",
|
||||||
|
keempat: "1980-01-10",
|
||||||
|
status: "Tidak Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Cicely",
|
||||||
|
kedua: "Sigler",
|
||||||
|
ketiga: "Senior Research Officer",
|
||||||
|
keempat: "1960-03-15",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Coy",
|
||||||
|
kedua: "Wollard",
|
||||||
|
ketiga: "Customer Service Operator",
|
||||||
|
keempat: "1982-10-12",
|
||||||
|
status: "Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Delma",
|
||||||
|
kedua: "Bonds",
|
||||||
|
ketiga: "Lead Brand Manager",
|
||||||
|
keempat: "1968-12-21",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Lorin",
|
||||||
|
kedua: "Forbes",
|
||||||
|
ketiga: "Product Marketing Manager",
|
||||||
|
keempat: "1974-05-08",
|
||||||
|
status: "Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Eldon",
|
||||||
|
kedua: "Marcellus",
|
||||||
|
ketiga: "Software Developer",
|
||||||
|
keempat: "1987-11-30",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Allie",
|
||||||
|
kedua: "Cordell",
|
||||||
|
ketiga: "UX Designer",
|
||||||
|
keempat: "1992-07-19",
|
||||||
|
status: "Digantung",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Sheridan",
|
||||||
|
kedua: "Caldwell",
|
||||||
|
ketiga: "HR Manager",
|
||||||
|
keempat: "1970-03-22",
|
||||||
|
status: "Tidak Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Rowan",
|
||||||
|
kedua: "Douglas",
|
||||||
|
ketiga: "Financial Analyst",
|
||||||
|
keempat: "1983-08-13",
|
||||||
|
status: "Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Elvin",
|
||||||
|
kedua: "Temple",
|
||||||
|
ketiga: "Operations Manager",
|
||||||
|
keempat: "1976-01-11",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Gisele",
|
||||||
|
kedua: "Erickson",
|
||||||
|
ketiga: "Public Relations Specialist",
|
||||||
|
keempat: "1989-09-30",
|
||||||
|
status: "Tidak Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Taryn",
|
||||||
|
kedua: "Ridgeway",
|
||||||
|
ketiga: "Content Strategist",
|
||||||
|
keempat: "1978-12-17",
|
||||||
|
status: "Digantung",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Armand",
|
||||||
|
kedua: "Copeland",
|
||||||
|
ketiga: "Legal Advisor",
|
||||||
|
keempat: "1965-04-02",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Tisha",
|
||||||
|
kedua: "Gillespie",
|
||||||
|
ketiga: "IT Support Specialist",
|
||||||
|
keempat: "1985-06-25",
|
||||||
|
status: "Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Brenton",
|
||||||
|
kedua: "Thornton",
|
||||||
|
ketiga: "Digital Marketing Specialist",
|
||||||
|
keempat: "1991-02-14",
|
||||||
|
status: "Digantung",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Annis",
|
||||||
|
kedua: "Hobson",
|
||||||
|
ketiga: "Project Coordinator",
|
||||||
|
keempat: "1981-05-07",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Dylan",
|
||||||
|
kedua: "Hudson",
|
||||||
|
ketiga: "Account Manager",
|
||||||
|
keempat: "1990-09-15",
|
||||||
|
status: "Tidak Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Kendall",
|
||||||
|
kedua: "Browning",
|
||||||
|
ketiga: "Supply Chain Manager",
|
||||||
|
keempat: "1973-07-03",
|
||||||
|
status: "Aktif",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kriteriaPertama: "Maris",
|
||||||
|
kedua: "Woodard",
|
||||||
|
ketiga: "Customer Relations Specialist",
|
||||||
|
keempat: "1962-11-20",
|
||||||
|
status: "Menunggu",
|
||||||
|
tindakan: "...",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const criteria = ref([
|
||||||
|
{
|
||||||
|
label: "Kriteria 1",
|
||||||
|
options: ["Aura", "Chantal", "Cicely", "Coy", "Delma"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kriteria 2",
|
||||||
|
options: ["Hard", "Nailor", "Sigler", "Wollard", "Bonds"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kriteria 3",
|
||||||
|
options: [
|
||||||
|
"Business Services Sales Representative",
|
||||||
|
"Technical Services Librarian",
|
||||||
|
"Senior Research Officer",
|
||||||
|
"Customer Service Operator",
|
||||||
|
"Lead Brand Manager",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kriteria 4",
|
||||||
|
options: [
|
||||||
|
"1969-04-19",
|
||||||
|
"1980-01-10",
|
||||||
|
"1960-03-15",
|
||||||
|
"1982-10-12",
|
||||||
|
"1968-12-21",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Kriteria 5",
|
||||||
|
options: ["Digantung", "Tidak Aktif", "Menunggu", "Aktif"],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const selectedCriteria = ref({
|
||||||
|
kriteria1: "",
|
||||||
|
kriteria2: "",
|
||||||
|
kriteria3: "",
|
||||||
|
kriteria4: "",
|
||||||
|
kriteria5: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const filteredData = ref([...data.value]);
|
||||||
|
|
||||||
|
const performSearch = () => {
|
||||||
|
filteredData.value = data.value.filter((item) => {
|
||||||
|
return (
|
||||||
|
(!selectedCriteria.value.kriteria1 ||
|
||||||
|
item.kriteriaPertama.includes(selectedCriteria.value.kriteria1)) &&
|
||||||
|
(!selectedCriteria.value.kriteria2 ||
|
||||||
|
item.kedua.includes(selectedCriteria.value.kriteria2)) &&
|
||||||
|
(!selectedCriteria.value.kriteria3 ||
|
||||||
|
item.ketiga.includes(selectedCriteria.value.kriteria3)) &&
|
||||||
|
(!selectedCriteria.value.kriteria4 ||
|
||||||
|
item.keempat.includes(selectedCriteria.value.kriteria4)) &&
|
||||||
|
(!selectedCriteria.value.kriteria5 ||
|
||||||
|
item.status.includes(selectedCriteria.value.kriteria5))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetFilter = () => {
|
||||||
|
selectedCriteria.value = {
|
||||||
|
kriteria1: "",
|
||||||
|
kriteria2: "",
|
||||||
|
kriteria3: "",
|
||||||
|
kriteria4: "",
|
||||||
|
kriteria5: "",
|
||||||
|
};
|
||||||
|
filteredData.value = [...data.value];
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<LayoutsBreadcrumb />
|
||||||
|
|
||||||
|
<rs-card>
|
||||||
|
<template #header> Laporan</template>
|
||||||
|
<template #body>
|
||||||
|
<FormKit type="form" :actions="false">
|
||||||
|
<div class="grid grid-cols-2 gap-4 mb-4">
|
||||||
|
<FormKit
|
||||||
|
v-for="(item, index) in criteria.slice(0, 2)"
|
||||||
|
:key="index"
|
||||||
|
type="select"
|
||||||
|
:name="item.label.toLowerCase().replace(' ', '_')"
|
||||||
|
:label="item.label"
|
||||||
|
:options="item.options"
|
||||||
|
v-model="selectedCriteria[`kriteria${index + 1}`]"
|
||||||
|
placeholder="Pilih pilihan"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<label
|
||||||
|
class="formkit-label text-gray-700 dark:text-gray-200 block mb-2 font-semibold text-sm formkit-invalid:text-red-500"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-3 gap-4">
|
||||||
|
<FormKit
|
||||||
|
v-for="(item, index) in criteria.slice(2)"
|
||||||
|
:key="index"
|
||||||
|
type="select"
|
||||||
|
:name="item.label.toLowerCase().replace(' ', '_')"
|
||||||
|
:label="item.label"
|
||||||
|
:options="item.options"
|
||||||
|
v-model="selectedCriteria[`kriteria${index + 3}`]"
|
||||||
|
placeholder="Pilih pilihan"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<label
|
||||||
|
class="formkit-label text-gray-700 dark:text-gray-200 block mb-2 font-semibold text-sm formkit-invalid:text-red-500"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-end items-center gap-2">
|
||||||
|
<rs-button @click="resetFilter" variant="primary-outline"
|
||||||
|
>Reset</rs-button
|
||||||
|
>
|
||||||
|
<rs-button type="submit" @click="performSearch">
|
||||||
|
Hantar Laporan
|
||||||
|
</rs-button>
|
||||||
|
</div>
|
||||||
|
</FormKit>
|
||||||
|
|
||||||
|
<rs-table
|
||||||
|
class="mt-8"
|
||||||
|
:key="filteredData"
|
||||||
|
:data="filteredData"
|
||||||
|
:pageSize="100"
|
||||||
|
>
|
||||||
|
<template v-slot:status="data">
|
||||||
|
<rs-badge
|
||||||
|
:variant="
|
||||||
|
data.text === 'Aktif'
|
||||||
|
? 'success'
|
||||||
|
: data.text === 'Menunggu'
|
||||||
|
? 'warning'
|
||||||
|
: data.text === 'Tidak Aktif'
|
||||||
|
? 'disabled'
|
||||||
|
: data.text === 'Digantung'
|
||||||
|
? 'danger'
|
||||||
|
: 'default'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ data.text }}
|
||||||
|
</rs-badge>
|
||||||
|
</template>
|
||||||
|
</rs-table>
|
||||||
|
</template>
|
||||||
|
</rs-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
@ -1,5 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from "~/stores/user";
|
import { useUserStore } from "~/stores/user";
|
||||||
|
import { RecaptchaV2 } from "vue3-recaptcha-v2";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
title: "Login",
|
title: "Login",
|
||||||
@ -54,6 +55,19 @@ const login = async () => {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleWidgetId = (widgetId) => {
|
||||||
|
console.log("Widget ID: ", widgetId);
|
||||||
|
};
|
||||||
|
const handleErrorCalback = () => {
|
||||||
|
console.log("Error callback");
|
||||||
|
};
|
||||||
|
const handleExpiredCallback = () => {
|
||||||
|
console.log("Expired callback");
|
||||||
|
};
|
||||||
|
const handleLoadCallback = (response) => {
|
||||||
|
console.log("Load callback", response);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -62,41 +76,53 @@ const login = async () => {
|
|||||||
>
|
>
|
||||||
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
||||||
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
||||||
<div
|
<div class="img-container flex justify-center items-center mb-5">
|
||||||
class="absolute -bottom-3 left-3 img-container flex justify-start items-center mb-5"
|
<img src="@/assets/img/logo/niise-logo.svg" class="max-w-[60px]" />
|
||||||
>
|
<img src="@/assets/img/logo/niise-text.svg" class="max-w-[120px]" />
|
||||||
<img
|
|
||||||
src="@/assets/img/logo/logo-word-black.svg"
|
|
||||||
class="max-w-[90px]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4">Login</h3>
|
<p class="text-slate-500 text-lg mb-6">Log masuk ke akaun anda</p>
|
||||||
<p class="text-slate-500 mb-6">
|
|
||||||
Welcome to Corrad. Please login to continue.
|
|
||||||
</p>
|
|
||||||
<div class="grid grid-cols-2">
|
<div class="grid grid-cols-2">
|
||||||
<FormKit
|
<FormKit
|
||||||
type="text"
|
type="text"
|
||||||
label="Username"
|
|
||||||
v-model="username"
|
v-model="username"
|
||||||
validation="required"
|
validation="required"
|
||||||
|
placeholder="Masukkan ID Pengguna"
|
||||||
:classes="{
|
:classes="{
|
||||||
outer: 'col-span-2',
|
outer: 'col-span-2',
|
||||||
label: 'text-left',
|
label: 'text-left',
|
||||||
messages: 'text-left',
|
messages: 'text-left',
|
||||||
}"
|
}"
|
||||||
/>
|
:validation-messages="{
|
||||||
<FormKit
|
required: 'ID Pengguna wajib diisi.',
|
||||||
:type="togglePasswordVisibility ? 'text' : 'password'"
|
|
||||||
label="Password"
|
|
||||||
v-model="password"
|
|
||||||
validation="required"
|
|
||||||
:classes="{
|
|
||||||
outer: 'col-span-2',
|
|
||||||
label: 'text-left',
|
|
||||||
messages: 'text-left',
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:user-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
<FormKit
|
||||||
|
:type="togglePasswordVisibility ? 'text' : 'password'"
|
||||||
|
v-model="password"
|
||||||
|
validation="required"
|
||||||
|
placeholder="Masukkan Kata Laluan"
|
||||||
|
:classes="{
|
||||||
|
outer: 'col-span-2',
|
||||||
|
label: 'text-left',
|
||||||
|
messages: 'text-left',
|
||||||
|
}"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Kata Laluan wajib diisi.',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:lock-key-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<div
|
<div
|
||||||
class="bg-gray-100 hover:bg-slate-200 dark:bg-slate-700 hover:dark:bg-slate-900 h-full rounded-r-md p-3 flex justify-center items-center cursor-pointer"
|
class="bg-gray-100 hover:bg-slate-200 dark:bg-slate-700 hover:dark:bg-slate-900 h-full rounded-r-md p-3 flex justify-center items-center cursor-pointer"
|
||||||
@ -111,29 +137,43 @@ const login = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
<FormKit type="checkbox" label="Remember Me" />
|
<div class="col-span-2 mb-4">
|
||||||
|
<RecaptchaV2
|
||||||
|
@widget-id="handleWidgetId"
|
||||||
|
@error-callback="handleErrorCalback"
|
||||||
|
@expired-callback="handleExpiredCallback"
|
||||||
|
@load-callback="handleLoadCallback"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
class="flex items-center justify-end h-5 mt-1 text-primary hover:underline"
|
class="col-span-2 flex items-center justify-end h-5 mt-1 text-primary hover:underline mb-5"
|
||||||
to="forgot-password"
|
to="forgot-password"
|
||||||
>Forgot Password?</NuxtLink
|
|
||||||
>
|
>
|
||||||
<!-- <NuxtLink to="/" class="col-span-2">
|
Lupa Kata Laluan?
|
||||||
</NuxtLink> -->
|
</NuxtLink>
|
||||||
<FormKit
|
<FormKit
|
||||||
type="button"
|
type="button"
|
||||||
input-class="w-full"
|
input-class="w-full"
|
||||||
outer-class="col-span-2"
|
outer-class="col-span-2"
|
||||||
@click="login"
|
@click="login"
|
||||||
>
|
>
|
||||||
Sign In
|
Log Masuk
|
||||||
|
|
||||||
|
<Icon name="ph:caret-circle-right" class="!w-5 !h-5 ml-1"></Icon>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-3 text-center text-slate-500">
|
<div class="flex justify-center items-center">
|
||||||
Don't have an account?
|
<hr class="w-full" />
|
||||||
<NuxtLink to="/register" class="text-primary hover:underline"
|
<p class="w-full !text-gray-400">Tiada akaun?</p>
|
||||||
>Sign Up</NuxtLink
|
<hr class="w-full" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<rs-button
|
||||||
|
@click="navigateTo('/register')"
|
||||||
|
class="w-full !bg-gray-100 !text-gray-600 border mt-5"
|
||||||
>
|
>
|
||||||
</p>
|
Daftar / Log masuk kali pertama
|
||||||
|
</rs-button>
|
||||||
</rs-card>
|
</rs-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,34 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { RecaptchaV2 } from "vue3-recaptcha-v2";
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
title: "Register",
|
title: "Register",
|
||||||
layout: "empty",
|
layout: "empty",
|
||||||
middleware: ["dashboard"],
|
middleware: ["dashboard"],
|
||||||
});
|
});
|
||||||
|
|
||||||
const togglePasswordVisibility = ref(false);
|
const formData = ref({
|
||||||
const togglePasswordVisibility2 = ref(false);
|
fullName: "",
|
||||||
|
idNumber: "",
|
||||||
|
phoneNumber: "",
|
||||||
|
password: "",
|
||||||
|
confirmPassword: "",
|
||||||
|
email: "",
|
||||||
|
confirmEmail: "",
|
||||||
|
subscribeNewsletter: false,
|
||||||
|
agreeTerms: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const register = () => {
|
||||||
|
// Simulate registration without API call
|
||||||
|
console.log("Registration attempted with:", formData.value);
|
||||||
|
// Add your registration logic here
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRecaptcha = (response) => {
|
||||||
|
console.log("reCAPTCHA response:", response);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -15,81 +37,181 @@ const togglePasswordVisibility2 = ref(false);
|
|||||||
>
|
>
|
||||||
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
||||||
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
||||||
<div
|
<div class="text-center mb-8">
|
||||||
class="absolute -bottom-3 left-3 img-container flex justify-start items-center mb-5"
|
<div class="img-container flex justify-center items-center mb-5">
|
||||||
>
|
<img src="@/assets/img/logo/niise-logo.svg" class="max-w-[60px]" />
|
||||||
<img
|
<img src="@/assets/img/logo/niise-text.svg" class="max-w-[120px]" />
|
||||||
src="@/assets/img/logo/logo-word-black.svg"
|
|
||||||
class="max-w-[90px]"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<h3 class="mb-4">Sign Up</h3>
|
<h2 class="mt-4 text-2xl font-bold text-gray-700">Daftar Akaun</h2>
|
||||||
<p class="text-slate-500 mb-6 col-sp">
|
<p class="text-sm text-gray-500">Semua medan adalah wajib</p>
|
||||||
Please fill in the form to create an account.
|
</div>
|
||||||
</p>
|
|
||||||
<FormKit label="Username" type="text" label-class="text-left" />
|
<FormKit type="form" :actions="false" @submit="register">
|
||||||
<FormKit label="Email" type="email" label-class="text-left" />
|
|
||||||
<FormKit
|
<FormKit
|
||||||
:type="togglePasswordVisibility ? 'text' : 'password'"
|
type="text"
|
||||||
label="Password"
|
name="fullName"
|
||||||
type="password"
|
placeholder="Nama Penuh"
|
||||||
label-class="text-left"
|
validation="required"
|
||||||
>
|
:validation-messages="{
|
||||||
<template #suffix>
|
required: 'Nama Penuh wajib diisi',
|
||||||
<div
|
}"
|
||||||
class="bg-gray-100 hover:bg-slate-200 dark:bg-slate-700 hover:dark:bg-slate-900 h-full rounded-r-md p-3 flex justify-center items-center cursor-pointer"
|
|
||||||
@click="togglePasswordVisibility = !togglePasswordVisibility"
|
|
||||||
>
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="!togglePasswordVisibility"
|
name="ph:user-fill"
|
||||||
name="ion:eye-outline"
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
size="19"
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-0 md:gap-4">
|
||||||
|
<FormKit
|
||||||
|
type="text"
|
||||||
|
name="idNumber"
|
||||||
|
placeholder="Nombor Mykad / Nombor Pasport"
|
||||||
|
validation="required"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Nombor Mykad / Nombor Pasport wajib diisi',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:identification-card-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
></Icon>
|
></Icon>
|
||||||
<Icon v-else name="ion:eye-off-outline" size="19"></Icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
<FormKit
|
<FormKit
|
||||||
:type="togglePasswordVisibility2 ? 'text' : 'password'"
|
type="tel"
|
||||||
label="Re-enter Password"
|
name="phoneNumber"
|
||||||
type="password"
|
placeholder="Nombor Telefon"
|
||||||
label-class="text-left"
|
validation="required"
|
||||||
>
|
:validation-messages="{
|
||||||
<template #suffix>
|
required: 'Nombor Telefon wajib diisi',
|
||||||
<div
|
}"
|
||||||
class="bg-gray-100 hover:bg-slate-200 dark:bg-slate-700 hover:dark:bg-slate-900 h-full rounded-r-md p-3 flex justify-center items-center cursor-pointer"
|
|
||||||
@click="togglePasswordVisibility2 = !togglePasswordVisibility2"
|
|
||||||
>
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="!togglePasswordVisibility2"
|
name="ph:device-mobile-camera-fill"
|
||||||
name="ion:eye-outline"
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
size="19"
|
|
||||||
></Icon>
|
></Icon>
|
||||||
<Icon v-else name="ion:eye-off-outline" size="19"></Icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-0 md:gap-4">
|
||||||
|
<FormKit
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
placeholder="Kata Laluan"
|
||||||
|
validation="required"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Kata Laluan wajib diisi',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:lock-key-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
<FormKit
|
||||||
|
type="password"
|
||||||
|
name="confirmPassword"
|
||||||
|
placeholder="Pengesahan Kata Laluan"
|
||||||
|
validation="required|confirm"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Pengesahan Kata Laluan wajib diisi',
|
||||||
|
confirm: 'Kata Laluan tidak sepadan',
|
||||||
|
}"
|
||||||
|
:validation-rules="{
|
||||||
|
confirm: (value) => value === value.password,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:lock-key-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-0 md:gap-4">
|
||||||
|
<FormKit
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="Emel"
|
||||||
|
validation="required|email"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Emel wajib diisi',
|
||||||
|
email: 'Format emel tidak sah',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:envelope-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
<FormKit
|
||||||
|
type="email"
|
||||||
|
name="confirmEmail"
|
||||||
|
placeholder="Pengesahan Emel"
|
||||||
|
validation="required|confirm"
|
||||||
|
:validation-messages="{
|
||||||
|
required: 'Pengesahan Emel wajib diisi',
|
||||||
|
confirm: 'Emel tidak sepadan',
|
||||||
|
}"
|
||||||
|
:validation-rules="{
|
||||||
|
confirm: (value) => value === value.email,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #prefixIcon>
|
||||||
|
<Icon
|
||||||
|
name="ph:envelope-fill"
|
||||||
|
class="!w-5 !h-5 ml-3 text-gray-500"
|
||||||
|
></Icon>
|
||||||
|
</template>
|
||||||
|
</FormKit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-start mb-4 mt-2">
|
||||||
|
<RecaptchaV2 @verify="handleRecaptcha" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormKit
|
<FormKit
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
label="agreement"
|
name="subscribeNewsletter"
|
||||||
outer-class="col-span-1 md:col-span-2"
|
label="Melanggan ke newsletter bulanan"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormKit
|
||||||
|
type="checkbox"
|
||||||
|
name="agreeTerms"
|
||||||
|
label="Setuju dengan terma perkhidmatan"
|
||||||
|
validation="accepted"
|
||||||
|
:validation-messages="{
|
||||||
|
accepted: 'Anda mesti bersetuju dengan terma perkhidmatan',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #label
|
<template #label>
|
||||||
>I agree to the
|
Setuju dengan
|
||||||
<a class="text-primary hover:underline ml-1">Term and Services</a>
|
<a href="#" class="text-blue-600 ml-1">terma perkhidmatan</a>
|
||||||
</template>
|
</template>
|
||||||
</FormKit>
|
</FormKit>
|
||||||
|
|
||||||
<NuxtLink to="/" class="col-span-1 md:col-span-2">
|
<rs-button btn-type="submit" class="w-full"> Daftar Akaun </rs-button>
|
||||||
<FormKit type="button" input-class="w-full">Sign up</FormKit>
|
</FormKit>
|
||||||
</NuxtLink>
|
|
||||||
|
|
||||||
<p class="mt-3 text-center text-slate-500">
|
<div class="text-center mt-4">
|
||||||
Already have an account?
|
<p class="text-sm text-gray-500">
|
||||||
<NuxtLink to="/login" class="text-primary hover:underline"
|
Sudah mempunyai akaun?
|
||||||
>Login</NuxtLink
|
<nuxt-link to="/login" class="text-blue-600">Log Masuk</nuxt-link>
|
||||||
>
|
|
||||||
</p>
|
</p>
|
||||||
|
</div>
|
||||||
</rs-card>
|
</rs-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
definePageMeta({
|
|
||||||
title: "Reset Password",
|
|
||||||
layout: "empty",
|
|
||||||
middleware: ["dashboard"],
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
class="flex-none md:flex justify-center text-center items-center h-screen"
|
|
||||||
>
|
|
||||||
<div class="w-full md:w-3/4 lg:w-1/2 xl:w-2/6 relative">
|
|
||||||
<rs-card class="h-screen md:h-auto px-10 md:px-16 py-12 md:py-20 mb-0">
|
|
||||||
<div
|
|
||||||
class="absolute -bottom-3 left-3 img-container flex justify-start items-center mb-5"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src="@/assets/img/logo/logo-word-black.svg"
|
|
||||||
class="max-w-[90px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<h3 class="mb-4">Reset Password</h3>
|
|
||||||
<p class="text-slate-500 mb-6">
|
|
||||||
Please fill in the form to reset your password.
|
|
||||||
</p>
|
|
||||||
<div class="grid grid-cols-1">
|
|
||||||
<FormKit label="Email" type="email" outer-class="text-left" />
|
|
||||||
<FormKit label="Password" type="password" outer-class="text-left" />
|
|
||||||
<FormKit
|
|
||||||
label="Re-enter Password"
|
|
||||||
type="password"
|
|
||||||
outer-class="text-left"
|
|
||||||
/>
|
|
||||||
<NuxtLink to="/login">
|
|
||||||
<FormKit type="button" input-class="w-full">Reset Password</FormKit>
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
|
||||||
</rs-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
8
plugins/recaptcha.client.js
Normal file
8
plugins/recaptcha.client.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { install } from "vue3-recaptcha-v2";
|
||||||
|
|
||||||
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
|
nuxtApp.vueApp.use(install, {
|
||||||
|
sitekey: "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI",
|
||||||
|
cnDomains: false,
|
||||||
|
});
|
||||||
|
});
|
@ -57,6 +57,8 @@ model lookup {
|
|||||||
lookupModifiedDate DateTime? @db.DateTime(0)
|
lookupModifiedDate DateTime? @db.DateTime(0)
|
||||||
assistant assistant[]
|
assistant assistant[]
|
||||||
project project[]
|
project project[]
|
||||||
|
project_project_projectViewTypeTolookup project[] @relation("project_projectViewTypeTolookup")
|
||||||
|
thread thread[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model userrole {
|
model userrole {
|
||||||
@ -152,17 +154,21 @@ model project {
|
|||||||
projectDescription String? @db.VarChar(255)
|
projectDescription String? @db.VarChar(255)
|
||||||
projectDefault Boolean? @default(dbgenerated("b'0'")) @db.Bit(1)
|
projectDefault Boolean? @default(dbgenerated("b'0'")) @db.Bit(1)
|
||||||
projectType Int?
|
projectType Int?
|
||||||
|
projectPublic Boolean? @db.Bit(1)
|
||||||
|
projectViewType Int?
|
||||||
projectCreatedDate DateTime? @db.DateTime(0)
|
projectCreatedDate DateTime? @db.DateTime(0)
|
||||||
projectModifiedDate DateTime? @db.DateTime(0)
|
projectModifiedDate DateTime? @db.DateTime(0)
|
||||||
chat chat[]
|
chat chat[]
|
||||||
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "project_ibfk_2")
|
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "project_ibfk_2")
|
||||||
lookup lookup? @relation(fields: [projectType], references: [lookupID], onDelete: NoAction, onUpdate: NoAction, map: "project_ibfk_3")
|
lookup lookup? @relation(fields: [projectType], references: [lookupID], onDelete: NoAction, onUpdate: NoAction, map: "project_ibfk_3")
|
||||||
|
lookup_project_projectViewTypeTolookup lookup? @relation("project_projectViewTypeTolookup", fields: [projectViewType], references: [lookupID], onDelete: NoAction, onUpdate: NoAction, map: "project_ibfk_4")
|
||||||
project_permission_project_permission_projectPermissionIDToproject project_permission? @relation("project_permission_projectPermissionIDToproject")
|
project_permission_project_permission_projectPermissionIDToproject project_permission? @relation("project_permission_projectPermissionIDToproject")
|
||||||
project_permission_project_permission_projectIDToproject project_permission[] @relation("project_permission_projectIDToproject")
|
project_permission_project_permission_projectIDToproject project_permission[] @relation("project_permission_projectIDToproject")
|
||||||
repository repository[]
|
repository repository[]
|
||||||
|
|
||||||
@@index([projectType], map: "projectType")
|
@@index([projectType], map: "projectType")
|
||||||
@@index([userID], map: "userID")
|
@@index([userID], map: "userID")
|
||||||
|
@@index([projectViewType], map: "projectViewType")
|
||||||
}
|
}
|
||||||
|
|
||||||
model project_permission {
|
model project_permission {
|
||||||
@ -205,12 +211,15 @@ model thread {
|
|||||||
assistantID Int?
|
assistantID Int?
|
||||||
threadTitle String? @db.VarChar(255)
|
threadTitle String? @db.VarChar(255)
|
||||||
threadOAIID String? @unique(map: "threadOAIID") @db.VarChar(255)
|
threadOAIID String? @unique(map: "threadOAIID") @db.VarChar(255)
|
||||||
|
threadStatus Int?
|
||||||
threadCreatedDate DateTime? @db.DateTime(0)
|
threadCreatedDate DateTime? @db.DateTime(0)
|
||||||
threadModifiedDate DateTime? @db.DateTime(0)
|
threadModifiedDate DateTime? @db.DateTime(0)
|
||||||
chat chat[]
|
chat chat[]
|
||||||
assistant assistant? @relation(fields: [assistantID], references: [assistantID], onDelete: NoAction, onUpdate: NoAction, map: "thread_ibfk_1")
|
assistant assistant? @relation(fields: [assistantID], references: [assistantID], onDelete: NoAction, onUpdate: NoAction, map: "thread_ibfk_1")
|
||||||
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "thread_ibfk_2")
|
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "thread_ibfk_2")
|
||||||
|
lookup lookup? @relation(fields: [threadStatus], references: [lookupID], onDelete: NoAction, onUpdate: NoAction, map: "thread_ibfk_3")
|
||||||
|
|
||||||
@@index([assistantID], map: "assistantID")
|
@@index([assistantID], map: "assistantID")
|
||||||
@@index([userID], map: "userID")
|
@@index([userID], map: "userID")
|
||||||
|
@@index([threadStatus], map: "threadStatus")
|
||||||
}
|
}
|
||||||
|
@ -9227,6 +9227,11 @@ vue3-perfect-scrollbar@^1.6.1:
|
|||||||
perfect-scrollbar "^1.5.5"
|
perfect-scrollbar "^1.5.5"
|
||||||
postcss-import "^12.0.0"
|
postcss-import "^12.0.0"
|
||||||
|
|
||||||
|
vue3-recaptcha-v2@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue3-recaptcha-v2/-/vue3-recaptcha-v2-2.0.2.tgz#127d568d90cd3de3588429eb500d16f408380f13"
|
||||||
|
integrity sha512-uIxJG4+BVquSVJxCLdkJV3Y0IgXPG+sWqAG34qwHt9MungDFshuKprtrN48oJHcLXePLey/FEo2B5pbfMB5cjQ==
|
||||||
|
|
||||||
vue@^2.5.16:
|
vue@^2.5.16:
|
||||||
version "2.7.14"
|
version "2.7.14"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.14.tgz#3743dcd248fd3a34d421ae456b864a0246bafb17"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-2.7.14.tgz#3743dcd248fd3a34d421ae456b864a0246bafb17"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user