Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions homeflow/app/(onboarding)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,6 @@ export default function OnboardingLayout() {
animation: 'slide_from_right',
}}
/>
<Stack.Screen
name="health-data-test"
options={{
animation: 'slide_from_right',
}}
/>
<Stack.Screen
name="fhir-parser-test"
options={{
animation: 'slide_from_right',
}}
/>
<Stack.Screen
name="medical-history"
options={{
Expand Down
19 changes: 14 additions & 5 deletions homeflow/app/(onboarding)/account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@
import { OnboardingStep } from '@/lib/constants';
import { OnboardingService } from '@/lib/services/onboarding-service';
import { useAuth } from '@/hooks/use-auth';
import { saveSurgeryDate } from '@/src/services/throneFirestore';
import { getAuth } from '@/src/services/firestore';
import {
OnboardingProgressBar,
ContinueButton,

Check warning on line 34 in homeflow/app/(onboarding)/account.tsx

View workflow job for this annotation

GitHub Actions / Lint

'ContinueButton' is defined but never used
DevToolBar,
} from '@/components/onboarding';

export default function AccountScreen() {
Expand All @@ -51,9 +52,21 @@
if (isAuthenticated) {
handleAdvance();
}
}, [isAuthenticated]);

Check warning on line 55 in homeflow/app/(onboarding)/account.tsx

View workflow job for this annotation

GitHub Actions / Lint

React Hook useEffect has a missing dependency: 'handleAdvance'. Either include it or remove the dependency array

const handleAdvance = async () => {
// Flush any surgery date collected before login to Firestore now that we have a UID.
const uid = getAuth().currentUser?.uid;
if (uid) {
const data = await OnboardingService.getData();
const surgeryDate = data.eligibility?.surgeryDate;
if (surgeryDate) {
saveSurgeryDate(uid, surgeryDate).catch((err) => {
console.warn('[Account] Failed to flush surgery date to Firestore:', err);
});
}
}

await OnboardingService.goToStep(OnboardingStep.PERMISSIONS);
router.push('/(onboarding)/permissions' as Href);
};
Expand Down Expand Up @@ -119,7 +132,7 @@
}
};

const handleDevSkip = async () => {

Check warning on line 135 in homeflow/app/(onboarding)/account.tsx

View workflow job for this annotation

GitHub Actions / Lint

'handleDevSkip' is assigned a value but never used
await OnboardingService.goToStep(OnboardingStep.PERMISSIONS);
router.push('/(onboarding)/permissions' as Href);
};
Expand Down Expand Up @@ -259,10 +272,6 @@
</ScrollView>
</KeyboardAvoidingView>

<DevToolBar
currentStep={OnboardingStep.ACCOUNT}
onContinue={handleDevSkip}
/>
</SafeAreaView>
);
}
Expand Down
4 changes: 1 addition & 3 deletions homeflow/app/(onboarding)/baseline-survey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
calculateIPSSScore,
getIPSSSeverityDescription,
} from '@/lib/questionnaires/ipss-questionnaire';
import { OnboardingProgressBar, ContinueButton, DevToolBar } from '@/components/onboarding';
import { OnboardingProgressBar, ContinueButton } from '@/components/onboarding';
import { IconSymbol } from '@/components/ui/icon-symbol';

export default function BaselineSurveyScreen() {
Expand Down Expand Up @@ -101,7 +101,7 @@
};

// Dev-only handler that bypasses the survey
const handleDevContinue = async () => {

Check warning on line 104 in homeflow/app/(onboarding)/baseline-survey.tsx

View workflow job for this annotation

GitHub Actions / Lint

'handleDevContinue' is assigned a value but never used
await OnboardingService.goToStep(OnboardingStep.COMPLETE);
router.replace('/(onboarding)/complete' as Href);
};
Expand Down Expand Up @@ -197,7 +197,6 @@
/>
</View>

<DevToolBar currentStep={OnboardingStep.BASELINE_SURVEY} onContinue={handleDevContinue} />
</SafeAreaView>
);
}
Expand Down Expand Up @@ -226,7 +225,6 @@
/>
</View>

