Merge branch 'dev-bagus' of https://github.com/defuj/eis into development

This commit is contained in:
Dede Fuji Abdul 2023-10-27 10:27:53 +07:00
commit 103cb9d0f4
12 changed files with 595 additions and 7 deletions

30
package-lock.json generated
View File

@ -12,6 +12,7 @@
"@headlessui/vue": "^1.7.16",
"@heroicons/vue": "^2.0.18",
"@lottiefiles/lottie-player": "^2.0.2",
"@phosphor-icons/vue": "^2.1.6",
"@types/qs": "^6.9.9",
"@types/uuid": "^9.0.2",
"devextreme": "23.1.5",
@ -500,9 +501,9 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz",
"integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.22.13",
@ -1191,6 +1192,17 @@
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"dev": true
},
"node_modules/@phosphor-icons/vue": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@phosphor-icons/vue/-/vue-2.1.6.tgz",
"integrity": "sha512-j4iVvNT4JbDR2udIVfakKZHd14i3jCvO4b24OC0W/1rasftU8qVg1Tnb3QDwAT0teNU+UxvaM+kCWxfGHC2dUg==",
"engines": {
"node": ">=14"
},
"peerDependencies": {
"vue": ">=3.2.39"
}
},
"node_modules/@pkgr/utils": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
@ -9492,9 +9504,9 @@
}
},
"@babel/traverse": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz",
"integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==",
"version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.22.13",
@ -9917,6 +9929,12 @@
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"dev": true
},
"@phosphor-icons/vue": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@phosphor-icons/vue/-/vue-2.1.6.tgz",
"integrity": "sha512-j4iVvNT4JbDR2udIVfakKZHd14i3jCvO4b24OC0W/1rasftU8qVg1Tnb3QDwAT0teNU+UxvaM+kCWxfGHC2dUg==",
"requires": {}
},
"@pkgr/utils": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",

View File

@ -18,6 +18,7 @@
"@headlessui/vue": "^1.7.16",
"@heroicons/vue": "^2.0.18",
"@lottiefiles/lottie-player": "^2.0.2",
"@phosphor-icons/vue": "^2.1.6",
"@types/qs": "^6.9.9",
"@types/uuid": "^9.0.2",
"devextreme": "23.1.5",

View File

