2025-09-11 18:20:40 +07:00
|
|
|
'use client'
|
|
|
|
|
|
|
|
|
|
import DateRangePicker from '@/components/RangeDatePicker'
|
|
|
|
|
import { ReportItem, ReportItemFooter, ReportItemHeader, ReportItemSubheader } from '@/components/report/ReportItem'
|
2025-09-25 15:45:49 +07:00
|
|
|
import { ExcelExportProfitLossService } from '@/services/export/excel/ExcelExportProfitLossService'
|
2025-09-25 14:59:08 +07:00
|
|
|
import { ProfitLossReport } from '@/types/services/analytic'
|
|
|
|
|
import { Button, Card, CardContent, Box } from '@mui/material'
|
2025-09-11 18:20:40 +07:00
|
|
|
|
2025-09-25 14:59:08 +07:00
|
|
|
interface ReportProfitLossContentProps {
|
|
|
|
|
profitData: ProfitLossReport | undefined
|
|
|
|
|
startDate: Date | null
|
|
|
|
|
endDate: Date | null
|
|
|
|
|
onStartDateChange: (date: Date | null) => void
|
|
|
|
|
onEndDateChange: (date: Date | null) => void
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Utility function to format date for display
|
|
|
|
|
const formatDisplayDate = (dateString: string) => {
|
|
|
|
|
const date = new Date(dateString)
|
|
|
|
|
return date.toLocaleDateString('id-ID', {
|
|
|
|
|
day: '2-digit',
|
|
|
|
|
month: '2-digit',
|
|
|
|
|
year: 'numeric'
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ReportProfitLossContent = ({
|
|
|
|
|
profitData,
|
|
|
|
|
startDate,
|
|
|
|
|
endDate,
|
|
|
|
|
onStartDateChange,
|
|
|
|
|
onEndDateChange
|
|
|
|
|
}: ReportProfitLossContentProps) => {
|
2025-09-25 15:45:49 +07:00
|
|
|
const handleExport = async () => {
|
|
|
|
|
if (!profitData) return
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const result = await ExcelExportProfitLossService.exportProfitLossToExcel(profitData)
|
|
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
// Optional: Show success notification
|
|
|
|
|
console.log('Export successful:', result.filename)
|
|
|
|
|
// You can add toast notification here
|
|
|
|
|
} else {
|
|
|
|
|
console.error('Export failed:', result.error)
|
|
|
|
|
alert('Export gagal. Silakan coba lagi.')
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Export error:', error)
|
|
|
|
|
alert('Terjadi kesalahan saat export.')
|
|
|
|
|
}
|
2025-09-25 14:59:08 +07:00
|
|
|
}
|
2025-09-11 18:20:40 +07:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
<div className='p-6 border-be'>
|
|
|
|
|
<div className='flex items-center justify-end gap-2'>
|
|
|
|
|
<Button
|
|
|
|
|
color='secondary'
|
|
|
|
|
variant='tonal'
|
|
|
|
|
startIcon={<i className='tabler-upload' />}
|
|
|
|
|
className='max-sm:is-full'
|
2025-09-25 14:59:08 +07:00
|
|
|
onClick={handleExport}
|
|
|
|
|
disabled={!profitData}
|
2025-09-11 18:20:40 +07:00
|
|
|
>
|
|
|
|
|
Ekspor
|
|
|
|
|
</Button>
|
|
|
|
|
<DateRangePicker
|
|
|
|
|
startDate={startDate}
|
|
|
|
|
endDate={endDate}
|
2025-09-25 14:59:08 +07:00
|
|
|
onStartDateChange={onStartDateChange}
|
|
|
|
|
onEndDateChange={onEndDateChange}
|
2025-09-11 18:20:40 +07:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<CardContent>
|
2025-09-25 14:59:08 +07:00
|
|
|
{profitData ? (
|
|
|
|
|
<>
|
|
|
|
|
{/* Summary Section */}
|
|
|
|
|
<ReportItemHeader
|
|
|
|
|
title='Pendapatan'
|
|
|
|
|
date={`${profitData.date_from.split('T')[0]} - ${profitData.date_to.split('T')[0]}`}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItemSubheader title='Penjualan' />
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Revenue'
|
|
|
|
|
amount={profitData.summary.total_revenue}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItemFooter title='Total Pendapatan' amount={profitData.summary.total_revenue} />
|
|
|
|
|
<ReportItemSubheader title='' />
|
|
|
|
|
|
|
|
|
|
<ReportItemHeader
|
|
|
|
|
title='Beban Pokok Penjualan'
|
|
|
|
|
date={`${profitData.date_from.split('T')[0]} - ${profitData.date_to.split('T')[0]}`}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Cost of Goods Sold'
|
|
|
|
|
amount={profitData.summary.total_cost}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItemFooter title='Total Beban Pokok Penjualan' amount={profitData.summary.total_cost} />
|
|
|
|
|
<ReportItemSubheader title='' />
|
|
|
|
|
|
|
|
|
|
<ReportItemHeader title='Laba Kotor' amount={profitData.summary.gross_profit} />
|
|
|
|
|
<ReportItemSubheader title='' />
|
|
|
|
|
|
|
|
|
|
{/* Daily Data Breakdown Section */}
|
|
|
|
|
{profitData.data && profitData.data.length > 0 && (
|
|
|
|
|
<>
|
|
|
|
|
<ReportItemHeader
|
|
|
|
|
title='Rincian Data Harian'
|
|
|
|
|
date={`${profitData.date_from.split('T')[0]} - ${profitData.date_to.split('T')[0]}`}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItemSubheader title='Breakdown per Hari' />
|
|
|
|
|
|
|
|
|
|
{profitData.data.map((dailyData, index) => (
|
|
|
|
|
<div key={index} className='mb-4'>
|
|
|
|
|
<ReportItemSubheader title={`Data ${formatDisplayDate(dailyData.date)}`} />
|
|
|
|
|
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Revenue Harian'
|
|
|
|
|
amount={dailyData.revenue}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItem accountCode='' accountName='Cost Harian' amount={dailyData.cost} onClick={() => {}} />
|
|
|
|
|
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Gross Profit Harian'
|
|
|
|
|
amount={dailyData.gross_profit}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItem accountCode='' accountName='Tax Harian' amount={dailyData.tax} onClick={() => {}} />
|
|
|
|
|
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Discount Harian'
|
|
|
|
|
amount={dailyData.discount}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Orders Harian'
|
|
|
|
|
amount={dailyData.orders}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItemFooter
|
|
|
|
|
title={`Net Profit ${formatDisplayDate(dailyData.date)}`}
|
|
|
|
|
amount={dailyData.net_profit}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
<ReportItemSubheader title='' />
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Operational Costs Section */}
|
|
|
|
|
<ReportItemHeader
|
|
|
|
|
title='Biaya Operasional'
|
|
|
|
|
date={`${profitData.date_from.split('T')[0]} - ${profitData.date_to.split('T')[0]}`}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItemSubheader title='Biaya Operasional' />
|
|
|
|
|
|
|
|
|
|
<ReportItem accountCode='' accountName='Tax' amount={profitData.summary.total_tax} onClick={() => {}} />
|
|
|
|
|
<ReportItem
|
|
|
|
|
accountCode=''
|
|
|
|
|
accountName='Discount'
|
|
|
|
|
amount={profitData.summary.total_discount}
|
|
|
|
|
onClick={() => {}}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<ReportItemFooter
|
|
|
|
|
title='Total Biaya Operasional'
|
|
|
|
|
amount={profitData.summary.total_tax + profitData.summary.total_discount}
|
|
|
|
|
/>
|
|
|
|
|
<ReportItemSubheader title='' />
|
|
|
|
|
|
|
|
|
|
<ReportItemHeader title='Laba Bersih' amount={profitData.summary.net_profit} />
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<Box display='flex' justifyContent='center' alignItems='center' minHeight={200}>
|
|
|
|
|
<span>No data available</span>
|
|
|
|
|
</Box>
|
|
|
|
|
)}
|
2025-09-11 18:20:40 +07:00
|
|
|
</CardContent>
|
|
|
|
|
</Card>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default ReportProfitLossContent
|