From 78b02085c55a8b24eddc491bc340ac48a28e25c8 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Mon, 5 May 2025 14:45:04 +0330 Subject: [PATCH] slug website --- src/app/globals.css | 139 +++++++++++++++++++++ src/app/home/types/HomeTypes.ts | 1 + src/app/layout.tsx | 2 + src/app/products/DetailService.tsx | 4 +- src/app/products/ProductsPage.tsx | 4 +- src/app/products/[id]/page.tsx | 9 +- src/app/products/hooks/useProductData.ts | 11 ++ src/app/products/service/ProductService.ts | 7 ++ src/app/products/types/ProductTypes.ts | 1 + src/components/ServiceItem.tsx | 2 +- src/components/SplashChatgpt.tsx | 55 ++++++++ src/shared/Footer.tsx | 6 +- 12 files changed, 229 insertions(+), 12 deletions(-) create mode 100644 src/components/SplashChatgpt.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 2c7a482..3be9ee8 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -153,3 +153,142 @@ tbody tr { .animate-slide-up { animation: slideUp 1s ease-out forwards; } + +@keyframes fade-in { + 0% { + opacity: 0; + transform: scale(0.9); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes pattern-fade-in { + 0% { + opacity: 0; + } + 50% { + opacity: 0.05; + } + 100% { + opacity: 0.05; + } +} + +@keyframes logo-float { + 0% { + transform: scale(0.9); + opacity: 0; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +@keyframes logo-glow { + 0% { + filter: drop-shadow(0 0 0 rgba(0, 0, 0, 0)); + } + 50% { + filter: drop-shadow(0 0 10px rgba(0, 0, 0, 0.1)); + } + 100% { + filter: drop-shadow(0 0 0 rgba(0, 0, 0, 0)); + } +} + +@keyframes progress-bar { + 0% { + width: 0%; + } + 100% { + width: 100%; + } +} + +.animate-fade-in { + animation: fade-in 0.8s ease-out forwards; +} + +.animate-pattern-fade-in { + animation: pattern-fade-in 1.5s ease-out forwards; +} + +.animate-logo-float { + animation: logo-float 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards; +} + +.animate-logo-glow { + animation: logo-glow 3s ease-in-out infinite; +} + +.animate-progress-bar { + animation: progress-bar 2.5s ease-out forwards; +} + +@keyframes circle-pulse { + 0% { + transform: scale(0.8); + opacity: 0; + } + 50% { + transform: scale(1); + opacity: 1; + } + 100% { + transform: scale(1.2); + opacity: 0; + } +} + +@keyframes circle-pulse-delayed { + 0% { + transform: scale(0.8); + opacity: 0; + } + 25% { + transform: scale(0.9); + opacity: 0.5; + } + 75% { + transform: scale(1.1); + opacity: 0.5; + } + 100% { + transform: scale(1.3); + opacity: 0; + } +} + +@keyframes wave { + 0% { + transform: translateX(0) translateY(0); + } + 50% { + transform: translateX(-25%) translateY(-10px); + } + 100% { + transform: translateX(-50%) translateY(0); + } +} + +.animate-circle-pulse { + animation: circle-pulse 3s ease-out infinite; +} + +.animate-circle-pulse-delayed { + animation: circle-pulse-delayed 3s ease-out infinite; +} + +.animate-wave { + background: linear-gradient( + 90deg, + transparent, + rgba(0, 0, 0, 0.05), + transparent + ); + animation: wave 10s linear infinite; +} diff --git a/src/app/home/types/HomeTypes.ts b/src/app/home/types/HomeTypes.ts index 5e4c2fe..577fd91 100644 --- a/src/app/home/types/HomeTypes.ts +++ b/src/app/home/types/HomeTypes.ts @@ -41,4 +41,5 @@ export interface DanakSuggestService { icon: string; deletedAt: string | null; category: ServiceCategoryType; + slug: string; } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 98ab4b9..517d73e 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -12,6 +12,7 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import QueryProvider from "@/config/QueryProvider"; import ToastContainer from "@/components/Toast"; +// import SplashChatgpt from "@/components/SplashChatgpt"; // import Splash from "@/components/Splash"; const geistSans = Geist({ @@ -53,6 +54,7 @@ export default function RootLayout({ {/* */} {/* */} + {/* */} diff --git a/src/app/products/DetailService.tsx b/src/app/products/DetailService.tsx index d9083ec..80afb2c 100644 --- a/src/app/products/DetailService.tsx +++ b/src/app/products/DetailService.tsx @@ -1,6 +1,6 @@ 'use client' import { FC, Fragment } from 'react' -import { useGetDetailService } from './hooks/useProductData' +import { useGetProductBySlug } from './hooks/useProductData' import ServiceHeader from './components/ServiceHeader' import moment from 'moment-jalaali' import ServiceImages from './components/ServiceImages' @@ -18,7 +18,7 @@ const DetailService: FC<{ id: string }> = ({ id }) => { // const { t } = useTranslation('global') // const getAdsLeft = useGetAds(AdsDisplayLocation.SINGLE_SERVICE_PAGE) - const getDetailService = useGetDetailService(id) + const getDetailService = useGetProductBySlug(id) // Show the skeleton loading component while data is loading if (getDetailService.isLoading) { diff --git a/src/app/products/ProductsPage.tsx b/src/app/products/ProductsPage.tsx index fb69515..6fe8a3b 100644 --- a/src/app/products/ProductsPage.tsx +++ b/src/app/products/ProductsPage.tsx @@ -34,7 +34,7 @@ const Products: FC = () => { return (
- + product {
- +
جزییات
queryFn: () => api.getDetailService(serviceId), }); +export const useGetProductBySlug = (slug: string) => + useQuery({ + queryKey: ["product-detail", slug], + queryFn: () => api.getProductBySlug(slug), + }); + export const detailServiceQueryOptions = (serviceId: string) => ({ queryKey: ["service-detail", serviceId], queryFn: () => api.getDetailService(serviceId), }); + +export const getProductBySlugQueryOptions = (slug: string) => ({ + queryKey: ["product-detail", slug], + queryFn: () => api.getProductBySlug(slug), +}); diff --git a/src/app/products/service/ProductService.ts b/src/app/products/service/ProductService.ts index abb3d8d..5f40548 100644 --- a/src/app/products/service/ProductService.ts +++ b/src/app/products/service/ProductService.ts @@ -45,3 +45,10 @@ export const getSliderProducts = async () => { ); return data; }; + +export const getProductBySlug = async (slug: string) => { + const { data } = await axios.get( + `/danak-services/slug/${slug}/public` + ); + return data; +}; diff --git a/src/app/products/types/ProductTypes.ts b/src/app/products/types/ProductTypes.ts index ab0ce06..b5f246a 100644 --- a/src/app/products/types/ProductTypes.ts +++ b/src/app/products/types/ProductTypes.ts @@ -59,6 +59,7 @@ export interface DanakService { link: string; icon: string; coverUrl: string; + slug: string; category: { id: string; title: string; diff --git a/src/components/ServiceItem.tsx b/src/components/ServiceItem.tsx index 44c8204..9242377 100644 --- a/src/components/ServiceItem.tsx +++ b/src/components/ServiceItem.tsx @@ -11,7 +11,7 @@ type Props = { const ServiceItem: FC = (props) => { return ( - +
{props.item.name} diff --git a/src/components/SplashChatgpt.tsx b/src/components/SplashChatgpt.tsx new file mode 100644 index 0000000..8c9727f --- /dev/null +++ b/src/components/SplashChatgpt.tsx @@ -0,0 +1,55 @@ +'use client'; +import { useEffect, useState } from 'react'; +import Image from 'next/image'; + +const SplashChatgpt = () => { + const [fadeOut, setFadeOut] = useState(false); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + const timer = setTimeout(() => { + setFadeOut(true); + }, 3000); + return () => clearTimeout(timer); + }, []); + + useEffect(() => { + if (fadeOut) { + document.body.style.overflow = 'auto'; + } else { + document.body.style.overflow = 'hidden'; + } + }, [fadeOut]); + + if (!mounted) return null; + + return ( +
+
+ + {/* Decorative circles */} +
+
+ + + +
+
+ Danak Logo +
+
+
+ ); +}; + +export default SplashChatgpt; \ No newline at end of file diff --git a/src/shared/Footer.tsx b/src/shared/Footer.tsx index b51bf4c..a2c7f0d 100644 --- a/src/shared/Footer.tsx +++ b/src/shared/Footer.tsx @@ -58,17 +58,17 @@ const Footer: FC = () => {
  • - + دی منو
  • - + دی میل
  • - + دی پیج