update
This commit is contained in:
parent
b299297fa5
commit
11fc5c43bf
29 changed files with 1041 additions and 124 deletions
|
|
@ -6,6 +6,7 @@ import 'package:pharmacy_mobile/pages/add_medicine_page.dart';
|
|||
import 'package:pharmacy_mobile/pages/add_stock_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/add_type_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/customer_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/customer_pages/customer_itemview_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/delete_stock_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/list_stocks_page.dart';
|
||||
import 'package:pharmacy_mobile/pages/login_page.dart';
|
||||
|
|
@ -92,10 +93,14 @@ final _router = GoRouter(
|
|||
path: '/customer',
|
||||
builder: (context, state) => const CustomerPage(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'itemview',
|
||||
path: '/itemview',
|
||||
builder: (context, state) => const CustomerItemviewPage(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
|
|
@ -5,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:gap/gap.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:internet_connection_checker/internet_connection_checker.dart';
|
||||
import 'package:pharmacy_mobile/security/encryption.dart';
|
||||
import 'package:pharmacy_mobile/tables/ref_categories.dart';
|
||||
import 'package:pharmacy_mobile/tables/ref_generic_names.dart';
|
||||
import 'package:pharmacy_mobile/tables/ref_manufactorers.dart';
|
||||
|
|
@ -21,6 +23,7 @@ import 'package:pharmacy_mobile/widgets/snackbar_widget.dart';
|
|||
import 'package:pharmacy_mobile/widgets/text_widget.dart';
|
||||
import 'package:pharmacy_mobile/widgets/title_widget.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
|
||||
|
|
@ -40,6 +43,7 @@ class _AddMedicinePageState extends State<AddMedicinePage> {
|
|||
final _refMedicines = RefMedicines();
|
||||
final _storage = Storage();
|
||||
final _nameController = TextEditingController();
|
||||
final _barcodeController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
bool _isLoading = false;
|
||||
|
||||
|
|
@ -134,17 +138,37 @@ class _AddMedicinePageState extends State<AddMedicinePage> {
|
|||
_selectedManufactorer = manufactorer;
|
||||
}
|
||||
|
||||
Future<void> _scanBarcode() async {
|
||||
String? barcode = await SimpleBarcodeScanner.scanBarcode(
|
||||
context,
|
||||
// barcodeAppBar: const BarcodeAppBar(
|
||||
// // appBarTitle: 'Test',
|
||||
// // centerTitle: false,
|
||||
// // enableBackButton: false,
|
||||
// // backButtonIcon: Icon(Icons.arrow_back_ios),
|
||||
// ),
|
||||
// isShowFlashIcon: true,
|
||||
delayMillis: 2000,
|
||||
scanType: ScanType.barcode,
|
||||
cameraFace: CameraFace.back,
|
||||
);
|
||||
_barcodeController.text = barcode != '-1' ? barcode ?? '' : '';
|
||||
}
|
||||
|
||||
void _saveMedicine() async {
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
try {
|
||||
final String encrpytedBarcode = await encrypt(_barcodeController.text);
|
||||
|
||||
if (await InternetConnectionChecker.instance.hasConnection) {
|
||||
final medName = _nameController.text;
|
||||
final medGenericUUID = await _refGenericNames.getUUID(_selectedGeneric);
|
||||
final medTypeUUID = await _refTypes.getUUID(_selectedType);
|
||||
final medManufactorerUUID = await _refManufactorer.getUUID(_selectedManufactorer);
|
||||
|
||||
await _refMedicines.postMedicine(uuid, medName, medManufactorerUUID, medGenericUUID, medTypeUUID);
|
||||
await _refMedicines.postMedicine(
|
||||
uuid, medName, medManufactorerUUID, medGenericUUID, medTypeUUID, encrpytedBarcode);
|
||||
} else {
|
||||
if (mounted) {
|
||||
showNotification(context, 'Error: No Internet Connection', false);
|
||||
|
|
@ -191,6 +215,7 @@ class _AddMedicinePageState extends State<AddMedicinePage> {
|
|||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_focusNode.dispose();
|
||||
_barcodeController.dispose();
|
||||
|
||||
_genericNameList = [];
|
||||
_selectedGeneric = '';
|
||||
|
|
@ -245,6 +270,10 @@ class _AddMedicinePageState extends State<AddMedicinePage> {
|
|||
list: _manufactorerList,
|
||||
listTitle: 'manufactorer_name',
|
||||
onChanged: _updateManufactorer),
|
||||
const Gap(16),
|
||||
InputWidget(label: 'Barcode', controller: _barcodeController),
|
||||
const Gap(8),
|
||||
ButtonWidget(text: 'Scan Barcode', onPressed: _scanBarcode),
|
||||
const Gap(32),
|
||||
if (imageUrl.isNotEmpty)
|
||||
Center(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:pharmacy_mobile/tables/ref_medicines.dart';
|
||||
|
|
@ -10,6 +12,7 @@ import 'package:pharmacy_mobile/widgets/input_widget.dart';
|
|||
import 'package:pharmacy_mobile/widgets/page_background_widget.dart';
|
||||
import 'package:pharmacy_mobile/widgets/text_widget.dart';
|
||||
import 'package:pharmacy_mobile/widgets/title_widget.dart';
|
||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
|
||||
|
||||
class AddStockPage extends StatefulWidget {
|
||||
const AddStockPage({super.key});
|
||||
|
|
@ -18,7 +21,7 @@ class AddStockPage extends StatefulWidget {
|
|||
State<AddStockPage> createState() => _AddStockPageState();
|
||||
}
|
||||
|
||||
class _AddStockPageState extends State<AddStockPage> {
|
||||
class _AddStockPageState extends State<AddStockPage> with WidgetsBindingObserver {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final _refMedicines = RefMedicines();
|
||||
|
|
@ -31,6 +34,7 @@ class _AddStockPageState extends State<AddStockPage> {
|
|||
late List _medicineList = [];
|
||||
late String _selectedMedicine = '';
|
||||
late DateTime selectedDate = DateTime.now();
|
||||
late String barcode = '';
|
||||
|
||||
void autoRun() async {
|
||||
_medicineList = await _refMedicines.getList();
|
||||
|
|
@ -101,7 +105,34 @@ class _AddStockPageState extends State<AddStockPage> {
|
|||
value: selectedDate,
|
||||
),
|
||||
const Gap(32),
|
||||
ButtonWidget(text: 'Add Stock', onPressed: _saveStock)
|
||||
ButtonWidget(text: 'Add Stock', onPressed: _saveStock),
|
||||
const Gap(16),
|
||||
ButtonWidget(
|
||||
text: 'Barcode',
|
||||
onPressed: () async {
|
||||
String? bc = await SimpleBarcodeScanner.scanBarcode(
|
||||
context,
|
||||
// barcodeAppBar: const BarcodeAppBar(
|
||||
// // appBarTitle: 'Test',
|
||||
// // centerTitle: false,
|
||||
// // enableBackButton: false,
|
||||
// // backButtonIcon: Icon(Icons.arrow_back_ios),
|
||||
// ),
|
||||
// isShowFlashIcon: true,
|
||||
delayMillis: 2000,
|
||||
scanType: ScanType.barcode,
|
||||
cameraFace: CameraFace.back,
|
||||
);
|
||||
setState(() {
|
||||
barcode = bc as String;
|
||||
});
|
||||
},
|
||||
),
|
||||
const Gap(16),
|
||||
TextWidget(
|
||||
text: barcode,
|
||||
size: 14,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -15,19 +15,15 @@ class CustomerCartPage extends StatelessWidget {
|
|||
body: PageBackgroundWidget(
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
const Gap(96),
|
||||
const TitleWidget(
|
||||
firstTextSize: 14,
|
||||
secondTextSize: 24,
|
||||
logoSize: 90,
|
||||
),
|
||||
const Gap(32),
|
||||
const TextWidget(text: 'My Cart'),
|
||||
const Gap(16),
|
||||
],
|
||||
)
|
||||
const Gap(96),
|
||||
const TitleWidget(
|
||||
firstTextSize: 14,
|
||||
secondTextSize: 24,
|
||||
logoSize: 90,
|
||||
),
|
||||
const Gap(32),
|
||||
const TextWidget(text: 'My Cart'),
|
||||
const Gap(16),
|
||||
],
|
||||
)));
|
||||
}
|
||||
|
|
|
|||
31
lib/pages/customer_pages/customer_itemview_page.dart
Normal file
31
lib/pages/customer_pages/customer_itemview_page.dart
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:pharmacy_mobile/tables/storage.dart';
|
||||
import 'package:pharmacy_mobile/widgets/page_background_widget.dart';
|
||||
|
||||
class CustomerItemviewPage extends StatelessWidget {
|
||||
const CustomerItemviewPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final storage = Storage();
|
||||
|
||||
void getURL() async {
|
||||
final image = await storage.getPublicURL('ref_medicines_images', 'cb6eafdb-d86f-460a-9571-44446570d4cb.webp');
|
||||
// setState(() {
|
||||
// imageUrl = image;
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: PageBackgroundWidget(
|
||||
child: Column(
|
||||
children: [
|
||||
Image.network('imageUrl',
|
||||
fit: BoxFit.cover,
|
||||
width: 21,
|
||||
height: 21 / 1.4,
|
||||
cacheWidth: (21 * MediaQuery.of(context).devicePixelRatio).round()),
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -76,6 +76,7 @@ class _CustomerSearchPageState extends State<CustomerSearchPage> {
|
|||
|
||||
return Scaffold(
|
||||
body: PageBackgroundWidget(
|
||||
// height: MediaQuery.of(context).size.height * 2,
|
||||
child: Column(
|
||||
children: [
|
||||
Column(
|
||||
|
|
@ -121,6 +122,30 @@ class _CustomerSearchPageState extends State<CustomerSearchPage> {
|
|||
// padding: EdgeInsets.all(8),
|
||||
// ),
|
||||
// )
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
ItemCardWidget(
|
||||
imageUrl: imageUrl,
|
||||
text: 'sample',
|
||||
price: 500,
|
||||
quantity: 15,
|
||||
),
|
||||
ItemCardWidget(
|
||||
imageUrl: imageUrl,
|
||||
text: 'sample',
|
||||
price: 20,
|
||||
quantity: 85,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
|
|
|
|||
24
lib/security/encryption.dart
Normal file
24
lib/security/encryption.dart
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:lazyxchacha/keypair.dart' as kp;
|
||||
import 'package:lazyxchacha/lazyxchacha.dart';
|
||||
|
||||
final key = kp.KeyPair.newKeyPair();
|
||||
|
||||
Future<String> encrypt(String text) async {
|
||||
final lazyxchacha = LazyXChaCha.instance;
|
||||
final localKey = await key;
|
||||
|
||||
final sharedKey = await localKey.sharedKey(localKey.pk);
|
||||
final ciphertext = await lazyxchacha.encrypt(text, sharedKey);
|
||||
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
Future<String> decrypt(String encrypted) async {
|
||||
final lazyXChaCha = LazyXChaCha.instance;
|
||||
final localKey = await key;
|
||||
|
||||
final sharedKey = await localKey.sharedKey(localKey.pk);
|
||||
final plaintext = await lazyXChaCha.decrypt(encrypted, sharedKey);
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
|
@ -29,13 +29,14 @@ class RefMedicines {
|
|||
return data.first['ref_medicines_uuid'];
|
||||
}
|
||||
|
||||
Future<void> postMedicine(String uuid, String name, String muuid, String guuid, String tuuid) async {
|
||||
Future<void> postMedicine(String uuid, String name, String muuid, String guuid, String tuuid, String barcode) async {
|
||||
final medicine = {
|
||||
'ref_medicines_uuid': uuid,
|
||||
'medicine_name': name,
|
||||
'ref_manufactorers_uuid': muuid,
|
||||
'ref_generic_names_uuid': guuid,
|
||||
'ref_types_uuid': tuuid
|
||||
'ref_types_uuid': tuuid,
|
||||
'barcode': barcode
|
||||
};
|
||||
|
||||
await _supabase.from('ref_medicines').insert(medicine);
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ class DropdownWrapperWidget extends StatelessWidget {
|
|||
spacing: 16,
|
||||
children: [
|
||||
const CircularProgressIndicator(color: Color.fromRGBO(255, 255, 255, 1)),
|
||||
TextWidget(
|
||||
text: 'Fetching $text',
|
||||
size: 16,
|
||||
)
|
||||
TextWidget(text: 'Fetching $text', size: 16, footer: true)
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ class DropdownWrapperMultiWidget extends StatelessWidget {
|
|||
spacing: 16,
|
||||
children: [
|
||||
const CircularProgressIndicator(color: Color.fromRGBO(255, 255, 255, 1)),
|
||||
TextWidget(
|
||||
text: 'Fetching $text',
|
||||
size: 16,
|
||||
)
|
||||
TextWidget(text: 'Fetching $text', size: 16, footer: true)
|
||||
],
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class InputWidget extends StatelessWidget {
|
|||
)),
|
||||
const Gap(8),
|
||||
TextField(
|
||||
textInputAction: TextInputAction.go,
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue