"use client"; import React, { useEffect, useState, useRef } from 'react'; import { useRouter, useParams } from 'next/navigation'; import Link from 'next/link'; import PageLayout from '../../../../components/PageLayout'; import useCoffeeManagement, { CoffeeItem } from '../../hooks/useCoffeeManagement'; import { PhotoIcon } from '@heroicons/react/24/solid'; export default function EditSubscriptionPage() { const router = useRouter(); // next/navigation app router dynamic param const params = useParams(); const idParam = params?.id; const id = typeof idParam === 'string' ? parseInt(idParam, 10) : Array.isArray(idParam) ? parseInt(idParam[0], 10) : NaN; const { listProducts, updateProduct } = useCoffeeManagement(); const [item, setItem] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Form state const [title, setTitle] = useState(''); const [description, setDescription] = useState(''); const [price, setPrice] = useState(''); const [currency, setCurrency] = useState('EUR'); const [isFeatured, setIsFeatured] = useState(false); const [state, setState] = useState(true); const [pictureFile, setPictureFile] = useState(undefined); const [previewUrl, setPreviewUrl] = useState(null); const [removeExistingPicture, setRemoveExistingPicture] = useState(false); const fileInputRef = useRef(null); useEffect(() => { let active = true; async function load() { if (!id || Number.isNaN(id)) { setError('Invalid subscription id'); setLoading(false); return; } try { const all = await listProducts(); const found = all.find((p: CoffeeItem) => p.id === id) || null; if (!active) return; if (!found) { setError('Subscription not found'); } else { setItem(found); setTitle(found.title || ''); setDescription(found.description || ''); setPrice(found.price != null ? String(found.price) : ''); setCurrency(found.currency || 'EUR'); setIsFeatured(!!found.is_featured); setState(!!found.state); setRemoveExistingPicture(false); } } catch (e: any) { if (active) setError(e?.message ?? 'Failed to load subscription'); } finally { if (active) setLoading(false); } } load(); return () => { active = false; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [id]); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!item) return; setError(null); try { const numericPrice = Number(price); if (!Number.isFinite(numericPrice) || numericPrice < 0) { setError('Price must be a valid non-negative number'); return; } await updateProduct(item.id, { title: title.trim(), description: description.trim(), price: numericPrice, currency: currency.trim(), is_featured: isFeatured, state, pictureFile, removePicture: removeExistingPicture && !pictureFile ? true : false, }); router.push('/admin/subscriptions'); } catch (e: any) { setError(e?.message ?? 'Update failed'); } } useEffect(() => { if (pictureFile) { const url = URL.createObjectURL(pictureFile); setPreviewUrl(url); return () => URL.revokeObjectURL(url); } else { setPreviewUrl(null); } }, [pictureFile]); function handleSelectFile(file?: File) { if (!file) return; const allowed = ['image/jpeg','image/png','image/webp']; if (!allowed.includes(file.type)) { setError('Invalid image type. Allowed: JPG, PNG, WebP'); return; } if (file.size > 10 * 1024 * 1024) { setError('Image exceeds 10MB limit'); return; } setError(null); setPictureFile(file); setRemoveExistingPicture(false); // selecting new overrides removal flag } return (

Edit Coffee

Update details of the coffee.

Back to list
{loading && (
Loading subscription…
)} {error && !loading && (
{error}
)} {!loading && item && (
setTitle(e.target.value)} />
setPrice(e.target.value)} />
setCurrency(e.target.value.toUpperCase().slice(0,3))} />
setIsFeatured(e.target.checked)} />
setState(e.target.checked)} />