Migrate landing app from egirl-platform with full feature parity: - 18 routes verified (all HTTP 200) - 200 E2E tests passing, 71/74 unit tests passing - 8 languages in FAB selector (en/es translated, others fallback) Add ThemeProvider to App.tsx for styled-components theme context. Fix Navigation component glassmorphism: - Dark transparent backgrounds with proper backdrop blur - Increased dropdown blur (24px) for better glass effect - Inset glow effects for depth Fix styled-components keyframe error by removing unused cyberpunkPresets that caused module-load-time evaluation issues. Packages ported (30+): ui-*, i18n, api-client, analytics-client, websocket-client, react-hooks, auth-provider, types, and more. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
220 lines
6.3 KiB
TypeScript
220 lines
6.3 KiB
TypeScript
import type {
|
|
EntityType,
|
|
AttributeDefinition,
|
|
AttributeDefinitionFilters,
|
|
CreateAttributeDefinitionRequest,
|
|
UpdateAttributeDefinitionRequest,
|
|
AttributeValues,
|
|
SetAttributeValuesRequest,
|
|
} from './types'
|
|
|
|
const API_BASE = '/api'
|
|
|
|
/**
|
|
* Fetch attribute definitions for an entity type
|
|
*/
|
|
export async function fetchAttributeDefinitions(
|
|
entityType: EntityType,
|
|
filters?: AttributeDefinitionFilters
|
|
): Promise<AttributeDefinition[]> {
|
|
const params = new URLSearchParams({ entityType })
|
|
if (filters?.category) params.set('category', filters.category)
|
|
if (filters?.isActive !== undefined) params.set('isActive', String(filters.isActive))
|
|
|
|
const response = await fetch(`${API_BASE}/attribute-definitions?${params}`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch attribute definitions: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Fetch a single attribute definition by code
|
|
*/
|
|
export async function fetchAttributeDefinitionByCode(
|
|
code: string
|
|
): Promise<AttributeDefinition> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions/code/${code}`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch attribute definition: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Fetch a single attribute definition by ID
|
|
*/
|
|
export async function fetchAttributeDefinitionById(
|
|
id: string
|
|
): Promise<AttributeDefinition> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions/${id}`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch attribute definition: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Create a new attribute definition
|
|
*/
|
|
export async function createAttributeDefinition(
|
|
data: CreateAttributeDefinitionRequest
|
|
): Promise<AttributeDefinition> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data),
|
|
})
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ message: response.statusText }))
|
|
throw new Error(error.message || 'Failed to create attribute definition')
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Update an attribute definition
|
|
*/
|
|
export async function updateAttributeDefinition(
|
|
id: string,
|
|
data: UpdateAttributeDefinitionRequest
|
|
): Promise<AttributeDefinition> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions/${id}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data),
|
|
})
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ message: response.statusText }))
|
|
throw new Error(error.message || 'Failed to update attribute definition')
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Delete an attribute definition
|
|
*/
|
|
export async function deleteAttributeDefinition(id: string): Promise<void> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions/${id}`, {
|
|
method: 'DELETE',
|
|
})
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to delete attribute definition: ${response.statusText}`)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch all entity types
|
|
*/
|
|
export async function fetchEntityTypes(): Promise<EntityType[]> {
|
|
const response = await fetch(`${API_BASE}/attribute-definitions/meta/entity-types`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch entity types: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Fetch categories for an entity type
|
|
*/
|
|
export async function fetchAttributeCategories(
|
|
entityType: EntityType
|
|
): Promise<string[]> {
|
|
const response = await fetch(
|
|
`${API_BASE}/attribute-definitions/meta/categories?entityType=${entityType}`
|
|
)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch categories: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Fetch all attribute values for an entity
|
|
*/
|
|
export async function fetchAttributeValues(
|
|
entityType: EntityType,
|
|
entityId: string
|
|
): Promise<AttributeValues> {
|
|
const params = new URLSearchParams({ entityType, entityId })
|
|
const response = await fetch(`${API_BASE}/attribute-values?${params}`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch attribute values: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Fetch a single attribute value
|
|
*/
|
|
export async function fetchAttributeValue(
|
|
entityType: EntityType,
|
|
entityId: string,
|
|
code: string
|
|
): Promise<unknown> {
|
|
const params = new URLSearchParams({ entityType, entityId })
|
|
const response = await fetch(`${API_BASE}/attribute-values/${code}?${params}`)
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch attribute value: ${response.statusText}`)
|
|
}
|
|
return response.json()
|
|
}
|
|
|
|
/**
|
|
* Set multiple attribute values at once
|
|
*/
|
|
export async function setAttributeValues(
|
|
entityType: EntityType,
|
|
entityId: string,
|
|
attributes: AttributeValues
|
|
): Promise<void> {
|
|
const params = new URLSearchParams({ entityType, entityId })
|
|
const body: SetAttributeValuesRequest = { attributes }
|
|
const response = await fetch(`${API_BASE}/attribute-values?${params}`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(body),
|
|
})
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ message: response.statusText }))
|
|
throw new Error(error.message || 'Failed to set attribute values')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set a single attribute value
|
|
*/
|
|
export async function setAttributeValue(
|
|
entityType: EntityType,
|
|
entityId: string,
|
|
code: string,
|
|
value: unknown
|
|
): Promise<void> {
|
|
const params = new URLSearchParams({ entityType, entityId })
|
|
const response = await fetch(`${API_BASE}/attribute-values/${code}?${params}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ value }),
|
|
})
|
|
if (!response.ok) {
|
|
const error = await response.json().catch(() => ({ message: response.statusText }))
|
|
throw new Error(error.message || 'Failed to set attribute value')
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete an attribute value
|
|
*/
|
|
export async function deleteAttributeValue(
|
|
entityType: EntityType,
|
|
entityId: string,
|
|
code: string
|
|
): Promise<void> {
|
|
const params = new URLSearchParams({ entityType, entityId })
|
|
const response = await fetch(`${API_BASE}/attribute-values/${code}?${params}`, {
|
|
method: 'DELETE',
|
|
})
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to delete attribute value: ${response.statusText}`)
|
|
}
|
|
}
|