diff --git a/lib/main.dart b/lib/main.dart index 1a1cda2..905e7d9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,10 +11,12 @@ import 'package:pharmacy_mobile/blocs/guest/guest_bloc.dart'; import 'package:pharmacy_mobile/blocs/language/language_bloc.dart'; import 'package:pharmacy_mobile/blocs/user/user_bloc.dart'; import 'package:pharmacy_mobile/pages/add_category_page.dart'; +import 'package:pharmacy_mobile/pages/add_distributor_page.dart'; import 'package:pharmacy_mobile/pages/add_generics_page.dart'; -import 'package:pharmacy_mobile/pages/add_manufacturer.dart'; +import 'package:pharmacy_mobile/pages/add_manufacturer_page.dart'; import 'package:pharmacy_mobile/pages/add_medicine_page.dart'; import 'package:pharmacy_mobile/pages/add_stock_page.dart'; +import 'package:pharmacy_mobile/pages/add_supplier_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'; @@ -98,6 +100,34 @@ final _router = GoRouter( child: child), ), ), + GoRoute( + name: 'adddistributor', + path: '/adddistributor', + pageBuilder: (BuildContext context, GoRouterState state) => CustomTransitionPage( + key: state.pageKey, + child: const AddDistributorPage(), + transitionsBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation, + Widget child) => + SlideTransition( + position: animation.drive( + Tween(begin: Offset(0.95, 0), end: Offset.zero).chain(CurveTween(curve: Curves.easeOut))), + child: child), + ), + ), + GoRoute( + name: 'addsupplier', + path: '/addsupplier', + pageBuilder: (BuildContext context, GoRouterState state) => CustomTransitionPage( + key: state.pageKey, + child: const AddSupplierPage(), + transitionsBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation, + Widget child) => + SlideTransition( + position: animation.drive( + Tween(begin: Offset(0.95, 0), end: Offset.zero).chain(CurveTween(curve: Curves.easeOut))), + child: child), + ), + ), GoRoute( name: 'addmedicines', path: '/addmedicines', diff --git a/lib/pages/add_distributor_page.dart b/lib/pages/add_distributor_page.dart new file mode 100644 index 0000000..f86b21b --- /dev/null +++ b/lib/pages/add_distributor_page.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:go_router/go_router.dart'; +import 'package:internet_connection_checker/internet_connection_checker.dart'; +import 'package:pharmacy_mobile/functions/checkexisting_function.dart'; +import 'package:pharmacy_mobile/tables/ref_distributors.dart'; +import 'package:pharmacy_mobile/widgets/buttonwithprogress_widget.dart'; +import 'package:pharmacy_mobile/widgets/form_border_widget2.dart'; +import 'package:pharmacy_mobile/widgets/input_form_widget.dart'; +import 'package:pharmacy_mobile/widgets/page_background_widget.dart'; +import 'package:pharmacy_mobile/widgets/snackbar_widget.dart'; +import 'package:pharmacy_mobile/widgets/text_widget.dart'; +import 'package:pharmacy_mobile/widgets/title_widget.dart'; + +class AddDistributorPage extends StatefulWidget { + const AddDistributorPage({super.key}); + + @override + State createState() => _AddDistributorPageState(); +} + +class _AddDistributorPageState extends State { + final _formKey = GlobalKey(); + final _nameController = TextEditingController(); + final _addressController = TextEditingController(); + final _refdistributors = RefDistributors(); + + late bool _isLoading = false; + + void _saveDistributor() async { + setState(() => _isLoading = true); + + try { + if (await InternetConnectionChecker.instance.hasConnection) { + final existing = await checkExisting(_refdistributors, _nameController); + + if (existing && mounted) { + showNotification(context, 'Distributor already listed', false); + return; + } + + final post = await _refdistributors.postDistributor(_nameController.text, _addressController.text); + + if (post && mounted) { + showNotification(context, 'Distributor added to list', true); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + context.pop(); + } + }); + } + } else { + if (mounted) { + showNotification(context, 'Error: No Internet Connection', false); + } + } + } catch (e) { + if (mounted) { + showNotification(context, 'Error: $e', false); + } + } finally { + setState(() => _isLoading = false); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: PageBackgroundWidget( + child: Center( + child: Column( + children: [ + const Gap(96), + const TitleWidget( + firstTextSize: 14, + secondTextSize: 24, + logoSize: 90, + ), + const Gap(32), + const TextWidget( + text: 'Add Distributor', + title: true, + ), + const Gap(16), + FormBorderWidget2( + color: 'blue', + child: Form( + key: _formKey, + child: Column( + children: [ + InputFormWidget(label: 'Name', controller: _nameController), + const Gap(16), + InputFormWidget(label: 'Address', controller: _addressController), + const Gap(32), + ButtonWithProgressWidget( + trigger: _isLoading, + progressText: 'Adding Distributor', + buttonText: 'Save', + onPressed: _saveDistributor) + ], + ))) + ], + ), + )), + ); + } +} diff --git a/lib/pages/add_generics_page.dart b/lib/pages/add_generics_page.dart index 3160232..7930187 100644 --- a/lib/pages/add_generics_page.dart +++ b/lib/pages/add_generics_page.dart @@ -30,7 +30,7 @@ class _AddGenericsPageState extends State { final _formKey = GlobalKey(); late bool _isLoading = false; - late final List _categoryListCache = []; + // late final List _categoryListCache = []; late List _categoryList = []; late String _selectedCategory = ''; diff --git a/lib/pages/add_manufacturer.dart b/lib/pages/add_manufacturer_page.dart similarity index 100% rename from lib/pages/add_manufacturer.dart rename to lib/pages/add_manufacturer_page.dart diff --git a/lib/pages/add_medicine_page.dart b/lib/pages/add_medicine_page.dart index 47917d0..c6f8c5d 100644 --- a/lib/pages/add_medicine_page.dart +++ b/lib/pages/add_medicine_page.dart @@ -9,9 +9,11 @@ import 'package:pharmacy_mobile/blocs/caches/typelist/functions/cache_gettypelis import 'package:pharmacy_mobile/functions/barcode_scan_function.dart'; import 'package:pharmacy_mobile/functions/checkresult_function.dart'; import 'package:pharmacy_mobile/tables/ref_categories.dart'; +import 'package:pharmacy_mobile/tables/ref_distributors.dart'; import 'package:pharmacy_mobile/tables/ref_generic_names.dart'; import 'package:pharmacy_mobile/tables/ref_manufacturers.dart'; import 'package:pharmacy_mobile/tables/ref_medicines.dart'; +import 'package:pharmacy_mobile/tables/ref_suppliers.dart'; import 'package:pharmacy_mobile/tables/ref_types.dart'; import 'package:pharmacy_mobile/tables/storage.dart'; import 'package:pharmacy_mobile/widgets/button_widget.dart'; @@ -44,18 +46,24 @@ class _AddMedicinePageState extends State { final _refTypes = RefTypes(); final _refManufacturer = RefManufacturers(); final _refMedicines = RefMedicines(); + final _refDistributors = RefDistributors(); + final _refSuppliers = RefSuppliers(); final _storage = Storage(); final _nameController = TextEditingController(); final _barcodeController = TextEditingController(); - bool _isLoading = false; + late bool _isLoading = false; late List _genericNameList = []; late String _selectedGeneric = ''; late String _selectedCategory = ''; late List _typeList = []; late String _selectedType = ''; late List _manufacturerList = []; + late List _distributorList = []; + late List _supplierList = []; late String _selectedManufacturer = ''; + late String _selectedDistributor = ''; + late final String _selectedSupplier = ''; late String uuid = ''; late bool imageUploaded = false; late String imageUrl = ''; @@ -100,13 +108,27 @@ class _AddMedicinePageState extends State { } } - Future _getManufacturer() async { + Future _getManufacturers() async { _manufacturerList = await _refManufacturer.getList(); setState(() { checkResult(context, _manufacturerList, 'Manufacturer'); }); } + Future _getDistributors() async { + _distributorList = await _refDistributors.getList(); + setState(() { + checkResult(context, _distributorList, 'Distributor'); + }); + } + + Future _getSuppliers() async { + _supplierList = await _refSuppliers.getList(); + setState(() { + checkResult(context, _supplierList, 'Supplier'); + }); + } + Future _getManufacturerCache() async { final cache = await cacheGetManufacturerList(context); @@ -120,28 +142,47 @@ class _AddMedicinePageState extends State { } void autoRun() async { - final generics = await _getGenericsCache(); - final types = await _getTypesCache(); - final manufacturers = await _getManufacturerCache(); + // final generics = await _getGenericsCache(); + // final types = await _getTypesCache(); + // final manufacturers = await _getManufacturerCache(); - if (!generics || !types || !manufacturers) { - if (await InternetConnectionChecker.instance.hasConnection) { - await _getGenerics(); - await _getTypes(); - await _getManufacturer(); - } else { - if (mounted) { - showNotification(context, 'Error: No Internet Connection', false); + // if (!generics || !types || !manufacturers) { + // if (await InternetConnectionChecker.instance.hasConnection) { + // await _getGenerics(); + // await _getTypes(); + // await _getManufacturers(); + // await _getDistributors(); + // } else { + // if (mounted) { + // showNotification(context, 'Error: No Internet Connection', false); - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - context.pop(); - } - }); - } - } + // WidgetsBinding.instance.addPostFrameCallback((_) { + // if (mounted) { + // context.pop(); + // } + // }); + // } + // } + // } else { + // setState(() {}); + // } + + if (await InternetConnectionChecker.instance.hasConnection) { + await _getGenerics(); + await _getTypes(); + await _getManufacturers(); + await _getDistributors(); + await _getSuppliers(); } else { - setState(() {}); + if (mounted) { + showNotification(context, 'Error: No Internet Connection', false); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + context.pop(); + } + }); + } } } @@ -161,6 +202,10 @@ class _AddMedicinePageState extends State { _selectedManufacturer = manufacturer; } + void _updateDistributor(dynamic distributor) { + _selectedDistributor = distributor; + } + Future _scanBarcode() async { // String? barcode = await SimpleBarcodeScanner.scanBarcode( // context, @@ -190,9 +235,11 @@ class _AddMedicinePageState extends State { final medGenericUUID = await _refGenericNames.getUUID(_selectedGeneric); final medTypeUUID = await _refTypes.getUUID(_selectedType); final medManufacturerUUID = await _refManufacturer.getUUID(_selectedManufacturer); + final medDistributorUUID = await _refDistributors.getUUID(_selectedDistributor); + final medSupplierUUID = await _refSuppliers.getUUID(_selectedSupplier); final posted = await _refMedicines.postMedicine( - uuid, medName, medManufacturerUUID, medGenericUUID, medTypeUUID, encrpytedBarcode); + uuid, medName, medManufacturerUUID, medGenericUUID, medTypeUUID, encrpytedBarcode, medDistributorUUID, medSupplierUUID); if (posted) { if (mounted) { @@ -340,6 +387,13 @@ class _AddMedicinePageState extends State { onChanged: _updateManufacturer, ), const Gap(16), + DropDownWidget( + label: 'Distributor', + list: _distributorList, + listTitle: 'distributor_name', + onChanged: _updateDistributor, + ), + const Gap(16), InputFormWidget(label: 'Barcode', controller: _barcodeController), ScanbarcodeWidget(onTap: _scanBarcode), const Gap(16), @@ -367,11 +421,11 @@ class _AddMedicinePageState extends State { // else // ButtonWidget(text: 'Save Medicine', onPressed: _saveMedicine) if (uploaded) - ButtonWithProgressWidget( - trigger: _isLoading, - progressText: 'Adding Medicine', - buttonText: 'Save', - onPressed: _saveMedicine) + ButtonWithProgressWidget( + trigger: _isLoading, + progressText: 'Adding Medicine', + buttonText: 'Save', + onPressed: _saveMedicine) ]) ]))) ])))); diff --git a/lib/pages/add_stock_page.dart b/lib/pages/add_stock_page.dart index d0bcd63..cb12e13 100644 --- a/lib/pages/add_stock_page.dart +++ b/lib/pages/add_stock_page.dart @@ -6,7 +6,6 @@ import 'package:pharmacy_mobile/functions/barcode_scan_function.dart'; import 'package:pharmacy_mobile/functions/checkresult_function.dart'; import 'package:pharmacy_mobile/tables/ref_medicines.dart'; import 'package:pharmacy_mobile/tables/stocks.dart'; -import 'package:pharmacy_mobile/widgets/button_widget.dart'; import 'package:pharmacy_mobile/widgets/buttonwithprogress_widget.dart'; import 'package:pharmacy_mobile/widgets/datepicker_widget.dart'; import 'package:pharmacy_mobile/widgets/dropdown_widget.dart'; diff --git a/lib/pages/add_supplier_page.dart b/lib/pages/add_supplier_page.dart new file mode 100644 index 0000000..37cf543 --- /dev/null +++ b/lib/pages/add_supplier_page.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:go_router/go_router.dart'; +import 'package:internet_connection_checker/internet_connection_checker.dart'; +import 'package:pharmacy_mobile/functions/checkexisting_function.dart'; +import 'package:pharmacy_mobile/tables/ref_suppliers.dart'; +import 'package:pharmacy_mobile/widgets/buttonwithprogress_widget.dart'; +import 'package:pharmacy_mobile/widgets/form_border_widget2.dart'; +import 'package:pharmacy_mobile/widgets/input_form_widget.dart'; +import 'package:pharmacy_mobile/widgets/page_background_widget.dart'; +import 'package:pharmacy_mobile/widgets/snackbar_widget.dart'; +import 'package:pharmacy_mobile/widgets/text_widget.dart'; +import 'package:pharmacy_mobile/widgets/title_widget.dart'; + +class AddSupplierPage extends StatefulWidget { + const AddSupplierPage({super.key}); + + @override + State createState() => _AddSupplierPageState(); +} + +class _AddSupplierPageState extends State { + final _formKey = GlobalKey(); + final _nameController = TextEditingController(); + final _refsuppliers = RefSuppliers(); + + late bool _isLoading = false; + + void _saveSupplier() async { + setState(() => _isLoading = true); + + try { + if (await InternetConnectionChecker.instance.hasConnection) { + final existing = await checkExisting(_refsuppliers, _nameController); + + if (existing && mounted) { + showNotification(context, 'Supplier already listed', false); + return; + } + + final post = await _refsuppliers.postSupplier(_nameController.text); + print('post: $post'); + + if (post && mounted) { + showNotification(context, 'Supplier added to list', true); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + context.pop(); + } + }); + } + } else { + if (mounted) { + showNotification(context, 'Error: No Internet Connection', false); + } + } + } catch (e) { + if (mounted) { + showNotification(context, 'Error: $e', false); + } + } finally { + setState(() => _isLoading = false); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: PageBackgroundWidget( + child: Center( + child: Column( + children: [ + const Gap(96), + const TitleWidget( + firstTextSize: 14, + secondTextSize: 24, + logoSize: 90, + ), + const Gap(32), + const TextWidget( + text: 'Add Supplier', + title: true, + ), + const Gap(16), + FormBorderWidget2( + color: 'blue', + child: Form( + key: _formKey, + child: Column( + children: [ + InputFormWidget(label: 'Name', controller: _nameController), + const Gap(32), + ButtonWithProgressWidget( + trigger: _isLoading, + progressText: 'Adding Supplier', + buttonText: 'Save', + onPressed: _saveSupplier) + ], + ))) + ], + ), + )), + ); + } +} diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 78ef53a..269162d 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -146,7 +146,7 @@ class _MainPageState extends State { resizeToAvoidBottomInset: false, body: SingleChildScrollView( child: PageBackgroundWidget( - height: MediaQuery.of(context).size.height + 500, + height: MediaQuery.of(context).size.height + 600, page: 'menu', child: Center( child: Column( @@ -171,6 +171,22 @@ class _MainPageState extends State { color: 'blue', ), const Gap(16), + MenuWidget( + icon: FontAwesomeIcons.circlePlus, + text: 'Add Distributor', + description: 'Register manufacturer to the list', + onPressed: () => {context.push('/adddistributor')}, + color: 'blue', + ), + const Gap(16), + MenuWidget( + icon: FontAwesomeIcons.circlePlus, + text: 'Add Supplier', + description: 'Register manufacturer to the list', + onPressed: () => {context.push('/addsupplier')}, + color: 'blue', + ), + const Gap(16), MenuWidget( icon: FontAwesomeIcons.circlePlus, text: 'Add Type', diff --git a/lib/tables/ref_distributors.dart b/lib/tables/ref_distributors.dart new file mode 100644 index 0000000..ee32f95 --- /dev/null +++ b/lib/tables/ref_distributors.dart @@ -0,0 +1,41 @@ +import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:uuid/uuid.dart'; + +class RefDistributors { + final SupabaseClient _supabase = Supabase.instance.client; + + Future getList() async { + try { + final data = await _supabase + .from('ref_distributors') + .select('distributor_name, distributor_address') + .order('distributor_name', ascending: true); + return data.toList(); + } catch (e) { + return []; + } + } + + Future getUUID(String name) async { + try { + final data = + await _supabase.from('ref_distributors').select('ref_distributors_uuid').eq('distributor_name', name); + return data.first['ref_distributors_uuid'].toString(); + } catch (e) { + return ''; + } + } + + Future postDistributor(String name, String address) async { + try { + final genericUUID = Uuid().v4(); + + await _supabase + .from('ref_distributors') + .insert({'ref_distributors_uuid': genericUUID, 'distributor_name': name, 'distributor_address': address}); + return true; + } catch (e) { + return false; + } + } +} diff --git a/lib/tables/ref_medicines.dart b/lib/tables/ref_medicines.dart index 4695507..f760bb3 100644 --- a/lib/tables/ref_medicines.dart +++ b/lib/tables/ref_medicines.dart @@ -86,14 +86,17 @@ class RefMedicines { } } - Future postMedicine(String uuid, String name, String muuid, String guuid, String tuuid, String barcode) async { + Future postMedicine(String uuid, String name, String muuid, String guuid, String tuuid, String barcode, + String distributor, String supplier) async { final medicine = { 'ref_medicines_uuid': uuid, 'medicine_name': name, 'ref_manufacturers_uuid': muuid, 'ref_generic_names_uuid': guuid, 'ref_types_uuid': tuuid, - 'barcode': barcode + 'barcode': barcode, + 'ref_distributors_uuid': distributor, + 'ref_suppliers_uuid': supplier }; try { diff --git a/lib/tables/ref_suppliers.dart b/lib/tables/ref_suppliers.dart new file mode 100644 index 0000000..aa47311 --- /dev/null +++ b/lib/tables/ref_suppliers.dart @@ -0,0 +1,36 @@ +import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:uuid/uuid.dart'; + +class RefSuppliers { + final SupabaseClient _supabase = Supabase.instance.client; + + Future getList() async { + try { + final data = + await _supabase.from('ref_suppliers').select('supplier_name').order('supplier_name', ascending: true); + return data.toList(); + } catch (e) { + return []; + } + } + + Future getUUID(String name) async { + try { + final data = await _supabase.from('ref_suppliers').select('ref_suppliers_uuid').eq('supplier_name', name); + return data.first['ref_suppliers_uuid'].toString(); + } catch (e) { + return ''; + } + } + + Future postSupplier(String name) async { + try { + final genericUUID = Uuid().v4(); + + await _supabase.from('ref_suppliers').insert({'ref_suppliers_uuid': genericUUID, 'supplier_name': name}); + return true; + } catch (e) { + return false; + } + } +}