pixel perfect

This commit is contained in:
hamid zarghami
2025-04-23 15:48:22 +03:30
parent 22844c71f1
commit 82c5dbdffa
11 changed files with 89 additions and 16 deletions
+2 -2
View File
@@ -21,11 +21,11 @@ export const metadata = {
const About: NextPage = () => { const About: NextPage = () => {
return ( return (
<div className='mt-24'> <div className='mt-24'>
<div className='flex items-start justify-between max-w-maxWidth mx-auto'> <div className='flex xl:flex-row flex-col items-start justify-between max-w-maxWidth mx-auto'>
<h1 className='text-2xl font-bold'> <h1 className='text-2xl font-bold'>
درباره ی داناک درباره ی داناک
</h1> </h1>
<div className='max-w-[500px] text-sm leading-6'> <div className='max-w-[500px] mt-4 xl:mt-0 text-sm leading-6'>
قبل از تبدیل شدن داناک به یک شرکت ، یک ایده بودیم. ایده ای نه برای ساخت یک محصول یا خدمت جدید، ایده ای برای ساخت یک فرهنگ خلاقانه و ارزش محور. داناک با این باور متولد شده که استعداد ، توانایی و تعهد افراد می تواند موتور محرکه شرکتی رو به آینده باشد. شرکتی که توانایی انجام کارهای شگفت انگیز و فوق العاده ای دارد و غیر ممکن ها را ممکن می سازد. داناک ترکیبی از بهترین مهندسین ، توانمندترین متخصصین ، جدیدترین تکنولوژی ها و خلاقانه ترین ایده هاست. به پشتوانه این ترکیب فوق العاده می توانیم با ارائه راه کار های مبتنی بر نرم افزار ، هوش مصنوعی و آنالیز داده به شما کمک کنیم تا سازمان خود را بهتر رصد کنید و تصمیم های هوشمندانه تری اتخاذ نمایید. قبل از تبدیل شدن داناک به یک شرکت ، یک ایده بودیم. ایده ای نه برای ساخت یک محصول یا خدمت جدید، ایده ای برای ساخت یک فرهنگ خلاقانه و ارزش محور. داناک با این باور متولد شده که استعداد ، توانایی و تعهد افراد می تواند موتور محرکه شرکتی رو به آینده باشد. شرکتی که توانایی انجام کارهای شگفت انگیز و فوق العاده ای دارد و غیر ممکن ها را ممکن می سازد. داناک ترکیبی از بهترین مهندسین ، توانمندترین متخصصین ، جدیدترین تکنولوژی ها و خلاقانه ترین ایده هاست. به پشتوانه این ترکیب فوق العاده می توانیم با ارائه راه کار های مبتنی بر نرم افزار ، هوش مصنوعی و آنالیز داده به شما کمک کنیم تا سازمان خود را بهتر رصد کنید و تصمیم های هوشمندانه تری اتخاذ نمایید.
</div> </div>
</div> </div>
+1 -1
View File
@@ -13,7 +13,7 @@ const BigBlogItem: FC<BigBlogItemProps> = ({ item }) => {
return ( return (
<div className='w-full rounded-4xl bg-white p-7 flex xl:flex-row flex-col gap-6'> <div className='w-full rounded-4xl bg-white p-7 flex xl:flex-row flex-col gap-6'>
<Link href={`/blogs/${item.slug}`}> <Link href={`/blogs/${item.slug}`}>
<Image src={item.imageUrl} alt='blog' width={300} height={300} className='size-[150px] object-cover mx-auto xl:mx-0 rounded-4xl' /> <Image src={item.imageUrl} alt='blog' width={300} height={300} className='xl:size-[150px] object-cover mx-auto xl:mx-0 rounded-4xl' />
</Link> </Link>
<div className='flex-1'> <div className='flex-1'>
<Link href={`/blogs/${item.slug}`}> <Link href={`/blogs/${item.slug}`}>
+7
View File
@@ -27,7 +27,9 @@ const BlogList: FC = () => {
<div className='mt-10 flex xl:flex-row flex-col gap-8'> <div className='mt-10 flex xl:flex-row flex-col gap-8'>
<div className='xl:w-[261px] w-full'> <div className='xl:w-[261px] w-full'>
<div className='hidden xl:block'>
<Category /> <Category />
</div>
{ {
@@ -68,6 +70,8 @@ const BlogList: FC = () => {
</a> </a>
} }
</div> </div>
<div className='flex-1 flex flex-col gap-8'> <div className='flex-1 flex flex-col gap-8'>
@@ -76,6 +80,9 @@ const BlogList: FC = () => {
))} ))}
</div> </div>
<div className='block xl:hidden'>
<Category />
</div>
<div className='xl:w-[261px] w-full'> <div className='xl:w-[261px] w-full'>
<MostVisited /> <MostVisited />
<div className='mt-6'> <div className='mt-6'>
+2 -2
View File
@@ -5,12 +5,12 @@ import Button from '../../../components/Button'
import { useFormik } from 'formik' import { useFormik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { ErrorType } from '../../../helpers/types' import { ErrorType } from '../../../helpers/types'
import { toast } from 'react-toastify'
import { useCreateBlogComment } from '../hooks/useBlogsData' import { useCreateBlogComment } from '../hooks/useBlogsData'
import { CreateBlogCommentType } from '../types/BlogTypes' import { CreateBlogCommentType } from '../types/BlogTypes'
import { useSharedStore } from '@/shared/store/sharedStore' import { useSharedStore } from '@/shared/store/sharedStore'
import Link from 'next/link' import Link from 'next/link'
import { LOGIN_URL } from '@/config/const' import { LOGIN_URL } from '@/config/const'
import { toast } from '@/components/Toast'
type Props = { type Props = {
refetch: () => void refetch: () => void
id: string id: string
@@ -41,7 +41,7 @@ const CreateReview: FC<Props> = ({ refetch, id }) => {
if (error.response && 'status' in error.response && error.response.status === 401) { if (error.response && 'status' in error.response && error.response.status === 401) {
window.location.href = LOGIN_URL + '?redirect=' + window.location.href window.location.href = LOGIN_URL + '?redirect=' + window.location.href
} else { } else {
toast.error(error.response?.data?.error?.message?.[0] || 'An error occurred') toast(error.response?.data?.error?.message?.[0] || 'An error occurred', 'error')
} }
} }
}) })
+3 -3
View File
@@ -8,8 +8,8 @@ import { CreateContactType } from './types/ContactTypes'
import { useFormik } from 'formik' import { useFormik } from 'formik'
import * as Yup from 'yup' import * as Yup from 'yup'
import { useCreateContact } from './hooks/useContactData' import { useCreateContact } from './hooks/useContactData'
import { toast } from 'react-toastify'
import { ErrorType } from '@/helpers/types' import { ErrorType } from '@/helpers/types'
import { toast } from '@/components/Toast'
const ContactForm = () => { const ContactForm = () => {
@@ -33,11 +33,11 @@ const ContactForm = () => {
onSubmit: (values) => { onSubmit: (values) => {
createContact.mutate(values, { createContact.mutate(values, {
onSuccess: () => { onSuccess: () => {
toast.success('پیام شما با موفقیت ثبت شد') toast('پیام شما با موفقیت ثبت شد', 'success')
formik.resetForm() formik.resetForm()
}, },
onError: (error: ErrorType) => { onError: (error: ErrorType) => {
toast.error(error.response?.data?.error.message[0]) toast(error.response?.data?.error.message[0] || 'An error occurred', 'error')
} }
}) })
}, },
+4 -4
View File
@@ -27,13 +27,13 @@ const HeroSection: FC = () => {
/> />
<div className='absolute flex items-center z-1 top-0 left-0 w-full h-full bg-black/10 rounded-4xl'> <div className='absolute flex items-center z-1 top-0 left-0 w-full h-full bg-black/10 rounded-4xl'>
<div className='max-w-maxWidth w-full mx-auto px-10 xl:text-4xl text-lg text-white'> <div className='max-w-maxWidth flex flex-col mt-1 xl:mt-0 xl:items-start items-center w-full mx-auto px-10 xl:text-4xl text-lg text-white'>
<p>{item.title}</p> <p className='xl:text-lg text-sm'>{item.title}</p>
<p className='xl:mt-5 font-bold'>{item.description}</p> <p className='xl:mt-5 mt-2 xl:text-2xl text-sm font-bold'>{item.description}</p>
<Link href={item.link}> <Link href={item.link}>
<Button <Button
className='xl:mt-12 mt-5 !w-fit px-10 bg-white !text-black' className='xl:mt-5 mt-2 !w-fit xl:px-10 px-5 h-8 xl:h-10 bg-white !text-black'
label='بیشتر بدانید' label='بیشتر بدانید'
/> />
</Link> </Link>
+3 -1
View File
@@ -4,13 +4,14 @@ import "swiper/css";
import "./globals.css"; import "./globals.css";
import 'rc-rate/assets/index.css'; import 'rc-rate/assets/index.css';
import "@/assets/fonts/irancell/style.css"; import "@/assets/fonts/irancell/style.css";
import { ToastContainer } from 'react-toastify'; // import { ToastContainer } from 'react-toastify';
import Header from "@/shared/Header"; import Header from "@/shared/Header";
import Footer from "@/shared/Footer"; import Footer from "@/shared/Footer";
import SideBar from "@/shared/SideBar"; import SideBar from "@/shared/SideBar";
import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import QueryProvider from "@/config/QueryProvider"; import QueryProvider from "@/config/QueryProvider";
import ToastContainer from "@/components/Toast";
const geistSans = Geist({ const geistSans = Geist({
variable: "--font-geist-sans", variable: "--font-geist-sans",
@@ -48,6 +49,7 @@ export default function RootLayout({
<Footer /> <Footer />
</div> </div>
<ReactQueryDevtools initialIsOpen={false} /> <ReactQueryDevtools initialIsOpen={false} />
{/* <ToastContainer /> */}
<ToastContainer /> <ToastContainer />
</QueryProvider> </QueryProvider>
+1 -1
View File
@@ -36,7 +36,7 @@ const Products: FC = () => {
<div className='rounded-4xl overflow-hidden relative'> <div className='rounded-4xl overflow-hidden relative'>
<Link href={`/products/${item.id}`}> <Link href={`/products/${item.id}`}>
<Image <Image
src={item.images[0].imageUrl} src={item.coverUrl}
alt='product' alt='product'
width={1080} width={1080}
height={1080} height={1080}
+1
View File
@@ -58,6 +58,7 @@ export interface DanakService {
isActive: boolean; isActive: boolean;
link: string; link: string;
icon: string; icon: string;
coverUrl: string;
category: { category: {
id: string; id: string;
title: string; title: string;
+59
View File
@@ -0,0 +1,59 @@
'use client'
import { CloseCircle, InfoCircle, TickCircle } from 'iconsax-react';
import React, { useState, useEffect } from 'react';
interface Toast {
id: string;
message: string;
type?: 'success' | 'error' | 'info';
}
let addToast: (toast: Toast) => void;
const ToastContainer: React.FC = () => {
const [toasts, setToasts] = useState<Toast[]>([]);
// ثبت toast جدید
const showToast = (toast: Toast) => {
setToasts((prev) => [...prev, toast]);
// حذف خودکار بعد از ۳ ثانیه
setTimeout(() => {
setToasts((prev) => prev.filter((t) => t.id !== toast.id));
}, 3000);
};
// تخصیص تابع نمایش toast به متغیر سراسری
useEffect(() => {
addToast = showToast;
}, []);
return (
<div className="fixed top-4 text-sm right-0 left-0 mx-auto w-fit z-50 flex flex-col gap-2">
{toasts.map((toast) => (
<div
key={toast.id}
className={`px-4 flex items-center gap-2 backdrop-blur-2xl h-16 min-w-[300px] rounded-2xl shadow-md transition-transform ${toast.type === 'success'
? 'bg-white/70 text-black'
: toast.type === 'error'
? 'bg-white/70 text-black'
: 'bg-white/70 text-black'
}`}
>
{
toast.type === 'success' ? <TickCircle className='size-5' color='green' /> :
toast.type === 'error' ? <CloseCircle className='size-5' color='red' /> :
<InfoCircle className='size-5' color='blue' />
}
{toast.message}
</div>
))}
</div>
);
};
export const toast = (message: string, type: 'success' | 'error' | 'info' = 'info') => {
addToast({ id: Date.now().toString(), message, type });
};
export default ToastContainer;
+5 -1
View File
@@ -93,7 +93,7 @@ const Footer: FC = () => {
</div> </div>
</div> </div>
<div className='w-full flex-1 max-w-[204px]'> <div className='w-full flex-1 xl:max-w-[204px]'>
<h6 className='font-bold xl:text-base text-xs'> <h6 className='font-bold xl:text-base text-xs'>
خبرنامه خبرنامه
</h6> </h6>
@@ -173,6 +173,10 @@ const Footer: FC = () => {
</Link> </Link>
</ul> </ul>
<a referrerPolicy='origin' target='_blank' href='https://trustseal.enamad.ir/?id=587664&Code=5mx5bxt3mnywD3cXcgFawApYNfTjmYGX'>
<img referrerPolicy='origin' src='https://trustseal.enamad.ir/logo.aspx?id=587664&Code=5mx5bxt3mnywD3cXcgFawApYNfTjmYGX' alt='enamad trust seal' style={{ cursor: 'pointer' }} />
</a>
<div className='xl:text-sm text-xs dltr pb-4 xl:pb-0'> <div className='xl:text-sm text-xs dltr pb-4 xl:pb-0'>
© 2025 Danak. All rights reserved. © 2025 Danak. All rights reserved.
</div> </div>