Commit Graph

175 Commits

Author SHA1 Message Date
2bf0ac0f3e chore: Implement route protection and security enhancements
- Add src/middleware.ts for global route proection
- Whitelist public routes (/, /auth/*, /splits/[slug])
- Add redirect logic to Home page for returning users
- Fix minor lint issues in Home page
2026-01-19 12:36:35 +01:00
bb9a78f755 feat: Revamp Analytics Dashboard
- Replace StatsDashboard with new AnalyticsDashboard component
- Add Recharts charts: Category Pie, ABV Area, Age Bar, Top Distilleries Bar, Price vs Quality Scatter
- Update fetching logic to include tasting ratings for analysis
- Enhance UI with new KPI cards and dark mode styling
2026-01-19 12:06:47 +01:00
45f562e2ce feat: Add admin page for tasting sessions
- Create /admin/sessions page showing all sessions from all users
- Stats: total sessions, active, hosts, participants, tastings
- Filter by host, status (active/ended)
- Show session duration, participant count, tasting count
- Add 'All Sessions' link to admin dashboard
2026-01-19 11:54:42 +01:00
5914ef2ac8 fix: Use correct column names for tastings table
- Change nose/palate/finish/notes to nose_notes/palate_notes/finish_notes
- Update query, interface, and all references in admin tastings page
2026-01-19 11:49:49 +01:00
948c70c7f2 fix: Use native img tags for admin pages
- Replace next/image with native img tags in admin bottles, splits, tastings
- Remove hardcoded Supabase hostname from next.config.mjs
- Native img works with any hostname without config changes on deploy
2026-01-19 11:46:26 +01:00
3c02d33531 fix: Add Supabase storage to Next.js images config
Allow next/image to optimize images from supaapi.cloud.fluffigewolke.de storage bucket.
2026-01-19 11:42:59 +01:00
6320cb14e5 fix: Service Worker always returns valid Response
- Fixed fetch handler that could return undefined instead of Response
- Changed from stale-while-revalidate to network-first with cache fallback
- Always return proper 503 Response when offline and no cache available
- Bump cache version to v21 to force SW update
2026-01-19 11:39:40 +01:00
f9192f2228 feat: Add admin pages for splits and tastings
- Create /admin/splits page showing all bottle splits
  - Stats: total splits, active, hosts, participants, volume
  - Filter by host, status (active/closed)
  - Progress bars showing reservation status

- Create /admin/tastings page showing all tasting notes
  - Stats: total tastings, users, avg rating, with notes, today
  - Filter by user, rating
  - Notes preview with star ratings

- Add navigation links to admin dashboard
2026-01-19 11:37:00 +01:00
ef64c89e9b feat: Add admin page to view all bottles from all users
- Create /admin/bottles page with comprehensive bottle overview
- Show stats: total bottles, total users, avg rating, top distilleries
- AdminBottlesList with search, filter by user/category, sorting
- Display bottle images, ratings, user info, and dates
- Add 'All Bottles' link to admin dashboard
2026-01-19 11:31:29 +01:00
c047966b43 feat: Add Admin UI for banner management
- Create /admin/banners page with full CRUD operations
- Add BannerManager.tsx client component for interactive management
- Add banner-actions.ts server actions (create, update, toggle, delete)
- Add 'Manage Banners' link to admin dashboard
- Features: image preview, activate/deactivate toggle, edit inline
2026-01-19 11:23:46 +01:00
169fa0ad63 style: Increase contrast for better readability
Override Tailwind zinc scale with brighter values for improved text contrast on dark backgrounds. Targets older users who may have difficulty reading gray-on-black text.

- zinc-500: #71717a → #8a8a95 (+20% brightness)
- zinc-600: #52525b → #6b6b75 (+25% brightness)
- zinc-400/700 also adjusted proportionally
2026-01-19 11:15:00 +01:00
886e5c121f feat: Complete GlitchTip error monitoring integration
- Add sentry.client.config.ts, sentry.server.config.ts, sentry.edge.config.ts
- Create /api/glitchtip-tunnel route for bypassing ad blockers
- Add SentryInit component for client-side initialization
- Add instrumentation.ts for server/edge initialization
- Integrate Sentry.captureException in error handlers
- Remove test button after verifying integration works

Env vars: NEXT_PUBLIC_GLITCHTIP_DSN, GLITCHTIP_DSN
2026-01-19 09:18:58 +01:00
ef2b9dfabf feat: Add GlitchTip error monitoring with Sentry SDK
- Install @sentry/nextjs
- Add sentry.client.config.ts, sentry.server.config.ts, sentry.edge.config.ts
- Conditional initialization based on GLITCHTIP_DSN env variable
- Add /api/glitchtip-tunnel route to bypass ad blockers
- Update next.config.mjs with withSentryConfig wrapper
- Integrate Sentry.captureException in error.tsx and global-error.tsx
- Support env vars: GLITCHTIP_DSN, NEXT_PUBLIC_GLITCHTIP_DSN, GLITCHTIP_URL, etc.
2026-01-18 21:33:59 +01:00
489b975911 feat: Improve Sessions and Buddies pages with modern UI
- Rename 'Events' to 'Tastings' in nav
- Sessions page: Create, list, delete sessions with sticky header
- Buddies page: Add, search, delete buddies with linked/unlinked sections
- Both pages match new home view design language
2026-01-18 21:24:53 +01:00
1d02079df3 fix: Fix navigation links and restore LanguageSwitcher
- Add missing nav keys to types.ts, de.ts, en.ts (sessions, buddies, stats, wishlist)
- Add LanguageSwitcher back to authenticated header
- Create /sessions page with SessionList
- Create /buddies page with BuddyList
- Create /stats page with StatsDashboard
- Create /wishlist placeholder page
2026-01-18 21:18:25 +01:00
d109dfad0e fix: Log empty OCR results to help debug TextDetector availability
- Cascade OCR now saves a log entry even when no text is detected
- Logs ocrMethod as 'text_detector' or 'not_supported' for debugging
- Helps identify when browsers block the TextDetector API
2026-01-18 20:57:41 +01:00
9ba0825bcd feat: Add Spotify-style backdrop, Cascade OCR, Smart Scan Flow & OCR Dashboard
- BottleGrid: Implement blurred backdrop effect for bottle cards
- Cascade OCR: TextDetector → RegEx → Fuzzy Match → window.ai pipeline
- Smart Scan: Native OCR for Android, Live Text fallback for iOS
- OCR Dashboard: Admin page at /admin/ocr-logs with stats and scan history
- Features: Add feature flags in src/config/features.ts
- SQL: Add ocr_logs table migration
- Services: Update analyze-bottle to use OpenRouter, add save-ocr-log
2026-01-18 20:38:48 +01:00
83e852e5fb Fix onboarding tutorial visibility and apply security remediation tasks (ABV sanitization, i18n hardening, regex escaping) 2026-01-06 13:19:05 +01:00
68ac857091 feat: restore scan quality, implement standardized naming, and add cask_type integration 2026-01-05 23:33:10 +01:00
21ca704abc Fix Storage RLS, refactor AI analysis to Base64, and improve ScanAndTaste save flow 2026-01-04 23:50:35 +01:00
71586fd6a8 Refactor: Centralized Supabase Auth and implemented Auth Guards to prevent 401 errors 2026-01-04 23:00:18 +01:00
9d6a8b358f feat: public split visibility, RLS recursion fixes, and consolidated tasting permission management
- Added public discovery section for active splits on the landing page
- Refactored split detail page for guest support and login redirects
- Extracted SplitCard component for reuse
- Consolidated RLS policies for bottles and tastings to resolve permission errors
- Added unified SQL consolidation script for RLS and naming fixes
- Enhanced service logging for better database error diagnostics
2025-12-28 22:02:46 +01:00
332bfdaf02 style: redesign app following HIG with larger hero images and refined typography 2025-12-28 20:38:10 +01:00
c51cd23d5e feat: enhanced AI usage logging (model, provider, response) and fixed build blockers 2025-12-27 00:10:55 +01:00
20659567fd feat: mobile-first refactor for BottleDetails & RLS security/performance optimizations 2025-12-26 23:58:35 +01:00
20f7436e66 fix: Dynamic credit initialization from subscription plan
- Removed hardcoded 100 credits from lazy initialization
- Now looks up user's subscription plan and uses monthly_credits
- Set total_purchased to 0 (previously incorrectly set to 100)
- Fallback to 10 credits if no plan found (starter default)
2025-12-26 23:16:13 +01:00
a3915bd610 feat: Dynamic credit initialization based on subscription plan
New trigger creates:
- Profile (username from metadata)
- Subscription (starter plan by default)
- Credits (from plan's monthly_credits, not hardcoded)

Includes RLS policies for self-insert fallback
2025-12-26 23:11:58 +01:00
37634c26c8 fix: Show plan monthly_credits when user has no credits entry yet
UserStatusBadge now falls back to plan's monthly_credits (e.g., 10 for Starter)
instead of showing 0 when user_credits entry doesn't exist
2025-12-26 23:10:02 +01:00
9e2abb0aa3 fix: Update handle_new_user trigger for reliable registration
- Simplified trigger to only create profile
- Added exception handling to prevent user creation failures
- Subscription created client-side after successful signup
2025-12-26 23:05:30 +01:00
30a716f3e2 feat: Add UserStatusBadge showing subscription level and credits
New component in header shows:
- Subscription plan badge (Starter/Bronze/Silver/Gold with icons)
- AI credits balance with sparkle icon

Also includes SQL migration for user_subscriptions RLS fix
2025-12-26 23:02:20 +01:00
02bd025bce feat: Enhanced registration with username, name, and auto-subscription
Registration form now includes:
- Username field (required, unique, validated)
- Full name field (optional)
- Auto-validates username format and availability
- Auto-creates 'starter' subscription on signup

Login form unchanged (email + password only)
2025-12-26 22:52:47 +01:00
73a057b1e3 feat: Hide tutorial on login, add 'Angemeldet bleiben' checkbox
- OnboardingTutorial: Skip on /login, /auth, /register paths
- AuthForm: Added remember-me checkbox (default: checked)
- Session persistence based on checkbox selection
2025-12-26 22:46:22 +01:00
1017ec2c57 fix: Add Glengyle distillery (producer of Kilkerran)
Glengyle is the actual distillery name, Kilkerran is the brand.
AI returns 'Glengyle' which was being mismatched to 'Glenglassaugh'.
2025-12-26 22:34:49 +01:00
e3d61af40a fix: Make distillery fuzzy matching stricter
- Threshold: 0.25 (was 0.4)
- Score check: 0.3 (was 0.5)
- minMatchCharLength: 4 (was 3)

Prevents false positives like 'Kilkeran' → 'Glenglassaugh'
2025-12-26 22:30:59 +01:00
883b2b61b4 feat: Add Fuse.js distillery name normalization
New: src/lib/distillery-matcher.ts
- normalizeDistillery(): Fuzzy matches AI responses against distilleries.json
- cleanBottleName(): Removes distillery from bottle name to avoid duplication
- normalizeWhiskyData(): Combined helper for both operations

Example transformations:
- 'ARDNAHOE DISTILLERY CO LTD' → 'Ardnahoe'
- 'Laphroaig 10 Year Old' → '10 Year Old' (with distillery in separate field)

Integration:
- gemini-vision.ts now normalizes results after AI response
- Enables consistent distillery names for enrichment cache
2025-12-26 22:20:31 +01:00
daf6c86633 feat: Add distillery enrichment cache
Caches AI enrichment results per distillery to save API calls:
- New table: enrichment_cache (distillery, tags, hit_count)
- New service: cache-enrichment.ts (get, save, increment, stats)
- enrich-data.ts checks cache before AI query
- Saves to cache after successful AI response
- Returns cached: true/false flag for transparency

Benefits:
- 0 API cost for repeated distillery scans
- Near-instant response for cached distilleries
- Shared across all users
2025-12-26 22:12:27 +01:00
537081cd1f fix: Add 'use client' to impressum page for onClick handlers 2025-12-26 22:05:34 +01:00
e6278e5ec6 feat: Add footer with legal links (Impressum, Datenschutz, Einstellungen) 2025-12-26 22:02:00 +01:00
f1990ebf2d feat: Add bot-proof Impressum page
- Email displayed as user[at]domain with onClick handler
- Phone displayed split with dashes
- All contact info clickable but not easily scraped
- Ready to fill in at src/app/impressum/page.tsx
2025-12-26 21:58:37 +01:00
f21b2738ad feat: Add onboarding tutorial and improved empty states
Onboarding Tutorial:
- 5-step walkthrough for new users
- Welcome, Scan, Taste, Sessions, Ready steps
- Skippable, stores completion in localStorage
- Beautiful full-screen overlay with animations

Empty States:
- SessionList: Visual empty state with icon and description
- BuddyList: Visual empty state with icon and description
- Reusable EmptyState component ready for more usage

Layout: Added OnboardingTutorial and CookieBanner
2025-12-26 21:43:26 +01:00
82531c5aff feat: Add navigation labels and EmptyState component
Bottom Navigation:
- Added text labels under icons (Start, Sammlung, Filter, Profil)
- Elevated SCAN button with label
- Improved touch targets and visual hierarchy

EmptyState Component:
- Reusable component for empty lists
- Icon, title, description, optional CTA button
- Ready for use in SessionList, BuddyList, BottleGrid
2025-12-26 21:40:31 +01:00
af54d8061c fix: Use username field instead of display_name in profile
- Updated profile-actions.ts to use username column
- Updated ProfileForm.tsx to use username
- Updated settings page to pass username
- Matches database schema (profiles.username)
2025-12-26 21:35:41 +01:00
f74090c8a5 feat: Link profile button to /settings page
- Added router.push('/settings') to onProfile handler
- User icon in bottom nav now navigates to settings
2025-12-26 21:33:36 +01:00
6c37481d17 feat: Add EU cookie banner and user settings page
Cookie Banner:
- GDPR-compliant consent banner
- Shows on first visit, stores consent in localStorage
- Two options: Accept All / Only Essential
- Dark theme with smooth animations

Settings Page (/settings):
- Profile form: display name editing
- Password change with validation
- Cookie settings info section
- Privacy links and account info

New files:
- src/hooks/useCookieConsent.ts
- src/components/CookieBanner.tsx
- src/components/ProfileForm.tsx
- src/components/PasswordChangeForm.tsx
- src/services/profile-actions.ts
- src/app/settings/page.tsx
2025-12-26 21:30:00 +01:00
9c5f538efb refactor: Consolidate all AI calls to use OpenRouter provider switch
- bulk-scan.ts: Now uses OpenRouter for batch analysis
- scan-label.ts: Now uses OpenRouter with Gemini fallback
- analyze-bottle.ts: Now uses OpenRouter with Gemini fallback
- All AI calls now respect AI_PROVIDER env variable
- Uses Nebius/FP8 provider preferences consistently
- Unified logging: [FunctionName] Using provider: openrouter/gemini
2025-12-26 21:21:56 +01:00
e978499b54 feat: Switch enrichment to use OpenRouter provider
- enrichData now uses same AI provider switch as vision
- Both scan and enrichment use OpenRouter by default
- Added retry logic for rate limits
- Uses Nebius/FP8 provider preferences
- Logs which provider is being used
2025-12-26 00:16:48 +01:00
ce49c9e347 feat: Route OpenRouter requests via Nebius with FP8 quantization
- Added OPENROUTER_PROVIDER_PREFERENCES config
- Prioritizes Nebius provider for better availability/speed
- Uses FP8 quantization for quality/speed balance
- Falls back to other providers if Nebius unavailable
2025-12-26 00:12:42 +01:00
8cf51d4aea fix: Add retry logic for OpenRouter 429 rate limit errors
- 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
2025-12-26 00:06:21 +01:00
8ccd600dcb feat: Instant editor opening with background AI analysis
- Editor opens immediately with placeholder data
- AI analyzes label in background while user can already edit
- Blue 'KI analysiert...' banner shows when AI is still working
- User edits preserved when AI results arrive (dirty field tracking)
- Model/provider shown in admin perf overlay
- Renamed 'CLOUD' to 'AI' in perf display
2025-12-26 00:02:38 +01:00
fb2a8d0f7b feat: Add OpenRouter as AI provider with easy switch
- 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
2025-12-25 23:56:24 +01:00