feat: implement admin dashboard with management modules and PocketBase setup script
This commit is contained in:
@@ -21,6 +21,7 @@ const COLLECTIONS = [
|
|||||||
type: 'base',
|
type: 'base',
|
||||||
...OPEN_RULES,
|
...OPEN_RULES,
|
||||||
fields: [
|
fields: [
|
||||||
|
{ name: 'id', type: 'text', primaryKey: true, system: true, min: 1, max: 255, pattern: '^[a-zA-Z0-9_-]+$' },
|
||||||
{ name: 'label', type: 'text', required: true },
|
{ name: 'label', type: 'text', required: true },
|
||||||
{ name: 'type', type: 'text', required: false },
|
{ name: 'type', type: 'text', required: false },
|
||||||
{ name: 'description', type: 'text', required: false },
|
{ name: 'description', type: 'text', required: false },
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import { Trash2 } from 'lucide-react';
|
|||||||
const Admin = () => {
|
const Admin = () => {
|
||||||
const [activeTab, setActiveTab] = useState('sources');
|
const [activeTab, setActiveTab] = useState('sources');
|
||||||
const [sources, setSources] = useState([]);
|
const [sources, setSources] = useState([]);
|
||||||
const [apiKey, setApiKey] = useState('');
|
|
||||||
const [model, setModel] = useState('');
|
const [model, setModel] = useState('');
|
||||||
const [useSimulation, setUseSimulation] = useState(false);
|
const [useSimulation, setUseSimulation] = useState(false);
|
||||||
const [saveStatus, setSaveStatus] = useState(null);
|
const [saveStatus, setSaveStatus] = useState(null);
|
||||||
@@ -31,7 +30,6 @@ const Admin = () => {
|
|||||||
loadSources();
|
loadSources();
|
||||||
}
|
}
|
||||||
if (activeTab === 'settings') {
|
if (activeTab === 'settings') {
|
||||||
setApiKey(storage.get('admin:anthropic_key', ''));
|
|
||||||
setModel(storage.get('admin:model', 'claude-sonnet-4-20250514'));
|
setModel(storage.get('admin:model', 'claude-sonnet-4-20250514'));
|
||||||
setUseSimulation(storage.get('admin:use_simulation', false));
|
setUseSimulation(storage.get('admin:use_simulation', false));
|
||||||
}
|
}
|
||||||
@@ -39,7 +37,6 @@ const Admin = () => {
|
|||||||
|
|
||||||
const saveSettings = (e) => {
|
const saveSettings = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
storage.set('admin:anthropic_key', apiKey.trim());
|
|
||||||
storage.set('admin:model', model.trim());
|
storage.set('admin:model', model.trim());
|
||||||
storage.set('admin:use_simulation', useSimulation);
|
storage.set('admin:use_simulation', useSimulation);
|
||||||
setSaveStatus('Saved!');
|
setSaveStatus('Saved!');
|
||||||
@@ -170,13 +167,6 @@ const Admin = () => {
|
|||||||
<form onSubmit={saveSettings} className="space-y-6">
|
<form onSubmit={saveSettings} className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-medium mb-4">AI Configuration</h3>
|
<h3 className="text-lg font-medium mb-4">AI Configuration</h3>
|
||||||
<Input
|
|
||||||
label="Anthropic API Key"
|
|
||||||
type="password"
|
|
||||||
placeholder="sk-ant-..."
|
|
||||||
value={apiKey}
|
|
||||||
onChange={(e) => setApiKey(e.target.value)}
|
|
||||||
/>
|
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Input
|
<Input
|
||||||
label="Model ID"
|
label="Model ID"
|
||||||
@@ -186,8 +176,8 @@ const Admin = () => {
|
|||||||
/>
|
/>
|
||||||
<p className="text-xs text-fg-muted mt-1">Leave blank for the default. Check your Anthropic Console for available models.</p>
|
<p className="text-xs text-fg-muted mt-1">Leave blank for the default. Check your Anthropic Console for available models.</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs text-fg-muted mt-2">
|
<p className="text-sm text-fg-muted mt-4">
|
||||||
Your API key is stored locally in your browser's <code>localStorage</code>.
|
Note: Your Anthropic API key is securely managed on the server side via environment variables.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user