phase 16: add registry/risk nginx proxies, add company form, network policies

This commit is contained in:
Celes Renata
2026-04-11 19:12:07 -07:00
parent 4cd8961db6
commit 6f5b2231a2
6 changed files with 116 additions and 6 deletions
+2 -2
View File
@@ -4,8 +4,8 @@
*/
const QUERY_API_BASE = import.meta.env.VITE_QUERY_API_URL ?? '';
const SYMBOL_REGISTRY_BASE = import.meta.env.VITE_SYMBOL_REGISTRY_URL ?? '';
const RISK_ENGINE_BASE = import.meta.env.VITE_RISK_ENGINE_URL ?? '';
const SYMBOL_REGISTRY_BASE = import.meta.env.VITE_SYMBOL_REGISTRY_URL ?? '/registry';
const RISK_ENGINE_BASE = import.meta.env.VITE_RISK_ENGINE_URL ?? '/risk';
export type ApiBase = 'query' | 'registry' | 'risk';
+74 -3
View File
@@ -1,7 +1,8 @@
import { useState } from 'react';
import { useNavigate } from '@tanstack/react-router';
import { useCompanies } from '../api/hooks';
import { useCompanies, useCreateCompany } from '../api/hooks';
import { DataTable, type Column } from '../components/DataTable';
import { StatusBadge, LoadingSpinner } from '../components/ui';
import { StatusBadge, LoadingSpinner, Card } from '../components/ui';
import type { Company } from '../api/hooks';
const columns: Column<Company>[] = [
@@ -23,13 +24,25 @@ const columns: Column<Company>[] = [
export function CompaniesPage() {
const navigate = useNavigate();
const { data, isLoading, error } = useCompanies();
const [showAdd, setShowAdd] = useState(false);
if (isLoading) return <LoadingSpinner />;
if (error) return <div className="text-red-400">Failed to load companies</div>;
return (
<div>
<h1 className="mb-4 text-xl font-semibold text-gray-100">Companies</h1>
<div className="mb-4 flex items-center justify-between">
<h1 className="text-xl font-semibold text-gray-100">Companies</h1>
<button
onClick={() => setShowAdd(true)}
className="rounded-md bg-brand-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-brand-700"
>
Add Company
</button>
</div>
{showAdd && <AddCompanyForm onClose={() => setShowAdd(false)} />}
<DataTable<Company>
data={data ?? []}
columns={columns}
@@ -47,3 +60,61 @@ export function CompaniesPage() {
</div>
);
}
function AddCompanyForm({ onClose }: { onClose: () => void }) {
const [ticker, setTicker] = useState('');
const [name, setName] = useState('');
const [sector, setSector] = useState('');
const [exchange, setExchange] = useState('');
const mutation = useCreateCompany();
return (
<Card className="mb-4">
<form
className="space-y-3"
onSubmit={(e) => {
e.preventDefault();
if (ticker.trim() && name.trim()) {
mutation.mutate(
{
ticker: ticker.trim().toUpperCase(),
legal_name: name.trim(),
sector: sector || undefined,
exchange: exchange || undefined,
},
{ onSuccess: onClose },
);
}
}}
>
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
<div>
<label className="mb-1 block text-xs text-gray-500" htmlFor="add-ticker">Ticker</label>
<input id="add-ticker" type="text" value={ticker} onChange={(e) => setTicker(e.target.value)} required placeholder="AAPL" className="w-full rounded-md border border-surface-700 bg-surface-900 px-2 py-1.5 text-sm text-gray-200 placeholder-gray-500 uppercase" />
</div>
<div>
<label className="mb-1 block text-xs text-gray-500" htmlFor="add-name">Legal Name</label>
<input id="add-name" type="text" value={name} onChange={(e) => setName(e.target.value)} required placeholder="Apple Inc." className="w-full rounded-md border border-surface-700 bg-surface-900 px-2 py-1.5 text-sm text-gray-200 placeholder-gray-500" />
</div>
<div>
<label className="mb-1 block text-xs text-gray-500" htmlFor="add-sector">Sector</label>
<input id="add-sector" type="text" value={sector} onChange={(e) => setSector(e.target.value)} placeholder="Technology" className="w-full rounded-md border border-surface-700 bg-surface-900 px-2 py-1.5 text-sm text-gray-200 placeholder-gray-500" />
</div>
<div>
<label className="mb-1 block text-xs text-gray-500" htmlFor="add-exchange">Exchange</label>
<input id="add-exchange" type="text" value={exchange} onChange={(e) => setExchange(e.target.value)} placeholder="NASDAQ" className="w-full rounded-md border border-surface-700 bg-surface-900 px-2 py-1.5 text-sm text-gray-200 placeholder-gray-500" />
</div>
</div>
{mutation.error && <div className="text-xs text-red-400">Failed to create company</div>}
<div className="flex gap-2">
<button type="submit" disabled={mutation.isPending} className="rounded-md bg-brand-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-brand-700 disabled:opacity-50">
{mutation.isPending ? 'Creating…' : 'Create'}
</button>
<button type="button" onClick={onClose} className="rounded-md border border-surface-700 px-3 py-1.5 text-sm text-gray-400 hover:bg-surface-800">
Cancel
</button>
</div>
</form>
</Card>
);
}