feat(frontend): add user attributes management UI
Add Vue components and API client for managing user custom attributes. - Add userAttributes API client with CRUD operations - Add UserAttributeForm component for displaying/editing attribute values - Add UserAttributesConfigModal for attribute definition management - Support all attribute types: text, textarea, number, email, url, date, select, multi_select 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import subscriptionsAPI from './subscriptions'
|
||||
import usageAPI from './usage'
|
||||
import geminiAPI from './gemini'
|
||||
import antigravityAPI from './antigravity'
|
||||
import userAttributesAPI from './userAttributes'
|
||||
|
||||
/**
|
||||
* Unified admin API object for convenient access
|
||||
@@ -31,7 +32,8 @@ export const adminAPI = {
|
||||
subscriptions: subscriptionsAPI,
|
||||
usage: usageAPI,
|
||||
gemini: geminiAPI,
|
||||
antigravity: antigravityAPI
|
||||
antigravity: antigravityAPI,
|
||||
userAttributes: userAttributesAPI
|
||||
}
|
||||
|
||||
export {
|
||||
@@ -46,7 +48,8 @@ export {
|
||||
subscriptionsAPI,
|
||||
usageAPI,
|
||||
geminiAPI,
|
||||
antigravityAPI
|
||||
antigravityAPI,
|
||||
userAttributesAPI
|
||||
}
|
||||
|
||||
export default adminAPI
|
||||
|
||||
131
frontend/src/api/admin/userAttributes.ts
Normal file
131
frontend/src/api/admin/userAttributes.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Admin User Attributes API endpoints
|
||||
* Handles user custom attribute definitions and values
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client'
|
||||
import type {
|
||||
UserAttributeDefinition,
|
||||
UserAttributeValue,
|
||||
CreateUserAttributeRequest,
|
||||
UpdateUserAttributeRequest,
|
||||
UserAttributeValuesMap
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* Get all attribute definitions
|
||||
*/
|
||||
export async function listDefinitions(): Promise<UserAttributeDefinition[]> {
|
||||
const { data } = await apiClient.get<UserAttributeDefinition[]>('/admin/user-attributes')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get enabled attribute definitions only
|
||||
*/
|
||||
export async function listEnabledDefinitions(): Promise<UserAttributeDefinition[]> {
|
||||
const { data } = await apiClient.get<UserAttributeDefinition[]>('/admin/user-attributes', {
|
||||
params: { enabled: true }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new attribute definition
|
||||
*/
|
||||
export async function createDefinition(
|
||||
request: CreateUserAttributeRequest
|
||||
): Promise<UserAttributeDefinition> {
|
||||
const { data } = await apiClient.post<UserAttributeDefinition>('/admin/user-attributes', request)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an attribute definition
|
||||
*/
|
||||
export async function updateDefinition(
|
||||
id: number,
|
||||
request: UpdateUserAttributeRequest
|
||||
): Promise<UserAttributeDefinition> {
|
||||
const { data } = await apiClient.put<UserAttributeDefinition>(
|
||||
`/admin/user-attributes/${id}`,
|
||||
request
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an attribute definition
|
||||
*/
|
||||
export async function deleteDefinition(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/user-attributes/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder attribute definitions
|
||||
*/
|
||||
export async function reorderDefinitions(ids: number[]): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.put<{ message: string }>('/admin/user-attributes/reorder', {
|
||||
ids
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's attribute values
|
||||
*/
|
||||
export async function getUserAttributeValues(userId: number): Promise<UserAttributeValue[]> {
|
||||
const { data } = await apiClient.get<UserAttributeValue[]>(
|
||||
`/admin/users/${userId}/attributes`
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user's attribute values (batch)
|
||||
*/
|
||||
export async function updateUserAttributeValues(
|
||||
userId: number,
|
||||
values: UserAttributeValuesMap
|
||||
): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.put<{ message: string }>(
|
||||
`/admin/users/${userId}/attributes`,
|
||||
{ values }
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch response type
|
||||
*/
|
||||
export interface BatchUserAttributesResponse {
|
||||
attributes: Record<number, Record<number, string>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attribute values for multiple users
|
||||
*/
|
||||
export async function getBatchUserAttributes(
|
||||
userIds: number[]
|
||||
): Promise<BatchUserAttributesResponse> {
|
||||
const { data } = await apiClient.post<BatchUserAttributesResponse>(
|
||||
'/admin/user-attributes/batch',
|
||||
{ user_ids: userIds }
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
export const userAttributesAPI = {
|
||||
listDefinitions,
|
||||
listEnabledDefinitions,
|
||||
createDefinition,
|
||||
updateDefinition,
|
||||
deleteDefinition,
|
||||
reorderDefinitions,
|
||||
getUserAttributeValues,
|
||||
updateUserAttributeValues,
|
||||
getBatchUserAttributes
|
||||
}
|
||||
|
||||
export default userAttributesAPI
|
||||
Reference in New Issue
Block a user