import React, { useState } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
TextInput,
ScrollView,
ActivityIndicator,
Alert,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { router, useLocalSearchParams } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import { AppColors, Spacing, BorderRadius, FontSizes, FontWeights } from '@/constants/theme';
import { useBeneficiary } from '@/contexts/BeneficiaryContext';
import { api } from '@/services/api';
export default function ActivateScreen() {
// Get params - lovedOneName from purchase flow, beneficiaryId from existing beneficiary
const params = useLocalSearchParams<{ lovedOneName?: string; beneficiaryId?: string }>();
const [activationCode, setActivationCode] = useState('');
const [isActivating, setIsActivating] = useState(false);
const [step, setStep] = useState<'code' | 'beneficiary' | 'complete'>('code');
// Pre-fill beneficiary name from params if available
const [beneficiaryName, setBeneficiaryName] = useState(params.lovedOneName || '');
const { addLocalBeneficiary, updateLocalBeneficiary, localBeneficiaries } = useBeneficiary();
// Check if we're activating for an existing beneficiary
const existingBeneficiaryId = params.beneficiaryId ? parseInt(params.beneficiaryId, 10) : null;
const existingBeneficiary = existingBeneficiaryId
? localBeneficiaries.find(b => b.id === existingBeneficiaryId)
: null;
// Demo serial for testing without real hardware
const DEMO_SERIAL = 'DEMO-00000';
const handleActivate = async () => {
const code = activationCode.trim().toUpperCase();
if (!code) {
Alert.alert('Error', 'Please enter serial number');
return;
}
// Check for demo serial
const isDemoMode = code === DEMO_SERIAL || code === 'DEMO-1234-5678';
// Validate code format: minimum 8 characters (or demo serial)
if (!isDemoMode && code.length < 8) {
Alert.alert('Invalid Code', 'Please enter a valid serial number from your WellNuo Starter Kit.\n\nFor testing, use: DEMO-00000');
return;
}
setIsActivating(true);
try {
// If we have an existing beneficiary, update them with device info
if (existingBeneficiaryId && existingBeneficiary) {
// Prepare update data
const updateData: any = {
hasDevices: true,
device_id: code,
equipmentStatus: 'active', // Clear awaiting state - sensors now active
};
// If beneficiary has pending subscription (from kit purchase), activate it
if (existingBeneficiary.subscription?.status === 'pending') {
updateData.subscription = {
...existingBeneficiary.subscription,
status: 'active',
};
}
await updateLocalBeneficiary(existingBeneficiaryId, updateData);
setBeneficiaryName(existingBeneficiary.name);
setStep('complete');
} else {
// Creating new beneficiary
const beneficiaryData: any = {
name: params.lovedOneName?.trim() || '',
hasDevices: true,
device_id: code,
};
if (isDemoMode) {
beneficiaryData.isDemo = true;
}
// If name was already provided from add-loved-one screen, skip to saving
if (params.lovedOneName && params.lovedOneName.trim()) {
await addLocalBeneficiary(beneficiaryData);
await api.setOnboardingCompleted(true);
setStep('complete');
} else {
// No name provided, show beneficiary form
setStep('beneficiary');
}
}
} catch (error) {
console.error('Failed to activate:', error);
Alert.alert('Error', 'Failed to activate kit. Please try again.');
} finally {
setIsActivating(false);
}
};
const handleAddBeneficiary = async () => {
if (!beneficiaryName.trim()) {
Alert.alert('Error', 'Please enter beneficiary name');
return;
}
setIsActivating(true);
try {
const code = activationCode.trim().toUpperCase();
const isDemoMode = code === DEMO_SERIAL || code === 'DEMO-1234-5678';
// Add beneficiary with device info
await addLocalBeneficiary({
name: beneficiaryName.trim(),
hasDevices: true,
device_id: code,
isDemo: isDemoMode,
});
// Mark onboarding as completed
await api.setOnboardingCompleted(true);
setStep('complete');
} catch (error) {
console.error('Failed to add beneficiary:', error);
Alert.alert('Error', 'Failed to add beneficiary. Please try again.');
} finally {
setIsActivating(false);
}
};
const handleComplete = () => {
// If updating existing beneficiary, go back to their detail page
if (existingBeneficiaryId) {
router.replace(`/(tabs)/beneficiaries/${existingBeneficiaryId}`);
} else {
// Navigate to main app
router.replace('/(tabs)');
}
};
// Step 1: Enter activation code
if (step === 'code') {
return (
{/* Header */}
{existingBeneficiary ? (
router.back()}>
) : (
)}
{existingBeneficiary ? 'Connect Sensors' : 'Activate Kit'}
{/* Icon */}
{/* Instructions */}
{existingBeneficiary
? `Connect sensors for ${existingBeneficiary.name}`
: 'Enter the activation code from your WellNuo Starter Kit packaging'}
{/* Input */}
{/* Demo Code Link */}
setActivationCode('DEMO-1234-5678')}
>
Use demo code
{/* Activate Button */}
{isActivating ? (
) : (
Activate
)}
{/* Skip for now - only show for new onboarding, not for existing beneficiary */}
{!existingBeneficiary && (
Skip for now
)}
);
}
// Step 2: Add beneficiary
if (step === 'beneficiary') {
return (
{/* Header */}
setStep('code')}>
Add Beneficiary
{/* Icon */}
{/* Instructions */}
Who will you be monitoring with this kit?
{/* Name Input */}
Full Name
{/* Continue Button */}
{isActivating ? (
) : (
Continue
)}
);
}
// Step 3: Complete
const displayName = beneficiaryName || existingBeneficiary?.name || params.lovedOneName;
return (
{/* Success Icon */}
{existingBeneficiary ? 'Sensors Connected!' : 'Kit Activated!'}
{existingBeneficiary
? `Sensors have been connected for `
: `Your WellNuo kit has been successfully activated for `}
{displayName}
{/* Next Steps */}
Next Steps:
{existingBeneficiary ? (
<>
1
Connect the hub to WiFi
2
Subscribe to start monitoring ($49/month)
>
) : (
<>
1
Place sensors in your loved one's home
2
Connect the hub to WiFi
3
Subscribe to start monitoring ($49/month)
>
)}
{/* Complete Button */}
{existingBeneficiary ? 'Continue' : 'Go to Dashboard'}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.background,
},
content: {
flex: 1,
padding: Spacing.lg,
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: Spacing.xl,
},
backButton: {
padding: Spacing.sm,
marginLeft: -Spacing.sm,
},
title: {
fontSize: FontSizes.xl,
fontWeight: FontWeights.bold,
color: AppColors.textPrimary,
},
placeholder: {
width: 40,
},
iconContainer: {
alignItems: 'center',
marginBottom: Spacing.xl,
},
instructions: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
textAlign: 'center',
marginBottom: Spacing.xl,
lineHeight: 24,
},
inputContainer: {
marginBottom: Spacing.lg,
},
inputGroup: {
marginBottom: Spacing.lg,
},
inputLabel: {
fontSize: FontSizes.sm,
fontWeight: FontWeights.medium,
color: AppColors.textPrimary,
marginBottom: Spacing.sm,
},
input: {
backgroundColor: AppColors.surface,
borderRadius: BorderRadius.lg,
paddingHorizontal: Spacing.lg,
paddingVertical: Spacing.md,
fontSize: FontSizes.lg,
color: AppColors.textPrimary,
textAlign: 'center',
borderWidth: 1,
borderColor: AppColors.border,
},
devNotice: {
alignItems: 'center',
marginBottom: Spacing.xl,
paddingVertical: Spacing.lg,
paddingHorizontal: Spacing.lg,
backgroundColor: `${AppColors.warning}10`,
borderRadius: BorderRadius.lg,
borderWidth: 1,
borderColor: `${AppColors.warning}30`,
},
devNoticeTitle: {
fontSize: FontSizes.base,
fontWeight: FontWeights.semibold,
color: AppColors.warning,
marginTop: Spacing.sm,
marginBottom: Spacing.sm,
},
devNoticeText: {
fontSize: FontSizes.sm,
color: AppColors.textSecondary,
textAlign: 'center',
lineHeight: 20,
marginBottom: Spacing.md,
},
demoCodeButton: {
paddingVertical: Spacing.sm,
paddingHorizontal: Spacing.lg,
backgroundColor: AppColors.warning,
borderRadius: BorderRadius.md,
},
demoCodeButtonText: {
fontSize: FontSizes.sm,
fontWeight: FontWeights.medium,
color: AppColors.white,
},
demoCodeLink: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
gap: 4,
marginBottom: Spacing.md,
},
demoCodeLinkText: {
fontSize: FontSizes.sm,
color: AppColors.textMuted,
},
primaryButton: {
backgroundColor: AppColors.primary,
paddingVertical: Spacing.lg,
borderRadius: BorderRadius.lg,
alignItems: 'center',
marginTop: Spacing.md,
},
buttonDisabled: {
opacity: 0.7,
},
primaryButtonText: {
fontSize: FontSizes.lg,
fontWeight: FontWeights.semibold,
color: AppColors.white,
},
skipButton: {
alignItems: 'center',
paddingVertical: Spacing.lg,
},
skipButtonText: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
textDecorationLine: 'underline',
},
successContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
successIcon: {
marginBottom: Spacing.xl,
},
successTitle: {
fontSize: FontSizes['2xl'],
fontWeight: FontWeights.bold,
color: AppColors.textPrimary,
marginBottom: Spacing.md,
},
successMessage: {
fontSize: FontSizes.base,
color: AppColors.textSecondary,
textAlign: 'center',
marginBottom: Spacing.md,
},
beneficiaryHighlight: {
fontWeight: FontWeights.bold,
color: AppColors.primary,
},
nextSteps: {
width: '100%',
backgroundColor: AppColors.surface,
borderRadius: BorderRadius.lg,
padding: Spacing.lg,
},
nextStepsTitle: {
fontSize: FontSizes.base,
fontWeight: FontWeights.semibold,
color: AppColors.textPrimary,
marginBottom: Spacing.md,
},
stepItem: {
flexDirection: 'row',
alignItems: 'center',
gap: Spacing.md,
marginBottom: Spacing.sm,
},
stepNumber: {
width: 24,
height: 24,
borderRadius: 12,
backgroundColor: AppColors.primary,
color: AppColors.white,
textAlign: 'center',
lineHeight: 24,
fontSize: FontSizes.sm,
fontWeight: FontWeights.bold,
overflow: 'hidden',
},
stepText: {
fontSize: FontSizes.sm,
color: AppColors.textSecondary,
flex: 1,
},
});