Skip to content

Commit

Permalink
Fix some issues and view
Browse files Browse the repository at this point in the history
  • Loading branch information
dipu-bd committed Jun 9, 2021
1 parent 78c41b2 commit 315bb0a
Show file tree
Hide file tree
Showing 14 changed files with 353 additions and 79 deletions.
Binary file added lib/res/RobotoSlab-Light.ttf
Binary file not shown.
Binary file added lib/res/pattern_back.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 49 additions & 3 deletions lib/src/blocs/repository.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:crypto/crypto.dart' show sha256;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:sales_tracker/src/blocs/global_bloc.dart';
Expand All @@ -14,19 +15,21 @@ class Repository {
late final FirebaseFirestore firestore;
late final CollectionReference<Product> _products;
late final CollectionReference<SalesRecord> _sales;
late final DocumentReference<Map<String, dynamic>> _userDoc;

Repository({required this.user}) {
firestore = FirebaseFirestore.instance;
final userDoc = firestore.collection('users').doc(user.uid);
_products = userDoc.collection("products").withConverter<Product>(
_userDoc = firestore.collection('users').doc(user.uid);
_products = _userDoc.collection("products").withConverter<Product>(
fromFirestore: (snap, _) => Product.fromJson(snap.id, snap.data()!),
toFirestore: (model, _) => model.toJson(),
);
_sales = userDoc.collection("sales").withConverter<SalesRecord>(
_sales = _userDoc.collection("sales").withConverter<SalesRecord>(
fromFirestore: (snap, _) =>
SalesRecord.fromJson(snap.id, snap.data()!),
toFirestore: (model, _) => model.toJson(),
);
_saveUserData(_userDoc, user);
}

/// Get all products
Expand Down Expand Up @@ -66,6 +69,41 @@ class Repository {
);
}

void _saveUserData(DocumentReference doc, User user) {
doc.update({
'uid': user.uid,
'email': user.email,
'displayName': user.displayName,
'phoneNumber': user.phoneNumber,
'photoURL': user.photoURL,
'tenantId': user.tenantId,
'creationTime': user.metadata.creationTime?.millisecondsSinceEpoch,
'lastSignInTime': user.metadata.lastSignInTime?.millisecondsSinceEpoch,
'isAnonymous': user.isAnonymous,
});
}

Future<bool> matchPassword(String password) async {
final hash = sha256.convert(password.codeUnits).toString();
final snapshot = await _userDoc.get();
final data = snapshot.data() ?? {};
if (!data.containsKey('password')) {
return false;
}
return hash == data['password'];
}

Future<void> savePassword(String oldPassword, String newPassword) async {
final oldHash = sha256.convert(oldPassword.codeUnits).toString();
final newHash = sha256.convert(newPassword.codeUnits).toString();
final snapshot = await _userDoc.get();
final data = snapshot.data() ?? {};
if (data.containsKey('password') && oldHash != data['password']) {
throw Exception('Password mismatch');
}
await _userDoc.update({'password': newHash});
}

Future<DocumentReference<Product>> addProduct(Product product) {
return _products.add(product);
}
Expand All @@ -92,4 +130,12 @@ class Repository {
return _sales.add(sales);
});
}

Future<void> clearAllData() async {
await _userDoc.delete();
final sales = await _sales.get();
final products = await _products.get();
await Future.wait(products.docs.map((doc) => doc.reference.delete()));
await Future.wait(sales.docs.map((doc) => doc.reference.delete()));
}
}
34 changes: 15 additions & 19 deletions lib/src/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import 'package:flutter/material.dart';
import 'package:sales_tracker/src/blocs/repository.dart';
import 'package:sales_tracker/src/models/product.dart';
import 'package:sales_tracker/src/pages/report_page.dart';
import 'package:sales_tracker/src/pages/widgets/product_form_dialog.dart';
import 'package:sales_tracker/src/pages/widgets/error_message.dart';
import 'package:sales_tracker/src/pages/widgets/home_page_drawer.dart';
import 'package:sales_tracker/src/pages/widgets/product_form_dialog.dart';
import 'package:sales_tracker/src/pages/widgets/product_item.dart';

