added android logo assets
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,4 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
|
||||||
</adaptive-icon>
|
|
||||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.7 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.9 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
Normal file
|
After Width: | Height: | Size: 687 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.2 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.1 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB |
BIN
android/app/src/main/res/play_store_512.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<color name="ic_launcher_background">#ffffff</color>
|
|
||||||
</resources>
|
|
||||||
@@ -20,6 +20,7 @@ class PayScreenModel {
|
|||||||
PaymentProcessor? selectedPaymentProcessor;
|
PaymentProcessor? selectedPaymentProcessor;
|
||||||
String region = '';
|
String region = '';
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
|
bool isLoadingProducts = false;
|
||||||
String? errorMessage;
|
String? errorMessage;
|
||||||
String? status;
|
String? status;
|
||||||
}
|
}
|
||||||
@@ -146,7 +147,7 @@ class PayController extends ChangeNotifier {
|
|||||||
|
|
||||||
Future<ApiResponse<List<BillProduct>>> getProducts(String providerId) async {
|
Future<ApiResponse<List<BillProduct>>> getProducts(String providerId) async {
|
||||||
try {
|
try {
|
||||||
model.isLoading = true;
|
model.isLoadingProducts = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
List<dynamic> response = await http.get(
|
List<dynamic> response = await http.get(
|
||||||
@@ -154,12 +155,12 @@ class PayController extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
model.products = response.map((e) => BillProduct.fromJson(e)).toList();
|
model.products = response.map((e) => BillProduct.fromJson(e)).toList();
|
||||||
|
|
||||||
model.isLoading = false;
|
model.isLoadingProducts = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return ApiResponse.success(model.products);
|
return ApiResponse.success(model.products);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.e(e);
|
logger.e(e);
|
||||||
model.isLoading = false;
|
model.isLoadingProducts = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return ApiResponse.failure(
|
return ApiResponse.failure(
|
||||||
"Problem fetching products, are you connected to the internet?",
|
"Problem fetching products, are you connected to the internet?",
|
||||||
|
|||||||
@@ -298,9 +298,7 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
|||||||
if (showAdditionalRecipientDetails)
|
if (showAdditionalRecipientDetails)
|
||||||
_buildAdditionalRecipientDetails(),
|
_buildAdditionalRecipientDetails(),
|
||||||
const SizedBox(height: 7),
|
const SizedBox(height: 7),
|
||||||
if (controller.model.products.isNotEmpty ||
|
_buildBillProductSelector(controller),
|
||||||
controller.model.isLoading)
|
|
||||||
_buildBillProductSelector(controller),
|
|
||||||
const SizedBox(height: 7),
|
const SizedBox(height: 7),
|
||||||
_buildPhoneField(),
|
_buildPhoneField(),
|
||||||
const SizedBox(height: 7),
|
const SizedBox(height: 7),
|
||||||
@@ -364,8 +362,9 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Debit Phone Number',
|
'Debit Phone Number',
|
||||||
@@ -607,6 +606,31 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBillProductSelector(PayController controller) {
|
Widget _buildBillProductSelector(PayController controller) {
|
||||||
|
if (controller.model.products.isEmpty && !controller.model.isLoadingProducts) {
|
||||||
|
return SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller.model.isLoadingProducts) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: 20),
|
||||||
|
const Text(
|
||||||
|
'Provider Product',
|
||||||
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -616,51 +640,48 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
|||||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
Skeletonizer(
|
DropdownButtonHideUnderline(
|
||||||
enabled: controller.model.isLoading,
|
child: DropdownButtonFormField<String>(
|
||||||
child: DropdownButtonHideUnderline(
|
initialValue: controller.model.selectedProduct?.uid,
|
||||||
child: DropdownButtonFormField<String>(
|
isExpanded: true,
|
||||||
initialValue: controller.model.selectedProduct?.uid,
|
icon: const Icon(Icons.arrow_drop_down),
|
||||||
isExpanded: true,
|
decoration: InputDecoration(
|
||||||
icon: const Icon(Icons.arrow_drop_down),
|
hintText: 'Select Product',
|
||||||
decoration: InputDecoration(
|
enabledBorder: OutlineInputBorder(
|
||||||
hintText: 'Select Product',
|
borderRadius: BorderRadius.circular(12),
|
||||||
enabledBorder: OutlineInputBorder(
|
borderSide: BorderSide(
|
||||||
borderRadius: BorderRadius.circular(12),
|
color: Theme.of(
|
||||||
borderSide: BorderSide(
|
context,
|
||||||
color: Theme.of(
|
).colorScheme.primary.withValues(alpha: 0.2),
|
||||||
context,
|
),
|
||||||
).colorScheme.primary.withValues(alpha: 0.2),
|
),
|
||||||
|
),
|
||||||
|
items: [
|
||||||
|
DropdownMenuItem(child: Text("Select Product")),
|
||||||
|
...controller.model.products.map(
|
||||||
|
(e) => DropdownMenuItem<String>(
|
||||||
|
value: e.uid,
|
||||||
|
child: Text(
|
||||||
|
'${e.displayName} - '
|
||||||
|
'${transactionController.model.formData.debitCurrency}${e.defaultAmount}',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
items: [
|
],
|
||||||
DropdownMenuItem(child: Text("Select Product")),
|
onChanged: (String? newValue) {
|
||||||
...controller.model.products.map(
|
if (newValue != null) {
|
||||||
(e) => DropdownMenuItem<String>(
|
BillProduct product = controller.model.products.firstWhere(
|
||||||
value: e.uid,
|
(e) => e.uid == newValue,
|
||||||
child: Text(
|
);
|
||||||
'${e.displayName} - '
|
controller.updateSelectedProduct(product);
|
||||||
'${transactionController.model.formData.debitCurrency}${e.defaultAmount}',
|
}
|
||||||
),
|
},
|
||||||
),
|
validator: (value) {
|
||||||
),
|
if (value == null || value.isEmpty) {
|
||||||
],
|
return 'Please select a product';
|
||||||
onChanged: (String? newValue) {
|
}
|
||||||
if (newValue != null) {
|
return null;
|
||||||
BillProduct product = controller.model.products.firstWhere(
|
},
|
||||||
(e) => e.uid == newValue,
|
|
||||||
);
|
|
||||||
controller.updateSelectedProduct(product);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return 'Please select a product';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||