210 lines
5.7 KiB
Vue
210 lines
5.7 KiB
Vue
<script setup lang="ts">
|
|
import { ref, computed, onMounted, watch } from 'vue'
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
import { useCatalogStore } from '@/stores/catalog'
|
|
import PageHeader from '@/components/layout/PageHeader.vue'
|
|
import SearchField from '@/components/ui/SearchField.vue'
|
|
import EmptyState from '@/components/ui/EmptyState.vue'
|
|
import PageSkeleton from '@/components/ui/PageSkeleton.vue'
|
|
import IconCatalog from '@/components/icons/IconCatalog.vue'
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const catalogStore = useCatalogStore()
|
|
const loading = ref(true)
|
|
|
|
const companyId = computed(() => route.params.companyId as string)
|
|
const company = computed(() => catalogStore.getCompany(companyId.value))
|
|
const search = ref('')
|
|
|
|
const catalogs = computed(() => catalogStore.fetchCatalogs(companyId.value, search.value))
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
if (!catalogStore.getCompany(companyId.value)) {
|
|
await catalogStore.loadCompanies()
|
|
}
|
|
await catalogStore.loadCatalogs(companyId.value)
|
|
loading.value = false
|
|
}
|
|
|
|
onMounted(load)
|
|
watch(companyId, load)
|
|
|
|
function openCatalog(catalogId: string) {
|
|
router.push(`/companies/${companyId.value}/catalogs/${catalogId}/products`)
|
|
}
|
|
|
|
function getProductCount(catalogId: string) {
|
|
const catalog = catalogStore.getCatalog(catalogId)
|
|
if (catalog?.productCount != null) return catalog.productCount
|
|
return catalogStore.fetchProducts(catalogId).length
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<!-- Mobile -->
|
|
<div class="page catalog-mobile-page mobile-only">
|
|
<PageHeader
|
|
:title="company?.name ?? 'کالیتهها'"
|
|
subtitle="کالیته مورد نظر را انتخاب کنید"
|
|
show-back
|
|
centered
|
|
@back="router.push('/')"
|
|
/>
|
|
|
|
<SearchField
|
|
v-model="search"
|
|
placeholder="جستجو بر اساس کد یا نام کالیته..."
|
|
class="catalog-page__search"
|
|
/>
|
|
|
|
<div class="page__scroll page__scroll--with-nav catalog-mobile-scroll">
|
|
<PageSkeleton v-if="loading" variant="cards" :rows="5" />
|
|
<div v-else-if="catalogs.length > 0" class="catalog-mobile-list">
|
|
<button
|
|
v-for="catalog in catalogs"
|
|
:key="catalog.id"
|
|
type="button"
|
|
class="catalog-card"
|
|
@click="openCatalog(catalog.id)"
|
|
>
|
|
<span class="catalog-card__icon"><IconCatalog :size="22" /></span>
|
|
<div class="catalog-card__info">
|
|
<h3>کالیته کد {{ catalog.code }}</h3>
|
|
<p>{{ catalog.name }}</p>
|
|
</div>
|
|
<span class="catalog-card__count">{{ getProductCount(catalog.id) }} محصول</span>
|
|
</button>
|
|
</div>
|
|
<EmptyState
|
|
v-else
|
|
:variant="search ? 'search' : 'catalogs'"
|
|
:message="search ? 'با این جستجو کالیتهای پیدا نشد' : 'برای این شرکت هنوز کالیتهای ثبت نشده است'"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Desktop -->
|
|
<div class="desktop-page catalog-desktop-page desktop-only">
|
|
<header class="desktop-page__head">
|
|
<h1 class="desktop-page__title">{{ company?.name ?? 'کالیتهها' }}</h1>
|
|
<p class="desktop-page__subtitle">کالیته مورد نظر را انتخاب کنید</p>
|
|
</header>
|
|
|
|
<SearchField
|
|
v-model="search"
|
|
placeholder="جستجو بر اساس کد یا نام کالیته..."
|
|
class="catalog-page__search"
|
|
/>
|
|
|
|
<div v-if="catalogs.length > 0" class="desktop-grid-3">
|
|
<button
|
|
v-for="catalog in catalogs"
|
|
:key="catalog.id"
|
|
type="button"
|
|
class="catalog-card catalog-card--desktop"
|
|
@click="openCatalog(catalog.id)"
|
|
>
|
|
<span class="catalog-card__icon"><IconCatalog :size="24" /></span>
|
|
<div class="catalog-card__info">
|
|
<h3>کالیته کد {{ catalog.code }}</h3>
|
|
<p>{{ catalog.name }}</p>
|
|
</div>
|
|
<span class="catalog-card__count">{{ getProductCount(catalog.id) }} محصول</span>
|
|
</button>
|
|
</div>
|
|
|
|
<EmptyState
|
|
v-else
|
|
:variant="search ? 'search' : 'catalogs'"
|
|
:message="search ? 'با این جستجو کالیتهای پیدا نشد' : 'برای این شرکت هنوز کالیتهای ثبت نشده است'"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.catalog-mobile-page {
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
padding: 12px 0 0;
|
|
}
|
|
|
|
.catalog-page__search {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.catalog-mobile-scroll {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
min-height: 0;
|
|
}
|
|
|
|
.catalog-mobile-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.catalog-card {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
width: 100%;
|
|
padding: 14px 16px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--color-elevated);
|
|
box-shadow: var(--shadow-sm);
|
|
color: var(--color-text);
|
|
text-align: right;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.catalog-card--desktop {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
min-height: 140px;
|
|
padding: 20px;
|
|
}
|
|
|
|
.catalog-card:hover {
|
|
border-color: var(--color-primary);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
|
|
.catalog-card__icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--color-primary-light);
|
|
border-radius: var(--radius-sm);
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
.catalog-card__info {
|
|
flex: 1;
|
|
}
|
|
|
|
.catalog-card__info h3 {
|
|
margin: 0 0 4px;
|
|
font-size: 0.9375rem;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.catalog-card__info p {
|
|
margin: 0;
|
|
font-size: 0.8125rem;
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
.catalog-card__count {
|
|
font-size: 0.8125rem;
|
|
font-weight: 600;
|
|
color: var(--color-primary);
|
|
}
|
|
</style>
|