✨ feat (nav-header): implement filter component with search and date range
This commit is contained in:
No files matched your search
@@ -0,0 +1,93 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Calendar as CalendarIcon, Filter as FilterIcon, Search } from 'lucide-vue-next'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
import type { DateRange } from 'radix-vue'
|
||||||
|
import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
|
||||||
|
import { cn } from '~/lib/utils'
|
||||||
|
import type { HeaderPrep, RefSearchNav } from '~/components/pub/custom-ui/data/types'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
prep: HeaderPrep
|
||||||
|
refSearchNav?: RefSearchNav
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// function emitSearchNavClick() {
|
||||||
|
// props.refSearchNav?.onClick()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function onInput(event: Event) {
|
||||||
|
// props.refSearchNav?.onInput((event.target as HTMLInputElement).value)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function btnClick() {
|
||||||
|
// props.prep?.addNav?.onClick?.()
|
||||||
|
// }
|
||||||
|
|
||||||
|
const searchQuery = ref('')
|
||||||
|
const dateRange = ref<{ from: Date | null; to: Date | null }>({
|
||||||
|
from: new Date(),
|
||||||
|
to: new Date(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const df = new DateFormatter('en-US', {
|
||||||
|
dateStyle: 'medium',
|
||||||
|
})
|
||||||
|
|
||||||
|
const value = ref({
|
||||||
|
start: new CalendarDate(2022, 1, 20),
|
||||||
|
end: new CalendarDate(2022, 1, 20).add({ days: 20 }),
|
||||||
|
}) as Ref<DateRange>
|
||||||
|
|
||||||
|
function onFilterClick() {
|
||||||
|
console.log('Search:', searchQuery.value)
|
||||||
|
console.log('Date Range:', dateRange.value)
|
||||||
|
props.refSearchNav?.onClick()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<header>
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<div class="relative w-64">
|
||||||
|
<Search class="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-gray-400" />
|
||||||
|
<Input v-model="searchQuery" type="text" placeholder="Cari Nama /No.RM" class="pl-9" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger as-child>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
:class="cn('w-[280px] justify-start text-left font-normal', !value && 'text-muted-foreground')"
|
||||||
|
>
|
||||||
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
|
<template v-if="value.start">
|
||||||
|
<template v-if="value.end">
|
||||||
|
{{ df.format(value.start.toDate(getLocalTimeZone())) }} -
|
||||||
|
{{ df.format(value.end.toDate(getLocalTimeZone())) }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
{{ df.format(value.start.toDate(getLocalTimeZone())) }}
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
<template v-else> Pick a date </template>
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent class="w-auto p-0">
|
||||||
|
<RangeCalendar
|
||||||
|
v-model="value"
|
||||||
|
initial-focus
|
||||||
|
:number-of-months="2"
|
||||||
|
@update:start-value="(startDate) => (value.start = startDate)"
|
||||||
|
/>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<Button variant="outline" class="border-orange-500 text-orange-600 hover:bg-orange-50" @click="onFilterClick">
|
||||||
|
<FilterIcon class="mr-2 size-4" />
|
||||||
|
Filter
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
@@ -24,17 +24,17 @@ function btnClick() {
|
|||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="ml-3 text-lg font-bold text-gray-900">
|
<div class="ml-3 text-lg font-bold text-gray-900">
|
||||||
<Icon :name="props.prep.icon!" class="mr-2 size-4 md:size-6 align-middle" />
|
<Icon :name="props.prep.icon!" class="mr-2 size-4 align-middle md:size-6" />
|
||||||
{{ props.prep.title }}
|
{{ props.prep.title }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div v-if="props.refSearchNav" class="ml-3 text-lg text-gray-900">
|
<div v-if="props.refSearchNav" class="ml-3 text-lg text-gray-900">
|
||||||
<Input
|
<!-- <Input -->
|
||||||
type="text" placeholder="Search"
|
<!-- type="text" placeholder="Search" -->
|
||||||
class="w-full rounded-md border bg-white px-4 py-2 text-gray-900 sm:text-sm" @click="emitSearchNavClick"
|
<!-- class="w-full rounded-md border bg-white px-4 py-2 text-gray-900 sm:text-sm" @click="emitSearchNavClick" -->
|
||||||
@input="onInput"
|
<!-- @input="onInput" -->
|
||||||
/>
|
<!-- /> -->
|
||||||
</div>
|
</div>
|
||||||
<div v-if="prep.addNav" class="m-2 flex items-center">
|
<div v-if="prep.addNav" class="m-2 flex items-center">
|
||||||
<Button size="md" class="rounded-md border border-gray-300 px-4 py-2 text-white sm:text-sm" @click="btnClick">
|
<Button size="md" class="rounded-md border border-gray-300 px-4 py-2 text-white sm:text-sm" @click="btnClick">
|
||||||
|
|||||||
Generated
+1619
-2751
File diff suppressed because it is too large
Load diff
Reference in New Issue
Block a user