| import React, { useState } from 'react'; |
|
|
| interface Props { onLock: () => void; } |
|
|
| const models = [ |
| { name: 'LLM', model: 'Llama 3.2 3B Instruct', q: 'Q4_K_M', size: '2.0 GB', pkg: 'llm-llamacpp' }, |
| { name: 'Embeddings', model: 'Nomic Embed Text v1.5', q: 'Q4_K_M', size: '260 MB', pkg: 'embed-llamacpp' }, |
| { name: 'Speech-to-Text', model: 'Whisper Base.en', q: 'GGML', size: '150 MB', pkg: 'transcription-whispercpp' }, |
| { name: 'Text-to-Speech', model: 'Piper Amy', q: 'ONNX', size: '75 MB', pkg: 'tts-onnx' }, |
| { name: 'Translation', model: 'OPUS MT (EN↔ES)', q: 'NMT', size: '50 MB', pkg: 'translation-nmtcpp' }, |
| { name: 'OCR', model: 'PaddleOCR v4', q: 'ONNX', size: '30 MB', pkg: 'ocr-onnx' }, |
| ]; |
|
|
| export default function SettingsPage({ onLock }: Props) { |
| const [network, setNetwork] = useState('devnet'); |
|
|
| return ( |
| <div className="max-w-2xl mx-auto px-8 py-section"> |
| <h2 className="display-text text-title-lg text-ink mb-8">Settings</h2> |
| |
| {/* Network */} |
| <div className="card mb-6"> |
| <div className="text-caption-strong text-muted uppercase tracking-wider mb-3">Network</div> |
| <div className="flex gap-2 p-1 bg-surface-soft rounded-pill"> |
| {[{ id: 'devnet', l: 'Devnet' }, { id: 'mainnet-beta', l: 'Mainnet' }, { id: 'testnet', l: 'Testnet' }].map(n => ( |
| <button key={n.id} onClick={() => setNetwork(n.id)} className={`flex-1 py-2 rounded-pill text-button transition-colors ${network === n.id ? 'bg-primary text-on-primary' : 'text-body hover:text-ink'}`}>{n.l}</button> |
| ))} |
| </div> |
| <p className="text-caption text-muted mt-2"> |
| {network === 'devnet' && 'Test tokens only. No real value.'} |
| {network === 'mainnet-beta' && 'Real tokens. Transactions irreversible.'} |
| {network === 'testnet' && 'Development purposes only.'} |
| </p> |
| </div> |
| |
| {/* AI Models — Coinbase pricing-tier-card pattern */} |
| <div className="card mb-6"> |
| <div className="flex items-center justify-between mb-4"> |
| <div className="text-caption-strong text-muted uppercase tracking-wider">QVAC AI Models</div> |
| <span className="badge-pill text-[10px]">6 MODULES · ~2.6 GB</span> |
| </div> |
| <div className="space-y-0"> |
| {models.map(m => ( |
| <div key={m.name} className="flex items-center justify-between py-3 border-b border-hairline-soft last:border-0"> |
| <div> |
| <div className="text-title-sm text-ink">{m.name}</div> |
| <div className="text-caption text-muted">{m.model}</div> |
| <div className="text-caption text-muted-soft font-mono">@qvac/{m.pkg}</div> |
| </div> |
| <div className="text-right"> |
| <span className="badge-pill text-[10px] mr-2">{m.q}</span> |
| <span className="number-mono text-caption text-muted">{m.size}</span> |
| </div> |
| </div> |
| ))} |
| </div> |
| <div className="hairline-soft mt-3 mb-3" /> |
| <div className="text-caption text-muted flex items-center gap-1.5"> |
| <div className="w-1.5 h-1.5 rounded-full bg-semantic-up" /> |
| All models run locally via QVAC Fabric (Vulkan GPU) — no CUDA required |
| </div> |
| </div> |
| |
| {/* About */} |
| <div className="card mb-6"> |
| <div className="text-caption-strong text-muted uppercase tracking-wider mb-3">About</div> |
| <div className="text-body-sm text-body space-y-2"> |
| <p><strong className="text-ink">SolVox</strong> — voice-first, privacy-preserving AI wallet for Solana.</p> |
| <p>Powered by <strong className="text-primary">Tether QVAC SDK</strong> — local AI that never phones home.</p> |
| </div> |
| <div className="flex flex-wrap gap-1.5 mt-3"> |
| {['Electron', 'React', 'TypeScript', 'QVAC SDK', 'Solana', 'Vulkan'].map(t => ( |
| <span key={t} className="badge-pill text-[10px]">{t}</span> |
| ))} |
| </div> |
| <div className="hairline-soft my-3" /> |
| <div className="text-caption text-muted-soft">Colosseum Frontier Hackathon · Tether QVAC Track</div> |
| </div> |
| |
| {/* Lock */} |
| <div className="card border-semantic-down/20" style={{ borderColor: 'rgba(207, 32, 47, 0.15)' }}> |
| <div className="text-caption-strong text-semantic-down uppercase tracking-wider mb-3">Danger zone</div> |
| <button onClick={onLock} className="w-full py-3 rounded-pill border border-semantic-down/30 text-semantic-down text-button hover:bg-semantic-down/5 transition-colors">Lock wallet</button> |
| <p className="text-caption text-muted text-center mt-2">Zeroes private key from memory. PIN required to unlock.</p> |
| </div> |
| </div> |
| ); |
| } |
|
|