Merge branch 'main' of https://github.com/Byeto-Company/hossein_por_shop
This commit is contained in:
@@ -266,3 +266,9 @@
|
||||
padding-inline: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@layer {
|
||||
button {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,20 @@ defineProps<Props>();
|
||||
|
||||
<template>
|
||||
<AvatarRoot
|
||||
class="bg-black inline-flex size-[45px] select-none items-center justify-center overflow-hidden rounded-full align-middle"
|
||||
class="inline-flex size-[45px] select-none items-center justify-center rounded-full align-middle"
|
||||
>
|
||||
<AvatarImage
|
||||
class="h-full w-full rounded-[inherit] object-cover"
|
||||
class="h-full w-full rounded-full object-cover"
|
||||
:src="src"
|
||||
:alt="alt"
|
||||
/>
|
||||
<AvatarFallback
|
||||
class="text-slate-300 leading-1 flex h-full w-full items-center justify-center bg-white text-sm font-medium"
|
||||
class="flex-center size-full text-sm font-medium rounded-full"
|
||||
:delay-ms="600"
|
||||
>
|
||||
{{ alt }}
|
||||
<div class="size-full rounded-full flex-center">
|
||||
<Icon name="ci:profile" size="16" class="**:stroke-black" />
|
||||
</div>
|
||||
</AvatarFallback>
|
||||
</AvatarRoot>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<script setup lang="ts">
|
||||
// types
|
||||
|
||||
type Props = {
|
||||
items: DropdownItem[];
|
||||
};
|
||||
|
||||
// props
|
||||
|
||||
defineProps<Props>();
|
||||
|
||||
// state
|
||||
|
||||
const toggleState = ref(false);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenuRoot v-model:open="toggleState" dir="rtl">
|
||||
<DropdownMenuTrigger>
|
||||
<slot name="trigger" />
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuPortal>
|
||||
<DropdownMenuContent
|
||||
v-if="items"
|
||||
class="min-w-[220px] w-full outline-none bg-white border border-gray-300 rounded-xl font-iran-yekan-x p-2 shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slide-down-fade data-[side=right]:animate-slide-left-fade data-[side=bottom]:animate-slide-up-fade data-[side=left]:animate-slide-right-fade z-10000"
|
||||
:side-offset="5"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
v-for="(item, index) in items"
|
||||
:key="index"
|
||||
@click="item.onClick"
|
||||
:class="
|
||||
item.itemClass ? item.itemClass : 'hover:!text-black'
|
||||
"
|
||||
class="group text-xs leading-none text-black hover:!bg-gray-100 rounded-md flex items-center justify-between py-3 px-1.5 relative select-none outline-none data-[disabled]:opacity-50 data-[disabled]:pointer-events-none data-[highlighted]:bg-black data-[highlighted]:text-white"
|
||||
>
|
||||
<span>
|
||||
{{ item.title }}
|
||||
</span>
|
||||
<Icon
|
||||
:name="item.icon"
|
||||
:class="item.iconClass"
|
||||
size="16"
|
||||
class="**:stroke-black"
|
||||
/>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuArrow class="fill-white stroke-gray-300" />
|
||||
</DropdownMenuContent>
|
||||
|
||||
<slot v-else name="content" />
|
||||
</DropdownMenuPortal>
|
||||
</DropdownMenuRoot>
|
||||
</template>
|
||||
@@ -1,4 +1,8 @@
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
// imports
|
||||
|
||||
import { NAV_LINKS } from "~/constants";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="w-full bg-black flex-center">
|
||||
@@ -7,15 +11,16 @@
|
||||
class="h-full flex flex-col items-start justify-between pe-[5rem] py-[5rem]"
|
||||
>
|
||||
<div class="flex flex-col items-start gap-[1.5rem] w-full">
|
||||
<span class="text-white typo-sub-h-xl"
|
||||
>Subscribe to our newsletter
|
||||
<span class="text-white typo-sub-h-xl font-light"
|
||||
>از آخرین اخبار، نوشتهها، مقالات و تخفیفها با خبر شوید
|
||||
😎
|
||||
</span>
|
||||
<div class="flex flex-col items-start gap-[.75rem] w-full">
|
||||
<div
|
||||
class="flex items-center justify-start gap-[.5rem] w-full"
|
||||
>
|
||||
<Input
|
||||
placeholder="Enter your email"
|
||||
placeholder="آدرس الکترونیکی شما"
|
||||
class="bg-slate-950 border-slate-800 hover:border-slate-800 w-8/12"
|
||||
/>
|
||||
<Button
|
||||
@@ -24,13 +29,16 @@
|
||||
/>
|
||||
</div>
|
||||
<span class="text-slate-400 typo-p-sm">
|
||||
By subscribing, you agree to our responsible data
|
||||
use
|
||||
با عضویت, شما با
|
||||
<NuxtLink to="#" class="text-cyan-500 underline"
|
||||
>قوانین و مقررات</NuxtLink
|
||||
>
|
||||
سایت موافقت می کنید.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-white typo-label-sm">
|
||||
© 2024 Nova - Tech Store. Powered by Capricorn Engineering
|
||||
<span class="text-white typo-label-sm font-light">
|
||||
© ۲۰۲۵ - ملز; هوشمند ترین وبسایت ایران
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -38,39 +46,51 @@
|
||||
class="flex flex-col items-start ps-[5rem] py-[5rem] gap-[6.875rem]"
|
||||
>
|
||||
<div class="w-full flex items-start gap-[3rem]">
|
||||
<div class="flex flex-col gap-[.75rem] text-white w-full">
|
||||
<NuxtLink to="#" class="typo-h-5"> About </NuxtLink>
|
||||
<NuxtLink to="#" class="typo-h-5"> Journal </NuxtLink>
|
||||
<NuxtLink to="#" class="typo-h-5"> FAQs </NuxtLink>
|
||||
<NuxtLink to="#" class="typo-h-5">
|
||||
Contact us
|
||||
<div class="flex flex-col gap-[1.5rem] w-full">
|
||||
<NuxtLink
|
||||
v-for="(link, index) in NAV_LINKS"
|
||||
:key="index"
|
||||
:to="link.path"
|
||||
class="typo-h-5 font-light text-white hover:text-white/70 transition-all"
|
||||
>
|
||||
{{ link.title }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div
|
||||
class="flex flex-col gap-[.75rem] text-slate-400 w-full"
|
||||
>
|
||||
<NuxtLink to="#" class="typo-label-md">
|
||||
Headphones
|
||||
<div class="flex flex-col gap-[.75rem] w-full">
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="typo-label-md font-light text-slate-400 hover:text-slate-500 transition-all"
|
||||
>
|
||||
سوالات متدوال
|
||||
</NuxtLink>
|
||||
<NuxtLink to="#" class="typo-label-md">
|
||||
Speakers
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="typo-label-md font-light text-slate-400 hover:text-slate-500 transition-all"
|
||||
>
|
||||
قوانین و مقررات
|
||||
</NuxtLink>
|
||||
<NuxtLink to="#" class="typo-label-md">
|
||||
Charging stations
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="typo-label-md font-light text-slate-400 hover:text-slate-500 transition-all"
|
||||
>
|
||||
گزارش خطا و باگ
|
||||
</NuxtLink>
|
||||
<NuxtLink to="#" class="typo-label-md">
|
||||
Lanterns
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="typo-label-md font-light text-slate-400 hover:text-slate-500 transition-all"
|
||||
>
|
||||
حریم خصوصی
|
||||
</NuxtLink>
|
||||
<NuxtLink to="#" class="typo-label-md">
|
||||
Portable charger
|
||||
<NuxtLink
|
||||
to="#"
|
||||
class="typo-label-md font-light text-slate-400 hover:text-slate-500 transition-all"
|
||||
>
|
||||
تماس با ما
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-between text-white w-full"
|
||||
>
|
||||
<span class="typo-label-sm">Privacy Policy</span>
|
||||
<div class="flex items-center justify-end text-white w-full">
|
||||
<div class="flex items-center gap-[1rem]">
|
||||
<NuxtLink to="#" class="flex-center size-[1.5rem]">
|
||||
<Icon
|
||||
|
||||
@@ -3,50 +3,49 @@
|
||||
|
||||
import useGetAccount from "~/composables/api/account/useGetAccount";
|
||||
import { useAuth } from "~/composables/api/auth/useAuth";
|
||||
|
||||
// types
|
||||
|
||||
type NavLink = {
|
||||
title: string;
|
||||
path: string;
|
||||
};
|
||||
import { useToast } from "~/composables/global/useToast";
|
||||
import { NAV_LINKS } from "~/constants";
|
||||
|
||||
// state
|
||||
|
||||
const { data: account } = useGetAccount();
|
||||
const route = useRoute();
|
||||
const { logout } = useAuth();
|
||||
const router = useRouter();
|
||||
|
||||
const nav_links = ref<NavLink[]>([
|
||||
const { addToast } = useToast();
|
||||
const { logout, token } = useAuth();
|
||||
|
||||
const profileDropdownItems = ref<DropdownItem[]>([
|
||||
{
|
||||
title: "خانه",
|
||||
path: "/",
|
||||
title: "ورود به پنل کاربری",
|
||||
icon: "ci:profile",
|
||||
onClick: () => router.push({ name: "profile" }),
|
||||
},
|
||||
{
|
||||
title: "محصولات",
|
||||
path: "/products",
|
||||
},
|
||||
{
|
||||
title: "دسته بندی ها",
|
||||
path: "/category",
|
||||
},
|
||||
{
|
||||
title: "ارتباط با ما",
|
||||
path: "/contact-us",
|
||||
},
|
||||
{
|
||||
title: "امکانات",
|
||||
path: "#",
|
||||
title: "خروج از حساب",
|
||||
icon: "bi:arrow-bar-left",
|
||||
itemClass: "!text-red-500",
|
||||
iconClass: "**:stroke-red-500 **:fill-transparent",
|
||||
onClick: () => {
|
||||
logout();
|
||||
nextTick(() => {
|
||||
addToast({
|
||||
message: "با موفقیت از حساب خارج شدید",
|
||||
options: {
|
||||
status: "success",
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// queries
|
||||
|
||||
const { data: account } = useGetAccount();
|
||||
|
||||
// computed
|
||||
|
||||
const isHomePage = computed(() => route.path === "/");
|
||||
|
||||
// lifecycle
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -60,16 +59,28 @@ onMounted(() => {});
|
||||
>
|
||||
<div class="flex items-center gap-16">
|
||||
<div class="flex items-center justify-end gap-[1.5rem]">
|
||||
<Tooltip v-if="!!account" title="حساب کاربری">
|
||||
<button
|
||||
@click="() => logout(true)"
|
||||
class="size-[1.6rem] flex items-center justify-center relative overflow-hidden rounded-full bg-slate-300"
|
||||
>
|
||||
<Avatar
|
||||
:src="account.profile_photo"
|
||||
:alt="`${account.first_name} ${account.last_name}`"
|
||||
/>
|
||||
</button>
|
||||
<Tooltip v-if="!!account && !!token" title="حساب کاربری">
|
||||
<Dropdown :items="profileDropdownItems">
|
||||
<template #trigger>
|
||||
<button
|
||||
class="size-[1.6rem] flex items-center justify-center relative overflow-hidden rounded-full border border-black"
|
||||
>
|
||||
<Avatar
|
||||
:src="account.profile_photo"
|
||||
:alt="
|
||||
account.first_name &&
|
||||
account.last_name
|
||||
? `${account.first_name.charAt(
|
||||
0
|
||||
)} ${account.last_name.charAt(
|
||||
0
|
||||
)}`
|
||||
: ''
|
||||
"
|
||||
/>
|
||||
</button>
|
||||
</template>
|
||||
</Dropdown>
|
||||
</Tooltip>
|
||||
<Tooltip v-else title="ورود">
|
||||
<NuxtLink to="/signin" class="flex-center">
|
||||
@@ -89,20 +100,22 @@ onMounted(() => {});
|
||||
/>
|
||||
</NuxtLink>
|
||||
</Tooltip>
|
||||
<NuxtLink to="/cart" class="flex-center">
|
||||
<Icon
|
||||
name="ci:cart"
|
||||
size="24px"
|
||||
class="**:stroke-black"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<Tooltip title="سبد خرید">
|
||||
<NuxtLink to="/cart" class="flex-center">
|
||||
<Icon
|
||||
name="ci:cart"
|
||||
size="24px"
|
||||
class="**:stroke-black"
|
||||
/>
|
||||
</NuxtLink>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<nav
|
||||
class="flex-center gap-[2.5rem] typo-label-sm font-light text-black/80"
|
||||
>
|
||||
<NuxtLink
|
||||
v-for="(link, index) in nav_links"
|
||||
v-for="(link, index) in NAV_LINKS"
|
||||
:key="index"
|
||||
:to="link.path"
|
||||
>
|
||||
|
||||
@@ -16,7 +16,7 @@ defineProps<Props>();
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
<TooltipContent
|
||||
class="bg-black text-white px-4 py-3 rounded-full text-sm font-iran-yekan-x animate-slide-down-fade"
|
||||
class="bg-black text-white px-4 py-3 rounded-full text-sm font-iran-yekan-x animate-slide-down-fade z-1000"
|
||||
:side-offset="5"
|
||||
>
|
||||
{{ title }}
|
||||
|
||||
@@ -56,3 +56,26 @@ export const PRODUCT_RANGE = {
|
||||
min: 0,
|
||||
max: 100_000_000,
|
||||
};
|
||||
|
||||
export const NAV_LINKS = [
|
||||
{
|
||||
title: "خانه",
|
||||
path: "/",
|
||||
},
|
||||
{
|
||||
title: "محصولات",
|
||||
path: "/products",
|
||||
},
|
||||
{
|
||||
title: "دسته بندی ها",
|
||||
path: "/category",
|
||||
},
|
||||
{
|
||||
title: "ارتباط با ما",
|
||||
path: "/contact-us",
|
||||
},
|
||||
{
|
||||
title: "امکانات",
|
||||
path: "#",
|
||||
},
|
||||
];
|
||||
|
||||
+29
-18
@@ -3,10 +3,14 @@ export default defineNuxtConfig({
|
||||
compatibilityDate: "2024-11-01",
|
||||
ssr: true,
|
||||
devtools: { enabled: true },
|
||||
css: ["~/assets/css/tailwind.css", "swiper/css", "animate.css/animate.min.css"],
|
||||
css: [
|
||||
"~/assets/css/tailwind.css",
|
||||
"swiper/css",
|
||||
"animate.css/animate.min.css",
|
||||
],
|
||||
|
||||
routeRules: {
|
||||
"/products": { prerender: false, ssr: false }
|
||||
"/products": { prerender: false, ssr: false },
|
||||
},
|
||||
|
||||
app: {
|
||||
@@ -15,22 +19,29 @@ export default defineNuxtConfig({
|
||||
"animate__animated animate__fadeIn animate__faster",
|
||||
leaveActiveClass:
|
||||
"animate__animated animate__fadeOut animate__faster",
|
||||
mode: "out-in"
|
||||
}
|
||||
mode: "out-in",
|
||||
},
|
||||
layoutTransition: {
|
||||
enterActiveClass:
|
||||
"animate__animated animate__fadeIn animate__faster",
|
||||
leaveActiveClass:
|
||||
"animate__animated animate__fadeOut animate__faster",
|
||||
mode: "out-in",
|
||||
},
|
||||
},
|
||||
|
||||
postcss: {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
autoprefixer: {},
|
||||
},
|
||||
},
|
||||
|
||||
components: [
|
||||
{
|
||||
path: "~/components",
|
||||
pathPrefix: false
|
||||
}
|
||||
pathPrefix: false,
|
||||
},
|
||||
],
|
||||
|
||||
icon: {
|
||||
@@ -38,9 +49,9 @@ export default defineNuxtConfig({
|
||||
customCollections: [
|
||||
{
|
||||
prefix: "ci",
|
||||
dir: "./public/icons"
|
||||
}
|
||||
]
|
||||
dir: "./public/icons",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
modules: [
|
||||
@@ -51,20 +62,20 @@ export default defineNuxtConfig({
|
||||
"DM Sans": "100..900",
|
||||
Inter: "100..900",
|
||||
download: true,
|
||||
inject: false
|
||||
}
|
||||
}
|
||||
inject: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
"@nuxt/icon",
|
||||
"reka-ui/nuxt",
|
||||
"@vueuse/nuxt",
|
||||
"@formkit/auto-animate/nuxt",
|
||||
'@nuxt/test-utils/module'
|
||||
"@nuxt/test-utils/module",
|
||||
],
|
||||
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
API_BASE_URL: "https://api.heymlz.com"
|
||||
}
|
||||
}
|
||||
API_BASE_URL: "https://api.heymlz.com",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
// meta
|
||||
|
||||
definePageMeta({
|
||||
middleware: "check-is-logged-in",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
// meta
|
||||
|
||||
definePageMeta({
|
||||
middleware: "check-is-logged-in",
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Vendored
+25
-17
@@ -44,23 +44,23 @@ declare global {
|
||||
};
|
||||
|
||||
type Article = {
|
||||
"id": number,
|
||||
"title": string,
|
||||
"slug": string,
|
||||
"content": string,
|
||||
"summery": string,
|
||||
"created_at": string,
|
||||
"updated_at": string,
|
||||
"cover_image": string,
|
||||
"views": number,
|
||||
"meta_description": string,
|
||||
"meta_keywords": string,
|
||||
"author": {
|
||||
"full_name": string,
|
||||
"profile_photo": string
|
||||
},
|
||||
"category": number
|
||||
}
|
||||
id: number;
|
||||
title: string;
|
||||
slug: string;
|
||||
content: string;
|
||||
summery: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
cover_image: string;
|
||||
views: number;
|
||||
meta_description: string;
|
||||
meta_keywords: string;
|
||||
author: {
|
||||
full_name: string;
|
||||
profile_photo: string;
|
||||
};
|
||||
category: number;
|
||||
};
|
||||
|
||||
type UserComment = {
|
||||
id: number;
|
||||
@@ -108,4 +108,12 @@ declare global {
|
||||
hour: string;
|
||||
price: string;
|
||||
};
|
||||
|
||||
type DropdownItem = {
|
||||
title: string;
|
||||
icon: string;
|
||||
itemClass?: string;
|
||||
iconClass?: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user