Hwandji's picture
feat: initial HuggingFace Space deployment
4343907
<template>
<div id="app" class="saap-app">
<!-- SAAP Header -->
<header class="saap-header">
<div class="header-content">
<div class="logo-section">
<h1 class="saap-heading-2">
<span class="logo-text">SAAP</span>
<span class="logo-subtitle">Multi-Agent Platform</span>
</h1>
</div>
<div class="status-section">
<div class="connection-status" :class="connectionStatusClass">
<div class="status-dot"></div>
<span>{{ connectionStatusText }}</span>
</div>
<div class="agent-summary">
<span class="agent-count">{{ activeAgents }}/{{ totalAgents }}</span>
<span class="agent-label">Agents Active</span>
</div>
</div>
</div>
</header>
<!-- Main Content Area - Direct Dashboard -->
<main class="saap-main">
<SaapDashboard />
</main>
<!-- Footer -->
<footer class="saap-footer">
<div class="footer-content">
<span class="footer-text">
SAAP v1.0.0 •
Built with Vue.js •
Powered by colossus Server
</span>
<span class="footer-build">
Build: {{ buildDate }}
</span>
</div>
</footer>
</div>
</template>
<script>
import { ref, computed, onMounted } from 'vue'
import SaapDashboard from './components/SaapDashboard.vue'
import saapApi from './services/saapApi.js'
export default {
name: 'SaapApp',
components: {
SaapDashboard
},
setup() {
// Reactive state
const isConnected = ref(false)
const totalAgents = ref(0)
const activeAgents = ref(0)
// Computed properties
const connectionStatusClass = computed(() => ({
'status-connected': isConnected.value,
'status-disconnected': !isConnected.value
}))
const connectionStatusText = computed(() =>
isConnected.value ? 'Connected' : 'Disconnected'
)
const buildDate = computed(() =>
new Date().toLocaleDateString('de-DE')
)
// Load agents data from API using saapApi service
const loadAgentsStats = async () => {
try {
console.log('🔄 Loading agents stats via API service...')
const response = await saapApi.getAgents()
console.log('📦 API Response:', response)
// Backend returns {agents: [...], total: N, active: N}
if (response && response.agents) {
totalAgents.value = response.total || response.agents.length
activeAgents.value = response.active || response.agents.filter(a => a.status === 'active').length
isConnected.value = true
console.log(`✅ Loaded ${totalAgents.value} agents (${activeAgents.value} active)`)
} else {
console.warn('⚠️ Unexpected API response format:', response)
isConnected.value = false
}
} catch (error) {
console.error('❌ Failed to load agents stats:', error)
isConnected.value = false
}
}
// Initialize app
onMounted(() => {
console.log('🚀 SAAP Dashboard initialized')
loadAgentsStats()
// Refresh stats every 3 seconds
setInterval(loadAgentsStats, 3000)
})
return {
isConnected,
totalAgents,
activeAgents,
connectionStatusClass,
connectionStatusText,
buildDate
}
}
}
</script>
<style scoped>
/* SAAP App Layout */
.saap-app {
min-height: 100vh;
display: flex;
flex-direction: column;
background: var(--saap-gray-50);
}
/* Header Styles */
.saap-header {
background: white;
border-bottom: 1px solid var(--saap-gray-200);
box-shadow: var(--saap-shadow-sm);
position: sticky;
top: 0;
z-index: 50;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--saap-space-4) var(--saap-space-6);
max-width: 1400px;
margin: 0 auto;
}
/* Logo Section */
.logo-section {
display: flex;
align-items: center;
}
.logo-text {
background: linear-gradient(135deg, var(--saap-primary-600), var(--saap-secondary-600));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: var(--saap-font-bold);
margin-right: var(--saap-space-2);
}
.logo-subtitle {
font-size: var(--saap-text-base);
font-weight: var(--saap-font-normal);
color: var(--saap-gray-600);
}
/* Status Section */
.status-section {
display: flex;
align-items: center;
gap: var(--saap-space-6);
}
.connection-status {
display: flex;
align-items: center;
gap: var(--saap-space-2);
padding: var(--saap-space-2) var(--saap-space-4);
border-radius: var(--saap-radius-lg);
font-size: var(--saap-text-sm);
font-weight: var(--saap-font-medium);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: var(--saap-radius-full);
transition: background-color var(--saap-transition-base);
}
.status-connected {
background: rgba(34, 197, 94, 0.1);
color: var(--saap-secondary-700);
}
.status-connected .status-dot {
background: var(--saap-secondary-500);
}
.status-disconnected {
background: rgba(239, 68, 68, 0.1);
color: var(--saap-accent-700);
}
.status-disconnected .status-dot {
background: var(--saap-accent-500);
}
/* Agent Summary */
.agent-summary {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.agent-count {
font-size: var(--saap-text-xl);
font-weight: var(--saap-font-bold);
color: var(--saap-primary-600);
}
.agent-label {
font-size: var(--saap-text-xs);
color: var(--saap-gray-500);
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* Main Content */
.saap-main {
flex: 1;
max-width: 1400px;
margin: 0 auto;
width: 100%;
}
/* Footer */
.saap-footer {
background: white;
border-top: 1px solid var(--saap-gray-200);
padding: var(--saap-space-4) var(--saap-space-6);
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1400px;
margin: 0 auto;
font-size: var(--saap-text-xs);
color: var(--saap-gray-500);
}
/* Responsive Design */
@media (max-width: 768px) {
.header-content {
flex-direction: column;
gap: var(--saap-space-4);
padding: var(--saap-space-4);
}
.logo-subtitle {
display: none;
}
.status-section {
gap: var(--saap-space-4);
}
.footer-content {
flex-direction: column;
gap: var(--saap-space-2);
text-align: center;
}
.saap-main {
padding: var(--saap-space-4);
}
}
</style>