This commit is contained in:
mohadese namavar
2024-06-16 00:22:14 +04:30
commit ec84dfd222
322 changed files with 77942 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
<template>
<header class="header-desktop">
<router-link to="/">
<img src="/images/logo.svg" alt="Asan Market" />
</router-link>
<AppDesktopHeaderNavigation />
<router-link v-if="!logged" :to="{ path: '/auth/login' }">
<Button v-bind="btns.login.props" />
</router-link>
<div v-else>
<template v-for="({ props, component }, key) in btns.logged" :key="key">
<Button v-bind="props" @click="overlay($event, component)" />
</template>
</div>
</header>
</template>
<script setup>
import init from '../../../../initialize/header'
const { btns } = init()
const logged = useCookie('token')
const { popup } = inject('service')
const overlay = (event, is) => {
popup.value.is = is
popup.value.toggle(event)
}
</script>
<style lang="scss">
.header-desktop {
box-shadow: 0px 2px 20px rgba(0.22, 75.27, 129.62, 0.14);
@apply w-full h-[3.3rem] lg:h-24 bg-white shadow border-b pl-3 lg:px-3 2xl:p-6 flex items-center justify-between;
@apply sticky top-0 z-10 xl:gap-4;
&>a>img {
@apply w-60 h-10;
}
&>a {
@apply shrink-0;
&>button {
@apply flex items-center text-white;
.p-button-icon {
@apply text-2xl;
}
.p-button-label {
@apply font-bold font-iran-sans tracking-widest whitespace-nowrap;
}
}
}
&>div {
@apply flex items-center gap-6 2xl:gap-12 relative;
&::after {
@apply content-['_'] w-0.5 h-[1.3rem] bg-[#DCDCDC] absolute left-[3.6rem] 2xl:left-[4.4rem];
}
button {
@apply border-[#CCCCCC] h-12 rounded-[0.6rem] #{!important};
.p-button-label {
@apply text-[#333333] text-lg font-medium font-vazir whitespace-nowrap;
}
.p-button-icon {
@apply text-[#333333] text-2xl;
}
&:first-child {
@apply pl-6 #{!important};
.p-button-icon {
@apply ml-2.5;
}
}
&:last-child {
@apply w-12 p-2 relative;
.p-badge {
@apply absolute w-4 h-4 bg-[#B3261E] top-0.5 right-0.5 flex items-center justify-center;
@apply text-white text-[0.7em] font-medium leading-none tracking-wide;
}
}
}
.p-blockui-container {
@apply absolute;
}
}
}
</style>
+189
View File
@@ -0,0 +1,189 @@
<template>
<Transition>
<nav v-if="visible" class="mega-menu" @click.self="visible = false">
<TransitionGroup name="list" tag="section">
<template v-for="(list, i) in menu" :key="i">
<ul v-if="list?.length">
<li v-for="(item, j) in list" :key="j" @mouseover="open(item, i)">
<router-link :to="{ path: '/search', query: { category: item.link } }">
<Button v-bind="getProps(item, i)" />
</router-link>
</li>
</ul>
</template>
</TransitionGroup>
</nav>
</Transition>
</template>
<script setup>
const visible = defineModel()
const store = useCategoriesStore()
const menu = reactive([])
const getProps = (item, i) => {
const temp = { label: item.name, link: true }
if (i === 0) {
temp.iconPos = 'right'
temp.icon = 'isax ' + item.icon
// temp.disabled = menu[1] == item.sub
} else if (i === 1 && item.sub.length > 0) {
temp.icon = 'isax isax-arrow-left-2'
// temp.disabled = menu[2] == item.sub
}
return temp
}
const open = (item, i) => {
if (i < 2) {
delete menu[i + 2]
menu[i + 1] = item.sub
}
}
onMounted(() => {
let cat = store.items
while (true) {
menu.push(cat)
if (cat[0]?.sub) cat = cat[0].sub
else break
}
})
const route = useRoute()
watch(() => route.query, () => visible.value = false)
</script>
<style lang="scss">
.mega-menu {
@apply fixed inset-x-0 z-[1] bottom-0 top-24 bg-black/40;
&>section {
@apply flex h-[32.4rem] w-full bg-white shadow-inner;
ul:nth-of-type(1) {
@apply flex flex-col gap-2 py-3 px-4 w-[16.5rem] h-[26.8rem] z-[10];
li {
button {
@apply w-full h-12 justify-end;
.p-button-label {
@apply text-[#292D32] text-lg font-medium font-vazir grow-0;
}
.p-button-icon {
@apply text-[#292D32] text-2xl ml-4;
}
&:hover * {
@apply text-primary-600;
}
&:disabled {
@apply opacity-100;
* {
@apply text-primary-600;
}
}
}
}
}
ul:nth-of-type(2) {
@apply border-x-2 border-[#E5E5E5] w-[16.5rem] h-[32.4rem] flex flex-col;
li {
@apply border-b border-[#E5E5E5];
button {
@apply w-full h-[3.7rem] justify-between px-2.5;
.p-button-label {
@apply text-[#292D32] text-lg font-vazir grow-0 ml-auto;
}
.p-button-icon {
@apply text-[#292D32] text-sm transition-transform;
}
&:hover * {
@apply text-primary-600;
}
&:disabled {
@apply opacity-100 bg-[#FAFAFA];
.p-button-label {
@apply text-[#333333] font-medium;
}
.p-button-icon {
@apply text-[#333333] -rotate-90;
}
}
}
}
}
ul:nth-of-type(3) {
@apply flex flex-col;
li {
@apply px-4;
button {
@apply w-full h-[3.8rem] justify-end;
.p-button-label {
@apply text-[#333333] text-lg font-normal font-vazir grow-0;
}
&:hover * {
@apply text-primary-600;
}
}
}
}
}
.list-enter-active,
.list-leave-active {
transition: all 0.2s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.menu-enter-active,
.menu-leave-active {
transition: all 0.3s ease;
div {
transition: all 0.3s ease;
}
}
.menu-enter-from,
.menu-leave-to {
opacity: 0;
div {
transform: translateX(30px);
}
}
}
.v-enter-active,
.v-leave-active {
transition: opacity 0.1s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
@@ -0,0 +1,70 @@
<template>
<ul class="mini-menu">
<li v-for="(item, i) in items" :key="i">
<router-link :to="item.to" @click="popup.hide()">
<Button v-bind="item.props" iconPos="right" severity="secondary" link />
</router-link>
</li>
<li>
<Button :label="$t('logout')" icon="isax isax-logout-1" iconPos="right" severity="secondary" link
@click="logout()" />
</li>
</ul>
</template>
<script setup>
const items = reactive([
{
to: "/panel/profile",
props: { label: "پروفایل کاربری", icon: "isax isax-user-square" },
},
{ to: "/panel/favorites", props: { label: "علاقه مندی ها", icon: "isax isax-heart" } },
{
to: "/panel/comments",
props: { label: "نظرات من", icon: "isax isax-message-text4" },
},
{ to: "/panel/factors", props: { label: "فاکتورها", icon: "isax isax-receipt-2-1" } },
{
to: "/panel/moeen",
props: { label: "فاکتور معین", icon: "isax isax-archive-book4" },
},
{ to: "/panel/notifications", props: { label: "اعلان ها", icon: "isax isax-notification" } },
{
to: "/panel/orders",
props: { label: "سفارشات", icon: "isax isax-shopping-cart" },
},
])
const { popup } = inject('service')
const { dialog } = inject('service')
const logout = () => {
popup.value.hide();
dialog.show(resolveComponent('PanelDialogLogout'))
}
</script>
<style lang="scss">
.mini-menu {
@apply flex flex-col gap-3 px-4 pt-[1.4rem] rtl shadow-[0px_2px_10px_#004b8229];
@apply w-[13.4rem] h-[27.8rem] bg-white rounded-2xl shadow border;
li {
button {
@apply h-10 py-1.5 justify-end #{!important};
.p-button-icon {
@apply text-[#333333] text-2xl ml-3;
}
.p-button-label {
@apply text-[#333333] text-lg font-medium font-vazir grow-0 whitespace-nowrap;
}
}
}
}
.p-overlaypanel:has(.mini-menu) {
@apply -translate-x-8;
}
</style>
@@ -0,0 +1,97 @@
<template>
<ul class="navigation">
<li>
<Button :label="$t('product-categories')" iconPos="right" severity="secondary" text icon="isax isax-menu-1"
@click="visible = !visible" />
</li>
<li v-for="(item, i) in items" :key="i">
<component :is="item.link.includes('http') ? 'a' : 'router-link'" :to="item.link" :href="item.link">
<Button iconPos="right" severity="secondary" text v-bind="item.props" />
</component>
</li>
<li>
<Button iconPos="right" severity="secondary" text icon="isax isax-search-normal-1"
@click="$router.push('/search')" />
</li>
</ul>
<AppDesktopHeaderMegaMenu v-model="visible" />
</template>
<script setup>
const items = ref([])
const visible = ref(false)
const { status, data, error } = await useFetch('/api/headers')
if (status.value == 'success')
items.value = data.value.map((item) => {
item.props = { label: item.title, icon: 'isax ' + item.icon }
return item
})
else throw createError(error.value)
</script>
<style lang="scss">
.navigation {
@apply flex items-center justify-center lg:gap-6 2xl:justify-between w-full max-w-[70.6rem];
li:first-child,
li:last-child {
@apply flex items-center relative;
}
li:first-child::after,
li:last-child::before {
@apply content-['_'] w-0.5 h-[1.3rem] bg-[#DCDCDC] absolute;
}
li:first-child {
@apply -ml-1;
&::after {
@apply left-0 2xl:-left-3;
}
}
li:last-child {
@apply -mr-1;
&::before {
@apply 2xl:-right-3;
}
}
li {
button {
.p-button-icon {
@apply text-[#333333] text-xl;
}
&:not(.p-button-icon-only) .p-button-icon {
@apply ml-2;
}
.p-button-label {
@apply text-[#333333] text-lg font-medium font-vazir whitespace-nowrap no-underline;
}
}
}
li:nth-child(n + 7):not(:last-child) {
@apply max-[1500px]:hidden;
}
li:nth-child(n + 6):not(:last-child) {
@apply max-[1380px]:hidden;
}
li:nth-child(n + 5):not(:last-child) {
@apply max-xl:hidden;
}
li:not(:last-child:first-child) {
@apply max-2xl:-mx-1;
}
}
</style>
@@ -0,0 +1,57 @@
<template>
<div class="header-cart-list-item">
<span>{{ quantity }}x</span>
<img :src="data.coverPath" />
<div>
<h3>{{ data.category[data.category.length - 1]?.name }}</h3>
<h2>{{ data.title }}</h2>
<span>
<b>{{ numberFormat(data.specialPrice || data.price) }} </b>
{{ $t('priceUnit') }}
</span>
</div>
<Button icon="isax isax-trash" severity="secondary" text @click="$emit('remove', data.id)" />
</div>
</template>
<script setup>
defineProps(['data', 'quantity'])
const numberFormat = (number) =>
new Intl.NumberFormat('fa-IR', { maximumSignificantDigits: 3 }).format(number)
</script>
<style lang="scss">
.header-cart-list-item {
box-shadow: 0px 2px 12px #004b8226;
@apply flex p-2 pl-6 w-[26.9rem] h-[10.1rem] bg-white rounded-lg shadow border relative;
&>span {
@apply absolute left-5 top-4 text-xs font-poppins;
}
img {
@apply w-[9.2rem] h-[9.2rem] p-2;
}
div {
@apply w-max gap-1 flex flex-col py-4 font-vazir mr-6;
h3 {
@apply text-right text-neutral-400 text-[0.9em] font-medium;
}
h2 {
@apply w-[13.1rem] h-14 text-right text-zinc-800 text-[1.1em] font-bold line-clamp-2;
}
span {
@apply text-zinc-800 text-[0.9em] mt-auto;
}
}
button {
@apply w-10 h-10 mb-2 -mx-2 shrink-0 self-end text-2xl text-[#7F7F7F] rounded-full #{!important};
}
}
</style>
@@ -0,0 +1,64 @@
<template>
<div class="header-cart-list">
<h3>{{ $t('itemsSubmittedInCart', { count: cart.count }) }}</h3>
<div>
<ul>
<li v-for="({ product, quantity }, i) in items" :key="i">
<AppDesktopHeaderCartItem :data="product" :quantity="quantity" @remove="remove" />
</li>
</ul>
</div>
<Button :label="$t('showCart')" @click="show()" />
</div>
</template>
<script setup>
const { popup } = inject('service')
const cart = useCartStore()
const items = computed(() => cart.items)
const emit = defineEmits(['hide'])
const router = useRouter()
const show = () => {
popup.value.hide()
router.push('/checkout/cart')
}
const remove = async (id) => {
await cart.update(id)
if (cart.count < 1) popup.value.hide()
}
</script>
<style lang="scss">
.header-cart-list {
box-shadow: 0px 2px 10px 0px rgba(0, 75, 130, 0.16);
@apply rtl w-[30.9rem] h-[40.6rem] flex flex-col gap-5 py-6 pl-2 bg-white rounded-2xl border overflow-hidden relative;
&>h3 {
@apply text-sky-700 text-[0.9em] font-medium font-vazir mb-2.5 mr-8 ml-6;
}
&>div {
@apply overflow-y-auto h-[29.8rem];
ul {
@apply w-full flex py-3 pr-8 pl-4 flex-col gap-3 items-center;
}
&::-webkit-scrollbar {
@apply hidden;
}
}
&>button {
@apply bg-sky-700 border-sky-700 mr-8 ml-6 text-xl font-bold font-vazir #{!important};
}
&::before {
content: ' ';
box-shadow: 0px -3px 16px 0px rgba(7, 50, 115, 0.16);
@apply absolute inset-x-0 -bottom-3 h-28 z-0;
}
}
</style>