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