import { useState, useEffect, useCallback } from 'react'; import Link from 'next/link'; import { listMedicines, createMedicine, deleteMedicine } from '@/services/medicines'; import { MedicineForm, StrengthUnit, MedicineCategory } from '@meshitrack/shared'; import type { CreateMedicineInput } from '@meshitrack/shared'; type Medicine = { _id: string; name: string; form: string; strength: number; strengthUnit: string; category: string; tags: string[]; }; const FORM_LABELS: Record = { tablet: 'Tablet', capsule: 'Capsule', liquid: 'Liquid', injection: 'Injection', other: 'Other', }; const CATEGORY_LABELS: Record = { prescription: 'Prescription', otc: 'OTC', supplement: 'Supplement', other: 'Other', }; const CATEGORY_COLORS: Record = { prescription: 'bg-blue-100 text-blue-700', otc: 'bg-green-100 text-green-700', supplement: 'bg-purple-100 text-purple-700', other: 'bg-gray-100 text-gray-700', }; export function LibraryTab({ householdId }: { householdId: string }) { const [medicines, setMedicines] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [showForm, setShowForm] = useState(false); const [search, setSearch] = useState(''); const [filterCategory, setFilterCategory] = useState(''); const [filterForm, setFilterForm] = useState(''); const fetchMedicines = useCallback(async () => { if (!householdId) return; setLoading(true); try { const result = await listMedicines(householdId, { q: search || undefined, category: filterCategory || undefined, form: filterForm || undefined, limit: 50, }); setMedicines(result.data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load medicines'); } finally { setLoading(false); } }, [householdId, search, filterCategory, filterForm]); useEffect(() => { if (householdId) { fetchMedicines(); } }, [householdId, fetchMedicines]); async function handleDelete(id: string, name: string) { if (!householdId || !confirm(`Delete "${name}"?`)) return; try { await deleteMedicine(householdId, id); setMedicines((prev) => prev.filter((m) => m._id !== id)); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete'); } } return (
{error && (
{error}
)} {showForm && ( { setShowForm(false); fetchMedicines(); }} onCancel={() => setShowForm(false)} /> )}
setSearch(e.target.value)} placeholder="Search medicines..." className="w-full max-w-md rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none" />
{loading ? (
{Array.from({ length: 3 }).map((_, i) => (
))}
) : medicines.length === 0 ? (
{search || filterCategory || filterForm ? 'No medicines found matching your filters.' : 'No medicines yet. Add your first one above.'}
) : (
{medicines.map((med) => (

{med.name}

{med.strength} {med.strengthUnit} {FORM_LABELS[med.form] ?? med.form}

{CATEGORY_LABELS[med.category] ?? med.category}
))}
)}
); } function CreateMedicineForm({ householdId, onCreated, onCancel, }: { householdId: string; onCreated: () => void; onCancel: () => void; }) { const [formData, setFormData] = useState({ name: '', form: MedicineForm.TABLET, strength: 0, strengthUnit: StrengthUnit.MG, category: MedicineCategory.OTC, tags: [], }); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(''); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(''); setSubmitting(true); try { await createMedicine(householdId, { ...formData, name: formData.name.trim(), strength: Number(formData.strength), }); onCreated(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create medicine'); } finally { setSubmitting(false); } } return (

Add Medicine

{error && (
{error}
)}
setFormData({ ...formData, name: e.target.value })} placeholder="e.g. Metformin" className="w-full rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none" />
setFormData({ ...formData, strength: Number(e.target.value) })} placeholder="500" className="w-full rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none" />
setFormData({ ...formData, notes: e.target.value || undefined })} placeholder="Any additional notes" className="w-full rounded-lg border px-3 py-2 text-sm focus:border-primary-500 focus:ring-1 focus:ring-primary-500 focus:outline-none" />
); }