mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 07:45:47 +00:00
refactor(FE): Remove DailyMarketingsTable component and refactor related
files
This commit is contained in:
@@ -1,289 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { ChangeEventHandler, useEffect, useState } from 'react';
|
|
||||||
import useSWR from 'swr';
|
|
||||||
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
|
||||||
|
|
||||||
import { Icon } from '@iconify/react';
|
|
||||||
import Table from '@/components/Table';
|
|
||||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
|
||||||
import Card from '@/components/Card';
|
|
||||||
import Collapse from '@/components/Collapse';
|
|
||||||
|
|
||||||
import {
|
|
||||||
cn,
|
|
||||||
formatCurrency,
|
|
||||||
formatDate,
|
|
||||||
formatNumber,
|
|
||||||
formatVechicleNumber,
|
|
||||||
} from '@/lib/helper';
|
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
|
||||||
import { DailyMarketingRow } from '@/types/api/report/marketing';
|
|
||||||
import { MarketingReportApi } from '@/services/api/report/marketing-report';
|
|
||||||
|
|
||||||
interface DailyMarketingsTableProps {
|
|
||||||
dailyMarketingsReportUrl: string;
|
|
||||||
onSetPage: (page: number) => void;
|
|
||||||
pageSize: number;
|
|
||||||
onSetPageSize: (pageSize: number) => void;
|
|
||||||
searchValue: string;
|
|
||||||
onSearchChange: ChangeEventHandler<HTMLInputElement>;
|
|
||||||
onFilterByChange: (filterBy: string) => void;
|
|
||||||
onSortByChange: (sort: 'asc' | 'desc' | '') => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DailyMarketingsTable = ({
|
|
||||||
dailyMarketingsReportUrl,
|
|
||||||
onSetPage,
|
|
||||||
pageSize,
|
|
||||||
onSetPageSize,
|
|
||||||
searchValue,
|
|
||||||
onSearchChange,
|
|
||||||
onFilterByChange,
|
|
||||||
onSortByChange,
|
|
||||||
}: DailyMarketingsTableProps) => {
|
|
||||||
const { data: dailyMarketings, isLoading: isLoadingDailyMarketings } = useSWR(
|
|
||||||
dailyMarketingsReportUrl,
|
|
||||||
MarketingReportApi.getAllDailyMarketingFetcher,
|
|
||||||
{
|
|
||||||
keepPreviousData: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const [open, setOpen] = useState(true);
|
|
||||||
|
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
|
||||||
|
|
||||||
const dailyMarketingColumns: ColumnDef<DailyMarketingRow>[] = [
|
|
||||||
{
|
|
||||||
header: 'No',
|
|
||||||
cell: (props) => props.row.index + 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'so_date',
|
|
||||||
header: 'Tanggal Jual',
|
|
||||||
cell: (props) => formatDate(props.row.original.so_date, 'DD-MMM-YYYY'),
|
|
||||||
footer: 'Total',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'realization_date',
|
|
||||||
header: 'Tanggal Realisasi',
|
|
||||||
cell: (props) =>
|
|
||||||
formatDate(props.row.original.realization_date, 'DD-MMM-YYYY'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'aging_days',
|
|
||||||
header: 'Aging',
|
|
||||||
cell: (props) => `${props.row.original.aging_days} hari`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'warehouse',
|
|
||||||
header: 'Gudang',
|
|
||||||
cell: ({ row }) => row.original.warehouse.name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'customer',
|
|
||||||
header: 'Pelanggan',
|
|
||||||
cell: ({ row }) => row.original.customer.name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'do_number',
|
|
||||||
header: 'No. DO',
|
|
||||||
enableSorting: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'sales_person',
|
|
||||||
header: 'Sales/Marketing',
|
|
||||||
cell: (props) => props.row.original.sales.name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'vehicle_number',
|
|
||||||
header: 'No. Polisi',
|
|
||||||
cell: (props) => (
|
|
||||||
<span className='text-nowrap'>
|
|
||||||
{formatVechicleNumber(props.row.original.vehicle_number)}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'marketing_type',
|
|
||||||
header: 'Marketing Type',
|
|
||||||
enableSorting: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'product',
|
|
||||||
header: 'Produk',
|
|
||||||
cell: ({ row }) => row.original.product.name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'qty',
|
|
||||||
header: 'Kuantitas',
|
|
||||||
cell: (props) => formatNumber(props.row.original.qty),
|
|
||||||
footer: () => {
|
|
||||||
const totalQty = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.total_qty
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalQty ? formatNumber(totalQty) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'average_weight',
|
|
||||||
header: 'Bobot Rata-Rata (Kg)',
|
|
||||||
cell: (props) => formatNumber(props.row.original.average_weight_kg),
|
|
||||||
footer: () => {
|
|
||||||
const totalAverageWeightKg = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.average_weight_kg
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalAverageWeightKg ? formatNumber(totalAverageWeightKg) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'total_weight',
|
|
||||||
header: 'Bobot Total (Kg)',
|
|
||||||
cell: (props) => formatNumber(props.row.original.total_weight_kg),
|
|
||||||
footer: () => {
|
|
||||||
const totalWeightKg = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.total_weight_kg
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalWeightKg ? formatNumber(totalWeightKg) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'sales_price',
|
|
||||||
header: 'Harga Jual (Rp)',
|
|
||||||
cell: (props) => formatCurrency(props.row.original.sales_price_per_kg),
|
|
||||||
footer: () => {
|
|
||||||
const totalSalesPrice = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.average_sales_price
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalSalesPrice ? formatNumber(totalSalesPrice) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'hpp_price',
|
|
||||||
header: 'HPP (Rp)',
|
|
||||||
cell: (props) => formatCurrency(props.row.original.hpp_price_per_kg),
|
|
||||||
footer: () => {
|
|
||||||
const totalHppPricePerKg = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.total_hpp_price_per_kg
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalHppPricePerKg ? formatCurrency(totalHppPricePerKg) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'sales_amount',
|
|
||||||
header: 'Total (Rp)',
|
|
||||||
cell: (props) => formatCurrency(props.row.original.sales_amount),
|
|
||||||
footer: () => {
|
|
||||||
const totalSalesAmount = isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.total?.total_sales_amount
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return totalSalesAmount ? formatCurrency(totalSalesAmount) : '-';
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (sorting.length === 1) {
|
|
||||||
onFilterByChange(sorting[0].id);
|
|
||||||
onSortByChange(sorting[0].desc ? 'desc' : 'asc');
|
|
||||||
} else {
|
|
||||||
onFilterByChange('');
|
|
||||||
onSortByChange('');
|
|
||||||
}
|
|
||||||
}, [sorting]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!open) {
|
|
||||||
setOpen(
|
|
||||||
isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings.data.length > 0
|
|
||||||
: false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [dailyMarketings, isResponseSuccess]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
className={{
|
|
||||||
wrapper: 'w-full',
|
|
||||||
body: 'p-4 shadow',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Collapse
|
|
||||||
open={open}
|
|
||||||
onOpenChange={setOpen}
|
|
||||||
title={
|
|
||||||
<div className='card-actions p-4 justify-between items-center w-full'>
|
|
||||||
<div className='card-title'>Penjualan Harian</div>
|
|
||||||
|
|
||||||
<Icon
|
|
||||||
icon='material-symbols:keyboard-arrow-down'
|
|
||||||
width={24}
|
|
||||||
height={24}
|
|
||||||
className={cn('text-primary transition-transform', {
|
|
||||||
'-rotate-180': open,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
className='w-full!'
|
|
||||||
titleClassName='w-full p-0!'
|
|
||||||
>
|
|
||||||
<div className='w-full p-0'>
|
|
||||||
<div className='flex flex-col gap-2 mb-4'>
|
|
||||||
<div className='w-full flex flex-col sm:flex-row justify-start items-end sm:items-center gap-4'>
|
|
||||||
<DebouncedTextInput
|
|
||||||
name='search'
|
|
||||||
placeholder='Cari Penjualan Harian'
|
|
||||||
value={searchValue}
|
|
||||||
onChange={onSearchChange}
|
|
||||||
className={{ wrapper: 'sm:max-w-3xs' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Table<DailyMarketingRow>
|
|
||||||
data={
|
|
||||||
isResponseSuccess(dailyMarketings) ? dailyMarketings?.data : []
|
|
||||||
}
|
|
||||||
columns={dailyMarketingColumns}
|
|
||||||
pageSize={pageSize}
|
|
||||||
onPageSizeChange={onSetPageSize}
|
|
||||||
rowOptions={[10, 20, 50, 100]}
|
|
||||||
page={
|
|
||||||
isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.meta?.page
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
totalItems={
|
|
||||||
isResponseSuccess(dailyMarketings)
|
|
||||||
? dailyMarketings?.meta?.total_results
|
|
||||||
: 0
|
|
||||||
}
|
|
||||||
onPageChange={onSetPage}
|
|
||||||
isLoading={isLoadingDailyMarketings}
|
|
||||||
sorting={sorting}
|
|
||||||
setSorting={setSorting}
|
|
||||||
renderFooter={true}
|
|
||||||
className={{
|
|
||||||
containerClassName: cn({
|
|
||||||
'w-full mb-20':
|
|
||||||
isResponseSuccess(dailyMarketings) &&
|
|
||||||
dailyMarketings?.data?.length === 0,
|
|
||||||
}),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Collapse>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DailyMarketingsTable;
|
|
||||||
@@ -14,7 +14,7 @@ const MarketingReportContent = () => {
|
|||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
label: 'Penjualan Harian',
|
label: 'Penjualan Harian',
|
||||||
content: <DailyMarketingReportContent />,
|
content: <DailyMarketingReportContent tabId={'1'} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2',
|
id: '2',
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user