diff --git a/src/apis/APIDashboard.js b/src/apis/APIDashboard.js index a76568ca..5fce8e14 100644 --- a/src/apis/APIDashboard.js +++ b/src/apis/APIDashboard.js @@ -32,4 +32,31 @@ export const APIDashboard = { } }, + getDashboardIncome: async () => { + try { + const response = await axiosInstance.get("/doctors/dashboard/graph"); + return response.data; + } catch (error) { + if (error instanceof AxiosError) { + const { message } = error; + throw new AxiosError(message); + } + throw new Error(error); + } + }, + + getCountDataForOneDay: async () => { + try { + const result = await axiosInstance.get( + "/doctors/dashboard/data-count-one-day", + ); + return result.data; + } catch (err) { + if (err instanceof AxiosError) { + const { message } = err; + throw new AxiosError(message); + } + throw new Error(err); + } + }, }; diff --git a/src/components/layout-components/Footer.jsx b/src/components/layout-components/Footer.jsx index b57c7c17..98e5e5a0 100644 --- a/src/components/layout-components/Footer.jsx +++ b/src/components/layout-components/Footer.jsx @@ -3,7 +3,7 @@ import { Link } from "react-router-dom"; import { FaFacebookF, FaTwitter, FaYoutube } from "react-icons/fa"; import { AiFillInstagram } from "react-icons/ai"; -import Logo from "@/assets/logo-white.png"; +import logo from "@/assets/logo-white.png"; export function Footer() { return ( @@ -16,7 +16,7 @@ export function Footer() {
- +

Sosial Media

diff --git a/src/components/layout-components/Topbar.jsx b/src/components/layout-components/Topbar.jsx index 871fc855..2b379bf7 100644 --- a/src/components/layout-components/Topbar.jsx +++ b/src/components/layout-components/Topbar.jsx @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from "react-redux"; import { Flex, Skeleton } from "antd"; import { DrawerSidebar } from "@/components/layout-components/DrawerSidebar"; -import BlankProfile from "@/assets/blank-profile.png"; +import anonymousPict from "@/assets/anonymous-pp.jpg"; import logoReproHealth from "@/assets/logo-reprohealth.png"; import { fetchGetDoctorProfile, @@ -63,7 +63,7 @@ export default function Topbar() { {stateDataDoctor.status === "success" && ( profile-doctor diff --git a/src/components/shared-components/BannerDownload.jsx b/src/components/shared-components/BannerDownload.jsx index e120f4b2..de5f7d30 100644 --- a/src/components/shared-components/BannerDownload.jsx +++ b/src/components/shared-components/BannerDownload.jsx @@ -3,7 +3,7 @@ import { Row, Col } from "antd"; import { ButtonGooglePlay } from "@/components/shared-components/ButtonGooglePlay"; import { ButtonAppStore } from "@/components/shared-components/ButtonAppStore"; -import HandPhone from "@/assets/handphone-2.png"; +import handPhone from "@/assets/handphone-2.png"; export function BannerDownload() { return ( @@ -14,7 +14,7 @@ export function BannerDownload() { > - handphone + handphone @@ -40,7 +40,7 @@ export function BannerDownload() { - handphone + handphone
diff --git a/src/views/app-views/appointment/components/CardAppointment.jsx b/src/views/app-views/appointment/components/CardAppointment.jsx index 91608731..8a881aff 100644 --- a/src/views/app-views/appointment/components/CardAppointment.jsx +++ b/src/views/app-views/appointment/components/CardAppointment.jsx @@ -1,5 +1,5 @@ -import Icon01 from "@/assets/db-icon-01.png"; -import Icon02 from "@/assets/db-icon-02.png"; +import icon01 from "@/assets/db-icon-01.png"; +import icon02 from "@/assets/db-icon-02.png"; import { Card, Col, Flex, Row } from "antd"; export function CardAppointment({ data }) { @@ -24,7 +24,7 @@ export function CardAppointment({ data }) {
- item-icon + item-icon
@@ -43,7 +43,7 @@ export function CardAppointment({ data }) {
- item-icon + item-icon
diff --git a/src/views/app-views/appointment/components/DetailPatient.jsx b/src/views/app-views/appointment/components/DetailPatient.jsx index 948dba3f..2d6ded49 100644 --- a/src/views/app-views/appointment/components/DetailPatient.jsx +++ b/src/views/app-views/appointment/components/DetailPatient.jsx @@ -14,6 +14,8 @@ import { toggleFetchLatestData, } from "@/store/toggle-fetch-new-data"; +import anonymousPict from "@/assets/anonymous-pp.jpg"; + export function DetailPatient({ idAppointment, handleOpen, isOpen }) { return ( <> @@ -95,7 +97,7 @@ const CardDetailPatient = ({ dataPasien, isError }) => { > pasien diff --git a/src/views/app-views/chatbot/index.jsx b/src/views/app-views/chatbot/index.jsx index 69faed62..ceb2d142 100644 --- a/src/views/app-views/chatbot/index.jsx +++ b/src/views/app-views/chatbot/index.jsx @@ -3,8 +3,8 @@ import { useState, useRef, useEffect } from "react"; import { LuSendHorizonal } from "react-icons/lu"; import { useForm } from "react-hook-form"; -import ChatbotIcon from "@/assets/chatbot-icon.svg"; -import ChatbotMascot from "@/assets/chatbot-mascot.svg"; +import chatbotIcon from "@/assets/chatbot-icon.svg"; +import chatbotMascot from "@/assets/chatbot-mascot.svg"; import profileDoctor from "@/assets/profile-doctor.svg"; import { useDocumentTitle } from "@/hooks/useDocumentTitle"; @@ -103,7 +103,7 @@ export default function Chatbot() {
- +
Asisten Dokter

@@ -115,7 +115,7 @@ export default function Chatbot() {

{selectedList[0]?.pesan.length === 0 ? (
- +

Selamat datang di Asisten Dokter! Saya adalah AI Bot yang siap membantu Anda menjelajahi topik Kesehatan Reproduksi. @@ -144,7 +144,7 @@ export default function Chatbot() { src={ pesan.pengirim === "user" ? profileDoctor - : ChatbotIcon + : chatbotIcon } className="hidden h-8 w-8 min-[500px]:block" alt="chatbot icon" diff --git a/src/views/app-views/dashboard/components/ChartIncome.jsx b/src/views/app-views/dashboard/components/ChartIncome.jsx index 6c5b24fe..17826794 100644 --- a/src/views/app-views/dashboard/components/ChartIncome.jsx +++ b/src/views/app-views/dashboard/components/ChartIncome.jsx @@ -1,3 +1,8 @@ +import dayjs from "dayjs"; +import "dayjs/locale/id"; + +dayjs.locale("id"); + import { Card, Col, Row } from "antd"; import { BarChart, @@ -10,11 +15,16 @@ import { Legend, } from "recharts"; -import { - DataIncome, - DataIncomeDay, - DataIncomeWeek, -} from "@/views/app-views/dashboard/constant/graph-income"; +import // DataIncome, +// DataIncomeDay, +// DataIncomeWeek, +// formatDateToStringDay, +// formatDateToStringWeek, +// formatDateToStringMonth, +"@/views/app-views/dashboard/constant/graph-income"; +import { useEffect, useState } from "react"; + +import { APIDashboard } from "@/apis/APIDashboard"; export function CustomTooltip({ active, payload, label }) { if (active && payload && payload.length) { @@ -38,15 +48,81 @@ export function CustomTooltip({ active, payload, label }) { } export function ChartIncome({ selectedFilter }) { - const IncomeMonth = DataIncome.slice(DataIncome.length - 7); - // const IncomeWeeks = DataIncomeWeek.slice(DataIncomeWeek.length - 7); - const IncomeWeeks = DataIncomeWeek; - const IncomeDays = DataIncomeDay.slice(DataIncomeDay.length - 7); + const [dataIncome, setDataIncome] = useState([]); + // const [isError, setIsError] = useState(null); + const today = dayjs(); const mobileSize = window.innerWidth <= 450; - console.log("week", IncomeWeeks); - console.log("month", IncomeMonth); - console.log("days", IncomeDays); + useEffect(() => { + const fecthDataIncome = async () => { + try { + const result = await APIDashboard.getDashboardIncome(); + console.log("data income", result); + + setDataIncome(result?.response); + } catch (error) { + console.error(error); + // setIsError(error); + } + }; + + fecthDataIncome(); + }, []); + + const filterAndAggregateData = (startDate, endDate) => { + const filteredData = dataIncome.filter( + (data) => dayjs(data.date) >= startDate && dayjs(data.date) <= endDate, + ); + + const sortedData = filteredData.sort( + (a, b) => dayjs(a.date).toDate() - dayjs(b.date).toDate(), + ); + + const aggregatedData = sortedData.reduce((acc, data) => { + // const date = dayjs(data.date).format("dddd, DD MMMM YYYY"); + let formattedDate = ""; + + if (selectedFilter === "hari") { + formattedDate = dayjs(data.date).format("dddd, DD MMMM YYYY"); + } + if (selectedFilter === "minggu") { + const value = dayjs(data.date); + const startOfWeek = value.startOf("week"); + const endOfWeek = value.endOf("week"); + + formattedDate = `Week ${value.week()}, ${startOfWeek.format( + "DD", + )} - ${endOfWeek.format("DD MMMM YYYY")}`; + } + if (selectedFilter === "bulan") { + formattedDate = dayjs(data.date).format("MMMM YYYY"); + } + + acc[formattedDate] = (acc[formattedDate] || 0) + parseFloat(data.income); + return acc; + }, {}); + + return Object.entries(aggregatedData).map(([date, income]) => ({ + date, + income, + })); + }; + + let chartData = []; + + switch (selectedFilter) { + case "hari": + chartData = filterAndAggregateData(today.subtract(7, "days"), today); + break; + case "minggu": + chartData = filterAndAggregateData(today.subtract(7, "weeks"), today); + break; + case "bulan": + chartData = filterAndAggregateData(today.subtract(7, "months"), today); + break; + default: + break; + } // const customTickYAxis = (values) => `${values.toString().slice(0, 2)} jt`; const customTickYAxis = (values) => { @@ -97,13 +173,15 @@ export function ChartIncome({ selectedFilter }) { diff --git a/src/views/app-views/dashboard/components/TotalCards.jsx b/src/views/app-views/dashboard/components/TotalCards.jsx index a2f7a06a..cf9f0c7b 100644 --- a/src/views/app-views/dashboard/components/TotalCards.jsx +++ b/src/views/app-views/dashboard/components/TotalCards.jsx @@ -2,13 +2,18 @@ import { Row, Col, Card, Skeleton, Flex } from "antd"; import { useEffect, useState } from "react"; import { APIDashboard } from "@/apis/APIDashboard"; -import Icon01 from "@/assets/db-icon-01.png"; -import Icon02 from "@/assets/db-icon-02.png"; -import Icon03 from "@/assets/db-icon-03.png"; -import Icon04 from "@/assets/db-icon-04.png"; +import icon01 from "@/assets/db-icon-01.png"; +import icon02 from "@/assets/db-icon-02.png"; +import icon03 from "@/assets/db-icon-03.png"; +import icon04 from "@/assets/db-icon-04.png"; export function TotalCards({ selectedFilter }) { - const [data, setData] = useState({}); + const [data, setData] = useState({ + totalConsultations: 0, + totalPatients: 0, + totalTransactions: 0, + totalArticles: 0, + }); const [isLoading, setIsLoading] = useState(false); useEffect(() => { @@ -21,7 +26,7 @@ export function TotalCards({ selectedFilter }) { } else if (selectedFilter === "minggu") { result = await APIDashboard.getCountDataForOneWeek(); } else if (selectedFilter === "hari") { - result = await APIDashboard.getCountDataForOneMonth(); + result = await APIDashboard.getCountDataForOneDay(); } setData(result); setIsLoading(false); @@ -36,9 +41,11 @@ export function TotalCards({ selectedFilter }) { const formatPrice = (num) => { if (num >= 1000000) { - return Math.floor(num / 1000000) + "M"; + return num / 1000000 + " M"; } else if (num >= 1000) { - return Math.floor(num / 1000) + "K"; + return num / 1000 + " K"; + } else { + return num; } }; @@ -54,25 +61,25 @@ export function TotalCards({ selectedFilter }) { { title: "Total Janji Temu", total: data.totalConsultations, - icon: `${Icon01}`, + icon: `${icon01}`, percent: formatPercentage(data.consultationPercentage), }, { title: "Total Pasien", total: data.totalPatients, - icon: `${Icon02}`, + icon: `${icon02}`, percent: formatPercentage(data.patientPercentage), }, { title: "Total Pendapatan", total: formatPrice(data.totalTransactions), - icon: `${Icon03}`, + icon: `${icon03}`, percent: formatPercentage(data.transactionPercentage), }, { title: "Total Artikel", total: data.totalArticles, - icon: `${Icon04}`, + icon: `${icon04}`, percent: formatPercentage(data.articlePercentage), }, ]; diff --git a/src/views/app-views/dashboard/constant/graph-income/index.js b/src/views/app-views/dashboard/constant/graph-income/index.js index 215c3e26..ac1a08b7 100644 --- a/src/views/app-views/dashboard/constant/graph-income/index.js +++ b/src/views/app-views/dashboard/constant/graph-income/index.js @@ -3,7 +3,7 @@ import "dayjs/locale/id"; dayjs.locale("id"); -const PlainDataIncomeWeek = [ +export const PlainDataIncomeWeek = [ { date: "13-10-2023", income: 22865856, @@ -212,7 +212,7 @@ const PlainDataIncomeDay = [ income: 800000, }, { - date: "26-11-2023", + date: "30-11-2023", income: 2286585, }, { @@ -228,13 +228,17 @@ const PlainDataIncomeDay = [ income: 900000, }, { - date: "30-11-2023", + date: "26-11-2023", income: 464004, }, { date: "01-12-2023", income: 2286585, }, + { + date: "01-12-2023", + income: 500000, + }, ]; const PlainDataIncomeMonth = [ @@ -268,17 +272,17 @@ const PlainDataIncomeMonth = [ }, ]; -const formatDateToStringMonth = (date) => { +export const formatDateToStringMonth = (date) => { const value = dayjs(date, "DD-MM-YYYY"); return value.format("MMMM YYYY"); }; -const formatDateToStringDay = (date) => { +export const formatDateToStringDay = (date) => { const value = dayjs(date, "DD-MM-YYYY"); return value.format("dddd, DD MMMM YYYY"); }; -const formatDateToStringWeek = (date, separator = "-") => { +export const formatDateToStringWeek = (date, separator = "-") => { const value = dayjs(date, "DD-MM-YYYY"); // return `Week ${value.week()}, ${value.format("MMMM YYYY")}`; return `Week ${value.week()}, ${value.format("DD")} ${separator} ${value @@ -296,12 +300,9 @@ export const DataIncome = PlainDataIncomeMonth.map((value) => { return value; }); -export const DataIncomeDay = PlainDataIncomeDay.map((value) => { - value.date = formatDateToStringDay(value.date); - return value; -}); - const ProcessedDataIncomeWeek = []; +// const ProcessedDataIncomeDay = []; + // loop through each week in PlainDataIncomeWeek for (let i = 0; i < PlainDataIncomeWeek.length; i += 7) { // calculate total income for week @@ -317,10 +318,57 @@ for (let i = 0; i < PlainDataIncomeWeek.length; i += 7) { }); } +// Days +// for (let i = 0; i < PlainDataIncomeDay.length; i++) { +// const totalIncomeDay = PlainDataIncomeDay.slice(i, i + 1).reduce( +// (acc, current) => acc + current.income, +// 0, +// ); + +// ProcessedDataIncomeDay.push({ +// date: formatDateToStringDay(PlainDataIncomeDay[i].date), +// income: totalIncomeDay, +// }); +// } + +// export const DataIncomeDay = ProcessedDataIncomeDay; export const DataIncomeWeek = ProcessedDataIncomeWeek; +// console.log("data days accumulated", DataIncomeDay); console.log("datas:", DataIncomeWeek); +// export const DataIncomeDay = PlainDataIncomeDay.map((value) => { +// value.date = formatDateToStringDay(value.date); +// return value; +// }); + +const sortedData = PlainDataIncomeDay.sort((a, b) => { + const dateA = dayjs(a.date, "DD-MM-YYYY").toDate(); + const dateB = dayjs(b.date, "DD-MM-YYYY").toDate(); + return dateA - dateB; +}); + +const last7DaysData = sortedData.slice(-8); + +const incomeMap = {}; + +for (const data of last7DaysData) { + const date = dayjs(data.date, "DD-MM-YYYY"); + if (!incomeMap[date]) { + incomeMap[date] = 0; + } + incomeMap[date] += data.income; +} + +export const DataIncomeDay = Object.entries(incomeMap).map( + ([date, income]) => ({ + date: dayjs(date).format("dddd, DD MMMM YYYY"), + income, + }), +); + +console.log("after sorted", DataIncomeDay); + // dataset // export const DataIncome = [ // { diff --git a/src/views/app-views/forum/components/AllDiscussion.jsx b/src/views/app-views/forum/components/AllDiscussion.jsx index 943715de..25975a50 100644 --- a/src/views/app-views/forum/components/AllDiscussion.jsx +++ b/src/views/app-views/forum/components/AllDiscussion.jsx @@ -151,7 +151,10 @@ export function AllDiscussion() { {data.status && ( doctor profile )} diff --git a/src/views/app-views/forum/misc/DiscussionDetail.jsx b/src/views/app-views/forum/misc/DiscussionDetail.jsx index 93b34f1d..2444c5ef 100644 --- a/src/views/app-views/forum/misc/DiscussionDetail.jsx +++ b/src/views/app-views/forum/misc/DiscussionDetail.jsx @@ -108,7 +108,10 @@ export default function DiscussionDetail() {

patient profile
diff --git a/src/views/app-views/profile/components/DoctorProfile.jsx b/src/views/app-views/profile/components/DoctorProfile.jsx index 224124bd..510b053e 100644 --- a/src/views/app-views/profile/components/DoctorProfile.jsx +++ b/src/views/app-views/profile/components/DoctorProfile.jsx @@ -4,7 +4,7 @@ import { BiSolidErrorCircle } from "react-icons/bi"; import { selectDoctorProfile } from "@/store/get-doctor-profile-slice"; -import BlankProfile from "@/assets/blank-profile.png"; +import anonymousPict from "@/assets/anonymous-pp.jpg"; export function DoctorProfile() { const stateDataDoctor = useSelector(selectDoctorProfile); @@ -19,7 +19,7 @@ export function DoctorProfile() {
profile-doctor