EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
page.tsx
Go to the documentation of this file.
1"use client";
2
3import { useState, useEffect, Suspense } from "react";
4import { useSearchParams } from "next/navigation";
5import { Icon } from '@/contexts/IconContext';
6
7type TabId = "advisor" | "sales" | "inventory" | "customers" | "financial" | "staff" | "operational";
8
9function ReportsPageContent() {
10 const searchParams = useSearchParams();
11 const source = searchParams.get('source');
12
13 const [activeTab, setActiveTab] = useState<TabId>(() => {
14 return source === 'advisor' ? 'advisor' : 'sales';
15 });
16
17 // Update active tab when source parameter changes
18 useEffect(() => {
19 if (source === 'advisor') {
20 setActiveTab('advisor');
21 }
22 }, [source]);
23
24 const tabs = [
25 { id: "advisor" as TabId, label: "Advisor Reports", icon: "lightbulb" },
26 { id: "sales" as TabId, label: "Sales Reports", icon: "trending_up" },
27 { id: "inventory" as TabId, label: "Inventory", icon: "inventory_2" },
28 { id: "customers" as TabId, label: "Customers", icon: "people" },
29 { id: "financial" as TabId, label: "Financial", icon: "account_balance" },
30 { id: "staff" as TabId, label: "Staff Performance", icon: "badge" },
31 { id: "operational" as TabId, label: "Operational", icon: "settings" },
32 ];
33
34 return (
35 <div className="p-6 min-h-screen bg-bg">
36 <div className="mb-6">
37 <h1 className="text-3xl font-bold text-text mb-2 flex items-center gap-2">
38 <Icon name="assessment" size={32} className="text-brand" />
39 Business Reports
40 </h1>
41 <p className="text-muted">Comprehensive reporting across all business functions</p>
42 </div>
43
44 {/* Tabs */}
45 <div className="bg-surface rounded-lg shadow-sm mb-6">
46 <div className="border-b border-border">
47 <nav className="flex space-x-2 p-2 overflow-x-auto">
48 {tabs.map((tab) => (
49 <button
50 key={tab.id}
51 onClick={() => setActiveTab(tab.id)}
52 className={`flex items-center gap-2 px-4 py-3 rounded-lg whitespace-nowrap transition ${
53 activeTab === tab.id
54 ? "bg-brand text-surface font-semibold"
55 : "text-muted hover:bg-surface-2"
56 }`}
57 >
58 <Icon name={tab.icon} className="text-xl" />
59 <span>{tab.label}</span>
60 </button>
61 ))}
62 </nav>
63 </div>
64
65 {/* Tab Content */}
66 <div className="p-6">
67 {activeTab === "advisor" && <AdvisorReports />}
68 {activeTab === "sales" && <SalesReports />}
69 {activeTab === "inventory" && <InventoryReports />}
70 {activeTab === "customers" && <CustomerReports />}
71 {activeTab === "financial" && <FinancialReports />}
72 {activeTab === "staff" && <StaffReports />}
73 {activeTab === "operational" && <OperationalReports />}
74 </div>
75 </div>
76 </div>
77 );
78}
79
80function AdvisorReports() {
81 const reports = [
82 { name: "Possible Duplicate Customers", desc: "Identify potential duplicate customer records", path: "/pages/reports/advisor/duplicate-customers" },
83 { name: "Products Priced Low", desc: "Products with pricing below cost or threshold", path: "/pages/reports/advisor/products-priced-low" },
84 { name: "Duplicate PLU Codes", desc: "Products with identical PLU numbers", path: "/pages/reports/advisor/duplicate-plu" },
85 { name: "Duplicate Product Descriptions", desc: "Products with identical descriptions", path: "/pages/reports/advisor/duplicate-descriptions" },
86 { name: "Spelling Issues", desc: "Potential spelling errors in product names", path: "/pages/reports/advisor/spelling-issues" },
87 { name: "Missing Product Information", desc: "Products with incomplete details", path: "/pages/reports/advisor/missing-info" },
88 { name: "Inactive Products", desc: "Products with no recent sales activity", path: "/pages/reports/advisor/inactive-products" },
89 { name: "Stock Level Issues", desc: "Products with incorrect or negative stock", path: "/pages/reports/advisor/stock-issues" },
90 { name: "Customer Data Quality", desc: "Customers with missing or invalid information", path: "/pages/reports/advisor/customer-data-quality" },
91 { name: "Price Inconsistencies", desc: "Products with unusual price variations", path: "/pages/products/price-changes" },
92 { name: "Supplier Data Issues", desc: "Suppliers with missing or outdated information", path: "/pages/reports/advisor/supplier-issues" },
93 { name: "Security Recommendations", desc: "System security and access suggestions", path: "/pages/reports/advisor/security-recommendations" },
94 ];
95
96 return (
97 <div>
98 <div className="mb-6">
99 <div className="flex items-center gap-3 mb-3">
100 <Icon name="lightbulb" size={24} className="text-warning" />
101 <h2 className="text-2xl font-bold text-text">Advisor Reports</h2>
102 </div>
103 <p className="text-muted">
104 Automated insights and recommendations from your business data. These reports are generated
105 by the Advisor system which continuously analyzes your data for potential issues,
106 inconsistencies, and opportunities for improvement.
107 </p>
108 </div>
109
110 <div className="bg-info/10 border border-info/30 rounded-lg p-4 mb-6">
111 <div className="flex items-start gap-3">
112 <Icon name="info" size={20} className="text-info flex-shrink-0 mt-0.5" />
113 <div>
114 <p className="text-sm text-text mb-2">
115 <strong>From Advisor Page:</strong> Click on any report below to view detailed information.
116 To customize which categories are analyzed, visit the{' '}
117 <a href="/advisor" className="text-brand hover:underline">
118 Advisor page
119 </a>.
120 </p>
121 <p className="text-sm text-muted">
122 The Advisor continuously monitors your business data across products, customers,
123 inventory, and operations to help you maintain data quality and identify issues early.
124 </p>
125 </div>
126 </div>
127 </div>
128
129 <ReportGrid reports={reports} />
130 </div>
131 );
132}
133
134function SalesReports() {
135 const reports = [
136 { name: "Daily Sales Summary", desc: "Sales totals by day with trends", path: "/pages/reports/sales-reports" },
137 { name: "Sales by Store", desc: "Compare performance across locations", path: "/pages/reports/sales-reports/sales-by-store" },
138 { name: "Sales by Product", desc: "Top selling products and categories", path: "/pages/reports/sales-reports" },
139 { name: "Sales by Staff Member", desc: "Individual staff performance", path: "/pages/reports/sales-reports/sales-by-teller" },
140 { name: "Sales with Discounts", desc: "Analyze discount usage and impact", path: "/pages/reports/sales-reports/sales-with-discounts" },
141 { name: "Hourly Sales Analysis", desc: "Peak trading hours identification", path: "/pages/reports/sales-reports" },
142 { name: "Sales by Payment Type", desc: "Payment method breakdown", path: "/pages/reports/sales-reports/payment-list" },
143 { name: "Basket Size Analysis", desc: "Average transaction values", path: "/pages/reports/sales-reports/basket-sizes" },
144 { name: "Sales KPI Dashboard", desc: "Key performance indicators", path: "/pages/reports/sales-reports/sales-kpi" },
145 { name: "Lost Sales Report", desc: "Track refused or cancelled sales", path: "/pages/reports/sales-reports/lost-sales" },
146 ];
147
148 return <ReportGrid reports={reports} />;
149}
150
151function InventoryReports() {
152 const reports = [
153 { name: "Stock Levels Overview", desc: "Current stock across all locations", path: "/pages/products" },
154 { name: "Low Stock Alert", desc: "Items below reorder point", path: "/pages/products" },
155 { name: "Stock Movement", desc: "Product velocity and turnover", path: "/pages/products" },
156 { name: "Dead Stock Analysis", desc: "Slow-moving and obsolete items", path: "/pages/products" },
157 { name: "Shrinkage Report", desc: "Stock loss and discrepancies", path: "/pages/products/stocktake" },
158 { name: "Reorder Recommendations", desc: "Suggested purchase orders", path: "/purchase-orders" },
159 { name: "Stock Valuation", desc: "Total inventory value by location", path: "/pages/products" },
160 { name: "Supplier Performance", desc: "Delivery times and quality metrics", path: "/pages/suppliers" },
161 { name: "Price Changes History", desc: "Track pricing adjustments", path: "/pages/products/price-changes" },
162 ];
163
164 return <ReportGrid reports={reports} />;
165}
166
167function CustomerReports() {
168 const reports = [
169 { name: "Customer Database", desc: "Complete customer listing", path: "/pages/customers" },
170 { name: "Top Customers", desc: "Highest value customers by spend", path: "/pages/reports/sales-reports/sales-by-customer" },
171 { name: "Customer Lifetime Value", desc: "Long-term customer worth analysis", path: "/pages/customers" },
172 { name: "New vs Returning", desc: "Customer acquisition and retention", path: "/pages/customers" },
173 { name: "Loyalty Program Analysis", desc: "Points, rewards, and redemption", path: "/pages/customers/loyalty" },
174 { name: "Customer Segmentation", desc: "Group customers by behavior", path: "/pages/customers" },
175 { name: "Aged Debtors", desc: "Outstanding customer accounts", path: "/pages/customers/customer-accounts/aged-debtors" },
176 { name: "Customer Purchase History", desc: "Individual buying patterns", path: "/pages/customers" },
177 { name: "Lapsed Customers", desc: "Inactive customer identification", path: "/pages/customers" },
178 ];
179
180 return <ReportGrid reports={reports} />;
181}
182
183function FinancialReports() {
184 const reports = [
185 { name: "Daily Takings", desc: "Cash, card, and total receipts", path: "/pages/sales/end-of-day" },
186 { name: "Monthly P&L", desc: "Profit and loss statement", path: "/pages/reports/analytics" },
187 { name: "Gross Margin Analysis", desc: "Product and category profitability", path: "/pages/reports/analytics" },
188 { name: "GST/Tax Summary", desc: "Tax collected and payable", path: "/pages/reports/analytics" },
189 { name: "Account Sales", desc: "Credit account transactions", path: "/pages/reports/sales-reports/sales-by-account" },
190 { name: "Payment Reconciliation", desc: "Match payments to deposits", path: "/pages/reports/sales-reports/payment-list" },
191 { name: "Refunds & Returns", desc: "Track product returns", path: "/pages/reports/sales-reports" },
192 { name: "Franchise Royalties", desc: "Franchise fee calculations", path: "/pages/reports/franchise-report" },
193 { name: "Cost of Goods Sold", desc: "COGS by period", path: "/pages/reports/analytics" },
194 { name: "Banking Summary", desc: "Deposits and cash flow", path: "/pages/sales/end-of-day" },
195 ];
196
197 return <ReportGrid reports={reports} />;
198}
199
200function StaffReports() {
201 const reports = [
202 { name: "Sales by Staff Member", desc: "Individual performance metrics", path: "/pages/reports/sales-reports/sales-by-teller" },
203 { name: "Staff Hours Report", desc: "Time tracking and scheduling", path: "/pages/settings/staff" },
204 { name: "Staff Productivity", desc: "Sales per hour worked", path: "/pages/reports/sales-reports/sales-by-teller" },
205 { name: "Staff Activity Log", desc: "Login times and transactions", path: "/audit" },
206 { name: "Commission Report", desc: "Sales commission calculations", path: "/pages/reports/sales-reports/sales-by-teller" },
207 { name: "Void & Discount Analysis", desc: "Staff discount and void usage", path: "/pages/reports/sales-reports/sales-with-discounts" },
208 { name: "Training Compliance", desc: "Staff training status", path: "/pages/settings/staff" },
209 { name: "Performance Reviews", desc: "KPIs and targets", path: "/pages/settings/staff" },
210 ];
211
212 return <ReportGrid reports={reports} />;
213}
214
215function OperationalReports() {
216 const reports = [
217 { name: "System Health Monitor", desc: "Server and database status", path: "/pages/operations/monitoring" },
218 { name: "Transaction Log", desc: "Complete audit trail", path: "/audit" },
219 { name: "End of Day Reports", desc: "Daily closeout summaries", path: "/pages/sales/end-of-day" },
220 { name: "Till Reconciliation", desc: "Cash drawer accuracy", path: "/pages/sales/end-of-day" },
221 { name: "Sale Processing Errors", desc: "Failed or edited transactions", path: "/pages/reports/sales-reports/edited-sales" },
222 { name: "Gift Card Activity", desc: "Gift card sales and redemptions", path: "/prepay" },
223 { name: "Layby Report", desc: "Layby payments and completions", path: "/pages/reports/sales-reports/layby" },
224 { name: "Open Quotations", desc: "Pending customer quotes", path: "/pages/reports/sales-reports/open-quotations" },
225 { name: "Store Comparison", desc: "Multi-location performance", path: "/pages/reports/sales-reports/sales-by-store" },
226 { name: "API Usage Statistics", desc: "System integration activity", path: "/api" },
227 ];
228
229 return <ReportGrid reports={reports} />;
230}
231
232function ReportGrid({ reports }: { reports: Array<{ name: string; desc: string; path: string }> }) {
233 return (
234 <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
235 {reports.map((report, idx) => (
236 <a
237 key={idx}
238 href={report.path}
239 className="group relative block bg-gradient-to-br from-surface to-surface-2 border border-border rounded-xl p-5 hover:shadow-xl hover:scale-[1.02] hover:border-brand/50 hover:from-brand/5 hover:to-brand/10 transition-all duration-300 overflow-hidden"
240 >
241 <div className="absolute inset-0 bg-gradient-to-br from-brand/0 to-brand/0 group-hover:from-brand/5 group-hover:to-brand/10 transition-all duration-300"></div>
242 <div className="relative z-10">
243 <h3 className="text-lg font-semibold text-text mb-1 group-hover:text-brand transition-colors duration-200">
244 {report.name}
245 </h3>
246 <p className="text-sm text-muted">{report.desc}</p>
247 </div>
248 </a>
249 ))}
250 </div>
251 );
252}
253
254export default function ReportsPage() {
255 return (
256 <Suspense fallback={<div className="flex items-center justify-center min-h-screen">Loading...</div>}>
257 <ReportsPageContent />
258 </Suspense>
259 );
260}