Add new frontend - fix 16

This commit is contained in:
Urtzi Alfaro
2025-07-23 07:26:04 +02:00
parent e6b0be0c95
commit 1d35912459
14 changed files with 588 additions and 169 deletions

View File

@@ -2,7 +2,7 @@
import { apiClient } from '../base/apiClient';
import {
ApiResponse,
TenantInfo,
TenantInfo, // Assuming TenantInfo is equivalent to TenantResponse from backend
} from '../types/api';
export interface TenantCreate {
@@ -84,52 +84,110 @@ export interface InviteUser {
send_invitation_email?: boolean;
}
// New interface for tenant member response based on backend
export interface TenantMemberResponse {
user_id: string;
tenant_id: string;
role: string;
// Add any other fields expected from the backend's TenantMemberResponse
}
export class TenantService {
/**
* Get current tenant info
* Register a new bakery (tenant)
* Corresponds to POST /tenants/register
*/
async registerBakery(bakeryData: TenantCreate): Promise<TenantInfo> {
const response = await apiClient.post<ApiResponse<TenantInfo>>('/api/v1/tenants/register', bakeryData);
return response.data!;
}
/**
* Get a specific tenant by ID
* Corresponds to GET /tenants/{tenant_id}
*/
async getTenantById(tenantId: string): Promise<TenantInfo> {
const response = await apiClient.get<ApiResponse<TenantInfo>>(`/api/v1/tenants/${tenantId}`);
return response.data!;
}
/**
* Update a specific tenant by ID
* Corresponds to PUT /tenants/{tenant_id}
*/
async updateTenant(tenantId: string, updates: TenantUpdate): Promise<TenantInfo> {
const response = await apiClient.put<ApiResponse<TenantInfo>>(`/api/v1/tenants/${tenantId}`, updates);
return response.data!;
}
/**
* Get all tenants associated with a user
* Corresponds to GET /users/{user_id}/tenants
*/
async getUserTenants(userId: string): Promise<TenantInfo[]> {
const response = await apiClient.get<ApiResponse<TenantInfo[]>>(`/api/v1/users/${userId}/tenants`);
return response.data!;
}
/**
* Add a team member to a tenant
* Corresponds to POST /tenants/{tenant_id}/members
*/
async addTeamMember(tenantId: string, userId: string, role: string): Promise<TenantMemberResponse> {
const response = await apiClient.post<ApiResponse<TenantMemberResponse>>(
`/api/v1/tenants/${tenantId}/members`,
{ user_id: userId, role }
);
return response.data!;
}
// --- Existing methods (kept for completeness, assuming they map to other backend endpoints not provided) ---
/**
* Get current tenant info (no direct backend mapping in provided file, but common)
*/
async getCurrentTenant(): Promise<TenantInfo> {
const response = await apiClient.get<ApiResponse<TenantInfo>>('/tenants/current');
const response = await apiClient.get<ApiResponse<TenantInfo>>('/api/v1/tenants/current');
return response.data!;
}
/**
* Update current tenant
* Update current tenant (no direct backend mapping in provided file, but common)
*/
async updateCurrentTenant(updates: TenantUpdate): Promise<TenantInfo> {
const response = await apiClient.put<ApiResponse<TenantInfo>>('/tenants/current', updates);
const response = await apiClient.put<ApiResponse<TenantInfo>>('/api/v1/tenants/current', updates);
return response.data!;
}
/**
* Get tenant settings
* Get tenant settings (no direct backend mapping in provided file)
*/
async getTenantSettings(): Promise<TenantSettings> {
const response = await apiClient.get<ApiResponse<TenantSettings>>('/tenants/settings');
const response = await apiClient.get<ApiResponse<TenantSettings>>('/api/v1/tenants/settings');
return response.data!;
}
/**
* Update tenant settings
* Update tenant settings (no direct backend mapping in provided file)
*/
async updateTenantSettings(settings: Partial<TenantSettings>): Promise<TenantSettings> {
const response = await apiClient.put<ApiResponse<TenantSettings>>(
'/tenants/settings',
'/api/v1/tenants/settings',
settings
);
return response.data!;
}
/**
* Get tenant statistics
* Get tenant statistics (no direct backend mapping in provided file)
*/
async getTenantStats(): Promise<TenantStats> {
const response = await apiClient.get<ApiResponse<TenantStats>>('/tenants/stats');
const response = await apiClient.get<ApiResponse<TenantStats>>('/api/v1/tenants/stats');
return response.data!;
}
/**
* Get tenant users
* Get tenant users (no direct backend mapping in provided file)
*/
async getTenantUsers(params?: {
role?: string;
@@ -142,12 +200,12 @@ export class TenantService {
page: number;
pages: number;
}> {
const response = await apiClient.get<ApiResponse<any>>('/tenants/users', { params });
const response = await apiClient.get<ApiResponse<any>>('/api/v1/tenants/users', { params });
return response.data!;
}
/**
* Invite user to tenant
* Invite user to tenant (no direct backend mapping in provided file)
*/
async inviteUser(invitation: InviteUser): Promise<{
invitation_id: string;
@@ -156,52 +214,52 @@ export class TenantService {
expires_at: string;
invitation_token: string;
}> {
const response = await apiClient.post<ApiResponse<any>>('/tenants/users/invite', invitation);
const response = await apiClient.post<ApiResponse<any>>('/api/v1/tenants/users/invite', invitation);
return response.data!;
}
/**
* Update user role
* Update user role (no direct backend mapping in provided file)
*/
async updateUserRole(userId: string, role: string): Promise<TenantUser> {
const response = await apiClient.patch<ApiResponse<TenantUser>>(
`/tenants/users/${userId}`,
`/api/v1/tenants/users/${userId}`,
{ role }
);
return response.data!;
}
/**
* Deactivate user
* Deactivate user (no direct backend mapping in provided file)
*/
async deactivateUser(userId: string): Promise<TenantUser> {
const response = await apiClient.patch<ApiResponse<TenantUser>>(
`/tenants/users/${userId}`,
`/api/v1/tenants/users/${userId}`,
{ is_active: false }
);
return response.data!;
}
/**
* Reactivate user
* Reactivate user (no direct backend mapping in provided file)
*/
async reactivateUser(userId: string): Promise<TenantUser> {
const response = await apiClient.patch<ApiResponse<TenantUser>>(
`/tenants/users/${userId}`,
`/api/v1/tenants/users/${userId}`,
{ is_active: true }
);
return response.data!;
}
/**
* Remove user from tenant
* Remove user from tenant (no direct backend mapping in provided file)
*/
async removeUser(userId: string): Promise<void> {
await apiClient.delete(`/tenants/users/${userId}`);
await apiClient.delete(`/api/v1/tenants/users/${userId}`);
}
/**
* Get pending invitations
* Get pending invitations (no direct backend mapping in provided file)
*/
async getPendingInvitations(): Promise<{
id: string;
@@ -211,26 +269,26 @@ export class TenantService {
expires_at: string;
invited_by: string;
}[]> {
const response = await apiClient.get<ApiResponse<any>>('/tenants/invitations');
const response = await apiClient.get<ApiResponse<any>>('/api/v1/tenants/invitations');
return response.data!;
}
/**
* Cancel invitation
* Cancel invitation (no direct backend mapping in provided file)
*/
async cancelInvitation(invitationId: string): Promise<void> {
await apiClient.delete(`/tenants/invitations/${invitationId}`);
await apiClient.delete(`/api/v1/tenants/invitations/${invitationId}`);
}
/**
* Resend invitation
* Resend invitation (no direct backend mapping in provided file)
*/
async resendInvitation(invitationId: string): Promise<void> {
await apiClient.post(`/tenants/invitations/${invitationId}/resend`);
await apiClient.post(`/api/v1/tenants/invitations/${invitationId}/resend`);
}
/**
* Get tenant activity log
* Get tenant activity log (no direct backend mapping in provided file)
*/
async getActivityLog(params?: {
userId?: string;
@@ -256,12 +314,12 @@ export class TenantService {
page: number;
pages: number;
}> {
const response = await apiClient.get<ApiResponse<any>>('/tenants/activity', { params });
const response = await apiClient.get<ApiResponse<any>>('/api/v1/tenants/activity', { params });
return response.data!;
}
/**
* Get tenant billing info
* Get tenant billing info (no direct backend mapping in provided file)
*/
async getBillingInfo(): Promise<{
subscription_plan: string;
@@ -285,12 +343,12 @@ export class TenantService {
};
};
}> {
const response = await apiClient.get<ApiResponse<any>>('/tenants/billing');
const response = await apiClient.get<ApiResponse<any>>('/api/v1/tenants/billing');
return response.data!;
}
/**
* Update billing info
* Update billing info (no direct backend mapping in provided file)
*/
async updateBillingInfo(billingData: {
payment_method_token?: string;
@@ -302,11 +360,11 @@ export class TenantService {
country: string;
};
}): Promise<void> {
await apiClient.put('/tenants/billing', billingData);
await apiClient.put('/api/v1/tenants/billing', billingData);
}
/**
* Change subscription plan
* Change subscription plan (no direct backend mapping in provided file)
*/
async changeSubscriptionPlan(
planId: string,
@@ -318,7 +376,7 @@ export class TenantService {
next_billing_date: string;
proration_amount?: number;
}> {
const response = await apiClient.post<ApiResponse<any>>('/tenants/subscription/change', {
const response = await apiClient.post<ApiResponse<any>>('/api/v1/tenants/subscription/change', {
plan_id: planId,
billing_cycle: billingCycle,
});
@@ -326,24 +384,24 @@ export class TenantService {
}
/**
* Cancel subscription
* Cancel subscription (no direct backend mapping in provided file)
*/
async cancelSubscription(cancelAt: 'immediately' | 'end_of_period'): Promise<{
cancelled_at: string;
will_cancel_at: string;
refund_amount?: number;
}> {
const response = await apiClient.post<ApiResponse<any>>('/tenants/subscription/cancel', {
const response = await apiClient.post<ApiResponse<any>>('/api/v1/tenants/subscription/cancel', {
cancel_at: cancelAt,
});
return response.data!;
}
/**
* Export tenant data
* Export tenant data (no direct backend mapping in provided file)
*/
async exportTenantData(dataTypes: string[], format: 'json' | 'csv'): Promise<Blob> {
const response = await apiClient.post('/tenants/export', {
const response = await apiClient.post('/api/v1/tenants/export', {
data_types: dataTypes,
format,
responseType: 'blob',
@@ -352,14 +410,14 @@ export class TenantService {
}
/**
* Delete tenant (GDPR compliance)
* Delete tenant (GDPR compliance) (no direct backend mapping in provided file)
*/
async deleteTenant(confirmationToken: string): Promise<{
deletion_scheduled_at: string;
data_retention_until: string;
recovery_period_days: number;
}> {
const response = await apiClient.delete<ApiResponse<any>>('/tenants/current', {
const response = await apiClient.delete<ApiResponse<any>>('/api/v1/tenants/current', {
data: { confirmation_token: confirmationToken },
});
return response.data!;