Skip to content

Commit

Permalink
feat: enhance cubit with more control and models related for return t…
Browse files Browse the repository at this point in the history
…ypes
  • Loading branch information
felipecastrosales committed May 12, 2024
1 parent 44bb684 commit ff4e89d
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,23 @@ class ContactRepositoryImpl implements ContactRepository {
required ContactModel contact,
}) async {
try {
final response = await _httpClient.post(
final Response response = await _httpClient.post(
ConstantsAPI.apiSendMail,
data: ContactUser.toJson(contact),
);

// return response.data;
return Success(ContactAnswer.fromJson(response.data));
return Success(
ContactAnswer.fromResponse(
contact: contact,
response: response,
),
);
} catch (e, s) {
log('Error: $e', stackTrace: s);
log('[Error]: ContactRepositoryImpl.sendMail', error: e, stackTrace: s);

return const Failure(ContactFailedResult.unknown);
return const Failure(
ContactFailedResult.unknown,
);
}
}
}
22 changes: 13 additions & 9 deletions lib/app/features/contact/domain/models/contact_answer.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import 'package:dio/dio.dart';
import 'package:site/app/features/contact/domain/models/contact_model.dart';

class ContactAnswer extends ContactModel {
factory ContactAnswer.fromJson(Map<String, dynamic> json) {
factory ContactAnswer.fromResponse({
required ContactModel contact,
required Response response,
}) {
return ContactAnswer(
name: json['sender_name'],
email: json['source_email'],
message: json['template_body'],
subject: json['template_subject'],
response: json['response'],
status: json['status'],
name: contact.name,
email: contact.email,
message: contact.message,
subject: contact.subject,
status: response.statusMessage ?? '',
response: '${response.statusCode}',
);
}

Expand All @@ -17,10 +21,10 @@ class ContactAnswer extends ContactModel {
required super.email,
required super.message,
required super.subject,
required this.response,
required this.status,
required this.response,
});

final String response;
final String status;
final String response;
}
46 changes: 32 additions & 14 deletions lib/app/features/contact/presentation/cubit/contact_cubit.dart
Original file line number Diff line number Diff line change
@@ -1,36 +1,54 @@
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:site/app/core/result/result.dart';
import 'package:site/app/features/contact/contact.dart';

part 'contact_state.dart';

