mirror of
https://github.com/christianvidalwolf-prog/Craze-Data-check.git
synced 2026-08-03 11:55:23 +02:00
feat: persist edits to Supabase database
This commit is contained in:
+31
-3
@@ -8,6 +8,7 @@ import { DataCompleteness } from './components/DataCompleteness';
|
||||
import { MatrixView } from './components/MatrixView';
|
||||
import { UploadReload } from './components/UploadReload';
|
||||
import { EditPanel } from './components/EditPanel';
|
||||
import { getAllSyncedRows, saveRowToSupabase } from './lib/supabase';
|
||||
|
||||
export default function App() {
|
||||
const [appState, setAppState] = useState<AppState>({
|
||||
@@ -60,9 +61,22 @@ export default function App() {
|
||||
const data = XLSX.utils.sheet_to_json<any[]>(ws, { header: 1 });
|
||||
|
||||
if (data.length > 0) {
|
||||
const rawHeaders = data[0];
|
||||
const rawRows = data.slice(1);
|
||||
|
||||
// Apply Supabase overrides
|
||||
console.log("Applying Supabase overrides...");
|
||||
const syncedData = await getAllSyncedRows();
|
||||
const articleNoIdx = COLUMNS.ARTICLE_NO;
|
||||
|
||||
const processedRows = rawRows.map(row => {
|
||||
const articleNo = String(row[articleNoIdx]);
|
||||
return syncedData[articleNo] || row;
|
||||
});
|
||||
|
||||
setAppState({
|
||||
headers: data[0],
|
||||
data: data.slice(1),
|
||||
headers: rawHeaders,
|
||||
data: processedRows,
|
||||
fileName: 'Data-Matrix.xlsx (Cloud Sync)',
|
||||
fileDate: new Date(),
|
||||
hasUnsavedChanges: false
|
||||
@@ -132,7 +146,8 @@ export default function App() {
|
||||
setAppState(prev => ({ ...prev, hasUnsavedChanges: false }));
|
||||
};
|
||||
|
||||
const handleSaveRow = (rowIndex: number, updatedRow: ExcelRow) => {
|
||||
const handleSaveRow = async (rowIndex: number, updatedRow: ExcelRow) => {
|
||||
// 1. Update UI state
|
||||
setAppState(prev => {
|
||||
const newData = [...prev.data];
|
||||
newData[rowIndex] = updatedRow;
|
||||
@@ -143,6 +158,19 @@ export default function App() {
|
||||
};
|
||||
});
|
||||
setEditingRowIndex(null);
|
||||
|
||||
// 2. Persist to Supabase
|
||||
const articleNo = String(updatedRow[COLUMNS.ARTICLE_NO]);
|
||||
console.log(`Saving article ${articleNo} to Supabase...`);
|
||||
const success = await saveRowToSupabase(articleNo, updatedRow);
|
||||
|
||||
if (success) {
|
||||
console.log(`Successfully saved ${articleNo}`);
|
||||
setAppState(prev => ({ ...prev, hasUnsavedChanges: false }));
|
||||
} else {
|
||||
console.error(`Failed to save ${articleNo} to Supabase`);
|
||||
alert("Error saving to database. Local changes will be lost on refresh if not saved.");
|
||||
}
|
||||
};
|
||||
|
||||
const stats = useMemo(() => {
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { ExcelRow } from '../types';
|
||||
|
||||
const SUPABASE_URL = 'https://hwithddwaapyhnfwcesj.supabase.co';
|
||||
const SUPABASE_KEY = 'sb_publishable_fGXkh0bSrAOqSk2jWKAzSg_NJD9YPCv';
|
||||
|
||||
export async function saveRowToSupabase(articleNo: string, rowData: ExcelRow) {
|
||||
try {
|
||||
const response = await fetch(`${SUPABASE_URL}/rest/v1/products_sync?id=eq.${encodeURIComponent(articleNo)}`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Prefer': 'resolution=merge-duplicates'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: articleNo,
|
||||
data: rowData,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
});
|
||||
|
||||
if (response.status === 204 || response.ok) {
|
||||
// If PATCH didn't find the record, try UPSERT
|
||||
const upsertResponse = await fetch(`${SUPABASE_URL}/rest/v1/products_sync`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Prefer': 'resolution=merge-duplicates'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id: articleNo,
|
||||
data: rowData,
|
||||
updated_at: new Date().toISOString()
|
||||
})
|
||||
});
|
||||
return upsertResponse.ok;
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error saving to Supabase:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAllSyncedRows(): Promise<Record<string, ExcelRow>> {
|
||||
try {
|
||||
const response = await fetch(`${SUPABASE_URL}/rest/v1/products_sync`, {
|
||||
headers: {
|
||||
'apikey': SUPABASE_KEY,
|
||||
'Authorization': `Bearer ${SUPABASE_KEY}`
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) return {};
|
||||
|
||||
const data = await response.json();
|
||||
const result: Record<string, ExcelRow> = {};
|
||||
data.forEach((item: any) => {
|
||||
result[item.id] = item.data;
|
||||
});
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error fetching from Supabase:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user