EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
Charts.tsx
Go to the documentation of this file.
1'use client';
2
3import {
4 Chart as ChartJS,
5 CategoryScale,
6 LinearScale,
7 BarElement,
8 LineElement,
9 PointElement,
10 ArcElement,
11 Title,
12 Tooltip,
13 Legend,
14 TimeScale,
15} from 'chart.js';
16import { Bar, Line, Doughnut, Pie } from 'react-chartjs-2';
17
18// Register Chart.js components
19ChartJS.register(
20 CategoryScale,
21 LinearScale,
22 BarElement,
23 LineElement,
24 PointElement,
25 ArcElement,
26 Title,
27 Tooltip,
28 Legend,
29 TimeScale
30);
31
32interface SalesHourlyChartProps {
33 data?: Array<{ hour: string; sales: number; amount: number }>;
34}
35
36export function SalesHourlyChart({ data }: SalesHourlyChartProps) {
37 // Demo data if no data provided
38 const defaultData = [
39 { hour: '9am', sales: 0, amount: 0 },
40 { hour: '10am', sales: 0, amount: 0 },
41 { hour: '11am', sales: 0, amount: 0 },
42 { hour: '12pm', sales: 0, amount: 0 },
43 { hour: '1pm', sales: 0, amount: 0 },
44 { hour: '2pm', sales: 0, amount: 0 },
45 { hour: '3pm', sales: 0, amount: 0 },
46 { hour: '4pm', sales: 0, amount: 0 },
47 { hour: '5pm', sales: 0, amount: 0 },
48 { hour: '6pm', sales: 0, amount: 0 },
49 ];
50
51 const chartData = data && data.length > 0 ? data : defaultData;
52
53 const config = {
54 labels: chartData.map(item => item.hour),
55 datasets: [
56 {
57 label: 'Sales Count',
58 data: chartData.map(item => item.sales),
59 backgroundColor: 'rgba(34, 197, 94, 0.8)',
60 borderColor: 'rgba(34, 197, 94, 1)',
61 borderWidth: 1,
62 yAxisID: 'y',
63 },
64 {
65 label: 'Sales Amount ($)',
66 data: chartData.map(item => item.amount),
67 backgroundColor: 'rgba(59, 130, 246, 0.8)',
68 borderColor: 'rgba(59, 130, 246, 1)',
69 borderWidth: 1,
70 yAxisID: 'y1',
71 },
72 ],
73 };
74
75 const options = {
76 responsive: true,
77 plugins: {
78 legend: {
79 position: 'top' as const,
80 },
81 title: {
82 display: true,
83 text: 'Sales Activity by Hour',
84 },
85 },
86 scales: {
87 y: {
88 type: 'linear' as const,
89 display: true,
90 position: 'left' as const,
91 title: {
92 display: true,
93 text: 'Number of Sales',
94 },
95 },
96 y1: {
97 type: 'linear' as const,
98 display: true,
99 position: 'right' as const,
100 title: {
101 display: true,
102 text: 'Sales Amount ($)',
103 },
104 grid: {
105 drawOnChartArea: false,
106 },
107 },
108 },
109 };
110
111 return <Bar data={config} options={options} />;
112}
113
114interface PaymentMethodsChartProps {
115 data?: Array<{ method: string; amount: number; percentage: number }>;
116}
117
118export function PaymentMethodsChart({ data }: PaymentMethodsChartProps) {
119 const defaultData = [
120 { method: 'EFTPOS', amount: 1590, percentage: 65 },
121 { method: 'Cash', amount: 612, percentage: 25 },
122 { method: 'Mobile Pay', amount: 245, percentage: 10 },
123 ];
124
125 const chartData = data || defaultData;
126
127 const config = {
128 labels: chartData.map(item => `${item.method} (${item.percentage}%)`),
129 datasets: [
130 {
131 data: chartData.map(item => item.amount),
132 backgroundColor: [
133 'rgba(34, 197, 94, 0.8)',
134 'rgba(59, 130, 246, 0.8)',
135 'rgba(168, 85, 247, 0.8)',
136 'rgba(239, 68, 68, 0.8)',
137 'rgba(245, 158, 11, 0.8)',
138 ],
139 borderColor: [
140 'rgba(34, 197, 94, 1)',
141 'rgba(59, 130, 246, 1)',
142 'rgba(168, 85, 247, 1)',
143 'rgba(239, 68, 68, 1)',
144 'rgba(245, 158, 11, 1)',
145 ],
146 borderWidth: 1,
147 },
148 ],
149 };
150
151 const options = {
152 responsive: true,
153 plugins: {
154 legend: {
155 position: 'bottom' as const,
156 },
157 title: {
158 display: true,
159 text: 'Payment Methods Today',
160 },
161 },
162 };
163
164 return <Doughnut data={config} options={options} />;
165}
166
167interface TopProductsChartProps {
168 data?: Array<{ name: string; quantity: number; value: number }>;
169}
170
171export function TopProductsChart({ data }: TopProductsChartProps) {
172 const defaultData = [
173 { name: 'HP 65 Black Ink', quantity: 12, value: 551.88 },
174 { name: 'Canon PG-545 Black', quantity: 9, value: 350.91 },
175 { name: 'Brother TN-2430 Toner', quantity: 4, value: 359.96 },
176 { name: 'Epson 603XL Black', quantity: 7, value: 300.93 },
177 { name: 'Samsung MLT-D111S', quantity: 3, value: 197.97 },
178 ];
179
180 const chartData = data || defaultData;
181
182 const config = {
183 labels: chartData.map(item => item.name.length > 20 ? item.name.substring(0, 20) + '...' : item.name),
184 datasets: [
185 {
186 label: 'Quantity Sold',
187 data: chartData.map(item => item.quantity),
188 backgroundColor: 'rgba(34, 197, 94, 0.8)',
189 borderColor: 'rgba(34, 197, 94, 1)',
190 borderWidth: 1,
191 },
192 ],
193 };
194
195 const options = {
196 responsive: true,
197 indexAxis: 'y' as const,
198 plugins: {
199 legend: {
200 display: false,
201 },
202 title: {
203 display: true,
204 text: 'Top Selling Products',
205 },
206 },
207 scales: {
208 x: {
209 beginAtZero: true,
210 title: {
211 display: true,
212 text: 'Quantity Sold',
213 },
214 },
215 },
216 };
217
218 return <Bar data={config} options={options} />;
219}
220
221interface StorePerformanceChartProps {
222 data?: Array<{ store: string; sales: number; amount: number }>;
223}
224
225export function StorePerformanceChart({ data }: StorePerformanceChartProps) {
226 const defaultData = [
227 { store: 'Main Store', sales: 45, amount: 1890.50 },
228 { store: 'North Branch', sales: 32, amount: 1340.25 },
229 { store: 'East Store', sales: 28, amount: 1150.75 },
230 ];
231
232 const chartData = data || defaultData;
233
234 const config = {
235 labels: chartData.map(item => item.store),
236 datasets: [
237 {
238 label: 'Sales Amount ($)',
239 data: chartData.map(item => item.amount),
240 backgroundColor: 'rgba(59, 130, 246, 0.8)',
241 borderColor: 'rgba(59, 130, 246, 1)',
242 borderWidth: 1,
243 },
244 ],
245 };
246
247 const options = {
248 responsive: true,
249 plugins: {
250 legend: {
251 display: false,
252 },
253 title: {
254 display: true,
255 text: 'Store Performance Today',
256 },
257 },
258 scales: {
259 y: {
260 beginAtZero: true,
261 title: {
262 display: true,
263 text: 'Sales Amount ($)',
264 },
265 },
266 },
267 };
268
269 return <Bar data={config} options={options} />;
270}
271
272interface TellerPerformanceChartProps {
273 data?: Array<{ teller: string; sales: number; amount: number }>;
274}
275
276export function TellerPerformanceChart({ data }: TellerPerformanceChartProps) {
277 const defaultData = [
278 { teller: 'Admin', sales: 25, amount: 1250.50 },
279 { teller: 'Sarah', sales: 22, amount: 1100.75 },
280 { teller: 'Mike', sales: 18, amount: 890.25 },
281 { teller: 'Jenny', sales: 15, amount: 720.00 },
282 ];
283
284 const chartData = data || defaultData;
285
286 const config = {
287 labels: chartData.map(item => item.teller),
288 datasets: [
289 {
290 label: 'Number of Sales',
291 data: chartData.map(item => item.sales),
292 backgroundColor: 'rgba(168, 85, 247, 0.8)',
293 borderColor: 'rgba(168, 85, 247, 1)',
294 borderWidth: 1,
295 yAxisID: 'y',
296 },
297 {
298 label: 'Sales Amount ($)',
299 data: chartData.map(item => item.amount),
300 backgroundColor: 'rgba(34, 197, 94, 0.8)',
301 borderColor: 'rgba(34, 197, 94, 1)',
302 borderWidth: 1,
303 yAxisID: 'y1',
304 },
305 ],
306 };
307
308 const options = {
309 responsive: true,
310 plugins: {
311 legend: {
312 position: 'top' as const,
313 },
314 title: {
315 display: true,
316 text: 'Teller Performance Today',
317 },
318 },
319 scales: {
320 y: {
321 type: 'linear' as const,
322 display: true,
323 position: 'left' as const,
324 title: {
325 display: true,
326 text: 'Number of Sales',
327 },
328 },
329 y1: {
330 type: 'linear' as const,
331 display: true,
332 position: 'right' as const,
333 title: {
334 display: true,
335 text: 'Sales Amount ($)',
336 },
337 grid: {
338 drawOnChartArea: false,
339 },
340 },
341 },
342 };
343
344 return <Bar data={config} options={options} />;
345}
346
347interface SalesOverTimeChartProps {
348 data?: Array<{ time: string; sales: number }>;
349 timeframe?: 'hour' | 'day' | 'week' | 'month';
350}
351
352export function SalesOverTimeChart({ data, timeframe = 'hour' }: SalesOverTimeChartProps) {
353 const defaultData = {
354 hour: [
355 { time: '9:00', sales: 3 },
356 { time: '10:00', sales: 8 },
357 { time: '11:00', sales: 12 },
358 { time: '12:00', sales: 18 },
359 { time: '13:00', sales: 15 },
360 { time: '14:00', sales: 22 },
361 { time: '15:00', sales: 19 },
362 { time: '16:00', sales: 14 },
363 { time: '17:00', sales: 9 },
364 ],
365 day: [
366 { time: 'Mon', sales: 85 },
367 { time: 'Tue', sales: 92 },
368 { time: 'Wed', sales: 78 },
369 { time: 'Thu', sales: 105 },
370 { time: 'Fri', sales: 120 },
371 { time: 'Sat', sales: 95 },
372 { time: 'Sun', sales: 70 },
373 ],
374 week: [
375 { time: 'Week 1', sales: 650 },
376 { time: 'Week 2', sales: 720 },
377 { time: 'Week 3', sales: 580 },
378 { time: 'Week 4', sales: 690 },
379 ],
380 month: [
381 { time: 'Jan', sales: 2800 },
382 { time: 'Feb', sales: 3200 },
383 { time: 'Mar', sales: 2900 },
384 { time: 'Apr', sales: 3500 },
385 { time: 'May', sales: 3100 },
386 { time: 'Jun', sales: 2750 },
387 ],
388 };
389
390 const chartData = data || defaultData[timeframe] || defaultData.hour;
391
392 const config = {
393 labels: chartData.map(item => item.time),
394 datasets: [
395 {
396 label: 'Sales',
397 data: chartData.map(item => item.sales),
398 borderColor: 'rgba(34, 197, 94, 1)',
399 backgroundColor: 'rgba(34, 197, 94, 0.1)',
400 tension: 0.3,
401 fill: true,
402 },
403 ],
404 };
405
406 const options = {
407 responsive: true,
408 plugins: {
409 legend: {
410 display: false,
411 },
412 title: {
413 display: true,
414 text: `Sales Over Time (${timeframe})`,
415 },
416 },
417 scales: {
418 y: {
419 beginAtZero: true,
420 title: {
421 display: true,
422 text: 'Number of Sales',
423 },
424 },
425 },
426 };
427
428 return <Line data={config} options={options} />;
429}
430
431// Top Customers Chart
432interface TopCustomersChartProps {
433 data?: Array<{
434 customer: string;
435 sales: number;
436 amount: number;
437 }>;
438}
439
440export function TopCustomersChart({ data }: TopCustomersChartProps) {
441 // Default demo data if none provided
442 const defaultData = [
443 { customer: 'ABC Office Supplies', sales: 12, amount: 1450.75 },
444 { customer: 'City Print Services', sales: 8, amount: 980.50 },
445 { customer: 'Local Business Co', sales: 6, amount: 720.25 },
446 { customer: 'Quick Copy Shop', sales: 5, amount: 650.00 },
447 { customer: 'School District #42', sales: 4, amount: 480.75 }
448 ];
449
450 const chartData = data && data.length > 0 ? data : defaultData;
451
452 const config = {
453 labels: chartData.map(item => item.customer),
454 datasets: [
455 {
456 label: 'Sales Amount ($)',
457 data: chartData.map(item => item.amount),
458 backgroundColor: [
459 'rgba(59, 130, 246, 0.8)',
460 'rgba(16, 185, 129, 0.8)',
461 'rgba(245, 158, 11, 0.8)',
462 'rgba(239, 68, 68, 0.8)',
463 'rgba(139, 92, 246, 0.8)'
464 ],
465 borderColor: [
466 'rgba(59, 130, 246, 1)',
467 'rgba(16, 185, 129, 1)',
468 'rgba(245, 158, 11, 1)',
469 'rgba(239, 68, 68, 1)',
470 'rgba(139, 92, 246, 1)'
471 ],
472 borderWidth: 1,
473 },
474 ],
475 };
476
477 const options = {
478 responsive: true,
479 maintainAspectRatio: false,
480 plugins: {
481 legend: {
482 display: false,
483 },
484 tooltip: {
485 callbacks: {
486 label: function(context: any) {
487 const customer = chartData[context.dataIndex];
488 return [
489 `Sales: ${customer.sales}`,
490 `Amount: $${customer.amount.toFixed(2)}`
491 ];
492 },
493 },
494 },
495 },
496 scales: {
497 y: {
498 beginAtZero: true,
499 ticks: {
500 callback: function(value: any) {
501 return '$' + value;
502 },
503 },
504 title: {
505 display: true,
506 text: 'Sales Amount ($)',
507 },
508 },
509 x: {
510 ticks: {
511 maxRotation: 45,
512 minRotation: 45,
513 },
514 title: {
515 display: true,
516 text: 'Customer',
517 },
518 },
519 },
520 };
521
522 return <Bar data={config} options={options} />;
523}