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>
556 lines
15 KiB
JSON
556 lines
15 KiB
JSON
{
|
||
"_meta": {
|
||
"name": "WellNuo - UX Flow (Step by Step)",
|
||
"updatedAt": "2025-12-12T21:07:42.362Z"
|
||
},
|
||
"elements": [
|
||
{
|
||
"id": "start",
|
||
"type": "card",
|
||
"title": "1. App Launch",
|
||
"borderColor": "purple",
|
||
"tags": [
|
||
"user"
|
||
],
|
||
"description": "Пользователь открывает приложение\n\nДействие: Tap на иконку WellNuo\nРезультат: Запуск приложения",
|
||
"x": 140,
|
||
"y": 396.25
|
||
},
|
||
{
|
||
"id": "check_token",
|
||
"type": "card",
|
||
"title": "2. Check Stored Token",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Frontend проверяет наличие токена\n\nИсточник: SecureStore\nКлюч: 'access_token'\n\nЕсли есть → проверить валидность\nЕсли нет → показать Login",
|
||
"x": 520,
|
||
"y": 396.25
|
||
},
|
||
{
|
||
"id": "token_exists",
|
||
"type": "condition",
|
||
"title": "Token exists?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "Есть ли сохраненный токен?",
|
||
"x": 890,
|
||
"y": 396.25
|
||
},
|
||
{
|
||
"id": "show_login",
|
||
"type": "card",
|
||
"title": "3. Login Screen",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Экран авторизации\n\nПоля:\n- Username (TextInput)\n- Password (TextInput, secure)\n- Login Button\n\nСостояние: loading, error, idle",
|
||
"x": 6160,
|
||
"y": 573.75
|
||
},
|
||
{
|
||
"id": "user_enters_creds",
|
||
"type": "card",
|
||
"title": "4. Enter Credentials",
|
||
"borderColor": "purple",
|
||
"tags": [
|
||
"user"
|
||
],
|
||
"description": "Пользователь вводит данные\n\nUsername: string (required)\nPassword: string (required)\n\nДействие: Нажимает Login",
|
||
"x": 6540,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "validate_input",
|
||
"type": "card",
|
||
"title": "5. Validate Input",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Клиентская валидация\n\nПроверки:\n- Username не пустой\n- Password не пустой\n- Длина >= 3 символов\n\nОшибка → показать inline error",
|
||
"x": 6920,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "input_valid",
|
||
"type": "condition",
|
||
"title": "Input valid?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "Прошла ли клиентская валидация?",
|
||
"x": 7290,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "send_auth_request",
|
||
"type": "card",
|
||
"title": "6. Send Auth Request",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "POST запрос на авторизацию\n\nURL: https://eluxnetworks.net/function/well-api/api\nContent-Type: x-www-form-urlencoded\n\nBody:\n- function=credentials\n- user_name={username}\n- ps={password}\n- clientId={deviceId}\n- nonce={timestamp}",
|
||
"x": 7660,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "backend_auth",
|
||
"type": "card",
|
||
"title": "7. Validate Credentials",
|
||
"borderColor": "blue",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"description": "Backend проверяет credentials\n\nПроцесс:\n1. Проверка user_name в DB\n2. Сравнение password hash\n3. Генерация access_token\n4. Возврат user_id, privileges\n\nУспех: { ok: true, access_token, user_id }\nОшибка: { ok: false, error: 'message' }",
|
||
"x": 8040,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "auth_success",
|
||
"type": "condition",
|
||
"title": "Auth success?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "ok === true?",
|
||
"x": 8410,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "store_token",
|
||
"type": "card",
|
||
"title": "8. Store Token",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Сохранение данных авторизации\n\nSecureStore:\n- access_token\n- user_id\n- user_name\n\nAsyncStorage:\n- privileges\n- login_timestamp",
|
||
"x": 8780,
|
||
"y": 145
|
||
},
|
||
{
|
||
"id": "show_auth_error",
|
||
"type": "card",
|
||
"title": "Auth Error",
|
||
"borderColor": "red",
|
||
"tags": [
|
||
"error",
|
||
"frontend"
|
||
],
|
||
"description": "Показать ошибку авторизации\n\nТипы ошибок:\n- Invalid credentials\n- Account locked\n- Network error\n- Server error\n\nДействие: Alert или inline message",
|
||
"x": 8780,
|
||
"y": 607.5
|
||
},
|
||
{
|
||
"id": "main_chat",
|
||
"type": "card",
|
||
"title": "9. Chat Screen",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Главный экран чата\n\nКомпоненты:\n- Header (user info, logout)\n- MessageList (FlatList)\n- InputField + Send Button\n\nСостояние:\n- messages: []\n- inputText: ''\n- isLoading: false",
|
||
"x": 1260,
|
||
"y": 155
|
||
},
|
||
{
|
||
"id": "user_types",
|
||
"type": "card",
|
||
"title": "10. Type Message",
|
||
"borderColor": "purple",
|
||
"tags": [
|
||
"user"
|
||
],
|
||
"description": "Пользователь пишет сообщение\n\nДействие: Ввод текста в TextInput\nЗатем: Нажимает Send или Enter",
|
||
"x": 1640,
|
||
"y": 325
|
||
},
|
||
{
|
||
"id": "validate_message",
|
||
"type": "card",
|
||
"title": "11. Validate Message",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Проверка сообщения\n\n- Не пустое\n- Длина <= 4000 символов\n- Не только пробелы\n\nДобавить в messages[] как 'user'",
|
||
"x": 2020,
|
||
"y": 325
|
||
},
|
||
{
|
||
"id": "message_valid",
|
||
"type": "condition",
|
||
"title": "Message valid?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "Прошла ли валидация сообщения?",
|
||
"x": 2390,
|
||
"y": 268.75
|
||
},
|
||
{
|
||
"id": "send_chat_request",
|
||
"type": "card",
|
||
"title": "12. Send Chat Request",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "POST запрос на AI chat\n\nURL: https://eluxnetworks.net/function/well-api/api\nContent-Type: x-www-form-urlencoded\n\nBody:\n- function=voice_ask\n- clientId={deviceId}\n- user_name={username}\n- token={access_token}\n- question={message}\n- deployment_id={model_id}\n\nState: isLoading = true",
|
||
"x": 2760,
|
||
"y": 268.75
|
||
},
|
||
{
|
||
"id": "backend_chat",
|
||
"type": "card",
|
||
"title": "13. Process Chat Request",
|
||
"borderColor": "blue",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"description": "Backend обрабатывает запрос\n\n1. Валидация token\n2. Rate limiting check\n3. Подготовка prompt\n4. Вызов AI провайдера\n5. Логирование\n6. Возврат ответа",
|
||
"x": 3140,
|
||
"y": 245
|
||
},
|
||
{
|
||
"id": "call_openrouter",
|
||
"type": "card",
|
||
"title": "14. AI Provider Request",
|
||
"borderColor": "orange",
|
||
"tags": [
|
||
"external"
|
||
],
|
||
"description": "Запрос к OpenRouter\n\nURL: https://openrouter.ai/api/v1/chat/completions\nModel: gpt-3.5-turbo\n\nПараметры:\n- messages: [{role, content}]\n- max_tokens: 1000\n- temperature: 0.7",
|
||
"x": 3520,
|
||
"y": 245
|
||
},
|
||
{
|
||
"id": "ai_response",
|
||
"type": "card",
|
||
"title": "15. AI Response",
|
||
"borderColor": "orange",
|
||
"tags": [
|
||
"external"
|
||
],
|
||
"description": "OpenRouter возвращает ответ\n\n{\n choices: [{\n message: {\n content: 'AI response text'\n }\n }]\n}",
|
||
"x": 3900,
|
||
"y": 245
|
||
},
|
||
{
|
||
"id": "backend_response",
|
||
"type": "card",
|
||
"title": "16. Backend Response",
|
||
"borderColor": "blue",
|
||
"tags": [
|
||
"backend"
|
||
],
|
||
"description": "Backend формирует ответ\n\nУспех:\n{\n ok: true,\n response: {\n body: 'AI response text'\n }\n}\n\nОшибка:\n{ ok: false, error: 'message' }",
|
||
"x": 4280,
|
||
"y": 245
|
||
},
|
||
{
|
||
"id": "chat_success",
|
||
"type": "condition",
|
||
"title": "Response OK?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "ok === true?",
|
||
"x": 4650,
|
||
"y": 245
|
||
},
|
||
{
|
||
"id": "display_response",
|
||
"type": "card",
|
||
"title": "17. Display Response",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Отображение ответа AI\n\nДобавить в messages[]:\n{\n role: 'assistant',\n content: response.body,\n timestamp: Date.now()\n}\n\nisLoading = false\nScroll to bottom",
|
||
"x": 5020,
|
||
"y": 77.5
|
||
},
|
||
{
|
||
"id": "show_chat_error",
|
||
"type": "card",
|
||
"title": "Chat Error",
|
||
"borderColor": "red",
|
||
"tags": [
|
||
"error",
|
||
"frontend"
|
||
],
|
||
"description": "Показать ошибку чата\n\nТипы:\n- Token expired → re-login\n- Rate limit → wait message\n- AI error → retry option\n- Network → offline mode?\n\nisLoading = false",
|
||
"x": 5020,
|
||
"y": 543.75
|
||
},
|
||
{
|
||
"id": "token_expired",
|
||
"type": "condition",
|
||
"title": "Token expired?",
|
||
"borderColor": "yellow",
|
||
"tags": [
|
||
"decision"
|
||
],
|
||
"description": "Ошибка 401 или token_expired?",
|
||
"x": 5400,
|
||
"y": 543.75
|
||
},
|
||
{
|
||
"id": "clear_auth",
|
||
"type": "card",
|
||
"title": "Clear Auth Data",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Очистка данных авторизации\n\nSecureStore.deleteItemAsync('access_token')\nSecureStore.deleteItemAsync('user_id')\n\nПеренаправление на Login Screen",
|
||
"x": 5780,
|
||
"y": 567.5
|
||
},
|
||
{
|
||
"id": "retry_option",
|
||
"type": "card",
|
||
"title": "Retry Option",
|
||
"borderColor": "green",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Предложить повторить\n\nUI: Кнопка 'Retry' под ошибкой\nДействие: Повторный send_chat_request\n\nМакс. 3 попытки",
|
||
"x": 5780,
|
||
"y": 291.25
|
||
},
|
||
{
|
||
"id": "logout",
|
||
"type": "card",
|
||
"title": "Logout",
|
||
"borderColor": "purple",
|
||
"tags": [
|
||
"user"
|
||
],
|
||
"description": "Пользователь выходит\n\nДействие: Нажимает Logout в Header\n\nОчистка:\n- SecureStore tokens\n- AsyncStorage data\n- Reset navigation to Login",
|
||
"x": 5400,
|
||
"y": 416.25
|
||
},
|
||
{
|
||
"id": "end_session",
|
||
"type": "card",
|
||
"title": "Session End",
|
||
"borderColor": "gray",
|
||
"tags": [
|
||
"frontend"
|
||
],
|
||
"description": "Завершение сессии\n\nВозврат на Login Screen\nГотов к новой авторизации",
|
||
"x": 5780,
|
||
"y": 440
|
||
}
|
||
],
|
||
"connections": [
|
||
{
|
||
"from": "start",
|
||
"to": "check_token"
|
||
},
|
||
{
|
||
"from": "check_token",
|
||
"to": "token_exists"
|
||
},
|
||
{
|
||
"from": "token_exists",
|
||
"to": "main_chat",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "token_exists",
|
||
"to": "show_login",
|
||
"label": "no"
|
||
},
|
||
{
|
||
"from": "show_login",
|
||
"to": "user_enters_creds"
|
||
},
|
||
{
|
||
"from": "user_enters_creds",
|
||
"to": "validate_input"
|
||
},
|
||
{
|
||
"from": "validate_input",
|
||
"to": "input_valid"
|
||
},
|
||
{
|
||
"from": "input_valid",
|
||
"to": "send_auth_request",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "input_valid",
|
||
"to": "show_login",
|
||
"label": "no (show error)"
|
||
},
|
||
{
|
||
"from": "send_auth_request",
|
||
"to": "backend_auth"
|
||
},
|
||
{
|
||
"from": "backend_auth",
|
||
"to": "auth_success"
|
||
},
|
||
{
|
||
"from": "auth_success",
|
||
"to": "store_token",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "auth_success",
|
||
"to": "show_auth_error",
|
||
"label": "no"
|
||
},
|
||
{
|
||
"from": "store_token",
|
||
"to": "main_chat"
|
||
},
|
||
{
|
||
"from": "show_auth_error",
|
||
"to": "show_login"
|
||
},
|
||
{
|
||
"from": "main_chat",
|
||
"to": "user_types"
|
||
},
|
||
{
|
||
"from": "user_types",
|
||
"to": "validate_message"
|
||
},
|
||
{
|
||
"from": "validate_message",
|
||
"to": "message_valid"
|
||
},
|
||
{
|
||
"from": "message_valid",
|
||
"to": "send_chat_request",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "message_valid",
|
||
"to": "main_chat",
|
||
"label": "no"
|
||
},
|
||
{
|
||
"from": "send_chat_request",
|
||
"to": "backend_chat"
|
||
},
|
||
{
|
||
"from": "backend_chat",
|
||
"to": "call_openrouter"
|
||
},
|
||
{
|
||
"from": "call_openrouter",
|
||
"to": "ai_response"
|
||
},
|
||
{
|
||
"from": "ai_response",
|
||
"to": "backend_response"
|
||
},
|
||
{
|
||
"from": "backend_response",
|
||
"to": "chat_success"
|
||
},
|
||
{
|
||
"from": "chat_success",
|
||
"to": "display_response",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "chat_success",
|
||
"to": "show_chat_error",
|
||
"label": "no"
|
||
},
|
||
{
|
||
"from": "display_response",
|
||
"to": "main_chat",
|
||
"label": "loop"
|
||
},
|
||
{
|
||
"from": "show_chat_error",
|
||
"to": "token_expired"
|
||
},
|
||
{
|
||
"from": "token_expired",
|
||
"to": "clear_auth",
|
||
"label": "yes"
|
||
},
|
||
{
|
||
"from": "token_expired",
|
||
"to": "retry_option",
|
||
"label": "no"
|
||
},
|
||
{
|
||
"from": "clear_auth",
|
||
"to": "show_login"
|
||
},
|
||
{
|
||
"from": "retry_option",
|
||
"to": "send_chat_request",
|
||
"label": "retry"
|
||
},
|
||
{
|
||
"from": "retry_option",
|
||
"to": "main_chat",
|
||
"label": "cancel"
|
||
},
|
||
{
|
||
"from": "main_chat",
|
||
"to": "logout",
|
||
"label": "logout action"
|
||
},
|
||
{
|
||
"from": "logout",
|
||
"to": "end_session"
|
||
},
|
||
{
|
||
"from": "end_session",
|
||
"to": "show_login"
|
||
}
|
||
],
|
||
"tagsDictionary": [
|
||
{
|
||
"id": "tag-user",
|
||
"name": "user",
|
||
"color": "purple"
|
||
},
|
||
{
|
||
"id": "tag-frontend",
|
||
"name": "frontend",
|
||
"color": "green"
|
||
},
|
||
{
|
||
"id": "tag-backend",
|
||
"name": "backend",
|
||
"color": "blue"
|
||
},
|
||
{
|
||
"id": "tag-external",
|
||
"name": "external",
|
||
"color": "orange"
|
||
},
|
||
{
|
||
"id": "tag-decision",
|
||
"name": "decision",
|
||
"color": "yellow"
|
||
},
|
||
{
|
||
"id": "tag-error",
|
||
"name": "error",
|
||
"color": "red"
|
||
}
|
||
]
|
||
} |