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">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||
</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;
|
||||
String region = '';
|
||||
bool isLoading = false;
|
||||
bool isLoadingProducts = false;
|
||||
String? errorMessage;
|
||||
String? status;
|
||||
}
|
||||
@@ -146,7 +147,7 @@ class PayController extends ChangeNotifier {
|
||||
|
||||
Future<ApiResponse<List<BillProduct>>> getProducts(String providerId) async {
|
||||
try {
|
||||
model.isLoading = true;
|
||||
model.isLoadingProducts = true;
|
||||
notifyListeners();
|
||||
|
||||
List<dynamic> response = await http.get(
|
||||
@@ -154,12 +155,12 @@ class PayController extends ChangeNotifier {
|
||||
);
|
||||
model.products = response.map((e) => BillProduct.fromJson(e)).toList();
|
||||
|
||||
model.isLoading = false;
|
||||
model.isLoadingProducts = false;
|
||||
notifyListeners();
|
||||
return ApiResponse.success(model.products);
|
||||
} catch (e) {
|
||||
logger.e(e);
|
||||
model.isLoading = false;
|
||||
model.isLoadingProducts = false;
|
||||
notifyListeners();
|
||||
return ApiResponse.failure(
|
||||
"Problem fetching products, are you connected to the internet?",
|
||||
|
||||
@@ -298,9 +298,7 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
if (showAdditionalRecipientDetails)
|
||||
_buildAdditionalRecipientDetails(),
|
||||
const SizedBox(height: 7),
|
||||
if (controller.model.products.isNotEmpty ||
|
||||
controller.model.isLoading)
|
||||
_buildBillProductSelector(controller),
|
||||
_buildBillProductSelector(controller),
|
||||
const SizedBox(height: 7),
|
||||
_buildPhoneField(),
|
||||
const SizedBox(height: 7),
|
||||
@@ -364,8 +362,9 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Debit Phone Number',
|
||||
@@ -607,6 +606,31 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
}
|
||||
|
||||
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(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -616,51 +640,48 @@ class _PayScreenState extends State<PayScreen> with TickerProviderStateMixin {
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Skeletonizer(
|
||||
enabled: controller.model.isLoading,
|
||||
child: DropdownButtonHideUnderline(
|
||||
child: DropdownButtonFormField<String>(
|
||||
initialValue: controller.model.selectedProduct?.uid,
|
||||
isExpanded: true,
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Select Product',
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withValues(alpha: 0.2),
|
||||
DropdownButtonHideUnderline(
|
||||
child: DropdownButtonFormField<String>(
|
||||
initialValue: controller.model.selectedProduct?.uid,
|
||||
isExpanded: true,
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Select Product',
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(
|
||||
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")),
|
||||
...controller.model.products.map(
|
||||
(e) => DropdownMenuItem<String>(
|
||||
value: e.uid,
|
||||
child: Text(
|
||||
'${e.displayName} - '
|
||||
'${transactionController.model.formData.debitCurrency}${e.defaultAmount}',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue != 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;
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (String? newValue) {
|
||||
if (newValue != 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;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||