mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-26 20:46:21 +00:00
Add Active Services page UI
Add Phone service entity
This commit is contained in:
parent
6fdcc0dd9e
commit
81e799c514
16 changed files with 422 additions and 36 deletions
23
lib/entities/cake_phone_entities/phone_number_service.dart
Normal file
23
lib/entities/cake_phone_entities/phone_number_service.dart
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
class PhoneNumberService {
|
||||||
|
const PhoneNumberService({
|
||||||
|
this.id,
|
||||||
|
this.phoneNumber,
|
||||||
|
this.planId,
|
||||||
|
this.usedUntil,
|
||||||
|
this.messageReceiveEnabled,
|
||||||
|
this.autoRenew,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final String phoneNumber;
|
||||||
|
final String planId;
|
||||||
|
final DateTime usedUntil;
|
||||||
|
final bool messageReceiveEnabled;
|
||||||
|
final bool autoRenew;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => other is PhoneNumberService && other.id == id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
}
|
|
@ -69,6 +69,7 @@ import 'package:cake_wallet/src/screens/cake_phone/cake_phone_welcome_page.dart'
|
||||||
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_verification_page.dart';
|
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_verification_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_products_page.dart';
|
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_products_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_products/phone_number_product_page.dart';
|
import 'package:cake_wallet/src/screens/cake_phone/cake_phone_products/phone_number_product_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/active_services_page.dart';
|
||||||
|
|
||||||
RouteSettings currentRouteSettings;
|
RouteSettings currentRouteSettings;
|
||||||
|
|
||||||
|
@ -409,6 +410,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.cakePhoneWelcome:
|
case Routes.cakePhoneWelcome:
|
||||||
return MaterialPageRoute<CakePhoneWelcomePage>(
|
return MaterialPageRoute<CakePhoneWelcomePage>(
|
||||||
|
settings: RouteSettings(name: Routes.cakePhoneWelcome),
|
||||||
builder: (_) => CakePhoneWelcomePage(),
|
builder: (_) => CakePhoneWelcomePage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -416,24 +418,34 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
final isLogin = settings.arguments as bool ?? false;
|
final isLogin = settings.arguments as bool ?? false;
|
||||||
|
|
||||||
return MaterialPageRoute<CakePhoneWelcomePage>(
|
return MaterialPageRoute<CakePhoneWelcomePage>(
|
||||||
|
settings: RouteSettings(name: Routes.cakePhoneAuth),
|
||||||
builder: (_) => CakePhoneAuthPage(isLogin: isLogin),
|
builder: (_) => CakePhoneAuthPage(isLogin: isLogin),
|
||||||
);
|
);
|
||||||
|
|
||||||
case Routes.cakePhoneVerification:
|
case Routes.cakePhoneVerification:
|
||||||
return MaterialPageRoute<CakePhoneVerificationPage>(
|
return MaterialPageRoute<CakePhoneVerificationPage>(
|
||||||
|
settings: RouteSettings(name: Routes.cakePhoneVerification),
|
||||||
builder: (_) => CakePhoneVerificationPage(),
|
builder: (_) => CakePhoneVerificationPage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
case Routes.cakePhoneProducts:
|
case Routes.cakePhoneProducts:
|
||||||
return MaterialPageRoute<CakePhoneProductsPage>(
|
return MaterialPageRoute<CakePhoneProductsPage>(
|
||||||
|
settings: RouteSettings(name: Routes.cakePhoneProducts),
|
||||||
builder: (_) => CakePhoneProductsPage(),
|
builder: (_) => CakePhoneProductsPage(),
|
||||||
);
|
);
|
||||||
|
|
||||||
case Routes.phoneNumberProduct:
|
case Routes.phoneNumberProduct:
|
||||||
return MaterialPageRoute<PhoneNumberProductPage>(
|
return MaterialPageRoute<PhoneNumberProductPage>(
|
||||||
|
settings: RouteSettings(name: Routes.phoneNumberProduct),
|
||||||
builder: (_) => PhoneNumberProductPage(getIt.get<PhonePlanViewModel>()),
|
builder: (_) => PhoneNumberProductPage(getIt.get<PhonePlanViewModel>()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case Routes.cakePhoneActiveServices:
|
||||||
|
return MaterialPageRoute<ActiveServicesPage>(
|
||||||
|
settings: RouteSettings(name: Routes.cakePhoneActiveServices),
|
||||||
|
builder: (_) => ActiveServicesPage(),
|
||||||
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => Scaffold(
|
builder: (_) => Scaffold(
|
||||||
|
|
|
@ -65,4 +65,5 @@ class Routes {
|
||||||
static const cakePhoneVerification = '/cake_phone_verification';
|
static const cakePhoneVerification = '/cake_phone_verification';
|
||||||
static const cakePhoneProducts = '/cake_phone_products';
|
static const cakePhoneProducts = '/cake_phone_products';
|
||||||
static const phoneNumberProduct = '/phone_number_product';
|
static const phoneNumberProduct = '/phone_number_product';
|
||||||
|
static const cakePhoneActiveServices = '/cake_phone_active_services';
|
||||||
}
|
}
|
127
lib/src/screens/cake_phone/active_services_page.dart
Normal file
127
lib/src/screens/cake_phone/active_services_page.dart
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/widgets/add_options_tile.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/widgets/info_text_column.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/widgets/subscribed_phone_numbers.dart';
|
||||||
|
|
||||||
|
class ActiveServicesPage extends BasePage {
|
||||||
|
ActiveServicesPage();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) => ActiveServicesBody();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget middle(BuildContext context) {
|
||||||
|
return Text(
|
||||||
|
S.of(context).active_services,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontFamily: 'Lato',
|
||||||
|
color: titleColor ?? Theme.of(context).primaryTextTheme.title.color),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActiveServicesBody extends StatefulWidget {
|
||||||
|
ActiveServicesBody();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ActiveServicesBodyState createState() => ActiveServicesBodyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActiveServicesBodyState extends State<ActiveServicesBody> {
|
||||||
|
// TODO: remove const dummy variables
|
||||||
|
final int freeSMSCount = 50;
|
||||||
|
final int freeMBCount = 0;
|
||||||
|
final int serviceDaysLeft = 23;
|
||||||
|
final double accountBalance = 20.34;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 20),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [
|
||||||
|
Theme.of(context).primaryTextTheme.subhead.color,
|
||||||
|
Theme.of(context).primaryTextTheme.subhead.decorationColor,
|
||||||
|
],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text(S.of(context).new_phone_number,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
freeBalanceInfoRow(),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
AddOptionsTile(
|
||||||
|
leading: InfoTextColumn(
|
||||||
|
title: S.of(context).account_balance,
|
||||||
|
subtitle: "\$${accountBalance.toStringAsFixed(2)}",
|
||||||
|
isReversed: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 64),
|
||||||
|
SubscribedPhoneNumbers(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget freeBalanceInfoRow() {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
|
color: Theme.of(context).primaryTextTheme.display3.decorationColor,
|
||||||
|
),
|
||||||
|
child: InfoTextColumn(
|
||||||
|
title: S.of(context).free_sms_balance,
|
||||||
|
subtitle: "${freeSMSCount} SMS",
|
||||||
|
padding: const EdgeInsets.only(top: 12, bottom: 4),
|
||||||
|
isReversed: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 9),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
|
color: Theme.of(context).primaryTextTheme.display3.decorationColor,
|
||||||
|
),
|
||||||
|
child: InfoTextColumn(
|
||||||
|
title: S.of(context).free_data_balance,
|
||||||
|
subtitle: "${freeMBCount} MB",
|
||||||
|
padding: const EdgeInsets.only(top: 12, bottom: 4),
|
||||||
|
isReversed: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,7 @@ class CakePhoneAuthPage extends BasePage {
|
||||||
isLogin ? S.of(context).login : S.of(context).signup,
|
isLogin ? S.of(context).login : S.of(context).signup,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
color: Theme.of(context).primaryTextTheme.title.color),
|
color: Theme.of(context).primaryTextTheme.title.color),
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/buy/buy_amount.dart';
|
||||||
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
|
||||||
import 'package:cake_wallet/di.dart';
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||||
import 'package:cake_wallet/store/app_store.dart';
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
@ -14,7 +15,7 @@ import 'package:flutter/cupertino.dart';
|
||||||
import 'package:country_pickers/country_pickers.dart';
|
import 'package:country_pickers/country_pickers.dart';
|
||||||
import 'package:country_pickers/countries.dart';
|
import 'package:country_pickers/countries.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/entities/service_plan.dart';
|
import 'package:cake_wallet/entities/cake_phone_entities/service_plan.dart';
|
||||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
|
@ -34,7 +35,7 @@ class PhoneNumberProductPage extends BasePage {
|
||||||
S.of(context).phone_number,
|
S.of(context).phone_number,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
color: Theme.of(context).primaryTextTheme.title.color),
|
color: Theme.of(context).primaryTextTheme.title.color),
|
||||||
);
|
);
|
||||||
|
@ -336,7 +337,7 @@ class PhoneNumberProductBodyState extends State<PhoneNumberProductBody> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
receiptRow(S.of(context).amount, amountText(phonePlanViewModel.totalPrice)),
|
receiptRow(S.of(context).amount, amountText(phonePlanViewModel.totalPrice)),
|
||||||
receiptRow(S.of(context).cake_pay_balance, amountText(100)),
|
receiptRow("${S.of(context).cake_pay_balance}: ", amountText(100)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
isDividerExists: true,
|
isDividerExists: true,
|
||||||
|
@ -344,6 +345,11 @@ class PhoneNumberProductBodyState extends State<PhoneNumberProductBody> {
|
||||||
leftButtonText: S.of(context).cancel,
|
leftButtonText: S.of(context).cancel,
|
||||||
actionRightButton: () {
|
actionRightButton: () {
|
||||||
Navigator.of(dialogContext).pop();
|
Navigator.of(dialogContext).pop();
|
||||||
|
Navigator.pushNamedAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
Routes.cakePhoneActiveServices,
|
||||||
|
ModalRoute.withName(Routes.cakePhoneWelcome),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
actionLeftButton: () => Navigator.of(dialogContext).pop());
|
actionLeftButton: () => Navigator.of(dialogContext).pop());
|
||||||
});
|
});
|
||||||
|
@ -452,7 +458,7 @@ class PhoneNumberProductBodyState extends State<PhoneNumberProductBody> {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"$title:",
|
title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
|
@ -483,26 +489,37 @@ class PhoneNumberProductBodyState extends State<PhoneNumberProductBody> {
|
||||||
builder: (context, AsyncSnapshot<BuyAmount> snapshot) {
|
builder: (context, AsyncSnapshot<BuyAmount> snapshot) {
|
||||||
double sourceAmount;
|
double sourceAmount;
|
||||||
double destAmount;
|
double destAmount;
|
||||||
double achAmount;
|
|
||||||
int minAmount;
|
|
||||||
|
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
sourceAmount = snapshot.data.sourceAmount;
|
sourceAmount = snapshot.data.sourceAmount;
|
||||||
destAmount = snapshot.data.destAmount;
|
destAmount = snapshot.data.destAmount;
|
||||||
minAmount = snapshot.data.minAmount;
|
|
||||||
achAmount = snapshot.data.achSourceAmount;
|
|
||||||
} else {
|
} else {
|
||||||
sourceAmount = 0.0;
|
sourceAmount = 0.0;
|
||||||
destAmount = 0.0;
|
destAmount = 0.0;
|
||||||
minAmount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Text(sourceAmount.toString()),
|
Text(
|
||||||
Text(destAmount.toString()),
|
"${sourceAmount} ${getIt.get<AppStore>().wallet.currency.toString()}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Theme.of(context).primaryTextTheme.title.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${destAmount} ${FiatCurrency.usd.title}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Theme.of(context).accentTextTheme.subhead.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class CakePhoneProductsPage extends BasePage {
|
||||||
S.of(context).get_phone_number,
|
S.of(context).get_phone_number,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
color: Theme.of(context).primaryTextTheme.title.color),
|
color: Theme.of(context).primaryTextTheme.title.color),
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,7 +21,7 @@ class CakePhoneVerificationPage extends BasePage {
|
||||||
S.of(context).email_verification,
|
S.of(context).email_verification,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
color: Theme.of(context).primaryTextTheme.title.color),
|
color: Theme.of(context).primaryTextTheme.title.color),
|
||||||
);
|
);
|
||||||
|
@ -123,7 +123,11 @@ class CakePhoneVerificationBodyState extends State<CakePhoneVerificationBody> {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PrimaryButton(
|
PrimaryButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pushNamed(context, Routes.cakePhoneProducts);
|
Navigator.pushNamedAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
Routes.cakePhoneProducts,
|
||||||
|
ModalRoute.withName(Routes.cakePhoneWelcome),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
text: S.of(context).continue_text,
|
text: S.of(context).continue_text,
|
||||||
color: Theme.of(context).accentTextTheme.body2.color,
|
color: Theme.of(context).accentTextTheme.body2.color,
|
||||||
|
|
|
@ -18,7 +18,7 @@ class CakePhoneWelcomePage extends BasePage {
|
||||||
S.of(context).welcome_to_cake_phone,
|
S.of(context).welcome_to_cake_phone,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w700,
|
||||||
fontFamily: 'Lato',
|
fontFamily: 'Lato',
|
||||||
color: titleColor ??
|
color: titleColor ??
|
||||||
Theme.of(context).primaryTextTheme.title.color),
|
Theme.of(context).primaryTextTheme.title.color),
|
||||||
|
|
43
lib/src/screens/cake_phone/widgets/add_options_tile.dart
Normal file
43
lib/src/screens/cake_phone/widgets/add_options_tile.dart
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AddOptionsTile extends StatelessWidget {
|
||||||
|
const AddOptionsTile({Key key, @required this.leading, this.onTap}) : super(key: key);
|
||||||
|
|
||||||
|
final Widget leading;
|
||||||
|
final Function() onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(15)),
|
||||||
|
color: Theme.of(context).primaryTextTheme.display3.decorationColor,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: leading,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 2,
|
||||||
|
height: 48,
|
||||||
|
color: Theme.of(context).primaryTextTheme.title.color,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
color: Theme.of(context).primaryTextTheme.title.color,
|
||||||
|
),
|
||||||
|
child: Icon(Icons.add, color: Colors.white, size: 15),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
47
lib/src/screens/cake_phone/widgets/info_text_column.dart
Normal file
47
lib/src/screens/cake_phone/widgets/info_text_column.dart
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class InfoTextColumn extends StatelessWidget {
|
||||||
|
const InfoTextColumn({
|
||||||
|
Key key,
|
||||||
|
@required this.title,
|
||||||
|
@required this.subtitle,
|
||||||
|
this.isReversed = false,
|
||||||
|
this.padding,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String subtitle;
|
||||||
|
final bool isReversed;
|
||||||
|
final EdgeInsets padding;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: isReversed ? subtitleTextStyle(context) : titleTextStyle(context),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: padding ?? const EdgeInsets.only(top: 4),
|
||||||
|
child: Text(
|
||||||
|
subtitle,
|
||||||
|
style: isReversed ? titleTextStyle(context) : subtitleTextStyle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle subtitleTextStyle(BuildContext context) => TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context).accentTextTheme.subhead.color,
|
||||||
|
);
|
||||||
|
|
||||||
|
TextStyle titleTextStyle(BuildContext context) => TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Theme.of(context).primaryTextTheme.title.color,
|
||||||
|
);
|
||||||
|
}
|
105
lib/src/screens/cake_phone/widgets/subscribed_phone_numbers.dart
Normal file
105
lib/src/screens/cake_phone/widgets/subscribed_phone_numbers.dart
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/entities/cake_phone_entities/phone_number_service.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/widgets/add_options_tile.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/cake_phone/widgets/info_text_column.dart';
|
||||||
|
|
||||||
|
class SubscribedPhoneNumbers extends StatefulWidget {
|
||||||
|
const SubscribedPhoneNumbers({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SubscribedPhoneNumbersState createState() => _SubscribedPhoneNumbersState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SubscribedPhoneNumbersState extends State<SubscribedPhoneNumbers> {
|
||||||
|
int selectedTab = 0;
|
||||||
|
final List<PhoneNumberService> subscribedPhoneNumbers = [
|
||||||
|
PhoneNumberService(id: "1", phoneNumber: "+1 888-888-8888", usedUntil: DateTime.now().add(Duration(days: 24))),
|
||||||
|
PhoneNumberService(id: "2", phoneNumber: "+1 888-888-8888", usedUntil: DateTime.now().add(Duration(days: 26))),
|
||||||
|
PhoneNumberService(id: "3", phoneNumber: "+1 999-999-9999", usedUntil: DateTime.now().subtract(Duration(days: 24))),
|
||||||
|
PhoneNumberService(id: "4", phoneNumber: "+1 999-999-9999", usedUntil: DateTime.now().subtract(Duration(days: 26))),
|
||||||
|
];
|
||||||
|
|
||||||
|
final List<PhoneNumberService> activePhoneNumbers = [];
|
||||||
|
final List<PhoneNumberService> expiredPhoneNumbers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
for (PhoneNumberService element in subscribedPhoneNumbers) {
|
||||||
|
if (element.usedUntil.isAfter(DateTime.now())) {
|
||||||
|
activePhoneNumbers.add(element);
|
||||||
|
} else {
|
||||||
|
expiredPhoneNumbers.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(5),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
|
color: Theme.of(context).primaryTextTheme.display3.decorationColor,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
tab(S.of(context).active, 0),
|
||||||
|
tab(S.of(context).expired, 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
...(selectedTab == 0 ? activePhoneNumbers : expiredPhoneNumbers).map(
|
||||||
|
(e) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
|
child: AddOptionsTile(
|
||||||
|
leading: InfoTextColumn(
|
||||||
|
title: e.phoneNumber,
|
||||||
|
subtitle: selectedTab == 0
|
||||||
|
? "${e.usedUntil.difference(DateTime.now()).inDays} ${S.of(context).days_of_service_remaining}"
|
||||||
|
: S.of(context).expired,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget tab(String title, int tabIndex) {
|
||||||
|
final selected = selectedTab == tabIndex;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (!selected) {
|
||||||
|
setState(() {
|
||||||
|
selectedTab = tabIndex;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
|
color: selected
|
||||||
|
? Theme.of(context).accentTextTheme.body2.color
|
||||||
|
: Theme.of(context).primaryTextTheme.display3.decorationColor,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: selected ? FontWeight.w700 : FontWeight.w500,
|
||||||
|
color: selected ? Colors.white : Theme.of(context).primaryTextTheme.title.color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,7 +82,7 @@ class WalletMenu {
|
||||||
handler: () => Navigator.of(context).pushNamed(Routes.support)),
|
handler: () => Navigator.of(context).pushNamed(Routes.support)),
|
||||||
// TODO: Move this to marketplace screen when ready
|
// TODO: Move this to marketplace screen when ready
|
||||||
WalletMenuItem(
|
WalletMenuItem(
|
||||||
title: S.current.settings_support,
|
title: "Temp Cake Phone",
|
||||||
image: Image.asset('assets/images/question_mark.png',
|
image: Image.asset('assets/images/question_mark.png',
|
||||||
height: 16, width: 16, color: Palette.darkBlue),
|
height: 16, width: 16, color: Palette.darkBlue),
|
||||||
handler: () => Navigator.of(context).pushNamed(Routes.cakePhoneWelcome)),
|
handler: () => Navigator.of(context).pushNamed(Routes.cakePhoneWelcome)),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:cake_wallet/entities/service_plan.dart';
|
import 'package:cake_wallet/entities/cake_phone_entities/service_plan.dart';
|
||||||
import 'package:country_pickers/countries.dart';
|
import 'package:country_pickers/countries.dart';
|
||||||
import 'package:country_pickers/country.dart';
|
import 'package:country_pickers/country.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
|
@ -568,5 +568,12 @@
|
||||||
"phone_number_country": "Phone Number Country",
|
"phone_number_country": "Phone Number Country",
|
||||||
"additional_sms_messages": "Additional SMS Messages",
|
"additional_sms_messages": "Additional SMS Messages",
|
||||||
"confirm_payment": "Confirm payment",
|
"confirm_payment": "Confirm payment",
|
||||||
"cake_pay_balance": "CakePay Balance"
|
"cake_pay_balance": "CakePay Balance",
|
||||||
|
"active_services": "Active Services",
|
||||||
|
"new_phone_number": "New Phone Number",
|
||||||
|
"free_sms_balance": "Free SMS Balance",
|
||||||
|
"free_data_balance": "Free Data Balance",
|
||||||
|
"account_balance": "Account Balance",
|
||||||
|
"days_of_service_remaining": "days of service remaining",
|
||||||
|
"active": "Active"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue