diff --git a/src/app/(main)/report/SemiFGProductionAnalysisReport.tsx b/src/app/(main)/report/SemiFGProductionAnalysisReport.tsx index 84e55bb..1bc9116 100644 --- a/src/app/(main)/report/SemiFGProductionAnalysisReport.tsx +++ b/src/app/(main)/report/SemiFGProductionAnalysisReport.tsx @@ -32,6 +32,7 @@ interface SemiFGProductionAnalysisReportProps { loading: boolean; setLoading: (loading: boolean) => void; reportTitle?: string; + onExportSuccess?: (format: "pdf" | "excel") => void; } export default function SemiFGProductionAnalysisReport({ @@ -40,6 +41,7 @@ export default function SemiFGProductionAnalysisReport({ loading, setLoading, reportTitle = '成品/半成品生產分析報告', + onExportSuccess, }: SemiFGProductionAnalysisReportProps) { const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [selectedItemCodesInfo, setSelectedItemCodesInfo] = useState([]); @@ -101,6 +103,7 @@ export default function SemiFGProductionAnalysisReport({ } else { await generateSemiFGProductionAnalysisReport(criteria, reportTitle); } + onExportSuccess?.(format); setShowConfirmDialog(false); } catch (error) { console.error('Failed to generate report:', error); diff --git a/src/app/(main)/report/page.tsx b/src/app/(main)/report/page.tsx index 1cc9985..5c01e36 100644 --- a/src/app/(main)/report/page.tsx +++ b/src/app/(main)/report/page.tsx @@ -27,6 +27,11 @@ import { fetchSemiFGItemCodesWithCategory } from './semiFGProductionAnalysisApi'; import { generateGrnReportExcel } from './grnReportApi'; +import { + FEATURE_USAGE, + FEATURE_USAGE_ACTION, + logFeatureUsage, +} from '@/lib/featureUsageLog'; interface ItemCodeWithName { code: string; @@ -138,6 +143,10 @@ export default function ReportPage() { setDynamicOptions({}); }, [selectedReportId]); + useEffect(() => { + logFeatureUsage(FEATURE_USAGE.REPORT_MANAGEMENT, FEATURE_USAGE_ACTION.PAGE_VIEW); + }, []); + const validateRequiredFields = () => { if (!currentReport) return true; @@ -220,6 +229,13 @@ export default function ReportPage() { link.remove(); window.URL.revokeObjectURL(downloadUrl); } + if (currentReport) { + logFeatureUsage( + FEATURE_USAGE.REPORT_MANAGEMENT, + FEATURE_USAGE_ACTION.DOWNLOAD, + `${currentReport.id}:excel`, + ); + } setShowConfirmDialog(false); } catch (error) { console.error("Failed to generate Excel report:", error); @@ -265,6 +281,12 @@ export default function ReportPage() { link.click(); link.remove(); window.URL.revokeObjectURL(downloadUrl); + + logFeatureUsage( + FEATURE_USAGE.REPORT_MANAGEMENT, + FEATURE_USAGE_ACTION.DOWNLOAD, + `${currentReport.id}:pdf`, + ); setShowConfirmDialog(false); } catch (error) { @@ -503,6 +525,13 @@ export default function ReportPage() { loading={loading} setLoading={setLoading} reportTitle={currentReport.title} + onExportSuccess={(format) => { + logFeatureUsage( + FEATURE_USAGE.REPORT_MANAGEMENT, + FEATURE_USAGE_ACTION.DOWNLOAD, + `${currentReport.id}:${format}`, + ); + }} /> ) : currentReport.id === 'rep-013' || currentReport.id === 'rep-009' || currentReport.id === 'rep-012' || currentReport.id === 'rep-004' || currentReport.id === 'rep-007' || currentReport.id === 'rep-008' || currentReport.id === 'rep-011' ? ( <> diff --git a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx index 475ccc9..6c1e291 100644 --- a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx +++ b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx @@ -45,6 +45,11 @@ import TruckRoutingSummaryTab, { TruckRoutingSummaryFilters } from "./TruckRouti import { clientAuthFetch } from "@/app/utils/clientAuthFetch"; import { NEXT_PUBLIC_API_URL } from "@/config/api"; import { fetchTruckRoutingSummaryPrecheck } from "@/app/(main)/report/truckRoutingSummaryApi"; +import { + FEATURE_USAGE, + FEATURE_USAGE_ACTION, + logFeatureUsage, +} from "@/lib/featureUsageLog"; interface Props { // pickOrders: PickOrderResult[]; @@ -350,6 +355,11 @@ const [selectedPrinterForDraft, setSelectedPrinterForDraft] = useState { + if (tabIndex === 5) { + logFeatureUsage(FEATURE_USAGE.TRUCK_ROUTING_SUMMARY, FEATURE_USAGE_ACTION.PAGE_VIEW); + } + }, [tabIndex]); + useEffect(() => { const onAssigned = () => { localStorage.removeItem('hideCompletedUntilNext'); diff --git a/src/components/FinishedGoodSearch/TruckRoutingSummaryTab.tsx b/src/components/FinishedGoodSearch/TruckRoutingSummaryTab.tsx index 2a7512d..14de613 100644 --- a/src/components/FinishedGoodSearch/TruckRoutingSummaryTab.tsx +++ b/src/components/FinishedGoodSearch/TruckRoutingSummaryTab.tsx @@ -11,6 +11,11 @@ import { fetchTruckRoutingSummaryPrecheck, ReportOption, } from "@/app/(main)/report/truckRoutingSummaryApi"; +import { + FEATURE_USAGE, + FEATURE_USAGE_ACTION, + logFeatureUsage, +} from "@/lib/featureUsageLog"; export type TruckRoutingSummaryFilters = { storeId: string; @@ -94,6 +99,11 @@ const TruckRoutingSummaryTab: React.FC = ({ onFiltersChange }) => { link.click(); link.remove(); window.URL.revokeObjectURL(downloadUrl); + logFeatureUsage( + FEATURE_USAGE.TRUCK_ROUTING_SUMMARY, + FEATURE_USAGE_ACTION.DOWNLOAD, + `pdf:${storeId}:${truckLanceCode}:${date}`, + ); } catch (error) { console.error("Failed to download Truck Routing Summary", error); alert("下載送貨路線摘要失敗,請稍後再試。"); diff --git a/src/i18n/en/dashboard.json b/src/i18n/en/dashboard.json index 914459f..f2ad726 100644 --- a/src/i18n/en/dashboard.json +++ b/src/i18n/en/dashboard.json @@ -111,5 +111,15 @@ "Show Supplier Code": "Show Supplier Code", "Show Purchase Order Codes": "Show Purchase Order Codes", "x/y orders received": "x/y orders received", - "Goods Receipt Status New": "Goods Receipt Status" + "Goods Receipt Status New": "Goods Receipt Status", + "Usage statistics": "Usage statistics", + "Usage stats description": "Report management and truck routing summary: page views, downloads, and direct prints.", + "Usage stats report section": "Report management (報告管理)", + "Usage stats truck routing section": "Truck routing summary (送貨路線摘要)", + "Usage stats user": "User", + "Usage stats page views": "Page views", + "Usage stats downloads": "Downloads", + "Usage stats prints": "Direct prints", + "Usage stats refresh": "Refresh", + "Usage stats load error": "Could not load usage statistics." } diff --git a/src/i18n/zh/dashboard.json b/src/i18n/zh/dashboard.json index 467d99e..2e67797 100644 --- a/src/i18n/zh/dashboard.json +++ b/src/i18n/zh/dashboard.json @@ -119,5 +119,15 @@ "Auto-refresh every 5 minutes": "每5分鐘自動刷新", "Auto-refresh every 10 minutes": "每10分鐘自動刷新", "Auto-refresh every 15 minutes": "每15分鐘自動刷新", - "Auto-refresh every 1 minute": "每1分鐘自動刷新" + "Auto-refresh every 1 minute": "每1分鐘自動刷新", + "Usage statistics": "報告管理與送貨路線摘要使用統計", + "Usage stats description": "報告管理與送貨路線摘要:進入頁面次數、下載與直接列印次數。", + "Usage stats report section": "報告管理", + "Usage stats truck routing section": "送貨路線摘要", + "Usage stats user": "使用者", + "Usage stats page views": "進入頁面次數", + "Usage stats downloads": "下載次數", + "Usage stats prints": "直接列印次數", + "Usage stats refresh": "重新整理", + "Usage stats load error": "無法載入使用統計。" }