class HomePage extends StatelessWidget {
Expand All @@ -14,6 +15,9 @@ class HomePage extends StatelessWidget {
backgroundColor: Colors.grey[300],
appBar: buildAppBar(context),
floatingActionButton: buildAddItemButton(context),
drawer: Drawer(
child: HomePageDrawer(),
),
body: StreamBuilder<List<Product>>(
stream: Repository.of(context).allProducts,
builder: (context, snapshot) {
Expand Down Expand Up @@ -64,26 +68,18 @@ class HomePage extends StatelessWidget {
return AppBar(
title: Text("Sales Tracker"),
actions: [
Container(
height: 26,
margin: EdgeInsets.all(10),
child: ElevatedButton.icon(
onPressed: () {
ReportPage.display(context);
},
icon: Icon(Icons.history),
label: Text('Report'),
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
),
ElevatedButton.icon(
onPressed: () => ReportPage.display(context),
icon: Icon(Icons.history),
label: Text('Report'),
style: ButtonStyle(
elevation: MaterialStateProperty.all(0),
),
),
IconButton(
onPressed: () {
FirebaseAuth.instance.signOut();
},
icon: Icon(Icons.logout),
),
// IconButton(
// onPressed: () => FirebaseAuth.instance.signOut(),
// icon: Icon(Icons.logout),
// ),
],
);
}
Expand Down
40 changes: 26 additions & 14 deletions lib/src/pages/login_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:rive/rive.dart';
import 'package:sales_tracker/src/pages/widgets/error_message.dart';

class LoginPage extends StatelessWidget {
@override
Expand All @@ -19,7 +20,7 @@ class LoginPage extends StatelessWidget {
color: Color(0xff62758d),
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: signInWithGoogle,
onPressed: () => signInWithGoogle(context),
child: ListTile(
title: Text('SIGN IN'),
trailing: Icon(Icons.login),
Expand All @@ -34,21 +35,32 @@ class LoginPage extends StatelessWidget {
);
}

Future<UserCredential> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
void signInWithGoogle(BuildContext context) async {
try {
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();

// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth =
await googleUser!.authentication;
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth =
await googleUser!.authentication;

// Create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// Create a new credential
final auth = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);

// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
// Once signed in, return the UserCredential
await FirebaseAuth.instance.signInWithCredential(auth);
} catch (err) {
showDialog(
context: context,
builder: (_) => ErrorMessage(
messageText: 'Failed to sign in',
errorDetails: err,
onDismiss: () => Navigator.of(context).pop(),
),
);
}
}
}
65 changes: 37 additions & 28 deletions lib/src/pages/report_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,36 @@ import 'package:sales_tracker/src/pages/widgets/report_view.dart';
import 'package:sales_tracker/src/utils/report_generate.dart';

class ReportPage extends StatelessWidget {
static Future<void> display(BuildContext context) {
static Future<void> display(BuildContext context) async {
DateTime now = DateTime.now();
DateTime startOfMonth = DateTime(now.year, now.month);
return showDateRangePicker(
DateTimeRange? range = await showDateRangePicker(
context: context,
saveText: 'Generate Report',
firstDate: DateTime(now.year - 10),
lastDate: DateTime(now.year + 1).subtract(Duration(microseconds: 1)),
lastDate: DateTime(now.year + 10).subtract(Duration(microseconds: 1)),
initialDateRange: DateTimeRange(
start: startOfMonth,
end: DateTime.now(),
),
helpText: 'View Report',
saveText: 'Generate',
useRootNavigator: false,
).then((range) {
if (range == null) return null;
DateTime start = range.start;
DateTime end = range.end;
return Navigator.of(context).push(
MaterialPageRoute(
maintainState: true,
fullscreenDialog: false,
builder: (_) => ReportPage(
startDate: DateTime(start.year, start.month, start.day),
endDate: DateTime(end.year, end.month, end.day)
.add(Duration(days: 1))
.subtract(Duration(milliseconds: 1)),
),
);

if (range == null) return null;
DateTime start = range.start;
DateTime end = range.end;

await Navigator.of(context).push(
MaterialPageRoute(
maintainState: true,
fullscreenDialog: false,
builder: (_) => ReportPage(
startDate: DateTime(start.year, start.month, start.day),
endDate: DateTime(end.year, end.month, end.day)
.add(Duration(days: 1))
.subtract(Duration(milliseconds: 1)),
),
);
});
),
);
}

final DateTime startDate;
Expand All @@ -54,6 +53,7 @@ class ReportPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
appBar: AppBar(
title: Text('Report'),
),
Expand Down Expand Up @@ -82,20 +82,29 @@ class ReportPage extends StatelessWidget {
}
return Column(
children: [
Expanded(child: ReportView(snapshot.data!)),
ListTile(
tileColor: Colors.green,
title: Text('Save as PDF'),
trailing: Icon(Icons.save_alt),
onTap: () => _generatePdf(context, snapshot.data!),
Expanded(
child: ReportView(snapshot.data!),
),
buildSaveAsPdfButton(context, snapshot.data!),
],
);
}
},
);
}

Widget buildSaveAsPdfButton(BuildContext context, Report report) {
if (report.totalItems == 0) {
return Container();
}
return ListTile(
tileColor: Colors.green,
title: Text('Save as PDF'),
trailing: Icon(Icons.save_alt),
onTap: () => _generatePdf(context, report),
);
}

void _generatePdf(BuildContext context, Report report) async {
Uint8List? result = await showDialog<Uint8List?>(
context: context,
Expand Down
9 changes: 7 additions & 2 deletions lib/src/pages/widgets/error_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ class ErrorMessage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(titleText),
title: Text(
titleText,
style: TextStyle(color: Colors.redAccent),
),
elevation: 5,
actionsPadding: EdgeInsets.symmetric(horizontal: 10),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(messageText),
] +
Expand All @@ -43,11 +47,12 @@ class ErrorMessage extends StatelessWidget {

Widget buildErrorDetails() {
return Container(
padding: EdgeInsets.all(10),
child: Text(
'$errorDetails',
style: TextStyle(
fontSize: 12,
fontFamily: 'monospaced',
fontSize: 11,
),
),
decoration: BoxDecoration(
Expand Down
Loading

0 comments on commit 315bb0a

Please sign in to comment.