Skip to content

Commit 051b6be

Browse files
committed
update
1 parent d090973 commit 051b6be

26 files changed

+411
-298
lines changed

lib/configs/router.dart

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:e_commerce_app/bottom_navigation.dart';
2+
import 'package:e_commerce_app/presentation/screens/detail_image/detail_image_screen.dart';
23
import 'package:e_commerce_app/presentation/screens/message/message_screen.dart';
34
import 'package:e_commerce_app/presentation/screens/detail_order_screen.dart/detail_order_screen.dart';
45
import 'package:e_commerce_app/presentation/screens/map/map_screen.dart';
@@ -16,7 +17,6 @@ import 'package:e_commerce_app/presentation/screens/settings/setting_screen.dart
1617
import 'package:e_commerce_app/presentation/screens/login/login_screen.dart';
1718
import 'package:e_commerce_app/presentation/screens/register/register_screen.dart';
1819
import 'package:e_commerce_app/presentation/screens/splash/splash_screen.dart';
19-
import 'package:e_commerce_app/presentation/screens/product_images/product_images_screen.dart';
2020

2121
class AppRouter {
2222
static const String SPLASH = '/splash';
@@ -27,7 +27,7 @@ class AppRouter {
2727
static const String HOME = '/home';
2828
static const String PROFILE = '/profile';
2929
static const String DETAIL_PRODUCT = '/detail_product';
30-
static const String PRODUCT_IMAGES = '/product_images';
30+
static const String DETAIL_IMAGE = '/detail_image';
3131
static const String FEEDBACK = '/feedback';
3232
static const String CART = '/cart';
3333
static const String MY_ORDERS = '/my_orders';
@@ -72,13 +72,10 @@ class AppRouter {
7272
var product = settings.arguments as Product;
7373
return MaterialPageRoute(
7474
builder: (_) => DetailProductScreen(product: product));
75-
case PRODUCT_IMAGES:
76-
var arguments = settings.arguments as Map<String, dynamic>;
75+
case DETAIL_IMAGE:
76+
var imageUrl = settings.arguments as String;
7777
return MaterialPageRoute(
78-
builder: (_) => ProductImagesScreen(
79-
product: arguments["product"],
80-
selectedIndex: arguments["selectedIndex"],
81-
),
78+
builder: (_) => DetailImageScreen( imageUrl: imageUrl),
8279
);
8380
case FEEDBACK:
8481
var product = settings.arguments as Product;

lib/data/repository/message_repository/firebase_message_repo.dart

+43-18
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,57 @@ import 'package:e_commerce_app/data/repository/repository.dart';
44

55
class FirebaseMessageRepository implements MessageRepository {
66
final userCollection = FirebaseFirestore.instance.collection("users");
7-
DocumentSnapshot? lastDocument;
87

9-
/// Get all messages of logged user
10-
Future<List<Message>> getMessages({
8+
/// Get 20 the first messages
9+
Stream<List<Message>> getRecentMessages({
1110
required String uid,
1211
required int messagesLimit,
13-
required bool isTheFirstTime,
14-
}) async {
15-
Query messagesQuery = userCollection
12+
}) {
13+
return userCollection
1614
.doc(uid)
1715
.collection("messages")
1816
.orderBy("createdAt", descending: true)
19-
.limit(messagesLimit);
20-
21-
if (isTheFirstTime == false && lastDocument != null) {
22-
messagesQuery = messagesQuery.startAfterDocument(lastDocument!);
23-
}
17+
.limit(messagesLimit)
18+
.snapshots()
19+
.map(
20+
(snapshot) =>
21+
snapshot.docs.map((doc) => Message.fromMap(doc.data()!)).toList(),
22+
);
23+
}
2424

25-
QuerySnapshot querySnapshot = await messagesQuery.get();
26-
if (querySnapshot.docs.isNotEmpty) {
27-
lastDocument = querySnapshot.docs[querySnapshot.docs.length - 1];
28-
}
25+
@override
26+
Future<List<Message>> getPreviousMessages({
27+
required String uid,
28+
required int messagesLimit,
29+
required Message lastMessage,
30+
}) async {
31+
var messagesCollection = userCollection.doc(uid).collection("messages");
32+
// Gets a reference to the last message in the existing list
33+
DocumentSnapshot lastDocument =
34+
await messagesCollection.doc(lastMessage.id).get();
35+
return messagesCollection
36+
.orderBy("createdAt", descending: true)
37+
.startAfterDocument(lastDocument)
38+
.limit(messagesLimit)
39+
.get()
40+
.then(
41+
(snapshot) =>
42+
snapshot.docs.map((doc) => Message.fromMap(doc.data()!)).toList(),
43+
);
44+
}
2945

30-
return querySnapshot.docs
31-
.map((doc) => Message.fromMap(doc.data()!))
32-
.toList();
46+
Future<Message?> getLastestMessage({
47+
required String uid,
48+
}) async {
49+
// Gets the lastest message in the existing list
50+
QuerySnapshot querySnapshot = await userCollection
51+
.doc(uid)
52+
.collection("messages")
53+
.orderBy("createdAt", descending: true)
54+
.limit(1)
55+
.get();
56+
if (querySnapshot.docs.isEmpty) return null;
57+
return Message.fromMap(querySnapshot.docs[0].data()!);
3358
}
3459

3560
/// Add item

lib/data/repository/message_repository/message_repo.dart

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
import 'package:e_commerce_app/data/entities/entites.dart';
22

33
abstract class MessageRepository {
4-
/// Get all messages of logged user
4+
/// Get 20 first messages
55
/// Created by NDH
6-
Future<List<Message>> getMessages({
6+
Stream<List<Message>> getRecentMessages({
77
required String uid,
88
required int messagesLimit,
9-
required bool isTheFirstTime,
109
});
1110

11+
/// Get more messages
12+
/// Created by NDH
13+
Future<List<Message>> getPreviousMessages({
14+
required String uid,
15+
required int messagesLimit,
16+
required Message lastMessage,
17+
});
18+
19+
/// Get lastest message
20+
/// Created by NDH
21+
Future<Message?> getLastestMessage({required String uid});
22+
1223
/// Add message
1324
/// [uid] is user id
1425
/// [newItem] is data of new message

lib/main.dart

+2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import 'package:e_commerce_app/presentation/common_blocs/common_bloc.dart';
44
import 'package:e_commerce_app/configs/config.dart';
55
import 'package:firebase_core/firebase_core.dart';
66
import 'package:flutter/material.dart';
7+
import 'package:flutter/services.dart';
78
import 'package:flutter_bloc/flutter_bloc.dart';
89
import 'package:e_commerce_app/app_view.dart';
910
import 'presentation/common_blocs/simple_bloc_observer.dart';
1011

1112
void main() async {
1213
WidgetsFlutterBinding.ensureInitialized();
14+
SystemUiOverlayStyle(statusBarColor: Colors.transparent);
1315
Bloc.observer = SimpleBlocObserver();
1416
await Firebase.initializeApp();
1517
runApp(MyApp());

lib/presentation/screens/delivery_address/delivery_address_bottom_sheet.dart

+8
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ class _DeliveryAddressBottomSheetState
5858
}
5959
}
6060

61+
@override
62+
void dispose() {
63+
nameController.dispose();
64+
phoneNumberController.dispose();
65+
detailAddressController.dispose();
66+
super.dispose();
67+
}
68+
6169
Function(bool value)? onSwitchButtonChanged() {
6270
return deliveryAddress == null || deliveryAddress!.isDefault
6371
? null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import 'dart:typed_data';
2+
3+
import 'package:dio/dio.dart';
4+
import 'package:e_commerce_app/configs/config.dart';
5+
import 'package:e_commerce_app/constants/constants.dart';
6+
import 'package:e_commerce_app/presentation/widgets/buttons/default_button.dart';
7+
import 'package:e_commerce_app/utils/translate.dart';
8+
import 'package:flutter/material.dart';
9+
// ignore: import_of_legacy_library_into_null_safe
10+
import 'package:image_gallery_saver/image_gallery_saver.dart';
11+
import 'package:uuid/uuid.dart';
12+
13+
class DetailImageScreen extends StatelessWidget {
14+
final String imageUrl;
15+
16+
const DetailImageScreen({
17+
Key? key,
18+
required this.imageUrl,
19+
}) : super(key: key);
20+
21+
void onSave(BuildContext context) async {
22+
var response = await Dio().get(
23+
imageUrl,
24+
options: Options(responseType: ResponseType.bytes),
25+
);
26+
await ImageGallerySaver.saveImage(
27+
Uint8List.fromList(response.data),
28+
quality: 60,
29+
name: Uuid().v1(),
30+
);
31+
32+
print("save success");
33+
34+
Navigator.pop(context);
35+
}
36+
37+
@override
38+
Widget build(BuildContext context) {
39+
return Scaffold(
40+
body: Container(
41+
height: SizeConfig.screenHeight,
42+
color: Colors.black,
43+
child: GestureDetector(
44+
onTap: () {
45+
Navigator.pop(context);
46+
},
47+
onLongPress: () {
48+
showModalBottomSheet(
49+
context: context,
50+
builder: (context) {
51+
return DefaultButton(
52+
onPressed: () => onSave(context),
53+
backgroundColor: Colors.white,
54+
child: Text(
55+
Translate.of(context).translate("save"),
56+
style: FONT_CONST.BOLD_DEFAULT_18,
57+
),
58+
);
59+
},
60+
);
61+
},
62+
child: Image.network(imageUrl),
63+
),
64+
),
65+
);
66+
}
67+
}

lib/presentation/screens/detail_product/widgets/product_images.dart

+2-5
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,8 @@ class _ProductImagesWidgetState extends State<ProductImagesWidget> {
3535
onTap: () {
3636
Navigator.pushNamed(
3737
context,
38-
AppRouter.PRODUCT_IMAGES,
39-
arguments: {
40-
"product": product,
41-
"selectedIndex": currentPage
42-
},
38+
AppRouter.DETAIL_IMAGE,
39+
arguments: product.images[index],
4340
);
4441
},
4542
child: Image.network(product.images[index]),

lib/presentation/screens/feedbacks/bloc/feedback_bloc.dart

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import 'dart:async';
2+
import 'package:cloud_firestore/cloud_firestore.dart';
23
import 'package:e_commerce_app/data/entities/entites.dart';
34
import 'package:e_commerce_app/data/repository/app_repository.dart';
45
import 'package:e_commerce_app/data/repository/repository.dart';
56
import 'package:e_commerce_app/presentation/screens/feedbacks/bloc/bloc.dart';
67
import 'package:flutter_bloc/flutter_bloc.dart';
8+
import 'package:uuid/uuid.dart';
79

810
class FeedbackBloc extends Bloc<FeedbacksEvent, FeedbackState> {
11+
final AuthRepository _authRepository = AppRepository.authRepository;
912
final FeedbackRepository _feedbackRepository =
1013
AppRepository.feedbackRepository;
1114
final ProductRepository _productRepository = AppRepository.productRepository;
@@ -43,9 +46,16 @@ class FeedbackBloc extends Bloc<FeedbacksEvent, FeedbackState> {
4346

4447
Stream<FeedbackState> _mapAddFeedbackToState(AddFeedback event) async* {
4548
try {
49+
var newFeedback = FeedBack(
50+
id: Uuid().v1(),
51+
content: event.content,
52+
rating: event.rating,
53+
userId: _authRepository.loggedFirebaseUser.uid,
54+
timestamp: Timestamp.now(),
55+
);
4656
await _feedbackRepository.addNewFeedback(
4757
_currentProduct.id,
48-
event.feedback,
58+
newFeedback,
4959
);
5060
} catch (e) {
5161
print(e);

lib/presentation/screens/feedbacks/bloc/feedback_event.dart

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ class LoadFeedbacks extends FeedbacksEvent {
2020
}
2121

2222
class AddFeedback extends FeedbacksEvent {
23-
final FeedBack feedback;
23+
final String content;
24+
final int rating;
2425

25-
AddFeedback(this.feedback);
26+
AddFeedback({required this.content, required this.rating});
2627

2728
@override
28-
List<Object?> get props => [feedback];
29+
List<Object?> get props => [content, rating];
2930
}
3031

3132
class StarChanged extends FeedbacksEvent {

lib/presentation/screens/feedbacks/feedbacks_screen.dart

+8-5
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ class FeedbacksScreen extends StatelessWidget {
6262
}
6363

6464
_openFeedbackBottomSheet(BuildContext context) async {
65-
var newFeedback = await showModalBottomSheet<FeedBack>(
65+
var feedbackBloc = BlocProvider.of<FeedbackBloc>(context);
66+
showModalBottomSheet<FeedBack>(
6667
isScrollControlled: true,
6768
backgroundColor: Colors.white,
6869
shape: RoundedRectangleBorder(
@@ -72,10 +73,12 @@ class FeedbacksScreen extends StatelessWidget {
7273
),
7374
),
7475
context: context,
75-
builder: (BuildContext context) => FeedbackBottomSheet(),
76+
builder: (BuildContext context) {
77+
return BlocProvider(
78+
create: (_) => feedbackBloc,
79+
child: FeedbackBottomSheet(),
80+
);
81+
},
7682
);
77-
if (newFeedback != null) {
78-
BlocProvider.of<FeedbackBloc>(context).add(AddFeedback(newFeedback));
79-
}
8083
}
8184
}

lib/presentation/screens/feedbacks/widgets/feedback_bottom_sheet.dart

+9-15
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import 'package:cloud_firestore/cloud_firestore.dart';
22
import 'package:e_commerce_app/presentation/common_blocs/profile/bloc.dart';
3-
import 'package:e_commerce_app/data/entities/feedback.dart';
43
import 'package:e_commerce_app/configs/size_config.dart';
54
import 'package:e_commerce_app/constants/constants.dart';
5+
import 'package:e_commerce_app/presentation/screens/feedbacks/bloc/bloc.dart';
66
import 'package:e_commerce_app/presentation/widgets/buttons/default_button.dart';
77
import 'package:e_commerce_app/presentation/widgets/others/rating_bar.dart';
88
import 'package:e_commerce_app/utils/utils.dart';
99
import 'package:flutter/material.dart';
1010
import 'package:flutter_bloc/flutter_bloc.dart';
1111
import 'package:e_commerce_app/constants/color_constant.dart';
12-
import 'package:uuid/uuid.dart';
12+
1313

1414
class FeedbackBottomSheet extends StatefulWidget {
1515
const FeedbackBottomSheet({Key? key}) : super(key: key);
@@ -23,20 +23,14 @@ class _FeedbackBottomSheetState extends State<FeedbackBottomSheet> {
2323
int rating = 5;
2424
String content = "";
2525

26-
void onAddFeeback() {
26+
void addFeeback() {
2727
if (content.isEmpty) return;
2828

29-
ProfileState profileState = BlocProvider.of<ProfileBloc>(context).state;
30-
if (profileState is ProfileLoaded) {
31-
var newFeedback = FeedBack(
32-
id: Uuid().v1(),
33-
userId: profileState.loggedUser.id,
34-
rating: rating,
35-
content: content,
36-
timestamp: Timestamp.now(),
37-
);
38-
Navigator.pop(context, newFeedback);
39-
}
29+
BlocProvider.of<FeedbackBloc>(context).add(AddFeedback(
30+
rating: rating,
31+
content: content,
32+
));
33+
Navigator.pop(context);
4034
}
4135

4236
@override
@@ -119,7 +113,7 @@ class _FeedbackBottomSheetState extends State<FeedbackBottomSheet> {
119113
Translate.of(context).translate('send'),
120114
style: FONT_CONST.BOLD_WHITE_18,
121115
),
122-
onPressed: onAddFeeback,
116+
onPressed: addFeeback,
123117
),
124118
),
125119
);

0 commit comments

Comments
 (0)