151 lines
3.7 KiB
Vue
151 lines
3.7 KiB
Vue
<template>
|
|
<div>
|
|
<div class="flex items-center justify-between mb-6">
|
|
<h1 class="text-3xl font-bold text-gray-900">Inventory</h1>
|
|
|
|
<div class="flex gap-2">
|
|
<UButton
|
|
to="/scan"
|
|
color="primary"
|
|
size="lg"
|
|
icon="i-heroicons-qr-code"
|
|
>
|
|
Scan Item
|
|
</UButton>
|
|
|
|
<UButton
|
|
color="white"
|
|
size="lg"
|
|
icon="i-heroicons-plus"
|
|
@click="showAddForm = true"
|
|
>
|
|
Add Manually
|
|
</UButton>
|
|
|
|
<UButton
|
|
color="gray"
|
|
size="lg"
|
|
icon="i-heroicons-funnel"
|
|
@click="showFilters = !showFilters"
|
|
>
|
|
Filter
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Search & Filters -->
|
|
<UCard v-if="showFilters" class="mb-6 space-y-4">
|
|
<!-- Search Bar -->
|
|
<div>
|
|
<UFormGroup label="Search Items">
|
|
<UInput
|
|
v-model="searchQuery"
|
|
placeholder="Search by item name..."
|
|
icon="i-heroicons-magnifying-glass"
|
|
size="lg"
|
|
:ui="{ icon: { trailing: { pointer: '' } } }"
|
|
>
|
|
<template #trailing>
|
|
<UButton
|
|
v-if="searchQuery"
|
|
color="gray"
|
|
variant="link"
|
|
icon="i-heroicons-x-mark"
|
|
:padded="false"
|
|
@click="searchQuery = ''"
|
|
/>
|
|
</template>
|
|
</UInput>
|
|
</UFormGroup>
|
|
</div>
|
|
|
|
<!-- Tag Filters -->
|
|
<div>
|
|
<TagsTagFilter v-model="selectedTagFilters" />
|
|
</div>
|
|
</UCard>
|
|
|
|
<!-- Add Item Form (Overlay) -->
|
|
<div v-if="showAddForm" class="fixed inset-0 z-50 flex items-start justify-center pt-20 px-4 bg-black/50">
|
|
<div class="w-full max-w-lg">
|
|
<AddItemForm
|
|
:initial-data="prefilledData"
|
|
@close="handleCloseAddForm"
|
|
@added="handleItemAdded"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit Item Modal -->
|
|
<EditItemModal
|
|
:item="editingItem"
|
|
@close="editingItem = null"
|
|
@updated="handleItemUpdated"
|
|
/>
|
|
|
|
<!-- Inventory List -->
|
|
<InventoryList
|
|
ref="inventoryListRef"
|
|
:refresh="refreshKey"
|
|
:tag-filters="selectedTagFilters"
|
|
:search-query="searchQuery"
|
|
@add-item="showAddForm = true"
|
|
@edit-item="editingItem = $event"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
definePageMeta({
|
|
layout: 'default'
|
|
})
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
const showAddForm = ref(false)
|
|
const showFilters = ref(false)
|
|
const editingItem = ref<any>(null)
|
|
const refreshKey = ref(0)
|
|
const inventoryListRef = ref()
|
|
const prefilledData = ref<any>(null)
|
|
const selectedTagFilters = ref<string[]>([])
|
|
const searchQuery = ref('')
|
|
|
|
// Handle scan-to-add flow (Issue #25)
|
|
onMounted(() => {
|
|
if (route.query.action === 'add') {
|
|
// Pre-fill data from query params (from scan)
|
|
prefilledData.value = {
|
|
barcode: route.query.barcode as string || undefined,
|
|
name: route.query.name as string || undefined,
|
|
brand: route.query.brand as string || undefined,
|
|
image_url: route.query.image_url as string || undefined,
|
|
quantity: route.query.quantity as string || undefined,
|
|
}
|
|
|
|
showAddForm.value = true
|
|
|
|
// Clean up URL
|
|
router.replace({ query: {} })
|
|
}
|
|
})
|
|
|
|
const handleCloseAddForm = () => {
|
|
showAddForm.value = false
|
|
prefilledData.value = null
|
|
}
|
|
|
|
const handleItemAdded = (item: any) => {
|
|
showAddForm.value = false
|
|
prefilledData.value = null
|
|
// Reload the inventory list
|
|
inventoryListRef.value?.reload()
|
|
}
|
|
|
|
const handleItemUpdated = (item: any) => {
|
|
editingItem.value = null
|
|
inventoryListRef.value?.reload()
|
|
}
|
|
</script>
|