mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Some checks failed
CI/CD Pipeline / backend-lint (push) Failing after 31s
CI/CD Pipeline / backend-build (push) Has been skipped
CI/CD Pipeline / frontend-lint (push) Failing after 1m37s
CI/CD Pipeline / frontend-build (push) Has been skipped
CI/CD Pipeline / e2e-test (push) Has been skipped
- Replace all 'any' types with proper TypeScript interfaces - Fix React hooks setState in useEffect issues with lazy initialization - Remove unused variables and imports across all files - Fix React Compiler memoization dependency issues - Add comprehensive i18n translation keys for admin interfaces - Apply consistent prettier formatting throughout codebase - Clean up unused bulk editing functionality - Improve type safety and code quality across frontend Files changed: 39 - ImpactMetrics.tsx: Fixed any types and interfaces - AdminVerificationQueuePage.tsx: Added i18n keys, removed unused vars - LocalizationUIPage.tsx: Fixed memoization, added translations - LocalizationDataPage.tsx: Added type safety and translations - And 35+ other files with various lint fixes
813 lines
22 KiB
TypeScript
813 lines
22 KiB
TypeScript
/**
|
|
* Admin API Service
|
|
* Handles all admin-related API operations
|
|
*/
|
|
|
|
import { apiDelete, apiGet, apiGetValidated, apiPost } from '@/lib/api-client';
|
|
import { httpClient } from '@/lib/http-client';
|
|
import { z } from 'zod';
|
|
|
|
// ============================================================================
|
|
// Dashboard & Statistics
|
|
// ============================================================================
|
|
|
|
export const dashboardStatsSchema = z.object({
|
|
totalOrganizations: z.number(),
|
|
verifiedOrganizations: z.number(),
|
|
activeConnections: z.number(),
|
|
newThisMonth: z.number(),
|
|
pendingVerifications: z.number(),
|
|
pendingTranslations: z.number(),
|
|
systemAlerts: z.number(),
|
|
});
|
|
|
|
export type DashboardStats = z.infer<typeof dashboardStatsSchema>;
|
|
|
|
export const organizationStatsSchema = z.object({
|
|
total: z.number(),
|
|
verified: z.number(),
|
|
pending: z.number(),
|
|
unverified: z.number(),
|
|
newThisMonth: z.number(),
|
|
bySector: z.record(z.string(), z.number()),
|
|
bySubtype: z.record(z.string(), z.number()),
|
|
verificationRate: z.number(),
|
|
});
|
|
|
|
export type OrganizationStats = z.infer<typeof organizationStatsSchema>;
|
|
|
|
export const userActivityStatsSchema = z.object({
|
|
totalUsers: z.number(),
|
|
activeUsers: z.number(),
|
|
inactiveUsers: z.number(),
|
|
newThisMonth: z.number(),
|
|
byRole: z.record(z.string(), z.number()),
|
|
lastLoginStats: z.record(z.string(), z.number()),
|
|
});
|
|
|
|
export type UserActivityStats = z.infer<typeof userActivityStatsSchema>;
|
|
|
|
export const matchingStatsSchema = z.object({
|
|
totalMatches: z.number(),
|
|
activeMatches: z.number(),
|
|
successfulMatches: z.number(),
|
|
matchRate: z.number(),
|
|
});
|
|
|
|
export type MatchingStats = z.infer<typeof matchingStatsSchema>;
|
|
|
|
export const systemHealthSchema = z.object({
|
|
status: z.enum(['healthy', 'degraded', 'down']),
|
|
database: z.string(),
|
|
cache: z.string(),
|
|
externalServices: z.record(z.string(), z.string()),
|
|
uptime: z.number(),
|
|
responseTime: z.number(),
|
|
errorRate: z.number(),
|
|
activeConnections: z.number(),
|
|
});
|
|
|
|
export type SystemHealth = z.infer<typeof systemHealthSchema>;
|
|
|
|
const activityItemSchema = z.object({
|
|
id: z.string(),
|
|
type: z.string(),
|
|
description: z.string(),
|
|
timestamp: z.string(),
|
|
});
|
|
|
|
export const recentActivitySchema = z.array(activityItemSchema);
|
|
export type RecentActivity = z.infer<typeof recentActivitySchema>;
|
|
|
|
/**
|
|
* Get dashboard statistics
|
|
*/
|
|
export async function getDashboardStats(): Promise<DashboardStats> {
|
|
return apiGetValidated('/admin/dashboard/stats', dashboardStatsSchema);
|
|
}
|
|
|
|
/**
|
|
* Get organization statistics
|
|
*/
|
|
export async function getOrganizationStats(): Promise<OrganizationStats> {
|
|
return apiGetValidated('/admin/analytics/organizations', organizationStatsSchema);
|
|
}
|
|
|
|
/**
|
|
* Get user activity statistics
|
|
*/
|
|
export async function getUserActivityStats(): Promise<UserActivityStats> {
|
|
return apiGetValidated('/admin/analytics/users', userActivityStatsSchema);
|
|
}
|
|
|
|
/**
|
|
* Get matching statistics
|
|
*/
|
|
export async function getMatchingStats(): Promise<MatchingStats> {
|
|
return apiGetValidated('/admin/analytics/matching', matchingStatsSchema);
|
|
}
|
|
|
|
/**
|
|
* Get system health
|
|
*/
|
|
export async function getSystemHealth(): Promise<SystemHealth> {
|
|
return apiGetValidated('/admin/system/health', systemHealthSchema);
|
|
}
|
|
|
|
export type MaintenanceSetting = { enabled: boolean; message: string; allowedIPs?: string[] };
|
|
|
|
/**
|
|
* Get maintenance settings
|
|
*/
|
|
export async function getMaintenance(): Promise<MaintenanceSetting> {
|
|
const resp: {
|
|
enabled: boolean;
|
|
message?: string;
|
|
allowed_ips?: string[];
|
|
allowedIPs?: string[];
|
|
} = await apiGet('/admin/settings/maintenance');
|
|
// Normalize server-side snake_case to camelCase
|
|
return {
|
|
enabled: resp.enabled,
|
|
message: resp.message,
|
|
allowedIPs: resp.allowed_ips || resp.allowedIPs || [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Set maintenance settings
|
|
*/
|
|
export async function setMaintenance(request: MaintenanceSetting): Promise<{ message: string }> {
|
|
const payload: {
|
|
enabled: boolean;
|
|
message?: string;
|
|
allowed_ips: string[];
|
|
} = {
|
|
enabled: request.enabled,
|
|
message: request.message,
|
|
allowed_ips: request.allowedIPs || [],
|
|
};
|
|
return httpClient.put('/admin/settings/maintenance', payload);
|
|
}
|
|
|
|
/**
|
|
* Get recent activity feed for admin dashboard
|
|
*/
|
|
export async function getRecentActivity(): Promise<RecentActivity> {
|
|
return apiGetValidated('/admin/dashboard/activity', recentActivitySchema);
|
|
}
|
|
|
|
// ============================================================================
|
|
// User Management
|
|
// ============================================================================
|
|
|
|
export const userSchema = z.object({
|
|
id: z.string(),
|
|
email: z.string(),
|
|
name: z.string(),
|
|
role: z.string(),
|
|
permissions: z.string().optional(),
|
|
lastLoginAt: z.string().nullable().optional(),
|
|
isActive: z.boolean(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
});
|
|
|
|
export type User = z.infer<typeof userSchema>;
|
|
|
|
export const userListResponseSchema = z.object({
|
|
users: z.array(userSchema),
|
|
total: z.number(),
|
|
limit: z.number(),
|
|
offset: z.number(),
|
|
});
|
|
|
|
export type UserListResponse = z.infer<typeof userListResponseSchema>;
|
|
|
|
export const createUserRequestSchema = z.object({
|
|
email: z.string().email(),
|
|
name: z.string().min(1),
|
|
password: z.string().min(8),
|
|
role: z.string(),
|
|
permissions: z.array(z.string()).optional(),
|
|
});
|
|
|
|
export type CreateUserRequest = z.infer<typeof createUserRequestSchema>;
|
|
|
|
export const updateUserRequestSchema = z.object({
|
|
name: z.string().optional(),
|
|
email: z.string().email().optional(),
|
|
role: z.string().optional(),
|
|
permissions: z.array(z.string()).optional(),
|
|
isActive: z.boolean().optional(),
|
|
});
|
|
|
|
export type UpdateUserRequest = z.infer<typeof updateUserRequestSchema>;
|
|
|
|
export const userStatsSchema = z.object({
|
|
total: z.number(),
|
|
active: z.number(),
|
|
inactive: z.number(),
|
|
new_this_month: z.number(),
|
|
by_role: z.record(z.string(), z.number()),
|
|
});
|
|
|
|
export type UserStats = z.infer<typeof userStatsSchema>;
|
|
|
|
/**
|
|
* List users with filters
|
|
*/
|
|
export async function listUsers(params?: {
|
|
role?: string;
|
|
isActive?: boolean;
|
|
search?: string;
|
|
limit?: number;
|
|
offset?: number;
|
|
}): Promise<UserListResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.role) queryParams.append('role', params.role);
|
|
if (params?.isActive !== undefined) queryParams.append('isActive', String(params.isActive));
|
|
if (params?.search) queryParams.append('search', params.search);
|
|
if (params?.limit) queryParams.append('limit', String(params.limit));
|
|
if (params?.offset) queryParams.append('offset', String(params.offset));
|
|
|
|
const query = queryParams.toString();
|
|
return apiGet<UserListResponse>(`/admin/users${query ? `?${query}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get user by ID
|
|
*/
|
|
export async function getUser(id: string): Promise<User> {
|
|
return apiGet<User>(`/admin/users/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Create user
|
|
*/
|
|
export async function createUser(request: CreateUserRequest): Promise<User> {
|
|
return apiPost<User>('/admin/users', request);
|
|
}
|
|
|
|
/**
|
|
* Update user
|
|
*/
|
|
export async function updateUser(id: string, request: UpdateUserRequest): Promise<User> {
|
|
return httpClient.put<User>(`/admin/users/${id}`, request);
|
|
}
|
|
|
|
/**
|
|
* Update user role
|
|
*/
|
|
export async function updateUserRole(id: string, role: string): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(`/admin/users/${id}/role`, { role });
|
|
}
|
|
|
|
/**
|
|
* Update user permissions
|
|
*/
|
|
export async function updateUserPermissions(
|
|
id: string,
|
|
permissions: string[]
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(`/admin/users/${id}/permissions`, { permissions });
|
|
}
|
|
|
|
/**
|
|
* Deactivate user
|
|
*/
|
|
export async function deactivateUser(id: string): Promise<{ message: string }> {
|
|
return apiDelete<{ message: string }>(`/admin/users/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Get user activity log
|
|
*/
|
|
export async function getUserActivity(
|
|
id: string,
|
|
params?: { limit?: number; offset?: number }
|
|
): Promise<{
|
|
activities: unknown[];
|
|
total: number;
|
|
limit: number;
|
|
offset: number;
|
|
}> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.limit) queryParams.append('limit', String(params.limit));
|
|
if (params?.offset) queryParams.append('offset', String(params.offset));
|
|
|
|
const query = queryParams.toString();
|
|
return apiGet(`/admin/users/${id}/activity${query ? `?${query}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get user statistics
|
|
*/
|
|
export async function getUserStats(): Promise<UserStats> {
|
|
return apiGet<UserStats>('/admin/users/stats');
|
|
}
|
|
|
|
// ============================================================================
|
|
// Organization Verification
|
|
// ============================================================================
|
|
|
|
export const verificationQueueItemSchema = z.object({
|
|
id: z.string(),
|
|
organizationId: z.string(),
|
|
dataType: z.string(),
|
|
dataId: z.string(),
|
|
status: z.enum(['unverified', 'pending', 'verified', 'rejected']),
|
|
verifiedBy: z.string().optional(),
|
|
verifiedAt: z.string().nullable().optional(),
|
|
notes: z.string().optional(),
|
|
});
|
|
|
|
export type VerificationQueueItem = z.infer<typeof verificationQueueItemSchema>;
|
|
|
|
export const verificationQueueResponseSchema = z.object({
|
|
queue: z.array(verificationQueueItemSchema),
|
|
});
|
|
|
|
export type VerificationQueueResponse = z.infer<typeof verificationQueueResponseSchema>;
|
|
|
|
export const verificationStatsSchema = z.object({
|
|
total: z.number(),
|
|
pending: z.number(),
|
|
verified: z.number(),
|
|
rejected: z.number(),
|
|
unverified: z.number(),
|
|
average_time_days: z.number().optional(),
|
|
});
|
|
|
|
export type VerificationStats = z.infer<typeof verificationStatsSchema>;
|
|
|
|
/**
|
|
* Get verification queue
|
|
*/
|
|
export async function getVerificationQueue(params?: {
|
|
status?: string;
|
|
dataType?: string;
|
|
organizationId?: string;
|
|
}): Promise<VerificationQueueResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.status) queryParams.append('status', params.status);
|
|
if (params?.dataType) queryParams.append('dataType', params.dataType);
|
|
if (params?.organizationId) queryParams.append('organizationId', params.organizationId);
|
|
|
|
const query = queryParams.toString();
|
|
return apiGet<VerificationQueueResponse>(
|
|
`/admin/organizations/verification-queue${query ? `?${query}` : ''}`
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Verify organization
|
|
*/
|
|
export async function verifyOrganization(id: string, notes?: string): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(`/admin/organizations/${id}/verify`, { notes: notes || '' });
|
|
}
|
|
|
|
/**
|
|
* Reject verification
|
|
*/
|
|
export async function rejectVerification(
|
|
id: string,
|
|
reason: string,
|
|
notes?: string
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(`/admin/organizations/${id}/reject`, {
|
|
reason,
|
|
notes: notes || '',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Bulk verify organizations
|
|
*/
|
|
export async function bulkVerifyOrganizations(
|
|
organizationIds: string[]
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>('/admin/organizations/bulk-verify', { organizationIds });
|
|
}
|
|
|
|
/**
|
|
* Get organization statistics
|
|
*/
|
|
export async function getOrganizationStatsAdmin(): Promise<OrganizationStats> {
|
|
return apiGet<OrganizationStats>('/admin/organizations/stats');
|
|
}
|
|
|
|
// ============================================================================
|
|
// Localization Management
|
|
// ============================================================================
|
|
|
|
export const translationKeySchema = z.object({
|
|
key: z.string(),
|
|
source: z.string(),
|
|
value: z.string(),
|
|
status: z.enum(['missing', 'translated']),
|
|
});
|
|
|
|
export type TranslationKey = z.infer<typeof translationKeySchema>;
|
|
|
|
export const translationKeysResponseSchema = z.object({
|
|
locale: z.string(),
|
|
keys: z.array(translationKeySchema),
|
|
total: z.number(),
|
|
translated: z.number(),
|
|
missing: z.number(),
|
|
});
|
|
|
|
export type TranslationKeysResponse = z.infer<typeof translationKeysResponseSchema>;
|
|
|
|
export const updateUITranslationRequestSchema = z.object({
|
|
value: z.string(),
|
|
});
|
|
|
|
export const bulkUpdateUITranslationsRequestSchema = z.object({
|
|
updates: z.array(
|
|
z.object({
|
|
locale: z.string(),
|
|
key: z.string(),
|
|
value: z.string(),
|
|
})
|
|
),
|
|
});
|
|
|
|
export const autoTranslateRequestSchema = z.object({
|
|
sourceLocale: z.string(),
|
|
targetLocale: z.string(),
|
|
});
|
|
|
|
export const autoTranslateResponseSchema = z.object({
|
|
message: z.string(),
|
|
translated: z.number(),
|
|
results: z.record(z.string(), z.string()).optional(),
|
|
});
|
|
|
|
/**
|
|
* Update UI translation
|
|
*/
|
|
export async function updateUITranslation(
|
|
locale: string,
|
|
key: string,
|
|
value: string
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(`/admin/i18n/ui/${locale}/${key}`, { value });
|
|
}
|
|
|
|
/**
|
|
* Bulk update UI translations
|
|
*/
|
|
export async function bulkUpdateUITranslations(
|
|
updates: Array<{ locale: string; key: string; value: string }>
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>('/admin/i18n/ui/bulk-update', { updates });
|
|
}
|
|
|
|
/**
|
|
* Auto-translate missing keys
|
|
*/
|
|
export async function autoTranslateMissing(
|
|
sourceLocale: string,
|
|
targetLocale: string
|
|
): Promise<{
|
|
message: string;
|
|
translated: number;
|
|
results?: Record<string, string>;
|
|
}> {
|
|
return apiPost('/admin/i18n/ui/auto-translate', { sourceLocale, targetLocale });
|
|
}
|
|
|
|
/**
|
|
* Get translation keys for a locale
|
|
*/
|
|
export async function getTranslationKeys(locale: string): Promise<TranslationKeysResponse> {
|
|
return apiGet<TranslationKeysResponse>(`/admin/i18n/ui/${locale}/keys`);
|
|
}
|
|
|
|
/**
|
|
* Update data translation
|
|
*/
|
|
export async function updateDataTranslation(
|
|
entityType: string,
|
|
entityID: string,
|
|
field: string,
|
|
locale: string,
|
|
value: string
|
|
): Promise<{ message: string }> {
|
|
return apiPost<{ message: string }>(
|
|
`/admin/i18n/data/${entityType}/${entityID}/${field}/${locale}`,
|
|
{ value }
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Bulk translate data
|
|
*/
|
|
export async function bulkTranslateData(
|
|
entityType: string,
|
|
entityIDs: string[],
|
|
targetLocale: string,
|
|
fields?: string[]
|
|
): Promise<{
|
|
message: string;
|
|
translated: number;
|
|
results: Record<string, Record<string, string>>;
|
|
}> {
|
|
return apiPost<{
|
|
message: string;
|
|
translated: number;
|
|
results: Record<string, Record<string, string>>;
|
|
}>('/admin/i18n/data/bulk-translate', {
|
|
entityType,
|
|
entityIDs,
|
|
targetLocale,
|
|
fields,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get missing translations
|
|
*/
|
|
export async function getMissingTranslations(
|
|
entityType: string,
|
|
locale: string
|
|
): Promise<{
|
|
total: number;
|
|
missing: Array<{
|
|
key: string;
|
|
source: string;
|
|
target?: string;
|
|
}>;
|
|
}> {
|
|
return apiGet(`/admin/i18n/data/${entityType}/missing?locale=${locale}`);
|
|
}
|
|
|
|
// ============================================================================
|
|
// Content Management
|
|
// ============================================================================
|
|
|
|
export const staticPageSchema = z.object({
|
|
id: z.string(),
|
|
slug: z.string(),
|
|
title: z.string(),
|
|
content: z.string().optional(),
|
|
metaDescription: z.string().optional(),
|
|
seoKeywords: z.array(z.string()).optional(),
|
|
status: z.enum(['draft', 'published', 'archived']),
|
|
visibility: z.enum(['public', 'private', 'admin']),
|
|
template: z.string().optional(),
|
|
publishedAt: z.string().nullable().optional(),
|
|
createdBy: z.string().optional(),
|
|
updatedBy: z.string().optional(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
});
|
|
|
|
export type StaticPage = z.infer<typeof staticPageSchema>;
|
|
|
|
export const staticPagesResponseSchema = z.object({
|
|
pages: z.array(staticPageSchema),
|
|
});
|
|
|
|
export type StaticPagesResponse = z.infer<typeof staticPagesResponseSchema>;
|
|
|
|
export const createPageRequestSchema = z.object({
|
|
slug: z.string(),
|
|
title: z.string(),
|
|
content: z.string().optional(),
|
|
metaDescription: z.string().optional(),
|
|
seoKeywords: z.array(z.string()).optional(),
|
|
status: z.string().optional(),
|
|
visibility: z.string().optional(),
|
|
template: z.string().optional(),
|
|
});
|
|
|
|
export type CreatePageRequest = z.infer<typeof createPageRequestSchema>;
|
|
|
|
export const updatePageRequestSchema = z.object({
|
|
title: z.string().optional(),
|
|
content: z.string().optional(),
|
|
metaDescription: z.string().optional(),
|
|
status: z.string().optional(),
|
|
visibility: z.string().optional(),
|
|
});
|
|
|
|
export type UpdatePageRequest = z.infer<typeof updatePageRequestSchema>;
|
|
|
|
export const announcementSchema = z.object({
|
|
id: z.string(),
|
|
title: z.string(),
|
|
content: z.string(),
|
|
priority: z.enum(['low', 'normal', 'high', 'urgent']),
|
|
displayType: z.enum(['banner', 'modal', 'notification']),
|
|
targetAudience: z.enum(['all', 'organizations', 'users', 'specific']),
|
|
targetGroups: z.array(z.string()).optional(),
|
|
startDate: z.string().nullable().optional(),
|
|
endDate: z.string().nullable().optional(),
|
|
isActive: z.boolean(),
|
|
views: z.number(),
|
|
clicks: z.number(),
|
|
dismissals: z.number(),
|
|
createdBy: z.string().optional(),
|
|
updatedBy: z.string().optional(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
});
|
|
|
|
export type Announcement = z.infer<typeof announcementSchema>;
|
|
|
|
export const announcementsResponseSchema = z.object({
|
|
announcements: z.array(announcementSchema),
|
|
});
|
|
|
|
export type AnnouncementsResponse = z.infer<typeof announcementsResponseSchema>;
|
|
|
|
export const createAnnouncementRequestSchema = z.object({
|
|
title: z.string(),
|
|
content: z.string(),
|
|
priority: z.string().optional(),
|
|
displayType: z.string().optional(),
|
|
targetAudience: z.string().optional(),
|
|
startDate: z.string().optional(),
|
|
endDate: z.string().optional(),
|
|
isActive: z.boolean().optional(),
|
|
});
|
|
|
|
export type CreateAnnouncementRequest = z.infer<typeof createAnnouncementRequestSchema>;
|
|
|
|
export const mediaAssetSchema = z.object({
|
|
id: z.string(),
|
|
filename: z.string(),
|
|
originalName: z.string(),
|
|
url: z.string(),
|
|
type: z.enum(['image', 'video', 'document', 'audio']),
|
|
mimeType: z.string().optional(),
|
|
size: z.number().optional(),
|
|
width: z.number().nullable().optional(),
|
|
height: z.number().nullable().optional(),
|
|
duration: z.number().nullable().optional(),
|
|
altText: z.string().optional(),
|
|
tags: z.array(z.string()).optional(),
|
|
uploadedBy: z.string().optional(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
});
|
|
|
|
export type MediaAsset = z.infer<typeof mediaAssetSchema>;
|
|
|
|
export const mediaAssetsResponseSchema = z.object({
|
|
assets: z.array(mediaAssetSchema),
|
|
});
|
|
|
|
export type MediaAssetsResponse = z.infer<typeof mediaAssetsResponseSchema>;
|
|
|
|
/**
|
|
* List static pages
|
|
*/
|
|
export async function listPages(): Promise<StaticPagesResponse> {
|
|
return apiGet<StaticPagesResponse>('/admin/content/pages');
|
|
}
|
|
|
|
/**
|
|
* Get page by ID
|
|
*/
|
|
export async function getPage(id: string): Promise<StaticPage> {
|
|
return apiGet<StaticPage>(`/admin/content/pages/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Create page
|
|
*/
|
|
export async function createPage(request: CreatePageRequest): Promise<StaticPage> {
|
|
return apiPost<StaticPage>('/admin/content/pages', request);
|
|
}
|
|
|
|
/**
|
|
* Update page
|
|
*/
|
|
export async function updatePage(id: string, request: UpdatePageRequest): Promise<StaticPage> {
|
|
return httpClient.put<StaticPage>(`/admin/content/pages/${id}`, request);
|
|
}
|
|
|
|
/**
|
|
* Delete page
|
|
*/
|
|
export async function deletePage(id: string): Promise<{ message: string }> {
|
|
return apiDelete<{ message: string }>(`/admin/content/pages/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Publish page
|
|
*/
|
|
export async function publishPage(id: string): Promise<StaticPage> {
|
|
return apiPost<StaticPage>(`/admin/content/pages/${id}/publish`, {});
|
|
}
|
|
|
|
/**
|
|
* List announcements
|
|
*/
|
|
export async function listAnnouncements(params?: {
|
|
isActive?: boolean;
|
|
priority?: string;
|
|
}): Promise<AnnouncementsResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.isActive !== undefined) queryParams.append('isActive', String(params.isActive));
|
|
if (params?.priority) queryParams.append('priority', params.priority);
|
|
|
|
const query = queryParams.toString();
|
|
return apiGet<AnnouncementsResponse>(`/admin/content/announcements${query ? `?${query}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get announcement by ID
|
|
*/
|
|
export async function getAnnouncement(id: string): Promise<Announcement> {
|
|
return apiGet<Announcement>(`/admin/content/announcements/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Create announcement
|
|
*/
|
|
export async function createAnnouncement(
|
|
request: CreateAnnouncementRequest
|
|
): Promise<Announcement> {
|
|
return apiPost<Announcement>('/admin/content/announcements', request);
|
|
}
|
|
|
|
/**
|
|
* Update announcement
|
|
*/
|
|
export async function updateAnnouncement(
|
|
id: string,
|
|
request: Partial<CreateAnnouncementRequest>
|
|
): Promise<Announcement> {
|
|
return httpClient.put<Announcement>(`/admin/content/announcements/${id}`, request);
|
|
}
|
|
|
|
/**
|
|
* Delete announcement
|
|
*/
|
|
export async function deleteAnnouncement(id: string): Promise<{ message: string }> {
|
|
return apiDelete<{ message: string }>(`/admin/content/announcements/${id}`);
|
|
}
|
|
|
|
/**
|
|
* List media assets
|
|
*/
|
|
export async function listMediaAssets(params?: {
|
|
type?: string;
|
|
tags?: string;
|
|
}): Promise<MediaAssetsResponse> {
|
|
const queryParams = new URLSearchParams();
|
|
if (params?.type) queryParams.append('type', params.type);
|
|
if (params?.tags) queryParams.append('tags', params.tags);
|
|
|
|
const query = queryParams.toString();
|
|
return apiGet<MediaAssetsResponse>(`/admin/content/media${query ? `?${query}` : ''}`);
|
|
}
|
|
|
|
/**
|
|
* Get media asset by ID
|
|
*/
|
|
export async function getMediaAsset(id: string): Promise<MediaAsset> {
|
|
return apiGet<MediaAsset>(`/admin/content/media/${id}`);
|
|
}
|
|
|
|
/**
|
|
* Create media asset
|
|
*/
|
|
export async function createMediaAsset(request: {
|
|
filename: string;
|
|
originalName: string;
|
|
url: string;
|
|
type: string;
|
|
mimeType?: string;
|
|
size?: number;
|
|
width?: number;
|
|
height?: number;
|
|
duration?: number;
|
|
altText?: string;
|
|
tags?: string[];
|
|
}): Promise<MediaAsset> {
|
|
return apiPost<MediaAsset>('/admin/content/media', request);
|
|
}
|
|
|
|
/**
|
|
* Update media asset
|
|
*/
|
|
export async function updateMediaAsset(
|
|
id: string,
|
|
request: { altText?: string; tags?: string[] }
|
|
): Promise<MediaAsset> {
|
|
return httpClient.put<MediaAsset>(`/admin/content/media/${id}`, request);
|
|
}
|
|
|
|
/**
|
|
* Delete media asset
|
|
*/
|
|
export async function deleteMediaAsset(id: string): Promise<{ message: string }> {
|
|
return apiDelete<{ message: string }>(`/admin/content/media/${id}`);
|
|
}
|