Add missing frontend platform components and update production deployment

This commit adds all previously untracked files and modifications needed for production deployment:
- New marketing components (BenefitsSection, CodeBlock, PluginShowcase, PricingTable)
- Platform admin components (EditPlatformEntityModal, PlatformListRow, PlatformListing, PlatformTable)
- Updated deployment configuration and scripts
- Various frontend API and component improvements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-30 19:49:06 -05:00
parent 0d1a3045fb
commit 2b321aef57
34 changed files with 1930 additions and 1291 deletions

View File

@@ -64,7 +64,7 @@ export interface User {
* Login user
*/
export const login = async (credentials: LoginCredentials): Promise<LoginResponse> => {
const response = await apiClient.post<LoginResponse>('/auth/login/', credentials);
const response = await apiClient.post<LoginResponse>('/api/auth/login/', credentials);
return response.data;
};
@@ -72,14 +72,14 @@ export const login = async (credentials: LoginCredentials): Promise<LoginRespons
* Logout user
*/
export const logout = async (): Promise<void> => {
await apiClient.post('/auth/logout/');
await apiClient.post('/api/auth/logout/');
};
/**
* Get current user
*/
export const getCurrentUser = async (): Promise<User> => {
const response = await apiClient.get<User>('/auth/me/');
const response = await apiClient.get<User>('/api/auth/me/');
return response.data;
};
@@ -87,7 +87,7 @@ export const getCurrentUser = async (): Promise<User> => {
* Refresh access token
*/
export const refreshToken = async (refresh: string): Promise<{ access: string }> => {
const response = await apiClient.post('/auth/refresh/', { refresh });
const response = await apiClient.post('/api/auth/refresh/', { refresh });
return response.data;
};
@@ -99,7 +99,7 @@ export const masquerade = async (
hijack_history?: MasqueradeStackEntry[]
): Promise<LoginResponse> => {
const response = await apiClient.post<LoginResponse>(
'/auth/hijack/acquire/',
'/api/auth/hijack/acquire/',
{ user_pk, hijack_history }
);
return response.data;
@@ -112,7 +112,7 @@ export const stopMasquerade = async (
masquerade_stack: MasqueradeStackEntry[]
): Promise<LoginResponse> => {
const response = await apiClient.post<LoginResponse>(
'/auth/hijack/release/',
'/api/auth/hijack/release/',
{ masquerade_stack }
);
return response.data;

View File

@@ -29,7 +29,7 @@ export const getNotifications = async (params?: { read?: boolean; limit?: number
queryParams.append('limit', String(params.limit));
}
const query = queryParams.toString();
const url = query ? `/notifications/?${query}` : '/notifications/';
const url = query ? `/api/notifications/?${query}` : '/api/notifications/';
const response = await apiClient.get(url);
return response.data;
};
@@ -38,7 +38,7 @@ export const getNotifications = async (params?: { read?: boolean; limit?: number
* Get count of unread notifications
*/
export const getUnreadCount = async (): Promise<number> => {
const response = await apiClient.get<UnreadCountResponse>('/notifications/unread_count/');
const response = await apiClient.get<UnreadCountResponse>('/api/notifications/unread_count/');
return response.data.count;
};
@@ -46,19 +46,19 @@ export const getUnreadCount = async (): Promise<number> => {
* Mark a single notification as read
*/
export const markNotificationRead = async (id: number): Promise<void> => {
await apiClient.post(`/notifications/${id}/mark_read/`);
await apiClient.post(`/api/notifications/${id}/mark_read/`);
};
/**
* Mark all notifications as read
*/
export const markAllNotificationsRead = async (): Promise<void> => {
await apiClient.post('/notifications/mark_all_read/');
await apiClient.post('/api/notifications/mark_all_read/');
};
/**
* Delete all read notifications
*/
export const clearAllNotifications = async (): Promise<void> => {
await apiClient.delete('/notifications/clear_all/');
await apiClient.delete('/api/notifications/clear_all/');
};

View File

@@ -45,7 +45,7 @@ export interface OAuthConnection {
* Get list of enabled OAuth providers
*/
export const getOAuthProviders = async (): Promise<OAuthProvider[]> => {
const response = await apiClient.get<{ providers: OAuthProvider[] }>('/auth/oauth/providers/');
const response = await apiClient.get<{ providers: OAuthProvider[] }>('/api/auth/oauth/providers/');
return response.data.providers;
};
@@ -54,7 +54,7 @@ export const getOAuthProviders = async (): Promise<OAuthProvider[]> => {
*/
export const initiateOAuth = async (provider: string): Promise<OAuthAuthorizationResponse> => {
const response = await apiClient.get<OAuthAuthorizationResponse>(
`/auth/oauth/${provider}/authorize/`
`/api/auth/oauth/${provider}/authorize/`
);
return response.data;
};
@@ -68,7 +68,7 @@ export const handleOAuthCallback = async (
state: string
): Promise<OAuthTokenResponse> => {
const response = await apiClient.post<OAuthTokenResponse>(
`/auth/oauth/${provider}/callback/`,
`/api/auth/oauth/${provider}/callback/`,
{
code,
state,
@@ -81,7 +81,7 @@ export const handleOAuthCallback = async (
* Get user's connected OAuth accounts
*/
export const getOAuthConnections = async (): Promise<OAuthConnection[]> => {
const response = await apiClient.get<{ connections: OAuthConnection[] }>('/auth/oauth/connections/');
const response = await apiClient.get<{ connections: OAuthConnection[] }>('/api/auth/oauth/connections/');
return response.data.connections;
};
@@ -89,5 +89,5 @@ export const getOAuthConnections = async (): Promise<OAuthConnection[]> => {
* Disconnect an OAuth account
*/
export const disconnectOAuth = async (provider: string): Promise<void> => {
await apiClient.delete(`/auth/oauth/connections/${provider}/`);
await apiClient.delete(`/api/auth/oauth/connections/${provider}/`);
};

View File

@@ -11,6 +11,7 @@ export interface PlatformBusinessOwner {
full_name: string;
email: string;
role: string;
email_verified: boolean;
}
export interface PlatformBusiness {
@@ -72,6 +73,7 @@ export interface PlatformUser {
is_active: boolean;
is_staff: boolean;
is_superuser: boolean;
email_verified: boolean;
business: number | null;
business_name?: string;
business_subdomain?: string;
@@ -83,7 +85,7 @@ export interface PlatformUser {
* Get all businesses (platform admin only)
*/
export const getBusinesses = async (): Promise<PlatformBusiness[]> => {
const response = await apiClient.get<PlatformBusiness[]>('/platform/businesses/');
const response = await apiClient.get<PlatformBusiness[]>('/api/platform/businesses/');
return response.data;
};
@@ -95,7 +97,7 @@ export const updateBusiness = async (
data: PlatformBusinessUpdate
): Promise<PlatformBusiness> => {
const response = await apiClient.patch<PlatformBusiness>(
`/platform/businesses/${businessId}/`,
`/api/platform/businesses/${businessId}/`,
data
);
return response.data;
@@ -108,7 +110,7 @@ export const createBusiness = async (
data: PlatformBusinessCreate
): Promise<PlatformBusiness> => {
const response = await apiClient.post<PlatformBusiness>(
'/platform/businesses/',
'/api/platform/businesses/',
data
);
return response.data;
@@ -118,7 +120,7 @@ export const createBusiness = async (
* Get all users (platform admin only)
*/
export const getUsers = async (): Promise<PlatformUser[]> => {
const response = await apiClient.get<PlatformUser[]>('/platform/users/');
const response = await apiClient.get<PlatformUser[]>('/api/platform/users/');
return response.data;
};
@@ -126,10 +128,17 @@ export const getUsers = async (): Promise<PlatformUser[]> => {
* Get users for a specific business
*/
export const getBusinessUsers = async (businessId: number): Promise<PlatformUser[]> => {
const response = await apiClient.get<PlatformUser[]>(`/platform/users/?business=${businessId}`);
const response = await apiClient.get<PlatformUser[]>(`/api/platform/users/?business=${businessId}`);
return response.data;
};
/**
* Verify a user's email (platform admin only)
*/
export const verifyUserEmail = async (userId: number): Promise<void> => {
await apiClient.post(`/api/platform/users/${userId}/verify_email/`);
};
// ============================================================================
// Tenant Invitations
// ============================================================================
@@ -209,7 +218,7 @@ export interface TenantInvitationAccept {
* Get all tenant invitations (platform admin only)
*/
export const getTenantInvitations = async (): Promise<TenantInvitation[]> => {
const response = await apiClient.get<TenantInvitation[]>('/platform/tenant-invitations/');
const response = await apiClient.get<TenantInvitation[]>('/api/platform/tenant-invitations/');
return response.data;
};
@@ -220,7 +229,7 @@ export const createTenantInvitation = async (
data: TenantInvitationCreate
): Promise<TenantInvitation> => {
const response = await apiClient.post<TenantInvitation>(
'/platform/tenant-invitations/',
'/api/platform/tenant-invitations/',
data
);
return response.data;
@@ -230,14 +239,14 @@ export const createTenantInvitation = async (
* Resend a tenant invitation (platform admin only)
*/
export const resendTenantInvitation = async (invitationId: number): Promise<void> => {
await apiClient.post(`/platform/tenant-invitations/${invitationId}/resend/`);
await apiClient.post(`/api/platform/tenant-invitations/${invitationId}/resend/`);
};
/**
* Cancel a tenant invitation (platform admin only)
*/
export const cancelTenantInvitation = async (invitationId: number): Promise<void> => {
await apiClient.post(`/platform/tenant-invitations/${invitationId}/cancel/`);
await apiClient.post(`/api/platform/tenant-invitations/${invitationId}/cancel/`);
};
/**
@@ -245,7 +254,7 @@ export const cancelTenantInvitation = async (invitationId: number): Promise<void
*/
export const getInvitationByToken = async (token: string): Promise<TenantInvitationDetail> => {
const response = await apiClient.get<TenantInvitationDetail>(
`/platform/tenant-invitations/token/${token}/`
`/api/platform/tenant-invitations/token/${token}/`
);
return response.data;
};
@@ -258,7 +267,7 @@ export const acceptInvitation = async (
data: TenantInvitationAccept
): Promise<{ detail: string }> => {
const response = await apiClient.post<{ detail: string }>(
`/platform/tenant-invitations/token/${token}/accept/`,
`/api/platform/tenant-invitations/token/${token}/accept/`,
data
);
return response.data;