diff --git a/package.json b/package.json index 6582db5..dcf73ce 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,13 @@ "@tanstack/react-query": "^5.29.2", "antd": "^5.16.1", "axios": "^1.6.8", + "chart.js": "^4.4.2", + "dayjs": "^1.11.11", "dotenv": "^16.4.5", "i18next": "^23.10.1", "js-cookie": "^3.0.5", "react": "^18.2.0", + "react-chartjs-2": "^5.2.0", "react-cookie": "^7.1.4", "react-dom": "^18.2.0", "react-redux": "^9.1.2", diff --git a/src/entities/dashboard/bar-chart/bar-chart.ts b/src/entities/dashboard/bar-chart/bar-chart.ts new file mode 100644 index 0000000..e2ab56a --- /dev/null +++ b/src/entities/dashboard/bar-chart/bar-chart.ts @@ -0,0 +1,40 @@ +import { useNotify } from 'app/providers/app' +import { useEffect } from 'react' +import { getAxiosInstance } from 'shared/api/api-query/api-query' +import { useAppSelector } from 'shared/redux/store' + +export const useBarChart = () => { + const { openNotification } = useNotify() + const dateType = useAppSelector((state) => state.dashboard.typeDate) + const { start, end } = useAppSelector((state) => state.dashboard.selectedDates) + const posts = useAppSelector((state) => state.dashboard.posts) + + const fetchData = async () => { + try { + const axiosInstance = await getAxiosInstance() + const res = await axiosInstance.get('/payments/pie-posts', { + params: { dateType: dateType, start: start, end: end, posts: posts }, + }) + console.log(res.data) + } catch (error) { + openNotification('Произошла ошибка при загрузке данных о платежах') + } + } + + useEffect(() => { + fetchData() + }, [dateType, start, end, posts]) + + const bar = { + labels: ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'], + datasets: [ + { + label: 'Общая сумма', + data: [12, 19, 3, 5, 2, 3, 7], + backgroundColor: 'rgb(110, 189, 116)', + }, + ], + } + + return { bar } +} diff --git a/src/entities/dashboard/bar-chart/index.ts b/src/entities/dashboard/bar-chart/index.ts new file mode 100644 index 0000000..29b2c22 --- /dev/null +++ b/src/entities/dashboard/bar-chart/index.ts @@ -0,0 +1,3 @@ +import { useBarChart } from 'entities/dashboard/bar-chart/bar-chart' + +export { useBarChart } diff --git a/src/entities/dashboard/payment-data/payment-data.ts b/src/entities/dashboard/payment-data/payment-data.ts index 2ff0ee7..7819151 100644 --- a/src/entities/dashboard/payment-data/payment-data.ts +++ b/src/entities/dashboard/payment-data/payment-data.ts @@ -4,7 +4,7 @@ import { IColumnPayments } from 'entities/dashboard/payment-data/model/interface import { IPostsResponse } from 'entities/settings/posts-table/model/interface' import { useEffect, useState } from 'react' import { getAxiosInstance } from 'shared/api/api-query/api-query' -import { setPaymentsState } from 'shared/redux/dashboard/dashboard-slice' +import { setPaymentsPostsData, setPaymentsState } from 'shared/redux/dashboard/dashboard-slice' import { useAppDispatch } from 'shared/redux/store' export const usePaymentData = () => { @@ -21,6 +21,7 @@ export const usePaymentData = () => { label: item.name, })) setPostSelect(select) + dispatch(setPaymentsPostsData(select)) } catch (error) { openNotification('Произошла ошибка при загрузке данных о пользователях') } diff --git a/src/entities/dashboard/pie-chart/index.ts b/src/entities/dashboard/pie-chart/index.ts new file mode 100644 index 0000000..0fd5958 --- /dev/null +++ b/src/entities/dashboard/pie-chart/index.ts @@ -0,0 +1,3 @@ +import { usePieChart } from 'entities/dashboard/pie-chart/pie-chart' + +export { usePieChart } diff --git a/src/entities/dashboard/pie-chart/pie-chart.ts b/src/entities/dashboard/pie-chart/pie-chart.ts new file mode 100644 index 0000000..ebc3317 --- /dev/null +++ b/src/entities/dashboard/pie-chart/pie-chart.ts @@ -0,0 +1,39 @@ +import { useNotify } from 'app/providers/app' +import { useEffect } from 'react' +import { getAxiosInstance } from 'shared/api/api-query/api-query' +import { useAppSelector } from 'shared/redux/store' + +export const usePieChart = () => { + const { openNotification } = useNotify() + const dateType = useAppSelector((state) => state.dashboard.typeDate) + const { start, end } = useAppSelector((state) => state.dashboard.selectedDates) + const posts = useAppSelector((state) => state.dashboard.posts) + + const fetchData = async () => { + try { + const axiosInstance = await getAxiosInstance() + const res = await axiosInstance.get('/payments/pie-type', { + params: { dateType: dateType, start: start, end: end, posts: posts }, + }) + console.log(res.data) + } catch (error) { + openNotification('Произошла ошибка при загрузке данных о платежах') + } + } + + useEffect(() => { + fetchData() + }, [dateType, start, end, posts]) + + const pie = { + labels: ['Наличные', 'Каспи'], + datasets: [ + { + data: [60, 40], + backgroundColor: ['rgb(110, 189, 116)', 'rgba(218,18,18,0.8)'], + }, + ], + } + + return { pie } +} diff --git a/src/entities/dashboard/table-data/table-data.ts b/src/entities/dashboard/table-data/table-data.ts index ca11cb0..4143411 100644 --- a/src/entities/dashboard/table-data/table-data.ts +++ b/src/entities/dashboard/table-data/table-data.ts @@ -19,7 +19,7 @@ export const useTableData = () => { setPaymentTableSum((prevState) => prevState + transformPrice(row.sum)) return { key: row.id, - date: unixDate(row.date * 1000, 'DMYHM'), + date: row.date ? unixDate(row.date * 1000, 'DMYHM') : '', post: row.device.name, sum: transformPrice(row.sum), } diff --git a/src/pages/dashboard/dashboard.tsx b/src/pages/dashboard/dashboard.tsx index 120a821..3aa5795 100644 --- a/src/pages/dashboard/dashboard.tsx +++ b/src/pages/dashboard/dashboard.tsx @@ -1,6 +1,8 @@ -import { Select, Table } from 'antd' import { usePaymentData } from 'entities/dashboard/payment-data' import { useTableData } from 'entities/dashboard/table-data' +import { DashboardCharts } from 'pages/dashboard/ui/dashboard-charts' +import { DashboardFilters } from 'pages/dashboard/ui/dashboard-filters' +import { DashboardPayment } from 'pages/dashboard/ui/dashboard-payment' import React, { FC } from 'react' export const Dashboard: FC = () => { @@ -9,46 +11,16 @@ export const Dashboard: FC = () => { return ( <> -
-
-
Посты
- { - fetchData() - }} - /> -
-
+ - -
- {'Итого: ' + paymentTableSum} -
) } diff --git a/src/pages/dashboard/ui/dashboard-charts/dashboard-charts.tsx b/src/pages/dashboard/ui/dashboard-charts/dashboard-charts.tsx new file mode 100644 index 0000000..1caa6d0 --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-charts/dashboard-charts.tsx @@ -0,0 +1,68 @@ +import { + ArcElement, + BarElement, + CategoryScale, + Chart as ChartJS, + Legend, + LinearScale, + Tooltip, +} from 'chart.js' +import { useBarChart } from 'entities/dashboard/bar-chart' +import { usePieChart } from 'entities/dashboard/pie-chart' +import { FC } from 'react' +import { Bar, Pie } from 'react-chartjs-2' +import { useMediaQuery } from 'react-responsive' +import { useAppSelector } from 'shared/redux/store' +import { PostCard } from 'shared/ui/post-card' + +ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement) + +export const DashboardCharts: FC = () => { + const isMobile = useMediaQuery({ query: '(max-width: 768px )' }) + const { pie } = usePieChart() + const { bar } = useBarChart() + const posts: { label: string; value: number }[] = useAppSelector( + (state) => state.dashboard.postsData, + ) + + return ( + <> +
+
+ +
+ +
+ +
+
+ +
+ {posts.map((item) => ( + + ))} +
+ + ) +} diff --git a/src/pages/dashboard/ui/dashboard-charts/index.ts b/src/pages/dashboard/ui/dashboard-charts/index.ts new file mode 100644 index 0000000..84b0e5c --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-charts/index.ts @@ -0,0 +1,3 @@ +import { DashboardCharts } from 'pages/dashboard/ui/dashboard-charts/dashboard-charts' + +export { DashboardCharts } diff --git a/src/pages/dashboard/ui/dashboard-filters/dashboard-filters.tsx b/src/pages/dashboard/ui/dashboard-filters/dashboard-filters.tsx new file mode 100644 index 0000000..6b36f34 --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-filters/dashboard-filters.tsx @@ -0,0 +1,68 @@ +import { DatePicker, Select } from 'antd' +import { IDashboardProps } from 'pages/dashboard/ui/dashboard-filters/model/interface' +import React, { FC } from 'react' +import { useMediaQuery } from 'react-responsive' +import { dateFilter } from 'shared/lib/constants' +import { + setPaymentsPost, + setPaymentsSelectedDates, + setPaymentsTypeDate, +} from 'shared/redux/dashboard/dashboard-slice' +import { useAppDispatch, useAppSelector } from 'shared/redux/store' + +export const DashboardFilters: FC = ({ refetch, options }) => { + const isMobile = useMediaQuery({ query: '(max-width: 768px )' }) + const dispatch = useAppDispatch() + const type = useAppSelector((state) => state.dashboard.typeDate) + + return ( +
+
+
Посты
+ { + if (value === 6) + dispatch(setPaymentsSelectedDates({ start: undefined, end: undefined })) + + dispatch(setPaymentsTypeDate(value)) + refetch() + }} + /> + {type === 6 && ( + { + dispatch( + setPaymentsSelectedDates({ start: date?.[0]?.toDate(), end: date?.[1]?.toDate() }), + ) + }} + /> + )} +
+
+ ) +} diff --git a/src/pages/dashboard/ui/dashboard-filters/index.ts b/src/pages/dashboard/ui/dashboard-filters/index.ts new file mode 100644 index 0000000..423654b --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-filters/index.ts @@ -0,0 +1,3 @@ +import { DashboardFilters } from 'pages/dashboard/ui/dashboard-filters/dashboard-filters' + +export { DashboardFilters } diff --git a/src/pages/dashboard/ui/dashboard-filters/model/interface.ts b/src/pages/dashboard/ui/dashboard-filters/model/interface.ts new file mode 100644 index 0000000..a820397 --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-filters/model/interface.ts @@ -0,0 +1,4 @@ +export interface IDashboardProps { + refetch: () => void + options: { label: string; value: number }[] +} diff --git a/src/pages/dashboard/ui/dashboard-payment/dashboard-payment.tsx b/src/pages/dashboard/ui/dashboard-payment/dashboard-payment.tsx new file mode 100644 index 0000000..f1fa3cc --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-payment/dashboard-payment.tsx @@ -0,0 +1,23 @@ +import { Table } from 'antd' +import { IDashboardPaymentProps } from 'pages/dashboard/ui/dashboard-payment/model/interface' +import React, { FC } from 'react' + +export const DashboardPayment: FC = ({ total, sum, columns, rows }) => { + return ( + <> +
+
+ {'Итого: ' + sum} +
+ + ) +} diff --git a/src/pages/dashboard/ui/dashboard-payment/index.ts b/src/pages/dashboard/ui/dashboard-payment/index.ts new file mode 100644 index 0000000..c85f126 --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-payment/index.ts @@ -0,0 +1,3 @@ +import { DashboardPayment } from 'pages/dashboard/ui/dashboard-payment/dashboard-payment' + +export { DashboardPayment } diff --git a/src/pages/dashboard/ui/dashboard-payment/model/interface.ts b/src/pages/dashboard/ui/dashboard-payment/model/interface.ts new file mode 100644 index 0000000..c057dd8 --- /dev/null +++ b/src/pages/dashboard/ui/dashboard-payment/model/interface.ts @@ -0,0 +1,10 @@ +import { ColumnsType } from 'antd/es/table' +import { IColumnPayments } from 'entities/dashboard/payment-data/model/interface' +import { ITablePaymentsState } from 'entities/dashboard/table-data/model/interface' + +export interface IDashboardPaymentProps { + total: number + sum: number + rows: ITablePaymentsState[] + columns: ColumnsType +} diff --git a/src/shared/lib/constants/index.ts b/src/shared/lib/constants/index.ts new file mode 100644 index 0000000..e4f7ccc --- /dev/null +++ b/src/shared/lib/constants/index.ts @@ -0,0 +1,9 @@ +export const dateFilter = [ + { label: 'За все время', value: 0 }, + { label: 'Сегодня', value: 1 }, + { label: 'Вчера', value: 2 }, + { label: 'Эта неделя', value: 3 }, + { label: 'Этот месяц', value: 4 }, + { label: 'Прошлая неделя', value: 5 }, + { label: 'Выбрать даты', value: 6 }, +] diff --git a/src/shared/redux/dashboard/dashboard-slice.ts b/src/shared/redux/dashboard/dashboard-slice.ts index 3c15397..483fed6 100644 --- a/src/shared/redux/dashboard/dashboard-slice.ts +++ b/src/shared/redux/dashboard/dashboard-slice.ts @@ -2,6 +2,10 @@ import { createSlice } from '@reduxjs/toolkit' const initialState = { payments: { items: [], totals: { count: 0 } }, + posts: undefined, + typeDate: 1, + selectedDates: { start: undefined, end: undefined }, + postsData: [], } export const DashboardSlice = createSlice({ @@ -11,9 +15,27 @@ export const DashboardSlice = createSlice({ setPaymentsState: (state, action) => { state.payments = action.payload }, + setPaymentsPost: (state, action) => { + state.posts = action.payload + }, + setPaymentsTypeDate: (state, action) => { + state.typeDate = action.payload + }, + setPaymentsSelectedDates: (state, action) => { + state.selectedDates = action.payload + }, + setPaymentsPostsData: (state, action) => { + state.postsData = action.payload + }, }, }) -export const { setPaymentsState } = DashboardSlice.actions +export const { + setPaymentsState, + setPaymentsPost, + setPaymentsPostsData, + setPaymentsSelectedDates, + setPaymentsTypeDate, +} = DashboardSlice.actions export default DashboardSlice.reducer diff --git a/src/shared/ui/post-card/index.ts b/src/shared/ui/post-card/index.ts new file mode 100644 index 0000000..e598f0a --- /dev/null +++ b/src/shared/ui/post-card/index.ts @@ -0,0 +1,3 @@ +import { PostCard } from 'shared/ui/post-card/post-card' + +export { PostCard } diff --git a/src/shared/ui/post-card/model/interface.ts b/src/shared/ui/post-card/model/interface.ts new file mode 100644 index 0000000..2b7548c --- /dev/null +++ b/src/shared/ui/post-card/model/interface.ts @@ -0,0 +1,4 @@ +export interface IPostCardProps { + name: string + value: number +} diff --git a/src/shared/ui/post-card/post-card.tsx b/src/shared/ui/post-card/post-card.tsx new file mode 100644 index 0000000..b7f1286 --- /dev/null +++ b/src/shared/ui/post-card/post-card.tsx @@ -0,0 +1,26 @@ +import { FC } from 'react' +import { IPostCardProps } from 'shared/ui/post-card/model/interface' + +export const PostCard: FC = ({ name, value }) => { + return ( +
+
{name}
+
{value}
+
+ ) +}