mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE): slicing ui dashboard, API integration with dummy data and form validation
This commit is contained in:
@@ -20,13 +20,19 @@ import Alert from '@/components/Alert';
|
||||
import {
|
||||
DashboardFilterSchema,
|
||||
DashboardFilterType,
|
||||
getDashboardFilterSchema,
|
||||
} from '@/components/pages/dashboard/filter/DashboardProductionFilter.schema';
|
||||
import DashboardLineChart from '@/components/pages/dashboard/chart/DashboardLineChart';
|
||||
import DashboardLineChartSkeleton from '@/components/pages/dashboard/skeleton/DashboardLineChartSkeleton';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/input/RadioInput';
|
||||
import { DashboardFilter } from '@/types/api/dashboard/dashboard';
|
||||
import {
|
||||
DashboardFilter,
|
||||
DashboardMeta,
|
||||
} from '@/types/api/dashboard/dashboard';
|
||||
import DashboardStats from '@/components/pages/dashboard/chart/DashboardStats';
|
||||
import { isResponseSuccess } from '@/lib/api-helper';
|
||||
import AlertErrorList from '@/components/helper/form/FormErrors';
|
||||
import { getUniqueFormikErrors } from '@/lib/formik-helper';
|
||||
|
||||
// Helper function to normalize values to array
|
||||
const normalizeToArray = (
|
||||
@@ -46,6 +52,7 @@ const DashboardProduction = () => {
|
||||
);
|
||||
const [endpointUrl, setEndpointUrl] = useState('/dashboard');
|
||||
const [selectedLocationIds, setSelectedLocationIds] = useState<number[]>([]);
|
||||
const [formErrorList, setFormErrorList] = useState<string[]>([]);
|
||||
|
||||
// ===== FETCH DATA =====
|
||||
const {
|
||||
@@ -78,7 +85,7 @@ const DashboardProduction = () => {
|
||||
location_id: selectedLocationIds ? selectedLocationIds.toString() : '',
|
||||
});
|
||||
const comparedByOptions = [
|
||||
{ value: 'LOCATION', label: 'Location' },
|
||||
{ value: 'LOCATION', label: 'Farm' },
|
||||
{ value: 'FLOCK', label: 'Flock' },
|
||||
{ value: 'KANDANG', label: 'Kandang' },
|
||||
];
|
||||
@@ -97,7 +104,7 @@ const DashboardProduction = () => {
|
||||
flockIds: [],
|
||||
kandangIds: [],
|
||||
} as DashboardFilterType,
|
||||
validationSchema: DashboardFilterSchema,
|
||||
validationSchema: getDashboardFilterSchema(analysisMode),
|
||||
onSubmit: (values) => {
|
||||
console.log(values);
|
||||
|
||||
@@ -117,6 +124,7 @@ const DashboardProduction = () => {
|
||||
setAnalysisMode('OVERVIEW');
|
||||
setEndpointUrl('/dashboard');
|
||||
};
|
||||
|
||||
const handleApplyFilter = (values: DashboardFilter) => {
|
||||
console.log(values);
|
||||
|
||||
@@ -140,6 +148,23 @@ const DashboardProduction = () => {
|
||||
formik.resetForm();
|
||||
};
|
||||
|
||||
const handleValidateForm = async () => {
|
||||
const errors = await formik.validateForm();
|
||||
|
||||
if (Object.keys(errors).length > 0) {
|
||||
// Parse and display errors
|
||||
const errorMessages = getUniqueFormikErrors(errors);
|
||||
setFormErrorList(errorMessages);
|
||||
return; // Stop submission
|
||||
}
|
||||
};
|
||||
|
||||
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
handleValidateForm();
|
||||
formik.handleSubmit();
|
||||
};
|
||||
|
||||
if (isLoadingDashboardProductionData) {
|
||||
return (
|
||||
<div className='w-full min-h-screen flex items-center justify-center'>
|
||||
@@ -155,11 +180,53 @@ const DashboardProduction = () => {
|
||||
<div className='flex flex-row justify-end gap-2'>
|
||||
<Button
|
||||
variant='outline'
|
||||
className='min-w-28 rounded-lg'
|
||||
className={`min-w-28 rounded-lg ${
|
||||
isResponseSuccess(dashboardProductionResponse) &&
|
||||
(dashboardProductionResponse.meta as unknown as DashboardMeta)
|
||||
.filters
|
||||
? 'bg-gradient-to-r from-blue-50 to-blue-100 border-blue-500 text-blue-600 hover:from-blue-100 hover:to-blue-200'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() => filterModal.openModal()}
|
||||
>
|
||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
||||
<Icon
|
||||
icon='heroicons:funnel'
|
||||
width={20}
|
||||
height={20}
|
||||
className={
|
||||
isResponseSuccess(dashboardProductionResponse) &&
|
||||
(dashboardProductionResponse.meta as unknown as DashboardMeta)
|
||||
.filters
|
||||
? 'text-blue-600'
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
Filter
|
||||
{isResponseSuccess(dashboardProductionResponse) &&
|
||||
dashboardProductionResponse.meta &&
|
||||
(dashboardProductionResponse.meta as unknown as DashboardMeta)
|
||||
.filters && (
|
||||
<span className='w-6 h-6 text-white bg-red-500 rounded-lg flex items-center justify-center text-xs'>
|
||||
{(() => {
|
||||
const meta =
|
||||
dashboardProductionResponse.meta as unknown as DashboardMeta;
|
||||
if (!meta.filters) return 0;
|
||||
const count =
|
||||
(meta.filters.location_ids.length > 1
|
||||
? meta.filters.location_ids.length
|
||||
: 0) +
|
||||
(meta.filters.flock_ids.length > 1
|
||||
? meta.filters.flock_ids.length
|
||||
: 0) +
|
||||
(meta.filters.kandang_ids.length > 1
|
||||
? meta.filters.kandang_ids.length
|
||||
: 0);
|
||||
return meta.filters.analysis_mode === 'OVERVIEW'
|
||||
? 1
|
||||
: count;
|
||||
})()}
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
<Button
|
||||
variant='outline'
|
||||
@@ -183,7 +250,15 @@ const DashboardProduction = () => {
|
||||
dashboardProductionData.charts &&
|
||||
Object.keys(dashboardProductionData.charts).length > 0 ? (
|
||||
<DashboardLineChart
|
||||
analysisMode={analysisMode}
|
||||
analysisMode={
|
||||
isResponseSuccess(dashboardProductionResponse)
|
||||
? dashboardProductionResponse.meta
|
||||
? (
|
||||
dashboardProductionResponse.meta as unknown as DashboardMeta
|
||||
).filters?.analysis_mode
|
||||
: analysisMode
|
||||
: analysisMode
|
||||
}
|
||||
data={dashboardProductionData}
|
||||
/>
|
||||
) : (
|
||||
@@ -214,7 +289,11 @@ const DashboardProduction = () => {
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<form className='space-y-4' onSubmit={formik.handleSubmit}>
|
||||
<form
|
||||
className='space-y-4'
|
||||
onSubmit={handleFormSubmit}
|
||||
onReset={handleResetFilter}
|
||||
>
|
||||
{/* Rentang Waktu */}
|
||||
<div className='px-4'>
|
||||
<label className='flex items-center gap-2 mb-3'>Tanggal</label>
|
||||
@@ -259,6 +338,7 @@ const DashboardProduction = () => {
|
||||
value={formik.values.analysisMode}
|
||||
onChange={(e) => {
|
||||
formik.handleChange(e);
|
||||
setAnalysisMode(e.target.value as 'OVERVIEW' | 'COMPARISON');
|
||||
// Reset all dependent fields when analysis mode changes
|
||||
formik.setFieldValue('location', []);
|
||||
formik.setFieldValue('flock', []);
|
||||
@@ -395,6 +475,14 @@ const DashboardProduction = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Error List Alert */}
|
||||
{formErrorList.length > 0 && (
|
||||
<AlertErrorList
|
||||
formErrorList={formErrorList}
|
||||
onClose={() => setFormErrorList([])}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
||||
<Button
|
||||
|
||||
@@ -522,7 +522,13 @@ const DashboardLineChart = ({
|
||||
? false
|
||||
: {
|
||||
r: 3,
|
||||
fill: getLineColor(series.id, index, analysisMode),
|
||||
fill: '#fff',
|
||||
stroke: getLineColor(
|
||||
series.id,
|
||||
index,
|
||||
analysisMode
|
||||
),
|
||||
strokeWidth: 2,
|
||||
}
|
||||
}
|
||||
activeDot={isStandard ? undefined : { r: 5 }}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Alert from '@/components/Alert';
|
||||
import Card from '@/components/Card';
|
||||
import { formatNumber } from '@/lib/helper';
|
||||
import { DashboardStatisticsData } from '@/types/api/dashboard/dashboard';
|
||||
import { Icon } from '@iconify/react';
|
||||
|
||||
@@ -7,7 +8,7 @@ interface DashboardStatsProps {
|
||||
data: DashboardStatisticsData[];
|
||||
}
|
||||
|
||||
// Configuration for each card's static properties
|
||||
// Konfigurasi untuk setiap kartu
|
||||
const CARD_CONFIG = [
|
||||
{
|
||||
key: 'HPP Global',
|
||||
@@ -57,7 +58,7 @@ const DashboardStats = ({ data }: DashboardStatsProps) => {
|
||||
return (
|
||||
<>
|
||||
{prefix}
|
||||
{value.toLocaleString('id-ID')}
|
||||
{formatNumber(value)}
|
||||
{suffix && (
|
||||
<span className='text-sm font-normal text-neutral-500'>{suffix}</span>
|
||||
)}
|
||||
|
||||
@@ -2,11 +2,11 @@ import { OptionType } from '@/components/input/SelectInput';
|
||||
import * as yup from 'yup';
|
||||
|
||||
export type DashboardFilterType = {
|
||||
startDate: string | undefined;
|
||||
endDate: string | undefined;
|
||||
analysisMode: string | undefined;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
analysisMode: string;
|
||||
comparedBy: string | undefined;
|
||||
location: OptionType | OptionType[] | undefined;
|
||||
location: OptionType | OptionType[];
|
||||
lokasiIds: number[] | undefined;
|
||||
flock: OptionType | OptionType[] | undefined;
|
||||
flockIds: number[] | undefined;
|
||||
@@ -14,18 +14,104 @@ export type DashboardFilterType = {
|
||||
kandangIds: number[] | undefined;
|
||||
};
|
||||
|
||||
export const DashboardFilterSchema: yup.ObjectSchema<DashboardFilterType> =
|
||||
// Schema untuk mode OVERVIEW - semua field required
|
||||
export const DashboardFilterOverviewSchema: yup.ObjectSchema<DashboardFilterType> =
|
||||
yup.object({
|
||||
startDate: yup.string().optional(),
|
||||
endDate: yup.string().optional(),
|
||||
analysisMode: yup.string().optional(),
|
||||
comparedBy: yup.string().optional(),
|
||||
startDate: yup.string().required('Start date is required'),
|
||||
endDate: yup.string().required('End date is required'),
|
||||
analysisMode: yup.string().required('Analysis mode is required'),
|
||||
comparedBy: yup.string().when('analysisMode', {
|
||||
is: 'COMPARISON',
|
||||
then: (schema) => schema.required('Compared by is required'),
|
||||
otherwise: (schema) => schema.optional(),
|
||||
}),
|
||||
lokasiIds: yup.array().optional(),
|
||||
flockIds: yup.array().optional(),
|
||||
kandangIds: yup.array().optional(),
|
||||
location: yup.mixed<OptionType | OptionType[]>().optional(),
|
||||
flock: yup.mixed<OptionType | OptionType[]>().optional(),
|
||||
kandang: yup.mixed<OptionType | OptionType[]>().optional(),
|
||||
location: yup
|
||||
.mixed<OptionType | OptionType[]>()
|
||||
.required('Farm is required')
|
||||
.test('is-not-empty', 'Farm is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
flock: yup
|
||||
.mixed<OptionType | OptionType[]>()
|
||||
.required('Flock is required')
|
||||
.test('is-not-empty', 'Flock is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
kandang: yup
|
||||
.mixed<OptionType | OptionType[]>()
|
||||
.required('Kandang is required')
|
||||
.test('is-not-empty', 'Kandang is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
});
|
||||
|
||||
// Schema untuk mode COMPARISON - conditional validation
|
||||
export const DashboardFilterComparisonSchema: yup.ObjectSchema<DashboardFilterType> =
|
||||
yup.object({
|
||||
startDate: yup.string().required('Start date is required'),
|
||||
endDate: yup.string().required('End date is required'),
|
||||
analysisMode: yup.string().required('Analysis mode is required'),
|
||||
comparedBy: yup.string().when('analysisMode', {
|
||||
is: 'COMPARISON',
|
||||
then: (schema) => schema.required('Compared by is required'),
|
||||
otherwise: (schema) => schema.optional(),
|
||||
}),
|
||||
lokasiIds: yup.array().optional(),
|
||||
flockIds: yup.array().optional(),
|
||||
kandangIds: yup.array().optional(),
|
||||
location: yup
|
||||
.mixed<OptionType | OptionType[]>()
|
||||
.required('Farm is required')
|
||||
.test('is-not-empty', 'Farm is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
flock: yup.mixed<OptionType | OptionType[]>().when('comparedBy', {
|
||||
is: (value: string) => value === 'FLOCK' || value === 'KANDANG',
|
||||
then: (schema) =>
|
||||
schema.test('is-required', 'Flock is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
otherwise: (schema) => schema.optional(),
|
||||
}),
|
||||
kandang: yup.mixed<OptionType | OptionType[]>().when('comparedBy', {
|
||||
is: 'KANDANG',
|
||||
then: (schema) =>
|
||||
schema.test('is-required', 'Kandang is required', (value) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0;
|
||||
}
|
||||
return !!value;
|
||||
}),
|
||||
otherwise: (schema) => schema.optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
// Helper function untuk mendapatkan schema yang sesuai berdasarkan analysis mode
|
||||
export const getDashboardFilterSchema = (analysisMode?: string) => {
|
||||
return analysisMode === 'OVERVIEW'
|
||||
? DashboardFilterOverviewSchema
|
||||
: DashboardFilterComparisonSchema;
|
||||
};
|
||||
|
||||
// Default schema
|
||||
export const DashboardFilterSchema = DashboardFilterComparisonSchema;
|
||||
|
||||
export type DashboardFilterValues = yup.InferType<typeof DashboardFilterSchema>;
|
||||
|
||||
@@ -1,366 +1,347 @@
|
||||
{
|
||||
"code": 200,
|
||||
"status": "success",
|
||||
"message": "Get dashboard performance kandang comparison successfully",
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total_pages": 1,
|
||||
"total_results": 1,
|
||||
"filters": {
|
||||
"start_date": "2025-12-01",
|
||||
"end_date": "2025-12-31",
|
||||
"analysis_mode": "COMPARASION",
|
||||
"lokasi_ids": [1],
|
||||
"flock_ids": [1],
|
||||
"kandang_ids": [1, 2, 3]
|
||||
"statistics_data": [
|
||||
{
|
||||
"label": "HPP Global",
|
||||
"value": 16200,
|
||||
"percent_last_month": 15.5
|
||||
},
|
||||
{
|
||||
"label": "Avg. Selling Price",
|
||||
"value": 28300,
|
||||
"percent_last_month": -50
|
||||
},
|
||||
{
|
||||
"label": "FCR",
|
||||
"value": 24.02,
|
||||
"percent_last_month": 15.5
|
||||
},
|
||||
{
|
||||
"label": "Mortality",
|
||||
"value": 5,
|
||||
"percent_last_month": -15.5
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"statistics_data": [
|
||||
{
|
||||
"label": "HPP Global",
|
||||
"value": 16200,
|
||||
"percent_last_month": 15.5
|
||||
},
|
||||
{
|
||||
"label": "Avg. Selling Price",
|
||||
"value": 28300,
|
||||
"percent_last_month": -50
|
||||
},
|
||||
{
|
||||
"label": "FCR",
|
||||
"value": 24.02,
|
||||
"percent_last_month": 15.5
|
||||
},
|
||||
{
|
||||
"label": "Mortality",
|
||||
"value": 5,
|
||||
"percent_last_month": -15.5
|
||||
}
|
||||
],
|
||||
"charts": {
|
||||
"kandang": {
|
||||
"series": [
|
||||
{
|
||||
"id": 1,
|
||||
"label": "Kandang Dago",
|
||||
"unit": "%"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"label": "Kandang Sulanjana",
|
||||
"unit": "%"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"label": "Kandang Garut 2",
|
||||
"unit": "%"
|
||||
}
|
||||
],
|
||||
"dataset": [
|
||||
{
|
||||
"week": 1,
|
||||
"1": 21.2,
|
||||
"2": 19.5,
|
||||
"3": 20.1
|
||||
},
|
||||
{
|
||||
"week": 2,
|
||||
"1": 22.5,
|
||||
"2": 19.8,
|
||||
"3": 20.4
|
||||
},
|
||||
{
|
||||
"week": 3,
|
||||
"1": 23.1,
|
||||
"2": 20.2,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 4,
|
||||
"1": 24.5,
|
||||
"2": 21.5,
|
||||
"3": 22.1
|
||||
},
|
||||
{
|
||||
"week": 5,
|
||||
"1": 25.8,
|
||||
"2": 22.4,
|
||||
"3": 23.5
|
||||
},
|
||||
{
|
||||
"week": 6,
|
||||
"1": 26.2,
|
||||
"2": 23.1,
|
||||
"3": 24.8
|
||||
},
|
||||
{
|
||||
"week": 7,
|
||||
"1": 27.5,
|
||||
"2": 24.5,
|
||||
"3": 26.2
|
||||
},
|
||||
{
|
||||
"week": 8,
|
||||
"1": 28.1,
|
||||
"2": 25.8,
|
||||
"3": 27.5
|
||||
},
|
||||
{
|
||||
"week": 9,
|
||||
"1": 28.8,
|
||||
"2": 26.2,
|
||||
"3": 28.4
|
||||
},
|
||||
{
|
||||
"week": 10,
|
||||
"1": 29.1,
|
||||
"2": 27.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 11,
|
||||
"1": 28.5,
|
||||
"2": 28.1,
|
||||
"3": 27.4
|
||||
},
|
||||
{
|
||||
"week": 12,
|
||||
"1": 27.2,
|
||||
"2": 29.1,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 13,
|
||||
"1": 26.1,
|
||||
"2": 28.5,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 14,
|
||||
"1": 25.8,
|
||||
"2": 27.2,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 15,
|
||||
"1": 24.5,
|
||||
"2": 26.1,
|
||||
"3": 23.1
|
||||
},
|
||||
{
|
||||
"week": 16,
|
||||
"1": 23.2,
|
||||
"2": 25.8,
|
||||
"3": 22.5
|
||||
},
|
||||
{
|
||||
"week": 17,
|
||||
"1": 22.8,
|
||||
"2": 24.5,
|
||||
"3": 21.9
|
||||
},
|
||||
{
|
||||
"week": 18,
|
||||
"1": 21.9,
|
||||
"2": 23.2,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 19,
|
||||
"1": 21.2,
|
||||
"2": 22.8,
|
||||
"3": 20.5
|
||||
},
|
||||
{
|
||||
"week": 20,
|
||||
"1": 20.5,
|
||||
"2": 21.9,
|
||||
"3": 19.8
|
||||
},
|
||||
{
|
||||
"week": 21,
|
||||
"1": 19.8,
|
||||
"2": 21.2,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 22,
|
||||
"1": 20.4,
|
||||
"2": 20.5,
|
||||
"3": 18.5
|
||||
},
|
||||
{
|
||||
"week": 23,
|
||||
"1": 21.0,
|
||||
"2": 19.8,
|
||||
"3": 18.1
|
||||
},
|
||||
{
|
||||
"week": 24,
|
||||
"1": 22.1,
|
||||
"2": 20.4,
|
||||
"3": 17.8
|
||||
},
|
||||
{
|
||||
"week": 25,
|
||||
"1": 23.5,
|
||||
"2": 21.0,
|
||||
"3": 18.5
|
||||
},
|
||||
{
|
||||
"week": 26,
|
||||
"1": 24.8,
|
||||
"2": 22.1,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 27,
|
||||
"1": 26.2,
|
||||
"2": 23.5,
|
||||
"3": 20.1
|
||||
},
|
||||
{
|
||||
"week": 28,
|
||||
"1": 27.5,
|
||||
"2": 24.8,
|
||||
"3": 21.5
|
||||
},
|
||||
{
|
||||
"week": 29,
|
||||
"1": 28.4,
|
||||
"2": 26.2,
|
||||
"3": 22.8
|
||||
},
|
||||
{
|
||||
"week": 30,
|
||||
"1": 28.1,
|
||||
"2": 27.5,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 31,
|
||||
"1": 27.4,
|
||||
"2": 28.4,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 32,
|
||||
"1": 26.5,
|
||||
"2": 28.1,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 33,
|
||||
"1": 25.8,
|
||||
"2": 27.4,
|
||||
"3": 27.2
|
||||
},
|
||||
{
|
||||
"week": 34,
|
||||
"1": 24.2,
|
||||
"2": 26.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 35,
|
||||
"1": 23.1,
|
||||
"2": 25.8,
|
||||
"3": 28.5
|
||||
},
|
||||
{
|
||||
"week": 36,
|
||||
"1": 22.5,
|
||||
"2": 24.2,
|
||||
"3": 29.1
|
||||
},
|
||||
{
|
||||
"week": 37,
|
||||
"1": 21.9,
|
||||
"2": 23.1,
|
||||
"3": 28.8
|
||||
},
|
||||
{
|
||||
"week": 38,
|
||||
"1": 21.0,
|
||||
"2": 22.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 39,
|
||||
"1": 20.5,
|
||||
"2": 21.9,
|
||||
"3": 27.4
|
||||
},
|
||||
{
|
||||
"week": 40,
|
||||
"1": 19.8,
|
||||
"2": 21.0,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 41,
|
||||
"1": 19.2,
|
||||
"2": 20.5,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 42,
|
||||
"1": 18.5,
|
||||
"2": 19.8,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 43,
|
||||
"1": 18.1,
|
||||
"2": 19.2,
|
||||
"3": 23.1
|
||||
},
|
||||
{
|
||||
"week": 44,
|
||||
"1": 17.8,
|
||||
"2": 18.5,
|
||||
"3": 22.5
|
||||
},
|
||||
{
|
||||
"week": 45,
|
||||
"1": 18.5,
|
||||
"2": 18.1,
|
||||
"3": 21.9
|
||||
},
|
||||
{
|
||||
"week": 46,
|
||||
"1": 19.2,
|
||||
"2": 17.8,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 47,
|
||||
"1": 20.1,
|
||||
"2": 18.5,
|
||||
"3": 20.5
|
||||
},
|
||||
{
|
||||
"week": 48,
|
||||
"1": 21.5,
|
||||
"2": 19.2,
|
||||
"3": 19.8
|
||||
},
|
||||
{
|
||||
"week": 49,
|
||||
"1": 22.8,
|
||||
"2": 20.1,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 50,
|
||||
"1": 24.2,
|
||||
"2": 21.5,
|
||||
"3": 18.5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"charts": {
|
||||
"kandang": {
|
||||
"series": [
|
||||
{
|
||||
"id": 1,
|
||||
"label": "Kandang Dago",
|
||||
"unit": "%"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"label": "Kandang Sulanjana",
|
||||
"unit": "%"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"label": "Kandang Garut 2",
|
||||
"unit": "%"
|
||||
}
|
||||
],
|
||||
"dataset": [
|
||||
{
|
||||
"week": 1,
|
||||
"1": 21.2,
|
||||
"2": 19.5,
|
||||
"3": 20.1
|
||||
},
|
||||
{
|
||||
"week": 2,
|
||||
"1": 22.5,
|
||||
"2": 19.8,
|
||||
"3": 20.4
|
||||
},
|
||||
{
|
||||
"week": 3,
|
||||
"1": 23.1,
|
||||
"2": 20.2,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 4,
|
||||
"1": 24.5,
|
||||
"2": 21.5,
|
||||
"3": 22.1
|
||||
},
|
||||
{
|
||||
"week": 5,
|
||||
"1": 25.8,
|
||||
"2": 22.4,
|
||||
"3": 23.5
|
||||
},
|
||||
{
|
||||
"week": 6,
|
||||
"1": 26.2,
|
||||
"2": 23.1,
|
||||
"3": 24.8
|
||||
},
|
||||
{
|
||||
"week": 7,
|
||||
"1": 27.5,
|
||||
"2": 24.5,
|
||||
"3": 26.2
|
||||
},
|
||||
{
|
||||
"week": 8,
|
||||
"1": 28.1,
|
||||
"2": 25.8,
|
||||
"3": 27.5
|
||||
},
|
||||
{
|
||||
"week": 9,
|
||||
"1": 28.8,
|
||||
"2": 26.2,
|
||||
"3": 28.4
|
||||
},
|
||||
{
|
||||
"week": 10,
|
||||
"1": 29.1,
|
||||
"2": 27.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 11,
|
||||
"1": 28.5,
|
||||
"2": 28.1,
|
||||
"3": 27.4
|
||||
},
|
||||
{
|
||||
"week": 12,
|
||||
"1": 27.2,
|
||||
"2": 29.1,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 13,
|
||||
"1": 26.1,
|
||||
"2": 28.5,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 14,
|
||||
"1": 25.8,
|
||||
"2": 27.2,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 15,
|
||||
"1": 24.5,
|
||||
"2": 26.1,
|
||||
"3": 23.1
|
||||
},
|
||||
{
|
||||
"week": 16,
|
||||
"1": 23.2,
|
||||
"2": 25.8,
|
||||
"3": 22.5
|
||||
},
|
||||
{
|
||||
"week": 17,
|
||||
"1": 22.8,
|
||||
"2": 24.5,
|
||||
"3": 21.9
|
||||
},
|
||||
{
|
||||
"week": 18,
|
||||
"1": 21.9,
|
||||
"2": 23.2,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 19,
|
||||
"1": 21.2,
|
||||
"2": 22.8,
|
||||
"3": 20.5
|
||||
},
|
||||
{
|
||||
"week": 20,
|
||||
"1": 20.5,
|
||||
"2": 21.9,
|
||||
"3": 19.8
|
||||
},
|
||||
{
|
||||
"week": 21,
|
||||
"1": 19.8,
|
||||
"2": 21.2,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 22,
|
||||
"1": 20.4,
|
||||
"2": 20.5,
|
||||
"3": 18.5
|
||||
},
|
||||
{
|
||||
"week": 23,
|
||||
"1": 21.0,
|
||||
"2": 19.8,
|
||||
"3": 18.1
|
||||
},
|
||||
{
|
||||
"week": 24,
|
||||
"1": 22.1,
|
||||
"2": 20.4,
|
||||
"3": 17.8
|
||||
},
|
||||
{
|
||||
"week": 25,
|
||||
"1": 23.5,
|
||||
"2": 21.0,
|
||||
"3": 18.5
|
||||
},
|
||||
{
|
||||
"week": 26,
|
||||
"1": 24.8,
|
||||
"2": 22.1,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 27,
|
||||
"1": 26.2,
|
||||
"2": 23.5,
|
||||
"3": 20.1
|
||||
},
|
||||
{
|
||||
"week": 28,
|
||||
"1": 27.5,
|
||||
"2": 24.8,
|
||||
"3": 21.5
|
||||
},
|
||||
{
|
||||
"week": 29,
|
||||
"1": 28.4,
|
||||
"2": 26.2,
|
||||
"3": 22.8
|
||||
},
|
||||
{
|
||||
"week": 30,
|
||||
"1": 28.1,
|
||||
"2": 27.5,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 31,
|
||||
"1": 27.4,
|
||||
"2": 28.4,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 32,
|
||||
"1": 26.5,
|
||||
"2": 28.1,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 33,
|
||||
"1": 25.8,
|
||||
"2": 27.4,
|
||||
"3": 27.2
|
||||
},
|
||||
{
|
||||
"week": 34,
|
||||
"1": 24.2,
|
||||
"2": 26.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 35,
|
||||
"1": 23.1,
|
||||
"2": 25.8,
|
||||
"3": 28.5
|
||||
},
|
||||
{
|
||||
"week": 36,
|
||||
"1": 22.5,
|
||||
"2": 24.2,
|
||||
"3": 29.1
|
||||
},
|
||||
{
|
||||
"week": 37,
|
||||
"1": 21.9,
|
||||
"2": 23.1,
|
||||
"3": 28.8
|
||||
},
|
||||
{
|
||||
"week": 38,
|
||||
"1": 21.0,
|
||||
"2": 22.5,
|
||||
"3": 28.1
|
||||
},
|
||||
{
|
||||
"week": 39,
|
||||
"1": 20.5,
|
||||
"2": 21.9,
|
||||
"3": 27.4
|
||||
},
|
||||
{
|
||||
"week": 40,
|
||||
"1": 19.8,
|
||||
"2": 21.0,
|
||||
"3": 26.5
|
||||
},
|
||||
{
|
||||
"week": 41,
|
||||
"1": 19.2,
|
||||
"2": 20.5,
|
||||
"3": 25.8
|
||||
},
|
||||
{
|
||||
"week": 42,
|
||||
"1": 18.5,
|
||||
"2": 19.8,
|
||||
"3": 24.2
|
||||
},
|
||||
{
|
||||
"week": 43,
|
||||
"1": 18.1,
|
||||
"2": 19.2,
|
||||
"3": 23.1
|
||||
},
|
||||
{
|
||||
"week": 44,
|
||||
"1": 17.8,
|
||||
"2": 18.5,
|
||||
"3": 22.5
|
||||
},
|
||||
{
|
||||
"week": 45,
|
||||
"1": 18.5,
|
||||
"2": 18.1,
|
||||
"3": 21.9
|
||||
},
|
||||
{
|
||||
"week": 46,
|
||||
"1": 19.2,
|
||||
"2": 17.8,
|
||||
"3": 21.0
|
||||
},
|
||||
{
|
||||
"week": 47,
|
||||
"1": 20.1,
|
||||
"2": 18.5,
|
||||
"3": 20.5
|
||||
},
|
||||
{
|
||||
"week": 48,
|
||||
"1": 21.5,
|
||||
"2": 19.2,
|
||||
"3": 19.8
|
||||
},
|
||||
{
|
||||
"week": 49,
|
||||
"1": 22.8,
|
||||
"2": 20.1,
|
||||
"3": 19.2
|
||||
},
|
||||
{
|
||||
"week": 50,
|
||||
"1": 24.2,
|
||||
"2": 21.5,
|
||||
"3": 18.5
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,13 @@
|
||||
* This file is auto-generated. Do not edit manually.
|
||||
*/
|
||||
|
||||
import { Dashboard } from '../../types/api/dashboard/dashboard';
|
||||
import { Dashboard, DashboardMeta } from '../../types/api/dashboard/dashboard';
|
||||
import { BaseApiResponse } from '@/types/api/api-general';
|
||||
import dummyData from './dashboard.default.json';
|
||||
|
||||
import dummyData from './dashboard.overview.dummy.json';
|
||||
import dummyData2 from './dashboard.comparasion.location.dummy.json';
|
||||
import dummyData3 from './dashboard.comparasion.flock.dummy.json';
|
||||
import dummyData4 from './dashboard.comparasion.kandang.dummy.json';
|
||||
import dummyData5 from './dashboard.default.json';
|
||||
/**
|
||||
* Get dummy DashboardProduction data
|
||||
* @returns Promise with BaseApiResponse containing DashboardProduction
|
||||
@@ -20,6 +23,18 @@ export async function getDummySingle(): Promise<BaseApiResponse<Dashboard>> {
|
||||
code: 200,
|
||||
status: 'success',
|
||||
message: 'Data retrieved successfully',
|
||||
meta: {
|
||||
page: 1,
|
||||
limit: 1,
|
||||
total_pages: 1,
|
||||
total_results: 1,
|
||||
filters: {
|
||||
analysis_mode: 'OVERVIEW',
|
||||
location_ids: [1],
|
||||
flock_ids: [1],
|
||||
kandang_ids: [1],
|
||||
},
|
||||
} as DashboardMeta,
|
||||
data: dummyData as unknown as Dashboard,
|
||||
});
|
||||
});
|
||||
|
||||
+10
@@ -1,3 +1,5 @@
|
||||
import { SuccessApiResponse } from '@/types/api/api-general';
|
||||
|
||||
export interface Dashboard {
|
||||
statistics_data: DashboardStatisticsData[];
|
||||
charts: DashboardComparisonCharts | DashboardOverviewCharts;
|
||||
@@ -48,3 +50,11 @@ export interface DashboardFilter {
|
||||
flock_ids: number[];
|
||||
kandang_ids: number[];
|
||||
}
|
||||
|
||||
export interface DashboardMeta {
|
||||
page: number;
|
||||
limit: number;
|
||||
total_pages: number;
|
||||
total_results: number;
|
||||
filters: DashboardFilter;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user