diff --git a/src/components/pages/report/DailyMarketingsTable.tsx b/src/components/pages/report/DailyMarketingsTable.tsx new file mode 100644 index 00000000..d6914cf1 --- /dev/null +++ b/src/components/pages/report/DailyMarketingsTable.tsx @@ -0,0 +1,255 @@ +'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 } 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; + 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([]); + + const dailyMarketingColumns: ColumnDef[] = [ + { + 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: 'do_date', + header: 'Tanggal DO', + cell: (props) => formatDate(props.row.original.do_date, 'DD-MMM-YYYY'), + }, + { + accessorKey: 'aging_days', + header: 'Aging', + cell: (props) => `${props.row.original.aging_days} hari`, + }, + { + accessorKey: 'warehouse.name', + header: 'Gudang', + }, + { + accessorKey: 'customer.name', + header: 'Pelanggan', + }, + { + accessorKey: 'do_number', + header: 'No. DO', + }, + { + accessorKey: 'sales', + header: 'Sales/Marketing', + }, + { + accessorKey: 'vehicle_number', + header: 'No. Polisi', + cell: (props) => ( + {props.row.original.vehicle_number} + ), + }, + { + accessorKey: 'marketing_type', + header: 'Marketing Type', + }, + { + accessorKey: 'product.name', + header: 'Produk', + }, + { + accessorKey: 'qty', + header: 'Kuantitas', + cell: (props) => formatNumber(props.row.original.qty), + footer: () => { + const totalQty = isResponseSuccess(dailyMarketings) + ? dailyMarketings.data.summary.total_qty + : 0; + + return formatNumber(totalQty); + }, + }, + { + accessorKey: 'average_weight_kg', + header: 'Bobot Rata-Rata (Kg)', + cell: (props) => formatNumber(props.row.original.average_weight_kg), + }, + { + accessorKey: 'total_weight_kg', + header: 'Bobot Total (Kg)', + cell: (props) => formatNumber(props.row.original.total_weight_kg), + footer: () => { + const totalWeightKg = isResponseSuccess(dailyMarketings) + ? dailyMarketings.data.summary.total_weight_kg + : 0; + + return formatNumber(totalWeightKg); + }, + }, + { + accessorKey: 'sales_price_per_kg', + header: 'Harga Jual (Rp)', + cell: (props) => formatCurrency(props.row.original.sales_price_per_kg), + }, + { + accessorKey: 'hpp_price_per_kg', + header: 'HPP (Rp)', + cell: (props) => formatCurrency(props.row.original.hpp_price_per_kg), + }, + { + accessorKey: 'sales_amount', + header: 'Total (Rp)', + cell: (props) => formatCurrency(props.row.original.sales_amount), + footer: () => { + const totalSalesAmount = isResponseSuccess(dailyMarketings) + ? dailyMarketings.data.summary.total_sales_amount + : 0; + + return 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.rows.length > 0 + : false + ); + } + }, [dailyMarketings, isResponseSuccess]); + + return ( + + +
Penjualan Harian
+ + + + } + className='w-full!' + titleClassName='w-full p-0!' + > +
+
+
+ +
+
+ + + data={ + isResponseSuccess(dailyMarketings) + ? dailyMarketings?.data.rows + : [] + } + 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?.rows.length === 0, + }), + }} + /> +
+
+
+ ); +}; + +export default DailyMarketingsTable;