diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx
index 87b97a3..35f1ebf 100644
--- a/src/app/about/page.tsx
+++ b/src/app/about/page.tsx
@@ -1,7 +1,8 @@
import InfoBox from '@/components/InfoBox'
-import { AddCircle, TickCircle } from 'iconsax-react'
+import { TickCircle } from 'iconsax-react'
import { NextPage } from 'next'
import React from 'react'
+import Accordion from '@/components/Accordion'
import WhyDanak from '../home/WhyDanak'
const About: NextPage = () => {
@@ -63,19 +64,19 @@ const About: NextPage = () => {
صادرکنندگان نرم افزار
- صادرکنندگان نرم افزار
+ مشاوره استقرار ISMS
- صادرکنندگان نرم افزار
+ نظام صنفی
- صادرکنندگان نرم افزار
+ GDPR
- صادرکنندگان نرم افزار
+ ISO:27001
- صادرکنندگان نرم افزار
+ SSAE18
@@ -93,42 +94,9 @@ const About: NextPage = () => {
diff --git a/src/app/blogs/[id]/page.tsx b/src/app/blogs/[id]/page.tsx
index 91fbed1..8a66de3 100644
--- a/src/app/blogs/[id]/page.tsx
+++ b/src/app/blogs/[id]/page.tsx
@@ -14,7 +14,6 @@ interface PageProps {
const SingleBlog: NextPage = async ({ params }) => {
const { id } = await params
- console.log("loading", id);
return (
}>
@@ -24,7 +23,6 @@ const SingleBlog: NextPage = async ({ params }) => {
}
async function BlogContent({ id }: { id: string }) {
- console.log(id)
const queryClient = new QueryClient()
await Promise.all([
diff --git a/src/app/blogs/components/CreateReview.tsx b/src/app/blogs/components/CreateReview.tsx
new file mode 100644
index 0000000..5b13b40
--- /dev/null
+++ b/src/app/blogs/components/CreateReview.tsx
@@ -0,0 +1,112 @@
+import { FC } from 'react'
+import Input from '../../../components/Input'
+import Textarea from '../../../components/Textarea'
+import Button from '../../../components/Button'
+import { useFormik } from 'formik'
+import * as Yup from 'yup'
+import { ErrorType } from '../../../helpers/types'
+import { toast } from 'react-toastify'
+import { useCreateBlogComment } from '../hooks/useBlogsData'
+import { CreateBlogCommentType } from '../types/BlogTypes'
+import { useSharedStore } from '@/shared/store/sharedStore'
+import Link from 'next/link'
+import { LOGIN_URL } from '@/config/const'
+type Props = {
+ refetch: () => void
+ id: string
+}
+
+const CreateReview: FC = ({ refetch, id }) => {
+
+ const { isLogin } = useSharedStore()
+
+ const createReview = useCreateBlogComment()
+
+ const formik = useFormik({
+ initialValues: {
+ title: '',
+ content: ''
+ },
+ validationSchema: Yup.object({
+ title: Yup.string().required('این فیلد الزامی است'),
+ content: Yup.string().required('این فیلد الزامی است'),
+ }),
+ onSubmit: (values) => {
+ createReview.mutate({ id: id, params: values }, {
+ onSuccess: () => {
+ formik.resetForm()
+ refetch()
+ },
+ onError: (error: ErrorType) => {
+ if (error.response && 'status' in error.response && error.response.status === 401) {
+ window.location.href = LOGIN_URL + '?redirect=' + window.location.href
+ } else {
+ toast.error(error.response?.data?.error?.message?.[0] || 'An error occurred')
+ }
+ }
+ })
+ },
+
+ })
+
+ return (
+
+
+ ارسال نظر
+
+
+
+ {
+ !isLogin ? (
+
+
+ برای ارسال نظر لطفا وارد حساب کاربری خود شوید
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+
+ formik.handleSubmit()}
+ isLoading={createReview.isPending}
+ />
+
+
+ )
+ }
+
+ )
+}
+
+export default CreateReview
\ No newline at end of file
diff --git a/src/app/blogs/components/SingleBlogPage.tsx b/src/app/blogs/components/SingleBlogPage.tsx
index 9dfbdfc..397e3cc 100644
--- a/src/app/blogs/components/SingleBlogPage.tsx
+++ b/src/app/blogs/components/SingleBlogPage.tsx
@@ -1,20 +1,21 @@
'use client'
-import { Profile, Calendar } from 'iconsax-react'
+import { Profile, Calendar, Tag } from 'iconsax-react'
import { FC } from 'react'
import Image from 'next/image'
// import MostVisited from '../components/MostVisited'
import ContactUs from '../components/ContactUs'
import { useGetBlogSingle } from '../hooks/useBlogsData'
-import { toJalaliDate } from '@/config/func'
+import { timeAgo, toJalaliDate } from '@/config/func'
import MostVisited from './MostVisited'
import { TelegramShareButton, WhatsappShareButton } from 'react-share'
+import CreateReview from './CreateReview'
type Props = {
id: string
}
const SingleBlogPage: FC = ({ id }) => {
- const { data } = useGetBlogSingle(id)
+ const { data, refetch } = useGetBlogSingle(id)
if (!data) return null
@@ -64,6 +65,20 @@ const SingleBlogPage: FC = ({ id }) => {
+
+
+
برچسب ها :
+ {
+ data?.data?.blog?.tags.map((tag) => {
+ return (
+
+ {tag}
+
+ )
+ })
+ }
+
+
اشتراک گذاری
@@ -84,6 +99,8 @@ const SingleBlogPage: FC
= ({ id }) => {
/>
+
+
@@ -96,6 +113,50 @@ const SingleBlogPage: FC
= ({ id }) => {
+
+
+
+
+
+ نظرات کاربران
+
+
+ {
+ data?.data?.comments?.length === 0 ?
+
+
+ هیچ نظری ثبت نشده است
+
+
+ :
+ data?.data?.comments?.map((comment) => {
+ return (
+
+
+
+
+ {comment.user?.firstName + ' ' + comment.user?.lastName}
+
+
+
+
+
+ {comment.title}
+
+
+ {timeAgo(comment.createdAt)}
+
+
+
+
+ {comment.content}
+
+
+ )
+ })
+ }
+
+
)
}
diff --git a/src/app/blogs/hooks/useBlogsData.ts b/src/app/blogs/hooks/useBlogsData.ts
index 874f9e4..d2d9d85 100644
--- a/src/app/blogs/hooks/useBlogsData.ts
+++ b/src/app/blogs/hooks/useBlogsData.ts
@@ -1,5 +1,6 @@
-import { useQuery } from "@tanstack/react-query";
+import { useQuery, useMutation } from "@tanstack/react-query";
import * as api from "../service/BlogService";
+import { CreateBlogCommentType } from "../types/BlogTypes";
// برای client
export const useGetBlogs = (categoryId: string) =>
@@ -38,6 +39,12 @@ export const useGetBlogSingle = (id: string) =>
queryFn: () => api.getBlogSingle(id),
});
+export const useCreateBlogComment = () =>
+ useMutation({
+ mutationFn: (variables: { id: string; params: CreateBlogCommentType }) =>
+ api.createBlogComment(variables.id, variables.params),
+ });
+
// برای server prefetch
export const blogsQueryOptions = {
queryKey: ["blogs", ""],
diff --git a/src/app/blogs/service/BlogService.ts b/src/app/blogs/service/BlogService.ts
index ade3d0a..0bda7ec 100644
--- a/src/app/blogs/service/BlogService.ts
+++ b/src/app/blogs/service/BlogService.ts
@@ -4,6 +4,7 @@ import {
BlogCombinedResponse,
BlogResponse,
BlogSingleResponse,
+ CreateBlogCommentType,
} from "../types/BlogTypes";
export const getBlogs = async (categoryId: string) => {
@@ -41,3 +42,14 @@ export const getBlogSingle = async (slug: string) => {
const { data } = await axios.get(`/blogs/slug/${slug}`);
return data;
};
+
+export const createBlogComment = async (
+ id: string,
+ params: CreateBlogCommentType
+) => {
+ const { data } = await axios.post(
+ `/blogs/${id}/comments`,
+ params
+ );
+ return data;
+};
diff --git a/src/app/blogs/types/BlogTypes.ts b/src/app/blogs/types/BlogTypes.ts
index 7f02751..7503a2b 100644
--- a/src/app/blogs/types/BlogTypes.ts
+++ b/src/app/blogs/types/BlogTypes.ts
@@ -25,6 +25,7 @@ export interface Blog {
author: Author;
category: Category;
content: string;
+ tags: string[];
}
export interface Pager {
@@ -59,6 +60,28 @@ export type BlogStoreType = {
setSelectedCategory: (category: string) => void;
};
+export type Comment = {
+ id: string;
+ createdAt: string;
+ title: string;
+ content: string;
+ status: string;
+ user: User;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ profilePic: string;
+};
+
export type BlogSingleResponse = ApiResponse<{
blog: Blog;
+ comments: Comment[];
}>;
+
+export type CreateBlogCommentType = {
+ title: string;
+ content: string;
+};
diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx
index f5cb1c8..117b4bc 100644
--- a/src/app/contact/page.tsx
+++ b/src/app/contact/page.tsx
@@ -59,7 +59,7 @@ const Contact: NextPage = () => {
color='black'
/>
- ۰۲۱-۲۱۲۳۲۱۲۳ | ۰۸۶-۲۱۰۰۲۰۰۱
+ ۰۲۱-۹۱۶۹۳۵۳۳
@@ -85,7 +85,7 @@ const Contact: NextPage = () => {
color='black'
/>
- یوسف آباد، فتجی شقایق، پلاک ۵ ، واحد ۱۳
+ تهران - یوسف آباد - فتحی شقاقی - پلاک ۵ - واحد ۱۳
diff --git a/src/app/danak-services/DanakServicesContent.tsx b/src/app/danak-services/DanakServicesContent.tsx
index a5afa76..8baaf50 100644
--- a/src/app/danak-services/DanakServicesContent.tsx
+++ b/src/app/danak-services/DanakServicesContent.tsx
@@ -12,7 +12,7 @@ const DanakServicesContent: FC = () => {
- ما در داناک با ترکیب خلاقیت، تخصص و تکنولوژیهای روز، راهکارهای نرمافزاری منحصربهفردی ارائه میدهیم که کسبوکار شما را به سطحی بالاتر میبرد.
+ داناک از ابتدای مسیر انتخاب تا استفاده از راهکارهای نرمافزاری در کنار شما خواهد بود.
diff --git a/src/app/developers/page.tsx b/src/app/developers/page.tsx
index ff1aac7..5b3ac27 100644
--- a/src/app/developers/page.tsx
+++ b/src/app/developers/page.tsx
@@ -12,7 +12,7 @@ const Developers: NextPage = () => {
-
+
چه در قالب فرد و یا شرکت ایده منحصر به فرد و خلاقانه ای دارید که نیاز به مشتری و گسترش بازار دارید؟
diff --git a/src/app/products/DetailService.tsx b/src/app/products/DetailService.tsx
index fd6031a..00da0af 100644
--- a/src/app/products/DetailService.tsx
+++ b/src/app/products/DetailService.tsx
@@ -110,40 +110,47 @@ const DetailService: FC<{ id: string }> = ({ id }) => {
{
- getDetailService.data?.data.danakService?.reviews?.map((item: ReviewItem) => {
- return (
-
-
-
-
- {item.user?.firstName + ' ' + item.user?.lastName}
-
-
-
-
-
- {item.title}
-
-
- {moment(item.createdAt).fromNow()}
-
-
-
-
-
-
-
-
- {item.comment}
-
+ getDetailService.data?.data.danakService?.reviews?.length === 0 ?
+
+
+ هیچ نظری ثبت نشده است
- )
- })
+
+ :
+ getDetailService.data?.data.danakService?.reviews?.map((item: ReviewItem) => {
+ return (
+
+
+
+
+ {item.user?.firstName + ' ' + item.user?.lastName}
+
+
+
+
+
+ {item.title}
+
+
+ {moment(item.createdAt).fromNow()}
+
+
+
+
+
+
+
+
+ {item.comment}
+
+
+ )
+ })
}
diff --git a/src/app/products/components/ServiceHeader.tsx b/src/app/products/components/ServiceHeader.tsx
index 1b7dc9c..5fd82a6 100644
--- a/src/app/products/components/ServiceHeader.tsx
+++ b/src/app/products/components/ServiceHeader.tsx
@@ -8,7 +8,7 @@ import Link from 'next/link'
import { DanakService } from '../types/ProductTypes'
import RadioGroup from '@/components/RadioGroup'
import Image from 'next/image'
-
+import { CONSOLE_URL } from '@/config/const'
type Props = {
data: DanakService,
}
@@ -25,8 +25,8 @@ const ServiceHeader: FC
= (props: Props) => {
const plan: any = data?.subscriptionPlans.find((item) => item.id === planSelected)
- setFinalPrice(plan.finalPrice)
- setPrice(plan?.price)
+ setFinalPrice(plan.price)
+ setPrice(plan?.originalPrice)
}, [data?.subscriptionPlans, planSelected])
@@ -82,11 +82,11 @@ const ServiceHeader: FC = (props: Props) => {
{NumberFormat(Number(price))}
}
- {NumberFormat(Number(price))}
+ {NumberFormat(Number(finalPrice))}
تومان
-
+
= ({ title, content }) => {
+ const [isOpen, setIsOpen] = useState(false)
+ const contentRef = useRef(null)
+ const [contentHeight, setContentHeight] = useState(0)
+
+ useEffect(() => {
+ if (contentRef.current) {
+ setContentHeight(isOpen ? contentRef.current.scrollHeight : 0)
+ }
+ }, [isOpen])
+
+ return (
+
+
setIsOpen(!isOpen)}>
+
+ {title}
+
+
+
+
+
+
+ )
+}
+
+export default Accordion
\ No newline at end of file
diff --git a/src/components/Input.tsx b/src/components/Input.tsx
index e067e55..0cb96d5 100644
--- a/src/components/Input.tsx
+++ b/src/components/Input.tsx
@@ -33,7 +33,7 @@ const Input: FC = (props: Props) => {
const [search, setSearch] = useState('')
const inputClass = clx(
- 'w-full h-10 text-black block px-4 text-xs rounded-xl border border-border',
+ 'w-full h-10 text-black block px-4 text-xs rounded-xl border border-[#D0D0D0]',
props.readOnly && 'bg-gray-100 border-0 text-description',
props.variant === 'search' && 'bg-[#EEF0F7] border-0 ps-10',
props.className
@@ -80,7 +80,7 @@ const Input: FC = (props: Props) => {
return (
-
+
{props.label}
diff --git a/src/components/Textarea.tsx b/src/components/Textarea.tsx
index 2872f79..e136fab 100644
--- a/src/components/Textarea.tsx
+++ b/src/components/Textarea.tsx
@@ -12,7 +12,7 @@ const Textarea: FC = (props: Props) => {
{
props.label &&
-
+
{props.label}
}
@@ -20,7 +20,7 @@ const Textarea: FC
= (props: Props) => {