implement filters to the menu

This commit is contained in:
kur0nek-o 2023-10-27 20:22:36 +07:00
parent dfcd95ba8a
commit 0f6ed81e48
10 changed files with 211 additions and 212 deletions

View File

@ -1607,10 +1607,6 @@ select {
--tw-divide-opacity: 0.1;
}
.divide-opacity-100 > :not([hidden]) ~ :not([hidden]) {
--tw-divide-opacity: 1;
}
.overflow-auto {
overflow: auto;
}
@ -1676,6 +1672,11 @@ select {
border-top-right-radius: 1rem;
}
.rounded-b-2xl {
border-bottom-right-radius: 1rem;
border-bottom-left-radius: 1rem;
}
.border {
border-width: 1px;
}
@ -1869,6 +1870,10 @@ select {
background-color: rgb(204 204 0 / var(--tw-bg-opacity));
}
.bg-opacity-100 {
--tw-bg-opacity: 1;
}
.bg-opacity-25 {
--tw-bg-opacity: 0.25;
}
@ -1889,8 +1894,8 @@ select {
--tw-bg-opacity: 0.8;
}
.bg-opacity-100 {
--tw-bg-opacity: 1;
.bg-none {
background-image: none;
}
.fill-gray-500 {
@ -1946,6 +1951,10 @@ select {
padding: 1.25rem;
}
.p-0 {
padding: 0px;
}
.\!px-2 {
padding-left: 0.5rem !important;
padding-right: 0.5rem !important;
@ -2112,10 +2121,6 @@ select {
padding-top: 0.5rem;
}
.pt-4 {
padding-top: 1rem;
}
.pt-5 {
padding-top: 1.25rem;
}
@ -2266,6 +2271,11 @@ select {
color: rgb(21 22 23 / var(--tw-text-opacity));
}
.text-gray-200 {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
}
.text-gray-300 {
--tw-text-opacity: 1;
color: rgb(209 213 219 / var(--tw-text-opacity));
@ -2396,11 +2406,6 @@ select {
color: rgb(153 153 0 / var(--tw-text-opacity));
}
.text-gray-200 {
--tw-text-opacity: 1;
color: rgb(229 231 235 / var(--tw-text-opacity));
}
.text-opacity-40 {
--tw-text-opacity: 0.4;
}
@ -3361,24 +3366,14 @@ select {
padding: 5rem;
}
.md\:px-4 {
padding-left: 1rem;
padding-right: 1rem;
}
.md\:py-0 {
padding-top: 0px;
padding-bottom: 0px;
}
.md\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.md\:py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
.md\:py-0 {
padding-top: 0px;
padding-bottom: 0px;
}
.md\:pl-4 {
@ -3476,21 +3471,6 @@ select {
padding-right: 2rem;
}
.lg\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
.lg\:py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
.lg\:text-3xl {
font-size: 1.875rem;
line-height: 2.25rem;
}
.lg\:text-xs {
font-size: 0.75rem;
line-height: 1rem;

View File

@ -0,0 +1,21 @@
<script setup lang="ts">
import { ref } from 'vue'
import VueTailwindDatepicker from 'vue-tailwind-datepicker'
const dateValue = ref('')
const formatter = ref({
date: 'DD MMM YYYY',
month: 'MMM'
})
</script>
<template>
<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"
/>
</template>

View File

@ -18,13 +18,13 @@
</script>
<template>
<div class="filters rounded-2xl shadow">
<div class="filters rounded-2xl">
<form class="filter-body bg-gray-50 mx-auto space-y-3 p-4">
<form class="filter-body bg-gray-50 mx-auto space-y-3 p-4 rounded-t-2xl">
<slot></slot>
</form>
<div class="filter-footer px-4 py-3 bg-primary-50 flex justify-end">
<div class="filter-footer rounded-b-2xl 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" />

View File

@ -1,67 +1,32 @@
<script setup lang="ts">
import Select from '@/components/Select.vue'
import DatePicker from '@/components/DatePicker.vue'
</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">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>
<Select placeholder="Semua Unit Induk Distribusi/Wilayah"/>
</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>
<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>
<Select placeholder="Semua Unit Pelaksanaan Pelayanan Pelanggan" />
</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>
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Posko:</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>
<Select placeholder="Semua Posko" />
</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>
<label class="text-gray-800 font-bold mb-2 sm:mb-0 block">Periode Tanggal:</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>
<DatePicker />
</div>
</template>
</template>

View File

@ -1,14 +1,3 @@
<script setup lang="ts">
import { ref } 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>
@ -45,17 +34,5 @@
<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>

View File

@ -2,7 +2,7 @@
import type { MenuItemModel } from '@/types/menu'
import { IconDotOutline } from '@/utils/icons';
defineProps({
const props = defineProps({
item: {
type: Object as () => MenuItemModel,
required: true
@ -29,7 +29,7 @@ defineProps({
<component :is="item.icon"
:class="[selected ? 'text-white fill-white' : 'text-aside group-hover:text-white group-hover:fill-white', 'mr-2 flex-shrink-0 h-6 w-6']"
aria-hidden="true" />
{{ item.name }}
{{ item.name.split(' | ')[0] }}
</RouterLink>
</div>
</template>@/utils/menu
</template>

View File

@ -1,9 +1,13 @@
<template>
<main class="flex-1 px-4 overflow-y-auto bg-white md:mr-3 sm:px-3 md:px-6 rounded-t-2xl md:rounded-t-3xl no-scroll-bar">
<div v-if="route.path !== '/home'" class="mt-4 lg:mt-6 max-w-7xl">
<h1 class="text-xl font-medium md:text-3xl text-dark">{{ currentRouteName }}</h1>
</div>
<h1 class="text-xl font-medium md:text-3xl text-dark">{{ pageMetaData[0] }}</h1>
</div>
<div class="mt-2 sm:mt-4 dx-viewport">
<Filters :report-button="typeof pageMetaData[2] !== 'undefined'" class="mb-4" v-if="pageMetaData.length > 1">
<Type1 v-if="pageMetaData[1] == 'type-1'" />
</Filters>
<slot></slot>
</div>
</main>
@ -12,10 +16,23 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import Filters from '../Form/Filters.vue'
import Type1 from '../Form/FiltersType/Type1.vue';
// Dapatkan objek route dari vue-router
const route = useRoute()
// Dapatkan nama rute menggunakan computed property
const currentRouteName = computed(() => route.name)
const pageMetaData = computed(() => {
let result: string[] = [];
if (typeof route.name === 'string' && route.name.includes(' | ')) {
result = route.name.split(' | ');
} else if (typeof route.name === 'string') {
result = [route.name]
}
return result
});
</script>

120
src/components/Select.vue Normal file
View File

@ -0,0 +1,120 @@
<script setup lang="ts">
interface DataItem {
id: number;
value: string;
}
import { ref, computed } from 'vue'
import {
Combobox,
ComboboxInput,
ComboboxButton,
ComboboxOptions,
ComboboxOption,
TransitionRoot
} from '@headlessui/vue'
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/vue/20/solid'
const props = defineProps({
placeholder: {
type: String,
default: ''
},
data: {
type: Array as () => DataItem[],
default: []
}
})
const data: DataItem[] = [
{id: 0, value: props.placeholder},
...props.data
]
let selected = ref(data[0])
let query = ref('')
let filteredData = computed(() =>
query.value === ''
? data
: data.filter((item: DataItem) =>
item.value
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, ''))
)
)
const show = ref(false)
</script>
<template>
<Combobox v-model="selected" v-slot="{ open }">
<div class="relative mt-1">
<div
class="relative w-full cursor-default overflow-hidden rounded-lg bg-gray-200 text-left 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 bg-gray-200 text-sm leading-5 text-gray-900 focus:ring-0"
:displayValue="(item: any) => (show || open ? '' : item.value)"
@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 z-10 max-h-60 w-full overflow-auto rounded-md bg-gray-200 py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
<div
v-if="filteredData.length === 0 && query !== ''"
class="relative cursor-default select-none py-2 px-4 text-gray-700"
>
Nothing found.
</div>
<ComboboxOption
v-for="item in filteredData"
as="template"
:key="item.id"
:value="item"
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 }"
>
{{ item.value }}
</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>
</template>

View File

@ -16,6 +16,8 @@ import {
import {
GangguanRekap1,
} from '@/components/Pages/Gangguan/Rekapitulasi'
import Type1 from '@/components/Form/FiltersType/Type1.vue'
import Button from '@/components/Button.vue'
export const routes: RouteRecordRaw[] = [
{
@ -38,8 +40,9 @@ export const routes: RouteRecordRaw[] = [
children: [
{
path: '1',
name: 'Daftar Keluhan Dialihkan Ke Posko Lain',
name: 'Daftar Keluhan Dialihkan Ke Posko Lain | type-1',
component: GangguanDaftar1,
props: true
},
{
path: '2',

View File

@ -1,96 +1,12 @@
<script setup lang="ts">
import Filters from '@/components/Form/Filters.vue'
import Type2 from '@/components/Form/FiltersType/Type2.vue'
import Type1 from '@/components/Form/FiltersType/Type1.vue'
</script>
<template>
<div class="container h-full p-5 mx-auto">
<Filters :reportButton="true" >
<Type2/>
<Type1/>
</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> -->