105 lines
4.3 KiB
JavaScript
105 lines
4.3 KiB
JavaScript
import { useState } from 'react'
|
||
import Modal from '../ui/Modal'
|
||
import { Badge, Icon } from '../ui/primitives'
|
||
import { useToast } from '../ui/Toast'
|
||
import { aiModules } from '../data/seed'
|
||
|
||
export default function AiStudio() {
|
||
const { toast } = useToast()
|
||
const [detail, setDetail] = useState(null)
|
||
const betaCount = aiModules.filter((m) => m.status === 'Beta').length
|
||
|
||
return (
|
||
<div className="page">
|
||
<div className="page-head">
|
||
<div>
|
||
<h1 className="page-title">AI Studio</h1>
|
||
<p className="page-sub">
|
||
Next-generation AI modules — designed and API-ready for backend integration
|
||
</p>
|
||
</div>
|
||
<div className="page-head-actions">
|
||
<span className="integration-status pending"><span className="pulse" />{betaCount} in Beta</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="card brand-hero mb-18">
|
||
<div className="card-body" style={{ display: 'flex', alignItems: 'center', gap: 20, flexWrap: 'wrap' }}>
|
||
<div className="ai-logo" style={{ margin: 0, width: 56, height: 56 }}><Icon name="sparkles" /></div>
|
||
<div style={{ flex: 1, minWidth: 220 }}>
|
||
<h2 style={{ fontSize: 19, marginBottom: 4 }}>Everything is API-ready</h2>
|
||
<p style={{ opacity: 0.88 }}>
|
||
Each module below ships with a complete, production-grade interface. Connect your model
|
||
endpoint to activate them — no UI work required.
|
||
</p>
|
||
</div>
|
||
<button className="btn btn-on-brand" onClick={() => toast('Integration guide opened', 'info')}>
|
||
<Icon name="external" /> Integration Guide
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid g-3">
|
||
{aiModules.map((m) => (
|
||
<div key={m.name} className="card" style={{ cursor: 'pointer' }} onClick={() => setDetail(m)}>
|
||
<div className="card-body">
|
||
<div className="flex items-center" style={{ justifyContent: 'space-between', marginBottom: 12 }}>
|
||
<span className={`kpi-icn ${m.cls}`} style={{ width: 46, height: 46, borderRadius: 13 }}>
|
||
<Icon name={m.icon} />
|
||
</span>
|
||
<Badge className={m.status === 'Beta' ? 'b-indigo' : 'b-gray'}>{m.status}</Badge>
|
||
</div>
|
||
<div className="lr-title" style={{ fontSize: 15 }}>{m.name}</div>
|
||
<div className="lr-sub" style={{ marginTop: 5, lineHeight: 1.5 }}>{m.desc}</div>
|
||
<div style={{ marginTop: 14, color: 'var(--primary)', fontWeight: 600, fontSize: 13 }}>
|
||
{m.status === 'Beta' ? 'Try it' : 'Join waitlist'} <Icon name="arrow-right" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
{detail && (
|
||
<Modal
|
||
title={detail.name}
|
||
subtitle={`${detail.status} · AI Module`}
|
||
size="modal-lg"
|
||
onClose={() => setDetail(null)}
|
||
footer={<button className="btn btn-secondary" onClick={() => setDetail(null)}>Close</button>}
|
||
>
|
||
<div className="flex items-center gap-16" style={{ marginBottom: 18 }}>
|
||
<span className={`kpi-icn ${detail.cls}`} style={{ width: 56, height: 56, borderRadius: 16 }}>
|
||
<Icon name={detail.icon} />
|
||
</span>
|
||
<div>
|
||
<div className="fw-600" style={{ fontSize: 16 }}>{detail.name}</div>
|
||
<div className="text-muted">{detail.desc}</div>
|
||
</div>
|
||
</div>
|
||
<div className="card" style={{ boxShadow: 'none', background: 'var(--bg-sunken)' }}>
|
||
<div className="card-body">
|
||
<div className="form-section-title" style={{ marginTop: 0 }}>API Contract (preview)</div>
|
||
<pre className="resume-thumb" style={{ maxHeight: 'none' }}>
|
||
{`POST /api/ai/${detail.name.toLowerCase().replace(/ /g, '-')}
|
||
{
|
||
"context": { "jobId": "JOB-1001", "candidateIds": [...] },
|
||
"options": { "model": "claude-opus", "stream": true }
|
||
}
|
||
|
||
→ 200 OK
|
||
{
|
||
"result": { ... },
|
||
"usage": { "tokens": 1240 }
|
||
}`}
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<p className="text-muted text-sm" style={{ marginTop: 14 }}>
|
||
<Icon name="lock" /> This feature’s UI is complete. Backend wiring is the only remaining step.
|
||
</p>
|
||
</Modal>
|
||
)}
|
||
</div>
|
||
)
|
||
}
|