Jose Salazar commited on
Commit
e5f4dd4
Β·
unverified Β·
2 Parent(s): 9ceda0368d7401

Merge pull request #37 from josesalazar2025/jose

Browse files
frontend/dist/assets/{index-QBJ3liVo.css β†’ index-B5AdzxgP.css} RENAMED
The diff for this file is too large to render. See raw diff
 
frontend/dist/assets/{index-BfINZMV7.js β†’ index-Dk2_c6vF.js} RENAMED
The diff for this file is too large to render. See raw diff
 
frontend/dist/index.html CHANGED
@@ -5,8 +5,8 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>PolySignal β€” Dashboard de Inteligencia de Mercados</title>
7
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
8
- <script type="module" crossorigin src="/assets/index-BfINZMV7.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-QBJ3liVo.css">
10
  </head>
11
  <body>
12
  <!-- Global loader: visible por defecto (sin JS) hasta que bootstrap lo oculte -->
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
  <title>PolySignal β€” Dashboard de Inteligencia de Mercados</title>
7
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
8
+ <script type="module" crossorigin src="/assets/index-Dk2_c6vF.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-B5AdzxgP.css">
10
  </head>
11
  <body>
12
  <!-- Global loader: visible por defecto (sin JS) hasta que bootstrap lo oculte -->
frontend/src/app.js CHANGED
@@ -770,6 +770,22 @@ function hasAlert(marketId) {
770
  return state.watchlist.some((w) => w.marketId === marketId && w.alertThreshold != null)
771
  }
772
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
  async function toggleWatchlistCard(marketId, wBtn, aBtn) {
774
  if (isInWatchlist(marketId)) {
775
  try {
@@ -781,6 +797,8 @@ async function toggleWatchlistCard(marketId, wBtn, aBtn) {
781
  aBtn.textContent = '⚑ Alertas'
782
  aBtn.classList.remove('active')
783
  aBtn.title = 'Activar alerta de precio'
 
 
784
  } catch (e) { console.warn('Error al quitar de watchlist:', e) }
785
  } else {
786
  try {
@@ -789,6 +807,8 @@ async function toggleWatchlistCard(marketId, wBtn, aBtn) {
789
  wBtn.textContent = 'β˜… Seguimiento'
790
  wBtn.classList.add('active')
791
  wBtn.title = 'Quitar de seguimiento'
 
 
792
  } catch (e) { console.warn('Error al aΓ±adir a watchlist:', e) }
793
  }
794
  }
@@ -804,6 +824,8 @@ function toggleAlertCard(marketId, aBtn, thresholdRow) {
804
  aBtn.textContent = '⚑ Alertas'
805
  aBtn.classList.remove('active')
806
  aBtn.title = 'Activar alerta de precio'
 
 
807
  })
808
  .catch((e) => console.warn('Error al desactivar alerta:', e))
809
  } else {
@@ -823,6 +845,8 @@ async function setAlertThreshold(marketId, threshold, aBtn, thresholdRow) {
823
  aBtn.classList.add('active')
824
  aBtn.title = 'Desactivar alerta'
825
  thresholdRow.classList.add('hidden')
 
 
826
  } catch (e) { console.warn('Error al configurar alerta:', e) }
827
  }
828
 
@@ -1342,9 +1366,7 @@ function renderPositions() {
1342
 
1343
  async function closePositionById(id) {
1344
  await simulator.closePosition(id)
1345
- await loadPositions()
1346
- renderPositions()
1347
- renderMiniPositions()
1348
  }
1349
 
1350
  /* ─── Render watchlist view ─── */
@@ -1403,6 +1425,7 @@ async function removeFromWatchlistById(marketId) {
1403
  try { await api.removeFromWatchlist(marketId) } catch (e) { console.warn(e) }
1404
  state.watchlist = state.watchlist.filter((w) => w.marketId !== marketId)
1405
  renderWatchlist()
 
1406
  }
1407
 
1408
  /* ─── Render alerts view ─── */
@@ -1509,6 +1532,12 @@ async function loadPositions() {
1509
  }
1510
  }
1511
 
 
 
 
 
 
 
