diff --git a/Discussion_Points.md b/Discussion_Points.md
new file mode 100644
index 0000000..29fb107
--- /dev/null
+++ b/Discussion_Points.md
@@ -0,0 +1,66 @@
+# WellNuo Mobile App
+## Discussion Points for EluxNetworks Team
+
+---
+
+## 1. Backend/API Development Access
+
+**Request:** Can I get access to develop backend/API endpoints myself?
+
+### Why?
+
+| Problem | Impact |
+|---------|--------|
+| No fixed technical specification | Requirements will change frequently |
+| Waiting for backend = blocked work | Significant development delays |
+| Can't predict all API needs upfront | Discovery happens during implementation |
+
+### Option A: Access Granted (Preferred)
+
+**I need:**
+- Repository access (or separate repo)
+- Database documentation
+- Architecture overview
+
+**I will:**
+- Implement endpoints myself
+- Document all changes
+
+### Option B: No Access
+
+**EluxNetworks implements these APIs:**
+
+| Category | Endpoints |
+|----------|-----------|
+| Auth | Registration, Password reset, Email verification |
+| Billing | Subscription plans, Payments (Stripe) |
+| Beneficiary | CRUD, Family invites |
+| Orders | Product catalog, Order tracking |
+| Notifications | Device registration, Push settings |
+| Profile | User CRUD, Password change, Account deletion |
+
+**Important:** This list is a rough estimate, not a final specification. Actual requirements will change during development. Expect multiple rounds of revisions and delays.
+
+---
+
+## 2. WebView Embed Mode
+
+**Request:** Add `?embedded=true` parameter to hide UI elements
+
+**Hide:**
+- Header "Dashboard Details"
+- Navigation arrows (< >)
+- Logout button
+
+**Reason:** Mobile app has its own navigation and auth.
+
+---
+
+## Summary
+
+| Option | Result |
+|--------|--------|
+| **Backend access** | Fast development, flexible, minimal delays |
+| **Wait for APIs** | Slow, multiple spec revisions, blocked work |
+
+**Recommendation:** Backend access for fastest delivery.
diff --git a/Discussion_Points.txt b/Discussion_Points.txt
new file mode 100644
index 0000000..c7bb9fa
--- /dev/null
+++ b/Discussion_Points.txt
@@ -0,0 +1,67 @@
+WELLNUO MOBILE APP
+Discussion Points for EluxNetworks Team
+
+────────────────────────────────────────────────────────────
+
+1. BACKEND/API DEVELOPMENT ACCESS
+
+Request: Can I get access to develop backend/API endpoints myself?
+
+
+Why?
+
+- No fixed technical specification - requirements will change frequently
+- Waiting for backend = blocked frontend work = significant delays
+- Can't predict all API needs upfront - discovery happens during implementation
+
+
+Option A: Access Granted (Preferred)
+
+I need:
+ - Repository access (or separate repo)
+ - Database documentation
+ - Architecture overview
+
+I will:
+ - Implement endpoints myself
+ - Document all changes
+
+
+Option B: No Access
+
+EluxNetworks implements these APIs:
+
+ - Auth: Registration, Password reset, Email verification
+ - Billing: Subscription plans, Payments (Stripe)
+ - Beneficiary: CRUD, Family invites
+ - Orders: Product catalog, Order tracking
+ - Notifications: Device registration, Push settings
+ - Profile: User CRUD, Password change, Account deletion
+
+Important: This list is a rough estimate, not a final specification.
+Actual requirements will change during development.
+Expect multiple rounds of revisions and delays.
+
+
+────────────────────────────────────────────────────────────
+
+2. WEBVIEW EMBED MODE
+
+Request: Add ?embedded=true parameter to hide UI elements
+
+Hide:
+ - Header "Dashboard Details"
+ - Navigation arrows (< >)
+ - Logout button
+
+Reason: Mobile app has its own navigation and auth.
+
+
+────────────────────────────────────────────────────────────
+
+SUMMARY
+
+Backend access = fast development, flexible, minimal delays
+Wait for APIs = slow, multiple spec revisions, blocked work
+
+Recommendation: Backend access for fastest delivery.
diff --git a/app/(auth)/forgot-password.tsx b/app/(auth)/forgot-password.tsx
new file mode 100644
index 0000000..c68bfb7
--- /dev/null
+++ b/app/(auth)/forgot-password.tsx
@@ -0,0 +1,159 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ KeyboardAvoidingView,
+ Platform,
+ ScrollView,
+ TouchableOpacity,
+ Alert,
+} from 'react-native';
+import { router } from 'expo-router';
+import { Ionicons } from '@expo/vector-icons';
+import { Button } from '@/components/ui/Button';
+import { Input } from '@/components/ui/Input';
+import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
+
+export default function ForgotPasswordScreen() {
+ const [email, setEmail] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleSubmit = () => {
+ if (!email.trim()) {
+ Alert.alert('Error', 'Please enter your email address');
+ return;
+ }
+
+ // Show "in development" message
+ Alert.alert(
+ 'Coming Soon',
+ 'Password recovery is currently under development. Please contact support for assistance.',
+ [{ text: 'OK' }]
+ );
+ };
+
+ return (
+
+
+ {/* Back Button */}
+ router.back()}>
+
+
+
+ {/* Header */}
+
+
+
+
+ Forgot Password?
+
+ Enter your email address and we'll send you instructions to reset your password.
+
+
+
+ {/* Form */}
+
+
+
+
+
+
+ {/* Footer */}
+
+ Remember your password?
+ router.back()}>
+ Sign In
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: AppColors.background,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ paddingHorizontal: Spacing.lg,
+ paddingTop: Spacing.xl,
+ paddingBottom: Spacing.xl,
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: BorderRadius.full,
+ backgroundColor: AppColors.surface,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.lg,
+ },
+ header: {
+ alignItems: 'center',
+ marginBottom: Spacing.xl,
+ },
+ iconContainer: {
+ width: 100,
+ height: 100,
+ borderRadius: BorderRadius.full,
+ backgroundColor: AppColors.primaryLight + '30',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.lg,
+ },
+ title: {
+ fontSize: FontSizes['2xl'],
+ fontWeight: '700',
+ color: AppColors.textPrimary,
+ marginBottom: Spacing.sm,
+ },
+ subtitle: {
+ fontSize: FontSizes.base,
+ color: AppColors.textSecondary,
+ textAlign: 'center',
+ lineHeight: 22,
+ },
+ form: {
+ marginBottom: Spacing.xl,
+ },
+ footer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ footerText: {
+ fontSize: FontSizes.base,
+ color: AppColors.textSecondary,
+ },
+ footerLink: {
+ fontSize: FontSizes.base,
+ color: AppColors.primary,
+ fontWeight: '600',
+ },
+});
diff --git a/app/(auth)/login.tsx b/app/(auth)/login.tsx
index e9e0e11..84b772a 100644
--- a/app/(auth)/login.tsx
+++ b/app/(auth)/login.tsx
@@ -108,7 +108,7 @@ export default function LoginScreen() {
returnKeyType="done"
/>
-
+ router.push('/(auth)/forgot-password')}>
Forgot Password?
@@ -124,7 +124,7 @@ export default function LoginScreen() {
{/* Footer */}
Don't have an account?
-
+ router.push('/(auth)/register')}>
Create Account
diff --git a/app/(auth)/register.tsx b/app/(auth)/register.tsx
new file mode 100644
index 0000000..e3fe688
--- /dev/null
+++ b/app/(auth)/register.tsx
@@ -0,0 +1,219 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ KeyboardAvoidingView,
+ Platform,
+ ScrollView,
+ TouchableOpacity,
+ Alert,
+} from 'react-native';
+import { router } from 'expo-router';
+import { Ionicons } from '@expo/vector-icons';
+import { Button } from '@/components/ui/Button';
+import { Input } from '@/components/ui/Input';
+import { AppColors, BorderRadius, FontSizes, Spacing } from '@/constants/theme';
+
+export default function RegisterScreen() {
+ const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [confirmPassword, setConfirmPassword] = useState('');
+ const [name, setName] = useState('');
+ const [phone, setPhone] = useState('');
+ const [isLoading, setIsLoading] = useState(false);
+
+ const handleSubmit = () => {
+ // Basic validation
+ if (!username.trim()) {
+ Alert.alert('Error', 'Username is required');
+ return;
+ }
+ if (!email.trim()) {
+ Alert.alert('Error', 'Email is required');
+ return;
+ }
+ if (!password.trim()) {
+ Alert.alert('Error', 'Password is required');
+ return;
+ }
+ if (password !== confirmPassword) {
+ Alert.alert('Error', 'Passwords do not match');
+ return;
+ }
+ if (!name.trim()) {
+ Alert.alert('Error', 'Full name is required');
+ return;
+ }
+
+ // Show "in development" message
+ Alert.alert(
+ 'Coming Soon',
+ 'Account registration is currently under development. Please contact support to create an account.',
+ [{ text: 'OK' }]
+ );
+ };
+
+ return (
+
+
+ {/* Back Button */}
+ router.back()}>
+
+
+
+ {/* Header */}
+
+ Create Account
+
+ Join WellNuo to start monitoring your loved ones
+
+
+
+ {/* Form */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Footer */}
+
+ Already have an account?
+ router.back()}>
+ Sign In
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: AppColors.background,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ paddingHorizontal: Spacing.lg,
+ paddingTop: Spacing.xl,
+ paddingBottom: Spacing.xl,
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: BorderRadius.full,
+ backgroundColor: AppColors.surface,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.lg,
+ },
+ header: {
+ alignItems: 'center',
+ marginBottom: Spacing.xl,
+ },
+ title: {
+ fontSize: FontSizes['2xl'],
+ fontWeight: '700',
+ color: AppColors.textPrimary,
+ marginBottom: Spacing.sm,
+ },
+ subtitle: {
+ fontSize: FontSizes.base,
+ color: AppColors.textSecondary,
+ textAlign: 'center',
+ },
+ form: {
+ marginBottom: Spacing.xl,
+ },
+ footer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ footerText: {
+ fontSize: FontSizes.base,
+ color: AppColors.textSecondary,
+ },
+ footerLink: {
+ fontSize: FontSizes.base,
+ color: AppColors.primary,
+ fontWeight: '600',
+ },
+});
diff --git a/app/(tabs)/beneficiaries/[id]/index.tsx b/app/(tabs)/beneficiaries/[id]/index.tsx
index 402a482..c831436 100644
--- a/app/(tabs)/beneficiaries/[id]/index.tsx
+++ b/app/(tabs)/beneficiaries/[id]/index.tsx
@@ -6,6 +6,12 @@ import {
ScrollView,
TouchableOpacity,
RefreshControl,
+ Image,
+ Modal,
+ TextInput,
+ Alert,
+ KeyboardAvoidingView,
+ Platform,
} from 'react-native';
import { useLocalSearchParams, router } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
@@ -26,6 +32,13 @@ export default function BeneficiaryDetailScreen() {
const [isRefreshing, setIsRefreshing] = useState(false);
const [error, setError] = useState(null);
+ // Edit modal state
+ const [isEditModalVisible, setIsEditModalVisible] = useState(false);
+ const [editForm, setEditForm] = useState({
+ name: '',
+ address: '',
+ });
+
const loadBeneficiary = useCallback(async (showLoading = true) => {
if (!id) return;
@@ -66,6 +79,32 @@ export default function BeneficiaryDetailScreen() {
router.push('/(tabs)/chat');
};
+ const handleEditPress = () => {
+ if (beneficiary) {
+ setEditForm({
+ name: beneficiary.name || '',
+ address: beneficiary.address || '',
+ });
+ setIsEditModalVisible(true);
+ }
+ };
+
+ const handleSaveEdit = () => {
+ Alert.alert(
+ 'Demo Mode',
+ 'This is a mockup feature. Saving beneficiary data requires backend API endpoints that are not yet implemented.\n\nContact your administrator to enable this feature.',
+ [{ text: 'OK', onPress: () => setIsEditModalVisible(false) }]
+ );
+ };
+
+ const showComingSoon = (featureName: string) => {
+ Alert.alert(
+ 'Coming Soon',
+ `${featureName} is currently in development.\n\nThis feature will be available in a future update.`,
+ [{ text: 'OK' }]
+ );
+ };
+
if (isLoading) {
return ;
}
@@ -90,8 +129,8 @@ export default function BeneficiaryDetailScreen() {
{beneficiary.name}
-
-
+
+
@@ -109,9 +148,13 @@ export default function BeneficiaryDetailScreen() {
{/* Beneficiary Info Card */}
-
- {beneficiary.name.charAt(0).toUpperCase()}
-
+ {beneficiary.avatar ? (
+
+ ) : (
+
+ {beneficiary.name.charAt(0).toUpperCase()}
+
+ )}
Chat with Julia
-
+ showComingSoon('Set Reminder')}>
Set Reminder
-
+ showComingSoon('Video Call')}>
Video Call
-
+ showComingSoon('Activity Report')}>
@@ -264,6 +307,76 @@ export default function BeneficiaryDetailScreen() {
/>
+
+ {/* Edit Modal */}
+ setIsEditModalVisible(false)}
+ >
+
+
+
+ Edit Beneficiary
+ setIsEditModalVisible(false)}
+ style={styles.modalCloseButton}
+ >
+
+
+
+
+
+ Name
+ setEditForm({ ...editForm, name: text })}
+ placeholder="Enter name"
+ placeholderTextColor={AppColors.textMuted}
+ />
+
+ Address
+ setEditForm({ ...editForm, address: text })}
+ placeholder="Enter address"
+ placeholderTextColor={AppColors.textMuted}
+ multiline
+ numberOfLines={3}
+ />
+
+
+
+
+ Other data (wellness score, temperature, sleep hours) is collected automatically from sensors.
+
+
+
+
+
+ setIsEditModalVisible(false)}
+ >
+ Cancel
+
+
+
+ Save Changes
+
+
+
+
+
);
}
@@ -291,7 +404,7 @@ const styles = StyleSheet.create({
fontWeight: '600',
color: AppColors.textPrimary,
},
- menuButton: {
+ editButton: {
padding: Spacing.xs,
},
content: {
@@ -317,6 +430,11 @@ const styles = StyleSheet.create({
fontWeight: '600',
color: AppColors.white,
},
+ avatarImage: {
+ width: 100,
+ height: 100,
+ borderRadius: BorderRadius.full,
+ },
statusBadge: {
position: 'absolute',
bottom: 0,
@@ -423,4 +541,104 @@ const styles = StyleSheet.create({
padding: Spacing.lg,
paddingBottom: Spacing.xxl,
},
+ // Modal styles
+ modalOverlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ justifyContent: 'flex-end',
+ },
+ modalContent: {
+ backgroundColor: AppColors.background,
+ borderTopLeftRadius: BorderRadius.xl,
+ borderTopRightRadius: BorderRadius.xl,
+ maxHeight: '80%',
+ },
+ modalHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ padding: Spacing.lg,
+ borderBottomWidth: 1,
+ borderBottomColor: AppColors.border,
+ },
+ modalTitle: {
+ fontSize: FontSizes.xl,
+ fontWeight: '600',
+ color: AppColors.textPrimary,
+ },
+ modalCloseButton: {
+ padding: Spacing.xs,
+ },
+ modalForm: {
+ padding: Spacing.lg,
+ },
+ inputLabel: {
+ fontSize: FontSizes.sm,
+ fontWeight: '500',
+ color: AppColors.textSecondary,
+ marginBottom: Spacing.xs,
+ marginTop: Spacing.md,
+ },
+ textInput: {
+ backgroundColor: AppColors.surface,
+ borderRadius: BorderRadius.md,
+ padding: Spacing.md,
+ fontSize: FontSizes.base,
+ color: AppColors.textPrimary,
+ borderWidth: 1,
+ borderColor: AppColors.border,
+ },
+ textAreaInput: {
+ minHeight: 80,
+ textAlignVertical: 'top',
+ },
+ infoBox: {
+ flexDirection: 'row',
+ backgroundColor: '#EFF6FF',
+ borderRadius: BorderRadius.md,
+ padding: Spacing.md,
+ marginTop: Spacing.lg,
+ gap: Spacing.sm,
+ },
+ infoBoxText: {
+ flex: 1,
+ fontSize: FontSizes.sm,
+ color: AppColors.primary,
+ lineHeight: 20,
+ },
+ modalFooter: {
+ flexDirection: 'row',
+ padding: Spacing.lg,
+ gap: Spacing.md,
+ borderTopWidth: 1,
+ borderTopColor: AppColors.border,
+ },
+ cancelButton: {
+ flex: 1,
+ paddingVertical: Spacing.md,
+ borderRadius: BorderRadius.md,
+ backgroundColor: AppColors.surface,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ cancelButtonText: {
+ fontSize: FontSizes.base,
+ fontWeight: '500',
+ color: AppColors.textSecondary,
+ },
+ saveButton: {
+ flex: 2,
+ flexDirection: 'row',
+ paddingVertical: Spacing.md,
+ borderRadius: BorderRadius.md,
+ backgroundColor: AppColors.primary,
+ alignItems: 'center',
+ justifyContent: 'center',
+ gap: Spacing.xs,
+ },
+ saveButtonText: {
+ fontSize: FontSizes.base,
+ fontWeight: '600',
+ color: AppColors.white,
+ },
});
diff --git a/app/(tabs)/chat.tsx b/app/(tabs)/chat.tsx
index 411be98..251d46a 100644
--- a/app/(tabs)/chat.tsx
+++ b/app/(tabs)/chat.tsx
@@ -8,6 +8,7 @@ import {
TouchableOpacity,
KeyboardAvoidingView,
Platform,
+ Alert,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
@@ -142,7 +143,10 @@ export default function ChatScreen() {
-
+ Alert.alert('Coming Soon', 'Chat settings will be available in a future update.')}
+ >
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
index f3a38e7..9c42f56 100644
--- a/app/(tabs)/index.tsx
+++ b/app/(tabs)/index.tsx
@@ -6,7 +6,8 @@ import {
FlatList,
TouchableOpacity,
ActivityIndicator,
- RefreshControl
+ RefreshControl,
+ Image,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
@@ -24,7 +25,6 @@ interface PatientCardProps {
}
function PatientCard({ patient, onPress }: PatientCardProps) {
- const isOnline = patient.status === 'online';
const wellnessColor = patient.wellness_score && patient.wellness_score >= 70
? AppColors.success
: patient.wellness_score && patient.wellness_score >= 40
@@ -35,11 +35,16 @@ function PatientCard({ patient, onPress }: PatientCardProps) {
{/* Avatar */}
-
-
- {patient.name.charAt(0).toUpperCase()}
-
- {isOnline && }
+
+ {patient.avatar ? (
+
+ ) : (
+
+
+ {patient.name.charAt(0).toUpperCase()}
+
+
+ )}
{/* Info */}
@@ -51,16 +56,9 @@ function PatientCard({ patient, onPress }: PatientCardProps) {
{patient.last_location}
)}
-
-
-
- {isOnline ? 'Active' : 'Inactive'}
-
-
- {patient.last_activity && (
- {patient.last_activity}
- )}
-
+ {patient.last_activity && (
+ {patient.last_activity}
+ )}
{/* Wellness Score */}
@@ -266,35 +264,31 @@ const styles = StyleSheet.create({
alignItems: 'center',
padding: Spacing.md,
},
+ avatarWrapper: {
+ width: 56,
+ height: 56,
+ borderRadius: 28,
+ position: 'relative',
+ overflow: 'hidden',
+ },
avatar: {
width: 56,
height: 56,
- borderRadius: BorderRadius.full,
+ borderRadius: 28,
backgroundColor: AppColors.primaryLight,
justifyContent: 'center',
alignItems: 'center',
- position: 'relative',
},
- avatarOnline: {
- borderWidth: 2,
- borderColor: AppColors.success,
+ avatarImage: {
+ width: 56,
+ height: 56,
+ borderRadius: 28,
},
avatarText: {
fontSize: FontSizes.xl,
fontWeight: '600',
color: AppColors.white,
},
- onlineIndicator: {
- position: 'absolute',
- bottom: 2,
- right: 2,
- width: 14,
- height: 14,
- borderRadius: 7,
- backgroundColor: AppColors.success,
- borderWidth: 2,
- borderColor: AppColors.white,
- },
info: {
flex: 1,
marginLeft: Spacing.md,
@@ -309,32 +303,6 @@ const styles = StyleSheet.create({
color: AppColors.textSecondary,
marginTop: 2,
},
- statusRow: {
- flexDirection: 'row',
- alignItems: 'center',
- marginTop: Spacing.xs,
- },
- statusBadge: {
- paddingHorizontal: Spacing.sm,
- paddingVertical: 2,
- borderRadius: BorderRadius.sm,
- },
- statusOnline: {
- backgroundColor: 'rgba(34, 197, 94, 0.1)',
- },
- statusOffline: {
- backgroundColor: 'rgba(107, 114, 128, 0.1)',
- },
- statusText: {
- fontSize: FontSizes.xs,
- fontWeight: '500',
- },
- statusTextOnline: {
- color: AppColors.success,
- },
- statusTextOffline: {
- color: AppColors.textMuted,
- },
lastActivity: {
fontSize: FontSizes.xs,
color: AppColors.textMuted,
diff --git a/app/(tabs)/profile/help.tsx b/app/(tabs)/profile/help.tsx
index c700574..e2405bf 100644
--- a/app/(tabs)/profile/help.tsx
+++ b/app/(tabs)/profile/help.tsx
@@ -7,6 +7,7 @@ import {
TouchableOpacity,
TextInput,
Linking,
+ Alert,
} from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
@@ -209,7 +210,11 @@ export default function HelpScreen() {
{ title: 'Understanding Data', duration: '4:15' },
{ title: 'Troubleshooting', duration: '5:00' },
].map((video, index) => (
-
+ Alert.alert('Coming Soon', `"${video.title}" video tutorial will be available in a future update.`)}
+ >
diff --git a/app/(tabs)/profile/support.tsx b/app/(tabs)/profile/support.tsx
index 6d97841..72270c3 100644
--- a/app/(tabs)/profile/support.tsx
+++ b/app/(tabs)/profile/support.tsx
@@ -374,7 +374,10 @@ export default function SupportScreen() {
numberOfLines={4}
textAlignVertical="top"
/>
-
+ Alert.alert('Coming Soon', 'Reply functionality will be available in a future update.')}
+ >
Send Reply
diff --git a/services/api.ts b/services/api.ts
index 0d08608..0fa9d3a 100644
--- a/services/api.ts
+++ b/services/api.ts
@@ -4,14 +4,13 @@ import type { AuthResponse, ChatResponse, Beneficiary, ApiResponse, ApiError, Da
const API_BASE_URL = 'https://eluxnetworks.net/function/well-api/api';
const CLIENT_ID = 'MA_001';
-// Avatar images for elderly beneficiaries (stable Unsplash URLs)
+// Avatar images for elderly beneficiaries - grandmothers (бабушки)
const ELDERLY_AVATARS = [
- 'https://images.unsplash.com/photo-1559839734-2b71ea197ec2?w=200&h=200&fit=crop&crop=face', // elderly woman 1
- 'https://images.unsplash.com/photo-1581579438747-104c53d7fbc4?w=200&h=200&fit=crop&crop=face', // elderly man 1
- 'https://images.unsplash.com/photo-1566616213894-2d4e1baee5d8?w=200&h=200&fit=crop&crop=face', // elderly woman 2
- 'https://images.unsplash.com/photo-1552058544-f2b08422138a?w=200&h=200&fit=crop&crop=face', // elderly man 2
- 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?w=200&h=200&fit=crop&crop=face', // elderly woman 3
- 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop&crop=face', // elderly man 3
+ 'https://images.unsplash.com/photo-1566616213894-2d4e1baee5d8?w=200&h=200&fit=crop&crop=face', // grandmother with gray hair
+ 'https://images.unsplash.com/photo-1544027993-37dbfe43562a?w=200&h=200&fit=crop&crop=face', // elderly woman smiling
+ 'https://images.unsplash.com/photo-1491308056676-205b7c9a7dc1?w=200&h=200&fit=crop&crop=face', // senior woman portrait
+ 'https://images.unsplash.com/photo-1580489944761-15a19d654956?w=200&h=200&fit=crop&crop=face', // older woman glasses
+ 'https://images.unsplash.com/photo-1548142813-c348350df52b?w=200&h=200&fit=crop&crop=face', // grandmother portrait
];
// Get consistent avatar based on deployment_id
@@ -283,9 +282,11 @@ class ApiService {
const lastDetected = data.last_detected_time ? new Date(data.last_detected_time) : null;
const isRecent = lastDetected && (Date.now() - lastDetected.getTime()) < 30 * 60 * 1000; // 30 min
+ const deploymentId = parseInt(data.deployment_id, 10);
patients.push({
- id: parseInt(data.deployment_id, 10),
+ id: deploymentId,
name: data.name,
+ avatar: getAvatarForBeneficiary(deploymentId),
status: isRecent ? 'online' : 'offline',
address: data.address,
timezone: data.time_zone,
diff --git a/wellnuoSheme/03_DiscussionQuestions.json b/wellnuoSheme/03_DiscussionQuestions.json
index 6c18511..60ca626 100644
--- a/wellnuoSheme/03_DiscussionQuestions.json
+++ b/wellnuoSheme/03_DiscussionQuestions.json
@@ -176,7 +176,7 @@
"api",
"profile"
],
- "description": "GET /api/profile\nPUT /api/profile\n{\n name: string\n email: string\n phone?: string\n avatar_url?: string\n language: string\n timezone: string\n}\n\nPOST /api/profile/change-password\nDELETE /api/profile (удаление аккаунта)",
+ "description": "GET /api/profile\nPUT /api/profile\n{\n name: string\n email: string\n phone?: string\n avatar_url?: string\n language: string\n timezone: string\n}\n\nPOST /api/profile/change-password\nDELETE /api/profile (delete account)",
"x": 2023.0888671875,
"y": 365.1834411621094
}
@@ -193,12 +193,12 @@
{
"from": "q_api_access",
"to": "api_yes",
- "label": "Да"
+ "label": "Yes"
},
{
"from": "q_api_access",
"to": "api_no",
- "label": "Нет"
+ "label": "No"
},
{
"from": "api_no",
diff --git a/wellnuoSheme/04_AppStorePublication.json b/wellnuoSheme/04_AppStorePublication.json
index 060af08..543348c 100644
--- a/wellnuoSheme/04_AppStorePublication.json
+++ b/wellnuoSheme/04_AppStorePublication.json
@@ -1,7 +1,7 @@
{
"_meta": {
"name": "App Store Publication",
- "updatedAt": "2025-12-12T21:45:27.718Z"
+ "updatedAt": "2025-12-13T00:48:45.179Z"
},
"elements": [
{
@@ -181,8 +181,8 @@
"design"
],
"description": "**Size:** 1024×1024 PNG\n\n**Requirements:**\n- No transparency (no alpha)\n- No rounded corners\n- Clear at all sizes\n\n**Style:**\nHeart/care, blue gradient",
- "x": 1660,
- "y": 550
+ "x": 1592.44091796875,
+ "y": 511.067626953125
},
{
"id": "prep_iap",
@@ -194,8 +194,8 @@
"appstore"
],
"description": "**Monthly:**\nID: com.wellnuo.premium.monthly\nPrice: $4.99/month\nName: WellNuo Premium\nDesc: Unlock unlimited history, AI insights, and family connections.\n\n**Yearly:**\nID: com.wellnuo.premium.yearly\nPrice: $49.99/year\nName: WellNuo Premium (Annual)\nDesc: Save 17% with annual subscription.\n\n**Lifetime:**\nID: com.wellnuo.lifetime\nPrice: $149.99\nName: WellNuo Lifetime\nDesc: One-time purchase for lifetime access.\n\n**Trial:** 7 days",
- "x": 2040,
- "y": 150
+ "x": 1115.09814453125,
+ "y": 637.2400722503662
},
{
"id": "prep_age_rating",