feat: initial commit
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
<!--
|
||||
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>
|
||||
Reference in New Issue
Block a user