mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
refactor(FE): Refactor marketing report components and add HPP filter
This commit is contained in:
@@ -1,11 +1,7 @@
|
|||||||
import MarketingReportContent from '@/components/pages/report/marketing/MarketingReportContent';
|
import MarketingReportContent from '@/components/pages/report/marketing/MarketingReportContent';
|
||||||
|
|
||||||
const MarketingReportPage = () => {
|
const MarketingReportPage = () => {
|
||||||
return (
|
return <MarketingReportContent />;
|
||||||
<section className='w-full p-4'>
|
|
||||||
<MarketingReportContent />
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MarketingReportPage;
|
export default MarketingReportPage;
|
||||||
|
|||||||
@@ -1,47 +1,42 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { JSX, useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
import Tabs from '@/components/Tabs';
|
import Tabs from '@/components/Tabs';
|
||||||
import DailyMarketingReportContent from '@/components/pages/report/marketing/tab/DailyMarketingReportContent';
|
import DailyMarketingReportContent from '@/components/pages/report/marketing/tab/DailyMarketingReportContent';
|
||||||
import HppPerKandangTab from '@/components/pages/report/marketing/tab/HppPerKandangTab';
|
import HppPerKandangTab from '@/components/pages/report/marketing/tab/HppPerKandangTab';
|
||||||
|
import { useMarketingTabStore } from '@/stores/marketing-tab/marketing-tab.store';
|
||||||
type MarketingReportTabType =
|
|
||||||
| 'daily'
|
|
||||||
| 'transaction'
|
|
||||||
| 'hpp-comparison'
|
|
||||||
| 'daily-hpp';
|
|
||||||
|
|
||||||
const marketingReportTabs: {
|
|
||||||
id: MarketingReportTabType;
|
|
||||||
label: string;
|
|
||||||
content: JSX.Element;
|
|
||||||
}[] = [
|
|
||||||
{
|
|
||||||
id: 'daily',
|
|
||||||
label: 'Penjualan Harian',
|
|
||||||
content: <DailyMarketingReportContent />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'daily-hpp',
|
|
||||||
label: 'HPP Harian Kandang',
|
|
||||||
content: <HppPerKandangTab />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const MarketingReportContent = () => {
|
const MarketingReportContent = () => {
|
||||||
const [activeTab, setActiveTab] = useState<string>('daily');
|
const [activeTabId, setActiveTabId] = useState<string>('1');
|
||||||
|
const tabActions = useMarketingTabStore((state) => state.tabActions);
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
label: 'Penjualan Harian',
|
||||||
|
content: <DailyMarketingReportContent />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
label: 'HPP Harian Kandang',
|
||||||
|
content: <HppPerKandangTab tabId={'2'} />,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='w-full max-w-full pb-16'>
|
<section className='w-full'>
|
||||||
<Tabs
|
<Tabs
|
||||||
activeTabId={activeTab}
|
tabs={tabs}
|
||||||
onTabChange={setActiveTab}
|
variant='boxed'
|
||||||
tabs={marketingReportTabs}
|
activeTabId={activeTabId}
|
||||||
variant='lifted'
|
onTabChange={setActiveTabId}
|
||||||
className={{
|
className={{
|
||||||
content: '-m-px pl-px',
|
tabHeaderWrapper:
|
||||||
|
'justify-between items-center p-3 border-b border-base-content/10',
|
||||||
|
tab: 'w-fit',
|
||||||
|
content: 'p-0 m-0',
|
||||||
}}
|
}}
|
||||||
|
sideContent={tabActions[activeTabId] || null}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
|
export type HppPerKandangFilterType = {
|
||||||
|
area_id: string | null;
|
||||||
|
location_id: string | null;
|
||||||
|
kandang_id: string | null;
|
||||||
|
weight_min: string | null;
|
||||||
|
weight_max: string | null;
|
||||||
|
period: string | null;
|
||||||
|
sort_by: string | null;
|
||||||
|
show_unrecorded: boolean | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HppPerKandangFilterSchema = yup.object({
|
||||||
|
area_id: yup.string().nullable(),
|
||||||
|
location_id: yup.string().nullable(),
|
||||||
|
kandang_id: yup.string().nullable(),
|
||||||
|
weight_min: yup.string().nullable(),
|
||||||
|
weight_max: yup
|
||||||
|
.string()
|
||||||
|
.nullable()
|
||||||
|
.test(
|
||||||
|
'is-greater-than-min',
|
||||||
|
'Rentang bobot max tidak boleh lebih kecil dari min',
|
||||||
|
function (value) {
|
||||||
|
const { weight_min } = this.parent;
|
||||||
|
if (!weight_min || !value) return true;
|
||||||
|
const weightMinNum = parseFloat(weight_min) || 0;
|
||||||
|
const weightMaxNum = parseFloat(value) || 0;
|
||||||
|
return weightMaxNum >= weightMinNum;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
period: yup.string().required('Periode wajib diisi'),
|
||||||
|
sort_by: yup.string().nullable(),
|
||||||
|
show_unrecorded: yup.boolean().nullable(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type HppPerKandangFilterValues = yup.InferType<
|
||||||
|
typeof HppPerKandangFilterSchema
|
||||||
|
>;
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton';
|
||||||
|
import Table from '@/components/Table';
|
||||||
|
import { HppPerKandangReport } from '@/types/api/report/hpp-per-kandang';
|
||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
const HppPerKandangSkeleton = ({
|
||||||
|
columns,
|
||||||
|
icon,
|
||||||
|
title,
|
||||||
|
subtitle,
|
||||||
|
}: {
|
||||||
|
columns: ColumnDef<HppPerKandangReport['rows'][0]>[];
|
||||||
|
icon: React.ReactNode;
|
||||||
|
title: string;
|
||||||
|
subtitle: string;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className='relative size-full'>
|
||||||
|
<Table
|
||||||
|
data={[]}
|
||||||
|
columns={columns}
|
||||||
|
isLoading={true}
|
||||||
|
className={{
|
||||||
|
skeletonCellClassName: 'animate-none w-full h-5 bg-base-content/4',
|
||||||
|
headerColumnClassName: 'whitespace-nowrap',
|
||||||
|
containerClassName: 'mb-0 overflow-hidden',
|
||||||
|
tableWrapperClassName: 'overflow-hidden',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className='absolute inset-0 flex items-center justify-center'>
|
||||||
|
<DataStateSkeleton icon={icon} title={title} description={subtitle} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HppPerKandangSkeleton;
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user