<DevToolBar currentStep={OnboardingStep.BASELINE_SURVEY} onContinue={handleDevContinue} />
</SafeAreaView>
);
}
Expand Down
47 changes: 36 additions & 11 deletions homeflow/app/(onboarding)/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ import { SafeAreaView } from 'react-native-safe-area-context';
import { Colors, StanfordColors, Spacing } from '@/constants/theme';
import { OnboardingStep } from '@/lib/constants';
import { OnboardingService } from '@/lib/services/onboarding-service';
import { OnboardingProgressBar, ContinueButton, DevToolBar } from '@/components/onboarding';
import { OnboardingProgressBar, ContinueButton } from '@/components/onboarding';
import { IconSymbol } from '@/components/ui/icon-symbol';

// Lazy-load so the screen still renders even if the package isn't available
let DateTimePicker: any = null;
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
DateTimePicker = require('react-native-ui-datepicker').DateTimePicker;
DateTimePicker = require('react-native-ui-datepicker').default;
} catch {
// noop – graceful degradation below
}
Expand Down Expand Up @@ -79,14 +79,23 @@ export default function OnboardingChatScreen() {
};

const handleContinue = async () => {
const dateStr = surgerySched === 'yes'
? surgeryDate.toISOString().split('T')[0]
: undefined;

await OnboardingService.updateData({
eligibility: {
hasIPhone: true,
hasBPHDiagnosis: bphDiagnosis === 'yes',
consideringSurgery: surgerySched === 'yes',
isEligible: canContinue,
surgeryDate: dateStr,
},
});

// Surgery date is persisted locally in OnboardingService (AsyncStorage).
// It will be flushed to Firestore after the user logs in (account.tsx).

await OnboardingService.goToStep(OnboardingStep.CONSENT);
router.push('/(onboarding)/consent' as Href);
};
Expand Down Expand Up @@ -197,18 +206,35 @@ export default function OnboardingChatScreen() {
<DateTimePicker
mode="single"
date={surgeryDate}
onChange={({ date }: { date: Date }) => {
onChange={({ date }: { date: any }) => {
if (date) {
setSurgeryDate(date);
// react-native-ui-datepicker returns a Dayjs object,
// not a native Date. Convert via valueOf() (epoch ms).
const nativeDate =
date instanceof Date
? date
: new Date(typeof date.valueOf === 'function' ? date.valueOf() : date);
setSurgeryDate(nativeDate);
setShowDatePicker(false);
}
}}
selectedItemColor={StanfordColors.cardinal}
headerButtonColor={StanfordColors.cardinal}
calendarTextStyle={{ color: colors.text }}
headerTextStyle={{ color: colors.text }}
weekDaysTextStyle={{ color: colors.icon }}
todayTextStyle={{ color: StanfordColors.cardinal }}
styles={{
// Day grid
day_label: { color: colors.text },
outside_label: { color: colors.icon },
disabled_label: { color: colors.icon, opacity: 0.35 },
// Weekday header row
weekday_label: { color: colors.icon },
// Month / year selectors in header
month_selector_label: { color: colors.text, fontWeight: '600' },
year_selector_label: { color: colors.text, fontWeight: '600' },
// Today highlight (unfilled ring)
today: { borderWidth: 1, borderColor: StanfordColors.cardinal, borderRadius: 999 },
today_label: { color: StanfordColors.cardinal },
// Selected day — filled cardinal circle
selected: { backgroundColor: StanfordColors.cardinal, borderRadius: 999 },
selected_label: { color: '#FFFFFF', fontWeight: '600' },
}}
/>
) : (
<Text style={[styles.pickerFallback, { color: colors.icon }]}>
Expand All @@ -230,7 +256,6 @@ export default function OnboardingChatScreen() {
/>
</View>

<DevToolBar currentStep={OnboardingStep.CHAT} onContinue={handleContinue} />
</SafeAreaView>
);
}
Expand Down
4 changes: 2 additions & 2 deletions homeflow/app/(onboarding)/complete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
import { useRouter } from 'expo-router';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Colors, StanfordColors, Spacing } from '@/constants/theme';
import { STUDY_INFO, OnboardingStep } from '@/lib/constants';

Check warning on line 20 in homeflow/app/(onboarding)/complete.tsx

View workflow job for this annotation

GitHub Actions / Lint

'OnboardingStep' is defined but never used
import { OnboardingService } from '@/lib/services/onboarding-service';
import { notifyOnboardingComplete } from '@/hooks/use-onboarding-status';
import { ContinueButton, DevToolBar } from '@/components/onboarding';
import { ContinueButton } from '@/components/onboarding';
import { devSkipAuth } from '@/lib/dev-flags';
import { IconSymbol } from '@/components/ui/icon-symbol';

Expand Down Expand Up @@ -145,6 +145,7 @@
style={{
opacity: contentFade,
transform: [{ translateY: contentSlide }],
alignSelf: 'stretch',
}}
>
<Text style={[styles.title, { color: colors.text }]}>
Expand Down Expand Up @@ -207,7 +208,6 @@
</Animated.View>
)}

