
import React, { useMemo, useState } from "react";
export default function EVChargeTimeSimulator() {
const [batteryKWh, setBatteryKWh] = useState(60);
const [socStart, setSocStart] = useState(0);
const [socTarget, setSocTarget] = useState(80);
const [powerKW, setPowerKW] = useState(7.4);
const [vehicleMaxAC, setVehicleMaxAC] = useState(7.4);
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
function hoursToHMM(h) {
if (!isFinite(h) || h <= 0) return "0 h";
const totalMinutes = Math.round(h * 60);
const hh = Math.floor(totalMinutes / 60);
const mm = totalMinutes % 60;
if (hh === 0) return `${mm} min`;
if (mm === 0) return `${hh} h`;
return `${hh} h ${mm} min`;
}
const result = useMemo(() => {
const soc0 = clamp(Number(socStart) || 0, 0, 99);
const soc1 = clamp(Number(socTarget) || 0, soc0 + 1, 100);
const cap = Math.max(1, Number(batteryKWh) || 0);
const pIn = Math.max(0.1, Number(powerKW) || 0);
const vehAC = Math.max(0.1, Number(vehicleMaxAC) || 0);
const energyToAdd = cap * (soc1 - soc0) / 100;
const effectivePower = Math.min(pIn, vehAC);
const timeH = energyToAdd / effectivePower;
return {
energyToAdd,
timeH,
};
}, [batteryKWh, socStart, socTarget, powerKW, vehicleMaxAC]);
const cards = [
{ label: "Énergie chargée dans le véhicule", value: `${result.energyToAdd.toFixed(1)} kWh` },
{ label: "Durée de charge estimée", value: hoursToHMM(result.timeH) }
];
function DoubleRange({ min = 0, max = 100, step = 10, low, high, onChange }) {
const gap = step;
const lowPct = ((low - min) / (max - min)) * 100;
const highPct = ((high - min) / (max - min)) * 100;
return (
);
}
function QuickButton({ children, onClick, active }) {
const base = "px-3 py-1 rounded-full border text-sm hover:shadow transition-colors";
const activeClass = active ? "bg-gradient-to-r from-blue-500 to-green-400 text-white border-blue-600" : "bg-white text-black";
return (
);
}
return (
{ setSocStart(low); setSocTarget(high); }}
/>
);
}
Min: 0%
Max: 100%
{
const v = Number(e.target.value);
const clamped = Math.min(v, high - gap);
onChange({ low: clamped, high });
}}
list="tickmarks"
className="absolute left-0 right-0 top-1/2 -translate-y-1/2 w-full appearance-none bg-transparent pointer-events-auto"
/>
{
const v = Number(e.target.value);
const clamped = Math.max(v, low + gap);
onChange({ low, high: clamped });
}}
list="tickmarks"
className="absolute left-0 right-0 top-1/2 -translate-y-1/2 w-full appearance-none bg-transparent pointer-events-auto"
/>
Départ: {low}%
Cible: {high}%
setBatteryKWh(Number(e.target.value))}
className="w-full mt-1 px-3 py-2 rounded-xl border border-blue-300 bg-white shadow-sm" />
{[2.3, 3.7, 7.4, 11, 22].map((v) => (
setPowerKW(v)} active={powerKW === v}>{v} kW
))}
{[3.7, 7.4, 11, 22].map((v) => (
setVehicleMaxAC(v)} active={vehicleMaxAC === v}>{v} kW
))}
{cards.map((c) => (
))}
{c.label}
{c.value}
