3import { useState } from 'react';
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);
10 async function handleSync() {
16 const response = await fetch('/api/auth/stores', {
19 'Content-Type': 'application/json',
23 const data = await response.json();
28 setError(data.error || 'Sync failed');
31 setError(err.message || 'Failed to sync stores');
37 async function handleViewStores() {
39 const response = await fetch('/api/auth/stores?sync=true');
40 const data = await response.json();
43 setError(err.message || 'Failed to fetch stores');
48 <div className="p-8 max-w-4xl mx-auto">
49 <h1 className="text-3xl font-bold mb-8">Stores Sync Admin</h1>
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.
57 <div className="flex gap-4">
61 className="bg-brand text-white px-6 py-2 rounded-md hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
63 {syncing ? 'Syncing...' : 'Sync Stores Now'}
67 onClick={handleViewStores}
68 className="bg-surface border-2 border-border text-text px-6 py-2 rounded-md hover:bg-surface-2"
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>
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>}
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)}
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>