diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 6dbb59e..5eb2b60 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -25,7 +25,8 @@ export default function App() { const [volumeMax, setVolumeMax] = useState(1000); const [timeSeconds, setTimeSeconds] = useState(300); const [rangePoints, setRangePoints] = useState(10); - const [configDirty, setConfigDirty] = useState(false); + const [configDirty, setConfigDirty] = useState(false); // qualquer campo mudou + const [backendDirty, setBackendDirty] = useState(false); // só campos que precisam do backend const [targetSymbol, setTargetSymbol] = useState('EURUSD'); // History Mode @@ -336,7 +337,7 @@ export default function App() { MODO DE FECHAMENTO { setCloseMode(e.target.value); setConfigDirty(true); }} + onChange={e => { setCloseMode(e.target.value); setConfigDirty(true); setBackendDirty(true); }} className="w-full bg-[#151B26] border border-slate-700 rounded-md px-2 py-1.5 text-xs text-slate-300 outline-none" > Delta @@ -351,12 +352,12 @@ export default function App() { DELTA MÁX - { setDeltaMax(d => Math.max(100, d - 100)); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− + { setDeltaMax(d => Math.max(100, d - 100)); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− { setDeltaMax(Math.max(100, Number(e.target.value) || 100)); setConfigDirty(true); }} + onChange={e => { setDeltaMax(Math.max(100, Number(e.target.value) || 100)); setConfigDirty(true); setBackendDirty(true); }} className="flex-1 bg-transparent text-center text-sm font-bold text-white outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" /> - { setDeltaMax(d => d + 100); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ + { setDeltaMax(d => d + 100); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ )} @@ -364,12 +365,12 @@ export default function App() { VOLUME MÁX - { setVolumeMax(v => Math.max(100, v - 100)); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− + { setVolumeMax(v => Math.max(100, v - 100)); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− { setVolumeMax(Math.max(100, Number(e.target.value) || 100)); setConfigDirty(true); }} + onChange={e => { setVolumeMax(Math.max(100, Number(e.target.value) || 100)); setConfigDirty(true); setBackendDirty(true); }} className="flex-1 bg-transparent text-center text-sm font-bold text-white outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" /> - { setVolumeMax(v => v + 100); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ + { setVolumeMax(v => v + 100); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ )} @@ -377,12 +378,12 @@ export default function App() { TEMPO (segundos) - { setTimeSeconds(t => Math.max(10, t - 30)); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− + { setTimeSeconds(t => Math.max(10, t - 30)); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− { setTimeSeconds(Math.max(10, Number(e.target.value) || 10)); setConfigDirty(true); }} + onChange={e => { setTimeSeconds(Math.max(10, Number(e.target.value) || 10)); setConfigDirty(true); setBackendDirty(true); }} className="flex-1 bg-transparent text-center text-sm font-bold text-white outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" /> - { setTimeSeconds(t => t + 30); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ + { setTimeSeconds(t => t + 30); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ )} @@ -390,19 +391,24 @@ export default function App() { RANGE (pontos) - { setRangePoints(r => Math.max(1, r - 1)); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− + { setRangePoints(r => Math.max(1, r - 1)); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">− { setRangePoints(Math.max(1, Number(e.target.value) || 1)); setConfigDirty(true); }} + onChange={e => { setRangePoints(Math.max(1, Number(e.target.value) || 1)); setConfigDirty(true); setBackendDirty(true); }} className="flex-1 bg-transparent text-center text-sm font-bold text-white outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none" /> - { setRangePoints(r => r + 1); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ + { setRangePoints(r => r + 1); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+ )} - {/* Apply */} + {/* Apply — só chama backend se campos do backend mudaram */} { applyConfig(closeMode, deltaMax, volumeMax, timeSeconds, rangePoints); setShowChartSettings(false); }} + onClick={() => { + if (backendDirty) applyConfig(closeMode, deltaMax, volumeMax, timeSeconds, rangePoints); + setConfigDirty(false); + setBackendDirty(false); + setShowChartSettings(false); + }} disabled={!configDirty} className={`w-full py-1.5 rounded-md text-xs font-semibold transition ${configDirty ? 'bg-[#00E676] text-slate-900 hover:bg-[#00c853]' : 'bg-slate-800 text-slate-600 cursor-not-allowed'}`} >