import * as React from 'react'; import Head from 'next/head'; import { useRouter } from 'next/router'; import { useForm } from 'react-hook-form'; import { MobileHeader, BottomNav } from 'components/mobile'; import { isOnline, queuePlantRegistration } from 'lib/mobile/offline'; import { getCamera, CapturedImage } from 'lib/mobile/camera'; interface QuickAddForm { name: string; species: string; variety?: string; parentId?: string; } const commonSpecies = [ 'Tomato', 'Pepper', 'Basil', 'Lettuce', 'Cucumber', 'Spinach', 'Kale', 'Carrot', 'Radish', 'Bean', 'Pea', 'Squash', 'Other', ]; export default function QuickAddPage() { const router = useRouter(); const { register, handleSubmit, watch, setValue, formState: { errors } } = useForm(); const [isSubmitting, setIsSubmitting] = React.useState(false); const [showCamera, setShowCamera] = React.useState(false); const [capturedImage, setCapturedImage] = React.useState(null); const [location, setLocation] = React.useState<{ lat: number; lng: number } | null>(null); const [locationError, setLocationError] = React.useState(null); const [submitResult, setSubmitResult] = React.useState<{ success: boolean; message: string; offline?: boolean } | null>(null); const videoRef = React.useRef(null); const selectedSpecies = watch('species'); // Get location on mount React.useEffect(() => { if ('geolocation' in navigator) { navigator.geolocation.getCurrentPosition( (position) => { setLocation({ lat: position.coords.latitude, lng: position.coords.longitude, }); }, (error) => { setLocationError(error.message); }, { enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 } ); } }, []); const handleCameraCapture = async () => { const camera = getCamera(); if (showCamera && videoRef.current) { try { const image = await camera.capturePhoto(); setCapturedImage(image); camera.stopCamera(); setShowCamera(false); } catch (error) { console.error('Failed to capture:', error); } } else { setShowCamera(true); if (videoRef.current) { try { await camera.startCamera(videoRef.current); } catch (error) { console.error('Failed to start camera:', error); setShowCamera(false); } } } }; const onSubmit = async (data: QuickAddForm) => { setIsSubmitting(true); setSubmitResult(null); const plantData = { ...data, location, image: capturedImage?.dataUrl, registeredAt: new Date().toISOString(), }; try { if (isOnline()) { // Online: submit directly to API const response = await fetch('/api/plants/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(plantData), }); if (response.ok) { const result = await response.json(); setSubmitResult({ success: true, message: `${data.name} registered successfully!`, }); setTimeout(() => { router.push(`/plants/${result.id}`); }, 2000); } else { throw new Error('Registration failed'); } } else { // Offline: queue for later await queuePlantRegistration(plantData); setSubmitResult({ success: true, message: `${data.name} saved offline. It will sync when you're back online.`, offline: true, }); setTimeout(() => { router.push('/m'); }, 2000); } } catch (error) { setSubmitResult({ success: false, message: 'Failed to register plant. Please try again.', }); } finally { setIsSubmitting(false); } }; return ( <> Quick Add Plant - LocalGreenChain
{/* Photo capture */}
{showCamera ? (
) : capturedImage ? (
Captured plant
) : ( )}
{/* Plant name */}
{errors.name && (

{errors.name.message}

)}
{/* Species selection */}
{commonSpecies.map((species) => ( ))}
{errors.species && (

{errors.species.message}

)}
{/* Variety (optional) */}
{/* Parent plant (optional) */}

If this plant is a clone or seedling from another plant

{/* Location status */}
{location ? ( <>

Location captured

{location.lat.toFixed(4)}, {location.lng.toFixed(4)}

) : locationError ? ( <>

Location unavailable

{locationError}

) : ( <>

Getting location...

Please allow location access

)}
{/* Submit result */} {submitResult && (
{submitResult.success ? ( ) : ( )}

{submitResult.message}

{submitResult.offline && (

Will sync automatically when online

)}
)} {/* Submit button */}
); }