Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3396a29
Merge remote-tracking branch 'origin/feature/custom-text-field' into …
ABDULLAHHG Jan 16, 2026
fffa0a4
Merge remote-tracking branch 'origin/dev' into test/create-account
ABDULLAHHG Jan 18, 2026
4f2c157
Merge remote-tracking branch 'refs/remotes/origin/dev' into test/crea…
ABDULLAHHG Jan 18, 2026
2dccf8d
Merge remote-tracking branch 'refs/remotes/origin/dev' into test/crea…
ABDULLAHHG Jan 18, 2026
c7bdf7a
Merge remote-tracking branch 'refs/remotes/origin/dev' into test/crea…
ABDULLAHHG Jan 20, 2026
bacb269
Merge remote-tracking branch 'refs/remotes/origin/dev' into test/crea…
ABDULLAHHG Jan 20, 2026
9905ed8
feat: add email to User entity
ABDULLAHHG Jan 20, 2026
645c7a1
feat: add authentication validator
ABDULLAHHG Jan 20, 2026
9aa80ce
feat: add create account cubit
ABDULLAHHG Jan 20, 2026
805d7cd
feat: add create account screen
ABDULLAHHG Jan 20, 2026
3d1e821
feat: add create account state
ABDULLAHHG Jan 20, 2026
3595aba
feat: add register method to AuthenticationRepository
ABDULLAHHG Jan 20, 2026
f24a354
feat: implement AuthenticationRepository
ABDULLAHHG Jan 20, 2026
8e489d8
feat: set app bar background color
ABDULLAHHG Jan 20, 2026
9a9b741
feat: add square lock, mail, and user icons
ABDULLAHHG Jan 20, 2026
1fd3d6d
feat: add create account dependencies
ABDULLAHHG Jan 20, 2026
5b64b5d
feat: add uuid dependency
ABDULLAHHG Jan 20, 2026
0904f4e
feat: add create account localization
ABDULLAHHG Jan 21, 2026
d4f7128
refactor: change user id type from int to String
ABDULLAHHG Jan 21, 2026
03c831a
feat: use gitIt instead of context.read
ABDULLAHHG Jan 23, 2026
9721d78
Merge remote-tracking branch 'origin/dev' into feature/create-account
ABDULLAHHG Jan 23, 2026
f6270ad
feat: add is_complete field to user sign up data
ABDULLAHHG Jan 25, 2026
307b36c
refactor: reorder name and email fields
ABDULLAHHG Jan 25, 2026
dfa5231
Merge remote-tracking branch 'refs/remotes/origin/dev' into feature/c…
ABDULLAHHG Jan 25, 2026
221b277
chore: add trailing comma in app_ar.arb
ABDULLAHHG Jan 25, 2026
3ea54c5
Merge remote-tracking branch 'refs/remotes/origin/dev' into feature/c…
ABDULLAHHG Jan 27, 2026
8cc18ea
resolve conflict
ABDULLAHHG Jan 27, 2026
8ba755a
Merge remote-tracking branch 'refs/remotes/origin/dev' into feature/c…
ABDULLAHHG Jan 28, 2026
6280f53
Merge remote-tracking branch 'origin/dev' into feature/create-account
ABDULLAHHG Jan 28, 2026
506672b
feat: add create account route
ABDULLAHHG Jan 30, 2026
97826f9
feat: implement navigation to create account screen
ABDULLAHHG Jan 30, 2026
8015f3e
feat: handle create account errors and display snackbar
ABDULLAHHG Jan 30, 2026
d88c79f
Merge remote-tracking branch 'origin/dev' into feature/create-account
ABDULLAHHG Jan 30, 2026
2782c54
refactor: rename l10n to localizations for consistency
ABDULLAHHG Jan 30, 2026
c15f85b
feat: add spending trend localization strings
ABDULLAHHG Jan 30, 2026
8e000c7
refactor: rename email icon asset for consistency
ABDULLAHHG Jan 30, 2026
e58ffa6
fix: di error
ABDULLAHHG Jan 31, 2026
194f1bc
Merge remote-tracking branch 'refs/remotes/origin/dev' into feature/c…
ABDULLAHHG Feb 5, 2026
542aa1f
resolve conflict
ABDULLAHHG Feb 5, 2026
d82eb42
Merge remote-tracking branch 'origin/dev' into feature/create-account
ABDULLAHHG Feb 8, 2026
d251773
feat: add log to the register error
ABDULLAHHG Feb 10, 2026
e3e0d0f
Merge remote-tracking branch 'refs/remotes/origin/dev' into feature/c…
ABDULLAHHG Feb 10, 2026
d77b144
resolve conflict
ABDULLAHHG Feb 10, 2026
54fd22d
resolve conflict
ABDULLAHHG Feb 10, 2026
018b6ed
Merge remote-tracking branch 'origin/dev' into feature/create-account
ABDULLAHHG Feb 11, 2026
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
3 changes: 3 additions & 0 deletions assets/icons/ic_heroicons_outline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/icons/ic_mail.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions assets/icons/ic_square_lock.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions assets/icons/ic_user_square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 20 additions & 13 deletions lib/core/l10n/app_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,31 @@
"moneyAmount": "{amount} {currency} ",
"date": "التاريخ",
"setUpYourAccount": "لنقم بإعداد حسابك",
"setSalary": "تحديد الراتب",
"currency": "العملة",
"salaryDay": "يوم الراتب",
"fromEachMonth": "من كل شهر",
"salary": "الراتب",
"accountSetup": "إعداد الحساب",
"search": "...بحث",
"select": "اختيار",
"next": "التالي",
"finishSetup": "إنهاء الإعداد",
"stepOf": "الخطوة {current} من {total}",
"stepOfTotal": "الخطوة {current} من {total}",
"setSalary": "تحديد الراتب",
"currency": "العملة",
"salaryDay": "يوم الراتب",
"fromEachMonth": "من كل شهر",
"salary": "الراتب",
"accountSetup": "إعداد الحساب",
"search": "...بحث",
"select": "اختيار",
"next": "التالي",
"finishSetup": "إنهاء الإعداد",
"stepOf": "الخطوة {current} من {total}",
"stepOfTotal": "الخطوة {current} من {total}",
"createAccount": "إنشاء حساب",
"createNewAccount": "إنشاء حساب جديد",
"startTakingControl": "ابدأ بالتحكم في أموالك",
"email": "البريد الإلكتروني",
"name": "الاسم",
"password": "كلمة المرور",
"passwordLimit": "*استخدم 8 أحرف على الأقل، وتأكد من وجود حرف كبير ورمز واحد على الأقل.",
"create": "إنشاء حساب",
"forgetPasswordAppBarTitle": "نسيت كلمة السر",
"forgetPasswordTitle": "نسيت كلمة المرور الخاصة بك",
"forgetPasswordSubtitle": "أدخل بريدك الإلكتروني وسنرسل لك رابطًا لإعادة التعيين",
"forgetPasswordEmailHint": "البريد الإلكتروني",
"forgetPasswordButton": "إرسال رابط إعادة التعيين",

