fix: Aplicar só dispara replay backend quando modo/delta/volume/tempo/range mudam

- Adiciona backendDirty separado de configDirty
- stepMultiplier e viewMode só setam configDirty (frontend-only, sem replay)
- closeMode, deltaMax, volumeMax, timeSeconds, rangePoints setam backendDirty também
- Aplicar chama applyConfig apenas se backendDirty=true, evitando reload desnecessário

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rufinomec-afk
2026-06-08 11:52:19 -03:00
parent d8dc47a27a
commit 775ecf75bd
+22 -16
View File
@@ -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() {
<span className="text-[10px] text-slate-500 font-bold block mb-1">MODO DE FECHAMENTO</span>
<select
value={closeMode}
onChange={e => { 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"
>
<option value="delta">Delta</option>
@@ -351,12 +352,12 @@ export default function App() {
<div>
<span className="text-[10px] text-slate-500 font-bold block mb-1">DELTA MÁX</span>
<div className="flex items-center bg-[#151B26] border border-slate-700 rounded-md overflow-hidden">
<button onClick={() => { 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"></button>
<button onClick={() => { 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"></button>
<input type="number" min="100" step="100" value={deltaMax}
onChange={e => { 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"
/>
<button onClick={() => { setDeltaMax(d => d + 100); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
<button onClick={() => { setDeltaMax(d => d + 100); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
</div>
</div>
)}
@@ -364,12 +365,12 @@ export default function App() {
<div>
<span className="text-[10px] text-slate-500 font-bold block mb-1">VOLUME MÁX</span>
<div className="flex items-center bg-[#151B26] border border-slate-700 rounded-md overflow-hidden">
<button onClick={() => { 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"></button>
<button onClick={() => { 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"></button>
<input type="number" min="100" step="100" value={volumeMax}
onChange={e => { 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"
/>
<button onClick={() => { setVolumeMax(v => v + 100); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
<button onClick={() => { setVolumeMax(v => v + 100); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
</div>
</div>
)}
@@ -377,12 +378,12 @@ export default function App() {
<div>
<span className="text-[10px] text-slate-500 font-bold block mb-1">TEMPO (segundos)</span>
<div className="flex items-center bg-[#151B26] border border-slate-700 rounded-md overflow-hidden">
<button onClick={() => { 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"></button>
<button onClick={() => { 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"></button>
<input type="number" min="10" step="30" value={timeSeconds}
onChange={e => { 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"
/>
<button onClick={() => { setTimeSeconds(t => t + 30); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
<button onClick={() => { setTimeSeconds(t => t + 30); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
</div>
</div>
)}
@@ -390,19 +391,24 @@ export default function App() {
<div>
<span className="text-[10px] text-slate-500 font-bold block mb-1">RANGE (pontos)</span>
<div className="flex items-center bg-[#151B26] border border-slate-700 rounded-md overflow-hidden">
<button onClick={() => { 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"></button>
<button onClick={() => { 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"></button>
<input type="number" min="1" step="1" value={rangePoints}
onChange={e => { 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"
/>
<button onClick={() => { setRangePoints(r => r + 1); setConfigDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
<button onClick={() => { setRangePoints(r => r + 1); setConfigDirty(true); setBackendDirty(true); }} className="px-3 py-1.5 text-slate-400 hover:text-white hover:bg-slate-800">+</button>
</div>
</div>
)}
{/* Apply */}
{/* Apply — só chama backend se campos do backend mudaram */}
<button
onClick={() => { 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'}`}
>