w-funnel/docs/TRIAL_CHOICE_PAYMENT_INTEGRATION.md
2025-10-23 02:02:49 +02:00

8.4 KiB
Raw Blame History

Trial Choice & Payment Integration

Проблемы которые решены

1. Связь выбора Trial Choice → Payment

Проблема: Пользователь выбирает вариант триала на экране TrialChoice, но на экране Payment всегда отображался первый вариант.

Решение:

  • Создан TrialVariantSelectionContext для хранения выбранного variantId
  • TrialChoiceTemplate сохраняет выбор пользователя в контекст
  • TrialPaymentTemplate читает выбранный вариант из контекста и использует его вместо первого

2. Общая логика загрузки и кеширование

Проблема:

  • Каждый экран (TrialChoice, Payment) делал отдельный запрос к API
  • TrialChoice показывал неправильные данные до завершения загрузки
  • Payment уже имел loader, но TrialChoice — нет

Решение:

  • Создан PaymentPlacementProvider для кеширования загруженных placement данных
  • usePaymentPlacement hook теперь использует кеш из контекста
  • Повторные запросы к API не выполняются если данные уже загружены
  • TrialChoiceTemplate показывает loader (как Payment) до загрузки данных

Архитектура

Контексты

PaymentPlacementProvider

  • Путь: src/entities/session/payment/PaymentPlacementProvider.tsx
  • Назначение: Кеширует результаты loadFunnelPaymentById чтобы избежать повторных запросов
  • Ключ кеша: ${funnelKey}:${paymentId}
  • Состояние: { placement, isLoading, error }

TrialVariantSelectionProvider

  • Путь: src/entities/session/payment/TrialVariantSelectionContext.tsx
  • Назначение: Хранит выбранный пользователем variantId для передачи между экранами
  • Состояние: { selectedVariantId, setSelectedVariantId }

Обновленные компоненты

TrialChoiceTemplate

  • Изменения:
    • Добавлен loader (Spinner) до загрузки placement
    • Сохраняет выбор в TrialVariantSelectionContext
    • Использует usePaymentPlacement с кешированием
    • Инициализирует локальный selectedId из selectedVariantId контекста

TrialPaymentTemplate

  • Изменения:
    • Читает selectedVariantId из TrialVariantSelectionContext
    • Использует выбранный вариант, если доступен: placement?.variants?.find((v) => v.id === selectedVariantId)
    • Fallback на первый вариант если выбор отсутствует
    • Использует usePaymentPlacement с кешированием

SpecialOfferTemplate

  • Изменения: Нет (специально)
  • Поведение: Продолжает использовать первый вариант placement?.variants?.[0]
  • Причина: Использует другой paymentId ("main_secret_discount") и не должен зависеть от выбора Trial

usePaymentPlacement Hook

  • Изменения:
    • Теперь использует PaymentPlacementContext для получения/загрузки данных
    • Упрощена логика: нет локального state, все в контексте
    • Автоматически триггерит загрузку если данных нет

Layout Integration

  • Файл: src/app/[funnelId]/layout.tsx
  • Изменения: Обернут в два новых провайдера:
    <PaymentPlacementProvider>
      <TrialVariantSelectionProvider>
        {children}
      </TrialVariantSelectionProvider>
    </PaymentPlacementProvider>
    

Потоки данных

Поток 1: Воронка С экраном Trial Choice

1. User открывает Trial Choice
   → PaymentPlacementProvider загружает "main" placement (если еще нет в кеше)
   → TrialChoiceTemplate показывает loader
   → После загрузки отображаются варианты

2. User выбирает вариант (например, id="plan-123")
   → setSelectedVariantId("plan-123") в TrialVariantSelectionContext

3. User переходит на Payment
   → PaymentPlacementProvider возвращает "main" placement из кеша (без запроса)
   → TrialPaymentTemplate читает selectedVariantId="plan-123"
   → Использует вариант с id="plan-123" вместо первого

Поток 2: Воронка БЕЗ экрана Trial Choice

1. User сразу открывает Payment
   → PaymentPlacementProvider загружает "main" placement
   → TrialPaymentTemplate показывает loader
   → selectedVariantId === null
   → Использует первый вариант (дефолт)

Поток 3: Special Offer

1. User открывает Special Offer
   → PaymentPlacementProvider загружает "main_secret_discount" placement
   → SpecialOfferTemplate показывает loader
   → Всегда использует первый вариант (не зависит от Trial Choice)

Тестирование

Сценарий 1: Trial Choice → Payment

  1. Открыть воронку с Trial Choice
  2. Дождаться загрузки вариантов
  3. Выбрать второй вариант (не первый)
  4. Нажать Continue
  5. Ожидается: На Payment отображается выбранный (второй) вариант

Сценарий 2: Прямой переход на Payment

  1. Открыть воронку без Trial Choice или перейти прямо на Payment
  2. Ожидается: На Payment отображается первый вариант (дефолт)

Сценарий 3: Кеширование

  1. Открыть Trial Choice → загрузка placement
  2. Перейти на Payment
  3. Ожидается: Payment загружается мгновенно (из кеша), без повторного API запроса

Сценарий 4: Special Offer

  1. Открыть Special Offer
  2. Ожидается: Всегда показывается первый вариант, независимо от выбора в Trial Choice

API изменения (Backend)

session.controller.ts

  • Изменения: Добавлены title и accent поля в варианты
  • Поведение: Возвращает все планы (не ограничивает до 4)
  • Дефолты: title использует ["Basic", "Standard", "Popular", "Premium"] с fallback "Premium"

Файлы созданы/изменены

Новые файлы

  • src/entities/session/payment/PaymentPlacementProvider.tsx
  • src/entities/session/payment/TrialVariantSelectionContext.tsx
  • src/entities/session/payment/index.ts

Измененные файлы

  • src/hooks/payment/usePaymentPlacement.ts - использует контекст вместо локального state
  • src/components/funnel/templates/TrialChoiceTemplate/TrialChoiceTemplate.tsx - loader + сохранение выбора
  • src/components/funnel/templates/TrialPaymentTemplate/TrialPaymentTemplate.tsx - использует выбранный вариант
  • src/app/[funnelId]/layout.tsx - обернут в провайдеры

Будущие улучшения

  1. Персистентность: Сохранять выбор в localStorage/sessionStorage для сохранения при перезагрузке
  2. Аналитика: Трекинг выбора вариантов для A/B тестирования
  3. Валидация: Проверять что выбранный variant все еще существует в placement
  4. Типизация: Усилить типы для garantie что только валидные paymentId используются