293 lines
11 KiB
Markdown
293 lines
11 KiB
Markdown
# 🎂 Система работы с возрастом WitLab Funnel
|
||
|
||
## Описание
|
||
|
||
Универсальная система автоматического расчета возраста и определения поколений из даты рождения пользователя. Интегрируется с системой вариативности для создания возрастных условий навигации.
|
||
|
||
## Возможности
|
||
|
||
### 🎯 **Автоматический расчет из даты:**
|
||
- **Точный возраст** (например: 25, 30, 45 лет)
|
||
- **Возрастные группы** (18-21, 22-25, 26-30, 31-35, 36-40, 41-45, 46-50, 51-60, 60+)
|
||
- **Поколения** (Generation Z, Millennials, Generation X, Boomers, Silent Generation)
|
||
- **Комбинации** со знаками зодиака
|
||
|
||
### 🎨 **Красивый UI для админки:**
|
||
- Селектор возрастных групп с описаниями
|
||
- Селектор поколений с иконками
|
||
- Возможность добавлять кастомные диапазоны
|
||
- Живое превью выбранных условий
|
||
|
||
## Технические детали
|
||
|
||
### 📊 **Возрастные группы:**
|
||
```typescript
|
||
export const AGE_GROUPS = [
|
||
{ id: "18-21", name: "18-21 год", min: 18, max: 21, description: "Студенческий возраст" },
|
||
{ id: "22-25", name: "22-25 лет", min: 22, max: 25, description: "Молодые профессионалы" },
|
||
{ id: "26-30", name: "26-30 лет", min: 26, max: 30, description: "Карьерный рост" },
|
||
{ id: "31-35", name: "31-35 лет", min: 31, max: 35, description: "Становление личности" },
|
||
{ id: "36-40", name: "36-40 лет", min: 36, max: 40, description: "Зрелость и стабильность" },
|
||
{ id: "41-45", name: "41-45 лет", min: 41, max: 45, description: "Средний возраст" },
|
||
{ id: "46-50", name: "46-50 лет", min: 46, max: 50, description: "Жизненный опыт" },
|
||
{ id: "51-60", name: "51-60 лет", min: 51, max: 60, description: "Зрелые отношения" },
|
||
{ id: "60+", name: "60+ лет", min: 60, max: 120, description: "Золотой возраст" },
|
||
] as const;
|
||
```
|
||
|
||
### 🚀 **Поколения:**
|
||
```typescript
|
||
export const GENERATION_GROUPS = [
|
||
{ id: "gen-z", name: "Поколение Z", minYear: 1997, maxYear: 2012, description: "Цифровые аборигены" },
|
||
{ id: "millennials", name: "Миллениалы", minYear: 1981, maxYear: 1996, description: "Поколение интернета" },
|
||
{ id: "gen-x", name: "Поколение X", minYear: 1965, maxYear: 1980, description: "Поколение перемен" },
|
||
{ id: "boomers", name: "Бумеры", minYear: 1946, maxYear: 1964, description: "Послевоенное поколение" },
|
||
{ id: "silent", name: "Молчаливое поколение", minYear: 1928, maxYear: 1945, description: "Довоенное поколение" },
|
||
] as const;
|
||
```
|
||
|
||
### ⚡ **Основные функции:**
|
||
|
||
#### 1. **Расчет возраста:**
|
||
```typescript
|
||
// Из даты рождения
|
||
calculateAge(new Date(1987, 3, 8)); // → 36
|
||
|
||
// Из массива [month, day, year]
|
||
calculateAgeFromArray([4, 8, 1987]); // → 36
|
||
```
|
||
|
||
#### 2. **Определение группы:**
|
||
```typescript
|
||
getAgeGroup(25); // → { id: "22-25", name: "22-25 лет", ... }
|
||
getGeneration(1987); // → { id: "millennials", name: "Миллениалы", ... }
|
||
```
|
||
|
||
#### 3. **Создание значений для навигации:**
|
||
```typescript
|
||
createAgeValue(25); // → "22-25"
|
||
createGenerationValue(1987); // → "millennials"
|
||
```
|
||
|
||
## Использование в вариативности
|
||
|
||
### 📅 **Date экраны автоматически:**
|
||
Когда пользователь вводит дату рождения в date экране, система автоматически добавляет к ответам:
|
||
|
||
**Пример:** Дата рождения 8 апреля 1987 года `[4, 8, 1987]`
|
||
|
||
**Автоматически добавляется в ответы:**
|
||
```typescript
|
||
[
|
||
"4", "8", "1987", // Исходная дата
|
||
"36-40", // Возрастная группа
|
||
"age-36", // Точный возраст
|
||
"millennials", // Поколение
|
||
"aries" // Знак зодиака (из существующей системы)
|
||
]
|
||
```
|
||
|
||
### 🎯 **Условия навигации:**
|
||
|
||
#### **По возрастным группам:**
|
||
```json
|
||
{
|
||
"conditions": [{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "includesAny",
|
||
"values": ["22-25", "26-30"]
|
||
}]
|
||
}
|
||
```
|
||
|
||
#### **По поколениям:**
|
||
```json
|
||
{
|
||
"conditions": [{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "equals",
|
||
"values": ["millennials"]
|
||
}]
|
||
}
|
||
```
|
||
|
||
#### **Комбинированные условия:**
|
||
```json
|
||
{
|
||
"conditions": [
|
||
{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "includesAny",
|
||
"values": ["gen-z", "millennials"]
|
||
},
|
||
{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "includesAny",
|
||
"values": ["aries", "leo", "sagittarius"]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
## UI компоненты
|
||
|
||
### 🎨 **AgeSelector для админки:**
|
||
```tsx
|
||
<AgeSelector
|
||
selectedValues={["22-25", "millennials"]}
|
||
onToggleValue={(value) => console.log('Selected:', value)}
|
||
onAddCustomValue={(value) => console.log('Added:', value)}
|
||
/>
|
||
```
|
||
|
||
**Возможности:**
|
||
- 🎂 Сетка возрастных групп с описаниями
|
||
- 🚀 Список поколений с иконками
|
||
- 🎯 Поле для кастомных диапазонов (25-35, 40+)
|
||
- 📋 Превью выбранных значений с цветовым кодированием
|
||
|
||
### 📊 **Интеграция в ScreenVariantsConfig:**
|
||
Для date экранов автоматически показываются:
|
||
1. **AgeSelector** - для возрастных условий
|
||
2. **ZodiacSelector** - для знаков зодиака
|
||
3. **Умная фильтрация** - каждый селектор показывает только свои значения
|
||
|
||
## Примеры использования
|
||
|
||
### 💖 **Романтические предпочтения по возрасту:**
|
||
```json
|
||
{
|
||
"id": "young-romance",
|
||
"variants": [{
|
||
"conditions": [{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "includesAny",
|
||
"values": ["18-21", "22-25"]
|
||
}],
|
||
"overrides": {
|
||
"title": { "text": "Найти **молодую любовь**!" },
|
||
"description": { "text": "Специально для **молодых сердец** - найдем твою половинку среди сверстников!" }
|
||
}
|
||
}]
|
||
}
|
||
```
|
||
|
||
### 🚀 **Карьерные амбиции по поколениям:**
|
||
```json
|
||
{
|
||
"id": "career-focus",
|
||
"variants": [{
|
||
"conditions": [{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "equals",
|
||
"values": ["millennials"]
|
||
}],
|
||
"overrides": {
|
||
"title": { "text": "Карьера + **отношения**" },
|
||
"description": { "text": "Для **миллениалов** - найдем партнера, который поддержит твои амбиции!" }
|
||
}
|
||
}]
|
||
}
|
||
```
|
||
|
||
### 🎯 **Зрелые отношения:**
|
||
```json
|
||
{
|
||
"id": "mature-love",
|
||
"variants": [{
|
||
"conditions": [{
|
||
"screenId": "birth-date",
|
||
"conditionType": "values",
|
||
"operator": "includesAny",
|
||
"values": ["46-50", "51-60", "60+"]
|
||
}],
|
||
"overrides": {
|
||
"title": { "text": "**Зрелая любовь**" },
|
||
"description": { "text": "Для тех, кто знает цену **настоящим чувствам** и **жизненному опыту**" }
|
||
}
|
||
}]
|
||
}
|
||
```
|
||
|
||
## Архитектура
|
||
|
||
### 📁 **Файловая структура:**
|
||
```
|
||
src/lib/age-utils.ts # Основные утилиты возраста
|
||
src/components/admin/builder/
|
||
├── AgeSelector.tsx # UI селектор для админки
|
||
├── AgeDemo.tsx # Демо компонент
|
||
└── ScreenVariantsConfig.tsx # Интеграция в вариативность
|
||
src/lib/funnel/navigation.ts # Интеграция в навигацию
|
||
```
|
||
|
||
### 🔧 **Интеграция в систему:**
|
||
|
||
#### **1. Автоматический расчет (navigation.ts):**
|
||
```typescript
|
||
// При получении ответов из date экрана автоматически добавляем:
|
||
const age = calculateAgeFromArray(dateArray);
|
||
const ageGroup = createAgeValue(age);
|
||
const generation = createGenerationValue(year);
|
||
const zodiac = getZodiacSign(month, day);
|
||
|
||
enhancedAnswers.push(ageGroup, `age-${age}`, generation, zodiac);
|
||
```
|
||
|
||
#### **2. UI селекция (AgeSelector.tsx):**
|
||
```typescript
|
||
// Красивые карточки для выбора условий
|
||
{AGE_GROUPS.map((group) => (
|
||
<button onClick={() => onToggleValue(group.id)}>
|
||
🎂 {group.name} - {group.description}
|
||
</button>
|
||
))}
|
||
```
|
||
|
||
#### **3. Валидация диапазонов:**
|
||
```typescript
|
||
// Проверка попадания возраста в диапазон
|
||
isAgeInRange(25, "22-25"); // → true
|
||
isAgeInRange(30, "18-21"); // → false
|
||
```
|
||
|
||
## Преимущества
|
||
|
||
### ✅ **Автоматизация:**
|
||
- Пользователь вводит только дату рождения
|
||
- Система автоматически рассчитывает все значения
|
||
- Не нужно спрашивать возраст отдельно
|
||
|
||
### ✅ **Гибкость:**
|
||
- Поддержка любых возрастных диапазонов
|
||
- Кастомные значения (25-35, 40+)
|
||
- Комбинации с другими условиями
|
||
|
||
### ✅ **UX дружелюбность:**
|
||
- Понятные названия групп
|
||
- Описания для каждой группы
|
||
- Иконки для поколений
|
||
- Превью выбранных условий
|
||
|
||
### ✅ **Маркетинговая сегментация:**
|
||
- Готовые возрастные группы для таргетинга
|
||
- Поколенческая сегментация
|
||
- Психологические портреты по возрасту
|
||
|
||
## Совместимость
|
||
|
||
- ✅ **React 18+**
|
||
- ✅ **TypeScript 5+**
|
||
- ✅ **Next.js 14+**
|
||
- ✅ **Существующая система зодиака**
|
||
- ✅ **Система вариативности**
|
||
- ✅ **Обратная совместимость** с существующими воронками
|
||
|
||
**💡 Теперь можно создавать условия навигации на основе возраста пользователя, автоматически рассчитанного из даты рождения!**
|