@ -705,6 +705,40 @@ select {
--tw-backdrop-sepia: ;
}
.container {
width: 100%;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
/* NavBar */
.menu-item {
@ -925,6 +959,10 @@ select {
top: 50%;
}
.top-16 {
top: 4rem;
}
.top-3 {
top: 0.75rem;
}
@ -1026,6 +1064,10 @@ select {
margin-bottom: 2rem;
}
.me-1 {
margin-inline-end: 0.25rem;
}
.ml-1 {
margin-left: 0.25rem;
}
@ -1278,6 +1320,10 @@ select {
width: 1.5rem;
}
.w-72 {
width: 18rem;
}
.w-8 {
width: 2rem;
}
@ -1414,6 +1460,16 @@ select {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
.cursor-default {
cursor: default;
}
@ -1485,6 +1541,14 @@ select {
gap: 0.25rem;
}
.gap-2 {
gap: 0.5rem;
}
.gap-3 {
gap: 0.75rem;
}
.gap-4 {
gap: 1rem;
}
@ -1581,6 +1645,10 @@ select {
border-radius: 0.25rem;
}
.rounded-2xl {
border-radius: 1rem;
}
.rounded-full {
border-radius: 9999px;
}
@ -1682,6 +1750,11 @@ select {
border-color: rgb(209 213 219 / var(--tw-border-opacity));
}
.border-primary-500 {
--tw-border-opacity: 1;
border-color: rgb(3 91 113 / var(--tw-border-opacity));
}
.border-transparent {
border-color: transparent;
}
@ -1696,6 +1769,11 @@ select {
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}
.bg-gray-200 {
--tw-bg-opacity: 1;
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
}
.bg-gray-300 {
--tw-bg-opacity: 1;
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
@ -1825,6 +1903,14 @@ select {
--tw-bg-opacity: 0.8;
}
.bg-none {
background-image: none;
}
.fill-gray-400 {
fill: #9ca3af;
}
.bg-opacity-100 {
--tw-bg-opacity: 1;
}
@ -1878,6 +1964,10 @@ select {
padding: 1rem;
}
.p-5 {
padding: 1.25rem;
}
.\!px-2 {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
@ -2359,6 +2449,10 @@ select {
opacity: 1;
}
.opacity-25 {
opacity: 0.25;
}
.opacity-30 {
opacity: 0.3;
}
@ -2371,6 +2465,10 @@ select {
opacity: 0.5;
}
.opacity-75 {
opacity: 0.75;
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@ -2412,6 +2510,10 @@ select {
--tw-shadow: var(--tw-shadow-colored);
}
.outline {
outline-style: solid;
}
.outline-0 {
outline-width: 0px;
}
@ -2572,6 +2674,11 @@ select {
color: rgb(75 85 99 / var(--tw-text-opacity));
}
.hover\:border-primary-500:hover {
--tw-border-opacity: 1;
border-color: rgb(3 91 113 / var(--tw-border-opacity));
}
.hover\:bg-gray-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
@ -2597,6 +2704,16 @@ select {
background-color: rgb(205 222 227 / var(--tw-bg-opacity));
}
.hover\:bg-primary-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(154 189 198 / var(--tw-bg-opacity));
}
.hover\:bg-primary-600:hover {
--tw-bg-opacity: 1;
background-color: rgb(2 73 90 / var(--tw-bg-opacity));
}
.hover\:bg-red-500:hover {
--tw-bg-opacity: 1;
background-color: rgb(255 0 0 / var(--tw-bg-opacity));
@ -2768,11 +2885,38 @@ select {
cursor: not-allowed;
}
.disabled\:border-primary-300:disabled {
--tw-border-opacity: 1;
border-color: rgb(104 157 170 / var(--tw-border-opacity));
}
.disabled\:bg-primary-200:disabled {
--tw-bg-opacity: 1;
background-color: rgb(154 189 198 / var(--tw-bg-opacity));
}
.disabled\:bg-primary-300:disabled {
--tw-bg-opacity: 1;
background-color: rgb(104 157 170 / var(--tw-bg-opacity));
}
.disabled\:bg-primary-400:disabled {
--tw-bg-opacity: 1;
background-color: rgb(53 124 141 / var(--tw-bg-opacity));
}
.disabled\:text-primary-300:disabled {
--tw-text-opacity: 1;
color: rgb(104 157 170 / var(--tw-text-opacity));
}
.disabled\:text-primary-400:disabled {
--tw-text-opacity: 1;
color: rgb(53 124 141 / var(--tw-text-opacity));
}
.group:hover .group-hover\:fill-gray-500 {
fill: #6b7280;
.group:hover .group-hover\:block {
display: block;
}
@ -3348,6 +3492,10 @@ select {
width: fit-content;
}
.lg\:grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.lg\:flex-nowrap {
flex-wrap: nowrap;
}

88
src/components/Button.vue Normal file
View File

@ -0,0 +1,88 @@
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps({
type: {
type: String as () => 'button' | 'submit' | 'reset',
default: 'button'
},
onClick: {
type: Function as unknown as () => (payload: MouseEvent) => void,
default: () => {}
},
label: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
isLoading: {
type: Boolean,
default: false
},
className: {
type: String,
default: ''
},
styleType: {
type: String as () => 'filled' | 'secondary' | 'outline' | 'text',
default: 'filled'
}
})
const buttonStyle = computed(() => {
switch (props.styleType) {
case 'filled':
return 'text-white border-transparent rounded-lg bg-primary-500 hover:bg-primary-600 focus:outline-0 disabled:bg-primary-200 disabled:text-primary-400'
case 'secondary':
return 'text-primary-500 bg-primary-50 border-transparent rounded-lg hover:bg-primary-200 focus:outline-0 disabled:bg-primary-300'
case 'outline':
return 'bg-none text-primary-500 border border-primary-500 rounded-lg disabled:border-primary-300 disabled:text-primary-300'
case 'text':
return 'bg-none text-primary-500 border border-transparent hover:border-primary-500 rounded-lg disabled:border-primary-300 disabled:text-primary-300'
}
})
</script>
<template>
<button
:type="type"
@click="onClick"
:disabled="isLoading ? true : disabled"
:class="['px-3 py-2 text-sm font-semibold', buttonStyle, className]"
>
<div class="flex items-center" v-if="!isLoading">
<span class="me-1">{{ label }}</span>
<slot></slot>
</div>
<span v-else>
<center>
<svg
class="animate-spin h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</center>
</span>
</button>
</template>

View File

@ -0,0 +1,44 @@
<script setup lang="ts">
// components
import Button from '@/components/Button.vue';
// icons
import {
PhArrowsCounterClockwise,
PhFileText,
PhMagnifyingGlass
} from '@phosphor-icons/vue';
defineProps({
reportButton: {
type: Boolean,
default: false
}
})
</script>
<template>
<div class="filters rounded-2xl shadow">
<form class="filter-body bg-gray-50 mx-auto space-y-3 p-4">
<slot></slot>
</form>
<div class="filter-footer px-4 py-3 bg-primary-50 flex justify-end">
<div class="filter-buttons flex gap-3 flex-wrap">
<Button label="Ulangi" style-type="outline" class-name="bg-white">
<PhArrowsCounterClockwise size="18" class="ml-1" weight="regular" />
</Button>
<Button v-if="reportButton" label="Lihat Laporan" style-type="outline" class-name="bg-white">
<PhFileText size="18" class="ml-1" weight="regular" />
</Button>
<Button label="Cari Data">
<PhMagnifyingGlass size="18" class="ml-1" weight="regular" />
</Button>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,67 @@
<template>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Regional:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Regional</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Induk Distribusi/Wilayah:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Induk Distribusi/Wilayah</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Pelaksanaan Pelayanan Pelanggan:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Pelaksanaan Pelayanan Pelanggan</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Layanan Pelanggan:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Layanan Pelanggan</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Periode:</label>
<div class="flex gap-2">
<div class="flex-1 relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Juli</option>
</select>
</div>
<div class="flex-1 relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">2023</option>
</select>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,61 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import VueTailwindDatepicker from 'vue-tailwind-datepicker'
const dateValue = ref([])
const formatter = ref({
date: 'DD MMM YYYY',
month: 'MMM'
})
</script>
<template>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Induk Distribusi/Wilayah:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Induk Distribusi/Wilayah</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Pelaksanaan Pelayanan Pelanggan:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Pelaksanaan Pelayanan Pelanggan</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Unit Layanan Pelanggan:</label>
<div class="relative w-full overflow-hidden rounded-lg bg-gray-200">
<select
class="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0">
<option value="">Semua Unit Layanan Pelanggan</option>
</select>
</div>
</div>
<div class="sm:grid sm:grid-cols-2 lg:grid-cols-3 sm:items-center">
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Periode Tanggal:</label>
<div class="flex-1 relative w-full rounded-lg bg-gray-200">
<vue-tailwind-datepicker
input-classes="w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0"
v-model="dateValue"
:formatter="formatter"
separator=" s/d "
:shortcuts="false"
:auto-apply="false"
/>
</div>
</div>
</template>

58
src/components/Input.vue Normal file
View File

@ -0,0 +1,58 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps({
type: {
type: String as () => "text" | "password" | "select" | "textarea",
default: "text",
},
placeholder: {
type: String,
default: "",
},
value: {
type: String,
default: "",
},
disabled: {
type: Boolean,
default: false,
},
readonly: {
type: Boolean,
default: false,
},
className: {
type: String,
default: "",
}
})
const emit = defineEmits(['update:value'])
const updateValue = (event: Event) => {
const value = (event.target as HTMLInputElement).value;
emit('update:value', value)
}
const inputType = ref(props.type)
const switchInputType = () => {
inputType.value = inputType.value == 'password' ? 'text' : 'password'
}
</script>
<template>
<div :class="['relative w-full overflow-hidden rounded-lg bg-gray-50 ', className]">
<input autocomplete="off" :type="inputType" :placeholder="placeholder" :value="value"
:disabled="disabled" :readonly="readonly"
:class="['w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-50 focus:outline-0 focus:border-0 focus:ring-0']" />
<span @click="switchInputType" v-if="type == 'password'"
class="absolute top-0 bottom-0 right-0 mx-3 my-auto cursor-pointer h-fit">
<svg width="20" height="20" viewBox="0 0 20 20"
:class="[inputType == 'password' ? 'fill-gray-500' : 'fill-primary-500']">
<path
d="M19.3211 9.74688C19.2937 9.68516 18.632 8.21719 17.1609 6.74609C15.2008 4.78594 12.725 3.75 9.99999 3.75C7.27499 3.75 4.79921 4.78594 2.83905 6.74609C1.36796 8.21719 0.703118 9.6875 0.678899 9.74688C0.643362 9.82681 0.625 9.91331 0.625 10.0008C0.625 10.0883 0.643362 10.1748 0.678899 10.2547C0.706243 10.3164 1.36796 11.7836 2.83905 13.2547C4.79921 15.2141 7.27499 16.25 9.99999 16.25C12.725 16.25 15.2008 15.2141 17.1609 13.2547C18.632 11.7836 19.2937 10.3164 19.3211 10.2547C19.3566 10.1748 19.375 10.0883 19.375 10.0008C19.375 9.91331 19.3566 9.82681 19.3211 9.74688ZM9.99999 15C7.5953 15 5.49452 14.1258 3.75546 12.4023C3.0419 11.6927 2.43483 10.8836 1.95312 10C2.4347 9.11636 3.04179 8.30717 3.75546 7.59766C5.49452 5.87422 7.5953 5 9.99999 5C12.4047 5 14.5055 5.87422 16.2445 7.59766C16.9595 8.307 17.5679 9.11619 18.0508 10C17.4875 11.0516 15.0336 15 9.99999 15ZM9.99999 6.25C9.25831 6.25 8.53329 6.46993 7.9166 6.88199C7.29992 7.29404 6.81927 7.87971 6.53544 8.56494C6.25162 9.25016 6.17735 10.0042 6.32205 10.7316C6.46674 11.459 6.82389 12.1272 7.34834 12.6517C7.87279 13.1761 8.54097 13.5333 9.2684 13.6779C9.99583 13.8226 10.7498 13.7484 11.4351 13.4645C12.1203 13.1807 12.7059 12.7001 13.118 12.0834C13.5301 11.4667 13.75 10.7417 13.75 10C13.749 9.00576 13.3535 8.05253 12.6505 7.34949C11.9475 6.64645 10.9942 6.25103 9.99999 6.25ZM9.99999 12.5C9.50554 12.5 9.02219 12.3534 8.61107 12.0787C8.19994 11.804 7.87951 11.4135 7.69029 10.9567C7.50107 10.4999 7.45157 9.99723 7.54803 9.51227C7.64449 9.02732 7.88259 8.58186 8.23222 8.23223C8.58186 7.8826 9.02731 7.6445 9.51227 7.54804C9.99722 7.45157 10.4999 7.50108 10.9567 7.6903C11.4135 7.87952 11.804 8.19995 12.0787 8.61107C12.3534 9.0222 12.5 9.50555 12.5 10C12.5 10.663 12.2366 11.2989 11.7678 11.7678C11.2989 12.2366 10.663 12.5 9.99999 12.5Z" />
</svg>
</span>
</div>
</template>

View File

@ -46,7 +46,7 @@ const switchInputType = () => {
<div :class="['relative w-full overflow-hidden rounded-lg bg-gray-50 ', className]">
<input autocomplete="off" :type="inputType" :placeholder="placeholder" :value="value" @input="updateValue($event)"
:disabled="disabled" :readonly="readonly"
:class="['w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-50 focus:outline-0 focus:border-0 focus:ring-0']" />
:class="['w-full px-4 py-2 text-sm leading-6 placeholder:text-gray-400 text-gray-900 border-0 border-transparent rounded-lg outline-0 bg-gray-200 focus:outline-0 focus:border-0 focus:ring-0']" />
<span @click="switchInputType" v-if="type == 'password'"
class="absolute top-0 bottom-0 right-0 mx-3 my-auto cursor-pointer h-fit">
<svg width="20" height="20" viewBox="0 0 20 20"

View File

@ -7,6 +7,7 @@ import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')

View File

@ -2,6 +2,7 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import HomeView from '@/views/HomeView.vue'
import TestView from '@/views/TestView.vue'
import LoginView from '@/views/LoginView.vue'
import NotFoundView from '@/views/NotFoundView.vue'
import WelcomePage from '@/components/Pages/Welcome.vue'
@ -529,6 +530,11 @@ export const routes: RouteRecordRaw[] = [
name: 'Login',
component: LoginView
},
{
path: '/playground',
name: 'Playground',
component: TestView
},
{
path: '/404',
name: 'Not Found',

96
src/views/TestView.vue Normal file
View File

@ -0,0 +1,96 @@
<script setup lang="ts">
import Filters from '@/components/Form/Filters.vue'
import Type2 from '@/components/Form/FiltersType/Type2.vue'
</script>
<template>
<div class="container h-full p-5 mx-auto">
<Filters :reportButton="true" >
<Type2/>
</Filters>
</div>
</template>
<!-- <template>
<div class="fixed top-16 w-72">
<Combobox v-model="selected" v-slot="{ open }">
<div class="relative mt-1">
<div
class="relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left shadow-md focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-teal-300 sm:text-sm">
<ComboboxInput class="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 text-gray-900 focus:ring-0"
:displayValue="(person: any) => (show || open) ? '' : person.name" @change="query = $event.target.value" @click="show = true" @blur="show = false" defaultValue="sasa" />
<ComboboxButton id="Test" class="absolute inset-y-0 right-0 flex items-center pr-2">
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
</ComboboxButton>
</div>
<TransitionRoot :show="show || open" leave="transition ease-in duration-100" leaveFrom="opacity-100" leaveTo="opacity-0"
@after-leave="query = ''">
<ComboboxOptions
class="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<div v-if="filteredPeople.length === 0 && query !== ''"
class="relative cursor-default select-none py-2 px-4 text-gray-700">
Nothing found.
</div>
<ComboboxOption v-for="person in filteredPeople" as="template" :key="person.id" :value="person"
v-slot="{ selected, active }">
<li class="relative cursor-default select-none py-2 pl-10 pr-4" :class="{
'bg-teal-600 text-white': active,
'text-gray-900': !active,
}">
<span class="block truncate" :class="{ 'font-medium': selected, 'font-normal': !selected }">
{{ person.name }}
</span>
<span v-if="selected" class="absolute inset-y-0 left-0 flex items-center pl-3"
:class="{ 'text-white': active, 'text-teal-600': !active }">
<CheckIcon class="h-5 w-5" aria-hidden="true" />
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</TransitionRoot>
</div>
</Combobox>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import {
Combobox,
ComboboxInput,
ComboboxButton,
ComboboxOptions,
ComboboxOption,
TransitionRoot,
} from '@headlessui/vue'
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/vue/20/solid'
const people = [
{ id: 1, name: 'Semua Regional' },
{ id: 2, name: 'Arlene Mccoy' },
{ id: 3, name: 'Devon Webb' },
{ id: 4, name: 'Tom Cook' },
{ id: 5, name: 'Tanya Fox' },
{ id: 6, name: 'Hellen Schmidt' },
]
let selected = ref(people[0])
let query = ref('')
let filteredPeople = computed(() =>
query.value === ''
? people
: people.filter((person) =>
person.name
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, ''))
)
)
const show = ref(false)
</script> -->