"updatePasswordAppBarTitle": "تحديث كلمة المرور",
"updatePasswordTitle": "أدخل كلمة مرور جديدة لـ",
"updatePasswordPasswordHint": "كلمة المرور الجديدة",
Expand Down
32 changes: 24 additions & 8 deletions lib/core/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,43 @@
"next": "Next",
"finishSetup": "Finish setup",
"stepOf": "Step {current} of {total}",
"stepOfTotal": "Step {current} of {total}",
"@stepOfTotal": {
"placeholders": {
"current": {},
"total": {}
}
"@stepOf": {
"placeholders": {
"current": {
"type": "int"
},
"total": {
"type": "int"
}
}
},
"stepOfTotal": "Step {current} of {total}",
"@stepOfTotal": {
"placeholders": {
"current": {},
"total": {}
}
},
"createAccount": "Create Account",
"createNewAccount": "Create new account",
"startTakingControl": "Start taking control of your money",
"email": "Email",
"name": "Name",
"password": "Password",
"passwordLimit": "*Use at least 8 characters, Contain at least one capital letter and one symbol.",
"create": "Create",
"forgetPasswordAppBarTitle": "Forget Password",
"forgetPasswordTitle": "Forget your password",
"forgetPasswordSubtitle": "Enter your email and we’ll send you a reset link",
"forgetPasswordEmailHint": "Email",
"forgetPasswordButton": "Send Reset Link",

"updatePasswordAppBarTitle": "Update Password",
"updatePasswordTitle": "Enter a new password for",
"updatePasswordPasswordHint": "New Password",
"updatePasswordConfirmHint": "Confirm New Password",
"updatePasswordButton": "Update Password",
"updatePasswordSuccessMessage": "Password updated successfully",
"updatePasswordErrorMessage": "Error updating password",

"error": "Error",
"success" : "Success",
"loading" : "Loading",
Expand Down
32 changes: 29 additions & 3 deletions lib/data/repository/authentication_repository.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import 'dart:developer';

import 'package:flutter/foundation.dart';
Expand All @@ -9,8 +8,8 @@ import '../../core/constants/app_constants.dart';
import '../../core/errors/error_model.dart';
import '../../core/errors/result.dart';
import '../../core/errors/supabase_auth_error.dart';
import '../../domain/repository/authentication_repository.dart';
import '../../domain/entity/user.dart';
import '../../domain/repository/authentication_repository.dart';
import '../service/app_secrets_provider.dart';
import '../service/supabase_service.dart';

Expand All @@ -23,6 +22,31 @@ class AuthenticationRepositoryImpl implements AuthenticationRepository {
required this.appSecrets,
});