<DevToolBar currentStep={OnboardingStep.COMPLETE} onContinue={handleDevContinue} />
</SafeAreaView>
);
}
Expand Down
26 changes: 20 additions & 6 deletions homeflow/app/(onboarding)/consent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
OnboardingProgressBar,
ConsentAgreement,
ContinueButton,
DevToolBar,
} from '@/components/onboarding';
import { IconSymbol } from '@/components/ui/icon-symbol';
import { SignaturePad, type SignaturePadRef } from '@/components/ui/SignaturePad';
import { useAuth } from '@/hooks/use-auth';
import { uploadConsentPdf } from '@/src/services/consentPdfSync';

function buildConsentText(): string {
const header = [
Expand Down Expand Up @@ -95,6 +95,7 @@
const [isSubmitting, setIsSubmitting] = useState(false);
const [emailModalVisible, setEmailModalVisible] = useState(false);
const [emailAddress, setEmailAddress] = useState(user?.email ?? '');
const [scrollEnabled, setScrollEnabled] = useState(true);

const scrollViewRef = useRef<ScrollView>(null);
const signaturePadRef = useRef<SignaturePadRef>(null);
Expand All @@ -112,16 +113,29 @@
setIsSubmitting(true);

try {
// Record consent — store typed name or a drawn-signature marker
const participantName =
signatureMode === 'type' ? typedSignature.trim() : null;
const signatureValue =
signatureMode === 'type'
? typedSignature.trim()
: '[Drawn signature provided]';

// Record consent locally (source of truth for gate-keeping)
await ConsentService.recordConsent(signatureValue);

// Update onboarding
await OnboardingService.goToStep(OnboardingStep.ACCOUNT);
// Upload signed PDF to Firebase Storage + write Firestore metadata.
// Non-fatal: failure should not block the participant from proceeding.
const pdfResult = await uploadConsentPdf({
signatureType: signatureMode === 'type' ? 'typed' : 'drawn',
participantName,
signatureValue,
});
if (!pdfResult.ok) {
console.warn('[Consent] PDF upload failed (non-fatal):', pdfResult.error);
}

// Advance onboarding
await OnboardingService.goToStep(OnboardingStep.ACCOUNT);
router.push('/(onboarding)/account' as Href);
} finally {
setIsSubmitting(false);
Expand Down Expand Up @@ -187,7 +201,7 @@
};

// Dev-only handler that bypasses consent validation
const handleDevContinue = async () => {

Check warning on line 204 in homeflow/app/(onboarding)/consent.tsx

View workflow job for this annotation

GitHub Actions / Lint

'handleDevContinue' is assigned a value but never used
setIsSubmitting(true);

try {
Expand Down Expand Up @@ -224,6 +238,7 @@
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={true}
keyboardShouldPersistTaps="handled"
scrollEnabled={scrollEnabled}
>
{/* Flat consent document */}
{CONSENT_DOCUMENT.sections.map((section, index) => (
Expand Down Expand Up @@ -330,6 +345,7 @@
<SignaturePad
ref={signaturePadRef}
onChanged={setHasDrawnSignature}
onDrawingActiveChange={active => setScrollEnabled(!active)}
strokeColor={colorScheme === 'dark' ? '#FFFFFF' : '#1A1A1A'}
backgroundColor={colorScheme === 'dark' ? '#2C2C2E' : '#F9F9F9'}
height={160}
Expand Down Expand Up @@ -407,8 +423,6 @@
/>
</View>

<DevToolBar currentStep={OnboardingStep.CONSENT} onContinue={handleDevContinue} />

{/* Email address prompt modal */}
<Modal
visible={emailModalVisible}
Expand Down
Loading
Loading