- Retries up to 3 times with exponential backoff (2s, 4s, 8s)
- Also handles 503 service unavailable errors
- Logs retry attempts for debugging
- Only retries rate limit errors, other errors fail immediately
- Added openrouter.ts with provider configuration
- Default provider: OpenRouter with google/gemma-3-27b-it
- Switch to Gemini via AI_PROVIDER=gemini in .env.local
- Both providers use same credit system
- OpenRouter uses OpenAI-compatible API
To switch providers, set in .env.local:
AI_PROVIDER=openrouter # default
AI_PROVIDER=gemini # Google Gemini
- Add 'Split starten' button to bottle detail page
- Support flexible sample sizes (1-20cl) instead of fixed 5/10cl
- Preselect bottle when coming from bottle page
- Save sample sizes/shipping defaults to localStorage
- Update schema: sample_sizes JSONB array
- Update server actions and UI for dynamic sizes
- Add Buddy linking via QR code/handshake (buddy_invites table)
- Add Bulk Scanner for rapid-fire bottle scanning in sessions
- Add processing_status to bottles for background AI analysis
- Fix offline OCR with proper tessdata caching in Service Worker
- Fix Supabase GoTrueClient singleton warning
- Add collection refresh after offline sync completes
New components:
- BuddyHandshake.tsx - QR code display and code entry
- BulkScanSheet.tsx - Camera UI with capture queue
- BottleSkeletonCard.tsx - Pending bottle display
- useBulkScanner.ts - Queue management hook
- buddy-link.ts - Server actions for buddy linking
- bulk-scan.ts - Server actions for batch processing
- Renamed app to DramLog and updated branding to Gold (#C89D46)
- Implemented new BottomNavigation with Floating Scan Button
- Fixed 'black screen' race condition in ScanAndTasteFlow
- Refactored TastingEditor and StatsDashboard for a cleaner editorial look
- Standardized colors and typography across the application
- Reverted theme from gold to amber and restored legacy typography.
- Refactored ScanAndTasteFlow and TastingEditor for robust desktop scrolling.
- Hotfixed sw.js to completely bypass Supabase Auth/API requests to fix 'Failed to fetch' in production.
- Integrated full tasting note persistence (tags, buddies, sessions).
- Migrated to Dexie.js for IndexedDB management
- Added optimistic UI for tasting notes with 'Wartet auf Sync' badge
- Implemented background caching for tags and buddies
- Unified scanning and tasting sync in a global UploadQueue
- Implemented reusable TagSelector component with i18n support
- Added tag weighting system (popularity scores 1-5)
- Created admin panel for tag management
- Integrated Nebius AI and Brave Search for 'Magic Scan'
- Refactored app focus: removed bottle status, updated counters, and displayed extended bottle details
- Updated i18n for German and English
- Added database migration scripts
- Added 'Upload from Gallery' button to CameraCapture component
- Implemented secondary file input without 'capture' attribute to allow gallery selection on mobile
- Fixed overlapping header elements on mobile by making the header responsive
- Compacted 'Dram of the Day' button on small screens
- Added translations for the new gallery upload feature
- Fetched api_usage and profiles separately to avoid Supabase join errors when relationships are not explicitly defined in the schema cache.
- Updated Gemini AI tracking integration to ensure all calls are recorded correctly.
- Improved error handling in admin dashboard.
- Integrated API tracking into analyze-bottle service
- Added credit balance check before Gemini API calls
- Deduct credits after successful Gemini analysis
- Track both successful and failed Gemini API calls
- Added debug logging to admin dashboard for recent API calls
- Fixed error handling in analyze-bottle
Now tracks both Google Search and Gemini AI API usage!
- Added plan dropdown to user edit modal
- Shows current plan with highlighted card
- Allows admin to assign/change user's subscription plan
- Loads user's current plan when opening edit modal
- Updates plan via setUserPlan service
- Visual feedback with success/error messages
Admins can now:
- View user's current subscription plan
- Assign users to different plans (Starter, Bronze, Silver, Gold)
- See plan details (credits/month, price) in dropdown
This completes the subscription plan system!
- Database schema:
* subscription_plans table - stores plan tiers (Starter, Bronze, Silver, Gold)
* user_subscriptions table - assigns users to plans
* Default plans created (10, 50, 100, 250 credits/month)
* All existing users assigned to Starter plan
- Subscription service (subscription-service.ts):
* getAllPlans() - fetch all plans
* getActivePlans() - fetch active plans for users
* createPlan() - admin creates new plan
* updatePlan() - admin edits plan
* deletePlan() - admin removes plan
* getUserSubscription() - get user's current plan
* setUserPlan() - admin assigns user to plan
* grantMonthlyCredits() - distribute credits to all users
- Plan management interface (/admin/plans):
* Visual plan cards with credits, price, description
* Create/Edit/Delete plans
* Toggle active/inactive status
* Sort order management
* Grant monthly credits button (manual trigger)
- Features:
* Monthly credit allocation based on plan
* Prevents duplicate credit grants (tracks last_credit_grant_at)
* Admin can manually trigger monthly credit distribution
* Plans can be activated/deactivated
* Custom pricing and credit amounts per plan
- UI:
* Beautiful plan cards with color coding
* Modal for create/edit with validation
* Success/error messages
* Manage Plans button in admin dashboard
Ready for future automation (cron job for monthly credits)
and payment integration (Stripe/PayPal).
- Database schema:
* Extended user_credits table with daily_limit, API costs, last_reset_at
* Created credit_transactions table for full audit trail
* Added RLS policies for secure access control
- Core services:
* credit-service.ts - balance checking, deduction, addition, transaction history
* admin-credit-service.ts - admin controls for managing users and credits
- API integration:
* Integrated credit checking into discover-whiskybase.ts
* Credits deducted after successful API calls
* Insufficient credits error handling
- Admin interface:
* /admin/users page with user management
* Statistics dashboard (total users, credits in circulation, usage)
* Interactive user table with search
* Edit modal for credit adjustment and settings
* Per-user daily limits and API cost configuration
- Features:
* Automatic credit initialization (100 credits for new users)
* Credit transaction logging with balance_after tracking
* Admin can add/remove credits with reason
* Admin can set custom daily limits per user
* Admin can set custom API costs per user
* Low credit warnings (< 10 credits)
* Full transaction history
- User experience:
* Credits checked before API calls
* Clear error messages for insufficient credits
* Graceful handling of credit deduction failures
System is ready for future enhancements like credit packages,
auto-recharge, and payment integration.
The admin_users policy was checking if user is admin by querying
the same table, causing infinite recursion. Changed to allow users
to view their own admin record directly using auth.uid() = user_id.
This fixes the error: 'infinite recursion detected in policy for
relation admin_users'
- Added database schema for API tracking system:
* api_usage table - tracks all Google Search and Gemini AI calls
* user_credits table - prepared for future credits system
* admin_users table - controls admin dashboard access
- Created comprehensive tracking service (track-api-usage.ts):
* trackApiUsage() - records API calls with success/failure
* checkDailyLimit() - enforces 80 Google Search calls/day limit
* getUserApiStats() - per-user statistics
* getGlobalApiStats() - app-wide statistics (admin only)
* checkIsAdmin() - server-side authorization
- Integrated tracking into discover-whiskybase.ts:
* Pre-call limit checking with friendly error messages
* Post-call usage tracking for success and failures
* User authentication verification
- Built admin dashboard at /admin:
* Global statistics cards (total, today, by API type)
* Top 10 users by API usage
* Recent activity log with 50 latest calls
* Color-coded status indicators
* Secure access with RLS policies
- Features:
* Daily limit resets at midnight Europe/Berlin timezone
* Graceful error handling (allows on tracking failure)
* Comprehensive indexes for fast queries
* Ready for future credits/monetization system
- Created type-safe i18n system with TranslationKeys interface
- Added German (de) and English (en) translations with 160+ keys
- Implemented I18nContext provider and useI18n hook
- Added LanguageSwitcher component for language selection
- Refactored all major components to use translations:
* Home page, StatsDashboard, DramOfTheDay
* BottleGrid, EditBottleForm, CameraCapture
* BuddyList, SessionList, TastingNoteForm
* StatusSwitcher and bottle management features
- Implemented locale-aware currency formatting (EUR)
- Implemented locale-aware date formatting
- Added localStorage persistence for language preference
- Added automatic browser language detection
- Organized translations into 8 main categories
- System is extensible for additional languages