Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
9 changes: 8 additions & 1 deletion lib/core/di/cubit_di.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:moneyplus/domain/repository/user_money_repository.dart';
import 'package:moneyplus/domain/validator/authentication_validator.dart';
import 'package:moneyplus/presentation/account_setup/cubit/account_setup_cubit.dart';
import 'package:moneyplus/presentation/createAccount/cubit/create_account_cubit.dart';
import 'package:moneyplus/presentation/edit_salary/salary_settings_cubit.dart';
import 'package:moneyplus/presentation/home/cubit/home_cubit.dart';
import 'package:moneyplus/presentation/income/cubit/add_income_cubit.dart';
import 'package:moneyplus/presentation/login/cubit/login_cubit.dart';
Expand Down Expand Up @@ -43,6 +44,7 @@ void initCubitDI() {
userMoneyRepository: getIt<UserMoneyRepository>(),
),
);

getIt.registerFactory<AddIncomeCubit>(
() => AddIncomeCubit(
transactionRepository: getIt<TransactionRepository>(),
Expand Down Expand Up @@ -71,7 +73,12 @@ void initCubitDI() {
getIt<AuthenticationRepository>(),
),
);

getIt.registerFactory<AccountCubit>(
() => AccountCubit(getIt<AccountRepository>()),
() => AccountCubit(getIt<AccountRepository>()),
);

getIt.registerFactory<SalarySettingsCubit>(
() => SalarySettingsCubit(userMoneyRepository: getIt<UserMoneyRepository>()),
);
}
3 changes: 3 additions & 0 deletions lib/core/l10n/app_ar.arb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@
"categoriesBreakdown": "تفاصيل الفئات",
"no_monthly_breakdown": "لا يوجد نفقات لتحليلها بعد",
"totalSpend": "إجمالي الإنفاق",
"salary_saved": "تم حفظ إعدادات الراتب بنجاح",
"failed_to_save_salary": "فشل في حفظ إعدادات الراتب",
"failed_to_load_salary_settings": "فشل في تحميل إعدادات الراتب",
"cancel": "إلغاء",
"english": "الإنجليزية",
"arabic": "العربية",
Expand Down
3 changes: 3 additions & 0 deletions lib/core/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@
"categoriesBreakdown": "Categories Breakdown",
"no_monthly_breakdown": "No expenses to analyze yet",
"totalSpend": "Total Spend",
"salary_saved": "Salary settings saved successfully",
"failed_to_save_salary": "Failed to save salary settings",
"failed_to_load_salary_settings": "Failed to load salary settings",
"cancel": "Cancel",
"english": "English",
"arabic": "Arabic",
Expand Down
37 changes: 33 additions & 4 deletions lib/data/repository/user_money_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class UserRepositoryImpl implements UserMoneyRepository {
}

