3import React, { useState, useEffect } from 'react';
4import { Icon } from '@/contexts/IconContext';
6interface ProfileUsage {
12interface ToggleSwitchProps {
14 onChange: (checked: boolean) => void;
18const ToggleSwitch: React.FC<ToggleSwitchProps> = ({ checked, onChange, disabled = false }) => {
20 <label className="relative inline-block w-12 h-6">
24 onChange={(e) => onChange(e.target.checked)}
26 className="sr-only peer"
28 <span className={`absolute inset-0 rounded-full transition-colors duration-300 cursor-pointer
29 ${checked ? 'bg-brand' : 'bg-danger'}
30 ${disabled ? 'opacity-30 cursor-not-allowed' : ''}
31 peer-focus:ring-2 peer-focus:ring-brand`}>
32 <span className={`absolute left-1 top-1 w-4 h-4 bg-surface rounded-full transition-transform duration-300
33 ${checked ? 'translate-x-6' : 'translate-x-0'}`} />
39export default function CameraSettingsPage() {
40 const [profiles, setProfiles] = useState<ProfileUsage[]>([
41 { id: 0, name: 'No Profile', used: 0 },
42 { id: 1, name: 'Profile 1', used: 0 },
43 { id: 2, name: 'Profile 2', used: 0 },
44 { id: 3, name: 'Profile 3', used: 0 },
45 { id: 4, name: 'Profile 4', used: 0 },
46 { id: 5, name: 'Profile 5', used: 0 },
47 { id: 6, name: 'Profile 6', used: 0 },
48 { id: 7, name: 'Profile 7', used: 0 },
49 { id: 8, name: 'Profile 8', used: 0 },
52 // Settings state - all are simple toggles
53 const [photoFirstItem, setPhotoFirstItem] = useState<Record<number, boolean>>({});
54 const [photoLogin, setPhotoLogin] = useState<Record<number, boolean>>({});
55 const [photoSettle, setPhotoSettle] = useState<Record<number, boolean>>({});
62 const loadProfileUsage = () => {
63 // API call: /BUCK?3=retailmax.elink.lane.summary&100=profileuse
64 console.log('Loading profile usage...');
65 // Mock data - would update profiles state with actual lane counts
68 const loadSettings = () => {
69 // Load all settings for all profiles
70 console.log('Loading camera settings...');
71 // Would make multiple API calls to load each setting
74 const saveSetting = (settingName: string, profile: number, value: boolean) => {
75 const suffix = profile === -1 ? '' : `@p${profile}`;
76 const fullSettingName = `${settingName}${suffix}`;
78 // API call: /DATI with XML payload
80 <f8_s>retailmax.elink.config.basesetting.edit</f8_s>
82 <f100_s>${fullSettingName}</f100_s>
83 <f101_E>${value ? 1 : 0}</f101_E>
87 console.log(`Saving ${fullSettingName} = ${value}`);
88 console.log('XML:', xml);
91 const ProfileCell: React.FC<{ profile: number }> = ({ profile }) => {
93 return <div className="text-xs text-muted">Default</div>;
95 const p = profiles.find(pr => pr.id === profile);
97 <div className="text-center">
98 <div className="text-xs font-medium text-text">{p?.name}</div>
99 <div className="text-xs text-muted">{p?.used} lanes</div>
105 <div className="p-6 min-h-screen bg-bg">
107 <div className="mb-6">
108 <h1 className="text-3xl font-bold text-text mb-2 flex items-center gap-2">
109 <Icon name="camera_alt" size={32} />
112 <p className="text-muted">
113 Configure when cameras automatically capture photos
117 <div className="max-w-[1600px] mx-auto">
119 <div className="mb-6">
120 <h1 className="text-2xl font-bold text-text mb-2">Camera Settings</h1>
121 <p className="text-sm text-muted">
122 Configure when cameras should automatically capture photos
126 {/* Storage Warning */}
127 <div className="bg-warn/10 border border-warn/30 rounded-lg p-4 mb-6">
128 <div className="flex items-start">
129 <Icon name="warning" size={20} className="text-warn mt-0.5 mr-3 flex-shrink-0" />
131 <h3 className="text-sm font-semibold text-text mb-1">Storage Requirements</h3>
132 <p className="text-sm text-text">
133 Enabling photos can require large amounts of disk storage, especially in high volume environments.
134 Ensure adequate storage capacity is available before enabling these features.
140 {/* Profile 0 Notice */}
141 {profiles[0].used > 0 && (
142 <div className="bg-info/10 border border-info/30 rounded-lg p-4 mb-6">
143 <p className="text-sm text-info">
144 There are {profiles[0].used} lanes not assigned to a profile. They use the default settings.
149 {/* Settings Table */}
150 <div className="bg-surface rounded-lg shadow overflow-x-auto">
151 <table className="w-full">
153 <tr className="border-b border-border bg-surface-2">
154 <th className="text-left p-4 font-semibold text-text min-w-[200px]">Setting</th>
155 <th className="text-center p-4 font-medium text-muted min-w-[100px]">
156 <ProfileCell profile={-1} />
158 {[1, 2, 3, 4, 5, 6, 7, 8].map(p => (
159 <th key={p} className="text-center p-4 font-medium text-muted min-w-[100px]">
160 <ProfileCell profile={p} />
163 <th className="text-center p-4 font-medium text-muted min-w-[80px]">Version</th>
167 {/* Take Photo on first item sold */}
168 <tr className="border-b border-border">
169 <td className="p-4 font-medium text-text">Take Photo on First Item Sold</td>
170 {[-1, 1, 2, 3, 4, 5, 6, 7, 8].map(p => (
171 <td key={p} className="p-4 text-center">
172 <div className="flex justify-center">
174 checked={photoFirstItem[p] || false}
175 onChange={(checked) => {
176 setPhotoFirstItem({ ...photoFirstItem, [p]: checked });
177 saveSetting('SalePhotoFirstItem', p, checked);
183 <td className="p-4 text-center text-xs text-muted">P1926</td>
185 <tr className="border-b border-border">
186 <td colSpan={11} className="p-4 text-sm text-muted bg-surface-2">
187 Should a photo be captured when the first item is sold onto a new sale?
188 <p className="mt-2 text-text">
189 <strong>Example use case:</strong> One retailer enabled this photo option and removed login requirements for sales,
190 only requiring a login for more advanced options. They are a high volume environment, often with queues at the checkouts,
191 so staff welcomed the chance to speed up the process. The photos are available for the rare instances where they needed
192 to identify the staff member that processed a sale.
197 {/* Take Photo on staff login */}
198 <tr className="border-b border-border bg-surface">
199 <td className="p-4 font-medium text-text">Take Photo on Staff Login</td>
200 {[-1, 1, 2, 3, 4, 5, 6, 7, 8].map(p => (
201 <td key={p} className="p-4 text-center">
202 <div className="flex justify-center">
204 checked={photoLogin[p] || false}
205 onChange={(checked) => {
206 setPhotoLogin({ ...photoLogin, [p]: checked });
207 saveSetting('LoginPhoto', p, checked);
213 <td className="p-4 text-center text-xs text-muted">P1926</td>
215 <tr className="border-b border-border">
216 <td colSpan={11} className="p-4 text-sm text-muted bg-surface-2">
217 Should a photo be captured when a login is processed? This provides a visual record of who logged in at each terminal
218 and when, useful for security auditing and staff accountability.
222 {/* Take Photo on End of Day */}
223 <tr className="border-b border-border bg-surface">
224 <td className="p-4 font-medium text-text">Take Photo on End of Day</td>
225 {[-1, 1, 2, 3, 4, 5, 6, 7, 8].map(p => (
226 <td key={p} className="p-4 text-center">
227 <div className="flex justify-center">
229 checked={photoSettle[p] || false}
230 onChange={(checked) => {
231 setPhotoSettle({ ...photoSettle, [p]: checked });
232 saveSetting('SettlePhoto', p, checked);
238 <td className="p-4 text-center text-xs text-muted">P1926</td>
240 <tr className="border-b border-border">
241 <td colSpan={11} className="p-4 text-sm text-muted bg-surface-2">
242 Should a photo be captured when the EOD settlement screen is accessed? This creates a visual record of who performed
243 end-of-day procedures, which is useful for reconciliation and audit purposes.
251 <div className="mt-6 grid md:grid-cols-2 gap-6">
252 <div className="bg-info/10 border border-info/30 rounded-lg p-4">
253 <h3 className="text-sm font-semibold text-text mb-2">About Camera Photos</h3>
254 <ul className="text-sm text-text space-y-1">
255 <li>• Photos are captured using the device's camera (webcam, tablet camera, etc.)</li>
256 <li>• Images are stored on the local system and synced to the server</li>
257 <li>• Photos are linked to sales, logins, or EOD procedures for easy retrieval</li>
258 <li>• Ensure cameras are properly positioned to capture useful images</li>
262 <div className="bg-success/10 border border-success/30 rounded-lg p-4">
263 <h3 className="text-sm font-semibold text-text mb-2">Best Practices</h3>
264 <ul className="text-sm text-text space-y-1">
265 <li>• Test camera positioning before enabling in production</li>
266 <li>• Monitor disk usage regularly when photo capture is enabled</li>
267 <li>• Implement photo retention policies to manage storage</li>
268 <li>• Inform staff that photos are being captured for transparency</li>
273 {/* Privacy Notice */}
274 <div className="mt-6 bg-surface-2 border border-border rounded-lg p-4">
275 <h3 className="text-sm font-semibold text-text mb-2">Privacy Considerations</h3>
276 <p className="text-sm text-text">
277 Ensure your use of camera photos complies with local privacy laws and workplace policies.
278 Staff should be notified that photos may be captured during their work activities. Photos
279 captured are intended for security, audit, and operational purposes only.