import React, { useState, useMemo } from 'react'; import { ShovelIcon, PlusCircleIcon, Trash2Icon } from '../components/icons'; type PotShape = 'rectangular' | 'round'; type Units = 'cm' | 'in'; const SoilVolumeCalculatorView: React.FC = () => { const [units, setUnits] = useState('in'); const [shape, setShape] = useState('rectangular'); const [dimensions, setDimensions] = useState({ length: 12, width: 8, depth: 4, diameter: 10 }); const [recipe, setRecipe] = useState([ { id: 1, name: 'Akadama', percentage: 40 }, { id: 2, name: 'Pumice', percentage: 30 }, { id: 3, name: 'Lava Rock', percentage: 30 }, ]); const totalPercentage = useMemo(() => recipe.reduce((sum, item) => sum + item.percentage, 0), [recipe]); const volumeCm3 = useMemo(() => { const d = dimensions; const toCm = units === 'in' ? 2.54 : 1; if (shape === 'rectangular') { return (d.length * toCm) * (d.width * toCm) * (d.depth * toCm); } else { // round const radius = (d.diameter * toCm) / 2; return Math.PI * (radius * radius) * (d.depth * toCm); } }, [dimensions, shape, units]); const handleRecipeChange = (id: number, field: 'name' | 'percentage', value: string | number) => { setRecipe(prev => prev.map(item => item.id === id ? { ...item, [field]: value } : item)); }; const addComponent = () => { setRecipe(prev => [...prev, { id: Date.now(), name: 'New Component', percentage: 0 }]); }; const removeComponent = (id: number) => { setRecipe(prev => prev.filter(item => item.id !== id)); }; const renderVolume = (volumeLiters: number) => (
{volumeLiters.toFixed(2)} L{(volumeLiters * 1.05669).toFixed(2)} qts{(volumeLiters * 0.264172).toFixed(2)} gal
); return (

Soil Mix Calculator

Mix the perfect amount of soil for your pot. No more waste or running out halfway through repotting.

1. Pot Dimensions

{shape === 'rectangular' ? ( <>
setDimensions(d => ({...d, length: Number(e.target.value)}))} className="w-full mt-1 p-2 border rounded-md" />
setDimensions(d => ({...d, width: Number(e.target.value)}))} className="w-full mt-1 p-2 border rounded-md" />
) : (
setDimensions(d => ({...d, diameter: Number(e.target.value)}))} className="w-full mt-1 p-2 border rounded-md" />
)}
setDimensions(d => ({...d, depth: Number(e.target.value)}))} className="w-full mt-1 p-2 border rounded-md" />

2. Soil Recipe

{recipe.map(item => (
handleRecipeChange(item.id, 'name', e.target.value)} className="w-full p-2 border rounded-md" /> handleRecipeChange(item.id, 'percentage', Number(e.target.value))} className="w-24 p-2 border rounded-md" /> %
))}
100 ? 'bg-red-500' : 'bg-green-600'}`} style={{ width: `${Math.min(100, totalPercentage)}%` }}>

Total: {totalPercentage}%

Component Volumes Needed

Total Pot Volume:

{renderVolume(volumeCm3 / 1000)}

{recipe.map(item => { const componentVolumeL = (volumeCm3 / 1000) * (item.percentage / 100); return (
{item.name} {item.percentage}%
{renderVolume(componentVolumeL)}
) })}
{totalPercentage !== 100 && (

Your recipe percentages must add up to 100% for an accurate calculation.

)}
); }; export default SoilVolumeCalculatorView;