Onboarding
This commit is contained in:
@@ -31,15 +31,26 @@ export const initDatabase = (): void => {
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_settings (
|
||||
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
language TEXT NOT NULL DEFAULT 'de',
|
||||
language_set INTEGER NOT NULL DEFAULT 0,
|
||||
appearance_mode TEXT NOT NULL DEFAULT 'system',
|
||||
color_palette TEXT NOT NULL DEFAULT 'forest',
|
||||
profile_image TEXT,
|
||||
onboarding_done INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS user_settings (
|
||||
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
language TEXT NOT NULL DEFAULT 'de',
|
||||
language_set INTEGER NOT NULL DEFAULT 0,
|
||||
appearance_mode TEXT NOT NULL DEFAULT 'system',
|
||||
color_palette TEXT NOT NULL DEFAULT 'forest',
|
||||
profile_image TEXT,
|
||||
onboarding_done INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user_onboarding_profile (
|
||||
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
acquisition_source TEXT,
|
||||
primary_goal TEXT,
|
||||
experience_level TEXT,
|
||||
lexicon_explored INTEGER NOT NULL DEFAULT 0,
|
||||
customization_done INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS plants (
|
||||
id TEXT PRIMARY KEY,
|
||||
@@ -193,7 +204,81 @@ export const SettingsDb = {
|
||||
|
||||
// ─── Plants ────────────────────────────────────────────────────────────────────
|
||||
|
||||
const DEFAULT_CARE_INFO: CareInfo = {
|
||||
export const OnboardingProfileDb = {
|
||||
get(userId: number) {
|
||||
const db = getDb();
|
||||
db.runSync('INSERT OR IGNORE INTO user_onboarding_profile (user_id) VALUES (?)', [userId]);
|
||||
return db.getFirstSync<{
|
||||
acquisition_source: string | null;
|
||||
primary_goal: string | null;
|
||||
experience_level: string | null;
|
||||
lexicon_explored: number;
|
||||
customization_done: number;
|
||||
}>('SELECT * FROM user_onboarding_profile WHERE user_id = ?', [userId])!;
|
||||
},
|
||||
|
||||
setAcquisitionSource(userId: number, source: string) {
|
||||
const db = getDb();
|
||||
db.runSync(
|
||||
`INSERT INTO user_onboarding_profile (user_id, acquisition_source, updated_at)
|
||||
VALUES (?, ?, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
acquisition_source = excluded.acquisition_source,
|
||||
updated_at = datetime('now')`,
|
||||
[userId, source],
|
||||
);
|
||||
},
|
||||
|
||||
setPrimaryGoal(userId: number, goal: string) {
|
||||
const db = getDb();
|
||||
db.runSync(
|
||||
`INSERT INTO user_onboarding_profile (user_id, primary_goal, updated_at)
|
||||
VALUES (?, ?, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
primary_goal = excluded.primary_goal,
|
||||
updated_at = datetime('now')`,
|
||||
[userId, goal],
|
||||
);
|
||||
},
|
||||
|
||||
setExperienceLevel(userId: number, level: string) {
|
||||
const db = getDb();
|
||||
db.runSync(
|
||||
`INSERT INTO user_onboarding_profile (user_id, experience_level, updated_at)
|
||||
VALUES (?, ?, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
experience_level = excluded.experience_level,
|
||||
updated_at = datetime('now')`,
|
||||
[userId, level],
|
||||
);
|
||||
},
|
||||
|
||||
setLexiconExplored(userId: number, explored: boolean) {
|
||||
const db = getDb();
|
||||
db.runSync(
|
||||
`INSERT INTO user_onboarding_profile (user_id, lexicon_explored, updated_at)
|
||||
VALUES (?, ?, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
lexicon_explored = excluded.lexicon_explored,
|
||||
updated_at = datetime('now')`,
|
||||
[userId, explored ? 1 : 0],
|
||||
);
|
||||
},
|
||||
|
||||
setCustomizationDone(userId: number, done: boolean) {
|
||||
const db = getDb();
|
||||
db.runSync(
|
||||
`INSERT INTO user_onboarding_profile (user_id, customization_done, updated_at)
|
||||
VALUES (?, ?, datetime('now'))
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
customization_done = excluded.customization_done,
|
||||
updated_at = datetime('now')`,
|
||||
[userId, done ? 1 : 0],
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const DEFAULT_CARE_INFO: CareInfo = {
|
||||
waterIntervalDays: 7,
|
||||
light: 'Bright indirect light',
|
||||
temp: '18-25 C',
|
||||
|
||||
44
services/onboardingProgressService.ts
Normal file
44
services/onboardingProgressService.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { OnboardingProfileDb } from './database';
|
||||
|
||||
export type PersistentOnboardingStep = 'lexicon' | 'customize';
|
||||
|
||||
export const OnboardingProgressService = {
|
||||
isStepCompleted(userId: number, step: PersistentOnboardingStep): boolean {
|
||||
const profile = OnboardingProfileDb.get(userId);
|
||||
return step === 'lexicon'
|
||||
? profile.lexicon_explored === 1
|
||||
: profile.customization_done === 1;
|
||||
},
|
||||
|
||||
completeStep(userId: number, step: PersistentOnboardingStep): void {
|
||||
if (step === 'lexicon') {
|
||||
OnboardingProfileDb.setLexiconExplored(userId, true);
|
||||
return;
|
||||
}
|
||||
OnboardingProfileDb.setCustomizationDone(userId, true);
|
||||
},
|
||||
|
||||
getSignals(userId: number) {
|
||||
const profile = OnboardingProfileDb.get(userId);
|
||||
return {
|
||||
lexiconExplored: profile.lexicon_explored === 1,
|
||||
customizationDone: profile.customization_done === 1,
|
||||
};
|
||||
},
|
||||
|
||||
getAcquisitionSource(userId: number): string | null {
|
||||
return OnboardingProfileDb.get(userId).acquisition_source;
|
||||
},
|
||||
|
||||
setAcquisitionSource(userId: number, source: string): void {
|
||||
OnboardingProfileDb.setAcquisitionSource(userId, source);
|
||||
},
|
||||
|
||||
setPrimaryGoal(userId: number, goal: string): void {
|
||||
OnboardingProfileDb.setPrimaryGoal(userId, goal);
|
||||
},
|
||||
|
||||
setExperienceLevel(userId: number, level: string): void {
|
||||
OnboardingProfileDb.setExperienceLevel(userId, level);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user