diff --git a/src/components/PurchaseOrderTracking.tsx b/src/components/PurchaseOrderTracking.tsx
index ecb4ab0..23e7ec9 100644
--- a/src/components/PurchaseOrderTracking.tsx
+++ b/src/components/PurchaseOrderTracking.tsx
@@ -2,6 +2,7 @@ import { useState, useEffect, useMemo } from 'react'
import { usePurchaseOrdersCrud } from '@/hooks/use-purchase-orders-crud'
import { useInvoicesCrud } from '@/hooks/use-invoices-crud'
import { useTranslation } from '@/hooks/use-translation'
+import { useDataExport } from '@/hooks/use-data-export'
import {
FileText,
Plus,
@@ -18,7 +19,8 @@ import {
Trash,
PencilSimple,
Eye,
- X
+ X,
+ Download
} from '@phosphor-icons/react'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
@@ -37,6 +39,7 @@ export function PurchaseOrderTracking() {
const { t } = useTranslation()
const { entities: purchaseOrders, create, update, remove } = usePurchaseOrdersCrud()
const { invoices } = useInvoicesCrud()
+ const { exportToCSV, exportToExcel } = useDataExport()
const [searchQuery, setSearchQuery] = useState('')
const [isCreateOpen, setIsCreateOpen] = useState(false)
const [isDetailOpen, setIsDetailOpen] = useState(false)
@@ -297,6 +300,30 @@ export function PurchaseOrderTracking() {
)
}, [invoices, selectedPO])
+ const handleExportPOs = () => {
+ try {
+ const exportData = filteredPOs.map(po => ({
+ 'PO Number': po.poNumber,
+ 'Client': po.clientName,
+ 'Status': po.status,
+ 'Issue Date': new Date(po.issueDate).toLocaleDateString(),
+ 'Expiry Date': po.expiryDate ? new Date(po.expiryDate).toLocaleDateString() : 'N/A',
+ 'Currency': po.currency,
+ 'Total Value': po.totalValue,
+ 'Utilised Value': po.utilisedValue,
+ 'Remaining Value': po.remainingValue,
+ 'Utilization %': ((po.utilisedValue / po.totalValue) * 100).toFixed(2),
+ 'Linked Invoices': po.linkedInvoices.length,
+ 'Created By': po.createdBy,
+ 'Created Date': new Date(po.createdDate).toLocaleDateString()
+ }))
+ exportToExcel(exportData, { filename: `purchase-orders-${new Date().toISOString().split('T')[0]}` })
+ toast.success(t('purchaseOrders.messages.exportSuccess') || 'Purchase orders exported successfully')
+ } catch (error) {
+ toast.error(t('purchaseOrders.messages.exportError') || 'Failed to export purchase orders')
+ }
+ }
+
if (isLoadingState) {
return (
@@ -315,10 +342,16 @@ export function PurchaseOrderTracking() {
{t('purchaseOrders.title')}
{t('purchaseOrders.subtitle')}
-
+
+
+
+
diff --git a/src/components/ReportsView.tsx b/src/components/ReportsView.tsx
index 87f7a79..d97bced 100644
--- a/src/components/ReportsView.tsx
+++ b/src/components/ReportsView.tsx
@@ -18,8 +18,10 @@ import {
import { useInvoicesCrud } from '@/hooks/use-invoices-crud'
import { usePayrollCrud } from '@/hooks/use-payroll-crud'
import { useTranslation } from '@/hooks/use-translation'
+import { useDataExport } from '@/hooks/use-data-export'
import type { MarginAnalysis, ForecastData } from '@/lib/types'
import { cn } from '@/lib/utils'
+import { toast } from 'sonner'
export function ReportsView() {
const [selectedPeriod, setSelectedPeriod] = useState<'week' | 'month' | 'quarter' | 'year'>('month')
@@ -28,6 +30,7 @@ export function ReportsView() {
const { invoices } = useInvoicesCrud()
const { payrollRuns } = usePayrollCrud()
+ const { exportToCSV, exportToExcel } = useDataExport()
const calculateMarginAnalysis = (): MarginAnalysis[] => {
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
@@ -111,6 +114,71 @@ export function ReportsView() {
...forecast.map(f => Math.max(f.predictedRevenue, f.predictedCosts))
)
+ const handleExportMarginAnalysis = () => {
+ try {
+ const exportData = marginAnalysis.map(item => ({
+ Period: item.period,
+ Year: selectedYear,
+ Revenue: item.revenue,
+ Costs: item.costs,
+ Margin: item.margin,
+ 'Margin %': item.marginPercentage.toFixed(2)
+ }))
+ exportToCSV(exportData, { filename: `margin-analysis-${selectedYear}` })
+ toast.success(t('reports.exportSuccess') || 'Margin analysis exported successfully')
+ } catch (error) {
+ toast.error(t('reports.exportError') || 'Failed to export margin analysis')
+ }
+ }
+
+ const handleExportForecast = () => {
+ try {
+ const exportData = forecast.map(item => ({
+ Period: item.period,
+ Year: selectedYear,
+ 'Predicted Revenue': item.predictedRevenue,
+ 'Predicted Costs': item.predictedCosts,
+ 'Predicted Margin': item.predictedMargin,
+ 'Confidence %': item.confidence
+ }))
+ exportToCSV(exportData, { filename: `forecast-${selectedYear}` })
+ toast.success(t('reports.exportSuccess') || 'Forecast data exported successfully')
+ } catch (error) {
+ toast.error(t('reports.exportError') || 'Failed to export forecast data')
+ }
+ }
+
+ const handleExportAll = () => {
+ try {
+ const combinedData = [
+ ...marginAnalysis.map(item => ({
+ Type: 'Actual',
+ Period: item.period,
+ Year: selectedYear,
+ Revenue: item.revenue,
+ Costs: item.costs,
+ Margin: item.margin,
+ 'Margin %': item.marginPercentage.toFixed(2),
+ Confidence: 100
+ })),
+ ...forecast.map(item => ({
+ Type: 'Forecast',
+ Period: item.period,
+ Year: selectedYear,
+ Revenue: item.predictedRevenue,
+ Costs: item.predictedCosts,
+ Margin: item.predictedMargin,
+ 'Margin %': ((item.predictedMargin / item.predictedRevenue) * 100).toFixed(2),
+ Confidence: item.confidence
+ }))
+ ]
+ exportToExcel(combinedData, { filename: `financial-report-${selectedYear}` })
+ toast.success(t('reports.exportSuccess') || 'Complete report exported successfully')
+ } catch (error) {
+ toast.error(t('reports.exportError') || 'Failed to export complete report')
+ }
+ }
+
return (
@@ -130,7 +198,7 @@ export function ReportsView() {
2023
-