Spaces:
Sleeping
Sleeping
<html lang="en" data-theme="dark"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>CryptoSentinel AI Dashboard</title> | |
<!-- Pico.css for modern, clean styling --> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css"> | |
<!-- HTMX Core and Server-Sent Events (SSE) Extension --> | |
<script src="https://unpkg.com/[email protected]" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script> | |
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script> | |
<style> | |
/* Add some spacing and alignment for a cleaner look */ | |
body { container-type: inline-size; } | |
main.container { | |
max-width: 800px; | |
margin: 2rem auto; | |
} | |
.htmx-indicator { | |
display: none; /* Hide indicator by default */ | |
} | |
.htmx-request .htmx-indicator { | |
display: inline; /* Show when a request is in flight */ | |
} | |
.htmx-request .hide-on-request { | |
display: none; /* Hide element during request */ | |
} | |
.sentiment-positive { color: var(--pico-color-green-400); } | |
.sentiment-negative { color: var(--pico-color-red-400); } | |
.sentiment-error { color: var(--pico-color-amber-400); } | |
#sentiment-results div { | |
border-bottom: 1px solid var(--pico-muted-border-color); | |
padding-bottom: 1rem; | |
margin-bottom: 1rem; | |
} | |
</style> | |
</head> | |
<!-- Enable the SSE extension for the whole body --> | |
<body hx-ext="sse"> | |
<main class="container"> | |
<header style="text-align: center;"> | |
<h1>π€ CryptoSentinel AI</h1> | |
<p>Real-Time Market Prices & Sentiment Analysis</p> | |
</header> | |
<!-- Section 1: Live Prices --> | |
<article> | |
<header><strong>Market Snapshot</strong></header> | |
<div | |
id="prices" | |
hx-get="/api/prices" | |
hx-trigger="load, every 10s" | |
hx-swap="innerHTML" | |
aria-live="polite"> | |
<!-- Initial loading state --> | |
<p aria-busy="true">Fetching latest prices...</p> | |
</div> | |
</article> | |
<!-- Section 2: Sentiment Analysis --> | |
<article> | |
<header><strong>Sentiment Analyzer</strong></header> | |
<!-- Form for submitting text --> | |
<form | |
hx-post="/api/sentiment" | |
hx-target="#analysis-status" | |
hx-swap="innerHTML" | |
hx-on::after-request="this.reset()"> | |
<label for="sentiment-text">Analyze market chatter, news, or a tweet:</label> | |
<textarea id="sentiment-text" name="text" placeholder="e.g., 'The market is pumping! To the moon! π'" required></textarea> | |
<button type="submit"> | |
<span class="hide-on-request">Analyze Sentiment</span> | |
<span class="htmx-indicator" aria-busy="true">Analyzing...</span> | |
</button> | |
<small id="analysis-status" style="margin-left: 1rem;"></small> | |
</form> | |
<!-- Area for real-time results from the SSE stream --> | |
<section> | |
<h5>Real-Time Results</h5> | |
<div | |
id="sentiment-results" | |
hx-sse="connect:/api/sentiment/stream" | |
hx-swap="afterbegin"> | |
<!-- New results will be prepended here by HTMX --> | |
<p><small>Waiting for first analysis...</small></p> | |
</div> | |
</section> | |
</article> | |
<footer> | |
<small>Price data sourced from CoinGecko & CoinCap. Sentiment analysis via Hugging Face.</small> | |
</footer> | |
</main> | |
<!-- Template for new sentiment results --> | |
<!-- This is not used directly, but shows the structure our server should send --> | |
<template id="sentiment-item-template"> | |
<div> | |
<blockquote>"{text}"</blockquote> | |
<p> | |
<strong>Result:</strong> | |
<span class="sentiment-{label}">{label}</span> | |
(Confidence: {score}) | |
</p> | |
</div> | |
</template> | |
</body> | |
</html> |