@override
Future<Result<void>> register(User user, String password) async {
try {
final client = await supabaseService.getClient();
final response = await client.auth.signUp(
email: user.email,
password: password,
data: {"name": user.name, "is_complete": false},
);

if (response.user != null) {
return Result.success(null);
} else {
return Result.error(ErrorModel('User data is null'));
}
} on AuthException catch (error) {
return Result.error(SupabaseAuthError.fromAuthException(error));
} catch (error) {
if (kDebugMode) {
print('Caught error during register: $error');
}
rethrow;
}
}

@override
void signInWithGoogle() async {
try {
Expand Down Expand Up @@ -62,6 +86,7 @@ class AuthenticationRepositoryImpl implements AuthenticationRepository {
static const String _googleWebClientId = "GOOGLE_WEB_CLIENT_ID";
static const String _googleIosClientId = "GOOGLE_IOS_CLIENT_ID";
static const List<String> _googleScopes = ['email', 'profile', 'openid'];

@override
Stream<AuthState> get onAuthStateChange {
final supabaseClientFuture = supabaseService.getClient();
Expand All @@ -78,6 +103,7 @@ class AuthenticationRepositoryImpl implements AuthenticationRepository {
redirectTo: AppConstants.resetPasswordRedirect,
);
}

@override
Future<void> updatePassword(String password) async {
final client = await supabaseService.getClient();
Expand Down Expand Up @@ -111,4 +137,4 @@ class AuthenticationRepositoryImpl implements AuthenticationRepository {
return Result.error(ErrorModel(error.toString()));
}
}
}
}
3 changes: 2 additions & 1 deletion lib/design_system/assets/app_assets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ class AppAssets {
static const String eyeClose = "$_icons/ic_eye_close.svg";
static const String eyeOpen = "$_icons/ic_eye_open.svg";
static const String lock = "$_icons/ic_lock.svg";
static const String email = "$_icons/ic_email.svg";
static const String google = "$_icons/ic_google.svg";
static const String icSquareLock = '$_icons/ic_square_lock.svg';
static const String icUser = '$_icons/ic_user_square.svg';
static const icMoneyAmount = '$_icons/ic_money_amount.svg';
static const String imgForgetPasswordLock = "$_icons/img_forget_password_lock.png";
static const String icEmail = "$_icons/ic_email.svg";
Expand Down
8 changes: 7 additions & 1 deletion lib/di/injection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import '../domain/repository/account_repository.dart';
import '../domain/repository/authentication_repository.dart';
import '../domain/repository/user_money_repository.dart';
import '../domain/validator/authentication_validator.dart';
import '../presentation/createAccount/cubit/create_account_cubit.dart';
import '../presentation/home/cubit/home_cubit.dart';
import '../presentation/income/cubit/add_income_cubit.dart';
import '../presentation/login/cubit/login_cubit.dart';
Expand All @@ -25,7 +26,6 @@ void initDI() {
() => SupabaseService(appSecretsProvider: getIt<AppSecretsProvider>()),
);


getIt.registerLazySingleton<AuthenticationRepository>(
() => AuthenticationRepositoryImpl(
supabaseService: getIt<SupabaseService>(),
Expand Down Expand Up @@ -69,4 +69,10 @@ void initDI() {
() =>
TransactionCubit(transactionRepository: getIt<TransactionRepository>()),
);
getIt.registerFactory<CreateAccountCubit>(
() => CreateAccountCubit(
getIt<AuthenticationValidator>(),
getIt<AuthenticationRepository>(),
),
);
}
2 changes: 1 addition & 1 deletion lib/domain/entity/user.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class User {
final String id;
final String email;
final String name;
final String email;

const User({
required this.id,
Expand Down
3 changes: 3 additions & 0 deletions lib/domain/repository/authentication_repository.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import '../entity/user.dart' as user_entity;

import 'dart:async';

import 'package:supabase_flutter/supabase_flutter.dart' hide User;
Expand All @@ -6,6 +8,7 @@ import '../../core/errors/result.dart';
import '../../domain/entity/user.dart';

abstract class AuthenticationRepository {
Future<Result<void>> register(user_entity.User user, String password);
void signInWithGoogle();
Future<void> resetPasswordForEmail(String email);

Expand Down
5 changes: 1 addition & 4 deletions lib/domain/validator/authentication_validator.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
class AuthenticationValidator {
bool isEmailValid(String email) {
return email.trim().isNotEmpty &&
RegExp(
r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$',
).hasMatch(email);
return email.trim().isNotEmpty && RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$').hasMatch(email);
}

bool isPasswordValid(String password) {
Expand Down
64 changes: 64 additions & 0 deletions lib/presentation/createAccount/cubit/create_account_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:moneyplus/domain/repository/authentication_repository.dart';

import '../../../domain/validator/authentication_validator.dart';
import 'create_account_state.dart';

class CreateAccountCubit extends Cubit<CreateAccountState> {
final AuthenticationValidator _validator;
final AuthenticationRepository _authenticationRepository;

CreateAccountCubit(this._validator, this._authenticationRepository)
: super(CreateAccountState());

void emailChanged(String value) {
emit(state.copyWith(email: value));
enable();
}

void nameChanged(String value) {
emit(state.copyWith(name: value));
enable();
}

void passwordChanged(String value) {
emit(state.copyWith(password: value));
if (_validator.isPasswordValid(state.password)) {
enable();
} else {
emit(state.copyWith(isEnabled: false));
}
}

void enable() {
if (_validator.isEmailValid(state.email) &&
state.name.isNotEmpty &&
_validator.isPasswordValid(state.password)) {
emit(state.copyWith(isEnabled: true));
} else {
emit(state.copyWith(isEnabled: false));
}
}

Future<void> submit() async {
emit(state.copyWith(isLoading: true));
final result = await _authenticationRepository.register(
state.toEntity(),
state.password,
);
result.when(
onSuccess: (user) {
emit(state.copyWith(isLoading: false));
},
onError: (error){
emit(state.copyWith(isLoading: false));
emit(state.copyWith(errorMessage: error.message));
emit(state.copyWith(errorMessage: null));
},
);
}

void togglePasswordVisibility() {
emit(state.copyWith(isPasswordVisible: !state.isPasswordVisible));
}
}
Loading