List<TopSpendingCategory> _getTopSpendingCategoriesFromResponseRows(
List<dynamic> rows,
List<dynamic> rows,
) {
return rows.map((row) {
final data = row as Map<String, dynamic>;
Expand All @@ -100,9 +100,9 @@ class UserRepositoryImpl implements UserMoneyRepository {

@override
Future<Currency> getCurrency() async {
final client = await service.getClient();
final response = await client.rpc('get_default_currency');
return Currency.fromJson(response);
final client = await service.getClient();
final response = await client.rpc('get_default_currency');
return Currency.fromJson(response);
}

@override
Expand Down Expand Up @@ -133,6 +133,35 @@ class UserRepositoryImpl implements UserMoneyRepository {
return ((currentMonthBalance - previousMonthBalance) / previousMonthBalance) * 100;
}

@override
Future<double> getSalary() async {
final client = await service.getClient();
final response = await client.from('users').select('salary_amount');
final balance = (response.firstOrNull?['salary_amount'] as num?)?.toDouble() ?? 0.0;
return balance;
}

@override
Future<int> getSalaryDay() async {
final client = await service.getClient();
final response = await client.from('users').select('salary_day');
final balance = (response.firstOrNull?['salary_day'] as int?)?.toInt() ?? 0;
return balance;
}

@override
Future<void> updateSalarySettings({
required double salary,
required int salaryDay,
}) async {
final client = await service.getClient();

await client
.from('users')
.update({'salary_amount': salary, 'salary_day': salaryDay})
.eq('id', client.auth.currentUser!.id);
}

void _validateMonth(int month){
if(month < 1 || month > 12){
throw Exception('Month value: "$month" is not valid, Month must be between 1 and 12');
Expand Down
16 changes: 14 additions & 2 deletions lib/domain/repository/user_money_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,22 @@ abstract class UserMoneyRepository {

Future<double> getMonthExpense(int month, int year);

Future<List<TopSpendingCategory>> getTopSpendingCategoriesInMonth(
{required int month,required int year, required int count});
Future<List<TopSpendingCategory>> getTopSpendingCategoriesInMonth({
required int month,
required int year,
required int count,
});

Future<Currency> getCurrency();

Future<double> getSavingSpendingPercentage(int month, int year);

Future<double> getSalary();

Future<int> getSalaryDay();

Future<void> updateSalarySettings({
required double salary,
required int salaryDay,
});
}
4 changes: 4 additions & 0 deletions lib/presentation/accout/screen/account_screen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:moneyplus/presentation/navigation/routes.dart';
import 'package:moneyplus/app_prefernces_cubit.dart';
import 'package:moneyplus/presentation/accout/widget/theme_selection_dialog.dart';

Expand Down Expand Up @@ -126,6 +127,9 @@ class AccountScreen extends StatelessWidget {
context,
title: l10n.salarySettings,
iconPath: AppAssets.iconMoney,
onTap: () {
EditSalaryRoute().push(context);
},
),
accountSection(
context,
Expand Down
83 changes: 83 additions & 0 deletions lib/presentation/edit_salary/salary_settings_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:moneyplus/domain/repository/user_money_repository.dart';
part 'salary_settings_state.dart';

class SalarySettingsCubit extends Cubit<SalarySettingsState> {
SalarySettingsCubit({required this.userMoneyRepository}) : super(SalarySettingsLoading());

UserMoneyRepository userMoneyRepository;

void getData() async {
try{
final salary = await userMoneyRepository.getSalary();
final salaryDay = await userMoneyRepository.getSalaryDay();
emit(
SalarySettingsLoaded(
salary: salary.toString(),
salaryDay: salaryDay.toString(),
isSaveButtonEnabled: false,
),
);
}catch(e){
emit(SalarySettingsError(failure: SalarySettingsFailure.loadFailed));
}
_setButtonVisibility();
}

void updateSalary(String salary) {
if (state is SalarySettingsLoaded) {
var currentState = state as SalarySettingsLoaded;
emit(currentState.copyWith(salary: salary));
_setButtonVisibility();
}
}

void updateSalaryDay(String salaryDay) {
if (state is SalarySettingsLoaded) {
var currentState = state as SalarySettingsLoaded;
emit(currentState.copyWith(salaryDay: salaryDay));
_setButtonVisibility();
}
}

Future<bool> saveChanges() async {
try{
if (state is SalarySettingsLoaded) {
var currentState = state as SalarySettingsLoaded;
await userMoneyRepository.updateSalarySettings(
salary: double.parse(currentState.salary),
salaryDay: int.parse(currentState.salaryDay),
);
}
return true;
}catch(e){
return false;
}

}



void _setButtonVisibility() {
bool checkIfButtonShouldBeEnabled(SalarySettingsLoaded state) {
final salary = double.tryParse(state.salary);
if (salary == null) return false;
final salaryDay = int.tryParse(state.salaryDay);
if (salaryDay == null) return false;
if(salaryDay < 1 || salaryDay > 31) return false;
if(salary < 0) return false;
return true;
}

if (state is SalarySettingsLoaded) {
var currentState = state as SalarySettingsLoaded;
final shouldBeEnabled = checkIfButtonShouldBeEnabled(currentState);
emit(currentState.copyWith(isButtonEnabled: shouldBeEnabled));
}
}
}

enum SalarySettingsFailure {
loadFailed,
}
Loading