add variant fileter
This commit is contained in:
@@ -85,6 +85,8 @@
|
||||
<tr class="border-b border-gray-700 bg-gray-700/30">
|
||||
<th class="text-left px-4 py-2 text-gray-400 font-semibold uppercase tracking-wider">Material</th>
|
||||
<th class="text-right px-4 py-2 text-gray-400 font-semibold uppercase tracking-wider">Qty</th>
|
||||
<th class="text-right px-4 py-2 text-gray-400 font-semibold uppercase tracking-wider">Unit Price</th>
|
||||
<th class="text-right px-4 py-2 text-gray-400 font-semibold uppercase tracking-wider">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -100,6 +102,36 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-1.5 text-right font-mono text-gray-200 font-medium">{{ mat.qty.toLocaleString() }}</td>
|
||||
<td class="px-4 py-1.5 text-right font-mono">
|
||||
<div v-if="editingItemId === mat.itemId" class="flex items-center justify-end gap-1">
|
||||
<input
|
||||
v-focus
|
||||
type="number"
|
||||
min="1"
|
||||
:placeholder="mat.unitPrice > 0 ? 'empty to clear' : 'silver'"
|
||||
class="w-28 bg-gray-900 border border-amber-500 rounded px-1.5 py-0.5 text-right text-xs font-mono text-gray-200 focus:outline-none placeholder-gray-600"
|
||||
v-model="inputValue"
|
||||
@keydown.enter="saveEdit(mat.itemId)"
|
||||
@keydown.escape="cancelEdit"
|
||||
/>
|
||||
<button class="text-amber-500 hover:text-amber-300 text-xs leading-none px-0.5" @click="saveEdit(mat.itemId)">✓</button>
|
||||
<button class="text-gray-500 hover:text-gray-300 text-xs leading-none px-0.5" @click="cancelEdit">✕</button>
|
||||
</div>
|
||||
<button
|
||||
v-else
|
||||
class="group flex items-center gap-0.5 ml-auto"
|
||||
:class="priceButtonClass(mat.itemId, mat.unitPrice)"
|
||||
:title="priceTitle(mat.itemId, mat.unitPrice)"
|
||||
@click="startEdit(mat.itemId, mat.unitPrice)"
|
||||
>
|
||||
{{ mat.unitPrice > 0 ? formatSilver(mat.unitPrice) : '—' }}
|
||||
<span class="opacity-0 group-hover:opacity-40 text-[10px] ml-0.5">✎</span>
|
||||
</button>
|
||||
</td>
|
||||
<td class="px-4 py-1.5 text-right font-mono text-gray-200"
|
||||
:title="mat.totalCost > 0 ? mat.totalCost.toLocaleString() : undefined">
|
||||
{{ mat.totalCost > 0 ? formatSilver(mat.totalCost) : '—' }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -169,17 +201,62 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useProductionOrder } from '../composables/useProductionOrder'
|
||||
import { useAlbionPrices } from '../composables/useAlbionPrices'
|
||||
import { useFilters } from '../composables/useFilters'
|
||||
import { formatSilver, formatItemId, tierStyle, itemImageUrl } from '../utils/formatting'
|
||||
import { formatSilver, formatItemId, formatLastUpdated, tierStyle, itemImageUrl } from '../utils/formatting'
|
||||
import type { Tier, JournalType } from '../types/crafting'
|
||||
|
||||
const vFocus = { mounted: (el: HTMLElement) => el.focus() }
|
||||
|
||||
const { orderItems, upsert, remove, clear } = useProductionOrder()
|
||||
const { getPrice } = useAlbionPrices()
|
||||
const { getPrice, isManualPrice, getManualEntry, setManualPrice, clearManualPrice } = useAlbionPrices()
|
||||
const { filters } = useFilters()
|
||||
|
||||
// ─── Inline price editing ─────────────────────────────────────────────────────
|
||||
|
||||
const editingItemId = ref<string | null>(null)
|
||||
const inputValue = ref('')
|
||||
|
||||
function startEdit(itemId: string, current: number) {
|
||||
editingItemId.value = itemId
|
||||
inputValue.value = current > 0 ? String(current) : ''
|
||||
}
|
||||
|
||||
function saveEdit(itemId: string) {
|
||||
const v = Math.round(Number(inputValue.value))
|
||||
if (!inputValue.value) {
|
||||
clearManualPrice(itemId, filters.value.city)
|
||||
} else if (v > 0) {
|
||||
setManualPrice(itemId, filters.value.city, v)
|
||||
}
|
||||
editingItemId.value = null
|
||||
inputValue.value = ''
|
||||
}
|
||||
|
||||
function cancelEdit() {
|
||||
editingItemId.value = null
|
||||
inputValue.value = ''
|
||||
}
|
||||
|
||||
function priceButtonClass(itemId: string, currentPrice: number): string {
|
||||
if (isManualPrice(itemId, filters.value.city)) return 'text-amber-400 hover:text-amber-200'
|
||||
if (currentPrice === 0) return 'text-gray-500 hover:text-amber-400'
|
||||
return 'text-gray-300 hover:text-gray-100'
|
||||
}
|
||||
|
||||
function priceTitle(itemId: string, currentPrice: number): string {
|
||||
const exact = currentPrice > 0 ? currentPrice.toLocaleString() : null
|
||||
const entry = getManualEntry(itemId, filters.value.city)
|
||||
if (entry && isManualPrice(itemId, filters.value.city)) {
|
||||
return exact
|
||||
? `${exact} — set ${formatLastUpdated(new Date(entry.editedAt))} — click to edit`
|
||||
: `Set ${formatLastUpdated(new Date(entry.editedAt))} — click to edit`
|
||||
}
|
||||
return exact ? `${exact} — click to set price` : 'Click to set price'
|
||||
}
|
||||
|
||||
// Laborer journal fills ≈ 13 crafts per book (ratio is constant across tiers)
|
||||
const CRAFTS_PER_JOURNAL = 13
|
||||
|
||||
|
||||
Reference in New Issue
Block a user