upd
This commit is contained in:
@@ -10,12 +10,14 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<span class="brand-tag">TMC</span>
|
<span class="brand-tag">TMC</span>
|
||||||
<span class="brand-sep" aria-hidden="true" />
|
<span class="brand-sep" aria-hidden="true" />
|
||||||
<h1 class="brand-title">Items <em>Manager</em></h1>
|
<h1 class="brand-title">
|
||||||
|
Items <em>Manager</em>
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<span class="header-meta-label">Item collection</span>
|
<span class="header-meta-label">Item collection</span>
|
||||||
<span class="header-vsep" aria-hidden="true" />
|
<!-- <span class="header-vsep" aria-hidden="true" /> -->
|
||||||
<time class="header-date">{{ formattedDate }}</time>
|
<!-- <time class="header-date">{{ formattedDate }}</time> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
:items="leftItems"
|
:items="leftItems"
|
||||||
:loading="leftLoading"
|
:loading="leftLoading"
|
||||||
:has-more="leftHasMore"
|
:has-more="leftHasMore"
|
||||||
|
:total="leftItemsTotal"
|
||||||
:search="leftSearch"
|
:search="leftSearch"
|
||||||
@update:search="leftSearch = $event"
|
@update:search="leftSearch = $event"
|
||||||
@load-more="fetchLeft()"
|
@load-more="fetchLeft()"
|
||||||
@@ -34,6 +37,7 @@
|
|||||||
:items="rightItems"
|
:items="rightItems"
|
||||||
:loading="rightLoading"
|
:loading="rightLoading"
|
||||||
:has-more="rightHasMore"
|
:has-more="rightHasMore"
|
||||||
|
:total="rightItemsTotal"
|
||||||
:search="rightSearch"
|
:search="rightSearch"
|
||||||
@update:search="rightSearch = $event"
|
@update:search="rightSearch = $event"
|
||||||
@load-more="fetchRight()"
|
@load-more="fetchRight()"
|
||||||
@@ -53,7 +57,9 @@ const formattedDate = computed(() =>
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
leftItems,
|
leftItems,
|
||||||
|
leftItemsTotal,
|
||||||
rightItems,
|
rightItems,
|
||||||
|
rightItemsTotal,
|
||||||
leftSearch,
|
leftSearch,
|
||||||
rightSearch,
|
rightSearch,
|
||||||
leftLoading,
|
leftLoading,
|
||||||
@@ -128,7 +134,7 @@ async function handleAdd(id: number) {
|
|||||||
.header-brand {
|
.header-brand {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 11px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-icon {
|
.brand-icon {
|
||||||
@@ -156,7 +162,7 @@ async function handleAdd(id: number) {
|
|||||||
.brand-title {
|
.brand-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-size: 1.08rem;
|
font-size: 1rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
letter-spacing: -0.025em;
|
letter-spacing: -0.025em;
|
||||||
|
|||||||
@@ -2,9 +2,12 @@
|
|||||||
<div class="panel">
|
<div class="panel">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<div class="panel-title-row">
|
<div class="panel-title-row">
|
||||||
<h2 class="panel-title">
|
<div class="panel-title-row">
|
||||||
All items
|
<h2 class="panel-title">
|
||||||
</h2>
|
All items
|
||||||
|
</h2>
|
||||||
|
<span v-if="total" class="item-count">{{ total }}</span>
|
||||||
|
</div>
|
||||||
<button class="btn-primary" @click="showAddModal = true">
|
<button class="btn-primary" @click="showAddModal = true">
|
||||||
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" aria-hidden="true">
|
<svg width="11" height="11" viewBox="0 0 11 11" fill="none" aria-hidden="true">
|
||||||
<path d="M5.5 1V10M1 5.5H10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
<path d="M5.5 1V10M1 5.5H10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
||||||
@@ -97,6 +100,7 @@ import { onUnmounted, ref, watch } from 'vue'
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
items: Item[]
|
items: Item[]
|
||||||
|
total: number | string
|
||||||
loading: boolean
|
loading: boolean
|
||||||
hasMore: boolean
|
hasMore: boolean
|
||||||
search: string
|
search: string
|
||||||
@@ -176,6 +180,22 @@ function submitAdd() {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-count {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 8px;
|
||||||
|
min-width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0 5px;
|
||||||
|
background: var(--surface-subtle);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 9999px;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.65rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.panel-title-row {
|
.panel-title-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<h2 class="panel-title">
|
<h2 class="panel-title">
|
||||||
Selected items
|
Selected items
|
||||||
</h2>
|
</h2>
|
||||||
<span v-if="items.length" class="item-count">{{ items.length }}</span>
|
<span v-if="total" class="item-count">{{ total }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-wrap">
|
<div class="search-wrap">
|
||||||
<span class="search-icon" aria-hidden="true">
|
<span class="search-icon" aria-hidden="true">
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<circle cx="6" cy="10" r="1.2" />
|
<circle cx="6" cy="10" r="1.2" />
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
<span class="item-order">{{ index + 1 }}</span>
|
<!-- <span class="item-order">{{ index + 1 }}</span> -->
|
||||||
<span class="item-id">{{ item.id }}</span>
|
<span class="item-id">{{ item.id }}</span>
|
||||||
<button class="action-btn" title="Remove from selected" @click="emit('deselect', item.id!)">
|
<button class="action-btn" title="Remove from selected" @click="emit('deselect', item.id!)">
|
||||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
|
||||||
@@ -78,6 +78,7 @@ import { VueDraggableNext } from 'vue-draggable-next'
|
|||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
items: Item[]
|
items: Item[]
|
||||||
|
total: number | string
|
||||||
loading: boolean
|
loading: boolean
|
||||||
hasMore: boolean
|
hasMore: boolean
|
||||||
search: string
|
search: string
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Item, PaginatedItems } from '~/services/api'
|
import type { Item } from '~/services/api'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { Api } from '~/services/api'
|
import { Api } from '~/services/api'
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ export function useItems() {
|
|||||||
|
|
||||||
const leftItems = ref<Item[]>([])
|
const leftItems = ref<Item[]>([])
|
||||||
const rightItems = ref<Item[]>([])
|
const rightItems = ref<Item[]>([])
|
||||||
|
const rightItemsTotal = ref(0)
|
||||||
|
const leftItemsTotal = ref(0)
|
||||||
const leftSearch = ref('')
|
const leftSearch = ref('')
|
||||||
const rightSearch = ref('')
|
const rightSearch = ref('')
|
||||||
const leftLoading = ref(false)
|
const leftLoading = ref(false)
|
||||||
@@ -27,13 +29,14 @@ export function useItems() {
|
|||||||
return
|
return
|
||||||
leftLoading.value = true
|
leftLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data: PaginatedItems = await client.api.itemsList({
|
const data = await client.api.itemsList({
|
||||||
page: leftPage.value,
|
page: leftPage.value,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
...(leftSearch.value ? { search: leftSearch.value } : {}),
|
...(leftSearch.value ? { search: leftSearch.value } : {}),
|
||||||
})
|
})
|
||||||
leftItems.value.push(...(data.data ?? []))
|
leftItems.value.push(...(data.data ?? []))
|
||||||
leftHasMore.value = data.hasMore ?? false
|
leftHasMore.value = data.hasMore ?? false
|
||||||
|
leftItemsTotal.value = data.total || 0
|
||||||
leftPage.value++
|
leftPage.value++
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -51,13 +54,14 @@ export function useItems() {
|
|||||||
return
|
return
|
||||||
rightLoading.value = true
|
rightLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data: PaginatedItems = await client.api.itemsSelectedList({
|
const data = await client.api.itemsSelectedList({
|
||||||
page: rightPage.value,
|
page: rightPage.value,
|
||||||
limit: 20,
|
limit: 20,
|
||||||
...(rightSearch.value ? { search: rightSearch.value } : {}),
|
...(rightSearch.value ? { search: rightSearch.value } : {}),
|
||||||
})
|
})
|
||||||
rightItems.value.push(...(data.data ?? []))
|
rightItems.value.push(...(data.data ?? []))
|
||||||
rightHasMore.value = data.hasMore ?? false
|
rightHasMore.value = data.hasMore ?? false
|
||||||
|
rightItemsTotal.value = data.total || 0
|
||||||
rightPage.value++
|
rightPage.value++
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -86,7 +90,9 @@ export function useItems() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
leftItems,
|
leftItems,
|
||||||
|
leftItemsTotal,
|
||||||
rightItems,
|
rightItems,
|
||||||
|
rightItemsTotal,
|
||||||
leftSearch,
|
leftSearch,
|
||||||
rightSearch,
|
rightSearch,
|
||||||
leftLoading,
|
leftLoading,
|
||||||
|
|||||||
Reference in New Issue
Block a user