revamp template
This commit is contained in:
200
src/pages/dashboards/home/DashboardHomePage.tsx
Normal file
200
src/pages/dashboards/home/DashboardHomePage.tsx
Normal file
@ -0,0 +1,200 @@
|
||||
import { Container, KeenIcon, DefaultTooltip } from '@/components';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue
|
||||
} from '@/components/ui/select';
|
||||
import { DateRange } from 'react-day-picker';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { Card, Chart, YearPicker } from './blocks';
|
||||
import moment from 'moment';
|
||||
import { useFetchCardData, useFetchChartData } from './hooks';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useFetchYear } from './hooks/useFetchYear';
|
||||
import { get5LastYear } from '@/utils/Date';
|
||||
// sum -> nominal, count-> total
|
||||
type CountType = 'sum' | 'count';
|
||||
type ChartType = 'line' | 'bar';
|
||||
type ChartLegend = 'true' | 'false';
|
||||
|
||||
const DashboardHomePage = () => {
|
||||
const selectYear = get5LastYear();
|
||||
const [initialYear, setInitialYear] = useState<string>('');
|
||||
const [selectedYear, setSelectedYear] = useState<string>('');
|
||||
const [count, setCount] = useState<CountType>('sum');
|
||||
const [chartType, setChartType] = useState<ChartType>('line');
|
||||
const [chartLegend, setChartLegend] = useState<ChartLegend>('true');
|
||||
const [dateRange, setDateRange] = useState<{ from: Date; to: Date }>({
|
||||
from: new Date(),
|
||||
to: new Date()
|
||||
});
|
||||
|
||||
// Menyusun tanggal awal dan akhir berdasarkan selectedYear
|
||||
useEffect(() => {
|
||||
if (selectYear.length > 0 && !selectedYear) {
|
||||
let latestYear = Math.max(...selectYear.map((item) => parseInt(item, 10))).toString();
|
||||
console.log('latestYear :', latestYear);
|
||||
setSelectedYear(latestYear);
|
||||
setInitialYear(latestYear);
|
||||
}
|
||||
}, [selectYear, selectedYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedYear) {
|
||||
setDateRange({
|
||||
from: moment(`${selectedYear}-01-01`, 'YYYY-MM-DD').toDate(),
|
||||
to: moment(`${selectedYear}-12-31`, 'YYYY-MM-DD').toDate()
|
||||
});
|
||||
}
|
||||
}, [selectedYear]);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialYear) {
|
||||
setDateRange({
|
||||
from: moment(`${initialYear}-01-01`, 'YYYY-MM-DD').toDate(),
|
||||
to: moment(`${initialYear}-12-31`, 'YYYY-MM-DD').toDate()
|
||||
});
|
||||
}
|
||||
}, [initialYear]);
|
||||
|
||||
const handleYearChange = (year: string) => {
|
||||
setSelectedYear(year);
|
||||
};
|
||||
|
||||
const handleCountType = (value: CountType) => {
|
||||
setCount(value);
|
||||
};
|
||||
|
||||
const handleChartType = (value: ChartType) => {
|
||||
setChartType(value);
|
||||
};
|
||||
|
||||
const handleChartLegend = (value: ChartLegend) => {
|
||||
setChartLegend(value);
|
||||
};
|
||||
|
||||
// const handleFilter = useCallback(
|
||||
// (date: DateRange | undefined) => {
|
||||
// setDateRange({
|
||||
// from: date?.from ?? moment(`${selectedYear}-01-01`, 'YYYY-MM-DD').toDate(),
|
||||
// to: date?.to ?? moment(`${selectedYear}-12-31`, 'YYYY-MM-DD').toDate()
|
||||
// });
|
||||
// },
|
||||
// [selectedYear]
|
||||
// );
|
||||
|
||||
const resetFilter = useCallback(() => {
|
||||
setDateRange({
|
||||
from: moment(`${initialYear}-01-01`, 'YYYY-MM-DD').toDate(),
|
||||
to: moment(`${initialYear}-12-31`, 'YYYY-MM-DD').toDate()
|
||||
});
|
||||
setSelectedYear(initialYear);
|
||||
setCount('sum');
|
||||
setChartType('line');
|
||||
setChartLegend('true');
|
||||
}, [initialYear]);
|
||||
|
||||
const { cardData } = useFetchCardData(
|
||||
moment(dateRange.from).format('YYYY-MM-DD'),
|
||||
moment(dateRange.to).format('YYYY-MM-DD'),
|
||||
count
|
||||
);
|
||||
|
||||
const { chartData } = useFetchChartData(
|
||||
moment(dateRange.from).format('YYYY-MM-DD'),
|
||||
moment(dateRange.to).format('YYYY-MM-DD'),
|
||||
count
|
||||
);
|
||||
|
||||
const toolbar = (
|
||||
<div className="flex gap-3 items-center w-1/2">
|
||||
<div className="w-auto min-w-[120px]">
|
||||
<Select value={chartType} onValueChange={handleChartType}>
|
||||
<SelectTrigger size="sm">
|
||||
<SelectValue placeholder="Select Chart Type" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="w-32">
|
||||
<SelectItem value="line">Line</SelectItem>
|
||||
<SelectItem value="bar">Bar</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="w-auto min-w-[120px]">
|
||||
<Select value={chartLegend} onValueChange={handleChartLegend}>
|
||||
<SelectTrigger size="sm">
|
||||
<SelectValue placeholder="Select Legend Visibility" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="w-full">
|
||||
<SelectItem value="true">Show Legend</SelectItem>
|
||||
<SelectItem value="false">Hide Legend</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<div className="flex gap-3 items-center mb-6">
|
||||
<YearPicker selectedYear={selectedYear} setSelectedYear={handleYearChange} />
|
||||
<div className="w-auto min-w-[120px]">
|
||||
<Select value={count} onValueChange={handleCountType}>
|
||||
<SelectTrigger size="sm">
|
||||
<SelectValue placeholder="Select Count Type" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="w-32">
|
||||
<SelectItem value="sum">Nominal</SelectItem>
|
||||
<SelectItem value="count">Status</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
{/* <DefaultTooltip title="Filter" placement="top">
|
||||
<Button variant="outline" className="h-7.5" onClick={() => handleFilter(dateRange)}>
|
||||
<KeenIcon icon="filter" />
|
||||
</Button>
|
||||
</DefaultTooltip> */}
|
||||
<DefaultTooltip title="Reset Filter" placement="top">
|
||||
<Button variant="outline" className="h-7.5" onClick={resetFilter}>
|
||||
<KeenIcon icon="arrow-circle-left" />
|
||||
</Button>
|
||||
</DefaultTooltip>
|
||||
</div>
|
||||
|
||||
{/* Cards */}
|
||||
<div className="grid gap-5 lg:gap-7.5 mb-5">
|
||||
<div className="grid lg:grid-cols-4 gap-y-5 lg:gap-5 items-stretch">
|
||||
{cardData.map((data: any) => (
|
||||
<div className="lg:col-span-1" key={data.type}>
|
||||
<Card
|
||||
title={data.type.toUpperCase()}
|
||||
total={data.total}
|
||||
type={data.type}
|
||||
count={count}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chart */}
|
||||
<div className="grid gap-5 lg:gap-7.5">
|
||||
<div className="grid lg:grid-cols-1 gap-y-5 lg:gap-5 items-stretch">
|
||||
<div className="lg:col-span-1">
|
||||
<Chart
|
||||
title="Overview"
|
||||
count={count}
|
||||
toolbar={toolbar}
|
||||
chartData={chartData}
|
||||
chartType={chartType}
|
||||
chartLegend={chartLegend}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardHomePage;
|
||||
52
src/pages/dashboards/home/blocks/Card.tsx
Normal file
52
src/pages/dashboards/home/blocks/Card.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { useLanguage } from '@/i18n';
|
||||
import { fCurrency } from '@/utils/FormatNumber';
|
||||
import { toAbsoluteUrl } from '@/utils/Assets';
|
||||
|
||||
interface CardDataProduct {
|
||||
title: string;
|
||||
total: string;
|
||||
type: Array<{ label: string; value: string; total: string }>;
|
||||
count: 'sum' | 'count';
|
||||
}
|
||||
|
||||
const Card = ({ title, total, type, count }: CardDataProduct) => {
|
||||
const { isRTL } = useLanguage();
|
||||
|
||||
return (
|
||||
<div className="card h-full bg-[length:85%] bg-[length:85%] [background-position:9rem_-4rem] rtl:[background-position:-4rem_-4rem] bg-no-repeat channel-stats-bg">
|
||||
<div className="card-body flex flex-col gap-4 p-5 lg:p-b-7.5 lg:pt-4">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col w-8/12" style={{ background: '' }}>
|
||||
<span className="text-sm font-normal text-gray-600 mb-5">{title}</span>
|
||||
<span className="text-3xl font-semibold text-gray-900 mb-0">
|
||||
{count === 'sum' ? fCurrency(total) : total}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col w-4/12 justify-between" style={{ background: '' }}>
|
||||
<img
|
||||
src={toAbsoluteUrl('/media/file-types/chart.svg')}
|
||||
className="dark:hidden h-5 h-8"
|
||||
alt="Chart Icon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* <hr className="" />
|
||||
<div className="">
|
||||
{type.map((data: any, index: number) => (
|
||||
<div key={data.label}>
|
||||
<div className="flex justify-between mb-1">
|
||||
<div className="w-8/12 text-sm">{data.label}</div>
|
||||
<div className="w-4/12 text-sm text-end">
|
||||
{count === 'sum' ? fCurrency(data.total) : data.total}{' '}
|
||||
</div>
|
||||
</div>
|
||||
{index !== type.length - 1 && <hr className="border-dashed my-2" />}
|
||||
</div>
|
||||
))}
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { Card };
|
||||
166
src/pages/dashboards/home/blocks/Chart.tsx
Normal file
166
src/pages/dashboards/home/blocks/Chart.tsx
Normal file
@ -0,0 +1,166 @@
|
||||
import ApexChart from 'react-apexcharts';
|
||||
import { ApexOptions } from 'apexcharts';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { fCurrency } from '@/utils/FormatNumber';
|
||||
|
||||
interface Series {
|
||||
name: string;
|
||||
data: any[];
|
||||
}
|
||||
|
||||
const Chart = ({
|
||||
title,
|
||||
toolbar,
|
||||
chartType,
|
||||
chartLegend,
|
||||
subtitle,
|
||||
number,
|
||||
count,
|
||||
chartData = []
|
||||
}: any) => {
|
||||
const [series, setSeries] = useState<Series[]>([]);
|
||||
const [categories, setCategories] = useState<string[]>([]);
|
||||
|
||||
let legendOpt = null;
|
||||
if (chartLegend == 'true') {
|
||||
legendOpt = true;
|
||||
} else {
|
||||
legendOpt = false;
|
||||
}
|
||||
const options: ApexOptions = {
|
||||
chart: {
|
||||
type: 'area',
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '50%'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
offsetY: -10,
|
||||
offsetX: chartType === 'bar' ? 1.5 : 0,
|
||||
formatter: (value: any) => {
|
||||
if (count == 'sum') {
|
||||
return fCurrency(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
},
|
||||
markers: {
|
||||
size: 0,
|
||||
shape: 'circle'
|
||||
},
|
||||
xaxis: {
|
||||
categories: categories,
|
||||
labels: {
|
||||
style: {
|
||||
colors: 'var(--tw-gray-500)',
|
||||
fontSize: '12px'
|
||||
}
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
labels: {
|
||||
style: {
|
||||
colors: 'var(--tw-gray-500)',
|
||||
fontSize: '12px'
|
||||
},
|
||||
formatter: (value: any) => {
|
||||
if (count == 'sum') {
|
||||
return fCurrency(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
borderColor: 'var(--tw-gray-200)',
|
||||
strokeDashArray: 5,
|
||||
padding: {
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 20,
|
||||
left: 0
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
shared: true,
|
||||
intersect: false,
|
||||
y: {
|
||||
formatter: (value: any) => {
|
||||
if (count == 'sum') {
|
||||
return fCurrency(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
curve: 'smooth',
|
||||
lineCap: 'butt',
|
||||
colors: undefined,
|
||||
width: 3,
|
||||
dashArray: 0
|
||||
},
|
||||
legend: {
|
||||
show: legendOpt,
|
||||
position: 'right',
|
||||
floating: false
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
if (chartData && chartData.length !== 0) {
|
||||
const categories = chartData.map((item: any) => item.month);
|
||||
const statusNames = Object.keys(chartData[0]).filter((key) => key !== 'month');
|
||||
const series = statusNames.map((status) => {
|
||||
const cleanName = status
|
||||
.replace('_count', '')
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/(^|\s)\S/g, (match) => match.toUpperCase());
|
||||
return {
|
||||
name: cleanName,
|
||||
data: chartData.map((item: any) => item[status])
|
||||
};
|
||||
});
|
||||
setCategories(categories);
|
||||
setSeries(series);
|
||||
}
|
||||
}, [chartData]);
|
||||
|
||||
return (
|
||||
<div className="card h-full">
|
||||
<div className="card-header border-0 ps-5 pb-0">
|
||||
<h3 className="card-title">{title}</h3>
|
||||
</div>
|
||||
<div className="card-body flex flex-col gap-4 p-2 lg:p-b7.5 lg:pt-4">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex flex-col w-full">
|
||||
<div className="ps-3">{toolbar && <div>{toolbar}</div>}</div>
|
||||
<span className="text-sm font-normal text-gray-700 mb-1">{subtitle}</span>
|
||||
<span className="text-3xl font-semibold text-gray-900 mb-0">{number}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ApexChart
|
||||
id="earnings_chart" //
|
||||
options={options}
|
||||
series={series}
|
||||
type={chartType}
|
||||
legend={chartLegend}
|
||||
height={350}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { Chart };
|
||||
53
src/pages/dashboards/home/blocks/DateRangePicker.tsx
Normal file
53
src/pages/dashboards/home/blocks/DateRangePicker.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import { useState } from 'react';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||
import { Calendar } from '@/components/ui/calendar';
|
||||
import { DateRange } from 'react-day-picker';
|
||||
import { format } from 'date-fns';
|
||||
import { KeenIcon } from '@/components/keenicons';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface DateRangePickerProps {
|
||||
date: DateRange | undefined;
|
||||
setDate: (date: DateRange | undefined) => void;
|
||||
}
|
||||
|
||||
const DateRangePicker = ({ date, setDate }: DateRangePickerProps) => {
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
id="date"
|
||||
className={cn(
|
||||
'btn btn-sm btn-light data-[state=open]:bg-light-active',
|
||||
!date && 'text-gray-400'
|
||||
)}
|
||||
>
|
||||
<KeenIcon icon="calendar" className="me-0.5" />
|
||||
{date?.from ? (
|
||||
date.to ? (
|
||||
<>
|
||||
{format(date.from, 'LLL dd, y')} - {format(date.to, 'LLL dd, y')}
|
||||
</>
|
||||
) : (
|
||||
format(date.from, 'LLL dd, y')
|
||||
)
|
||||
) : (
|
||||
<span>Pick a date range</span>
|
||||
)}
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="end">
|
||||
<Calendar
|
||||
initialFocus
|
||||
mode="range"
|
||||
defaultMonth={date?.from}
|
||||
selected={date}
|
||||
onSelect={setDate}
|
||||
numberOfMonths={2}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
export { DateRangePicker };
|
||||
48
src/pages/dashboards/home/blocks/YearPicker.tsx
Normal file
48
src/pages/dashboards/home/blocks/YearPicker.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue
|
||||
} from '@/components/ui/select';
|
||||
import { get5LastYear } from '@/utils/Date';
|
||||
|
||||
interface YearPickerProps {
|
||||
selectedYear: string;
|
||||
setSelectedYear: (year: string) => void;
|
||||
}
|
||||
|
||||
// Komponen YearPicker
|
||||
const YearPicker = ({ selectedYear, setSelectedYear }: YearPickerProps) => {
|
||||
const selectYear = get5LastYear();
|
||||
|
||||
const handleYearChange = (year: string) => {
|
||||
setSelectedYear(year);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex gap-3">
|
||||
<Select value={selectedYear} onValueChange={handleYearChange}>
|
||||
<SelectTrigger size="sm" className="w-28">
|
||||
<SelectValue placeholder="Pilih Tahun" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{selectYear.length > 0 ? (
|
||||
selectYear.map((year, index) => (
|
||||
<SelectItem key={index} value={year}>
|
||||
{year}
|
||||
</SelectItem>
|
||||
))
|
||||
) : (
|
||||
<SelectItem value="no-data" disabled>
|
||||
No data available
|
||||
</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export { YearPicker };
|
||||
4
src/pages/dashboards/home/blocks/index.ts
Normal file
4
src/pages/dashboards/home/blocks/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './Card';
|
||||
export * from './DateRangePicker';
|
||||
export * from './Chart';
|
||||
export * from './YearPicker';
|
||||
17
src/pages/dashboards/home/hooks/DashboardHomeContext.tsx
Normal file
17
src/pages/dashboards/home/hooks/DashboardHomeContext.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React, { createContext, useCallback, useState } from 'react';
|
||||
|
||||
interface ContextProps {}
|
||||
|
||||
const initialProps: ContextProps = {};
|
||||
|
||||
const DashboardHomeContext = createContext<ContextProps>(initialProps);
|
||||
|
||||
const DashboardHomeContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
/* state */
|
||||
|
||||
/* action */
|
||||
|
||||
return <DashboardHomeContext.Provider value={{}}>{children}</DashboardHomeContext.Provider>;
|
||||
};
|
||||
|
||||
export { DashboardHomeContextProvider, DashboardHomeContext };
|
||||
5
src/pages/dashboards/home/hooks/index.ts
Normal file
5
src/pages/dashboards/home/hooks/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './DashboardHomeContext';
|
||||
export * from './useDashboardHomeContext';
|
||||
export * from './useFetchCardData';
|
||||
export * from './useFetchChartData';
|
||||
// export * from './useFetchYear';
|
||||
12
src/pages/dashboards/home/hooks/useDashboardHomeContext.tsx
Normal file
12
src/pages/dashboards/home/hooks/useDashboardHomeContext.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import { useContext } from 'react';
|
||||
import { DashboardHomeContext } from './DashboardHomeContext';
|
||||
|
||||
const useDashboardHomeContext = () => {
|
||||
const context = useContext(DashboardHomeContext);
|
||||
|
||||
if (!context) throw new Error('useDashboardHomeContext must be used within AuthProvider');
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
export { useDashboardHomeContext };
|
||||
49
src/pages/dashboards/home/hooks/useFetchCardData.tsx
Normal file
49
src/pages/dashboards/home/hooks/useFetchCardData.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { DateRange } from 'react-day-picker';
|
||||
import { formatDate } from 'date-fns';
|
||||
import { apiConfig } from '@/config/api.config';
|
||||
|
||||
const API_URL = apiConfig.service_credit;
|
||||
|
||||
interface UseFetchCardDataResult {
|
||||
cardData: any;
|
||||
isCardLoading: boolean;
|
||||
cardError: any;
|
||||
}
|
||||
|
||||
const useFetchCardData = (
|
||||
start_date: string,
|
||||
end_date: string,
|
||||
count: string
|
||||
): UseFetchCardDataResult => {
|
||||
const [cardData, setCardData] = useState<[]>([]);
|
||||
const [isCardLoading, setIsCardLoading] = useState<boolean>(false);
|
||||
const [cardError, setCardError] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setIsCardLoading(true);
|
||||
const response = await axios.get(`${API_URL}/dashboard/card`, {
|
||||
params: {
|
||||
start_date: start_date,
|
||||
end_date: end_date,
|
||||
aggregate: count
|
||||
}
|
||||
});
|
||||
setCardData(response.data.data);
|
||||
} catch (err) {
|
||||
setCardError(err);
|
||||
} finally {
|
||||
setIsCardLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [start_date, end_date, count]); // Dependensi pada from dan to
|
||||
|
||||
return { cardData, isCardLoading, cardError };
|
||||
};
|
||||
|
||||
export { useFetchCardData };
|
||||
49
src/pages/dashboards/home/hooks/useFetchChartData.tsx
Normal file
49
src/pages/dashboards/home/hooks/useFetchChartData.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { DateRange } from 'react-day-picker';
|
||||
import { formatDate } from 'date-fns';
|
||||
import { apiConfig } from '@/config/api.config';
|
||||
|
||||
const API_URL = apiConfig.service_credit;
|
||||
|
||||
interface UseFetchChartDataResult {
|
||||
chartData: any[];
|
||||
isChartLoading: boolean;
|
||||
chartError: any;
|
||||
}
|
||||
|
||||
const useFetchChartData = (
|
||||
start_date: string,
|
||||
end_date: string,
|
||||
count: string
|
||||
): UseFetchChartDataResult => {
|
||||
const [chartData, setChartData] = useState<any[]>([]);
|
||||
const [isChartLoading, setIsChartLoading] = useState<boolean>(false);
|
||||
const [chartError, setChartError] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setIsChartLoading(true);
|
||||
const response = await axios.get(`${API_URL}/dashboard/chart`, {
|
||||
params: {
|
||||
start_date: start_date,
|
||||
end_date: end_date,
|
||||
aggregate: count
|
||||
}
|
||||
});
|
||||
setChartData(response.data.data);
|
||||
} catch (err) {
|
||||
setChartError(err);
|
||||
} finally {
|
||||
setIsChartLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [start_date, end_date, count]); // Dependensi pada from dan to
|
||||
|
||||
return { chartData, isChartLoading, chartError };
|
||||
};
|
||||
|
||||
export { useFetchChartData };
|
||||
45
src/pages/dashboards/home/hooks/useFetchYear.tsx
Normal file
45
src/pages/dashboards/home/hooks/useFetchYear.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { apiConfig } from '@/config/api.config';
|
||||
|
||||
const API_URL = apiConfig.service_credit;
|
||||
|
||||
interface YearData {
|
||||
year: string;
|
||||
}
|
||||
interface UseFetchselectYearResult {
|
||||
selectYear: YearData[];
|
||||
isselectYearLoading: boolean;
|
||||
selectYearError: any;
|
||||
}
|
||||
|
||||
const useFetchYear = (
|
||||
path: string = '',
|
||||
start_date: string = '',
|
||||
end_date: string = '',
|
||||
year: string = ''
|
||||
): UseFetchselectYearResult => {
|
||||
const [selectYear, setSelectYear] = useState<YearData[]>([]);
|
||||
const [isselectYearLoading, setIsselectYearLoading] = useState<boolean>(false);
|
||||
const [selectYearError, setSelectYearError] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
setIsselectYearLoading(true);
|
||||
const response = await axios.get(`${API_URL}/dashboard/year`);
|
||||
setSelectYear(response.data.data.map((item: { year: string }) => ({ year: item.year })));
|
||||
} catch (err) {
|
||||
setSelectYearError(err);
|
||||
} finally {
|
||||
setIsselectYearLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [path, start_date, end_date, year]);
|
||||
|
||||
return { selectYear, isselectYearLoading, selectYearError };
|
||||
};
|
||||
|
||||
export { useFetchYear };
|
||||
1
src/pages/dashboards/home/index.ts
Normal file
1
src/pages/dashboards/home/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './DashboardHomePage';
|
||||
Reference in New Issue
Block a user