diff --git a/.env b/.env
index 06ab540..3b15816 100644
--- a/.env
+++ b/.env
@@ -1,12 +1,12 @@
VITE_TOKEN_NAME = 'dsc_token'
VITE_REFRESH_TOKEN_NAME = 'dsc_refresh_token'
-# VITE_BASE_URL = 'http://192.168.1.113:4001'
-VITE_BASE_URL = 'https://api-dzone.danakcorp.com'
+VITE_BASE_URL = 'http://192.168.82.158:4000'
+# VITE_BASE_URL = 'https://api-dzone.danakcorp.com'
# VITE_DANAK_BASE_URL ='http://192.168.1.113:4000'
VITE_DANAK_BASE_URL ='https://api.danakcorp.com'
VITE_SERVICE_ID = '7e3c2f08-b7e7-4402-ae5f-fea99cff56bd'
VITE_WORKSPACE_ID = 'workspace_id'
-VITE_LOGIN_URL = 'https://console.danakcorp.com/auth/login'
-# VITE_LOGIN_URL = 'http://localhost:5174/auth/login'
+# VITE_LOGIN_URL = 'https://console.danakcorp.com/auth/login'
+VITE_LOGIN_URL = 'http://localhost:5174/auth/login'
VITE_DZONE_URL = 'https://dzone.danakcorp.com'
\ No newline at end of file
diff --git a/src/pages/company/Update.tsx b/src/pages/company/Update.tsx
index 83d27fb..d86837b 100644
--- a/src/pages/company/Update.tsx
+++ b/src/pages/company/Update.tsx
@@ -244,7 +244,7 @@ const UpdateCompany: FC = () => {
>
-
ثبت شرکت
+
بروزرسانی شرکت
diff --git a/src/pages/slider/Create.tsx b/src/pages/slider/Create.tsx
new file mode 100644
index 0000000..525c851
--- /dev/null
+++ b/src/pages/slider/Create.tsx
@@ -0,0 +1,140 @@
+import { useFormik } from 'formik'
+import { FC, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { CreateSliderType } from './types/SliderTypes'
+import * as Yup from 'yup'
+import Button from '../../components/Button'
+import { useCreateSlider } from './hooks/useSliderData'
+import { TickCircle } from 'iconsax-react'
+import Input from '../../components/Input'
+import Textarea from '../../components/Textarea'
+import UploadBox from '../../components/UploadBox'
+import SwitchComponent from '../../components/Switch'
+import { toast } from 'react-toastify'
+import { useSingleUpload } from '../service/hooks/useServiceData'
+import { Pages } from '../../config/Pages'
+import { useNavigate } from 'react-router-dom'
+import { ErrorType } from '../../helpers/types'
+const CreateSlider: FC = () => {
+
+ const navigate = useNavigate()
+ const { t } = useTranslation('global')
+ const createSlider = useCreateSlider()
+ const singleUpload = useSingleUpload()
+ const [file, setFile] = useState(null)
+ const formik = useFormik({
+ initialValues: {
+ title: '',
+ description: '',
+ imageUrl: '',
+ link: '',
+ order: 0,
+ isActive: true,
+ },
+ validationSchema: Yup.object({
+ title: Yup.string().required(t('errors.required')),
+ description: Yup.string().required(t('errors.required')),
+ link: Yup.string().required(t('errors.required')),
+ order: Yup.number().required(t('errors.required')),
+ }),
+ onSubmit: async (values) => {
+ if (!file) {
+ toast.error(t('slider.image_required'))
+ return
+ }
+
+ const formData = new FormData()
+ formData.append('file', file)
+ await singleUpload.mutateAsync(formData, {
+ onSuccess: (data) => {
+ values.imageUrl = data?.data?.url
+ }
+ })
+
+ values.order = +values.order
+
+ createSlider.mutate(values, {
+ onSuccess: () => {
+ navigate(Pages.sliders.list)
+ },
+ onError: (error: ErrorType) => {
+ toast.error(error.response?.data?.error.message[0])
+ }
+ })
+ }
+ })
+
+ return (
+
+
+
+ {t('slider.new_slider')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setFile(file[0])}
+ />
+
+
+
+
+
+
+
+ formik.setFieldValue('isActive', value)}
+ />
+
+
+
+
+
+ )
+}
+
+export default CreateSlider
\ No newline at end of file
diff --git a/src/pages/slider/List.tsx b/src/pages/slider/List.tsx
new file mode 100644
index 0000000..7de4faa
--- /dev/null
+++ b/src/pages/slider/List.tsx
@@ -0,0 +1,106 @@
+import { FC } from 'react'
+import { Link } from 'react-router-dom'
+import { Pages } from '../../config/Pages'
+import Button from '../../components/Button'
+import { Add, Edit } from 'iconsax-react'
+import { useTranslation } from 'react-i18next'
+import Td from '../../components/Td'
+import { useDeleteSlider, useGetSliders } from './hooks/useSliderData'
+import { SliderItemType } from './types/SliderTypes'
+import PageLoading from '../../components/PageLoading'
+import { toast } from 'react-toastify'
+import { ErrorType } from '../../helpers/types'
+import TrashWithConfrim from '../../components/TrashWithConfrim'
+const SliderList: FC = () => {
+
+ const { t } = useTranslation('global')
+ const { data: sliders, isPending, refetch } = useGetSliders()
+ const deleteSlider = useDeleteSlider()
+
+ const handleDelete = (id: string) => {
+ deleteSlider.mutate(id, {
+ onSuccess: () => {
+ toast.success(t('slider.slider_deleted'))
+ refetch()
+ },
+ onError: (error: ErrorType) => {
+ toast.error(error.response?.data?.error.message[0])
+ }
+ })
+ }
+
+ return (
+
+
+
+ {t('slider.list_slider')}
+
+
+
+
+
+
+
+
+ {
+ isPending ?
+
+ :
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+
+ {sliders?.data?.sliders?.map((item: SliderItemType) => (
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+ handleDelete(item.id)}
+ isLoading={deleteSlider.isPending}
+ />
+
+ |
+
+ ))}
+
+
+
+ }
+
+
+ )
+}
+
+export default SliderList
\ No newline at end of file
diff --git a/src/pages/slider/Update.tsx b/src/pages/slider/Update.tsx
new file mode 100644
index 0000000..b0ba21b
--- /dev/null
+++ b/src/pages/slider/Update.tsx
@@ -0,0 +1,148 @@
+import { useFormik } from 'formik'
+import { FC, useEffect, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { CreateSliderType } from './types/SliderTypes'
+import * as Yup from 'yup'
+import Button from '../../components/Button'
+import { useGetSliderDetail, useUpdateSlider } from './hooks/useSliderData'
+import { TickCircle } from 'iconsax-react'
+import Input from '../../components/Input'
+import Textarea from '../../components/Textarea'
+import UploadBox from '../../components/UploadBox'
+import SwitchComponent from '../../components/Switch'
+import { toast } from 'react-toastify'
+import { useSingleUpload } from '../service/hooks/useServiceData'
+import { Pages } from '../../config/Pages'
+import { useNavigate, useParams } from 'react-router-dom'
+import { ErrorType } from '../../helpers/types'
+const UpdateSlider: FC = () => {
+
+ const { id } = useParams()
+ const navigate = useNavigate()
+ const { t } = useTranslation('global')
+ const updateSlider = useUpdateSlider()
+ const singleUpload = useSingleUpload()
+ const { data: sliderDetail } = useGetSliderDetail(id || '')
+
+ const [file, setFile] = useState(null)
+ const formik = useFormik({
+ initialValues: {
+ title: '',
+ description: '',
+ imageUrl: '',
+ link: '',
+ order: 0,
+ isActive: true,
+ },
+ validationSchema: Yup.object({
+ title: Yup.string().required(t('errors.required')),
+ description: Yup.string().required(t('errors.required')),
+ link: Yup.string().required(t('errors.required')),
+ order: Yup.number().required(t('errors.required')),
+ }),
+ onSubmit: async (values) => {
+
+ if (file) {
+ const formData = new FormData()
+ formData.append('file', file)
+ await singleUpload.mutateAsync(formData, {
+ onSuccess: (data) => {
+ values.imageUrl = data?.data?.url
+ }
+ })
+ }
+
+ values.order = +values.order
+
+ updateSlider.mutate({ id: id || '', data: values }, {
+ onSuccess: () => {
+ navigate(Pages.sliders.list)
+ },
+ onError: (error: ErrorType) => {
+ toast.error(error.response?.data?.error.message[0])
+ }
+ })
+ }
+ })
+
+ useEffect(() => {
+ if (sliderDetail?.data?.slider) {
+ formik.setValues(sliderDetail?.data?.slider)
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [sliderDetail])
+
+ return (
+
+
+
+ {t('slider.new_slider')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setFile(file[0])}
+ />
+
+
+
+
+
+
+
+ formik.setFieldValue('isActive', value)}
+ />
+
+
+
+
+
+ )
+}
+
+export default UpdateSlider
\ No newline at end of file
diff --git a/src/pages/slider/hooks/useSliderData.ts b/src/pages/slider/hooks/useSliderData.ts
new file mode 100644
index 0000000..7886a79
--- /dev/null
+++ b/src/pages/slider/hooks/useSliderData.ts
@@ -0,0 +1,35 @@
+import { useMutation, useQuery } from "@tanstack/react-query";
+import * as api from "../service/SliderService";
+import { CreateSliderType } from "../types/SliderTypes";
+export const useCreateSlider = () => {
+ return useMutation({
+ mutationFn: api.createSlider,
+ });
+};
+
+export const useGetSliders = () => {
+ return useQuery({
+ queryKey: ["sliders"],
+ queryFn: api.getSliders,
+ });
+};
+
+export const useGetSliderDetail = (id: string) => {
+ return useQuery({
+ queryKey: ["slider-detail", id],
+ queryFn: () => api.getSliderDetail(id),
+ });
+};
+
+export const useUpdateSlider = () => {
+ return useMutation({
+ mutationFn: (params: { id: string; data: CreateSliderType }) =>
+ api.updateSlider(params.id, params.data),
+ });
+};
+
+export const useDeleteSlider = () => {
+ return useMutation({
+ mutationFn: (id: string) => api.deleteSlider(id),
+ });
+};
diff --git a/src/pages/slider/service/SliderService.ts b/src/pages/slider/service/SliderService.ts
new file mode 100644
index 0000000..82df7c6
--- /dev/null
+++ b/src/pages/slider/service/SliderService.ts
@@ -0,0 +1,27 @@
+import axios from "../../../config/axios";
+import { CreateSliderType } from "../types/SliderTypes";
+
+export const createSlider = async (params: CreateSliderType) => {
+ const { data } = await axios.post("/sliders", params);
+ return data;
+};
+
+export const getSliders = async () => {
+ const { data } = await axios.get("/sliders");
+ return data;
+};
+
+export const getSliderDetail = async (id: string) => {
+ const { data } = await axios.get(`/sliders/${id}`);
+ return data;
+};
+
+export const updateSlider = async (id: string, params: CreateSliderType) => {
+ const { data } = await axios.patch(`/sliders/${id}`, params);
+ return data;
+};
+
+export const deleteSlider = async (id: string) => {
+ const { data } = await axios.delete(`/sliders/${id}`);
+ return data;
+};
diff --git a/src/pages/slider/types/SliderTypes.ts b/src/pages/slider/types/SliderTypes.ts
new file mode 100644
index 0000000..b238fab
--- /dev/null
+++ b/src/pages/slider/types/SliderTypes.ts
@@ -0,0 +1,20 @@
+export type CreateSliderType = {
+ title: string;
+ description: string;
+ imageUrl: string;
+ link: string;
+ order: number;
+ isActive: boolean;
+};
+
+export type SliderItemType = {
+ createdAt: string;
+ description: string;
+ id: string;
+ imageUrl: string;
+ isActive: boolean;
+ link: string;
+ order: number;
+ title: string;
+ updatedAt: string;
+};
diff --git a/src/router/Main.tsx b/src/router/Main.tsx
index b43be51..1f6f23b 100644
--- a/src/router/Main.tsx
+++ b/src/router/Main.tsx
@@ -52,6 +52,9 @@ import CompanyList from '../pages/company/List'
import UpdateCompany from '../pages/company/Update'
import RequestsList from '../pages/requests/List'
import RequestDetail from '../pages/requests/Detail'
+import SliderList from '../pages/slider/List'
+import UpdateSlider from '../pages/slider/Update'
+import CreateSlider from '../pages/slider/Create'
const MainRouter: FC = () => {
const { hasSubMenu } = useSharedStore()
@@ -117,6 +120,9 @@ const MainRouter: FC = () => {
} />
} />
} />
+ } />
+ } />
+ } />
diff --git a/src/shared/SideBar.tsx b/src/shared/SideBar.tsx
index 8112362..e9f37fb 100644
--- a/src/shared/SideBar.tsx
+++ b/src/shared/SideBar.tsx
@@ -2,7 +2,7 @@ import { FC, Fragment, useEffect, useState } from 'react'
import LogoImage from '../assets/images/logo.svg'
import LogoSmall from '../assets/images/logo-small.svg'
import { useTranslation } from 'react-i18next'
-import { Building, DocumentText, Home2, Logout, Messages3, NoteAdd, NotificationStatus, Receipt21, Setting2 } from 'iconsax-react'
+import { Building, DocumentText, Gallery, Home2, Logout, Messages3, NoteAdd, NotificationStatus, Receipt21, Setting2 } from 'iconsax-react'
import SideBarItem from './SideBarItem'
import { useLocation } from 'react-router-dom'
import { Pages } from '../config/Pages'
@@ -149,6 +149,14 @@ const SideBar: FC = () => {
/>
+ }
+ title={t('sidebar.sliders')}
+ isActive={isActive('sliders')}
+ link={Pages.sliders.list}
+ activeName='sliders'
+ />
+
}