Files
course-craft-service/packages/shared/src/constants/index.ts
2026-02-06 02:17:59 +03:00

205 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Default AI model for all tiers (can override in user settings on PRO)
const DEFAULT_AI_MODEL = 'openai/gpt-4o-mini';
// Subscription tier limits
export const SUBSCRIPTION_LIMITS = {
FREE: {
coursesPerMonth: 2,
defaultAiModel: DEFAULT_AI_MODEL,
},
PREMIUM: {
coursesPerMonth: 5,
defaultAiModel: DEFAULT_AI_MODEL,
},
PRO: {
coursesPerMonth: 15,
defaultAiModel: DEFAULT_AI_MODEL,
},
} as const;
// Prices in RUB for Russian locale (approximate)
const PRICE_RUB = {
FREE: 0,
PREMIUM: 999,
PRO: 2999,
} as const;
// Subscription plans for display
export const SUBSCRIPTION_PLANS = [
{
tier: 'FREE' as const,
name: 'Free',
nameRu: 'Бесплатный',
description: 'Perfect for trying out CourseCraft',
descriptionRu: 'Идеально для знакомства с CourseCraft',
price: 0,
priceRu: PRICE_RUB.FREE,
currency: 'USD',
features: [
'2 courses per month',
'Basic AI model',
'Standard support',
],
featuresRu: [
'2 курса в месяц',
'Базовая нейросеть',
'Стандартная поддержка',
],
stripePriceId: null,
},
{
tier: 'PREMIUM' as const,
name: 'Premium',
nameRu: 'Премиум',
description: 'For creators who need more',
descriptionRu: 'Для тех, кому нужно больше',
price: 9.99,
priceRu: PRICE_RUB.PREMIUM,
currency: 'USD',
features: [
'5 courses per month',
'Enhanced AI model',
'Priority support',
'Advanced editing tools',
],
featuresRu: [
'5 курсов в месяц',
'Улучшенная нейросеть',
'Приоритетная поддержка',
'Расширенные инструменты редактирования',
],
stripePriceId: process.env.STRIPE_PRICE_PREMIUM || null,
},
{
tier: 'PRO' as const,
name: 'Pro',
nameRu: 'Профессиональный',
description: 'For power users and teams',
descriptionRu: 'Для профессионалов и команд',
price: 29.99,
priceRu: PRICE_RUB.PRO,
currency: 'USD',
features: [
'15 courses per month',
'Best AI model available',
'Priority support 24/7',
'Advanced editing tools',
'Custom AI model selection',
'Export to PDF (coming soon)',
],
featuresRu: [
'15 курсов в месяц',
'Лучшая доступная нейросеть',
'Приоритетная поддержка 24/7',
'Расширенные инструменты редактирования',
'Выбор модели нейросети',
'Экспорт в PDF (скоро)',
],
stripePriceId: process.env.STRIPE_PRICE_PRO || null,
},
] as const;
export type SubscriptionPlan = (typeof SUBSCRIPTION_PLANS)[number];
/** Format plan price for display. Uses RUB when language is Russian. */
export function formatPlanPrice(
plan: { price: number; priceRu: number; currency: string },
language: string
): { amount: number; currency: string; formatted: string } {
const isRu = language === 'ru' || language.startsWith('ru');
if (isRu) {
const amount = plan.priceRu;
return {
amount,
currency: 'RUB',
formatted: amount === 0 ? 'Бесплатно' : `${amount.toLocaleString('ru-RU')}`,
};
}
return {
amount: plan.price,
currency: plan.currency,
formatted: plan.price === 0 ? 'Free' : `$${plan.price}`,
};
}
// Generation progress steps
export const GENERATION_STEPS = {
PENDING: { progress: 0, label: 'Waiting to start', labelRu: 'Ожидание запуска' },
ANALYZING: { progress: 10, label: 'Analyzing your request', labelRu: 'Анализ запроса' },
ASKING_QUESTIONS: { progress: 15, label: 'Preparing questions', labelRu: 'Подготовка вопросов' },
WAITING_FOR_ANSWERS: { progress: 20, label: 'Waiting for your answers', labelRu: 'Ожидание ваших ответов' },
RESEARCHING: { progress: 30, label: 'Researching the topic', labelRu: 'Исследование темы' },
GENERATING_OUTLINE: { progress: 50, label: 'Creating course structure', labelRu: 'Создание структуры курса' },
GENERATING_CONTENT: { progress: 70, label: 'Writing course content', labelRu: 'Написание содержания' },
COMPLETED: { progress: 100, label: 'Course completed!', labelRu: 'Курс готов!' },
FAILED: { progress: 0, label: 'Generation failed', labelRu: 'Ошибка генерации' },
CANCELLED: { progress: 0, label: 'Generation cancelled', labelRu: 'Генерация отменена' },
} as const;
// API Routes
export const API_ROUTES = {
AUTH: {
ME: '/auth/me',
CALLBACK: '/auth/callback',
LOGOUT: '/auth/logout',
},
USERS: {
PROFILE: '/users/profile',
SETTINGS: '/users/settings',
},
COURSES: {
LIST: '/courses',
CREATE: '/courses',
GET: (id: string) => `/courses/${id}`,
UPDATE: (id: string) => `/courses/${id}`,
DELETE: (id: string) => `/courses/${id}`,
},
CHAPTERS: {
LIST: (courseId: string) => `/courses/${courseId}/chapters`,
CREATE: (courseId: string) => `/courses/${courseId}/chapters`,
UPDATE: (courseId: string, chapterId: string) => `/courses/${courseId}/chapters/${chapterId}`,
DELETE: (courseId: string, chapterId: string) => `/courses/${courseId}/chapters/${chapterId}`,
REORDER: (courseId: string) => `/courses/${courseId}/chapters/reorder`,
},
LESSONS: {
GET: (courseId: string, lessonId: string) => `/courses/${courseId}/lessons/${lessonId}`,
UPDATE: (courseId: string, lessonId: string) => `/courses/${courseId}/lessons/${lessonId}`,
},
GENERATION: {
START: '/generation/start',
STATUS: (id: string) => `/generation/${id}/status`,
ANSWER: (id: string) => `/generation/${id}/answer`,
CANCEL: (id: string) => `/generation/${id}/cancel`,
},
SUBSCRIPTIONS: {
PLANS: '/subscriptions/plans',
CURRENT: '/subscriptions/current',
CHECKOUT: '/subscriptions/checkout',
PORTAL: '/subscriptions/portal',
},
SEARCH: {
COURSES: '/search/courses',
},
} as const;
// Validation
export const VALIDATION = {
COURSE: {
TITLE_MIN: 3,
TITLE_MAX: 200,
DESCRIPTION_MAX: 5000,
},
CHAPTER: {
TITLE_MIN: 2,
TITLE_MAX: 200,
},
LESSON: {
TITLE_MIN: 2,
TITLE_MAX: 200,
},
PROMPT: {
MIN: 10,
MAX: 2000,
},
} as const;