Files
mindfulness/client/app/(onboarding)/onboarding.tsx

151 lines
4.3 KiB
TypeScript

import { useState } from 'react';
import { useRouter } from 'expo-router';
import * as Notifications from 'expo-notifications';
import { OnboardingLayout } from '@/components/onboarding/OnboardingLayout';
import { NameInputStep } from '@/components/onboarding/NameInputStep';
import { SelectionStep } from '@/components/onboarding/SelectionStep';
import { ReminderStep } from '@/components/onboarding/ReminderStep';
import { setOnboardingCompleted, setUserProfile, setDailyReminderSettings } from '@/src/storage/appStorage';
const STEPS = [
{ id: 'name', type: 'name', title: '我可以怎么称呼你?' },
{
id: 'status',
type: 'selection',
title: '媽媽的狀態?',
options: [
{ id: 'pregnant', label: '懷孕中/準備成為媽媽' },
{ id: 'has_kids', label: '已經有孩子' },
{ id: 'no_fill', label: '不想填寫' },
]
},
{
id: 'emotion',
type: 'selection',
title: '當下情緒狀態?',
options: [
{ id: 'happy', label: '愉悅、滿足' },
{ id: 'calm', label: '平靜、安穩' },
{ id: 'stressed', label: '被壓得有點喘不過氣' },
{ id: 'low', label: '情緒低落' },
]
},
{
id: 'influence',
type: 'selection',
title: '是什麼影響了你最近的感受?',
options: [
{ id: 'family', label: '家庭與孩子' },
{ id: 'work', label: '工作或學習' },
{ id: 'relationship', label: '親密關係' },
{ id: 'friends', label: '朋友與人際' },
{ id: 'health', label: '身心健康' },
]
},
{
id: 'support',
type: 'selection',
title: '最需要什麼支持?',
options: [
{ id: 'emotional', label: '情緒支持' },
{ id: 'parenting', label: '育兒壓力' },
{ id: 'self_worth', label: '自我價值' },
{ id: 'anxiety', label: '焦慮舒緩' },
{ id: 'balance', label: '休息與平衡' },
]
},
{ id: 'reminder', type: 'reminder', title: '你需要每天几次提醒?' },
];
export default function OnboardingScreen() {
const router = useRouter();
const [stepIndex, setStepIndex] = useState(0);
const [name, setName] = useState('');
const [selections, setSelections] = useState<Record<string, string[]>>({});
const [reminderTimes, setReminderTimes] = useState(3);
const currentStep = STEPS[stepIndex];
async function onFinish() {
// 请求推送权限
const { status } = await Notifications.requestPermissionsAsync();
const pushEnabled = status === 'granted';
await setUserProfile({
name,
intents: Object.values(selections).flat()
});
await setDailyReminderSettings({
timesPerDay: reminderTimes,
pushEnabled: pushEnabled
});
await setOnboardingCompleted(true);
router.replace('/(app)/home');
}
const onNext = () => {
if (stepIndex < STEPS.length - 1) {
setStepIndex(stepIndex + 1);
} else {
onFinish();
}
};
const onBack = () => {
if (stepIndex > 0) {
setStepIndex(stepIndex - 1);
}
};
const onSkip = async () => {
await setOnboardingCompleted(true);
router.replace('/(app)/home');
};
const handleToggleSelection = (id: string) => {
setSelections(prev => {
const currentIds = prev[currentStep.id] || [];
const nextIds = currentIds.includes(id)
? currentIds.filter(i => i !== id)
: [...currentIds, id];
return { ...prev, [currentStep.id]: nextIds };
});
};
return (
<OnboardingLayout
title={currentStep.title}
currentStep={stepIndex}
totalSteps={STEPS.length - 1}
onSkip={onSkip}
onBack={onBack}
showBackButton={stepIndex > 0}
>
{currentStep.type === 'name' && (
<NameInputStep
value={name}
onChangeText={setName}
onNext={onNext}
/>
)}
{currentStep.type === 'selection' && (
<SelectionStep
options={currentStep.options!}
selectedIds={selections[currentStep.id] || []}
onToggle={handleToggleSelection}
onNext={onNext}
/>
)}
{currentStep.type === 'reminder' && (
<ReminderStep
value={reminderTimes}
onChange={setReminderTimes}
onFinish={onFinish}
/>
)}
</OnboardingLayout>
);
}