Skip to content

Commit 2c8f4cb

Browse files
authored
feat(mobile): register flow + onboarding redesign (#60)
Add a RegisterScreen with email + password. Rework the final onboarding slide into a three-tier hierarchy: primary Create account, secondary Log in, tertiary Skip for now. Mirror that hierarchy on the home sheet guest state and in Settings > Account so guests can register from anywhere. Login/Register screens accept an onSuccess callback so onboarding completes after either auth path succeeds. Restores the pre-paint-mode onboarding copy (anonymous-session bullet, "use without account" wording) now that painting is available on iOS.
1 parent 471c181 commit 2c8f4cb

13 files changed

Lines changed: 596 additions & 66 deletions

mobile/lib/l10n/app_de.arb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
"loginErrorEmptyPassword": "Passwort eingeben",
1414
"loginErrorInvalid": "Ungültige Email oder ungültiges Passwort",
1515

16+
"registerTitle": "Konto erstellen",
17+
"registerSubmit": "Registrieren",
18+
"registerErrorPasswordTooShort": "Passwort muss mindestens 8 Zeichen lang sein",
19+
"registerErrorEmailTaken": "Mit dieser Email existiert bereits ein Konto",
20+
"registerErrorGeneric": "Konto konnte nicht erstellt werden. Bitte versuch es erneut.",
21+
1622
"settingsTitle": "Einstellungen",
1723
"settingsGuest": "Gast",
1824
"settingsHome": "Zuhause",
@@ -49,18 +55,21 @@
4955
"onboardingNext": "Weiter",
5056
"onboardingFinish": "Los geht's",
5157
"onboardingLogin": "Jetzt einloggen",
58+
"onboardingCreateAccount": "Registrieren",
59+
"onboardingSkip": "Später erst",
5260
"onboardingPrivacyLink": "Vollständige Datenschutzerklärung",
5361
"onboardingPrivacyTitle": "Datenschutz",
5462
"onboardingPrivacyOpenBrowser": "Im Browser öffnen",
5563
"onboardingPrivacyLoadError": "Datenschutzerklärung konnte nicht geladen werden.",
5664
"onboarding1Headline": "Male deine Lieblingsstrecken",
57-
"onboarding1Body": "Male mit dem Pinsel auf der Karte wo du gerne Rad fährst und wo du lieber fernbleiben möchtest. beebeebike plant daraus Radrouten nach deinen Wünschen.",
65+
"onboarding1Body": "Male mit dem Pinsel auf der Karte wo du gerne Rad fährst und wo es keinen Spaß macht. beebeebike plant dann Radrouten nach deinen Wünschen.",
5866
"onboarding2Headline": "Was wir speichern",
59-
"onboarding2Bullet1": "Deine Bewertungen, gespeicherten Standorte, E-Mail und Passwort-Hash liegen auf einem Hetzner-Server in Deutschland.",
60-
"onboarding2Bullet2": "Ortssuche: Deine Eingabe wird über unseren Server an den Geocoding-Dienst Photon (betrieben von der Komoot GmbH, Deutschland) weitergeleitet. Deine Konto-Daten werden dabei nicht übertragen.",
67+
"onboarding2Bullet1": "Deine Bewertungen, deine gespeicherten Standorte und — wenn du einen Account machst — deine E-Mail plus Passwort-Hash liegen auf einem Server in Deutschland.",
68+
"onboarding2Bullet2": "Ortssuche: Deine Eingabe wird über unseren Server an den Geocoding-Dienst Photon (betrieben von der Komoot GmbH, Deutschland) weitergeleitet. Konto-Daten werden dabei nicht übertragen.",
69+
"onboarding2Bullet3": "Ohne Konto bleibst du anonym — wir speichern nur eine zufällige Session-ID.",
6170
"onboarding2Bullet4": "Du kannst dein Konto jederzeit in den Einstellungen löschen. Damit werden alle serverseitig gespeicherten Daten entfernt.",
6271
"onboarding3Headline": "Am Rechner malen, am Rad fahren",
63-
"onboarding3Body": "Male deine Bewertungen am Rechner auf beebeebike.com — sie landen automatisch auf dem Handy. Zum Loslegen einloggen.",
72+
"onboarding3Body": "Du kannst beebeebike sofort anonym nutzen. Mit einem kostenlosen Konto kannst du auf beebeebike.com am Rechner schneller malen — deine Bewertungen landen automatisch auf dem Handy.",
6473

6574
"searchHint": "Wohin?",
6675
"searchSavedPlaces": "Gespeicherte Orte",

mobile/lib/l10n/app_en.arb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313
"loginErrorEmptyPassword": "Enter your password",
1414
"loginErrorInvalid": "Invalid email or password",
1515

16+
"registerTitle": "Create account",
17+
"registerSubmit": "Create account",
18+
"registerErrorPasswordTooShort": "Password must be at least 8 characters",
19+
"registerErrorEmailTaken": "An account with this email already exists",
20+
"registerErrorGeneric": "Could not create account. Please try again.",
21+
1622
"settingsTitle": "Settings",
1723
"settingsGuest": "Guest",
1824
"settingsHome": "Home",
@@ -49,18 +55,21 @@
4955
"onboardingNext": "Next",
5056
"onboardingFinish": "Let's go",
5157
"onboardingLogin": "Sign in",
58+
"onboardingCreateAccount": "Create account",
59+
"onboardingSkip": "Skip for now",
5260
"onboardingPrivacyLink": "Full privacy policy",
5361
"onboardingPrivacyTitle": "Privacy",
5462
"onboardingPrivacyOpenBrowser": "Open in browser",
5563
"onboardingPrivacyLoadError": "Could not load the privacy policy.",
5664
"onboarding1Headline": "Paint your favourite routes",
5765
"onboarding1Body": "Paint on the map where you like to ride and where you'd rather avoid. beebeebike turns that into bike routes that match your taste.",
5866
"onboarding2Headline": "What we store",
59-
"onboarding2Bullet1": "Your ratings, saved places, email and password hash live on a Hetzner server in Germany.",
60-
"onboarding2Bullet2": "Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). Your account data is not sent along.",
67+
"onboarding2Bullet1": "Your ratings, saved places and — if you register an account — your email plus a password hash live on a server in Germany.",
68+
"onboarding2Bullet2": "Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). No account data is sent along.",
69+
"onboarding2Bullet3": "Without an account you stay anonymous — we only set a random session ID.",
6170
"onboarding2Bullet4": "You can delete your account anytime in Settings. All server-side data is removed with it.",
6271
"onboarding3Headline": "Paint on the desktop, ride with your phone",
63-
"onboarding3Body": "Paint your ratings on beebeebike.com in the browser — they sync to your phone automatically. Sign in to get started.",
72+
"onboarding3Body": "You can use beebeebike right away anonymously. With a free account you can paint faster on beebeebike.com in the browser — your ratings sync to the phone automatically.",
6473

6574
"searchHint": "Where to?",
6675
"searchSavedPlaces": "Saved places",

mobile/lib/l10n/generated/app_localizations.dart

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,36 @@ abstract class AppLocalizations {
152152
/// **'Invalid email or password'**
153153
String get loginErrorInvalid;
154154

155+
/// No description provided for @registerTitle.
156+
///
157+
/// In en, this message translates to:
158+
/// **'Create account'**
159+
String get registerTitle;
160+
161+
/// No description provided for @registerSubmit.
162+
///
163+
/// In en, this message translates to:
164+
/// **'Create account'**
165+
String get registerSubmit;
166+
167+
/// No description provided for @registerErrorPasswordTooShort.
168+
///
169+
/// In en, this message translates to:
170+
/// **'Password must be at least 8 characters'**
171+
String get registerErrorPasswordTooShort;
172+
173+
/// No description provided for @registerErrorEmailTaken.
174+
///
175+
/// In en, this message translates to:
176+
/// **'An account with this email already exists'**
177+
String get registerErrorEmailTaken;
178+
179+
/// No description provided for @registerErrorGeneric.
180+
///
181+
/// In en, this message translates to:
182+
/// **'Could not create account. Please try again.'**
183+
String get registerErrorGeneric;
184+
155185
/// No description provided for @settingsTitle.
156186
///
157187
/// In en, this message translates to:
@@ -344,6 +374,18 @@ abstract class AppLocalizations {
344374
/// **'Sign in'**
345375
String get onboardingLogin;
346376

377+
/// No description provided for @onboardingCreateAccount.
378+
///
379+
/// In en, this message translates to:
380+
/// **'Create account'**
381+
String get onboardingCreateAccount;
382+
383+
/// No description provided for @onboardingSkip.
384+
///
385+
/// In en, this message translates to:
386+
/// **'Skip for now'**
387+
String get onboardingSkip;
388+
347389
/// No description provided for @onboardingPrivacyLink.
348390
///
349391
/// In en, this message translates to:
@@ -389,15 +431,21 @@ abstract class AppLocalizations {
389431
/// No description provided for @onboarding2Bullet1.
390432
///
391433
/// In en, this message translates to:
392-
/// **'Your ratings, saved places, email and password hash live on a Hetzner server in Germany.'**
434+
/// **'Your ratings, saved places and — only with an account — your email plus a password hash live on a Hetzner server in Germany.'**
393435
String get onboarding2Bullet1;
394436

395437
/// No description provided for @onboarding2Bullet2.
396438
///
397439
/// In en, this message translates to:
398-
/// **'Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). Your account data is not sent along.'**
440+
/// **'Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). No account data is sent along.'**
399441
String get onboarding2Bullet2;
400442

443+
/// No description provided for @onboarding2Bullet3.
444+
///
445+
/// In en, this message translates to:
446+
/// **'Without an account you stay anonymous — we only set a random session ID.'**
447+
String get onboarding2Bullet3;
448+
401449
/// No description provided for @onboarding2Bullet4.
402450
///
403451
/// In en, this message translates to:
@@ -413,7 +461,7 @@ abstract class AppLocalizations {
413461
/// No description provided for @onboarding3Body.
414462
///
415463
/// In en, this message translates to:
416-
/// **'Paint your ratings on beebeebike.com in the browser — they sync to your phone automatically. Sign in to get started.'**
464+
/// **'You can use beebeebike right away without an account. With a free account you can paint faster on beebeebike.com in the browser — your ratings sync to the phone automatically.'**
417465
String get onboarding3Body;
418466

419467
/// No description provided for @searchHint.

mobile/lib/l10n/generated/app_localizations_de.dart

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ class AppLocalizationsDe extends AppLocalizations {
3535
@override
3636
String get loginErrorInvalid => 'Ungültige Email oder ungültiges Passwort';
3737

38+
@override
39+
String get registerTitle => 'Konto erstellen';
40+
41+
@override
42+
String get registerSubmit => 'Registrieren';
43+
44+
@override
45+
String get registerErrorPasswordTooShort =>
46+
'Passwort muss mindestens 8 Zeichen lang sein';
47+
48+
@override
49+
String get registerErrorEmailTaken =>
50+
'Mit dieser Email existiert bereits ein Konto';
51+
52+
@override
53+
String get registerErrorGeneric =>
54+
'Konto konnte nicht erstellt werden. Bitte versuch es erneut.';
55+
3856
@override
3957
String get settingsTitle => 'Einstellungen';
4058

@@ -136,6 +154,12 @@ class AppLocalizationsDe extends AppLocalizations {
136154
@override
137155
String get onboardingLogin => 'Jetzt einloggen';
138156

157+
@override
158+
String get onboardingCreateAccount => 'Registrieren';
159+
160+
@override
161+
String get onboardingSkip => 'Später erst';
162+
139163
@override
140164
String get onboardingPrivacyLink => 'Vollständige Datenschutzerklärung';
141165

@@ -161,11 +185,15 @@ class AppLocalizationsDe extends AppLocalizations {
161185

162186
@override
163187
String get onboarding2Bullet1 =>
164-
'Deine Bewertungen, gespeicherten Standorte, E-Mail und Passwort-Hash liegen auf einem Hetzner-Server in Deutschland.';
188+
'Deine Bewertungen, deine gespeicherten Standorte und — nur mit Konto — deine E-Mail plus Passwort-Hash liegen auf einem Hetzner-Server in Deutschland.';
165189

166190
@override
167191
String get onboarding2Bullet2 =>
168-
'Ortssuche: Deine Eingabe wird über unseren Server an den Geocoding-Dienst Photon (betrieben von der Komoot GmbH, Deutschland) weitergeleitet. Deine Konto-Daten werden dabei nicht übertragen.';
192+
'Ortssuche: Deine Eingabe wird über unseren Server an den Geocoding-Dienst Photon (betrieben von der Komoot GmbH, Deutschland) weitergeleitet. Konto-Daten werden dabei nicht übertragen.';
193+
194+
@override
195+
String get onboarding2Bullet3 =>
196+
'Ohne Konto bleibst du anonym — wir setzen nur eine zufällige Sitzungs-ID.';
169197

170198
@override
171199
String get onboarding2Bullet4 =>
@@ -176,7 +204,7 @@ class AppLocalizationsDe extends AppLocalizations {
176204

177205
@override
178206
String get onboarding3Body =>
179-
'Male deine Bewertungen am Rechner auf beebeebike.com — sie landen automatisch auf dem Handy. Zum Loslegen einloggen.';
207+
'Du kannst beebeebike sofort ohne Konto nutzen. Mit einem kostenlosen Konto kannst du auf beebeebike.com am Rechner schneller malen — deine Bewertungen landen automatisch auf dem Handy.';
180208

181209
@override
182210
String get searchHint => 'Wohin?';

mobile/lib/l10n/generated/app_localizations_en.dart

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,24 @@ class AppLocalizationsEn extends AppLocalizations {
3535
@override
3636
String get loginErrorInvalid => 'Invalid email or password';
3737

38+
@override
39+
String get registerTitle => 'Create account';
40+
41+
@override
42+
String get registerSubmit => 'Create account';
43+
44+
@override
45+
String get registerErrorPasswordTooShort =>
46+
'Password must be at least 8 characters';
47+
48+
@override
49+
String get registerErrorEmailTaken =>
50+
'An account with this email already exists';
51+
52+
@override
53+
String get registerErrorGeneric =>
54+
'Could not create account. Please try again.';
55+
3856
@override
3957
String get settingsTitle => 'Settings';
4058

@@ -135,6 +153,12 @@ class AppLocalizationsEn extends AppLocalizations {
135153
@override
136154
String get onboardingLogin => 'Sign in';
137155

156+
@override
157+
String get onboardingCreateAccount => 'Create account';
158+
159+
@override
160+
String get onboardingSkip => 'Skip for now';
161+
138162
@override
139163
String get onboardingPrivacyLink => 'Full privacy policy';
140164

@@ -159,11 +183,15 @@ class AppLocalizationsEn extends AppLocalizations {
159183

160184
@override
161185
String get onboarding2Bullet1 =>
162-
'Your ratings, saved places, email and password hash live on a Hetzner server in Germany.';
186+
'Your ratings, saved places and — only with an account — your email plus a password hash live on a Hetzner server in Germany.';
163187

164188
@override
165189
String get onboarding2Bullet2 =>
166-
'Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). Your account data is not sent along.';
190+
'Place search: your query is forwarded through our server to the Photon geocoder (run by Komoot GmbH, Germany). No account data is sent along.';
191+
192+
@override
193+
String get onboarding2Bullet3 =>
194+
'Without an account you stay anonymous — we only set a random session ID.';
167195

168196
@override
169197
String get onboarding2Bullet4 =>
@@ -175,7 +203,7 @@ class AppLocalizationsEn extends AppLocalizations {
175203

176204
@override
177205
String get onboarding3Body =>
178-
'Paint your ratings on beebeebike.com in the browser — they sync to your phone automatically. Sign in to get started.';
206+
'You can use beebeebike right away without an account. With a free account you can paint faster on beebeebike.com in the browser — your ratings sync to the phone automatically.';
179207

180208
@override
181209
String get searchHint => 'Where to?';

mobile/lib/screens/login_screen.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import '../l10n/generated/app_localizations.dart';
44
import '../widgets/login_form.dart';
55

66
class LoginScreen extends StatelessWidget {
7-
const LoginScreen({super.key});
7+
const LoginScreen({super.key, this.onSuccess});
8+
9+
final VoidCallback? onSuccess;
810

911
@override
1012
Widget build(BuildContext context) {
@@ -14,7 +16,10 @@ class LoginScreen extends StatelessWidget {
1416
body: Padding(
1517
padding: const EdgeInsets.all(24),
1618
child: LoginForm(
17-
onSuccess: () => Navigator.of(context).pop(),
19+
onSuccess: () {
20+
Navigator.of(context).pop();
21+
onSuccess?.call();
22+
},
1823
),
1924
),
2025
);

0 commit comments

Comments
 (0)