Files
tehran_taj/apps/user-app/src/views/HomeView.vue
T
2026-09-09 06:46:27 +03:30

127 lines
5.6 KiB
Vue

<!--
Ported from legacy henza_pwa/src/views/home/index.vue.
Honest adaptations:
- legacy fetched a single curated payload from POST /front (categories
with icons, a hand-picked "newest" list, a hand-picked "shelf" list, a
home banner slider config). The new API only exposes GET
/catalog/products (flat, uncurated), so `configStore` supplies the
banner slides (placeholder artwork, legacy's exact slide shape) and
derives the real category list from the product catalogue. The two
product sections both draw from the same flat product list (first 4 as
"newest", the rest as the shelf) rather than two independently curated
lists.
- the "please login" nudge (DialogVant, 5s after load) is ported and will
fire, since there is genuinely no login yet — matching legacy's real
behavior for an unauthenticated visitor.
- the notification bell (`NotificationList`) was already commented out of
legacy's own template — not ported, matching legacy's actual current state.
-->
<template>
<Spinner :spinning="loading" tip="درحال دریافت اطلاعات">
<AppHeader>
<nav class="flex justify-between items-center">
<span></span>
<img src="/img/henza1.svg" alt="هنزاگلد" />
</nav>
</AppHeader>
<container class="px-[16px] pb-[66px]" v-if="flag">
<HomeSlider class="z-0 mx-[-16px]" :slides="memory.config.main_slider" :height="sliderHeight" />
<section>
<h5 class="font-bold">دسته بندی ها</h5>
<div class="no-scrollbar grid grid-cols-3 gap-4 mt-[16px] items-stretch">
<Category class="h-full" v-for="item in memory.cats" :key="item.id" :value="item" />
</div>
<Divider class="border-grey"><img v-lazy="vectorIcon" alt="svg" class="mx-[10px]" /></Divider>
<h4 class="font-bold">محصولات جدید</h4>
<ProductHorizontal class="mt-[10px]" v-for="item in newestProducts" :key="item.id" :value="item" />
<router-link :to="{ name: 'newestProduct' }">
<Button :type="('light' as any)" class="mt-[16px]" block size="large">
<template #icon>
<Icon icon="vuesax-linear:arrow-left-1" class="cursor-pointer text-primary" size="25" />
</template>
مشاهده همه
</Button>
</router-link>
<Divider class="border-grey"><img v-lazy="vectorIcon" alt="svg" class="mx-[10px]" /></Divider>
<div class="no-scrollbar flex overflow-x-auto mt-[16px] mx-[-16px] px-[16px]">
<ProductVertical class="flex-[0_0_280px] ml-[16px]" v-for="item in shelfProducts" :key="item.id" :value="item" />
<ViewAll class="last:ml-0 flex-[0_0_280px]" to="/search" />
</div>
</section>
</container>
<DialogVant :timeOut="-1" v-model:show="loginNotify" :closeOnClickOverlay="true">
<template v-slot:img>
<img :src="loginDialogImage" alt="" class="opacity-80" />
</template>
<template v-slot:title>
<div class="p-8 text-justify">برای دسترسی به تمامی امکانات نرم افزار هنزاگلد، ابتدا گزینه ورود/ثبت نام را لمس کنید و در صورت نداشتن حساب کاربری، ثبت نام نمایید.</div>
</template>
<template v-slot:button>
<div class="text-center text-[#1C2D56]" @click="router.push({ name: 'login' })">ورود/ثبت نام</div>
<div class="text-center text-danger" @click="loginNotify = false">بیخیال</div>
</template>
</DialogVant>
</Spinner>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { Button, Divider } from 'ant-design-vue'
import Icon from '../components/icon/Icon.vue'
import AppHeader from '../components/AppHeader.vue'
import Spinner from '../components/Spinner.vue'
import DialogVant from '../components/DialogVant.vue'
import Category from '../components/product/Category.vue'
import ProductHorizontal from '../components/product/ProductHorizontal.vue'
import ProductVertical from '../components/product/ProductVertical.vue'
import ViewAll from '../components/ViewAll.vue'
import HomeSlider from '../components/slider/HomeSlider.vue'
import vectorIcon from '../assets/img/Vector.svg'
import loginDialogImage from '../assets/img/empty/dialogEmpty1.svg'
import { useWindowDataStore } from '../stores/windowDataStore'
import { useConfigStore } from '../stores/configStore'
import { isUserLoggedIn } from '../utils/checkAccess'
import { api, type ProductSummary } from '../api/client'
const router = useRouter()
const windowData = useWindowDataStore()
// legacy's `memory` — the global config store (banner slider + categories)
const memory = useConfigStore()
const loading = ref(false)
const flag = ref(false)
const loginNotify = ref(false)
const products = ref<ProductSummary[]>([])
const newestProducts = computed(() => products.value.slice(0, 4))
const shelfProducts = computed(() => products.value.slice(4))
const sliderHeight = computed(() => Math.min(windowData.width, 768) / 2.2125 + 'px')
const getFront = async () => {
try {
loading.value = true
products.value = await api.listProducts()
flag.value = true
setTimeout(() => {
if (!isUserLoggedIn()) {
loginNotify.value = true
}
}, 5000)
} catch (e) {
console.log(e)
} finally {
loading.value = false
}
}
onMounted(async () => {
// legacy home/index.vue ran getFront() alongside the global store init, which
// is what populated the slider + category grid.
await Promise.all([getFront(), memory.init()])
})
</script>