Onboarding flow

This commit is contained in:
2026-07-06 22:25:52 +02:00
parent 99cd885833
commit 6b57a2acfc
37 changed files with 1503 additions and 507 deletions

View File

@@ -29,7 +29,7 @@ import { IdentificationResult, PlantHealthCheck } from '../../types';
const MOCK_ACCOUNT_STORE_KEY = 'greenlens_mock_backend_accounts_v1';
const MOCK_IDEMPOTENCY_STORE_KEY = 'greenlens_mock_backend_idempotency_v1';
const FREE_MONTHLY_CREDITS = 0;
const FREE_MONTHLY_CREDITS = 3;
const GUEST_TRIAL_CREDITS = 0;
const TRIAL_MONTHLY_CREDITS = 30;
const PRO_MONTHLY_CREDITS = 100;
@@ -827,38 +827,56 @@ export const mockBackendService = {
};
}
let creditsCharged = 0;
const modelPath: string[] = [];
creditsCharged += consumeCreditsWithIdempotency(
account,
stores.idempotency,
chargeKey('scan-primary', request.userId, request.idempotencyKey),
SCAN_PRIMARY_COST,
);
let creditsCharged = 0;
const modelPath: string[] = [];
if (request.userId === 'guest') {
modelPath.push('guest-demo-no-credit');
} else {
creditsCharged += consumeCreditsWithIdempotency(
account,
stores.idempotency,
chargeKey('scan-primary', request.userId, request.idempotencyKey),
SCAN_PRIMARY_COST,
);
}
let usedOpenAi = false;
let result: IdentificationResult = getMockPlantByImage(request.imageUri, request.language, false);
if (openAiScanService.isConfigured()) {
const openAiPrimary = await openAiScanService.identifyPlant(
request.imageUri,
request.language,
'primary',
account.plan === 'pro' ? 'pro' : 'free',
);
if (openAiPrimary) {
result = openAiPrimary;
usedOpenAi = true;
modelPath.push('openai-primary');
} else {
result = getMockPlantByImage(request.imageUri, request.language, false);
modelPath.push('openai-primary-failed');
modelPath.push('mock-primary-fallback');
}
} else {
modelPath.push('mock-primary');
}
if (openAiScanService.isConfigured()) {
const openAiPrimary = await openAiScanService.identifyPlant(
request.imageUri,
request.language,
'primary',
'pro',
);
if (openAiPrimary) {
result = openAiPrimary;
usedOpenAi = true;
modelPath.push('openai-primary');
} else {
if (request.userId === 'guest') {
throw new BackendApiError(
'PROVIDER_ERROR',
'AI demo scan failed. Please try again with a clearer plant photo.',
502,
);
}
result = getMockPlantByImage(request.imageUri, request.language, false);
modelPath.push('openai-primary-failed');
modelPath.push('mock-primary-fallback');
}
} else {
if (request.userId === 'guest') {
throw new BackendApiError(
'PROVIDER_ERROR',
'AI demo scan is unavailable. Please configure OpenAI before enabling guest demo scans.',
502,
);
}
modelPath.push('mock-primary');
}
const shouldReview = result.confidence < LOW_CONFIDENCE_REVIEW_THRESHOLD;
if (shouldReview && account.plan === 'pro') {

View File

@@ -7,6 +7,7 @@ export type PreAuthAnswers = {
acquisitionSource?: string;
primaryGoal?: string;
experienceLevel?: string;
lightLevel?: string;
};
export const PreAuthOnboardingService = {