From b702a33232d4b43f29730e6bd1cffd01a8988c89 Mon Sep 17 00:00:00 2001 From: Torben Sorensen Date: Mon, 10 Nov 2025 14:56:03 -0800 Subject: [PATCH] various fixes maybe now she worky? --- App.tsx | 5 +++-- services/supabaseClient.ts | 45 +++++++++++++++++++++++++------------ supabase/.temp/cli-latest | 1 + tailwind.config.js | 3 ++- types/supabase.ts | Bin 0 -> 131284 bytes 5 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 supabase/.temp/cli-latest create mode 100644 types/supabase.ts diff --git a/App.tsx b/App.tsx index 90e1d8fa..28cab8c6 100644 --- a/App.tsx +++ b/App.tsx @@ -6,7 +6,8 @@ import { PriceChart } from './components/PriceChart'; import { ErrorDisplay } from './components/ErrorDisplay'; import { Header } from './components/Header'; import { isImageAFlyer, extractCoreDataFromImage, extractAddressFromImage, extractLogoFromImage } from './services/geminiService'; -import type { FlyerItem, Flyer, MasterGroceryItem, DealItem, ProcessingStage, StageStatus, Store, Profile, ShoppingList, ShoppingListItem, Database } from './types'; +import type { FlyerItem, Flyer, MasterGroceryItem, DealItem, ProcessingStage, StageStatus, Store, Profile, ShoppingList, ShoppingListItem } from './types'; +import type { Database } from './types/supabase'; // Correctly import the Database type import { BulkImporter } from './components/BulkImporter'; import { PriceHistoryChart } from './components/PriceHistoryChart'; import { supabase, uploadFlyerImage, createFlyerRecord, saveFlyerItems, getFlyers, getFlyerItems, findFlyerByChecksum, getWatchedItems, addWatchedItem, getAllMasterItems, getFlyerItemsForFlyers, countFlyerItemsForFlyers, getUserProfile, updateUserPreferences, removeWatchedItem, getShoppingLists, createShoppingList, addShoppingListItem, updateShoppingListItem, removeShoppingListItem, deleteShoppingList, uploadLogoAndUpdateStore } from './services/supabaseClient'; @@ -316,7 +317,7 @@ function App() { price_display: item.price_display, price_in_cents: item.price_in_cents, quantity: item.quantity, - storeName: flyerIdToStoreName.get(item.flyer_id!) || 'Unknown Store', + storeName: (flyerIdToStoreName.get(item.flyer_id!) || 'Unknown Store') as string, master_item_name: item.master_item_name, unit_price: item.unit_price, })); diff --git a/services/supabaseClient.ts b/services/supabaseClient.ts index ebe8c436..36f8a03f 100644 --- a/services/supabaseClient.ts +++ b/services/supabaseClient.ts @@ -13,7 +13,7 @@ if (!supabaseUrl || !supabaseAnonKey) { // Create and export the Supabase client. // If the keys are missing, this will be null, and features requiring it will be disabled. -export const supabase = (supabaseUrl && supabaseAnonKey) +export let supabase = (supabaseUrl && supabaseAnonKey) ? createClient(supabaseUrl, supabaseAnonKey) : null; @@ -199,15 +199,22 @@ export const saveFlyerItems = async (items: Omit ({ ...item, flyer_id: flyerId })); + const itemsToInsert = items.map(item => { + // Create a new object without the properties that don't exist in the DB table + const { master_item_name, ...rest } = item; + return { ...rest, flyer_id: flyerId }; + }); const { data: savedItems, error } = await supabase .from('flyer_items') - .insert(itemsToInsert) + // We cast to `any` here to bypass the strict type check on the `unit_price` (Json vs UnitPrice) + // This is safe because UnitPrice is a valid JSONB structure. + .insert(itemsToInsert as any) .select(); if (error) throw new Error(`Failed to save flyer items: ${error.message}`); - return savedItems; + // Cast the result back to the expected application type + return savedItems as unknown as FlyerItem[]; }; /** @@ -223,7 +230,8 @@ export const getFlyers = async (): Promise => { .order('created_at', { ascending: false }); if (error) throw new Error(`Failed to get flyers: ${error.message}`); - return data || []; + // Cast the result back to the expected application type + return (data as Flyer[]) || []; }; /** @@ -241,7 +249,8 @@ export const getFlyerItems = async (flyerId: number): Promise => { .order('item', { ascending: true }); if (error) throw new Error(`Failed to get flyer items: ${error.message}`); - return data || []; + // Cast the result back to the expected application type + return (data as unknown as FlyerItem[]) || []; }; /** @@ -457,7 +466,8 @@ export const getFlyerItemsForFlyers = async (flyerIds: number[]): Promise => console.error("Error fetching user profile:", error.message); return null; } - return data; + // Cast the result back to the expected application type + return data as Profile | null; }; /** @@ -528,12 +539,14 @@ export const updateUserProfile = async (userId: string, updates: { full_name?: s if (!supabase) throw new Error("Supabase client not initialized"); const { data, error } = await supabase .from('profiles') - .update(updates) + // Cast to `any` to handle potential JSONB type mismatches if more fields are added + .update(updates as any) .eq('id', userId) .select() .single(); if (error) throw new Error(`Error updating profile: ${error.message}`); - return data; + // Cast the result back to the expected application type + return data as Profile; }; /** @@ -546,12 +559,14 @@ export const updateUserPreferences = async (userId: string, preferences: Profile if (!supabase) throw new Error("Supabase client not initialized"); const { data, error } = await supabase .from('profiles') - .update({ preferences }) + // Cast to `any` to handle the JSONB type mismatch for `preferences` + .update({ preferences: preferences as any }) .eq('id', userId) .select() .single(); if (error) throw new Error(`Error updating preferences: ${error.message}`); - return data; + // Cast the result back to the expected application type + return data as Profile; }; /** @@ -770,14 +785,16 @@ export const addShoppingListItem = async (listId: number, { masterItemId, custom */ export const updateShoppingListItem = async (itemId: number, updates: Partial): Promise => { if (!supabase) throw new Error("Supabase client not initialized"); + // The 'id' cannot be part of the update payload. + const { id, ...updateData } = updates; const { data, error } = await supabase .from('shopping_list_items') - .update(updates) + .update(updateData) .eq('id', itemId) .select('*, master_item:master_grocery_items(name)') .single(); if (error) throw new Error(`Error updating shopping list item: ${error.message}`); - return data; + return data as ShoppingListItem; }; /** diff --git a/supabase/.temp/cli-latest b/supabase/.temp/cli-latest new file mode 100644 index 00000000..11335d2f --- /dev/null +++ b/supabase/.temp/cli-latest @@ -0,0 +1 @@ +v2.54.11 \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index d25373a3..0ca752de 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -3,7 +3,8 @@ export default { // Configure files to scan for Tailwind classes content: [ "./index.html", - "./*.{js,ts,jsx,tsx}", // Scans for files in the root directory + "./*.{js,ts,jsx,tsx}", // Scans for files in the root directory like index.tsx + "./components/**/*.{js,ts,jsx,tsx}", // Scans all component files ], // Enable dark mode using a class darkMode: 'class', diff --git a/types/supabase.ts b/types/supabase.ts new file mode 100644 index 0000000000000000000000000000000000000000..cc84215b214d32db1a88a96097d555483912881c GIT binary patch literal 131284 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 Zv&yV|*T8=ML7t-;h}t?Tf*1{7@t?#I$R_{* literal 0 HcmV?d00001