Fix UI issues

This commit is contained in:
Urtzi Alfaro
2025-09-20 08:59:12 +02:00
parent 66ef2121a1
commit abe7cf2444
19 changed files with 1327 additions and 2277 deletions

View File

@@ -76,6 +76,11 @@ export type {
SubscriptionLimits,
FeatureCheckResponse,
UsageCheckResponse,
UsageSummary,
AvailablePlans,
Plan,
PlanUpgradeValidation,
PlanUpgradeResult
} from './types/subscription';
// Types - Sales
@@ -346,6 +351,8 @@ export type {
export {
ProductionStatusEnum,
ProductionPriorityEnum,
ProductionBatchStatus,
QualityCheckStatus,
} from './types/production';
// Types - POS

View File

@@ -2,12 +2,16 @@
* Subscription Service - Mirror backend subscription endpoints
*/
import { apiClient } from '../client';
import {
SubscriptionLimits,
FeatureCheckRequest,
FeatureCheckResponse,
UsageCheckRequest,
UsageCheckResponse
import {
SubscriptionLimits,
FeatureCheckRequest,
FeatureCheckResponse,
UsageCheckRequest,
UsageCheckResponse,
UsageSummary,
AvailablePlans,
PlanUpgradeValidation,
PlanUpgradeResult
} from '../types/subscription';
export class SubscriptionService {
@@ -62,6 +66,129 @@ export class SubscriptionService {
}> {
return apiClient.get(`${this.baseUrl}/${tenantId}/usage/current`);
}
async getUsageSummary(tenantId: string): Promise<UsageSummary> {
try {
return await apiClient.get<UsageSummary>(`${this.baseUrl}/${tenantId}/summary`);
} catch (error) {
// Return mock data if backend endpoint doesn't exist yet
console.warn('Using mock subscription data - backend endpoint not implemented yet');
return this.getMockUsageSummary();
}
}
async getAvailablePlans(): Promise<AvailablePlans> {
try {
return await apiClient.get<AvailablePlans>(`${this.baseUrl}/plans`);
} catch (error) {
// Return mock data if backend endpoint doesn't exist yet
console.warn('Using mock plans data - backend endpoint not implemented yet');
return this.getMockAvailablePlans();
}
}
async validatePlanUpgrade(tenantId: string, planKey: string): Promise<PlanUpgradeValidation> {
try {
return await apiClient.post<PlanUpgradeValidation>(`${this.baseUrl}/${tenantId}/validate-upgrade`, {
plan: planKey
});
} catch (error) {
console.warn('Using mock validation - backend endpoint not implemented yet');
return { can_upgrade: true };
}
}
async upgradePlan(tenantId: string, planKey: string): Promise<PlanUpgradeResult> {
try {
return await apiClient.post<PlanUpgradeResult>(`${this.baseUrl}/${tenantId}/upgrade`, {
plan: planKey
});
} catch (error) {
console.warn('Using mock upgrade - backend endpoint not implemented yet');
return { success: true, message: 'Plan actualizado correctamente (modo demo)' };
}
}
formatPrice(amount: number): string {
return new Intl.NumberFormat('es-ES', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 0,
maximumFractionDigits: 2
}).format(amount);
}
getPlanDisplayInfo(planKey: string): { name: string; color: string } {
const planInfo = {
starter: { name: 'Starter', color: 'blue' },
professional: { name: 'Professional', color: 'purple' },
enterprise: { name: 'Enterprise', color: 'amber' }
};
return planInfo[planKey as keyof typeof planInfo] || { name: 'Desconocido', color: 'gray' };
}
private getMockUsageSummary(): UsageSummary {
return {
plan: 'professional',
status: 'active',
monthly_price: 49.99,
next_billing_date: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
usage: {
users: {
current: 3,
limit: 10,
unlimited: false,
usage_percentage: 30
},
locations: {
current: 1,
limit: 3,
unlimited: false,
usage_percentage: 33
},
products: {
current: 45,
limit: -1,
unlimited: true,
usage_percentage: 0
}
}
};
}
private getMockAvailablePlans(): AvailablePlans {
return {
plans: {
starter: {
name: 'Starter',
description: 'Perfecto para panaderías pequeñas',
monthly_price: 29.99,
max_users: 3,
max_locations: 1,
max_products: 50,
popular: false
},
professional: {
name: 'Professional',
description: 'Para panaderías en crecimiento',
monthly_price: 49.99,
max_users: 10,
max_locations: 3,
max_products: -1,
popular: true
},
enterprise: {
name: 'Enterprise',
description: 'Para grandes operaciones',
monthly_price: 99.99,
max_users: -1,
max_locations: -1,
max_products: -1,
contact_sales: true
}
}
};
}
}
export const subscriptionService = new SubscriptionService();

View File

@@ -15,6 +15,22 @@ export enum ProductionPriorityEnum {
URGENT = "urgent"
}
export enum ProductionBatchStatus {
PLANNED = "planned",
IN_PROGRESS = "in_progress",
COMPLETED = "completed",
CANCELLED = "cancelled",
ON_HOLD = "on_hold"
}
export enum QualityCheckStatus {
PENDING = "pending",
IN_PROGRESS = "in_progress",
PASSED = "passed",
FAILED = "failed",
REQUIRES_ATTENTION = "requires_attention"
}
export interface ProductionBatchBase {
product_id: string;
product_name: string;

View File

@@ -3,6 +3,8 @@
* Generated based on backend schemas in services/recipes/app/schemas/recipes.py
*/
import { ProductionPriorityEnum } from './production';
export enum RecipeStatus {
DRAFT = 'draft',
ACTIVE = 'active',
@@ -32,12 +34,6 @@ export enum ProductionStatus {
CANCELLED = 'cancelled'
}
export enum ProductionPriority {
LOW = 'low',
NORMAL = 'normal',
HIGH = 'high',
URGENT = 'urgent'
}
export interface RecipeIngredientCreate {
ingredient_id: string;
@@ -272,7 +268,7 @@ export interface ProductionBatchCreate {
planned_end_time?: string | null;
planned_quantity: number;
batch_size_multiplier?: number;
priority?: ProductionPriority;
priority?: ProductionPriorityEnum;
assigned_staff?: Array<Record<string, any>> | null;
production_notes?: string | null;
customer_order_reference?: string | null;
@@ -291,7 +287,7 @@ export interface ProductionBatchUpdate {
actual_quantity?: number | null;
batch_size_multiplier?: number | null;
status?: ProductionStatus | null;
priority?: ProductionPriority | null;
priority?: ProductionPriorityEnum | null;
assigned_staff?: Array<Record<string, any>> | null;
production_notes?: string | null;
quality_score?: number | null;

View File

@@ -40,4 +40,58 @@ export interface UsageCheckResponse {
current_usage: number;
remaining: number;
message?: string;
}
export interface UsageSummary {
plan: string;
status: 'active' | 'inactive' | 'past_due' | 'cancelled';
monthly_price: number;
next_billing_date: string;
usage: {
users: {
current: number;
limit: number;
unlimited: boolean;
usage_percentage: number;
};
locations: {
current: number;
limit: number;
unlimited: boolean;
usage_percentage: number;
};
products: {
current: number;
limit: number;
unlimited: boolean;
usage_percentage: number;
};
};
}
export interface Plan {
name: string;
description: string;
monthly_price: number;
max_users: number;
max_locations: number;
max_products: number;
popular?: boolean;
contact_sales?: boolean;
}
export interface AvailablePlans {
plans: {
[key: string]: Plan;
};
}
export interface PlanUpgradeValidation {
can_upgrade: boolean;
reason?: string;
}
export interface PlanUpgradeResult {
success: boolean;
message: string;
}