Introcuced a Free LLM for easier food input
This commit is contained in:
@@ -29,11 +29,51 @@ export default function ProductNotFoundForm({
|
||||
const [mealType, setMealType] = useState(initialMealType || defaultMealType())
|
||||
const [error, setError] = useState('')
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [description, setDescription] = useState('')
|
||||
const [isEstimating, setIsEstimating] = useState(false)
|
||||
const [estimateError, setEstimateError] = useState('')
|
||||
const [wasEstimated, setWasEstimated] = useState(false)
|
||||
|
||||
function optionalDecimal(value) {
|
||||
return value === '' ? undefined : parseDecimal(value)
|
||||
}
|
||||
|
||||
function formatEstimate(value) {
|
||||
return String(Math.round(value * 10) / 10)
|
||||
}
|
||||
|
||||
async function handleEstimate() {
|
||||
if (description.trim().length < 2) return
|
||||
setEstimateError('')
|
||||
setIsEstimating(true)
|
||||
try {
|
||||
const { data } = await apiClient.post('/api/products/estimate', {
|
||||
description: description.trim(),
|
||||
})
|
||||
setName(data.name)
|
||||
setCalories(formatEstimate(data.calories))
|
||||
setCarbs(formatEstimate(data.carbs))
|
||||
setProtein(formatEstimate(data.protein))
|
||||
setFat(formatEstimate(data.fat))
|
||||
setSugar(formatEstimate(data.sugar))
|
||||
setFiber(formatEstimate(data.fiber))
|
||||
setSaturatedFat(formatEstimate(data.saturated_fat))
|
||||
setSalt(formatEstimate(data.salt))
|
||||
if (mode === 'log') {
|
||||
setAmountG(formatEstimate(data.portion_g))
|
||||
}
|
||||
setWasEstimated(true)
|
||||
} catch (err) {
|
||||
setEstimateError(
|
||||
err.response?.status === 503
|
||||
? 'KI-Schätzung gerade nicht verfügbar.'
|
||||
: 'Schätzung fehlgeschlagen. Bitte erneut versuchen.',
|
||||
)
|
||||
} finally {
|
||||
setIsEstimating(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit(e) {
|
||||
e.preventDefault()
|
||||
setError('')
|
||||
@@ -72,7 +112,7 @@ export default function ProductNotFoundForm({
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-end justify-center bg-black/50 sm:items-center">
|
||||
<div className="w-full max-w-sm rounded-t-2xl bg-white p-6 sm:rounded-2xl dark:bg-gray-800">
|
||||
<div className="max-h-[90vh] w-full max-w-sm overflow-y-auto rounded-t-2xl bg-white p-6 sm:rounded-2xl dark:bg-gray-800">
|
||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-50">
|
||||
{barcode ? 'Produkt nicht gefunden' : 'Neues Produkt anlegen'}
|
||||
</h2>
|
||||
@@ -82,6 +122,42 @@ export default function ProductNotFoundForm({
|
||||
: 'Bitte Nährwerte pro 100g eintragen'}
|
||||
</p>
|
||||
|
||||
<div className="mb-4 rounded-lg border border-dashed border-gray-300 p-3 dark:border-gray-600">
|
||||
<label className={labelClass}>Nährwerte per KI schätzen (optional)</label>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault()
|
||||
handleEstimate()
|
||||
}
|
||||
}}
|
||||
placeholder="z. B. Döner mit allem"
|
||||
disabled={isEstimating}
|
||||
className="min-w-0 flex-1 rounded-lg border border-gray-300 px-3 py-2 text-base text-gray-900 focus:border-emerald-500 focus:outline-none disabled:opacity-60 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-50"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleEstimate}
|
||||
disabled={isEstimating || description.trim().length < 2}
|
||||
className="shrink-0 rounded-lg bg-emerald-600 px-3 py-2 text-sm font-medium text-white active:bg-emerald-700 disabled:opacity-60"
|
||||
>
|
||||
{isEstimating ? '…' : 'Schätzen'}
|
||||
</button>
|
||||
</div>
|
||||
{estimateError && (
|
||||
<p className="mt-2 text-sm text-red-600 dark:text-red-400">{estimateError}</p>
|
||||
)}
|
||||
{wasEstimated && !estimateError && (
|
||||
<p className="mt-2 text-xs text-amber-700 dark:text-amber-400">
|
||||
Geschätzte Werte — bitte prüfen und bei Bedarf korrigieren.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-3">
|
||||
<div>
|
||||
<label className={labelClass}>Name</label>
|
||||
|
||||
Reference in New Issue
Block a user