add pdf generator
This commit is contained in:
BIN
assets/fonts/OpenSans-Bold.ttf
Normal file
BIN
assets/fonts/OpenSans-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/OpenSans-BoldItalic.ttf
Normal file
BIN
assets/fonts/OpenSans-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/OpenSans-Italic.ttf
Normal file
BIN
assets/fonts/OpenSans-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/OpenSans-Regular.ttf
Normal file
BIN
assets/fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
@@ -250,6 +250,7 @@ class AuthFb {
|
|||||||
StreamSubscription<fb.User?>? authListener;
|
StreamSubscription<fb.User?>? authListener;
|
||||||
|
|
||||||
Future<void> _start() async {
|
Future<void> _start() async {
|
||||||
|
await authListener?.cancel();
|
||||||
authListener = _fb.authStateChanges().listen((firebaseUser) {
|
authListener = _fb.authStateChanges().listen((firebaseUser) {
|
||||||
if (firebaseUser == null) {
|
if (firebaseUser == null) {
|
||||||
controller.add(null);
|
controller.add(null);
|
||||||
@@ -261,12 +262,8 @@ class AuthFb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _stop() {
|
void _stop() {
|
||||||
if (userListener != null) {
|
userListener?.cancel();
|
||||||
userListener!.cancel();
|
authListener?.cancel();
|
||||||
}
|
|
||||||
if (authListener != null) {
|
|
||||||
authListener!.cancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
controller = StreamController<User?>(
|
controller = StreamController<User?>(
|
||||||
|
|||||||
69
lib/helpers/pdf.dart
Normal file
69
lib/helpers/pdf.dart
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:open_file/open_file.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:pdf/pdf.dart';
|
||||||
|
import 'package:pdf/widgets.dart' as pw;
|
||||||
|
|
||||||
|
import '../domain/entities/carton.dart';
|
||||||
|
|
||||||
|
Future<void> generateCartonPdf(Carton carton) async {
|
||||||
|
var myTheme = pw.ThemeData.withFont(
|
||||||
|
base:
|
||||||
|
pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Regular.ttf")),
|
||||||
|
bold: pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Bold.ttf")),
|
||||||
|
italic:
|
||||||
|
pw.Font.ttf(await rootBundle.load("assets/fonts/OpenSans-Italic.ttf")),
|
||||||
|
boldItalic: pw.Font.ttf(
|
||||||
|
await rootBundle.load("assets/fonts/OpenSans-BoldItalic.ttf")),
|
||||||
|
);
|
||||||
|
|
||||||
|
final doc = pw.Document(
|
||||||
|
theme: myTheme,
|
||||||
|
);
|
||||||
|
|
||||||
|
PdfPageFormat format =
|
||||||
|
const PdfPageFormat(PdfPageFormat.inch * 3, PdfPageFormat.inch * 1);
|
||||||
|
doc.addPage(pw.Page(
|
||||||
|
pageFormat: format,
|
||||||
|
build: (pw.Context context) {
|
||||||
|
return pw.Padding(
|
||||||
|
padding: const pw.EdgeInsets.all(5),
|
||||||
|
child: pw.Row(
|
||||||
|
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: pw.CrossAxisAlignment.center,
|
||||||
|
children: <pw.Widget>[
|
||||||
|
pw.BarcodeWidget(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
color: PdfColor.fromHex("#000000"),
|
||||||
|
barcode: pw.Barcode.qrCode(),
|
||||||
|
data: carton.cartonNumber!),
|
||||||
|
pw.Padding(
|
||||||
|
padding: const pw.EdgeInsets.all(5),
|
||||||
|
child: pw.Column(
|
||||||
|
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
pw.Text(carton.cartonNumber!,
|
||||||
|
style: pw.TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
)),
|
||||||
|
pw.Text(carton.userName!,
|
||||||
|
style: pw.TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
)),
|
||||||
|
pw.Text("${carton.actualWeight} lb",
|
||||||
|
style: pw.TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: PdfColor.fromInt(0xFF757575)))
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]));
|
||||||
|
}));
|
||||||
|
|
||||||
|
List<int> d = await doc.save();
|
||||||
|
final path = (await getExternalStorageDirectory())?.path ?? "";
|
||||||
|
final file = File("$path/${carton.cartonNumber}.pdf");
|
||||||
|
await file.writeAsBytes(d, flush: true);
|
||||||
|
OpenFile.open(file.path);
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:fcs/pages/carton/model/carton_model.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import '../../../helpers/pdf.dart';
|
||||||
import '../carton_info.dart';
|
import '../carton_info.dart';
|
||||||
|
|
||||||
class CartonListRow extends StatelessWidget {
|
class CartonListRow extends StatelessWidget {
|
||||||
@@ -64,7 +67,11 @@ class CartonListRow extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 15),
|
const SizedBox(width: 15),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {}, icon: Icon(AntDesign.qrcode,color: Colors.black))
|
onPressed: () {
|
||||||
|
_pdf(box, context);
|
||||||
|
},
|
||||||
|
icon:
|
||||||
|
Icon(AntDesign.qrcode, color: Colors.black))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -100,4 +107,11 @@ class CartonListRow extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pdf(Carton carton, BuildContext context) async {
|
||||||
|
Carton? c = await context.read<CartonModel>().getCarton(carton.id!);
|
||||||
|
if (c == null) return;
|
||||||
|
|
||||||
|
generateCartonPdf(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
|
|
||||||
set setMessaginToken(token) {
|
set setMessaginToken(token) {
|
||||||
this.messagingToken = token;
|
this.messagingToken = token;
|
||||||
uploadMsgToken();
|
_uploadMsgToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting? setting;
|
Setting? setting;
|
||||||
@@ -84,24 +84,50 @@ class MainModel extends ChangeNotifier {
|
|||||||
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
|
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
|
||||||
this.packageInfo = await PackageInfo.fromPlatform();
|
this.packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
if (userListener != null) userListener!.cancel();
|
userListener?.cancel();
|
||||||
userListener =
|
userListener =
|
||||||
Services.instance.authService.getUserStream().listen((_user) {
|
Services.instance.authService.getUserStream().listen((_user) {
|
||||||
|
// if (_user != null) {
|
||||||
|
// models.forEach((m) => m.initUser(_user));
|
||||||
|
// // call diffPrivileges if privilege changed or first time login
|
||||||
|
// if (this.user == null || _user.diffPrivileges(this.user!)) {
|
||||||
|
// models.forEach((m) => m.privilegeChanged());
|
||||||
|
// }
|
||||||
|
// if (this.user == null) {
|
||||||
|
// uploadMsgToken();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (this.user != null) {
|
||||||
|
// models.forEach((m) => m.logout());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// this.user = _user;
|
||||||
|
// isLoaded = true;
|
||||||
|
|
||||||
|
bool isFirstTime = user == null && _user != null;
|
||||||
|
bool diffPrivilege =
|
||||||
|
_user != null && (user == null || user!.diffPrivileges(_user));
|
||||||
|
bool loggingOut = user != null && _user == null;
|
||||||
|
user = _user;
|
||||||
|
|
||||||
if (_user != null) {
|
if (_user != null) {
|
||||||
models.forEach((m) => m.initUser(_user));
|
for (final m in models) {
|
||||||
// call diffPrivileges if privilege changed or first time login
|
m.initUser(_user);
|
||||||
if (this.user == null || _user.diffPrivileges(this.user!)) {
|
if (diffPrivilege) {
|
||||||
models.forEach((m) => m.privilegeChanged());
|
m.privilegeChanged();
|
||||||
}
|
}
|
||||||
if (this.user == null) {
|
|
||||||
uploadMsgToken();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.user != null) {
|
|
||||||
models.forEach((m) => m.logout());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.user = _user;
|
if (loggingOut) {
|
||||||
|
for (final m in models) {
|
||||||
|
m.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFirstTime) {
|
||||||
|
_uploadMsgToken();
|
||||||
|
}
|
||||||
|
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
@@ -136,20 +162,23 @@ class MainModel extends ChangeNotifier {
|
|||||||
return authResult;
|
return authResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void>? uploadMsgToken() {
|
Future<void> _uploadMsgToken() {
|
||||||
if (messagingToken == null || user == null) return null;
|
log.info("messagingToken:$messagingToken::user:$user");
|
||||||
|
if (messagingToken == null || user == null) return Future.value();
|
||||||
return Services.instance.userService.uploadMsgToken(messagingToken!);
|
return Services.instance.userService.uploadMsgToken(messagingToken!);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void>? removeMsgToken() {
|
Future<void> _removeMsgToken() {
|
||||||
if (messagingToken == null || user == null) return null;
|
if (messagingToken == null || user == null) return Future.value();
|
||||||
return Services.instance.userService.removeMsgToken(messagingToken!);
|
return Services.instance.userService.removeMsgToken(messagingToken!);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> signout() async {
|
Future<void> signout() async {
|
||||||
try {
|
try {
|
||||||
await removeMsgToken();
|
await _removeMsgToken();
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
log.info(e.toString());
|
||||||
|
}
|
||||||
await Services.instance.authService.signout();
|
await Services.instance.authService.signout();
|
||||||
models.forEach((m) => m.logout());
|
models.forEach((m) => m.logout());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ dependencies:
|
|||||||
cached_network_image: ^3.3.1
|
cached_network_image: ^3.3.1
|
||||||
flutter_cache_manager: ^3.1.2
|
flutter_cache_manager: ^3.1.2
|
||||||
flutter_vector_icons: ^2.0.0
|
flutter_vector_icons: ^2.0.0
|
||||||
|
open_file: ^3.3.2
|
||||||
|
pdf: ^3.10.8
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -65,6 +67,7 @@ flutter:
|
|||||||
assets:
|
assets:
|
||||||
- assets/
|
- assets/
|
||||||
- assets/local/
|
- assets/local/
|
||||||
|
- assets/fonts/
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: Roboto
|
- family: Roboto
|
||||||
|
|||||||
Reference in New Issue
Block a user