1512
  async function loadWatchlist() {
1513
  try {
1514
  state.watchlist = await api.getWatchlist()
@@ -1563,6 +1592,11 @@ async function initAppData() {
1563
  map.init('map-container', state.markets, state.signals, selectMarket)
1564
  simulator.init(state)
1565
 
 
 
 
 
 
1566
  state.activeMarketId = state.markets[0]?.id || null
1567
  renderSignals()
1568
  renderDetail()
@@ -1669,6 +1703,6 @@ export async function init() {
1669
  socket.on('price_alert', (data) => {
1670
  if (!data?.marketId || !data.type) return
1671
  state.alerts.unshift(data)
1672
- if (state.view === 'alerts') renderAlerts()
1673
  })
1674
  }
 
770
  return state.watchlist.some((w) => w.marketId === marketId && w.alertThreshold != null)
771
  }
772
 
773
+ function updateSignalCardWatchlistState(marketId) {
774
+ document.querySelectorAll(`#signals-list .market-card[data-market="${CSS.escape(marketId)}"]`).forEach((card) => {
775
+ const wBtn = card.querySelector('.card-btn-watch')
776
+ const aBtn = card.querySelector('.card-btn-alert')
777
+ if (!wBtn || !aBtn) return
778
+ const inWl = isInWatchlist(marketId)
779
+ const hasAl = hasAlert(marketId)
780
+ wBtn.textContent = inWl ? 'β˜… Seguimiento' : 'β˜† Seguimiento'
781
+ wBtn.classList.toggle('active', inWl)
782
+ wBtn.title = inWl ? 'Quitar de seguimiento' : 'AΓ±adir a seguimiento'
783
+ aBtn.textContent = hasAl ? '⚑ Alerta activa' : '⚑ Alertas'
784
+ aBtn.classList.toggle('active', hasAl)
785
+ aBtn.title = hasAl ? 'Desactivar alerta' : 'Activar alerta de precio'
786
+ })
787
+ }
788
+
789
  async function toggleWatchlistCard(marketId, wBtn, aBtn) {
790
  if (isInWatchlist(marketId)) {
791
  try {
 
797
  aBtn.textContent = '⚑ Alertas'
798
  aBtn.classList.remove('active')
799
  aBtn.title = 'Activar alerta de precio'
800
+ renderWatchlist()
801
+ updateSignalCardWatchlistState(marketId)
802
  } catch (e) { console.warn('Error al quitar de watchlist:', e) }
803
  } else {
804
  try {
 
807
  wBtn.textContent = 'β˜… Seguimiento'
808
  wBtn.classList.add('active')
809
  wBtn.title = 'Quitar de seguimiento'
810
+ renderWatchlist()
811
+ updateSignalCardWatchlistState(marketId)
812
  } catch (e) { console.warn('Error al aΓ±adir a watchlist:', e) }
813
  }
814
  }
 
824
  aBtn.textContent = '⚑ Alertas'
825
  aBtn.classList.remove('active')
826
  aBtn.title = 'Activar alerta de precio'
827
+ renderWatchlist()
828
+ updateSignalCardWatchlistState(marketId)
829
  })
830
  .catch((e) => console.warn('Error al desactivar alerta:', e))
831
  } else {
 
845
  aBtn.classList.add('active')
846
  aBtn.title = 'Desactivar alerta'
847
  thresholdRow.classList.add('hidden')
848
+ renderWatchlist()
849
+ updateSignalCardWatchlistState(marketId)
850
  } catch (e) { console.warn('Error al configurar alerta:', e) }
851
  }
852
 
 
1366
 
1367
  async function closePositionById(id) {
1368
  await simulator.closePosition(id)
1369
+ // El evento 'positions:changed' se encarga de refrescar las listas
 
 
1370
  }
1371
 
1372
  /* ─── Render watchlist view ─── */
 
1425
  try { await api.removeFromWatchlist(marketId) } catch (e) { console.warn(e) }
1426
  state.watchlist = state.watchlist.filter((w) => w.marketId !== marketId)
1427
  renderWatchlist()
1428
+ updateSignalCardWatchlistState(marketId)
1429
  }
1430
 
1431
  /* ─── Render alerts view ─── */
 
1532
  }
1533
  }
1534
 
1535
+ async function refreshPositions() {
1536
+ await loadPositions()
1537
+ renderPositions()
1538
+ renderMiniPositions()
1539
+ }
1540
+
1541
  async function loadWatchlist() {
1542
  try {
1543
  state.watchlist = await api.getWatchlist()
 
1592
  map.init('map-container', state.markets, state.signals, selectMarket)
1593
  simulator.init(state)
1594
 
1595
+ // Refrescar listas de posiciones cuando el simulador notifique cambios
1596
+ document.addEventListener('positions:changed', () => {
1597
+ refreshPositions()
1598
+ })
1599
+
1600
  state.activeMarketId = state.markets[0]?.id || null
1601
  renderSignals()
1602
  renderDetail()
 
1703
  socket.on('price_alert', (data) => {
1704
  if (!data?.marketId || !data.type) return
1705
  state.alerts.unshift(data)
1706
+ renderAlerts()
1707
  })
1708
  }
frontend/src/style.css CHANGED
@@ -2362,8 +2362,7 @@ td {
2362
  border-color: var(--blue2);
2363
  }
2364
 
2365
- #btn-notif,
2366
- #btn-auth-mobile {
2367
  display: flex;
2368
  }
2369
 
 
2362
  border-color: var(--blue2);
2363
  }
2364
 
2365
+ #btn-notif {
 
2366
  display: flex;
2367
  }
2368