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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Profile current phase section for the authenticated `/profile` tab, reusing the bootstrap profile phase snapshot plus aggregate statistics frequency summary to render the read-only phase block without a standalone phase slice.
- Introduce personal parameters section for the authenticated `/profile` tab, including canonical `user-parameters` read/update flow, editable profile form card, weekly-goal save support, and selective workouts overview refresh when goal, equipment, or level changes regenerate the personal plan.
- Add profile bottom section for the authenticated `/profile` tab, including logout and delete-profile confirmation actions plus direct links to the bundled legal documents.
- Sign-up page now redirects users with unverified emails to the verify-email screen: shows a brief non-dismissible feedback dialog, then automatically pushes the verify-email route after 2 seconds, matching the existing sign-in behavior.
- Profile subscription section for the authenticated `/profile` tab, including active and empty subscription states, catalog entrypoints, profile-local subscription card hydration by `subscriptionId`, cancel-subscription confirmation flow and profile page refresh after cancellation.
- Profile saved cards section for the authenticated `/profile` tab, including dedicated cards API/repository flow, saved-cards list rendering, add-card dialog with manual card form, default-card command, delete-card confirmation, and local refresh after successful actions.
- Authenticated subscriptions catalog screen, including dedicated subscriptions route, catalog Cubit, card UI with normalized remote images, and a profile CTA for opening available subscription plans.
Expand Down
49 changes: 44 additions & 5 deletions lib/features/auth/presentation/pages/sign_up_page.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import 'dart:async';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

import '../../../../core/constants/app_strings.dart';
import '../../../../core/failures/feature/auth/auth_failure.dart';
import '../../../../core/router/router_paths.dart';
import '../../../../uikit/buttons/button_state.dart';
import '../../../../uikit/buttons/main_button.dart';
Expand Down Expand Up @@ -36,14 +39,48 @@ class _SignUpPageState extends State<SignUpPage> {

bool _isAgree = false;

NavigatorState? _rootNavigator;
Timer? _redirectTimer;

@override
void didChangeDependencies() {
super.didChangeDependencies();
_rootNavigator ??= Navigator.of(context, rootNavigator: true);
}

@override
void dispose() {
_redirectTimer?.cancel();
_nameController.dispose();
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}

void _redirectUnverifiedUser({required String dialogMessage}) {
if (_redirectTimer != null) return;

showAppFeedbackDialog<void>(
context,
title: AppStrings.feedbackErrorTitle,
message: dialogMessage,
isBarrierDismissible: false,
);

_redirectTimer = Timer(const Duration(seconds: 2), () {
_redirectTimer = null;
if (!mounted) return;
_rootNavigator?.pop();
context.push(
AppRoutePaths.verifyEmailPath,
extra: VerifyEmailRouteArgs(
email: _emailController.text.trim(),
resendOnOpen: true,
),
);
});
}

void _submit() {
final form = _formKey.currentState;
if (form == null || !form.validate()) {
Expand Down Expand Up @@ -82,11 +119,13 @@ class _SignUpPageState extends State<SignUpPage> {
},
failed: (failure) {
if (failure.message.isNotEmpty) {
showAppFeedbackDialog(
context,
title: AppStrings.feedbackErrorTitle,
message: failure.message,
);
failure is EmailNotVerifiedFailure
? _redirectUnverifiedUser(dialogMessage: failure.message)
: showAppFeedbackDialog(
context,
title: AppStrings.feedbackErrorTitle,
message: failure.message,
);
}
},
);
Expand Down
Loading