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 } from 'react';
4
5export default function StoresSyncPage() {
6 const [syncing, setSyncing] = useState(false);
7 const [result, setResult] = useState<any>(null);
8 const [error, setError] = useState<string | null>(null);
9
10 async function handleSync() {
11 setSyncing(true);
12 setError(null);
13 setResult(null);
14
15 try {
16 const response = await fetch('/api/auth/stores', {
17 method: 'POST',
18 headers: {
19 'Content-Type': 'application/json',
20 },
21 });
22
23 const data = await response.json();
24
25 if (response.ok) {
26 setResult(data);
27 } else {
28 setError(data.error || 'Sync failed');
29 }
30 } catch (err: any) {
31 setError(err.message || 'Failed to sync stores');
32 } finally {
33 setSyncing(false);
34 }
35 }
36
37 async function handleViewStores() {
38 try {
39 const response = await fetch('/api/auth/stores?sync=true');
40 const data = await response.json();
41 setResult(data);
42 } catch (err: any) {
43 setError(err.message || 'Failed to fetch stores');
44 }
45 }
46
47 return (
48 <div className="p-8 max-w-4xl mx-auto">
49 <h1 className="text-3xl font-bold mb-8">Stores Sync Admin</h1>
50
51 <div className="bg-white p-6 rounded-lg shadow-md mb-6">
52 <h2 className="text-xl font-semibold mb-4">Sync Stores from Fieldpine</h2>
53 <p className="text-gray-600 mb-4">
54 This will fetch all locations from the Fieldpine API and update the stores manifest.
55 </p>
56
57 <div className="flex gap-4">
58 <button
59 onClick={handleSync}
60 disabled={syncing}
61 className="bg-brand text-white px-6 py-2 rounded-md hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
62 >
63 {syncing ? 'Syncing...' : 'Sync Stores Now'}
64 </button>
65
66 <button
67 onClick={handleViewStores}
68 className="bg-surface border-2 border-border text-text px-6 py-2 rounded-md hover:bg-surface-2"
69 >
70 View Current Stores
71 </button>
72 </div>
73 </div>
74
75 {error && (
76 <div className="border px-4 py-3 rounded-md mb-6" style={{ background: 'rgba(var(--danger), 0.1)', borderColor: 'var(--danger)', color: 'var(--danger)' }}>
77 <p className="font-semibold">Error</p>
78 <p>{error}</p>
79 </div>
80 )}
81
82 {result && (
83 <div className="border px-4 py-3 rounded-md mb-6" style={{ background: 'rgba(var(--success), 0.1)', borderColor: 'var(--success)', color: 'var(--success)' }}>
84 <p className="font-semibold mb-2">Success!</p>
85 <div className="text-sm">
86 <p><strong>Store Count:</strong> {result.storeCount || result.data?.length || 'N/A'}</p>
87 <p><strong>Last Updated:</strong> {result.lastUpdated || 'N/A'}</p>
88 {result.message && <p><strong>Message:</strong> {result.message}</p>}
89 </div>
90
91 {result.data && (
92 <details className="mt-4">
93 <summary className="cursor-pointer font-semibold">View Stores</summary>
94 <pre className="mt-2 p-4 bg-white rounded border overflow-auto max-h-96 text-xs">
95 {JSON.stringify(result.data, null, 2)}
96 </pre>
97 </details>
98 )}
99 </div>
100 )}
101
102 <div className="bg-blue-50 border border-blue-200 p-4 rounded-md">
103 <h3 className="font-semibold mb-2">How it works:</h3>
104 <ol className="list-decimal list-inside space-y-1 text-sm text-gray-700">
105 <li>Fetches all locations from <code>/api/v1/locations</code></li>
106 <li>Maps Fieldpine location fields to Store format</li>
107 <li>Updates <code>/data/config/stores-manifest.json</code></li>
108 <li>Clears the API cache</li>
109 <li>New stores appear in the login dropdown immediately</li>
110 </ol>
111 </div>
112 </div>
113 );
114}