class ContactCubit extends Cubit<ContactState> {
ContactCubit({
required ContactRepositoryImpl contactRepository,
required ContactRepository contactRepository,
}) : _contactRepository = contactRepository,
super(
const ContactInitial(),
);

final ContactRepositoryImpl _contactRepository;
final ContactRepository _contactRepository;

Future<void> sendMail({
required ContactModel contact,
}) async {
emit(const ContactLoading());

try {
await _contactRepository.sendMail(
contact: contact,
);
emit(
ContactSuccess(
contact: contact,
message: 'Email sent successfully',
),
);
} catch (e) {
final result = await _contactRepository.sendMail(contact: contact);

switch (result) {
case Success(object: final contactAnswer):
emit(
ContactSuccess(
contact: contactAnswer,
message: 'Email sent successfully',
),
);
case Failure(error: final contactFailedResult):
emit(
ContactError(
contact: contact,
message: switch (contactFailedResult) {
ContactFailedResult.unauthorized => 'Unauthorized',
ContactFailedResult.tooManyRequests =>
'Too many requests, try again later',
ContactFailedResult.unknown => 'Error sending email',
},
),
);
}
} catch (e, s) {
log('[Error]: ContactCubit.sendMail', error: e, stackTrace: s);
emit(
ContactError(
contact: contact,
Expand All @@ -42,8 +60,8 @@ class ContactCubit extends Cubit<ContactState> {
}


// class ContactController extends ChangeNotifier {
// ContactController({
// class ContactCubit extends ChangeNotifier {
// ContactCubit({
// ContactRepositoryImpl? contactRepository,
// }) : _contactRepository = contactRepository ?? getIt();

Expand Down
2 changes: 1 addition & 1 deletion lib/app/features/contact/presentation/presentation.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export 'controller/controller.dart';
export 'widgets/widgets.dart';
export 'cubit/contact_cubit.dart';
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class CustomForm extends StatelessWidget {
required this.subjectController,
required this.messageController,
required this.onPressed,
ContactController? contactController,
}) : _contactController = contactController ??
ContactController(
ContactCubit? contactCubit,
}) : _contactCubit = contactCubit ??
ContactCubit(
contactRepository: ContactRepositoryImpl(
httpClient: getIt(),
),
Expand All @@ -30,8 +30,7 @@ class CustomForm extends StatelessWidget {
final TextEditingController subjectController;
final TextEditingController messageController;
final VoidCallback onPressed;

final ContactController? _contactController;
final ContactCubit? _contactCubit;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -77,9 +76,21 @@ class CustomForm extends StatelessWidget {
Center(
child: AppTextButton(
text: AppTexts.get(context).sendEmailUpper,
onPressed: onPressed,

/// TODO:
// onPressed: onPressed,
onPressed: () {
_contactCubit?.sendMail(
contact: ContactUser(
name: 'felipe sales',
email: '[email protected]',
message: 'teste de mensagem',
subject: 'vamos testar, mais uma vez',
),
);
},
onLongPress: () {
_contactController?.sendMail(
_contactCubit?.sendMail(
contact: ContactUser(
name: 'felipe sales',
email: '[email protected]',
Expand Down
107 changes: 48 additions & 59 deletions lib/app/features/contact/presentation/widgets/ui/contact_widget.dart
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import 'package:site/app/core/injections/injections.dart';
import 'package:site/app/core/l10n/l10n.dart';
import 'package:site/app/core/responsive/responsive.dart';
import 'package:site/app/core/shared/app_keys.dart';
import 'package:site/app/core/tokens/tokens.dart';
import 'package:site/app/features/contact/contact.dart';
import 'package:site/app/widgets/snack_bars/snack_bars.dart';
// import 'package:site/data/services/recaptcha/recaptcha.dart';

class ContactWidget extends StatelessWidget {
ContactWidget({
super.key,
ContactController? contactController,
}) : _contactController = contactController ??
ContactController(
contactRepository: ContactRepositoryImpl(
httpClient: getIt(),
),
);
ContactCubit? contactCubit,
}) : _contactCubit = contactCubit ?? _cubit;

final ContactController? _contactController;
final ContactCubit? _contactCubit;

static final _cubit = ContactCubit(
contactRepository: ContactRepositoryImpl(
httpClient: getIt(),
),
);

@override
Widget build(BuildContext context) {
Expand All @@ -29,56 +28,46 @@ class ContactWidget extends StatelessWidget {
final emailController = TextEditingController();
final messageController = TextEditingController();
final subjectController = TextEditingController();
final form = CustomForm(
formKey: formKey,
nameController: nameController,
emailController: emailController,
subjectController: subjectController,
messageController: messageController,
onPressed: () async {
if (formKey.currentState?.validate() ?? false) {
// final isNotABot = await RecaptchaService.isNotABot();

// if (isNotABot) {
if (true) {
if (context.mounted) {
appShowSnackBar(
context,
text: AppTexts.get(context).emailSendedWithSuccess,
icon: Icons.check,
color: AppColors.primaryDark,
width: 300,
);
}

_contactController?.sendMail(
contact: ContactUser(
name: nameController.text,
email: emailController.text.trim(),
message: messageController.text,
subject: subjectController.text,
),
);

for (var controller in [
nameController,
emailController,
messageController,
subjectController,
]) {
controller.clear();
}
} else if (context.mounted) {
appShowSnackBar(
context,
text: AppTexts.get(context).emailNotSended,
icon: Icons.error,
color: AppColors.red,
width: 300,
);
final form = BlocProvider(
create: (context) => _contactCubit ?? _cubit,
child: BlocConsumer<ContactCubit, ContactState>(
listener: (context, state) {
if ([ContactSuccess, ContactError].contains(state.runtimeType)) {
appShowSnackBarFromContact(context, state);
}
}
},
},
builder: (context, state) {
return CustomForm(
formKey: formKey,
nameController: nameController,
emailController: emailController,
subjectController: subjectController,
messageController: messageController,
onPressed: () {
if (formKey.currentState?.validate() ?? false) {
_contactCubit?.sendMail(
contact: ContactUser(
name: nameController.text,
email: emailController.text,
subject: subjectController.text,
message: messageController.text,
),
);

for (var controller in [
nameController,
emailController,
messageController,
subjectController,
]) {
controller.clear();
}
}
},
);
},
),
);

return LayoutBuilder(
Expand Down
11 changes: 6 additions & 5 deletions lib/app/features/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,18 @@ class _HomePageState extends State<HomePage> {
void initState() {
super.initState();
items = [
Presentation(itemScrollController),
const Projects(),
const Experience(),
const Social(),
/// TODO:
ContactWidget(
contactController: ContactController(
contactCubit: ContactCubit(
contactRepository: ContactRepositoryImpl(
httpClient: widget._httpClient,
),
),
),
Presentation(itemScrollController),
const Projects(),
const Experience(),
const Social(),
const CustomFooter(),
];
}
Expand Down
27 changes: 27 additions & 0 deletions lib/app/widgets/snack_bars/app_show_snack_bar.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import 'package:flutter/material.dart';

import 'package:auto_size_text/auto_size_text.dart';
import 'package:site/app/core/l10n/localizations/localizations.dart';

import 'package:site/app/core/tokens/tokens.dart';
import 'package:site/app/features/contact/presentation/presentation.dart';

ScaffoldFeatureController appShowSnackBar(
BuildContext context, {
Expand Down Expand Up @@ -44,3 +46,28 @@ ScaffoldFeatureController appShowSnackBar(
),
);
}

ScaffoldFeatureController appShowSnackBarFromContact(
BuildContext context,
ContactState state,
) {
return appShowSnackBar(
context,
width: 300,
text: switch (state) {
ContactSuccess() => AppTexts.get(context).emailSendedWithSuccess,
ContactError() => AppTexts.get(context).emailNotSended,
_ => '',
},
icon: switch (state) {
ContactSuccess() => Icons.check,
ContactError() => Icons.error,
_ => Icons.error,
},
color: switch (state) {
ContactSuccess() => AppColors.primaryDark,
ContactError() => AppColors.red,
_ => AppColors.red,
},
);
}
Loading

0 comments on commit ff4e89d

Please sign in to comment.