slug website

This commit is contained in:
hamid zarghami
2025-05-05 14:45:04 +03:30
parent 4a16d560d9
commit 78b02085c5
12 changed files with 229 additions and 12 deletions
+139
View File
@@ -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;
}
+1
View File
@@ -41,4 +41,5 @@ export interface DanakSuggestService {
icon: string;
deletedAt: string | null;
category: ServiceCategoryType;
slug: string;
}
+2
View File
@@ -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({
{/* <ToastContainer /> */}
<ToastContainer />
{/* <Splash /> */}
{/* <SplashChatgpt /> */}
</QueryProvider>
</body>
</html>
+2 -2
View File
@@ -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) {
+2 -2
View File
@@ -34,7 +34,7 @@ const Products: FC = () => {
return (
<SwiperSlide key={item.id} className='xl:max-w-[45%] max-w-[90%]'>
<div className='rounded-4xl overflow-hidden relative'>
<Link href={`/products/${item.id}`}>
<Link href={`/products/${item.slug}`}>
<Image
src={item.coverUrl}
alt='product'
@@ -70,7 +70,7 @@ const Products: FC = () => {
</div>
</div>
</div>
<Link href={`/products/${item.id}`}>
<Link href={`/products/${item.slug}`}>
<div className='flex gap-1.5 text-sm items-center'>
<div>جزییات</div>
<ArrowLeft
+5 -4
View File
@@ -1,6 +1,6 @@
import { Suspense } from 'react'
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'
import { detailServiceQueryOptions } from '../hooks/useProductData'
import { getProductBySlugQueryOptions } from '../hooks/useProductData'
import { Metadata, NextPage } from 'next'
import DetailService from '../DetailService'
import Loading from './loading'
@@ -19,8 +19,9 @@ export async function generateMetadata(
const { id } = await params
const queryClient = new QueryClient()
await queryClient.prefetchQuery(detailServiceQueryOptions(id))
const service = queryClient.getQueryData(detailServiceQueryOptions(id).queryKey) as ServiceDetailResponse
await queryClient.prefetchQuery(getProductBySlugQueryOptions(id))
const service = queryClient.getQueryData(getProductBySlugQueryOptions(id).queryKey) as ServiceDetailResponse
console.log('service', service);
return {
title: 'محصولات داناک' + ' | ' + service.data.danakService.name,
@@ -43,7 +44,7 @@ async function SingleServicePage({ id }: { id: string }) {
const queryClient = new QueryClient()
await Promise.all([
queryClient.prefetchQuery(detailServiceQueryOptions(id)),
queryClient.prefetchQuery(getProductBySlugQueryOptions(id)),
])
return (
+11
View File
@@ -51,7 +51,18 @@ export const useGetDetailService = (serviceId: string) =>
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),
});
@@ -45,3 +45,10 @@ export const getSliderProducts = async () => {
);
return data;
};
export const getProductBySlug = async (slug: string) => {
const { data } = await axios.get<ServiceDetailResponse>(
`/danak-services/slug/${slug}/public`
);
return data;
};
+1
View File
@@ -59,6 +59,7 @@ export interface DanakService {
link: string;
icon: string;
coverUrl: string;
slug: string;
category: {
id: string;
title: string;