ads + blog + ...

This commit is contained in:
hamid zarghami
2025-04-19 15:35:22 +03:30
parent cdc611a65d
commit 1bf0b56a63
20 changed files with 236 additions and 73 deletions
+10
View File
@@ -0,0 +1,10 @@
import * as api from "../service/AdsService";
import { useQuery } from "@tanstack/react-query";
export const useGetAds = (location: string) => {
return useQuery({
queryKey: ["ads", location],
queryFn: () => api.getAds(location),
enabled: !!location,
});
};
+8
View File
@@ -0,0 +1,8 @@
import axios from "@/config/axios";
export const getAds = async (location: string) => {
const { data } = await axios.get(
`/advertise/by-location?location=${location}`
);
return data;
};
+23
View File
@@ -0,0 +1,23 @@
export enum AdsDisplayLocation {
HOMEPAGE_TOP = "HOMEPAGE_TOP",
SINGLE_SERVICE_PAGE = "SINGLE_SERVICE_PAGE",
MY_SERVICES_PAGE = "MY_SERVICES_PAGE",
OTHER_SERVICES_TOP = "OTHER_SERVICES_TOP",
OTHER_SERVICES_LEFT = "OTHER_SERVICES_LEFT",
SERVICE = "SERVICE",
BLOG_PAGE_TOP_RIGHT = "BLOG_PAGE_TOP_RIGHT",
BLOG_PAGE_BOTTOM_RIGHT = "BLOG_PAGE_BOTTOM_RIGHT",
BLOG_PAGE_TOP_LEFT = "BLOG_PAGE_TOP_LEFT",
}
export type AdsItemType = {
id: string;
title: string;
imageUrl: string;
link: string;
isActive: boolean;
createdAt: string;
startDate: string;
endDate: string;
displayLocation: AdsDisplayLocation;
};
+45
View File
@@ -7,10 +7,15 @@ import MostVisited from './MostVisited'
import ContactUs from './ContactUs'
import { useGetBlogs } from '../hooks/useBlogsData'
import { useBlogStore } from '../store/BlogStore'
import { useGetAds } from '@/app/ads/hooks/useAdsData'
import { AdsDisplayLocation } from '@/app/ads/types/AdsTypes'
import Image from 'next/image'
const BlogList: FC = () => {
const { selectedCategory } = useBlogStore()
const { data } = useGetBlogs(selectedCategory)
const getAds = useGetAds(AdsDisplayLocation.BLOG_PAGE_TOP_RIGHT)
const getAdsBottom = useGetAds(AdsDisplayLocation.BLOG_PAGE_BOTTOM_RIGHT)
return (
<div className=''>
@@ -23,6 +28,46 @@ const BlogList: FC = () => {
<div className='mt-10 flex xl:flex-row flex-col gap-8'>
<div className='xl:w-[261px] w-full'>
<Category />
{
getAds.isSuccess && getAds.data.data.ads[0] &&
<a href={getAds.data?.data?.ads[0].link} target='_blank' className='mt-11 relative flex w-full aspect-square bg-white rounded-4xl overflow-hidden'>
<Image
alt={getAds.data.data.ads[0].title}
width={261}
height={550}
src={getAds.data.data.ads[0].imageUrl}
className='w-full backdrop-blur-[100px] aspect-square object-cover'
/>
<div className='absolute flex items-center px-4 w-full bottom-0 h-[86px] bg-black bg-opacity-5 backdrop-blur-[14px]'>
<div className='max-w-[80%] text-sm leading-6 text-white'>
{getAds.data.data.ads[0].title}
</div>
</div>
</a>
}
{
getAdsBottom.isSuccess && getAdsBottom.data.data.ads[0] &&
<a href={getAdsBottom.data?.data?.ads[0].link} target='_blank' className='flex-1 mt-11 bg-white relative rounded-4xl min-h-[500px] overflow-hidden flex'>
<Image
alt={getAdsBottom.data.data.ads[0].title}
width={261}
height={550}
src={getAdsBottom.data.data.ads[0].imageUrl}
className='w-full backdrop-blur-[100px] aspect-square object-cover'
/>
<div className='absolute flex items-center px-4 w-full bottom-0 h-[86px] bg-black bg-opacity-5 backdrop-blur-[14px]'>
<div className='max-w-[80%] text-sm leading-6 text-white'>
{getAdsBottom.data.data.ads[0].title}
</div>
</div>
</a>
}
</div>
<div className='flex-1 flex flex-col gap-8'>
+45 -23
View File
@@ -2,40 +2,62 @@ import BlogItem from '@/components/BlogItem'
import Image from 'next/image'
import { FC } from 'react'
import { useGetBlogCombined } from '../hooks/useBlogsData'
import { AdsDisplayLocation } from '@/app/ads/types/AdsTypes'
import { useGetAds } from '@/app/ads/hooks/useAdsData'
const HeroSection: FC = () => {
const { data } = useGetBlogCombined()
const getAdsTopLeft = useGetAds(AdsDisplayLocation.BLOG_PAGE_TOP_LEFT)
return (
<div>
{
data?.data?.pinnedBlogs?.map((item, index: number) => {
if (index === 0) {
return (
<div key={item.id} className='relative rounded-4xl overflow-hidden'>
<Image
src={item.imageUrl}
alt={item.title}
width={1920}
height={1080}
className='w-full rounded-4xl object-cover xl:mt-14 mt-8 xl:min-h-[210px] min-h-[350px] max-h-[450px]'
/>
<div className='flex gap-8 xl:mt-14 mt-8'>
{
data?.data?.pinnedBlogs?.map((item, index: number) => {
if (index === 0) {
return (
<div key={item.id} className='relative flex-[2] rounded-4xl overflow-hidden h-fit bg-red-50'>
<Image
src={item.imageUrl}
alt={item.title}
width={1920}
height={1080}
className='w-full rounded-4xl object-cover xl:min-h-[210px] min-h-[350px] max-h-[450px]'
/>
<div className='absolute bottom-0 h-[140px] modalGlass3 w-full p-6 text-white'>
<h4 className='font-bold xl:text-base text-sm'>
{item.title}
</h4>
<div className='absolute bottom-0 h-[140px] modalGlass3 w-full p-6 text-white'>
<h4 className='font-bold xl:text-base text-sm'>
{item.title}
</h4>
<div className="text-xs xl:text-sm mt-4 leading-7 truncate xl:text-clip xl:whitespace-normal">
{item.previewContent.replace(/<\/?[^>]+(>|$)/g, "")}
<div className="text-xs xl:text-sm mt-4 leading-7 truncate xl:text-clip xl:whitespace-normal line-clamp-2">
{item.previewContent.replace(/<\/?[^>]+(>|$)/g, "")}
</div>
</div>
</div>
)
}
})
}
{
getAdsTopLeft.isSuccess && getAdsTopLeft.data.data.ads[0] &&
<a href={getAdsTopLeft.data?.data?.ads[0].link} target='_blank' className='flex-1 overflow-hidden relative hidden xl:flex bg-gray-100 rounded-4xl items-center justify-center'>
<Image
alt={getAdsTopLeft.data.data.ads[0].title}
width={261}
height={550}
src={getAdsTopLeft.data.data.ads[0].imageUrl}
className='w-full h-full backdrop-blur-[100px] aspect-square object-cover'
/>
<div className='absolute flex items-center px-4 w-full bottom-0 h-[86px] bg-black bg-opacity-5 backdrop-blur-[14px]'>
<div className='max-w-[80%] text-sm leading-6 text-white'>
{getAdsTopLeft.data.data.ads[0].title}
</div>
)
}
})
}
</div>
</a>
}
</div>
<div className='flex xl:flex-row flex-col gap-8 mt-10'>
+6 -1
View File
@@ -100,11 +100,13 @@ const Contact: NextPage = () => {
placeholder='نام و نام خانوادگی'
{...formik.getFieldProps('fullName')}
error_text={formik.touched.fullName && formik.errors.fullName ? formik.errors.fullName : undefined}
className='border-t-0 border-x-0 rounded-none place-black'
/>
<Input
placeholder='نام شرکت '
{...formik.getFieldProps('businessName')}
error_text={formik.touched.businessName && formik.errors.businessName ? formik.errors.businessName : undefined}
className='border-t-0 border-x-0 rounded-none place-black'
/>
</div>
<div className='rowTwoInput mt-8'>
@@ -112,19 +114,22 @@ const Contact: NextPage = () => {
placeholder='شماره تماس'
{...formik.getFieldProps('phone')}
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : undefined}
className='border-t-0 border-x-0 rounded-none place-black'
/>
<Input
placeholder='ایمیل'
{...formik.getFieldProps('email')}
error_text={formik.touched.email && formik.errors.email ? formik.errors.email : undefined}
className='border-t-0 border-x-0 rounded-none place-black'
/>
</div>
<div className='mt-8'>
<Textarea
label='پیام'
placeholder='پیام'
{...formik.getFieldProps('content')}
error_text={formik.touched.content && formik.errors.content ? formik.errors.content : undefined}
className='border-t-0 border-x-0 place-black rounded-none min-h-[40px]'
/>
</div>
@@ -38,7 +38,7 @@ const DanakServicesContent: FC = () => {
<div className='flex-1 xl:p-4 p-2 bg-white/23 rounded-4xl border-[3px] border-white'>
<Image
src='https://picsum.photos/seed/picsum/200/300'
src='/images/consulting.webp'
alt='service-1'
width={300}
height={300}
@@ -51,7 +51,7 @@ const DanakServicesContent: FC = () => {
<div className='max-w-maxWidth px-4 xl:px-0 mx-auto flex xl:flex-row flex-col items-center xl:gap-32 gap-14'>
<div className='flex-1 xl:p-4 p-2 bg-white/23 rounded-4xl border-[3px] border-white'>
<Image
src='https://picsum.photos/seed/picsum/200/300'
src='/images/security.webp'
alt='service-1'
width={300}
height={300}
@@ -102,7 +102,7 @@ const DanakServicesContent: FC = () => {
<div className='flex-1 xl:p-4 p-2 bg-white/23 rounded-4xl border-[3px] border-white'>
<Image
src='https://picsum.photos/seed/picsum/200/300'
src='/images/solutions.webp'
alt='service-1'
width={300}
height={300}
@@ -115,7 +115,7 @@ const DanakServicesContent: FC = () => {
<div className='max-w-maxWidth px-4 xl:px-0 mx-auto flex xl:flex-row flex-col items-center xl:gap-32 gap-14'>
<div className='flex-1 xl:p-4 p-2 bg-white/23 rounded-4xl border-[3px] border-white'>
<Image
src='https://picsum.photos/seed/picsum/200/300'
src='/images/support.webp'
alt='service-1'
width={300}
height={300}
+8
View File
@@ -35,6 +35,14 @@ textarea::placeholder {
color: #888888;
}
input.place-black::placeholder {
color: black;
}
textarea.place-black::placeholder {
color: black;
}
@theme {
--color-primary: black;
--color-description: #888888;
+3
View File
@@ -34,6 +34,9 @@ export default function RootLayout({
}>) {
return (
<html lang="fa">
<head>
<link rel="icon" href="/favicon.svg" sizes="any" />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
+31 -31
View File
@@ -29,60 +29,60 @@ const Representatives: NextPage = () => {
</h6>
<div className='flex gap-8 flex-wrap mt-14'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#0028FF' size={24} />}
title='محصولات داناک'
description='متفاوت و قدرتمند و به اعتراف مشتریان در نظر سنجی های انجام شده فوق العاده راحت است. لذا خود محصولات می توانند مشتری های بعدی خود را به سرعت جذب نماید.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
icon={<TickCircle color='#FF7B00' size={24} />}
title='مهارت'
description='روش های موفق پیشنهادی برای چگونگی افزایش مشتریان بالقوه، نحوه ارائه نرم افزار، نحوه قطعی کردن فروش و دیگر مهارت های فروش که در اختیار نمایندگان جدید قرار خواهد گرفت.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
icon={<TickCircle color='#00980F' size={24} />}
title='رشد فردی'
description='برگزاری دوره ای همایش هایی سراسری برای نمایندگان کل کشور و ایجاد شرایطی برای رشد و بروز شدن اطلاعات نمایندگان در زمینه های مختلف فروش و بازاریابی با حضور اساتید مطرح این علوم.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#FF00B8' size={24} />}
title='درامد خوب'
description='فروش نرم افزار یکی از مشاغل جدید و بسیار پر درآمد در بسیاری از کشورهاست. در کشور ما نیز اخیرا مشتریان نرم افزاری همچون سیلی در مقابل تولیدکنندگان و فروشندگان نرم افزاری ظهور پیدا کرده اند. به طوری که هیچ سقفی برای درآمد مدیران توانمند در این حرفه وجود ندارد.'
icon={<TickCircle color='#FFB800' size={24} />}
title='ارتقا شغلی'
description='نمایندگانی که با انرژی فعالیت میکنند، درآمد نسبتا بالایی دارند به طوری که نمایندگان میتوانند برای ارتقای شغلی و درآمد زایی خود در این شرکت، اهداف دراز مدت تعیین کنند.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1'>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#E63EF5' size={24} />}
title='سیاست ها'
description='سیاست ها و استراتژی های اعطای نمایندگی در شرکت داناک منحصر به فرد، نماینده محور می باشد.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#FF2E00' size={24} />}
title='روابط عمومی'
description='کسانی که دارای روابط عمومی بالایی هستند و یا دوست دارند که روابط گسترده ای ایجاد کنند، بهترین ها خواهند بود.'
/>
</div>
<div className='xl:min-w-[23%] min-w-[60%] flex-1 flex'>
<InfoBox
icon={<TickCircle color='#0028FF' size={24} />}
title='محصولات داناک'
description='متفاوت و قدرتمند و به اعتراف مشتریان در نظر سنجی های انجام شده فوق العاده راحت است. لذا خود محصولات می توانند مشتری های بعدی خود را به سرعت جذب نماید.'
title='یکپارچگی مجموعه'
description='ارتباط نزدیک و صمیمانه دفتر مرکزی با نمایندگان و همراهی آن ها.'
/>
</div>
</div>