135 lines
6.8 KiB
Vue
135 lines
6.8 KiB
Vue
<template>
|
|
<div>
|
|
<!-- Storage Items -->
|
|
<div class="product-list" v-if="storage.length">
|
|
<div v-for="item in storage" :key="item.item_name" class="listing-card">
|
|
<img :src="getItemImage(item.item_name)" @error="onImgError" class="product-card-img" />
|
|
<div class="listing-card-info">
|
|
<div class="listing-name">{{ item.item_label }}</div>
|
|
<div class="listing-meta">{{ item.quantity }}x eingelagert</div>
|
|
</div>
|
|
<div v-if="!viewOnly" class="listing-card-actions">
|
|
<button class="listing-action-btn" @click="startMoveToShelf(item)" title="Auf Regal stellen">
|
|
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else class="empty-state">
|
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg>
|
|
<div>Lager ist leer</div>
|
|
</div>
|
|
|
|
<!-- Add from Inventory (owner only) -->
|
|
<div v-if="!viewOnly && !movingItem" style="margin-top: 10px;">
|
|
<button v-if="!showInventory" class="create-zone-btn" @click="showInventory = true">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
|
Aus Inventar einlagern
|
|
</button>
|
|
|
|
<div v-if="showInventory">
|
|
<div class="search-bar">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
|
<input type="text" v-model="search" placeholder="Item suchen..." />
|
|
</div>
|
|
<div class="product-list scrollable-list" v-if="filteredItems.length">
|
|
<div v-for="item in filteredItems" :key="item.name" class="product-card" @click="selectInventoryItem(item)">
|
|
<img :src="getItemImage(item.name)" @error="onImgError" class="product-card-img" />
|
|
<div class="product-card-info">
|
|
<div class="product-name">{{ item.label }}</div>
|
|
<div class="product-meta">{{ item.amount }}x vorhanden</div>
|
|
</div>
|
|
<svg class="product-card-arrow" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
|
|
</div>
|
|
</div>
|
|
<div v-else class="empty-state">
|
|
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>
|
|
<div>{{ search ? 'Nichts gefunden' : 'Inventar leer' }}</div>
|
|
</div>
|
|
<button class="shop-btn small red" @click="showInventory = false" style="margin-top: 6px;">Schliessen</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Selected inventory item -->
|
|
<div v-if="selectedInvItem" class="detail-section" style="margin-top: 10px;">
|
|
<div class="quantity-label" style="margin-bottom: 6px;">{{ selectedInvItem.label }} einlagern</div>
|
|
<div class="quantity-section" style="padding: 0; border: none;">
|
|
<div class="quantity-row">
|
|
<span class="quantity-label">Menge</span>
|
|
<button class="qty-btn" @click="invQty = Math.max(1, invQty - 1)">-</button>
|
|
<span class="quantity-value">{{ invQty }}</span>
|
|
<button class="qty-btn" @click="invQty = Math.min(selectedInvItem.amount, invQty + 1)">+</button>
|
|
<span class="quantity-max">max {{ selectedInvItem.amount }}</span>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; gap: 6px; margin-top: 8px;">
|
|
<button class="shop-btn small" @click="addToStorage">Einlagern</button>
|
|
<button class="shop-btn small red" @click="selectedInvItem = null">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Move to shelf modal -->
|
|
<div v-if="movingItem" class="detail-section" style="margin-top: 10px;">
|
|
<div class="quantity-label" style="margin-bottom: 6px;">{{ movingItem.item_label }} auf Regal stellen</div>
|
|
<div style="margin-bottom: 6px;">
|
|
<div class="quantity-label" style="margin-bottom: 4px;">Preis ($)</div>
|
|
<input type="number" class="price-input" v-model.number="movePrice" min="1" max="9999999" />
|
|
</div>
|
|
<div class="quantity-section" style="padding: 0; border: none; margin-bottom: 6px;">
|
|
<div class="quantity-row">
|
|
<span class="quantity-label">Menge</span>
|
|
<button class="qty-btn" @click="moveQty = Math.max(1, moveQty - 1)">-</button>
|
|
<span class="quantity-value">{{ moveQty }}</span>
|
|
<button class="qty-btn" @click="moveQty = Math.min(movingItem.quantity, moveQty + 1)">+</button>
|
|
<span class="quantity-max">max {{ movingItem.quantity }}</span>
|
|
</div>
|
|
</div>
|
|
<div style="display: flex; gap: 6px;">
|
|
<button class="shop-btn small" :disabled="!movePrice" @click="confirmMove">Einstellen</button>
|
|
<button class="shop-btn small red" @click="movingItem = null">Abbrechen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed } from 'vue'
|
|
const props = defineProps({
|
|
storage: { type: Array, default: () => [] },
|
|
playerItems: { type: Array, default: () => [] },
|
|
viewOnly: { type: Boolean, default: false },
|
|
})
|
|
const emit = defineEmits(['addToStorage', 'moveToShelves'])
|
|
|
|
const search = ref('')
|
|
const showInventory = ref(false)
|
|
const selectedInvItem = ref(null)
|
|
const invQty = ref(1)
|
|
const movingItem = ref(null)
|
|
const movePrice = ref(100)
|
|
const moveQty = ref(1)
|
|
|
|
const filteredItems = computed(() => {
|
|
const items = props.playerItems.filter(i => i.amount > 0)
|
|
if (!search.value.trim()) return items
|
|
const q = search.value.toLowerCase()
|
|
return items.filter(i => (i.label || i.name).toLowerCase().includes(q))
|
|
})
|
|
|
|
function getItemImage(name) { const n = (name || 'example').replace(/\.png$/i, ''); return `https://cfx-nui-codem-inventory/html/itemimages/${n}.png` }
|
|
function onImgError(e) { if (!e.target.src.endsWith('example.png')) e.target.src = './items/example.png' }
|
|
|
|
function selectInventoryItem(item) { selectedInvItem.value = item; invQty.value = 1; showInventory.value = false }
|
|
function addToStorage() {
|
|
if (!selectedInvItem.value) return
|
|
emit('addToStorage', { itemName: selectedInvItem.value.name, itemLabel: selectedInvItem.value.label, quantity: invQty.value })
|
|
selectedInvItem.value = null
|
|
}
|
|
function startMoveToShelf(item) { movingItem.value = item; movePrice.value = 100; moveQty.value = 1 }
|
|
function confirmMove() {
|
|
if (!movingItem.value || !movePrice.value) return
|
|
emit('moveToShelves', { itemName: movingItem.value.item_name, quantity: moveQty.value, price: movePrice.value })
|
|
movingItem.value = null
|
|
}
|
|
</script>
|