mirror of
https://github.com/hay-kot/homebox.git
synced 2025-08-03 16:20:27 +00:00
add location selector
This commit is contained in:
parent
55ac472c9e
commit
fb9e3d6735
5 changed files with 59 additions and 12 deletions
|
@ -50,7 +50,7 @@
|
|||
interface Props {
|
||||
label: string;
|
||||
modelValue: string | ItemsObject;
|
||||
items: string[] | ItemsObject[];
|
||||
items: ItemsObject[] | Record<string, unknown>[] | string[];
|
||||
itemText?: keyof ItemsObject;
|
||||
itemValue?: keyof ItemsObject;
|
||||
search?: string;
|
||||
|
|
|
@ -17,20 +17,18 @@
|
|||
<Icon name="heroicons-map-pin" class="swap-off" />
|
||||
</label>
|
||||
{{ location.name }}
|
||||
<span v-if="location.itemCount" class="badge badge-secondary badge-lg ml-auto text-secondary-content">
|
||||
{{ location.itemCount }}</span
|
||||
>
|
||||
<span v-if="hasCount" class="badge badge-secondary badge-lg ml-auto text-secondary-content"> {{ count }}</span>
|
||||
</h2>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { LocationOutCount } from "~~/lib/api/types/data-contracts";
|
||||
import { LocationOut, LocationOutCount, LocationSummary } from "~~/lib/api/types/data-contracts";
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
location: {
|
||||
type: Object as () => LocationOutCount,
|
||||
type: Object as () => LocationOutCount | LocationOut | LocationSummary,
|
||||
required: true,
|
||||
},
|
||||
dense: {
|
||||
|
@ -39,6 +37,16 @@
|
|||
},
|
||||
});
|
||||
|
||||
const hasCount = computed(() => {
|
||||
return !!(props.location as LocationOutCount).itemCount;
|
||||
});
|
||||
|
||||
const count = computed(() => {
|
||||
if (hasCount.value) {
|
||||
return (props.location as LocationOutCount).itemCount;
|
||||
}
|
||||
});
|
||||
|
||||
const card = ref(null);
|
||||
const isHover = useElementHover(card);
|
||||
const { focused } = useFocus(card);
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { BaseAPI, route } from "../base";
|
||||
import { LocationOutCount, LocationCreate, LocationOut } from "../types/data-contracts";
|
||||
import { LocationOutCount, LocationCreate, LocationOut, LocationUpdate } from "../types/data-contracts";
|
||||
import { Results } from "../types/non-generated";
|
||||
|
||||
export type LocationUpdate = LocationCreate;
|
||||
|
||||
export class LocationsApi extends BaseAPI {
|
||||
getAll() {
|
||||
return this.http.get<Results<LocationOutCount>>({ url: route("/locations") });
|
||||
|
|
|
@ -191,11 +191,13 @@ export interface LocationCreate {
|
|||
}
|
||||
|
||||
export interface LocationOut {
|
||||
children: LocationSummary[];
|
||||
createdAt: Date;
|
||||
description: string;
|
||||
id: string;
|
||||
items: ItemSummary[];
|
||||
name: string;
|
||||
parent: LocationSummary;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
|
@ -216,6 +218,13 @@ export interface LocationSummary {
|
|||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface LocationUpdate {
|
||||
description: string;
|
||||
id: string;
|
||||
name: string;
|
||||
parentId: string | null;
|
||||
}
|
||||
|
||||
export interface PaginationResultRepoItemSummary {
|
||||
items: ItemSummary[];
|
||||
page: number;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { Detail, CustomDetail } from "~~/components/global/DetailsSection/types";
|
||||
import { LocationSummary, LocationUpdate } from "~~/lib/api/types/data-contracts";
|
||||
import { useLocationStore } from "~~/stores/locations";
|
||||
|
||||
definePageMeta({
|
||||
middleware: ["auth"],
|
||||
|
@ -20,6 +22,11 @@
|
|||
navigateTo("/home");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.parent) {
|
||||
parent.value = locations.value.find(l => l.id === data.parent.id);
|
||||
}
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
|
@ -80,9 +87,11 @@
|
|||
|
||||
const updateModal = ref(false);
|
||||
const updating = ref(false);
|
||||
const updateData = reactive({
|
||||
const updateData = reactive<LocationUpdate>({
|
||||
id: locationId.value,
|
||||
name: "",
|
||||
description: "",
|
||||
parentId: null,
|
||||
});
|
||||
|
||||
function openUpdate() {
|
||||
|
@ -93,6 +102,7 @@
|
|||
|
||||
async function update() {
|
||||
updating.value = true;
|
||||
updateData.parentId = parent.value?.id || null;
|
||||
const { error, data } = await api.locations.update(locationId.value, updateData);
|
||||
|
||||
if (error) {
|
||||
|
@ -105,6 +115,12 @@
|
|||
updateModal.value = false;
|
||||
updating.value = false;
|
||||
}
|
||||
|
||||
const locationStore = useLocationStore();
|
||||
const locations = computed(() => locationStore.locations);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const parent = ref<LocationSummary | any>({});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -114,6 +130,7 @@
|
|||
<form v-if="location" @submit.prevent="update">
|
||||
<FormTextField v-model="updateData.name" :autofocus="true" label="Location Name" />
|
||||
<FormTextArea v-model="updateData.description" label="Location Description" />
|
||||
<FormAutocomplete v-model="parent" :items="locations" item-text="name" item-value="id" label="Parent" />
|
||||
<div class="modal-action">
|
||||
<BaseButton type="submit" :loading="updating"> Update </BaseButton>
|
||||
</div>
|
||||
|
@ -127,6 +144,14 @@
|
|||
<span class="text-base-content">
|
||||
{{ location ? location.name : "" }}
|
||||
</span>
|
||||
<div v-if="location && location.parent" class="text-sm breadcrumbs pb-0">
|
||||
<ul class="text-base-content/70">
|
||||
<li>
|
||||
<NuxtLink :to="`/location/${location.parent.id}`"> {{ location.parent.name }}</NuxtLink>
|
||||
</li>
|
||||
<li>{{ location.name }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</BaseSectionHeader>
|
||||
</template>
|
||||
|
||||
|
@ -152,11 +177,18 @@
|
|||
<DetailsSection :details="details" />
|
||||
</BaseCard>
|
||||
|
||||
<section v-if="location">
|
||||
<section v-if="location && location.items.length > 0">
|
||||
<BaseSectionHeader class="mb-5"> Items </BaseSectionHeader>
|
||||
<div class="grid gap-2 grid-cols-1 sm:grid-cols-2">
|
||||
<ItemCard v-for="item in location.items" :key="item.id" :item="item" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="location && location.children.length > 0">
|
||||
<BaseSectionHeader class="mb-5"> Child Locations </BaseSectionHeader>
|
||||
<div class="grid gap-2 grid-cols-1 sm:grid-cols-3">
|
||||
<LocationCard v-for="item in location.children" :key="item.id" :location="item" />
|
||||
</div>
|
||||
</section>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue