/** * Consumer API Client for Findagram * * Handles authenticated requests for: * - Favorites * - Price Alerts * - Saved Searches * * All methods require auth token (use with AuthContext's authFetch) */ // ============================================================ // FAVORITES // ============================================================ /** * Get all user's favorites * @param {Function} authFetch - Authenticated fetch from AuthContext */ export async function getFavorites(authFetch) { return authFetch('/api/consumer/favorites'); } /** * Add product to favorites * @param {Function} authFetch * @param {number} productId * @param {number} [dispensaryId] - Optional dispensary context */ export async function addFavorite(authFetch, productId, dispensaryId = null) { return authFetch('/api/consumer/favorites', { method: 'POST', body: JSON.stringify({ productId, dispensaryId }), }); } /** * Remove favorite by favorite ID * @param {Function} authFetch * @param {number} favoriteId */ export async function removeFavorite(authFetch, favoriteId) { return authFetch(`/api/consumer/favorites/${favoriteId}`, { method: 'DELETE', }); } /** * Remove favorite by product ID * @param {Function} authFetch * @param {number} productId */ export async function removeFavoriteByProduct(authFetch, productId) { return authFetch(`/api/consumer/favorites/product/${productId}`, { method: 'DELETE', }); } /** * Check if product is favorited * @param {Function} authFetch * @param {number} productId * @returns {Promise<{isFavorited: boolean}>} */ export async function checkFavorite(authFetch, productId) { return authFetch(`/api/consumer/favorites/check/product/${productId}`); } // ============================================================ // ALERTS // ============================================================ /** * Get all user's alerts * @param {Function} authFetch */ export async function getAlerts(authFetch) { return authFetch('/api/consumer/alerts'); } /** * Get alert statistics * @param {Function} authFetch */ export async function getAlertStats(authFetch) { return authFetch('/api/consumer/alerts/stats'); } /** * Create a price drop alert * @param {Function} authFetch * @param {Object} params * @param {number} params.productId - Product to track * @param {number} params.targetPrice - Price to alert at * @param {number} [params.dispensaryId] - Optional dispensary context */ export async function createPriceAlert(authFetch, { productId, targetPrice, dispensaryId }) { return authFetch('/api/consumer/alerts', { method: 'POST', body: JSON.stringify({ alertType: 'price_drop', productId, targetPrice, dispensaryId, }), }); } /** * Create a back-in-stock alert * @param {Function} authFetch * @param {Object} params * @param {number} params.productId - Product to track * @param {number} [params.dispensaryId] - Optional dispensary context */ export async function createStockAlert(authFetch, { productId, dispensaryId }) { return authFetch('/api/consumer/alerts', { method: 'POST', body: JSON.stringify({ alertType: 'back_in_stock', productId, dispensaryId, }), }); } /** * Create a brand/category alert * @param {Function} authFetch * @param {Object} params * @param {string} [params.brand] - Brand to track * @param {string} [params.category] - Category to track */ export async function createBrandCategoryAlert(authFetch, { brand, category }) { return authFetch('/api/consumer/alerts', { method: 'POST', body: JSON.stringify({ alertType: 'product_on_special', brand, category, }), }); } /** * Update an alert * @param {Function} authFetch * @param {number} alertId * @param {Object} updates * @param {boolean} [updates.isActive] * @param {number} [updates.targetPrice] */ export async function updateAlert(authFetch, alertId, updates) { return authFetch(`/api/consumer/alerts/${alertId}`, { method: 'PUT', body: JSON.stringify(updates), }); } /** * Toggle alert active status * @param {Function} authFetch * @param {number} alertId */ export async function toggleAlert(authFetch, alertId) { return authFetch(`/api/consumer/alerts/${alertId}/toggle`, { method: 'POST', }); } /** * Delete an alert * @param {Function} authFetch * @param {number} alertId */ export async function deleteAlert(authFetch, alertId) { return authFetch(`/api/consumer/alerts/${alertId}`, { method: 'DELETE', }); } // ============================================================ // SAVED SEARCHES // ============================================================ /** * Get all user's saved searches * @param {Function} authFetch */ export async function getSavedSearches(authFetch) { return authFetch('/api/consumer/saved-searches'); } /** * Create a saved search * @param {Function} authFetch * @param {Object} params * @param {string} params.name - Display name * @param {string} [params.query] - Search query * @param {string} [params.category] - Category filter * @param {string} [params.brand] - Brand filter * @param {string} [params.strainType] - Strain type filter * @param {number} [params.minPrice] - Min price filter * @param {number} [params.maxPrice] - Max price filter * @param {number} [params.minThc] - Min THC filter * @param {number} [params.maxThc] - Max THC filter * @param {boolean} [params.notifyOnNew] - Notify on new products * @param {boolean} [params.notifyOnPriceDrop] - Notify on price drops */ export async function createSavedSearch(authFetch, params) { return authFetch('/api/consumer/saved-searches', { method: 'POST', body: JSON.stringify(params), }); } /** * Update a saved search * @param {Function} authFetch * @param {number} searchId * @param {Object} updates */ export async function updateSavedSearch(authFetch, searchId, updates) { return authFetch(`/api/consumer/saved-searches/${searchId}`, { method: 'PUT', body: JSON.stringify(updates), }); } /** * Delete a saved search * @param {Function} authFetch * @param {number} searchId */ export async function deleteSavedSearch(authFetch, searchId) { return authFetch(`/api/consumer/saved-searches/${searchId}`, { method: 'DELETE', }); } /** * Run a saved search (get search params) * @param {Function} authFetch * @param {number} searchId * @returns {Promise<{searchParams: Object, searchUrl: string}>} */ export async function runSavedSearch(authFetch, searchId) { return authFetch(`/api/consumer/saved-searches/${searchId}/run`, { method: 'POST', }); } // ============================================================ // HELPER: Generate search name from filters // ============================================================ /** * Generate a display name for a search based on filters * @param {Object} filters * @returns {string} */ export function generateSearchName(filters) { const parts = []; if (filters.query || filters.search) parts.push(`"${filters.query || filters.search}"`); if (filters.category || filters.type) parts.push(filters.category || filters.type); if (filters.brand || filters.brandName) parts.push(filters.brand || filters.brandName); if (filters.strainType) parts.push(filters.strainType); if (filters.maxPrice) parts.push(`Under $${filters.maxPrice}`); if (filters.minThc) parts.push(`${filters.minThc}%+ THC`); return parts.length > 0 ? parts.join(' - ') : 'All Products'; } // Default export const consumerApi = { // Favorites getFavorites, addFavorite, removeFavorite, removeFavoriteByProduct, checkFavorite, // Alerts getAlerts, getAlertStats, createPriceAlert, createStockAlert, createBrandCategoryAlert, updateAlert, toggleAlert, deleteAlert, // Saved Searches getSavedSearches, createSavedSearch, updateSavedSearch, deleteSavedSearch, runSavedSearch, // Helpers generateSearchName, }; export default consumerApi;