Spaces:
Paused
Paused
CrispStrobe commited on
Commit ·
d699da8
1
Parent(s): c3fc087
feat: implement 5 granular jurisdiction filters and shorten table labels
Browse files- src/App.css +5 -5
- src/App.tsx +20 -10
src/App.css
CHANGED
|
@@ -188,11 +188,11 @@ tr.group-divider {
|
|
| 188 |
}
|
| 189 |
|
| 190 |
/* Jurisdiction Colors */
|
| 191 |
-
.eu
|
| 192 |
-
.
|
| 193 |
-
.us-
|
| 194 |
-
.us
|
| 195 |
-
.other
|
| 196 |
|
| 197 |
footer {
|
| 198 |
margin-top: 2rem;
|
|
|
|
| 188 |
}
|
| 189 |
|
| 190 |
/* Jurisdiction Colors */
|
| 191 |
+
.eu { background-color: #dcfce7; color: #166534; }
|
| 192 |
+
.eea { background-color: #fef9c3; color: #854d0e; }
|
| 193 |
+
.us-eu { background-color: #ffedd5; color: #9a3412; }
|
| 194 |
+
.us { background-color: #fee2e2; color: #991b1b; }
|
| 195 |
+
.other { background-color: #f1f5f9; color: #475569; }
|
| 196 |
|
| 197 |
footer {
|
| 198 |
margin-top: 2rem;
|
src/App.tsx
CHANGED
|
@@ -90,6 +90,7 @@ const CAP_ICON: Record<string, string> = {
|
|
| 90 |
tools: '🔧',
|
| 91 |
reasoning: '💡',
|
| 92 |
embedding: '🧩',
|
|
|
|
| 93 |
}
|
| 94 |
|
| 95 |
function App() {
|
|
@@ -208,25 +209,28 @@ function App() {
|
|
| 208 |
setDataVersion((v) => v + 1);
|
| 209 |
}, []);
|
| 210 |
|
| 211 |
-
const getComplianceStatus = (provider: Provider) => {
|
| 212 |
const hq = provider.headquarters.toLowerCase();
|
| 213 |
const isEU = provider.region === 'EU' || hq === 'germany' || hq === 'france' || hq === 'netherlands';
|
| 214 |
-
const isUS = hq === 'usa';
|
| 215 |
const isEEA = provider.region === 'EEA Equivalent' || hq === 'switzerland';
|
| 216 |
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
if (
|
| 221 |
-
return '
|
|
|
|
|
|
|
|
|
|
| 222 |
};
|
| 223 |
|
| 224 |
const allModels = useMemo(() => {
|
| 225 |
const rawModels: (Model & { provider: Provider; complianceStatus: string })[] = []
|
| 226 |
|
| 227 |
liveProviders.forEach((provider: Provider) => {
|
| 228 |
-
const status = getComplianceStatus(provider);
|
| 229 |
provider.models.forEach((model) => {
|
|
|
|
| 230 |
let cleanName = model.name;
|
| 231 |
// Strip provider/ prefix for all models
|
| 232 |
if (cleanName.includes('/')) {
|
|
@@ -259,7 +263,11 @@ function App() {
|
|
| 259 |
const matchesSearch = model.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
| 260 |
model.provider.name.toLowerCase().includes(searchTerm.toLowerCase())
|
| 261 |
const matchesType = selectedType === 'all' || model.type === selectedType
|
| 262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
return matchesSearch && matchesType && matchesRegion
|
| 264 |
})
|
| 265 |
}, [searchTerm, selectedType, selectedRegion, allModels])
|
|
@@ -429,8 +437,10 @@ function App() {
|
|
| 429 |
<select value={selectedRegion} onChange={(e) => setSelectedRegion(e.target.value)} className="type-select">
|
| 430 |
<option value="all">All Jurisdictions</option>
|
| 431 |
<option value="EU">EU (Sovereign)</option>
|
| 432 |
-
<option value="
|
|
|
|
| 433 |
<option value="US">US (Cloud Act)</option>
|
|
|
|
| 434 |
</select>
|
| 435 |
<label className="checkbox-label">
|
| 436 |
<input
|
|
|
|
| 90 |
tools: '🔧',
|
| 91 |
reasoning: '💡',
|
| 92 |
embedding: '🧩',
|
| 93 |
+
'eu-endpoint': '🇪🇺',
|
| 94 |
}
|
| 95 |
|
| 96 |
function App() {
|
|
|
|
| 209 |
setDataVersion((v) => v + 1);
|
| 210 |
}, []);
|
| 211 |
|
| 212 |
+
const getComplianceStatus = (provider: Provider, model?: Model) => {
|
| 213 |
const hq = provider.headquarters.toLowerCase();
|
| 214 |
const isEU = provider.region === 'EU' || hq === 'germany' || hq === 'france' || hq === 'netherlands';
|
| 215 |
+
const isUS = hq === 'usa' || provider.region === 'US';
|
| 216 |
const isEEA = provider.region === 'EEA Equivalent' || hq === 'switzerland';
|
| 217 |
|
| 218 |
+
// Model-level override for OpenRouter or similar aggregators
|
| 219 |
+
const hasEuEndpoint = model?.capabilities?.includes('eu-endpoint') || provider.eu_endpoints;
|
| 220 |
+
|
| 221 |
+
if (isEU) return 'EU';
|
| 222 |
+
if (isEEA) return 'EEA';
|
| 223 |
+
if (isUS && hasEuEndpoint) return 'US/EU';
|
| 224 |
+
if (isUS) return 'US';
|
| 225 |
+
return 'Other';
|
| 226 |
};
|
| 227 |
|
| 228 |
const allModels = useMemo(() => {
|
| 229 |
const rawModels: (Model & { provider: Provider; complianceStatus: string })[] = []
|
| 230 |
|
| 231 |
liveProviders.forEach((provider: Provider) => {
|
|
|
|
| 232 |
provider.models.forEach((model) => {
|
| 233 |
+
const status = getComplianceStatus(provider, model);
|
| 234 |
let cleanName = model.name;
|
| 235 |
// Strip provider/ prefix for all models
|
| 236 |
if (cleanName.includes('/')) {
|
|
|
|
| 263 |
const matchesSearch = model.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
| 264 |
model.provider.name.toLowerCase().includes(searchTerm.toLowerCase())
|
| 265 |
const matchesType = selectedType === 'all' || model.type === selectedType
|
| 266 |
+
|
| 267 |
+
let matchesRegion = selectedRegion === 'all' || model.complianceStatus === selectedRegion;
|
| 268 |
+
// US filter includes US/EU
|
| 269 |
+
if (selectedRegion === 'US' && model.complianceStatus === 'US/EU') matchesRegion = true;
|
| 270 |
+
|
| 271 |
return matchesSearch && matchesType && matchesRegion
|
| 272 |
})
|
| 273 |
}, [searchTerm, selectedType, selectedRegion, allModels])
|
|
|
|
| 437 |
<select value={selectedRegion} onChange={(e) => setSelectedRegion(e.target.value)} className="type-select">
|
| 438 |
<option value="all">All Jurisdictions</option>
|
| 439 |
<option value="EU">EU (Sovereign)</option>
|
| 440 |
+
<option value="EEA">EEA (Swiss/EEA)</option>
|
| 441 |
+
<option value="US/EU">US/EU (EU Endpoint)</option>
|
| 442 |
<option value="US">US (Cloud Act)</option>
|
| 443 |
+
<option value="Other">Other</option>
|
| 444 |
</select>
|
| 445 |
<label className="checkbox-label">
|
| 446 |
<input
|