more integration tests added
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 2m43s

This commit is contained in:
2025-11-25 20:30:15 -08:00
parent 88ddbddb0e
commit b92818ce1f
7 changed files with 444 additions and 107 deletions

View File

@@ -368,12 +368,12 @@ export const countFlyerItemsForFlyers = async (flyerIds: number[]): Promise<numb
* @param logoImage The logo image file.
* @returns A promise that resolves with the new logo URL.
*/
export const uploadLogoAndUpdateStore = async (storeId: number, logoImage: File): Promise<{ logoUrl: string }> => {
export const uploadLogoAndUpdateStore = async (storeId: number, logoImage: File, tokenOverride?: string): Promise<{ logoUrl: string }> => {
const formData = new FormData();
formData.append('logoImage', logoImage);
// Use apiFetch to ensure the user is authenticated to perform this action.
const response = await apiFetch(`${API_BASE_URL}/stores/${storeId}/logo`, {
const response = await apiFetch(`/stores/${storeId}/logo`, {
method: 'POST',
body: formData,
// Do not set Content-Type for FormData, browser handles it.
@@ -388,12 +388,12 @@ export const uploadLogoAndUpdateStore = async (storeId: number, logoImage: File)
* @param logoImage The logo image file.
* @returns A promise that resolves with the new logo URL.
*/
export const uploadBrandLogo = async (brandId: number, logoImage: File): Promise<{ logoUrl: string }> => {
export const uploadBrandLogo = async (brandId: number, logoImage: File, tokenOverride?: string): Promise<{ logoUrl: string }> => {
const formData = new FormData();
formData.append('logoImage', logoImage);
// Use apiFetch to ensure the user is an authenticated admin.
const response = await apiFetch(`${API_BASE_URL}/admin/brands/${brandId}/logo`, {
const response = await apiFetch(`/admin/brands/${brandId}/logo`, {
method: 'POST',
body: formData,
// Do not set Content-Type for FormData, browser handles it.
@@ -408,12 +408,12 @@ export const uploadBrandLogo = async (brandId: number, logoImage: File): Promise
* @param masterItemIds An array of master grocery item IDs.
* @returns A promise that resolves to an array of historical price records.
*/
export const fetchHistoricalPriceData = async (masterItemIds: number[]): Promise<{ master_item_id: number; summary_date: string; avg_price_in_cents: number | null; }[]> => {
export const fetchHistoricalPriceData = async (masterItemIds: number[], tokenOverride?: string): Promise<{ master_item_id: number; summary_date: string; avg_price_in_cents: number | null; }[]> => {
if (masterItemIds.length === 0) {
return [];
}
const response = await apiFetch(`${API_BASE_URL}/price-history`, {
const response = await apiFetch(`/price-history`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ masterItemIds }),
@@ -429,8 +429,8 @@ export const fetchHistoricalPriceData = async (masterItemIds: number[]): Promise
// --- Watched Items API Functions ---
export const fetchWatchedItems = async (): Promise<MasterGroceryItem[]> => {
const response = await apiFetch(`${API_BASE_URL}/watched-items`);
export const fetchWatchedItems = async (tokenOverride?: string): Promise<MasterGroceryItem[]> => {
const response = await apiFetch(`/watched-items`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch watched items.' }));
throw new Error(errorData.message);
@@ -438,12 +438,12 @@ export const fetchWatchedItems = async (): Promise<MasterGroceryItem[]> => {
return response.json();
};
export const addWatchedItem = async (itemName: string, category: string): Promise<MasterGroceryItem> => {
const response = await apiFetch(`${API_BASE_URL}/watched-items`, {
export const addWatchedItem = async (itemName: string, category: string, tokenOverride?: string): Promise<MasterGroceryItem> => {
const response = await apiFetch(`/watched-items`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ itemName, category }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to add watched item.' }));
throw new Error(errorData.message);
@@ -451,10 +451,10 @@ export const addWatchedItem = async (itemName: string, category: string): Promis
return response.json();
};
export const removeWatchedItem = async (masterItemId: number): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/watched-items/${masterItemId}`, {
export const removeWatchedItem = async (masterItemId: number, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/watched-items/${masterItemId}`, {
method: 'DELETE',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to remove watched item.' }));
throw new Error(errorData.message);
@@ -463,8 +463,8 @@ export const removeWatchedItem = async (masterItemId: number): Promise<void> =>
// --- Shopping List API Functions ---
export const fetchShoppingLists = async (): Promise<ShoppingList[]> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists`);
export const fetchShoppingLists = async (tokenOverride?: string): Promise<ShoppingList[]> => {
const response = await apiFetch(`/shopping-lists`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch shopping lists.' }));
throw new Error(errorData.message);
@@ -472,12 +472,12 @@ export const fetchShoppingLists = async (): Promise<ShoppingList[]> => {
return response.json();
};
export const createShoppingList = async (name: string): Promise<ShoppingList> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists`, {
export const createShoppingList = async (name: string, tokenOverride?: string): Promise<ShoppingList> => {
const response = await apiFetch(`/shopping-lists`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to create shopping list.' }));
throw new Error(errorData.message);
@@ -485,22 +485,22 @@ export const createShoppingList = async (name: string): Promise<ShoppingList> =>
return response.json();
};
export const deleteShoppingList = async (listId: number): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists/${listId}`, {
export const deleteShoppingList = async (listId: number, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/shopping-lists/${listId}`, {
method: 'DELETE',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to delete shopping list.' }));
throw new Error(errorData.message);
}
};
export const addShoppingListItem = async (listId: number, item: { masterItemId?: number, customItemName?: string }): Promise<ShoppingListItem> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists/${listId}/items`, {
export const addShoppingListItem = async (listId: number, item: { masterItemId?: number, customItemName?: string }, tokenOverride?: string): Promise<ShoppingListItem> => {
const response = await apiFetch(`/shopping-lists/${listId}/items`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(item),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to add item to list.' }));
throw new Error(errorData.message);
@@ -508,12 +508,12 @@ export const addShoppingListItem = async (listId: number, item: { masterItemId?:
return response.json();
};
export const updateShoppingListItem = async (itemId: number, updates: Partial<ShoppingListItem>): Promise<ShoppingListItem> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists/items/${itemId}`, {
export const updateShoppingListItem = async (itemId: number, updates: Partial<ShoppingListItem>, tokenOverride?: string): Promise<ShoppingListItem> => {
const response = await apiFetch(`/shopping-lists/items/${itemId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to update list item.' }));
throw new Error(errorData.message);
@@ -521,10 +521,10 @@ export const updateShoppingListItem = async (itemId: number, updates: Partial<Sh
return response.json();
};
export const removeShoppingListItem = async (itemId: number): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists/items/${itemId}`, {
export const removeShoppingListItem = async (itemId: number, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/shopping-lists/items/${itemId}`, {
method: 'DELETE',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to remove list item.' }));
throw new Error(errorData.message);
@@ -581,13 +581,13 @@ export async function loginUser(email: string, password: string, rememberMe: boo
* @param receiptImage The image file of the receipt.
* @returns A promise that resolves with the backend's response, including the newly created receipt record.
*/
export const uploadReceipt = async (receiptImage: File): Promise<{ message: string; receipt: Receipt }> => {
export const uploadReceipt = async (receiptImage: File, tokenOverride?: string): Promise<{ message: string; receipt: Receipt }> => {
const formData = new FormData();
formData.append('receiptImage', receiptImage);
// Use apiFetch to ensure the user is authenticated for this action.
// The browser will automatically set the correct 'Content-Type' for FormData.
const response = await apiFetch(`${API_BASE_URL}/receipts/upload`, {
const response = await apiFetch(`/receipts/upload`, {
method: 'POST',
body: formData,
});
@@ -604,8 +604,8 @@ export const uploadReceipt = async (receiptImage: File): Promise<{ message: stri
* @param receiptId The ID of the processed receipt.
* @returns A promise that resolves to an array of ReceiptDeal objects.
*/
export const getDealsForReceipt = async (receiptId: number): Promise<ReceiptDeal[]> => {
const response = await apiFetch(`/receipts/${receiptId}/deals`);
export const getDealsForReceipt = async (receiptId: number, tokenOverride?: string): Promise<ReceiptDeal[]> => {
const response = await apiFetch(`/receipts/${receiptId}/deals`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch deals for receipt.' }));
throw new Error(errorData.message);
@@ -641,9 +641,9 @@ export const trackFlyerItemInteraction = async (itemId: number, type: 'view' | '
* This is a "fire-and-forget" call.
* @param query The search query data to log.
*/
export const logSearchQuery = async (query: Omit<SearchQuery, 'id' | 'created_at' | 'user_id'>): Promise<void> => {
export const logSearchQuery = async (query: Omit<SearchQuery, 'id' | 'created_at' | 'user_id'>, tokenOverride?: string): Promise<void> => {
try {
apiFetch(`${API_BASE_URL}/search/log`, {
apiFetch(`/search/log`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(query),
@@ -658,8 +658,8 @@ export const logSearchQuery = async (query: Omit<SearchQuery, 'id' | 'created_at
* Fetches all pantry locations for the current user.
* @returns A promise that resolves to an array of PantryLocation objects.
*/
export const getPantryLocations = async (): Promise<PantryLocation[]> => {
const response = await apiFetch(`${API_BASE_URL}/pantry/locations`);
export const getPantryLocations = async (tokenOverride?: string): Promise<PantryLocation[]> => {
const response = await apiFetch(`/pantry/locations`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch pantry locations.' }));
throw new Error(errorData.message);
@@ -672,12 +672,12 @@ export const getPantryLocations = async (): Promise<PantryLocation[]> => {
* @param name The name of the new location (e.g., "Fridge").
* @returns A promise that resolves to the newly created PantryLocation object.
*/
export const createPantryLocation = async (name: string): Promise<PantryLocation> => {
const response = await apiFetch(`${API_BASE_URL}/pantry/locations`, {
export const createPantryLocation = async (name: string, tokenOverride?: string): Promise<PantryLocation> => {
const response = await apiFetch(`/pantry/locations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to create pantry location.' }));
throw new Error(errorData.message);
@@ -691,12 +691,12 @@ export const createPantryLocation = async (name: string): Promise<PantryLocation
* @param totalSpentCents Optional total amount spent on the trip.
* @returns A promise that resolves to an object containing the new shopping trip ID.
*/
export const completeShoppingList = async (shoppingListId: number, totalSpentCents?: number): Promise<{ newTripId: number }> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-lists/${shoppingListId}/complete`, {
export const completeShoppingList = async (shoppingListId: number, totalSpentCents?: number, tokenOverride?: string): Promise<{ newTripId: number }> => {
const response = await apiFetch(`/shopping-lists/${shoppingListId}/complete`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ totalSpentCents }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to complete shopping list.' }));
throw new Error(errorData.message);
@@ -708,8 +708,8 @@ export const completeShoppingList = async (shoppingListId: number, totalSpentCen
* Fetches the historical shopping trips for the current user.
* @returns A promise that resolves to an array of ShoppingTrip objects.
*/
export const getShoppingTripHistory = async (): Promise<ShoppingTrip[]> => {
const response = await apiFetch(`${API_BASE_URL}/shopping-history`);
export const getShoppingTripHistory = async (tokenOverride?: string): Promise<ShoppingTrip[]> => {
const response = await apiFetch(`/shopping-history`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch shopping trip history.' }));
throw new Error(errorData.message);
@@ -749,8 +749,8 @@ export const getAppliances = async (): Promise<Appliance[]> => {
* Fetches the dietary restrictions for the currently authenticated user.
* @returns A promise that resolves to an array of the user's DietaryRestriction objects.
*/
export const getUserDietaryRestrictions = async (): Promise<DietaryRestriction[]> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/dietary-restrictions`);
export const getUserDietaryRestrictions = async (tokenOverride?: string): Promise<DietaryRestriction[]> => {
const response = await apiFetch(`/users/me/dietary-restrictions`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch user dietary restrictions.' }));
throw new Error(errorData.message);
@@ -763,12 +763,12 @@ export const getUserDietaryRestrictions = async (): Promise<DietaryRestriction[]
* This will replace all existing restrictions with the new set.
* @param restrictionIds An array of numbers representing the IDs of the selected restrictions.
*/
export const setUserDietaryRestrictions = async (restrictionIds: number[]): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/dietary-restrictions`, {
export const setUserDietaryRestrictions = async (restrictionIds: number[], tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/users/me/dietary-restrictions`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ restrictionIds }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to set user dietary restrictions.' }));
throw new Error(errorData.message);
@@ -779,8 +779,8 @@ export const setUserDietaryRestrictions = async (restrictionIds: number[]): Prom
* Fetches recipes that are compatible with the user's dietary restrictions.
* @returns A promise that resolves to an array of compatible Recipe objects.
*/
export const getCompatibleRecipes = async (): Promise<Recipe[]> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/compatible-recipes`);
export const getCompatibleRecipes = async (tokenOverride?: string): Promise<Recipe[]> => {
const response = await apiFetch(`/users/me/compatible-recipes`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch compatible recipes.' }));
throw new Error(errorData.message);
@@ -794,8 +794,8 @@ export const getCompatibleRecipes = async (): Promise<Recipe[]> => {
* @param offset The starting offset for pagination.
* @returns A promise that resolves to an array of ActivityLogItem objects.
*/
export const getUserFeed = async (limit: number = 20, offset: number = 0): Promise<ActivityLogItem[]> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/feed?limit=${limit}&offset=${offset}`);
export const getUserFeed = async (limit: number = 20, offset: number = 0, tokenOverride?: string): Promise<ActivityLogItem[]> => {
const response = await apiFetch(`/users/me/feed?limit=${limit}&offset=${offset}`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch user feed.' }));
throw new Error(errorData.message);
@@ -808,10 +808,10 @@ export const getUserFeed = async (limit: number = 20, offset: number = 0): Promi
* @param originalRecipeId The ID of the recipe to fork.
* @returns A promise that resolves to the newly created Recipe object.
*/
export const forkRecipe = async (originalRecipeId: number): Promise<Recipe> => {
const response = await apiFetch(`${API_BASE_URL}/recipes/${originalRecipeId}/fork`, {
export const forkRecipe = async (originalRecipeId: number, tokenOverride?: string): Promise<Recipe> => {
const response = await apiFetch(`/recipes/${originalRecipeId}/fork`, {
method: 'POST',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fork recipe.' }));
throw new Error(errorData.message);
@@ -823,10 +823,10 @@ export const forkRecipe = async (originalRecipeId: number): Promise<Recipe> => {
* Follows another user.
* @param userIdToFollow The UUID of the user to follow.
*/
export const followUser = async (userIdToFollow: string): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/users/${userIdToFollow}/follow`, {
export const followUser = async (userIdToFollow: string, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/users/${userIdToFollow}/follow`, {
method: 'POST',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to follow user.' }));
throw new Error(errorData.message);
@@ -837,10 +837,10 @@ export const followUser = async (userIdToFollow: string): Promise<void> => {
* Unfollows another user.
* @param userIdToUnfollow The UUID of the user to unfollow.
*/
export const unfollowUser = async (userIdToUnfollow: string): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/users/${userIdToUnfollow}/follow`, {
export const unfollowUser = async (userIdToUnfollow: string, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/users/${userIdToUnfollow}/follow`, {
method: 'DELETE',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to unfollow user.' }));
throw new Error(errorData.message);
@@ -855,8 +855,8 @@ export const unfollowUser = async (userIdToUnfollow: string): Promise<void> => {
* @param offset The starting offset for pagination.
* @returns A promise that resolves to an array of ActivityLogItem objects.
*/
export const fetchActivityLog = async (limit: number = 20, offset: number = 0): Promise<ActivityLogItem[]> => {
const response = await apiFetch(`${API_BASE_URL}/activity-log?limit=${limit}&offset=${offset}`);
export const fetchActivityLog = async (limit: number = 20, offset: number = 0, tokenOverride?: string): Promise<ActivityLogItem[]> => {
const response = await apiFetch(`/activity-log?limit=${limit}&offset=${offset}`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch activity log.' }));
throw new Error(errorData.message);
@@ -866,8 +866,8 @@ export const fetchActivityLog = async (limit: number = 20, offset: number = 0):
// --- Favorite Recipes API Functions ---
export const getUserFavoriteRecipes = async (): Promise<Recipe[]> => {
const response = await apiFetch(`${API_BASE_URL}/users/favorite-recipes`);
export const getUserFavoriteRecipes = async (tokenOverride?: string): Promise<Recipe[]> => {
const response = await apiFetch(`/users/favorite-recipes`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch favorite recipes.' }));
throw new Error(errorData.message);
@@ -875,12 +875,12 @@ export const getUserFavoriteRecipes = async (): Promise<Recipe[]> => {
return response.json();
};
export const addFavoriteRecipe = async (recipeId: number): Promise<FavoriteRecipe> => {
const response = await apiFetch(`${API_BASE_URL}/users/favorite-recipes`, {
export const addFavoriteRecipe = async (recipeId: number, tokenOverride?: string): Promise<FavoriteRecipe> => {
const response = await apiFetch(`/users/favorite-recipes`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ recipeId }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to add favorite recipe.' }));
throw new Error(errorData.message);
@@ -888,10 +888,10 @@ export const addFavoriteRecipe = async (recipeId: number): Promise<FavoriteRecip
return response.json();
};
export const removeFavoriteRecipe = async (recipeId: number): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/users/favorite-recipes/${recipeId}`, {
export const removeFavoriteRecipe = async (recipeId: number, tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/users/favorite-recipes/${recipeId}`, {
method: 'DELETE',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to remove favorite recipe.' }));
throw new Error(errorData.message);
@@ -910,12 +910,12 @@ export const getRecipeComments = async (recipeId: number): Promise<RecipeComment
return response.json();
};
export const addRecipeComment = async (recipeId: number, content: string, parentCommentId?: number): Promise<RecipeComment> => {
const response = await apiFetch(`${API_BASE_URL}/recipes/${recipeId}/comments`, {
export const addRecipeComment = async (recipeId: number, content: string, parentCommentId?: number, tokenOverride?: string): Promise<RecipeComment> => {
const response = await apiFetch(`/recipes/${recipeId}/comments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content, parentCommentId }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to add recipe comment.' }));
throw new Error(errorData.message);
@@ -946,12 +946,12 @@ export const getUnmatchedFlyerItems = async (): Promise<UnmatchedFlyerItem[]> =>
* @param status The new status for the recipe.
* @returns A promise that resolves to the updated Recipe object.
*/
export const updateRecipeStatus = async (recipeId: number, status: 'private' | 'pending_review' | 'public' | 'rejected'): Promise<Recipe> => {
const response = await apiFetch(`${API_BASE_URL}/admin/recipes/${recipeId}/status`, {
export const updateRecipeStatus = async (recipeId: number, status: 'private' | 'pending_review' | 'public' | 'rejected', tokenOverride?: string): Promise<Recipe> => {
const response = await apiFetch(`/admin/recipes/${recipeId}/status`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to update recipe status.' }));
throw new Error(errorData.message);
@@ -966,12 +966,12 @@ export const updateRecipeStatus = async (recipeId: number, status: 'private' | '
* @param status The new status for the comment.
* @returns A promise that resolves to the updated RecipeComment object.
*/
export const updateRecipeCommentStatus = async (commentId: number, status: 'visible' | 'hidden' | 'reported'): Promise<RecipeComment> => {
const response = await apiFetch(`${API_BASE_URL}/admin/comments/${commentId}/status`, {
export const updateRecipeCommentStatus = async (commentId: number, status: 'visible' | 'hidden' | 'reported', tokenOverride?: string): Promise<RecipeComment> => {
const response = await apiFetch(`/admin/comments/${commentId}/status`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to update recipe comment status.' }));
throw new Error(errorData.message);
@@ -983,8 +983,8 @@ export const updateRecipeCommentStatus = async (commentId: number, status: 'visi
* Fetches all brands from the backend. Requires admin privileges.
* @returns A promise that resolves to an array of Brand objects.
*/
export const fetchAllBrands = async (): Promise<Brand[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/brands`);
export const fetchAllBrands = async (tokenOverride?: string): Promise<Brand[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/brands`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch brands.' }));
throw new Error(errorData.message);
@@ -1009,8 +1009,8 @@ export interface DailyStat {
* Fetches daily user registration and flyer upload stats for the last 30 days.
* @returns A promise that resolves to an array of daily stat objects.
*/
export const getDailyStats = async (): Promise<DailyStat[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/stats/daily`);
export const getDailyStats = async (tokenOverride?: string): Promise<DailyStat[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/stats/daily`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch daily statistics.' }));
throw new Error(errorData.message);
@@ -1021,8 +1021,8 @@ export const getDailyStats = async (): Promise<DailyStat[]> => {
* Fetches application-wide statistics. Requires admin privileges.
* @returns A promise that resolves to an object containing app stats.
*/
export const getApplicationStats = async (): Promise<AppStats> => {
const response = await apiFetch(`${API_BASE_URL}/admin/stats`);
export const getApplicationStats = async (tokenOverride?: string): Promise<AppStats> => {
const response = await apiFetch(`${API_BASE_URL}/admin/stats`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch application statistics.' }));
throw new Error(errorData.message);
@@ -1036,8 +1036,8 @@ export const getApplicationStats = async (): Promise<AppStats> => {
* Fetches all pending suggested corrections. Requires admin privileges.
* @returns A promise that resolves to an array of SuggestedCorrection objects.
*/
export const getSuggestedCorrections = async (): Promise<SuggestedCorrection[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/corrections`);
export const getSuggestedCorrections = async (tokenOverride?: string): Promise<SuggestedCorrection[]> => {
const response = await apiFetch(`${API_BASE_URL}/admin/corrections`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch suggested corrections.' }));
throw new Error(errorData.message);
@@ -1050,10 +1050,10 @@ export const getSuggestedCorrections = async (): Promise<SuggestedCorrection[]>
* @param correctionId The ID of the correction to approve.
* @returns A promise that resolves with the success message.
*/
export const approveCorrection = async (correctionId: number): Promise<{ message: string }> => {
const response = await apiFetch(`${API_BASE_URL}/admin/corrections/${correctionId}/approve`, {
export const approveCorrection = async (correctionId: number, tokenOverride?: string): Promise<{ message: string }> => {
const response = await apiFetch(`/admin/corrections/${correctionId}/approve`, {
method: 'POST',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to approve correction.' }));
throw new Error(errorData.message);
@@ -1065,10 +1065,10 @@ export const approveCorrection = async (correctionId: number): Promise<{ message
* Rejects a suggested correction. Requires admin privileges.
* @param correctionId The ID of the correction to reject.
*/
export const rejectCorrection = async (correctionId: number): Promise<{ message: string }> => {
const response = await apiFetch(`${API_BASE_URL}/admin/corrections/${correctionId}/reject`, {
export const rejectCorrection = async (correctionId: number, tokenOverride?: string): Promise<{ message: string }> => {
const response = await apiFetch(`/admin/corrections/${correctionId}/reject`, {
method: 'POST',
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to reject correction.' }));
throw new Error(errorData.message);
@@ -1082,12 +1082,12 @@ export const rejectCorrection = async (correctionId: number): Promise<{ message:
* @param newSuggestedValue The new value for the suggestion.
* @returns A promise that resolves to the updated SuggestedCorrection object.
*/
export const updateSuggestedCorrection = async (correctionId: number, newSuggestedValue: string): Promise<SuggestedCorrection> => {
const response = await apiFetch(`${API_BASE_URL}/admin/corrections/${correctionId}`, {
export const updateSuggestedCorrection = async (correctionId: number, newSuggestedValue: string, tokenOverride?: string): Promise<SuggestedCorrection> => {
const response = await apiFetch(`/admin/corrections/${correctionId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ suggested_value: newSuggestedValue }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to update suggested correction.' }));
throw new Error(errorData.message);
@@ -1226,8 +1226,8 @@ export async function exportUserData(tokenOverride?: string): Promise<UserDataEx
* Fetches the kitchen appliances for the currently authenticated user.
* @returns A promise that resolves to an array of the user's Appliance objects.
*/
export const getUserAppliances = async (): Promise<Appliance[]> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/appliances`);
export const getUserAppliances = async (tokenOverride?: string): Promise<Appliance[]> => {
const response = await apiFetch(`/users/me/appliances`, {}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to fetch user appliances.' }));
throw new Error(errorData.message);
@@ -1240,12 +1240,12 @@ export const getUserAppliances = async (): Promise<Appliance[]> => {
* This will replace all existing appliances with the new set.
* @param applianceIds An array of numbers representing the IDs of the selected appliances.
*/
export const setUserAppliances = async (applianceIds: number[]): Promise<void> => {
const response = await apiFetch(`${API_BASE_URL}/users/me/appliances`, {
export const setUserAppliances = async (applianceIds: number[], tokenOverride?: string): Promise<void> => {
const response = await apiFetch(`/users/me/appliances`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ applianceIds }),
});
}, tokenOverride);
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: 'Failed to set user appliances.' }));
throw new Error(errorData.message);