From e44c88094190ee223d068d85437bba68866c23d1 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 15 Nov 2025 09:26:39 +0000 Subject: [PATCH] V1.11 --- api/ticker.php | 68 ++++++++++++++++++++++++++++++++++++++++++ assets/css/custom.css | 20 ++++++++++++- assets/js/main.js | 69 +++++++++++++++++++++++++++++++++++++++++-- index.php | 20 ++++++++++++- 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 api/ticker.php diff --git a/api/ticker.php b/api/ticker.php new file mode 100644 index 0000000..5dd75be --- /dev/null +++ b/api/ticker.php @@ -0,0 +1,68 @@ + $api_url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TIMEOUT => 10, + CURLOPT_HTTPHEADER => [ + 'Accept: application/json' + ], + // It's good practice to set a user-agent + CURLOPT_USERAGENT => 'FlatlogicMarketDetector/1.0' +]); + +$response = curl_exec($ch); +$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); +$error = curl_error($ch); +curl_close($ch); + +// --- Response Handling --- +if ($error) { + http_response_code(500); + echo json_encode(['error' => 'cURL Error: ' . $error]); + exit; +} + +if ($http_code !== 200) { + http_response_code($http_code); + echo json_encode(['error' => 'Bitget API returned non-200 status', 'details' => json_decode($response)]); + exit; +} + +$data = json_decode($response, true); + +// --- Data Validation & Output --- +if (json_last_error() !== JSON_ERROR_NONE || empty($data['data'])) { + http_response_code(500); + echo json_encode(['error' => 'Failed to parse JSON response or data is empty']); + exit; +} + +// Extract the first ticker object from the response data array +$ticker_data = $data['data'][0] ?? null; + +if (!$ticker_data) { + http_response_code(404); + echo json_encode(['error' => 'Ticker data for symbol not found in API response']); + exit; +} + +// --- Sanitize and Structure Output --- +// We select and sanitize the fields we want to send to the frontend. +$output = [ + 'exchange' => 'Bitget', + 'symbol' => $ticker_data['symbol'] ?? 'N/A', + 'price' => $ticker_data['lastPr'] ?? '0.00', + // Bitget provides the 24h change as a decimal, e.g., 0.025 for +2.5% + 'change_24h_percent' => isset($ticker_data['priceChangePercent']) ? (float)$ticker_data['priceChangePercent'] * 100 : 0, + 'signal' => '-' // Placeholder for future signal detection +]; + +echo json_encode($output); diff --git a/assets/css/custom.css b/assets/css/custom.css index dd9708c..0318f2f 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,4 +1,3 @@ - /* Import Google Fonts */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); @@ -45,3 +44,22 @@ body { .badge { font-weight: 600; } + +/* Price flash animations */ +@keyframes flash-success-anim { + from { background-color: rgba(25, 135, 84, 0.2); } + to { background-color: transparent; } +} + +.flash-success { + animation: flash-success-anim 0.75s ease-out; +} + +@keyframes flash-danger-anim { + from { background-color: rgba(220, 53, 69, 0.2); } + to { background-color: transparent; } +} + +.flash-danger { + animation: flash-danger-anim 0.75s ease-out; +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index a256fd6..9a5de2f 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,3 +1,68 @@ +document.addEventListener('DOMContentLoaded', function () { + const POLLING_INTERVAL = 3000; // 3 seconds -// No custom JavaScript needed for the initial static dashboard. -// This file is ready for future interactivity. + const liveRow = document.getElementById('live-crypto-row'); + if (!liveRow) { + console.error('Live crypto row with ID #live-crypto-row not found.'); + return; + } + + // Select cells to update + const priceCell = liveRow.querySelector('.price'); + const changeCell = liveRow.querySelector('.change'); + const symbolCell = liveRow.querySelector('.symbol'); + const exchangeCell = liveRow.querySelector('.exchange'); + + let lastPrice = 0; + + async function fetchLivePrice() { + try { + const response = await fetch('api/ticker.php'); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + const data = await response.json(); + + if (data.error) { + throw new Error(`API Error: ${data.error}`); + } + + updateRow(data); + + } catch (error) { + console.error('Failed to fetch live price:', error); + // Optionally, display an error state in the UI + priceCell.textContent = 'Error'; + changeCell.textContent = '--'; + } + } + + function updateRow(data) { + const currentPrice = parseFloat(data.price); + const priceChange = currentPrice - lastPrice; + + // Update text content + priceCell.textContent = `$${currentPrice.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; + symbolCell.textContent = data.symbol.replace('_SPBL', ''); // Clean up symbol name + exchangeCell.textContent = data.exchange; + + // Update 24h change + const changePercent = parseFloat(data.change_24h_percent); + changeCell.textContent = `${changePercent.toFixed(2)}%`; + changeCell.classList.toggle('text-success', changePercent >= 0); + changeCell.classList.toggle('text-danger', changePercent < 0); + + // Visual flash on price change + if (lastPrice !== 0 && priceChange !== 0) { + const flashClass = priceChange > 0 ? 'flash-success' : 'flash-danger'; + priceCell.classList.add(flashClass); + setTimeout(() => priceCell.classList.remove(flashClass), 750); + } + + lastPrice = currentPrice; + } + + // Initial fetch and start polling + fetchLivePrice(); + setInterval(fetchLivePrice, POLLING_INTERVAL); +}); \ No newline at end of file diff --git a/index.php b/index.php index 76032b7..386735c 100644 --- a/index.php +++ b/index.php @@ -54,9 +54,27 @@ + + + Bitget + +
+ + BTC/USDT +
+ + $0.00 + + + --% + + + - + + 'KCEX', 'symbol' => 'BTC/USDT', 'price' => '68,123.45', 'change' => 2.5, 'signal' => null], ['exchange' => 'Bitget', 'symbol' => 'ETH/USDT', 'price' => '3,789.12', 'change' => -21.8, 'signal' => 'Crash Alert'], ['exchange' => 'WEEX', 'symbol' => 'PEPE/USDT', 'price' => '0.00001234', 'change' => 255.1, 'signal' => 'Pump Alert'], ['exchange' => 'KuCoin', 'symbol' => 'SOL/USDT', 'price' => '165.80', 'change' => -1.2, 'signal' => 'Bearish Reversal'],