feat: implement Save & Taste flow in CameraCapture
This commit is contained in:
@@ -1,17 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { Camera, Upload, CheckCircle2, AlertCircle, Sparkles, ExternalLink } from 'lucide-react';
|
||||
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
|
||||
import { analyzeBottle } from '@/services/analyze-bottle';
|
||||
import { saveBottle } from '@/services/save-bottle';
|
||||
import { BottleMetadata } from '@/types/whisky';
|
||||
import { savePendingBottle } from '@/lib/offline-db';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { findMatchingBottle } from '@/services/find-matching-bottle';
|
||||
import Link from 'next/link';
|
||||
|
||||
// ... (skipping to line 192 in the actual file, index adjust needed)
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
|
||||
interface CameraCaptureProps {
|
||||
onImageCaptured?: (base64Image: string) => void;
|
||||
@@ -21,6 +12,10 @@ interface CameraCaptureProps {
|
||||
|
||||
export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onSaveComplete }: CameraCaptureProps) {
|
||||
const supabase = createClientComponentClient();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const sessionId = searchParams.get('session_id');
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
@@ -29,6 +24,7 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
|
||||
const [analysisResult, setAnalysisResult] = useState<BottleMetadata | null>(null);
|
||||
const [isQueued, setIsQueued] = useState(false);
|
||||
const [matchingBottle, setMatchingBottle] = useState<{ id: string; name: string } | null>(null);
|
||||
const [lastSavedId, setLastSavedId] = useState<string | null>(null);
|
||||
|
||||
const handleCapture = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const file = event.target.files?.[0];
|
||||
@@ -100,11 +96,9 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
|
||||
|
||||
const response = await saveBottle(analysisResult, previewUrl, user.id);
|
||||
|
||||
if (response.success) {
|
||||
setPreviewUrl(null);
|
||||
setAnalysisResult(null);
|
||||
if (response.success && response.data) {
|
||||
setLastSavedId(response.data.id);
|
||||
if (onSaveComplete) onSaveComplete();
|
||||
// Optionale Erfolgsmeldung oder Redirect
|
||||
} else {
|
||||
setError(response.error || 'Speichern fehlgeschlagen.');
|
||||
}
|
||||
@@ -190,9 +184,38 @@ export default function CameraCapture({ onImageCaptured, onAnalysisComplete, onS
|
||||
className="hidden"
|
||||
/>
|
||||
|
||||
{matchingBottle ? (
|
||||
{lastSavedId ? (
|
||||
<div className="flex flex-col gap-3 w-full animate-in zoom-in-95 duration-300">
|
||||
<div className="flex items-center gap-2 text-green-600 font-bold justify-center p-2">
|
||||
<CheckCircle2 size={24} className="text-green-500" />
|
||||
Erfolgreich gespeichert!
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
const url = `/bottles/${lastSavedId}${sessionId ? `?session_id=${sessionId}` : ''}`;
|
||||
router.push(url);
|
||||
}}
|
||||
className="w-full py-4 px-6 bg-zinc-900 dark:bg-zinc-100 text-white dark:text-zinc-900 rounded-2xl font-black uppercase tracking-widest flex items-center justify-center gap-2 hover:bg-zinc-800 dark:hover:bg-white transition-all shadow-xl"
|
||||
>
|
||||
Jetzt verkosten
|
||||
<ChevronRight size={20} />
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => {
|
||||
setPreviewUrl(null);
|
||||
setAnalysisResult(null);
|
||||
setLastSavedId(null);
|
||||
}}
|
||||
className="w-full py-3 px-6 text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200 font-bold transition-colors"
|
||||
>
|
||||
Später (Zurück zur Liste)
|
||||
</button>
|
||||
</div>
|
||||
) : matchingBottle ? (
|
||||
<Link
|
||||
href={`/bottles/${matchingBottle.id}`}
|
||||
href={`/bottles/${matchingBottle.id}${sessionId ? `?session_id=${sessionId}` : ''}`}
|
||||
className="w-full py-4 px-6 bg-amber-600 hover:bg-amber-700 text-white rounded-xl font-semibold flex items-center justify-center gap-2 transition-all active:scale-[0.98] shadow-lg shadow-amber-600/20"
|
||||
>
|
||||
<ExternalLink size={20} />
|
||||
|
||||
Reference in New Issue
Block a user