scaffold: kind+Tilt cluster, api/ui/docs stubs, green at nvi.local.ar

This commit is contained in:
2026-06-03 00:33:51 -03:00
commit 131f4d9b86
39 changed files with 3571 additions and 0 deletions

80
ui/app/src/pages/Ask.vue Normal file
View File

@@ -0,0 +1,80 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const question = ref('Which districts had the sharpest rise in loan defaults?')
const submitting = ref(false)
const error = ref<string | null>(null)
const router = useRouter()
async function submit() {
if (!question.value.trim()) return
submitting.value = true
error.value = null
try {
const res = await fetch('/ask', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question: question.value }),
})
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`)
const { run_id } = await res.json()
router.push(`/runs/${run_id}`)
} catch (e: any) {
error.value = e.message ?? String(e)
} finally {
submitting.value = false
}
}
</script>
<template>
<div class="ask">
<h2>Ask a question</h2>
<textarea v-model="question" rows="3" :disabled="submitting" />
<div class="actions">
<button @click="submit" :disabled="submitting || !question.trim()">
{{ submitting ? 'Submitting…' : 'Ask' }}
</button>
</div>
<p v-if="error" class="error">{{ error }}</p>
</div>
</template>
<style scoped>
.ask {
max-width: 720px;
display: flex;
flex-direction: column;
gap: 12px;
}
textarea {
background: var(--surface-2);
color: var(--text-primary);
border: var(--panel-border);
padding: 12px;
font-family: var(--font-mono);
font-size: 14px;
}
.actions {
display: flex;
justify-content: flex-end;
}
button {
padding: 8px 20px;
font-family: var(--font-mono);
background: var(--accent-dim);
color: var(--text-primary);
border: var(--panel-border);
cursor: pointer;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.error {
color: var(--status-error, #f55);
font-family: var(--font-mono);
font-size: 12px;
}
</style>