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 React, { useState, useEffect } from 'react';
4import { Icon } from '@/contexts/IconContext';
5
6interface BusinessDetails {
7 companyName: string;
8 taxId: string;
9 companyPhone: string;
10 companyEmail: string;
11 companyAddress0: string;
12 companyAddress1: string;
13 companyAddress2: string;
14 catchAllReceiptMessage: string;
15 catchAllReceiptMessageAccount: string;
16 companyWeb: string;
17 internalGdsWeb: string;
18 logo: string;
19 countryCode: string;
20 locationDefaultRegion: string;
21}
22
23export default function YourDetailsPage() {
24 const [details, setDetails] = useState<BusinessDetails>({
25 companyName: '',
26 taxId: '',
27 companyPhone: '',
28 companyEmail: '',
29 companyAddress0: '',
30 companyAddress1: '',
31 companyAddress2: '',
32 catchAllReceiptMessage: '',
33 catchAllReceiptMessageAccount: '',
34 companyWeb: '',
35 internalGdsWeb: '',
36 logo: '',
37 countryCode: '',
38 locationDefaultRegion: '',
39 });
40
41 const [showCountryNotes, setShowCountryNotes] = useState(false);
42 const [showRegionCanada, setShowRegionCanada] = useState(false);
43
44 useEffect(() => {
45 loadData();
46 }, []);
47
48 const loadData = async () => {
49 try {
50 // Load business details from API
51 // Mock data for demonstration
52 console.log('Loading business details...');
53 } catch (error) {
54 console.error('Error loading business details:', error);
55 }
56 };
57
58 const saveSetting = (settingName: string, value: string) => {
59 console.log('Saving setting:', settingName, '=', value);
60
61 // API call to save setting
62 // DATI XML format:
63 // <DATI>
64 // <f8_s>retailmax.elink.config.basesetting.edit</f8_s>
65 // <f11_B>E</f11_B>
66 // <f100_s>{settingName}</f100_s>
67 // <f101_s>{value}</f101_s>
68 // <f112_E>1</f112_E>
69 // </DATI>
70 };
71
72 const handleChange = (field: keyof BusinessDetails, value: string) => {
73 setDetails(prev => ({ ...prev, [field]: value }));
74 };
75
76 const handleBlur = (settingName: string, value: string) => {
77 saveSetting(settingName, value);
78 };
79
80 const handleCountryChange = (value: string) => {
81 setDetails(prev => ({ ...prev, countryCode: value }));
82
83 // Show notes for Canada
84 if (value === '9001') {
85 setShowCountryNotes(true);
86 setShowRegionCanada(true);
87 } else {
88 setShowCountryNotes(false);
89 setShowRegionCanada(false);
90 }
91
92 saveSetting('CountryCode', value);
93 };
94
95 return (
96 <div className="min-h-screen bg-bg">
97 {/* Header */}
98 <div className="bg-brand text-white px-6 py-4 shadow-lg">
99 <div className="flex items-center gap-4">
100 <div className="text-sm">
101 <a href="/pages/settings" className="hover:underline">Settings</a>
102 <span className="mx-2">›</span>
103 <span>Your Business Details</span>
104 </div>
105 </div>
106 </div>
107
108 <div className="max-w-[1400px] mx-auto p-6">
109 {/* Page Title */}
110 <div className="mb-6">
111 <h1 className="text-3xl font-bold text-text mb-2 flex items-center gap-3">
112 <Icon name="business" size={32} />
113 Your Business Details
114 </h1>
115 </div>
116
117 {/* Main Content */}
118 <div className="bg-surface rounded-lg shadow-md p-6">
119 <h2 className="text-xl font-bold text-text mb-4">Common Information</h2>
120
121 <p className="text-text mb-4">
122 Supply the broad details about your business. This information is used in a number of customer facing areas,
123 so only enter information that is intended to be publically visible. For example, many of the details below
124 may be printed on your receipts.
125 </p>
126
127 <p className="text-sm text-muted mb-6 italic">
128 Information entered below applies to ALL stores, unless specifically overridden by a store.
129 </p>
130
131 <div className="space-y-8">
132 {/* Business Name */}
133 <div>
134 <label className="block text-sm font-semibold text-text mb-2">
135 Business Name
136 </label>
137 <input
138 type="text"
139 size={40}
140 value={details.companyName}
141 onChange={(e) => handleChange('companyName', e.target.value)}
142 onBlur={(e) => handleBlur('StoreSetup.CompanyName', e.target.value)}
143 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
144 />
145 </div>
146
147 {/* Tax Number */}
148 <div>
149 <label className="block text-sm font-semibold text-text mb-2">
150 Tax Number (GST, MwST, VAT etc)
151 </label>
152 <input
153 type="text"
154 size={40}
155 value={details.taxId}
156 onChange={(e) => handleChange('taxId', e.target.value)}
157 onBlur={(e) => handleBlur('StoreSetup.TaxId.0', e.target.value)}
158 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
159 />
160 </div>
161
162 {/* Company Phone */}
163 <div>
164 <label className="block text-sm font-semibold text-text mb-2">
165 Company Phone No.
166 </label>
167 <input
168 type="text"
169 size={40}
170 value={details.companyPhone}
171 onChange={(e) => handleChange('companyPhone', e.target.value)}
172 onBlur={(e) => handleBlur('StoreSetup.CompanyPhone', e.target.value)}
173 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
174 />
175 </div>
176
177 {/* Company Email */}
178 <div>
179 <label className="block text-sm font-semibold text-text mb-2">
180 Company Email
181 </label>
182 <input
183 type="email"
184 size={40}
185 value={details.companyEmail}
186 onChange={(e) => handleChange('companyEmail', e.target.value)}
187 onBlur={(e) => handleBlur('StoreSetup.CompanyEmail', e.target.value)}
188 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
189 />
190 </div>
191
192 {/* Company Address */}
193 <div>
194 <label className="block text-sm font-semibold text-text mb-2">
195 Company Address
196 </label>
197 <div className="space-y-2">
198 <input
199 type="text"
200 size={40}
201 value={details.companyAddress0}
202 onChange={(e) => handleChange('companyAddress0', e.target.value)}
203 onBlur={(e) => handleBlur('StoreSetup.CompanyAddress0', e.target.value)}
204 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
205 placeholder="Address Line 1"
206 />
207 <input
208 type="text"
209 size={40}
210 value={details.companyAddress1}
211 onChange={(e) => handleChange('companyAddress1', e.target.value)}
212 onBlur={(e) => handleBlur('StoreSetup.CompanyAddress1', e.target.value)}
213 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
214 placeholder="Address Line 2"
215 />
216 <input
217 type="text"
218 size={40}
219 value={details.companyAddress2}
220 onChange={(e) => handleChange('companyAddress2', e.target.value)}
221 onBlur={(e) => handleBlur('StoreSetup.CompanyAddress2', e.target.value)}
222 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
223 placeholder="Address Line 3"
224 />
225 </div>
226 </div>
227
228 {/* Invoice/Receipt Message */}
229 <div>
230 <label className="block text-sm font-semibold text-text mb-2">
231 Invoice/Receipt Message
232 </label>
233 <p className="text-xs text-muted mb-2">For all sales, unless specifically overridden for individual customer/account.</p>
234 <textarea
235 cols={40}
236 rows={4}
237 value={details.catchAllReceiptMessage}
238 onChange={(e) => handleChange('catchAllReceiptMessage', e.target.value)}
239 onBlur={(e) => handleBlur('CatchAllReceiptMessage', e.target.value)}
240 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
241 />
242 </div>
243
244 {/* Account Invoice/Receipt Message */}
245 <div>
246 <label className="block text-sm font-semibold text-text mb-2">
247 Account Invoice/Receipt Message
248 </label>
249 <p className="text-xs text-muted mb-2">For all sales that have an account</p>
250 <textarea
251 cols={40}
252 rows={4}
253 value={details.catchAllReceiptMessageAccount}
254 onChange={(e) => handleChange('catchAllReceiptMessageAccount', e.target.value)}
255 onBlur={(e) => handleBlur('CatchAllReceiptMessageAccount', e.target.value)}
256 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
257 />
258 </div>
259
260 {/* Company Website */}
261 <div>
262 <label className="block text-sm font-semibold text-text mb-2">
263 Company Website
264 </label>
265 <p className="text-xs text-muted mb-2">Potentially given to customers</p>
266 <input
267 type="text"
268 size={40}
269 value={details.companyWeb}
270 onChange={(e) => handleChange('companyWeb', e.target.value)}
271 onBlur={(e) => handleBlur('StoreSetup.CompanyWeb', e.target.value)}
272 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
273 placeholder="https://www.example.com"
274 />
275 </div>
276
277 {/* Internal Website */}
278 <div>
279 <label className="block text-sm font-semibold text-text mb-2">
280 Internal Website
281 </label>
282 <p className="text-xs text-muted mb-2">For internal use - what is the NAME this Fieldpine System can be reached on</p>
283 <input
284 type="text"
285 size={40}
286 value={details.internalGdsWeb}
287 onChange={(e) => handleChange('internalGdsWeb', e.target.value)}
288 onBlur={(e) => handleBlur('StoreSetup.InternalGdsWeb', e.target.value)}
289 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
290 />
291 </div>
292
293 {/* Company Logo */}
294 <div>
295 <label className="block text-sm font-semibold text-text mb-2">
296 Company Logo
297 </label>
298 <div className="flex gap-4 items-start">
299 <div className="flex-1 max-w-2xl">
300 <input
301 type="text"
302 size={40}
303 value={details.logo}
304 onChange={(e) => handleChange('logo', e.target.value)}
305 onBlur={(e) => handleBlur('StoreSetup.Logo', e.target.value)}
306 className="w-full border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
307 placeholder="https://example.com/logo.png"
308 />
309 <p className="text-xs text-muted mt-2">Enter the URL of your logo. This will be used on receipts and similar places.</p>
310 </div>
311 <div className="border border-dashed border-border rounded p-4 min-w-[200px] min-h-[100px] flex items-center justify-center">
312 {details.logo ? (
313 <img src={details.logo} alt="Company Logo" className="max-w-full max-h-[150px]" onError={(e) => {
314 (e.target as HTMLImageElement).style.display = 'none';
315 (e.target as HTMLImageElement).parentElement!.innerHTML = '<div class="text-sm text-muted">Invalid logo URL</div>';
316 }} />
317 ) : (
318 <div className="text-sm text-muted">Current Logo<br />None</div>
319 )}
320 </div>
321 </div>
322 </div>
323
324 {/* Country */}
325 <div>
326 <label className="block text-sm font-semibold text-text mb-2">
327 Country
328 </label>
329 <select
330 value={details.countryCode}
331 onChange={(e) => handleCountryChange(e.target.value)}
332 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
333 >
334 <option value="">Based on Windows Regional settings</option>
335 <option value="61">Australia</option>
336 <option value="9001">Canada</option>
337 <option value="972">Israel</option>
338 <option value="64">New Zealand</option>
339 <option value="27">South Africa</option>
340 <option value="44">United Kingdom</option>
341 <option value="263">Zimbabwe</option>
342 </select>
343
344 {showCountryNotes && (
345 <div className="mt-3 p-4 border-2 border-danger rounded bg-danger/10 text-danger">
346 Canada has regional taxes. You need to edit each store and select the region it belongs too for these regional taxes to apply.
347 You can also specify a default region below if you only operate in one region.
348 </div>
349 )}
350
351 <p className="text-xs text-muted mt-2">
352 What country are you operating in? If left blank the Pos will detect and use whatever is configured on the PC.
353 However, we recommend explicitly setting this value as it is quite common for computers to be configured under
354 Windows Regional settings for the wrong country.
355 </p>
356 </div>
357
358 {/* Default Region (Canada) */}
359 {showRegionCanada && (
360 <div>
361 <label className="block text-sm font-semibold text-text mb-2">
362 Default Region
363 </label>
364 <select
365 value={details.locationDefaultRegion}
366 onChange={(e) => {
367 handleChange('locationDefaultRegion', e.target.value);
368 saveSetting('LocationDefaultRegion', e.target.value);
369 }}
370 className="w-full max-w-2xl border border-border rounded px-3 py-2 focus:ring-2 focus:ring-brand focus:border-transparent"
371 >
372 <option value="">Unknown</option>
373 <option value="90010001">Ontario</option>
374 <option value="90010002">British Columbia</option>
375 <option value="90010003">Nova Scotia</option>
376 <option value="90010004">Brunswick</option>
377 <option value="90010005">Newfoundland</option>
378 <option value="90010006">Quebec</option>
379 </select>
380 </div>
381 )}
382 </div>
383 </div>
384 </div>
385 </div>
386 );
387}