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 { useEffect, useState } from 'react';
4import Image from 'next/image';
5import { useStore } from '@/contexts/StoreContext';
6
7interface CartItem {
8 id: number;
9 name: string;
10 price: number;
11 quantity: number;
12}
13
14interface DisplayData {
15 type: 'cart-update' | 'clear';
16 cart?: CartItem[];
17 total?: number;
18 subtotal?: number;
19 tax?: number;
20 customer?: { name: string } | null;
21}
22
23export default function CustomerDisplayPage() {
24 const { storeName, session } = useStore();
25 const [cart, setCart] = useState<CartItem[]>([]);
26 const [total, setTotal] = useState(0);
27 const [subtotal, setSubtotal] = useState(0);
28 const [tax, setTax] = useState(0);
29 const [customer, setCustomer] = useState<{ name: string } | null>(null);
30 const [connected, setConnected] = useState(false);
31
32 const displayStoreName = storeName || session?.store?.name || 'Cartridge World';
33
34 useEffect(() => {
35 // Check if BroadcastChannel is supported
36 if (typeof BroadcastChannel === 'undefined') {
37 console.error('BroadcastChannel not supported');
38 return;
39 }
40
41 const channel = new BroadcastChannel('pos-display');
42 setConnected(true);
43
44 channel.onmessage = (event: MessageEvent<DisplayData>) => {
45 const data = event.data;
46
47 if (data.type === 'cart-update') {
48 setCart(data.cart || []);
49 setTotal(data.total || 0);
50 setSubtotal(data.subtotal || 0);
51 setTax(data.tax || 0);
52 setCustomer(data.customer || null);
53 } else if (data.type === 'clear') {
54 setCart([]);
55 setTotal(0);
56 setSubtotal(0);
57 setTax(0);
58 setCustomer(null);
59 }
60 };
61
62 // Send ready signal
63 channel.postMessage({ type: 'display-ready' });
64
65 return () => {
66 channel.close();
67 };
68 }, []);
69
70 return (
71 <div className="min-h-screen bg-bg p-8">
72 <div className="max-w-4xl mx-auto">
73 {/* Header */}
74 <div className="mb-8 text-center">
75 <h1 className="text-5xl font-bold text-text mb-4">{displayStoreName}</h1>
76 <div className="flex items-center justify-center gap-2">
77 <div className={`w-3 h-3 rounded-full ${connected ? 'bg-success' : 'bg-danger'}`} />
78 <span className="text-muted text-sm">
79 {connected ? 'Connected to POS' : 'Disconnected'}
80 </span>
81 </div>
82 </div>
83
84 {/* Customer Info */}
85 {customer && (
86 <div className="bg-info/10 border border-info/30 rounded-lg p-4 mb-6">
87 <p className="text-lg font-semibold text-info">Customer: {customer.name}</p>
88 </div>
89 )}
90
91 {/* Cart Items */}
92 <div className="bg-surface rounded-lg shadow-lg p-6 mb-6">
93 <h2 className="text-2xl font-bold text-text mb-4">Items</h2>
94
95 {cart.length === 0 ? (
96 <div className="text-center py-12">
97 <p className="text-muted text-xl">Waiting for items...</p>
98 </div>
99 ) : (
100 <div className="space-y-4">
101 {cart.map((item, index) => (
102 <div
103 key={`${item.id}-${index}`}
104 className="flex justify-between items-center py-4 border-b border-border last:border-0"
105 >
106 <div className="flex-1">
107 <p className="text-xl font-semibold text-text">{item.name}</p>
108 <p className="text-muted">Qty: {item.quantity}</p>
109 </div>
110 <div className="text-right">
111 <p className="text-2xl font-bold text-brand">
112 ${(item.price * item.quantity).toFixed(2)}
113 </p>
114 <p className="text-sm text-muted">
115 ${item.price.toFixed(2)} each
116 </p>
117 </div>
118 </div>
119 ))}
120 </div>
121 )}
122 </div>
123
124 {/* Total */}
125 {cart.length > 0 && (
126 <div className="bg-surface rounded-lg shadow-lg p-6">
127 <div className="space-y-3">
128 <div className="flex justify-between text-lg">
129 <span className="text-muted">Subtotal:</span>
130 <span className="font-semibold text-text">${subtotal.toFixed(2)}</span>
131 </div>
132 <div className="flex justify-between text-lg">
133 <span className="text-muted">Tax:</span>
134 <span className="font-semibold text-text">${tax.toFixed(2)}</span>
135 </div>
136 <div className="border-t border-border pt-3">
137 <div className="flex justify-between items-center">
138 <span className="text-2xl font-bold text-text">Total:</span>
139 <span className="text-4xl font-bold text-brand">${total.toFixed(2)}</span>
140 </div>
141 </div>
142 </div>
143 </div>
144 )}
145 </div>
146 </div>
147 );
148}