Compare commits
6 commits
cb69b25b98
...
6a565815fc
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a565815fc | |||
| 5566610020 | |||
| 9268a3337d | |||
| cf9cdafc6b | |||
| c3914325cf | |||
| 9ef7e5ffe3 |
11 changed files with 285 additions and 55 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application android:label="ocbo_esign_mobile" android:name="${applicationName}" android:icon="@mipmap/launcher_icon">
|
||||
<application android:label="OCBO eSign" android:name="${applicationName}" android:icon="@mipmap/launcher_icon">
|
||||
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:taskAffinity="" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
|
|
|
|||
BIN
assets/ocbologo.webp
Normal file
BIN
assets/ocbologo.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
|
|
@ -13,7 +13,7 @@
|
|||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>ocbo_esign_mobile</string>
|
||||
<string>OCBO eSign</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:ocbo_esign_mobile/blocs/application/functions/bloc_getapplication.dart';
|
||||
import 'package:ocbo_esign_mobile/blocs/qr/functions/bloc_getqr.dart';
|
||||
import 'package:ocbo_esign_mobile/functions/get_api.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/box_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/loading_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/text_widget.dart';
|
||||
|
||||
class ApplicationInfoPage extends StatefulWidget {
|
||||
|
|
@ -12,13 +16,51 @@ class ApplicationInfoPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ApplicationInfoPageState extends State<ApplicationInfoPage> {
|
||||
// final NumberFormat formatter = NumberFormat('#,###.##');
|
||||
final NumberFormat formatter = NumberFormat.currency(symbol: '₱ ', decimalDigits: 2);
|
||||
|
||||
late String _applicationNo = '';
|
||||
late String _name = '';
|
||||
late String _monthApproved = '';
|
||||
late String _dayApproved = '';
|
||||
late String _yearApproved = '';
|
||||
late String _monthPrinted = '';
|
||||
late String _dayPrinted = '';
|
||||
late String _yearPrinted = '';
|
||||
late String _amount = '';
|
||||
late bool _isLoading = false;
|
||||
|
||||
void _getInfo() async {
|
||||
final applicationBloc = await blocGetApplication(context);
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
late String applicationBloc = '';
|
||||
late String qrBloc = '';
|
||||
|
||||
if (context.mounted) {
|
||||
applicationBloc = await blocGetApplication(context);
|
||||
// ignore: use_build_context_synchronously
|
||||
qrBloc = await blocGetQr(context);
|
||||
}
|
||||
|
||||
final id = await getApi('get-esignid-byname', qrBloc, null);
|
||||
final responseApproval = await getApi('get-infoapproval-electrical', applicationBloc, id["result"].toString());
|
||||
final responsePrinted = await getApi('get-infoprinted-electrical', applicationBloc, id["result"].toString());
|
||||
final responseAmount = await getApi('get-totalamount-electrical', applicationBloc, null);
|
||||
final formattedAmount = formatter.format(double.parse(responseAmount["result"].toString()));
|
||||
|
||||
setState(() {
|
||||
_applicationNo = applicationBloc;
|
||||
_name = responseApproval["result"].toString();
|
||||
_monthApproved = responseApproval["result2"].toString();
|
||||
_dayApproved = responseApproval["result3"].toString();
|
||||
_yearApproved = responseApproval["result4"].toString();
|
||||
_monthPrinted = responsePrinted["result"].toString();
|
||||
_dayPrinted = responsePrinted["result2"].toString();
|
||||
_yearPrinted = responsePrinted["result3"].toString();
|
||||
_amount = formattedAmount;
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -30,36 +72,124 @@ class _ApplicationInfoPageState extends State<ApplicationInfoPage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color.fromRGBO(37, 25, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(25, 46, 41, 1),
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Container(
|
||||
padding: EdgeInsets.only(left: 16, right: 16),
|
||||
alignment: Alignment.center,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color.fromRGBO(37, 25, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(22, 33, 44, 1),
|
||||
Color.fromRGBO(25, 46, 41, 1),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const Gap(88),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
padding: EdgeInsets.all(8),
|
||||
content: _isLoading
|
||||
? Center(child: LoadingWidget(text: 'Gathering Data, please wait'))
|
||||
: Center(child: TextWidget(text: _applicationNo, bold: true, size: 30)),
|
||||
),
|
||||
const Gap(16),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
padding: EdgeInsets.all(8),
|
||||
content: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const TextWidget(
|
||||
text: 'Name of Owner',
|
||||
bold: false,
|
||||
size: 8,
|
||||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||||
),
|
||||
const Gap(4),
|
||||
TextWidget(text: _name, bold: false, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
width: 140,
|
||||
padding: EdgeInsets.all(0),
|
||||
content: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const TextWidget(
|
||||
text: 'Approved Date',
|
||||
bold: false,
|
||||
size: 8,
|
||||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||||
),
|
||||
const Gap(4),
|
||||
TextWidget(text: _monthApproved, bold: false, size: 16),
|
||||
TextWidget(text: _dayApproved, bold: true, size: 40),
|
||||
TextWidget(text: _yearApproved, bold: false, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
width: 140,
|
||||
padding: EdgeInsets.all(0),
|
||||
content: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const TextWidget(
|
||||
text: 'Printed Date',
|
||||
bold: false,
|
||||
size: 8,
|
||||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||||
),
|
||||
const Gap(4),
|
||||
TextWidget(text: _monthPrinted, bold: false, size: 16),
|
||||
TextWidget(text: _dayPrinted, bold: true, size: 40),
|
||||
TextWidget(text: _yearPrinted, bold: false, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Gap(8),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
padding: EdgeInsets.all(8),
|
||||
content: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const TextWidget(
|
||||
text: 'Total Amount',
|
||||
bold: false,
|
||||
size: 8,
|
||||
color: Color.fromRGBO(255, 255, 255, 0.8),
|
||||
),
|
||||
const Gap(4),
|
||||
TextWidget(text: _amount, bold: true, size: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const Gap(88),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
content: Center(child: TextWidget(text: _applicationNo, bold: true)),
|
||||
),
|
||||
const Gap(16),
|
||||
BoxWidget(
|
||||
circular: 16,
|
||||
content: Center(child: TextWidget(text: _applicationNo, bold: true)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,18 +46,13 @@ class IndexPage extends StatelessWidget {
|
|||
const Gap(88),
|
||||
const ImageWidget(imagePath: 'assets/esign-mobile.webp', size: 160, measureByHeight: false),
|
||||
const Gap(20),
|
||||
const TextWidget(
|
||||
text: "OCBO e-Sign",
|
||||
color: Color.fromARGB(255, 244, 243, 243),
|
||||
bold: true,
|
||||
size: 34,
|
||||
),
|
||||
const TextWidget(text: "OCBO e-Sign", color: Color.fromRGBO(244, 243, 243, 1), bold: true, size: 34),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: (screenWidth / 2) - 100),
|
||||
child: const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextWidget(text: "Mobile", color: Color.fromARGB(255, 244, 243, 243), bold: false, size: 16),
|
||||
TextWidget(text: "Mobile", color: Color.fromRGBO(244, 243, 243, 1), bold: false, size: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -85,15 +80,36 @@ class IndexPage extends StatelessWidget {
|
|||
const MaxGap(516),
|
||||
const Opacity(
|
||||
opacity: 0.7,
|
||||
child: ImageWidget(imagePath: 'assets/pat-alcala.webp', size: 74, measureByHeight: false),
|
||||
),
|
||||
const Gap(4),
|
||||
const TextWidget(
|
||||
text: "Developed By: Pat Alcala",
|
||||
color: Color.fromRGBO(244, 243, 243, 0.7),
|
||||
bold: false,
|
||||
size: 10,
|
||||
child: Column(
|
||||
children: [
|
||||
ImageWidget(imagePath: 'assets/ocbologo.webp', size: 26, measureByHeight: false),
|
||||
Gap(8),
|
||||
TextWidget(text: '© 2026 Office of the City Building Official', size: 10),
|
||||
Gap(8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
TextWidget(
|
||||
text: "Developed By:",
|
||||
color: Color.fromRGBO(244, 243, 243, 0.7),
|
||||
bold: false,
|
||||
size: 10,
|
||||
),
|
||||
Gap(4),
|
||||
ImageWidget(imagePath: 'assets/pat-alcala.webp', size: 60, measureByHeight: false),
|
||||
Gap(4),
|
||||
TextWidget(
|
||||
text: "Pat Alcala",
|
||||
color: Color.fromRGBO(244, 243, 243, 0.7),
|
||||
bold: false,
|
||||
size: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const Gap(24),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:ocbo_esign_mobile/functions/get_api.dart';
|
|||
import 'package:ocbo_esign_mobile/widgets/box_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/image_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/input_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/loading_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/text_widget.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
|
|
@ -19,7 +20,7 @@ class ValidateDetailPage extends StatefulWidget {
|
|||
|
||||
class _ValidateDetailPageState extends State<ValidateDetailPage> {
|
||||
final _searchController = TextEditingController();
|
||||
final NumberFormat formatter = NumberFormat('#,###.##');
|
||||
final NumberFormat formatter = NumberFormat('#,###');
|
||||
final dateFormatter = DateFormat('yyyy-MM-dd');
|
||||
// final Color greenColor = const Color(0xFF4CCE51);
|
||||
late bool isLoading = false;
|
||||
|
|
@ -129,7 +130,7 @@ class _ValidateDetailPageState extends State<ValidateDetailPage> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
isLoading
|
||||
? TextWidget(text: 'Loading Data, please wait', size: 20, bold: false)
|
||||
? LoadingWidget(text: 'Loading Data, please wait')
|
||||
: Column(
|
||||
children: [
|
||||
TextWidget(text: formatter.format(_total), size: 50, bold: true),
|
||||
|
|
@ -169,7 +170,7 @@ class _ValidateDetailPageState extends State<ValidateDetailPage> {
|
|||
const Gap(4),
|
||||
TextWidget(text: 'Time: ${_timeList[index]}', size: 10, opacity: 1),
|
||||
const Gap(4),
|
||||
TextWidget(text: 'Tap to show details', size: 9, opacity: 0.6),
|
||||
const TextWidget(text: 'Tap to show details', size: 9, opacity: 0.6),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:mobile_scanner/mobile_scanner.dart';
|
|||
import 'package:ocbo_esign_mobile/blocs/qr/functions/bloc_setqr.dart';
|
||||
import 'package:ocbo_esign_mobile/functions/get_api.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/button_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/loading_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/text_widget.dart';
|
||||
import 'package:vibration/vibration.dart';
|
||||
|
||||
|
|
@ -26,13 +27,18 @@ class BarcodeScannerScreen extends StatefulWidget {
|
|||
|
||||
class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
||||
final Color _redColorShade = const Color.fromRGBO(86, 38, 38, 0.2);
|
||||
final Color _redColor = const Color.fromRGBO(235, 88, 115, 0.91);
|
||||
final Color _greenColorShade = const Color.fromARGB(51, 41, 115, 43);
|
||||
final Color _greenColor = const Color.fromRGBO(76, 206, 81, 0.91);
|
||||
final Color _redColor = const Color.fromRGBO(235, 88, 115, 0.8);
|
||||
final Color _greenColorShade = const Color.fromRGBO(41, 115, 43, 0.2);
|
||||
final Color _greenColor = const Color.fromRGBO(76, 206, 81, 0.8);
|
||||
|
||||
late String _qrResult = '';
|
||||
late bool _scanning = false;
|
||||
|
||||
void readQr(String value) async {
|
||||
setState(() {
|
||||
_scanning = true;
|
||||
});
|
||||
|
||||
if (value.contains('OCBO e-Sign')) {
|
||||
final qr = value.substring(35);
|
||||
final response = await getApi('check-qr', qr, null);
|
||||
|
|
@ -40,15 +46,18 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
|
||||
if (result != '') {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = result;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = 'non-exist';
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = 'invalid';
|
||||
});
|
||||
|
||||
|
|
@ -61,6 +70,10 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
}
|
||||
|
||||
void tryQR() async {
|
||||
setState(() {
|
||||
_scanning = true;
|
||||
});
|
||||
|
||||
final value = "Use OCBO e-Sign Validator - scanid=0918d59e";
|
||||
|
||||
if (value.contains('OCBO e-Sign')) {
|
||||
|
|
@ -70,10 +83,12 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
|
||||
if (result != null) {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = result;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = 'non-exist';
|
||||
});
|
||||
|
||||
|
|
@ -85,6 +100,7 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
}
|
||||
} else {
|
||||
setState(() {
|
||||
_scanning = false;
|
||||
_qrResult = 'invalid';
|
||||
});
|
||||
|
||||
|
|
@ -181,6 +197,13 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
),
|
||||
const Gap(24),
|
||||
// ButtonWidget(text: 'Try API', disabled: false, onPressed: tryQR),
|
||||
if (_scanning)
|
||||
Column(
|
||||
children: [
|
||||
const Gap(16),
|
||||
const LoadingWidget(text: 'Reading QR'),
|
||||
],
|
||||
),
|
||||
if (_qrResult.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
|
|
@ -214,7 +237,20 @@ class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
|
|||
),
|
||||
),
|
||||
const Gap(16),
|
||||
TextWidget(text: 'QR Detected is not OCBO e-Sign', bold: true, size: 20, color: _redColor),
|
||||
Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: _redColor, width: 2),
|
||||
color: _redColorShade,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: TextWidget(
|
||||
text: 'Not OCBO e-Sign QR detected',
|
||||
bold: true,
|
||||
size: 18,
|
||||
color: _redColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
else if (_qrResult == 'non-exist')
|
||||
|
|
|
|||
|
|
@ -4,20 +4,29 @@ class BoxWidget extends StatelessWidget {
|
|||
final Widget content;
|
||||
final double? circular;
|
||||
final CrossAxisAlignment? alignment;
|
||||
final double? width;
|
||||
final EdgeInsets? padding;
|
||||
// final double? titleSize;
|
||||
|
||||
const BoxWidget({super.key, required this.content, this.circular = 8, this.alignment = CrossAxisAlignment.start});
|
||||
const BoxWidget({
|
||||
super.key,
|
||||
required this.content,
|
||||
this.circular = 8,
|
||||
this.alignment = CrossAxisAlignment.start,
|
||||
this.width,
|
||||
this.padding,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
padding: padding ?? EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(circular ?? 8),
|
||||
color: Color.fromRGBO(16, 22, 28, 0.584),
|
||||
border: Border.all(color: const Color.fromRGBO(41, 60, 78, 0.914)),
|
||||
),
|
||||
width: MediaQuery.of(context).size.width - 30,
|
||||
width: width ?? MediaQuery.of(context).size.width - 30,
|
||||
child: Column(
|
||||
crossAxisAlignment: alignment ?? CrossAxisAlignment.start,
|
||||
children: [Padding(padding: const EdgeInsets.all(16), child: content)],
|
||||
|
|
|
|||
28
lib/widgets/loading_widget.dart
Normal file
28
lib/widgets/loading_widget.dart
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:loading_animation_widget/loading_animation_widget.dart';
|
||||
import 'package:ocbo_esign_mobile/widgets/text_widget.dart';
|
||||
|
||||
class LoadingWidget extends StatelessWidget {
|
||||
final String? text;
|
||||
|
||||
const LoadingWidget({super.key, this.text});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
children: [
|
||||
LoadingAnimationWidget.discreteCircle(
|
||||
color: const Color.fromRGBO(164, 168, 229, 0.8),
|
||||
secondRingColor: const Color.fromRGBO(141, 145, 210, 0.8),
|
||||
thirdRingColor: const Color.fromRGBO(117, 123, 204, 0.8),
|
||||
size: 60,
|
||||
),
|
||||
const Gap(16),
|
||||
TextWidget(text: text ?? '', size: 16, bold: true),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -376,6 +376,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
loading_animation_widget:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: loading_animation_widget
|
||||
sha256: "9fe23381f3096e902f39e87e487648ff7f74925e86234353fa885bb9f6c98004"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ dependencies:
|
|||
flutter_bloc: ^9.1.1
|
||||
vibration: ^3.1.4
|
||||
intl: ^0.20.2
|
||||
loading_animation_widget: ^1.3.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
@ -48,3 +49,4 @@ flutter:
|
|||
- assets/esign.webp
|
||||
- assets/esign-mobile.webp
|
||||
- assets/esign-check.webp
|
||||
- assets/ocbologo.webp
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue