Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: integrates feedback with the backend #282

Merged
merged 7 commits into from
Apr 13, 2024
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
2 changes: 1 addition & 1 deletion lib/data/services/remote/api_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ abstract class ApiService {
Future<List<FeedbackResponse>> responseOfFeedbacks();

@POST(ApiEndpoints.newFeedback)
Future<AppetizerFeedback> newFeedback(
Future<void> newFeedback(
@Body() Map<String, dynamic> map,
);

Expand Down
16 changes: 4 additions & 12 deletions lib/domain/models/feedback/appetizer_feedback.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,18 @@ part 'appetizer_feedback.g.dart';

@JsonSerializable(fieldRename: FieldRename.snake)
class AppetizerFeedback {
int id;
String type;
String title;
String message;
int timestamp;
dynamic mealId;
dynamic imageUrl;
int dateIssue;
dynamic response;
// dynamic imageUrl;
int ratings;

AppetizerFeedback({
required this.id,
required this.type,
required this.title,
required this.message,
required this.timestamp,
required this.mealId,
required this.imageUrl,
required this.dateIssue,
required this.response,
// required this.imageUrl,
required this.ratings,
});

factory AppetizerFeedback.fromJson(Map<String, dynamic> json) =>
Expand Down
9 changes: 5 additions & 4 deletions lib/domain/repositories/feedback_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ class FeedbackRepository {
}
}

Future<AppetizerFeedback> newFeedback(AppetizerFeedback feedback) async {
Future<void> newFeedback(AppetizerFeedback feedback) async {
Map<String, dynamic> map = {
'type': feedback.type,
'title': feedback.title,
'message': feedback.message,
'date_issue': feedback.dateIssue,
'meal_id': feedback.mealId,
'ratings': feedback.ratings,
// 'image_url': feedback.imageUrl,
};
try {
return await _apiService.newFeedback(map);
await _apiService.newFeedback(map);
} catch (e) {
debugPrint(e.toString());
throw Failure(AppConstants.GENERIC_FAILURE);
Expand Down
42 changes: 26 additions & 16 deletions lib/presentation/feedback/bloc/feedback_page_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:appetizer/domain/models/feedback/appetizer_feedback.dart';
import 'package:appetizer/domain/repositories/feedback_repository.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
Expand All @@ -10,36 +11,44 @@ class FeedbackPageBloc extends Bloc<FeedbackPageEvent, FeedbackPageState> {
FeedbackPageBloc({
required this.repo,
}) : super(
const FeedbackPageState.initial(),
FeedbackPageState.initial(),
) {
on<FeedbackPageSubmitEvent>(_onSubmit);
on<FeedbackPageDescriptionChangedEvent>(_onDescriptionChange);
}

void _onSubmit(
FeedbackPageSubmitEvent event, Emitter<FeedbackPageState> emit) {
// TODO: implement repository call
bool submissionSuccessful = true;
if (submissionSuccessful) {
FeedbackPageSubmitEvent event, Emitter<FeedbackPageState> emit) async {
try {
int ratings = event.rating;
AppetizerFeedback feedback = AppetizerFeedback(
title: 'Feedback',
message: event.description,
mealId: event.mealId,
// imageUrl: null,
ratings: ratings,
);
await repo.newFeedback(feedback);
emit(
FeedbackPageState(
rating: event.rating,
description: event.description,
submitted: true,
error: false,
mealId: event.mealId,
),
);
} catch (e) {
emit(
FeedbackPageState(
rating: event.rating,
description: event.description,
submitted: false,
error: true,
mealId: event.mealId,
),
);
}
// else {
// emit(
// FeedbackPageState(
// rating: event.rating,
// description: event.description,
// submitted: false,
// error: true,
// ),
// );
// }
}

void _onDescriptionChange(FeedbackPageDescriptionChangedEvent event,
Expand All @@ -50,7 +59,8 @@ class FeedbackPageBloc extends Bloc<FeedbackPageEvent, FeedbackPageState> {
rating: state.rating,
description: event.description,
submitted: state.submitted,
error: state.error,
error: false,
mealId: state.mealId,
),
);
}
Expand Down
6 changes: 4 additions & 2 deletions lib/presentation/feedback/bloc/feedback_page_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ class FeedbackPageSubmitEvent extends FeedbackPageEvent {
const FeedbackPageSubmitEvent({
required this.rating,
required this.description,
required this.mealId,
});
final List<int> rating;
final int rating;
final String description;
final int mealId;

@override
List<Object> get props => [rating, description];
List<Object> get props => [rating, description, mealId];
}

class FeedbackPageDescriptionChangedEvent extends FeedbackPageEvent {
Expand Down
14 changes: 9 additions & 5 deletions lib/presentation/feedback/bloc/feedback_page_state.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
part of 'feedback_page_bloc.dart';

// ignore: must_be_immutable
class FeedbackPageState extends Equatable {
const FeedbackPageState({
FeedbackPageState({
required this.rating,
required this.description,
required this.mealId,
required this.submitted,
required this.error,
});

const FeedbackPageState.initial()
: rating = const [0, 0, 0, 0, 0],
FeedbackPageState.initial()
: rating = 0,
description = '',
mealId = 0,
submitted = false,
error = false;

final List<int> rating;
int rating;
final String description;
final int mealId;
final bool submitted;
final bool error;

@override
List<Object> get props => [rating, description, error];
List<Object> get props => [rating, description, mealId, error];
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ class FeedbackTile extends StatelessWidget {
const FeedbackTile({
required this.title,
required this.parentState,
required this.index,
super.key,
});

final String title;
final FeedbackPageState parentState;
final int index;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -44,7 +42,7 @@ class FeedbackTile extends StatelessWidget {
onPressed: () {
context.read<FeedbackTileBloc>().add(
FeedbackRatingChangedEvent(newRating: index + 1));
parentState.rating[this.index] = index + 1;
parentState.rating = index + 1;
},
icon: index < state.rating
? SvgPicture.asset('assets/images/filledStar.svg')
Expand Down
89 changes: 66 additions & 23 deletions lib/presentation/feedback/feedback_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ import 'package:appetizer/presentation/feedback/components/feedback_banner.dart'
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluttertoast/fluttertoast.dart';

@RoutePage()
class FeedbackScreen extends StatelessWidget {
FeedbackScreen({super.key});
FeedbackScreen({required this.mealId, super.key});
final TextEditingController textController = TextEditingController();
final int mealId;
static const List<String> feedbackHeadings = [
"Ambience",
"Hygiene and Cleanliness",
"Weekly Menu",
"Worker and Services",
"Diet and Nutrition",
"Your Feedback",
];

@override
Expand All @@ -29,7 +27,7 @@ class FeedbackScreen extends StatelessWidget {
body: BlocProvider(
create: (context) =>
FeedbackPageBloc(repo: context.read<FeedbackRepository>()),
child: BlocBuilder<FeedbackPageBloc, FeedbackPageState>(
child: BlocConsumer<FeedbackPageBloc, FeedbackPageState>(
builder: (context, state) {
return Column(
children: [
Expand All @@ -52,17 +50,14 @@ class FeedbackScreen extends StatelessWidget {
),
),
6.toVerticalSizedBox,
...List.generate(feedbackHeadings.length, (ind) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: 2.toAutoScaledHeight),
child: FeedbackTile(
parentState: state,
title: feedbackHeadings[ind],
index: ind,
),
);
}, growable: false),
Padding(
padding: EdgeInsets.symmetric(
vertical: 2.toAutoScaledHeight),
child: FeedbackTile(
parentState: state,
title: "Your Feedback",
),
),
2.toVerticalSizedBox,
Text(
'If any other feeback, please describe below',
Expand Down Expand Up @@ -100,11 +95,36 @@ class FeedbackScreen extends StatelessWidget {
Align(
alignment: Alignment.bottomRight,
child: BlackIconButton(
onTap: context.router.pop,
// onTap: () => context.read<FeedbackPageBloc>().add(
// FeedbackPageSubmitEvent(
// rating: state.rating,
// description: state.description)),
onTap: () {
if (state.rating == 0) {
Fluttertoast.showToast(
msg: "Please rate before submitting!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
textColor: Colors.white,
backgroundColor: AppTheme.red,
fontSize: 12.toAutoScaledFont);
return;
}

if (state.description.trim().isEmpty) {
Fluttertoast.showToast(
msg: "Please describe your Feedback!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
textColor: Colors.white,
backgroundColor: AppTheme.red,
fontSize: 12.toAutoScaledFont);
return;
}
context.read<FeedbackPageBloc>().add(
FeedbackPageSubmitEvent(
mealId: mealId,
rating: state.rating,
description: state.description));
},
title: "SUBMIT",
width: 102.toAutoScaledWidth,
icon: Icons.keyboard_double_arrow_right_sharp,
Expand All @@ -118,6 +138,29 @@ class FeedbackScreen extends StatelessWidget {
],
);
},
listener: (BuildContext context, FeedbackPageState state) {
if (state.submitted) {
Fluttertoast.showToast(
msg: "Feedback submitted successfully!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
textColor: Colors.white,
backgroundColor: AppTheme.green,
fontSize: 12.toAutoScaledFont);
context.router.pop();
}
if (state.error) {
Fluttertoast.showToast(
msg: state.description,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
textColor: Colors.white,
backgroundColor: AppTheme.red,
fontSize: 16.0);
}
},
),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class FeedbackOrCouponButton extends StatelessWidget {
if (meal.isOutdated) {
return GestureDetector(
onTap: () {
context.router.navigate(FeedbackRoute());
context.router.navigate(FeedbackRoute(mealId: meal.id));
},
child: const FeedbackAndCouponWidget(taken: false, coupon: false),
);
Expand Down
Loading
Loading