Changes: - Add wellnuoSheme/ folder with project documentation - Rename patients -> beneficiaries (proper WellNuo terminology) - Add BeneficiaryContext for state management - Update API service with WellNuo endpoints - Add dashboard screen for beneficiary overview - Update navigation and layout Scheme files include: - API documentation with credentials - Project description - System analysis - UX flow - Legal documents (privacy, terms, support) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
957 lines
28 KiB
JSON
957 lines
28 KiB
JSON
{
|
||
"_meta": {
|
||
"name": "SysAnal",
|
||
"updatedAt": "2025-12-12T21:15:34.928Z"
|
||
},
|
||
"elements": [
|
||
{
|
||
"id": "info-project",
|
||
"type": "card",
|
||
"title": "WellNuo Mobile App",
|
||
"subtitle": "Мониторинг пожилых людей",
|
||
"description": "**Стек:**\n- React Native 0.81.5 + Expo SDK 54\n- Expo Router 6.x\n- Backend: существующий API (Python)\n- AI: OpenAI GPT-3.5-turbo (только текст)\n\n**Репозиторий:**\nGitea: `robert/MobileApp_react_native`\nBranch: `development`\n\n**Мы делаем:** только frontend",
|
||
"tags": [
|
||
"system"
|
||
],
|
||
"borderColor": "gray",
|
||
"x": 140,
|
||
"y": 543.75
|
||
},
|
||
{
|
||
"id": "info-legend",
|
||
"type": "card",
|
||
"title": "ЛЕГЕНДА ТЕГОВ",
|
||
"subtitle": "Кто выполняет действие",
|
||
"description": "**frontend** - React Native приложение (наша работа)\n**backend** - Существующий API (уже готов)\n**external** - Внешние сервисы (OpenAI, Stripe)\n**env** - Переменные окружения/доступы\n\n**completed: true** = доступ получен/проверен\n**completed: false** = нужно получить",
|
||
"tags": [
|
||
"system"
|
||
],
|
||
"borderColor": "gray",
|
||
"x": 520,
|
||
"y": 716.25
|
||
},
|
||
{
|
||
"id": "info-data-flow",
|
||
"type": "card",
|
||
"title": "DATA FLOW PATTERN",
|
||
"subtitle": "Как данные ходят",
|
||
"description": "**Каждый экран с данными:**\n\n1. **Mount** → setLoading(true)\n2. **API Request** → frontend → backend\n3. **Condition** → успех/ошибка?\n4. **Success** → setData() → render\n5. **Error** → setError() → Retry\n\n**Стрелки:** → запрос | ← ответ",
|
||
"tags": [
|
||
"system"
|
||
],
|
||
"borderColor": "gray",
|
||
"x": 140,
|
||
"y": 780
|
||
},
|
||
{
|
||
"id": "env-section",
|
||
"type": "card",
|
||
"title": "ENV / CREDENTIALS",
|
||
"subtitle": "Все доступы проекта",
|
||
"description": "Секция с переменными окружения.\nПроверено: 12 декабря 2025\n\n✅ = есть | ❌ = нужно",
|
||
"tags": [
|
||
"env"
|
||
],
|
||
"borderColor": "cyan",
|
||
"x": 520,
|
||
"y": 307.5
|
||
},
|
||
{
|
||
"id": "env-gitea",
|
||
"type": "card",
|
||
"title": "GITEA_URL ✅",
|
||
"subtitle": "Репозиторий кода",
|
||
"description": "https://gitea.serv00.org\n\n**Repo:** robert/MobileApp_react_native\n**Branch:** development",
|
||
"tags": [
|
||
"env"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": true,
|
||
"x": 900,
|
||
"y": 77.5
|
||
},
|
||
{
|
||
"id": "env-api-url",
|
||
"type": "card",
|
||
"title": "API_URL ✅",
|
||
"subtitle": "Backend API endpoint",
|
||
"description": "**URL:** `https://eluxnetworks.net/function/well-api/api`\n\n**Format:** x-www-form-urlencoded\n**Параметр:** function=название_функции\n\n**Dashboard:** https://react.eluxnetworks.net/dashboard\n\n**Проверено:** работает ✅",
|
||
"tags": [
|
||
"env",
|
||
"backend"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": true,
|
||
"x": 900,
|
||
"y": 192.5
|
||
},
|
||
{
|
||
"id": "env-api-credentials",
|
||
"type": "card",
|
||
"title": "API_CREDENTIALS ✅",
|
||
"subtitle": "Логин/пароль для API",
|
||
"description": "**Username:** anandk\n**Password:** anandk_8\n\n**Тестовый ответ:**\n- user_id: 43\n- max_role: 2\n- privileges: 21,38,29,41,42\n\n**Проверено:** 12.12.2025 ✅",
|
||
"tags": [
|
||
"env",
|
||
"backend"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": true,
|
||
"x": 900,
|
||
"y": 307.5
|
||
},
|
||
{
|
||
"id": "env-expo-project",
|
||
"type": "card",
|
||
"title": "EXPO_PROJECT_ID ❌",
|
||
"subtitle": "EAS Project ID",
|
||
"description": "Для EAS Build и Push Notifications\n\nhttps://expo.dev\n\n(нужно создать проект)",
|
||
"tags": [
|
||
"env"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": false,
|
||
"x": 900,
|
||
"y": 422.5
|
||
},
|
||
{
|
||
"id": "env-stripe-pub",
|
||
"type": "card",
|
||
"title": "STRIPE_PUBLISHABLE_KEY ❌",
|
||
"subtitle": "Stripe Public Key",
|
||
"description": "`pk_xxx`\n\nДля оплаты в приложении\n\nhttps://dashboard.stripe.com/apikeys",
|
||
"tags": [
|
||
"env",
|
||
"external"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": false,
|
||
"x": 1280,
|
||
"y": 77.5
|
||
},
|
||
{
|
||
"id": "env-stripe-secret",
|
||
"type": "card",
|
||
"title": "STRIPE_SECRET_KEY ❌",
|
||
"subtitle": "Stripe Secret (backend)",
|
||
"description": "`sk_xxx`\n\nТолько на backend!",
|
||
"tags": [
|
||
"env",
|
||
"backend"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": false,
|
||
"x": 1280,
|
||
"y": 192.5
|
||
},
|
||
{
|
||
"id": "env-sendgrid",
|
||
"type": "card",
|
||
"title": "SENDGRID_API_KEY ❌",
|
||
"subtitle": "Email сервис",
|
||
"description": "`SG.xxx`\n\nДля отправки:\n- Welcome email\n- Password reset",
|
||
"tags": [
|
||
"env",
|
||
"external"
|
||
],
|
||
"borderColor": "cyan",
|
||
"completed": false,
|
||
"x": 1280,
|
||
"y": 307.5
|
||
},
|
||
{
|
||
"id": "api-structure",
|
||
"type": "card",
|
||
"title": "API STRUCTURE",
|
||
"subtitle": "Структура существующего API",
|
||
"description": "**Base URL:**\n`https://eluxnetworks.net/function/well-api/api`\n\n**Format:** POST x-www-form-urlencoded\n\n**Функции (проверенные):**\n- `function=credentials` → логин\n- `function=voice_ask` → AI чат\n\n**Параметры credentials:**\n- user_name, ps, clientId, nonce\n\n**Параметры voice_ask:**\n- clientId, user_name, token, question, deployment_id",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 900,
|
||
"y": 537.5
|
||
},
|
||
{
|
||
"id": "flow-start",
|
||
"type": "card",
|
||
"title": "1. APP START",
|
||
"subtitle": "Запуск приложения",
|
||
"description": "**Файл:** `app/_layout.tsx`\n\nПользователь открывает приложение.\nПоказывается Splash Screen.",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 900,
|
||
"y": 652.5
|
||
},
|
||
{
|
||
"id": "flow-check-token",
|
||
"type": "condition",
|
||
"title": "2. Токен в SecureStore?",
|
||
"subtitle": "Проверка авторизации",
|
||
"description": "```javascript\nconst token = await SecureStore.getItemAsync('accessToken')\n```\n\nЕсли токен есть → проверяем валидность\nЕсли нет → Login Screen",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "yellow",
|
||
"x": 1280,
|
||
"y": 652.5
|
||
},
|
||
{
|
||
"id": "flow-login-screen",
|
||
"type": "card",
|
||
"title": "3. LOGIN SCREEN",
|
||
"subtitle": "Экран входа",
|
||
"description": "**Файл:** `app/(auth)/login.tsx`\n\n**State:**\n- username, password\n- loading, error\n\n**Поля:**\n- Username (не email!)\n- Password\n\n**Кнопки:**\n- [Sign In]\n- [Forgot Password?]\n- [Create Account]",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 1660,
|
||
"y": 710
|
||
},
|
||
{
|
||
"id": "flow-login-loading",
|
||
"type": "card",
|
||
"title": "3a. Loading State",
|
||
"subtitle": "Показать спиннер",
|
||
"description": "```javascript\nsetLoading(true)\nsetError(null)\n```\n\n- Disable кнопку\n- Показать спиннер",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 1660,
|
||
"y": 540
|
||
},
|
||
{
|
||
"id": "flow-login-api",
|
||
"type": "card",
|
||
"title": "4. POST function=credentials",
|
||
"subtitle": "Авторизация (существующий API)",
|
||
"description": "**URL:** https://eluxnetworks.net/function/well-api/api\n**Format:** x-www-form-urlencoded\n\n**Request:**\n```\nfunction=credentials\nuser_name=anandk\nps=password\nclientId=001\nnonce=random_number\n```\n\n**Response 200:**\n```json\n{\n \"access_token\": \"jwt...\",\n \"privileges\": \"21,38,29,41,42\",\n \"user_id\": 43,\n \"max_role\": 2,\n \"status\": \"200 OK\"\n}\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 2026.443603515625,
|
||
"y": 542.4937133789062
|
||
},
|
||
{
|
||
"id": "flow-login-condition",
|
||
"type": "condition",
|
||
"title": "4a. Успех?",
|
||
"subtitle": "Проверка ответа",
|
||
"description": "**status === \"200 OK\"?**\n\n**Да** → Сохранить токен\n**Нет** → Показать ошибку",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "yellow",
|
||
"x": 2420,
|
||
"y": 542
|
||
},
|
||
{
|
||
"id": "flow-login-success",
|
||
"type": "card",
|
||
"title": "5. Сохранение токена",
|
||
"subtitle": "SecureStore",
|
||
"description": "```javascript\nawait SecureStore.setItemAsync('accessToken', response.access_token)\nawait SecureStore.setItemAsync('userId', response.user_id)\nawait SecureStore.setItemAsync('privileges', response.privileges)\n```\n\nПереход на главный экран",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 2800,
|
||
"y": 480
|
||
},
|
||
{
|
||
"id": "flow-login-error",
|
||
"type": "card",
|
||
"title": "5b. Error State",
|
||
"subtitle": "Показать ошибку",
|
||
"description": "```javascript\nsetLoading(false)\nsetError('Invalid credentials')\n```\n\n- Красный текст ошибки\n- Кнопка Retry активна",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "red",
|
||
"x": 2800,
|
||
"y": 620
|
||
},
|
||
{
|
||
"id": "flow-register-screen",
|
||
"type": "card",
|
||
"title": "3r. REGISTER SCREEN",
|
||
"subtitle": "Экран регистрации",
|
||
"description": "**Файл:** `app/(auth)/register.tsx`\n\n**Поля:**\n- Full Name\n- Email\n- Password\n- Confirm Password\n\n**Кнопки:**\n- [Create Account]\n- [Sign In]",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 1660,
|
||
"y": 880
|
||
},
|
||
{
|
||
"id": "flow-register-validate",
|
||
"type": "condition",
|
||
"title": "3r-1. Валидация?",
|
||
"subtitle": "Клиентская проверка",
|
||
"description": "- Name не пустой?\n- Email валидный?\n- Password >= 6?\n- Passwords совпадают?",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "yellow",
|
||
"x": 2040,
|
||
"y": 880
|
||
},
|
||
{
|
||
"id": "flow-register-api",
|
||
"type": "card",
|
||
"title": "3r-2. POST register",
|
||
"subtitle": "API регистрации",
|
||
"description": "**Request:**\n```json\n{\n \"name\": \"John\",\n \"email\": \"user@example.com\",\n \"password\": \"xxx\"\n}\n```\n\n**Response 201:** tokens\n**Error 409:** Email exists",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 2420,
|
||
"y": 880
|
||
},
|
||
{
|
||
"id": "flow-register-email",
|
||
"type": "card",
|
||
"title": "3r-3. Welcome Email",
|
||
"subtitle": "SendGrid",
|
||
"description": "Backend отправляет приветственное письмо\n\n(на сервере)",
|
||
"tags": [
|
||
"external"
|
||
],
|
||
"borderColor": "orange",
|
||
"x": 2800,
|
||
"y": 880
|
||
},
|
||
{
|
||
"id": "flow-forgot-screen",
|
||
"type": "card",
|
||
"title": "3f. FORGOT PASSWORD",
|
||
"subtitle": "Восстановление пароля",
|
||
"description": "**Файл:** `app/(auth)/forgot.tsx`\n\n**Поле:** Email\n\n**Кнопки:**\n- [Send Reset Link]\n- [Back to Login]",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 1660,
|
||
"y": 1050
|
||
},
|
||
{
|
||
"id": "flow-forgot-api",
|
||
"type": "card",
|
||
"title": "3f-1. POST forgot",
|
||
"subtitle": "API сброса",
|
||
"description": "**Request:**\n```json\n{ \"email\": \"user@example.com\" }\n```\n\n**Response 200:**\n```json\n{ \"message\": \"Reset link sent\" }\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 2040,
|
||
"y": 1050
|
||
},
|
||
{
|
||
"id": "flow-patients-list",
|
||
"type": "card",
|
||
"title": "6. PATIENTS LIST",
|
||
"subtitle": "Главный экран - список пациентов",
|
||
"description": "**Файл:** `app/(tabs)/index.tsx`\n\n**State:**\n- patients: Patient[]\n- loading, error\n\n**UI:**\n- Список карточек\n- Pull to refresh\n- [+] Добавить\n\n**Tab Bar:** Home | Chat | Profile",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3180,
|
||
"y": 480
|
||
},
|
||
{
|
||
"id": "flow-patients-loading",
|
||
"type": "card",
|
||
"title": "6a. Loading",
|
||
"subtitle": "useEffect mount",
|
||
"description": "```javascript\nuseEffect(() => {\n loadPatients()\n}, [])\n```\n\nsetLoading(true)",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3560,
|
||
"y": 400
|
||
},
|
||
{
|
||
"id": "flow-patients-api",
|
||
"type": "card",
|
||
"title": "6b. GET patients",
|
||
"subtitle": "API запрос",
|
||
"description": "**Request:**\n```\nfunction=get_patients\ntoken=jwt\n```\n\n**Response:**\n```json\n{ \"patients\": [...] }\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 3940,
|
||
"y": 400
|
||
},
|
||
{
|
||
"id": "flow-patients-condition",
|
||
"type": "condition",
|
||
"title": "6c. Успех?",
|
||
"subtitle": "Проверка",
|
||
"description": "**ok === true?**\n\n**Да** → render\n**Нет** → error",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "yellow",
|
||
"x": 4320,
|
||
"y": 400
|
||
},
|
||
{
|
||
"id": "flow-patients-render",
|
||
"type": "card",
|
||
"title": "6d. Render",
|
||
"subtitle": "Отрисовка",
|
||
"description": "```javascript\nsetLoading(false)\nsetPatients(data)\n```\n\nFlatList обновляется",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 4700,
|
||
"y": 340
|
||
},
|
||
{
|
||
"id": "flow-patients-error",
|
||
"type": "card",
|
||
"title": "6e. Error",
|
||
"subtitle": "Ошибка + Retry",
|
||
"description": "```javascript\nsetError('Failed')\n```\n\n[Retry] кнопка",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "red",
|
||
"x": 4700,
|
||
"y": 480
|
||
},
|
||
{
|
||
"id": "flow-patient-dashboard",
|
||
"type": "card",
|
||
"title": "7. PATIENT DASHBOARD",
|
||
"subtitle": "Дашборд пациента",
|
||
"description": "**Файл:** `app/patients/[id]/index.tsx`\n\n**Секции:**\n- Статус (online/offline)\n- Здоровье (пульс, шаги, сон)\n- Напоминания о лекарствах\n- [Chat with Julia] → AI Chat",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3180,
|
||
"y": 620
|
||
},
|
||
{
|
||
"id": "flow-add-patient",
|
||
"type": "card",
|
||
"title": "6+. ADD PATIENT",
|
||
"subtitle": "Добавить пациента",
|
||
"description": "**Файл:** `app/patients/add.tsx`\n\n**Поля:**\n- Name\n- Photo\n- Relationship\n- Device ID",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3180,
|
||
"y": 760
|
||
},
|
||
{
|
||
"id": "flow-chat-screen",
|
||
"type": "card",
|
||
"title": "8. AI CHAT SCREEN",
|
||
"subtitle": "Текстовый чат с Julia",
|
||
"description": "**Файл:** `app/(tabs)/chat.tsx`\n\n**State:**\n- messages: Message[]\n- input, sending\n\n**UI:**\n- История (bubbles)\n- Input + Send\n- Typing indicator",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3560,
|
||
"y": 620
|
||
},
|
||
{
|
||
"id": "flow-chat-send",
|
||
"type": "card",
|
||
"title": "8a. Send",
|
||
"subtitle": "Отправка сообщения",
|
||
"description": "```javascript\nsetSending(true)\nsetMessages([...messages, {\n role: 'user',\n content: input\n}])\n```",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3940,
|
||
"y": 560
|
||
},
|
||
{
|
||
"id": "flow-chat-send-api",
|
||
"type": "card",
|
||
"title": "9. POST function=voice_ask",
|
||
"subtitle": "Отправка сообщения (существующий API)",
|
||
"description": "**URL:** https://eluxnetworks.net/function/well-api/api\n**Format:** x-www-form-urlencoded\n\n**Request:**\n```\nfunction=voice_ask\nclientId=MA_001\nuser_name=anandk\ntoken=jwt_token\nquestion=How is mom doing?\ndeployment_id=21\n```\n\n**Response 200:**\n```json\n{\n \"ok\": true,\n \"response\": {\n \"Command\": \"REPORT\",\n \"body\": \"Hello! How can I assist you?\",\n \"language\": \"English\"\n },\n \"status\": \"200 OK\"\n}\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 4320,
|
||
"y": 560
|
||
},
|
||
{
|
||
"id": "flow-chat-openai",
|
||
"type": "card",
|
||
"title": "10. OpenAI GPT-3.5-turbo",
|
||
"subtitle": "AI обработка (на бэкенде)",
|
||
"description": "Бэкенд использует:\n**Модель:** gpt-3.5-turbo\n\nЭто происходит на сервере.\nФронтенд просто отправляет question и получает ответ.\n\n**Мы НЕ вызываем OpenAI напрямую!**",
|
||
"tags": [
|
||
"external"
|
||
],
|
||
"borderColor": "orange",
|
||
"x": 4700,
|
||
"y": 620
|
||
},
|
||
{
|
||
"id": "flow-chat-response",
|
||
"type": "card",
|
||
"title": "10a. Render Response",
|
||
"subtitle": "Показать ответ",
|
||
"description": "```javascript\nsetSending(false)\nsetMessages([...messages, {\n role: 'assistant',\n content: response.body\n}])\n```",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 4700,
|
||
"y": 760
|
||
},
|
||
{
|
||
"id": "flow-profile-screen",
|
||
"type": "card",
|
||
"title": "11. PROFILE SCREEN",
|
||
"subtitle": "Профиль пользователя",
|
||
"description": "**Файл:** `app/(tabs)/profile.tsx`\n\n**Секции:**\n- Аватар, имя, email\n- [Edit Profile]\n- Notification Settings\n- [Subscription]\n- [Logout]",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3560,
|
||
"y": 760
|
||
},
|
||
{
|
||
"id": "flow-profile-api",
|
||
"type": "card",
|
||
"title": "11a. GET profile",
|
||
"subtitle": "Загрузка профиля",
|
||
"description": "**Response:**\n```json\n{\n \"name\": \"John\",\n \"email\": \"...\",\n \"subscription\": {...}\n}\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 3940,
|
||
"y": 760
|
||
},
|
||
{
|
||
"id": "flow-profile-update",
|
||
"type": "card",
|
||
"title": "11b. PATCH profile",
|
||
"subtitle": "Обновление",
|
||
"description": "**Request:**\n```json\n{ \"name\": \"New\" }\n```",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 4320,
|
||
"y": 760
|
||
},
|
||
{
|
||
"id": "flow-subscription-screen",
|
||
"type": "card",
|
||
"title": "12. SUBSCRIPTION",
|
||
"subtitle": "Управление подпиской",
|
||
"description": "**Файл:** `app/subscription/index.tsx`\n\n**Планы:**\n- Free: 1 пациент\n- Basic ($9.99): 3 пациента\n- Premium ($19.99): Unlimited",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3560,
|
||
"y": 900
|
||
},
|
||
{
|
||
"id": "flow-stripe-checkout",
|
||
"type": "card",
|
||
"title": "12a. Stripe Checkout",
|
||
"subtitle": "Страница оплаты",
|
||
"description": "WebView или in-app browser\n\nПосле оплаты → redirect\n`wellnuo://payment-success`",
|
||
"tags": [
|
||
"external"
|
||
],
|
||
"borderColor": "orange",
|
||
"x": 3940,
|
||
"y": 900
|
||
},
|
||
{
|
||
"id": "flow-stripe-webhook",
|
||
"type": "card",
|
||
"title": "12b. Stripe Webhook",
|
||
"subtitle": "Backend обработка",
|
||
"description": "**Events:**\n- checkout.session.completed\n- invoice.paid\n\nОбновление БД",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "green",
|
||
"x": 4320,
|
||
"y": 900
|
||
},
|
||
{
|
||
"id": "flow-logout",
|
||
"type": "card",
|
||
"title": "13. LOGOUT",
|
||
"subtitle": "Выход из системы",
|
||
"description": "```javascript\nawait SecureStore.deleteItemAsync('accessToken')\nawait SecureStore.deleteItemAsync('userId')\nrouter.replace('/(auth)/login')\n```",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"x": 3180,
|
||
"y": 900
|
||
},
|
||
{
|
||
"id": "db-schema",
|
||
"type": "card",
|
||
"title": "DATABASE SCHEMA",
|
||
"subtitle": "PostgreSQL таблицы",
|
||
"description": "**users:** id, name, email, password_hash, avatar, subscription\n\n**patients:** id, name, avatar, device_id, status, health_data\n\n**user_patients:** user_id, patient_id, relationship\n\n**messages:** id, user_id, patient_id, role, content\n\n**alerts:** id, patient_id, type, message, read\n\n**password_resets:** id, user_id, token, expires_at",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"borderColor": "teal",
|
||
"x": 140,
|
||
"y": 1000
|
||
},
|
||
{
|
||
"id": "design-colors",
|
||
"type": "card",
|
||
"title": "DESIGN: Colors",
|
||
"subtitle": "Цветовая палитра",
|
||
"description": "**Primary:**\n- `#4A90D9` - Primary Blue\n- `#2E5C8A` - Primary Dark\n\n**Status:**\n- `#5AC8A8` - Success\n- `#F5A623` - Warning\n- `#D0021B` - Error\n\n**Neutral:**\n- `#FFFFFF` - Background\n- `#F5F7FA` - Surface\n- `#333333` - Text Primary",
|
||
"tags": [
|
||
"system"
|
||
],
|
||
"borderColor": "pink",
|
||
"x": 520,
|
||
"y": 1000
|
||
},
|
||
{
|
||
"id": "design-typography",
|
||
"type": "card",
|
||
"title": "DESIGN: Typography",
|
||
"subtitle": "Шрифты",
|
||
"description": "**Font:** Inter\n\n**Sizes:**\nxs: 12, sm: 14, base: 16\nlg: 18, xl: 20, 2xl: 24\n\n**Weights:** 400, 500, 600, 700",
|
||
"tags": [
|
||
"system"
|
||
],
|
||
"borderColor": "pink",
|
||
"x": 900,
|
||
"y": 1000
|
||
},
|
||
{
|
||
"id": "todo-frontend",
|
||
"type": "card",
|
||
"title": "TODO: Frontend задачи",
|
||
"subtitle": "Что нужно сделать",
|
||
"description": "**1. Auth:**\n- [ ] Login screen\n- [ ] Register screen\n- [ ] Forgot password\n- [ ] SecureStore\n\n**2. Chat:**\n- [ ] Chat UI (bubbles)\n- [ ] voice_ask API\n- [ ] Typing indicator\n\n**3. Patients:**\n- [ ] List screen\n- [ ] Dashboard\n- [ ] Add patient\n\n**4. Profile:**\n- [ ] Profile screen\n- [ ] Subscription\n- [ ] Logout",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"borderColor": "blue",
|
||
"completed": false,
|
||
"x": 1280,
|
||
"y": 1000
|
||
}
|
||
],
|
||
"connections": [
|
||
{
|
||
"from": "info-project",
|
||
"to": "info-legend"
|
||
},
|
||
{
|
||
"from": "info-legend",
|
||
"to": "info-data-flow"
|
||
},
|
||
{
|
||
"from": "info-project",
|
||
"to": "env-section"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-gitea"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-api-url"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-api-credentials"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-expo-project"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-stripe-pub"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-stripe-secret"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "env-sendgrid"
|
||
},
|
||
{
|
||
"from": "env-section",
|
||
"to": "api-structure"
|
||
},
|
||
{
|
||
"from": "api-structure",
|
||
"to": "flow-start"
|
||
},
|
||
{
|
||
"from": "flow-start",
|
||
"to": "flow-check-token"
|
||
},
|
||
{
|
||
"from": "flow-check-token",
|
||
"to": "flow-login-screen",
|
||
"label": "Нет токена"
|
||
},
|
||
{
|
||
"from": "flow-check-token",
|
||
"to": "flow-patients-list",
|
||
"label": "Есть токен"
|
||
},
|
||
{
|
||
"from": "flow-login-screen",
|
||
"to": "flow-login-loading",
|
||
"label": "Sign In"
|
||
},
|
||
{
|
||
"from": "flow-login-loading",
|
||
"to": "flow-login-api"
|
||
},
|
||
{
|
||
"from": "flow-login-api",
|
||
"to": "flow-login-condition"
|
||
},
|
||
{
|
||
"from": "flow-login-condition",
|
||
"to": "flow-login-success",
|
||
"label": "200 OK"
|
||
},
|
||
{
|
||
"from": "flow-login-condition",
|
||
"to": "flow-login-error",
|
||
"label": "Error"
|
||
},
|
||
{
|
||
"from": "flow-login-success",
|
||
"to": "flow-patients-list"
|
||
},
|
||
{
|
||
"from": "flow-login-error",
|
||
"to": "flow-login-screen",
|
||
"label": "Retry"
|
||
},
|
||
{
|
||
"from": "flow-login-screen",
|
||
"to": "flow-register-screen",
|
||
"label": "Create Account"
|
||
},
|
||
{
|
||
"from": "flow-register-screen",
|
||
"to": "flow-register-validate",
|
||
"label": "Submit"
|
||
},
|
||
{
|
||
"from": "flow-register-validate",
|
||
"to": "flow-register-api",
|
||
"label": "Valid"
|
||
},
|
||
{
|
||
"from": "flow-register-api",
|
||
"to": "flow-register-email"
|
||
},
|
||
{
|
||
"from": "flow-register-email",
|
||
"to": "flow-login-success"
|
||
},
|
||
{
|
||
"from": "flow-login-screen",
|
||
"to": "flow-forgot-screen",
|
||
"label": "Forgot?"
|
||
},
|
||
{
|
||
"from": "flow-forgot-screen",
|
||
"to": "flow-forgot-api",
|
||
"label": "Submit"
|
||
},
|
||
{
|
||
"from": "flow-forgot-api",
|
||
"to": "flow-login-screen",
|
||
"label": "Email sent"
|
||
},
|
||
{
|
||
"from": "flow-patients-list",
|
||
"to": "flow-patients-loading",
|
||
"label": "Mount"
|
||
},
|
||
{
|
||
"from": "flow-patients-loading",
|
||
"to": "flow-patients-api"
|
||
},
|
||
{
|
||
"from": "flow-patients-api",
|
||
"to": "flow-patients-condition"
|
||
},
|
||
{
|
||
"from": "flow-patients-condition",
|
||
"to": "flow-patients-render",
|
||
"label": "Success"
|
||
},
|
||
{
|
||
"from": "flow-patients-condition",
|
||
"to": "flow-patients-error",
|
||
"label": "Error"
|
||
},
|
||
{
|
||
"from": "flow-patients-error",
|
||
"to": "flow-patients-loading",
|
||
"label": "Retry"
|
||
},
|
||
{
|
||
"from": "flow-patients-render",
|
||
"to": "flow-patients-list",
|
||
"label": "Render"
|
||
},
|
||
{
|
||
"from": "flow-patients-list",
|
||
"to": "flow-patient-dashboard",
|
||
"label": "Select patient"
|
||
},
|
||
{
|
||
"from": "flow-patients-list",
|
||
"to": "flow-add-patient",
|
||
"label": "+ Add"
|
||
},
|
||
{
|
||
"from": "flow-add-patient",
|
||
"to": "flow-patients-list",
|
||
"label": "Created"
|
||
},
|
||
{
|
||
"from": "flow-patient-dashboard",
|
||
"to": "flow-chat-screen",
|
||
"label": "Chat with Julia"
|
||
},
|
||
{
|
||
"from": "flow-chat-screen",
|
||
"to": "flow-chat-send",
|
||
"label": "Send"
|
||
},
|
||
{
|
||
"from": "flow-chat-send",
|
||
"to": "flow-chat-send-api"
|
||
},
|
||
{
|
||
"from": "flow-chat-send-api",
|
||
"to": "flow-chat-openai"
|
||
},
|
||
{
|
||
"from": "flow-chat-openai",
|
||
"to": "flow-chat-response"
|
||
},
|
||
{
|
||
"from": "flow-chat-response",
|
||
"to": "flow-chat-screen",
|
||
"label": "Render"
|
||
},
|
||
{
|
||
"from": "flow-patients-list",
|
||
"to": "flow-profile-screen",
|
||
"label": "Tab: Profile"
|
||
},
|
||
{
|
||
"from": "flow-profile-screen",
|
||
"to": "flow-profile-api",
|
||
"label": "Load"
|
||
},
|
||
{
|
||
"from": "flow-profile-screen",
|
||
"to": "flow-profile-update",
|
||
"label": "Edit"
|
||
},
|
||
{
|
||
"from": "flow-profile-screen",
|
||
"to": "flow-subscription-screen",
|
||
"label": "Subscription"
|
||
},
|
||
{
|
||
"from": "flow-profile-screen",
|
||
"to": "flow-logout",
|
||
"label": "Logout"
|
||
},
|
||
{
|
||
"from": "flow-subscription-screen",
|
||
"to": "flow-stripe-checkout",
|
||
"label": "Select Plan"
|
||
},
|
||
{
|
||
"from": "flow-stripe-checkout",
|
||
"to": "flow-stripe-webhook"
|
||
},
|
||
{
|
||
"from": "flow-stripe-webhook",
|
||
"to": "flow-profile-screen",
|
||
"label": "Updated"
|
||
},
|
||
{
|
||
"from": "flow-logout",
|
||
"to": "flow-login-screen"
|
||
},
|
||
{
|
||
"from": "db-schema",
|
||
"to": "design-colors"
|
||
},
|
||
{
|
||
"from": "design-colors",
|
||
"to": "design-typography"
|
||
},
|
||
{
|
||
"from": "design-typography",
|
||
"to": "todo-frontend"
|
||
}
|
||
],
|
||
"tagsDictionary": [
|
||
{
|
||
"name": "system",
|
||
"color": "gray"
|
||
},
|
||
{
|
||
"name": "env",
|
||
"color": "cyan"
|
||
},
|
||
{
|
||
"name": "frontend",
|
||
"color": "blue"
|
||
},
|
||
{
|
||
"name": "backend",
|
||
"color": "green"
|
||
},
|
||
{
|
||
"name": "external",
|
||
"color": "orange"
|
||
}
|
||
]
|
||
} |