Compare commits
71 Commits
99db140a0c
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 848891e1f4 | |||
| 4f2380fcdf | |||
| c23075304a | |||
| 17c7559158 | |||
| 711e5f3f52 | |||
| a99365fb0a | |||
| 41f0bb7a68 | |||
| c97130239d | |||
| 1b867227c7 | |||
| 4b07219928 | |||
| 9cdda42b8b | |||
| 6f5d3ccca8 | |||
| ff515e2621 | |||
| f057a346c2 | |||
| f84fe1017d | |||
| 27ba55314b | |||
| 59e046bd92 | |||
| 4461b78565 | |||
| f2f688f9f3 | |||
| d1adfd2ab0 | |||
| 33b2ab85e3 | |||
| 6a43a3dcaf | |||
| db1280b272 | |||
| ae4f9c25c4 | |||
| a87afe16cb | |||
| 1904e9a4a3 | |||
| d79959c47f | |||
| 38837bd4f8 | |||
| d966108e9e | |||
| 506f364b87 | |||
| 506480d812 | |||
| a6ea9a2314 | |||
| 176261923d | |||
| a3148d8210 | |||
| 6e03fa5fa7 | |||
| de1782c2c2 | |||
| 89a79276a6 | |||
| 4737a91ab1 | |||
| ff135dd47b | |||
| 2e98c1a234 | |||
| c4c0479341 | |||
| e510aaefd7 | |||
| dfb947dce5 | |||
| 9761dc369c | |||
| 9e2304990c | |||
| 8b1b3e950f | |||
| aa987fe320 | |||
| ad6195061d | |||
| b5a382ce96 | |||
| fdca27233b | |||
| bd065242e6 | |||
| a35110af71 | |||
| 83211e76f9 | |||
| 57a4e828c9 | |||
| 466d49312d | |||
| 9ba8b79112 | |||
| 4f50dc951a | |||
| d66a9e3435 | |||
| 8e04b4e77e | |||
| afc2bd3cc9 | |||
| 66ace5b217 | |||
| 5cb76fca7f | |||
| e86e67b9c9 | |||
| a6248520ef | |||
| eb1eb83d52 | |||
| 7706fe4387 | |||
| 9da1675250 | |||
| 298d7f46d2 | |||
| 368f326123 | |||
| a574f30424 | |||
| ce2bf8a777 |
BIN
assets/icons/icon-card.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/icons/icon-ceklis-outline.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/icons/icon-chat.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/icons/icon-education.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/icons/icon-fund.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/icons/icon-gadget-outline.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/icon-home.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/icon-lock.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
assets/icons/icon-logout.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
assets/icons/icon-navigation-home.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/icons/icon-navigation-plan.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/icons/icon-navigation-portfolio.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/icons/icon-navigation-profile.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/icons/icon-navigation-transaction.png
Normal file
|
After Width: | Height: | Size: 899 B |
BIN
assets/icons/icon-profile.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/icons/icon-remove.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/icons/icon-setting.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/icons/icon-shop.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/images/bg-profile.png
Normal file
|
After Width: | Height: | Size: 4.0 MiB |
BIN
assets/images/frame-signature.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
assets/images/img-cat-outlined.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/images/img-empty-transaction.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
assets/images/img-expand-purchase.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
assets/images/img-finish.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
@@ -37,6 +37,9 @@ class PathAssets {
|
|||||||
static const String iconHouse = 'assets/icons/icon-house.png';
|
static const String iconHouse = 'assets/icons/icon-house.png';
|
||||||
static const String iconToga = 'assets/icons/icon-toga.png';
|
static const String iconToga = 'assets/icons/icon-toga.png';
|
||||||
static const String iconCreatePlan = 'assets/icons/icon-create-plan.png';
|
static const String iconCreatePlan = 'assets/icons/icon-create-plan.png';
|
||||||
|
static const String iconChecklistOutlined =
|
||||||
|
'assets/icons/icon-ceklis-outline.png';
|
||||||
|
static const String iconLock = 'assets/icons/icon-lock.png';
|
||||||
static const String iconThumb = 'assets/icons/icon-thumb.png';
|
static const String iconThumb = 'assets/icons/icon-thumb.png';
|
||||||
static const String iconPortofolio = 'assets/icons/icon-portofolio.png';
|
static const String iconPortofolio = 'assets/icons/icon-portofolio.png';
|
||||||
static const String iconPlane = 'assets/icons/icon-plane.png';
|
static const String iconPlane = 'assets/icons/icon-plane.png';
|
||||||
@@ -46,6 +49,28 @@ class PathAssets {
|
|||||||
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
static const String iconTicket = 'assets/icons/icon-ticket.png';
|
||||||
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
static const String iconGadget = 'assets/icons/icon-gadget.png';
|
||||||
static const String iconCar = 'assets/icons/icon-car.png';
|
static const String iconCar = 'assets/icons/icon-car.png';
|
||||||
|
static const String iconNavigationHome =
|
||||||
|
'assets/icons/icon-navigation-home.png';
|
||||||
|
static const String iconNavigationPlan =
|
||||||
|
'assets/icons/icon-navigation-plan.png';
|
||||||
|
static const String iconNavigationTransaction =
|
||||||
|
'assets/icons/icon-navigation-transaction.png';
|
||||||
|
static const String iconNavigationPortfolio =
|
||||||
|
'assets/icons/icon-navigation-portfolio.png';
|
||||||
|
static const String iconNavigationProfile =
|
||||||
|
'assets/icons/icon-navigation-profile.png';
|
||||||
|
static const String iconRemove = 'assets/icons/icon-remove.png';
|
||||||
|
static const String iconEducation = 'assets/icons/icon-education.png';
|
||||||
|
static const String iconFund = 'assets/icons/icon-fund.png';
|
||||||
|
static const String iconHome = 'assets/icons/icon-home.png';
|
||||||
|
static const String iconShop = 'assets/icons/icon-shop.png';
|
||||||
|
static const String iconCard = 'assets/icons/icon-card.png';
|
||||||
|
static const String iconChat = 'assets/icons/icon-chat.png';
|
||||||
|
static const String iconLogout = 'assets/icons/icon-logout.png';
|
||||||
|
static const String iconProfile = 'assets/icons/icon-profile.png';
|
||||||
|
static const String iconSetting = 'assets/icons/icon-setting.png';
|
||||||
|
static const String iconGadgetOutline =
|
||||||
|
'assets/icons/icon-gadget-outline.png';
|
||||||
|
|
||||||
/// IMAGE
|
/// IMAGE
|
||||||
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
static const String imgSplashLogo = 'assets/images/splash-logo.png';
|
||||||
@@ -74,11 +99,36 @@ class PathAssets {
|
|||||||
static const String imgMoneyIncome = 'assets/images/img-money-income.png';
|
static const String imgMoneyIncome = 'assets/images/img-money-income.png';
|
||||||
static const String imgGrowing = 'assets/images/img-growing.png';
|
static const String imgGrowing = 'assets/images/img-growing.png';
|
||||||
static const String imgCat = 'assets/images/img-cat.png';
|
static const String imgCat = 'assets/images/img-cat.png';
|
||||||
|
static const String imgCatOutlined = 'assets/images/img-cat-outlined.png';
|
||||||
static const String imgDeer = 'assets/images/img-deer.png';
|
static const String imgDeer = 'assets/images/img-deer.png';
|
||||||
static const String imgLion = 'assets/images/img-lion.png';
|
static const String imgLion = 'assets/images/img-lion.png';
|
||||||
static const String imgGuideBank = 'assets/images/img-guide-bank.png';
|
static const String imgGuideBank = 'assets/images/img-guide-bank.png';
|
||||||
static const String imgGuide1 = 'assets/images/img-guide1.png';
|
static const String imgGuide1 = 'assets/images/img-guide1.png';
|
||||||
static const String imgGuide2 = 'assets/images/img-guide2.png';
|
static const String imgGuide2 = 'assets/images/img-guide2.png';
|
||||||
static const String imgOpenShopping = 'assets/images/img-open-shopping.png';
|
static const String imgOpenShopping = 'assets/images/img-open-shopping.png';
|
||||||
static const String imgPaymentSuccess = 'assets/images/img-payment-success.png';
|
static const String imgPaymentSuccess =
|
||||||
|
'assets/images/img-payment-success.png';
|
||||||
|
static const String frameSignature = 'assets/images/frame-signature.png';
|
||||||
|
static const String imgFinish = 'assets/images/img-finish.png';
|
||||||
|
static const String imgExpandPurchase =
|
||||||
|
'assets/images/img-expand-purchase.png';
|
||||||
|
static const String imgEmptyTransaction =
|
||||||
|
'assets/images/img-empty-transaction.png';
|
||||||
|
static const String bgProfile = 'assets/images/bg-profile.png';
|
||||||
|
|
||||||
|
static const Map<String, String> goalInvestIcon = {
|
||||||
|
'Education': iconToga,
|
||||||
|
'Marriage': iconCake,
|
||||||
|
'Old age days': iconHouse,
|
||||||
|
'Home': iconHouse,
|
||||||
|
'Other Plan': iconCreatePlan,
|
||||||
|
'Create Plan': iconCreatePlan,
|
||||||
|
'Entertainment': iconTicket,
|
||||||
|
'Gadget': iconGadget,
|
||||||
|
'Business': iconMarket,
|
||||||
|
'Fashion': iconBag,
|
||||||
|
'Shop': iconBag,
|
||||||
|
'Vehicle': iconCar,
|
||||||
|
'Holiday': iconPlane,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CardTransactionView extends StatelessWidget {
|
||||||
|
final VoidCallback onTap;
|
||||||
|
final String iconPath, type, amount, subs, step;
|
||||||
|
final String? timeTransaction;
|
||||||
|
const CardTransactionView({
|
||||||
|
Key? key,
|
||||||
|
required this.step,
|
||||||
|
required this.type,
|
||||||
|
required this.amount,
|
||||||
|
required this.iconPath,
|
||||||
|
required this.subs,
|
||||||
|
required this.onTap,
|
||||||
|
this.timeTransaction,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: SizeConfig.width * .4,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: iconPath, width: SizeConfig.width * .12),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Text(
|
||||||
|
type,
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
child: Text(
|
||||||
|
amount,
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
width: SizeConfig.width * .4,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: SizeConfig.height * .08,
|
||||||
|
child: Text(
|
||||||
|
subs,
|
||||||
|
style: const TextStyle(color: ColorPalette.primary),
|
||||||
|
)),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
step == 'waiting'
|
||||||
|
? const Icon(Icons.access_time_sharp,
|
||||||
|
color: ColorPalette.slate400)
|
||||||
|
: const SizedBox(),
|
||||||
|
step == 'waiting'
|
||||||
|
? Text(timeTransaction.toString())
|
||||||
|
: const SizedBox(),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16.0),
|
||||||
|
child: Icon(Icons.arrow_forward_ios),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class EmptyCardTransaction extends StatelessWidget {
|
||||||
|
final VoidCallback onPressedButton;
|
||||||
|
const EmptyCardTransaction({Key? key, required this.onPressedButton})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgEmptyTransaction,
|
||||||
|
width: SizeConfig.width * .4,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'No Transaction Yet',
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Let's keep building your investment for even greater financial growth!",
|
||||||
|
style: textTheme.bodyMedium,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Investing Now',
|
||||||
|
width: SizeConfig.width * .5,
|
||||||
|
onPressed: onPressedButton,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,9 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
const CustomAppBar({
|
const CustomAppBar({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.height,
|
required this.height,
|
||||||
this.leading,
|
|
||||||
required this.title,
|
required this.title,
|
||||||
this.trailing,
|
this.trailing,
|
||||||
|
this.leading,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
144
lib/application/component/date_picker/date_picker_view.dart
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import 'package:calendar_date_picker2/calendar_date_picker2.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class DatePickerView extends StatelessWidget {
|
||||||
|
final String name;
|
||||||
|
final TextEditingController ctrl;
|
||||||
|
final DateTime? minDate, maxDate;
|
||||||
|
final String? hintText, buttonName;
|
||||||
|
final bool isMultipleSelection, enabled;
|
||||||
|
final List<DateTime>? initialValue;
|
||||||
|
final ValueChanged<OnChangedDatePickerModel>? onChanged;
|
||||||
|
final ValueChanged<List<DateTime?>>? onFinish;
|
||||||
|
final FormFieldValidator<String>? validatorDate;
|
||||||
|
const DatePickerView(
|
||||||
|
{Key? key,
|
||||||
|
required this.name,
|
||||||
|
required this.ctrl,
|
||||||
|
this.minDate,
|
||||||
|
this.maxDate,
|
||||||
|
this.hintText,
|
||||||
|
this.buttonName,
|
||||||
|
required this.isMultipleSelection,
|
||||||
|
required this.enabled,
|
||||||
|
this.initialValue,
|
||||||
|
this.onChanged,
|
||||||
|
this.onFinish,
|
||||||
|
this.validatorDate})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
String _dateFormat(DateTime? dateTime) =>
|
||||||
|
dateTime != null ? DateFormat('dd/MM/yyyy').format(dateTime) : "";
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<DateTime?> initData = initialValue ?? [];
|
||||||
|
List<DateTime?> dateList = [];
|
||||||
|
|
||||||
|
String dateLabel() {
|
||||||
|
return dateList.map((e) => _dateFormat(e)).join(" - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangedDatePicker(List<DateTime?> value) {
|
||||||
|
if (isMultipleSelection) {
|
||||||
|
final pickerDateRange = PickerDateRange(
|
||||||
|
startDate: value[0] ?? DateTime.now(),
|
||||||
|
endDate:
|
||||||
|
value.length > 1 ? value[1] ?? DateTime.now() : DateTime.now(),
|
||||||
|
);
|
||||||
|
onChanged
|
||||||
|
?.call(OnChangedDatePickerModel(pickerDateRange: pickerDateRange));
|
||||||
|
} else {
|
||||||
|
onChanged?.call(OnChangedDatePickerModel(dateTime: value[0]));
|
||||||
|
}
|
||||||
|
dateList = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogDatePicker() {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
height: SizeConfig.height * .65,
|
||||||
|
child: Column(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
CalendarDatePicker2(
|
||||||
|
value: [...initData],
|
||||||
|
config: CalendarDatePicker2Config(
|
||||||
|
centerAlignModePicker: true,
|
||||||
|
calendarType: isMultipleSelection
|
||||||
|
? CalendarDatePicker2Type.range
|
||||||
|
: CalendarDatePicker2Type.single,
|
||||||
|
customModePickerIcon: const SizedBox(),
|
||||||
|
firstDate: minDate ?? DateTime(1900),
|
||||||
|
lastDate: maxDate,
|
||||||
|
),
|
||||||
|
// initialValue: [...initData],
|
||||||
|
onValueChanged: (value) {
|
||||||
|
onChangedDatePicker(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: ButtonView(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
onPressed: () {
|
||||||
|
if (dateList.isNotEmpty) {
|
||||||
|
onFinish?.call(dateList);
|
||||||
|
ctrl.text = dateLabel();
|
||||||
|
initData = dateList;
|
||||||
|
}
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
name: 'OK',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextFormView(
|
||||||
|
name: name,
|
||||||
|
hintText: hintText,
|
||||||
|
readOnly: true,
|
||||||
|
ctrl: ctrl,
|
||||||
|
validator: validatorDate,
|
||||||
|
enabled: enabled,
|
||||||
|
onTap: () {
|
||||||
|
if (enabled) dialogDatePicker();
|
||||||
|
},
|
||||||
|
suffixIcon: const UnconstrainedBox(
|
||||||
|
child: Icon(
|
||||||
|
Icons.calendar_today_rounded,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OnChangedDatePickerModel {
|
||||||
|
final DateTime? dateTime;
|
||||||
|
final PickerDateRange? pickerDateRange;
|
||||||
|
|
||||||
|
OnChangedDatePickerModel({this.dateTime, this.pickerDateRange});
|
||||||
|
}
|
||||||
|
|
||||||
|
class PickerDateRange {
|
||||||
|
final DateTime startDate;
|
||||||
|
final DateTime endDate;
|
||||||
|
|
||||||
|
PickerDateRange({required this.startDate, required this.endDate});
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
import 'package:cims_apps/application/component/expandable_widget/see_more_less_widget.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ExpandableWidget extends StatelessWidget {
|
||||||
|
final String? content;
|
||||||
|
final double? fontSize;
|
||||||
|
final int maxLinesToShow;
|
||||||
|
final Alignment? alignmentMore;
|
||||||
|
final bool? hideTextMore;
|
||||||
|
final bool? hideIconMore;
|
||||||
|
|
||||||
|
ExpandableWidget({
|
||||||
|
super.key,
|
||||||
|
required this.content,
|
||||||
|
this.fontSize,
|
||||||
|
this.maxLinesToShow = 1,
|
||||||
|
this.alignmentMore,
|
||||||
|
this.hideTextMore = false,
|
||||||
|
this.hideIconMore = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
ValueNotifier<bool> expanded = ValueNotifier(false);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final TextSpan textSpan = TextSpan(
|
||||||
|
text: content ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize ?? 16.0,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final TextPainter textPainter = TextPainter(
|
||||||
|
text: textSpan,
|
||||||
|
maxLines: expanded.value ? null : maxLinesToShow,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
strutStyle: StrutStyle(
|
||||||
|
fontSize: fontSize ?? 16.0,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
textPainter.layout(maxWidth: SizeConfig.width);
|
||||||
|
|
||||||
|
final int numberOfLines = textPainter.computeLineMetrics().length;
|
||||||
|
return ValueListenableBuilder(
|
||||||
|
valueListenable: expanded,
|
||||||
|
builder: (context, values, _) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
|
if (!expanded.value && numberOfLines >= maxLinesToShow) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
content ?? "",
|
||||||
|
maxLines: maxLinesToShow,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize ?? 16.0,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* See More :: type 1 - See More | 2 - See Less */
|
||||||
|
SeeMoreLessWidget(
|
||||||
|
textData: 'See More',
|
||||||
|
type: 1,
|
||||||
|
section: 1,
|
||||||
|
onSeeMoreLessTap: () {
|
||||||
|
expanded.value = true;
|
||||||
|
},
|
||||||
|
alignment: alignmentMore,
|
||||||
|
hideIconMore: hideIconMore!,
|
||||||
|
hideTextMore: hideTextMore!,
|
||||||
|
),
|
||||||
|
/* See More :: type 1 - See More | 2 - See Less */
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
content ?? "",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: fontSize ?? 16.0,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (expanded.value && numberOfLines >= maxLinesToShow)
|
||||||
|
/* See Less :: type 1 - See More | 2 - See Less */
|
||||||
|
SeeMoreLessWidget(
|
||||||
|
textData: 'See Less',
|
||||||
|
type: 2,
|
||||||
|
section: 1,
|
||||||
|
onSeeMoreLessTap: () {
|
||||||
|
expanded.value = false;
|
||||||
|
},
|
||||||
|
alignment: alignmentMore,
|
||||||
|
hideIconMore: hideIconMore!,
|
||||||
|
hideTextMore: hideTextMore!,
|
||||||
|
),
|
||||||
|
/* See Less :: type 1 - See More | 2 - See Less */
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SeeMoreLessWidget extends StatelessWidget {
|
||||||
|
final String? textData;
|
||||||
|
final int? type; /* type 1 - See More | 2 - See Less */
|
||||||
|
final Function? onSeeMoreLessTap;
|
||||||
|
final int?
|
||||||
|
section; /* 1: About the course | 2 - Who can take up this course? | 3 - Mentors | 4 - Course Video Reviews */
|
||||||
|
final Alignment? alignment;
|
||||||
|
final bool hideTextMore;
|
||||||
|
final bool hideIconMore;
|
||||||
|
|
||||||
|
const SeeMoreLessWidget({
|
||||||
|
super.key,
|
||||||
|
required this.textData,
|
||||||
|
required this.type,
|
||||||
|
required this.onSeeMoreLessTap,
|
||||||
|
required this.section,
|
||||||
|
required this.alignment,
|
||||||
|
required this.hideTextMore,
|
||||||
|
required this.hideIconMore,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Align(
|
||||||
|
alignment: alignment ?? Alignment.centerLeft,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (onSeeMoreLessTap != null) {
|
||||||
|
onSeeMoreLessTap!();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text.rich(
|
||||||
|
softWrap: true,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
TextSpan(
|
||||||
|
text: "",
|
||||||
|
children: [
|
||||||
|
if(!hideTextMore)
|
||||||
|
TextSpan(
|
||||||
|
text: textData,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if(!hideTextMore && !hideIconMore)
|
||||||
|
const WidgetSpan(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 3.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if(!hideIconMore)
|
||||||
|
WidgetSpan(
|
||||||
|
child: Icon(
|
||||||
|
(type == 1)
|
||||||
|
? Icons.keyboard_arrow_down
|
||||||
|
: Icons.keyboard_arrow_up,
|
||||||
|
color: ColorPalette.slate300,
|
||||||
|
size: 28,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
75
lib/application/component/list_tile/list_tile_view.dart
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ListTileView extends StatelessWidget {
|
||||||
|
final String title;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final Widget? prefixIcon, suffixIcon;
|
||||||
|
final EdgeInsetsGeometry? padding, margin;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
const ListTileView(
|
||||||
|
{Key? key,
|
||||||
|
required this.title,
|
||||||
|
this.onPressed,
|
||||||
|
this.prefixIcon,
|
||||||
|
this.suffixIcon,
|
||||||
|
this.padding,
|
||||||
|
this.textStyle,
|
||||||
|
this.margin})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: padding ??
|
||||||
|
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 8.0),
|
||||||
|
margin: margin ?? const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorPalette.blue50,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
color: ColorPalette.greyLights,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
prefixIcon ??
|
||||||
|
const ImageView(
|
||||||
|
image: PathAssets.iconChecklistOutlined,
|
||||||
|
width: 38,
|
||||||
|
height: 38,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: textStyle ??
|
||||||
|
const TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
suffixIcon ??
|
||||||
|
IconButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// : const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -102,7 +104,8 @@ class NumericPad extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: FontWeight.bold
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -117,8 +120,9 @@ class NumericPad extends StatelessWidget {
|
|||||||
onNumberSelected('');
|
onNumberSelected('');
|
||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.highlight_remove,
|
Icons.backspace_outlined,
|
||||||
size: 28,
|
size: 28,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/otp/otp_viewmodel.dart';
|
import 'package:cims_apps/application/component/otp/otp_viewmodel.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -112,10 +113,8 @@ class OtpView extends StatelessWidget {
|
|||||||
create: (context) => OtpViewModel(),
|
create: (context) => OtpViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: CustomAppBar(height: SizeConfig.height * .1, title: title),
|
||||||
title: Text(title),
|
body: SingleChildScrollView(
|
||||||
),
|
|
||||||
body: Container(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child:
|
child:
|
||||||
Consumer<OtpViewModel>(builder: (context, provider, child) {
|
Consumer<OtpViewModel>(builder: (context, provider, child) {
|
||||||
|
|||||||
57
lib/application/component/radio_agreement.dart
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class RadioAgreement extends StatelessWidget {
|
||||||
|
final void Function() onTap;
|
||||||
|
final bool isAgree;
|
||||||
|
final String desc;
|
||||||
|
const RadioAgreement({super.key, required this.isAgree, required this.desc, required this.onTap,});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: AnimatedContainer(
|
||||||
|
margin: const EdgeInsets.only(top: 4),
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: isAgree
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate200)),
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
isAgree ? ColorPalette.primary : ColorPalette.white,
|
||||||
|
shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: ExpandableWidget(
|
||||||
|
content: desc,
|
||||||
|
maxLinesToShow: 3,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/expandable_widget/expandable_widget.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
||||||
@@ -73,20 +74,20 @@ class RiskProfile extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
riskProfile.type,
|
riskProfile.type,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
color: ColorPalette.white
|
color: ColorPalette.white
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16,),
|
const SizedBox(height: 16,),
|
||||||
Text('Total Score :',
|
const Text('Total Score :',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -94,7 +95,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('$totalScore',
|
Text('$totalScore',
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
color: ColorPalette.white
|
color: ColorPalette.white
|
||||||
@@ -107,20 +108,20 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
Text(
|
ExpandableWidget(
|
||||||
riskProfile.desc,
|
content: riskProfile.desc,
|
||||||
style: TextStyle(
|
hideTextMore: true,
|
||||||
color: ColorPalette.slate500,
|
hideIconMore: false,
|
||||||
fontSize: 16
|
maxLinesToShow: 4,
|
||||||
)
|
alignmentMore: Alignment.center,
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
Text(
|
const Text(
|
||||||
'Suitable Product',
|
'Suitable Product',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
@@ -128,7 +129,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
fontSize: 18
|
fontSize: 18
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
rowSuitableProduct ?
|
rowSuitableProduct ?
|
||||||
@@ -137,7 +138,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0),
|
margin: EdgeInsets.only(left: e.key != 0 ? 12 : 0),
|
||||||
padding: EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
borderRadius: BorderRadius.circular(6)
|
borderRadius: BorderRadius.circular(6)
|
||||||
@@ -146,18 +147,18 @@ class RiskProfile extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: riskProfile.color.withOpacity(0.1)
|
color: riskProfile.color.withOpacity(0.1)
|
||||||
),
|
),
|
||||||
child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
child: Image.asset(e.value['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Text(e.value['desc'],
|
Text(e.value['desc'],
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
@@ -173,7 +174,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: riskProfile.suitableProduct.map((e) {
|
children: riskProfile.suitableProduct.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
@@ -181,7 +182,7 @@ class RiskProfile extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
@@ -189,12 +190,12 @@ class RiskProfile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: riskProfile.color)
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(e['desc'],
|
child: Text(e['desc'],
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class ItemSelectForm {
|
|||||||
final String text;
|
final String text;
|
||||||
final String? description;
|
final String? description;
|
||||||
final bool isOther;
|
final bool isOther;
|
||||||
final String image;
|
String image;
|
||||||
|
|
||||||
ItemSelectForm(
|
ItemSelectForm(
|
||||||
this.key,
|
this.key,
|
||||||
@@ -25,7 +25,6 @@ class SelectFormView extends StatelessWidget {
|
|||||||
final String? hintText;
|
final String? hintText;
|
||||||
final TextStyle? hintTextStyle;
|
final TextStyle? hintTextStyle;
|
||||||
final TextEditingController? ctrl;
|
final TextEditingController? ctrl;
|
||||||
final Widget? bottomSheetTitle;
|
|
||||||
final List<ItemSelectForm> listItem;
|
final List<ItemSelectForm> listItem;
|
||||||
final ValueChanged<String> onSelect;
|
final ValueChanged<String> onSelect;
|
||||||
final FormFieldValidator<String>? validator;
|
final FormFieldValidator<String>? validator;
|
||||||
@@ -37,7 +36,6 @@ class SelectFormView extends StatelessWidget {
|
|||||||
this.hintText,
|
this.hintText,
|
||||||
this.hintTextStyle,
|
this.hintTextStyle,
|
||||||
this.ctrl,
|
this.ctrl,
|
||||||
this.bottomSheetTitle,
|
|
||||||
required this.listItem,
|
required this.listItem,
|
||||||
required this.onSelect,
|
required this.onSelect,
|
||||||
this.validator,
|
this.validator,
|
||||||
@@ -49,6 +47,7 @@ class SelectFormView extends StatelessWidget {
|
|||||||
bottomSheet() {
|
bottomSheet() {
|
||||||
showModalBottomSheet<void>(
|
showModalBottomSheet<void>(
|
||||||
context: context,
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: _borderRadius,
|
topLeft: _borderRadius,
|
||||||
@@ -56,48 +55,74 @@ class SelectFormView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
ItemSelectForm? selectedForm;
|
|
||||||
String? selectedKey;
|
|
||||||
if (listItem.isNotEmpty) {
|
|
||||||
var res = listItem.where((element) => element.key == selectedKey);
|
|
||||||
if (res.isNotEmpty) {
|
|
||||||
selectedForm = res.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return StatefulBuilder(builder: (
|
return StatefulBuilder(builder: (
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
StateSetter stateSetter,
|
StateSetter stateSetter,
|
||||||
) {
|
) {
|
||||||
return Container(
|
return Container(
|
||||||
height: SizeConfig.height * .45,
|
height: SizeConfig.height * .45,
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
bottomSheetTitle ?? Container(),
|
Row(
|
||||||
// const SizedBox(height: 16),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
name,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
ctrl?.clear();
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 26,
|
||||||
|
color: ColorPalette.greyBase,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
...listItem.map(
|
...listItem.map((e) {
|
||||||
(e) => Card(
|
bool selected = e.text == ctrl?.text;
|
||||||
|
return Card(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
color: Colors.transparent,
|
color: Colors.white,
|
||||||
shape: const RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
side: BorderSide(
|
side: BorderSide(
|
||||||
color: ColorPalette.greyBorder,
|
color: selected
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.greyBorder,
|
||||||
),
|
),
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.all(Radius.circular(12)),
|
const BorderRadius.all(Radius.circular(12)),
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
e.text,
|
e.text,
|
||||||
style: const TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 16,
|
||||||
),
|
fontWeight: FontWeight.w500,
|
||||||
|
color: selected
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate500),
|
||||||
),
|
),
|
||||||
subtitle: e.description != null
|
subtitle: e.description != null
|
||||||
? Text(
|
? Text(
|
||||||
@@ -106,37 +131,19 @@ class SelectFormView extends StatelessWidget {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
// trailing: const Icon(
|
trailing: selected
|
||||||
// Icons.check_circle,
|
? const Icon(Icons.check_circle_rounded,
|
||||||
// color: ColorPalette.primary,
|
color: ColorPalette.primary)
|
||||||
// ),
|
: null,
|
||||||
trailing: Radio(
|
|
||||||
focusColor: ColorPalette.primary,
|
|
||||||
activeColor: ColorPalette.primary,
|
|
||||||
visualDensity: const VisualDensity(
|
|
||||||
horizontal: VisualDensity.minimumDensity,
|
|
||||||
vertical: VisualDensity.minimumDensity,
|
|
||||||
),
|
|
||||||
materialTapTargetSize:
|
|
||||||
MaterialTapTargetSize.shrinkWrap,
|
|
||||||
value: e.key,
|
|
||||||
groupValue: selectedKey,
|
|
||||||
onChanged: (value) {
|
|
||||||
// selectedForm =
|
|
||||||
// ItemSelectForm(e.key, e.text);
|
|
||||||
// stateSetter(() {
|
|
||||||
// selectedKey = selectedForm!.key;
|
|
||||||
// });
|
|
||||||
},
|
|
||||||
),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
stateSetter(() {
|
||||||
ctrl?.text = e.text;
|
ctrl?.text = e.text;
|
||||||
onSelect(e.key);
|
onSelect(e.text);
|
||||||
Navigator.of(context).pop();
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -145,7 +152,9 @@ class SelectFormView extends StatelessWidget {
|
|||||||
name: 'Select',
|
name: 'Select',
|
||||||
marginVertical: 4.0,
|
marginVertical: 4.0,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// print('object $')
|
if (ctrl!.text.isNotEmpty) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
135
lib/application/component/set_pin_view/set_pin_view.dart
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/set_pin_view/set_pin_viewmodel.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/registration_success_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pinput/pinput.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class SetPinView extends StatelessWidget {
|
||||||
|
final String currentPin;
|
||||||
|
final void Function(BuildContext context, String pin) submitPin;
|
||||||
|
|
||||||
|
const SetPinView({
|
||||||
|
Key? key,
|
||||||
|
required this.currentPin,
|
||||||
|
required this.submitPin,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
Widget _stepItem({bool isCurrentStep = false, bool isDone = false}) {
|
||||||
|
return Container(
|
||||||
|
margin:
|
||||||
|
const EdgeInsets.only(right: 4.0, left: 4.0, top: 16.0, bottom: 40.0),
|
||||||
|
height: 6,
|
||||||
|
width: SizeConfig.width * .08,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isCurrentStep || isDone
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.greyBorderNeutrals,
|
||||||
|
borderRadius: BorderRadius.circular(50),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final textTheme = Theme.of(context).textTheme;
|
||||||
|
final pinInputController = TextEditingController();
|
||||||
|
const pinInputLength = 6;
|
||||||
|
const defaultPinTheme = PinTheme(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 4.0, vertical: 16.0),
|
||||||
|
textStyle: TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final pInputFocusNode = FocusNode();
|
||||||
|
|
||||||
|
final focusedPinTheme = defaultPinTheme.copyWith(
|
||||||
|
decoration: defaultPinTheme.decoration?.copyWith(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final submittedPinTheme = defaultPinTheme.copyWith(
|
||||||
|
decoration: defaultPinTheme.decoration?.copyWith(),
|
||||||
|
);
|
||||||
|
final followingPinTheme = defaultPinTheme.copyWith(
|
||||||
|
width: 13,
|
||||||
|
height: 13,
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Color.fromRGBO(30, 60, 87, 1),
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
decoration: defaultPinTheme.decoration?.copyWith(
|
||||||
|
color: ColorPalette.white,
|
||||||
|
border: Border.all(color: ColorPalette.slate300),
|
||||||
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => SetPinViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: CustomAppBar(
|
||||||
|
height: SizeConfig.height * .1, title: 'Registration'),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Consumer<SetPinViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: List.generate(
|
||||||
|
9,
|
||||||
|
(index) => _stepItem(isCurrentStep: true, isDone: true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.iconLock,
|
||||||
|
width: SizeConfig.width * .15,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
!provider.isPinCompleted
|
||||||
|
? 'Set your PIN'
|
||||||
|
: 'Confirm your PIN',
|
||||||
|
style: textTheme.headlineLarge,
|
||||||
|
),
|
||||||
|
Pinput(
|
||||||
|
onCompleted: (pin) {
|
||||||
|
if (!provider.isPinCompleted) {
|
||||||
|
provider.changePin();
|
||||||
|
pinInputController.clear();
|
||||||
|
} else {
|
||||||
|
routePush(context,
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
page: const RegistrationSuccessView());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
obscureText: true,
|
||||||
|
autofocus: true,
|
||||||
|
isCursorAnimationEnabled: false,
|
||||||
|
length: pinInputLength,
|
||||||
|
controller: pinInputController,
|
||||||
|
defaultPinTheme: defaultPinTheme,
|
||||||
|
focusNode: pInputFocusNode,
|
||||||
|
focusedPinTheme: focusedPinTheme,
|
||||||
|
submittedPinTheme: submittedPinTheme,
|
||||||
|
followingPinTheme: followingPinTheme,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SetPinViewModel extends ChangeNotifier {
|
||||||
|
bool isPinCompleted = false;
|
||||||
|
void changePin() {
|
||||||
|
isPinCompleted = !isPinCompleted;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,8 +36,8 @@ class GoalInvestingView extends StatelessWidget {
|
|||||||
routePush(
|
routePush(
|
||||||
context,
|
context,
|
||||||
page: OtherPlanView(
|
page: OtherPlanView(
|
||||||
selectedPlan: (value) {
|
selectedPlan: (val) {
|
||||||
onListSelected(e.value.title);
|
onListSelected(val);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -6,9 +8,13 @@ import 'package:cims_apps/core/utils/size_config.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InputInvestmentView extends StatefulWidget {
|
class InputInvestmentView extends StatefulWidget {
|
||||||
final String selectedPlan;
|
final String? currentPlan;
|
||||||
|
final void Function()? changePlan;
|
||||||
|
final int? currentPrice;
|
||||||
|
final int? minimumPrice;
|
||||||
|
final int? maximumPrice;
|
||||||
final void Function(String value) nextMove;
|
final void Function(String value) nextMove;
|
||||||
const InputInvestmentView({super.key, required this.selectedPlan, required this.nextMove});
|
const InputInvestmentView({super.key, required this.nextMove, this.currentPlan, this.minimumPrice, this.maximumPrice, this.currentPrice, this.changePlan});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<InputInvestmentView> createState() => _InputInvestmentViewState();
|
State<InputInvestmentView> createState() => _InputInvestmentViewState();
|
||||||
@@ -17,10 +23,35 @@ class InputInvestmentView extends StatefulWidget {
|
|||||||
class _InputInvestmentViewState extends State<InputInvestmentView> {
|
class _InputInvestmentViewState extends State<InputInvestmentView> {
|
||||||
TextEditingController inputController = TextEditingController();
|
TextEditingController inputController = TextEditingController();
|
||||||
|
|
||||||
|
void validationInputValue(String currentValue) {
|
||||||
|
currentValue = currentValue.replaceAll('Rp ', '').replaceAll('.', '');
|
||||||
|
if(currentValue.isEmpty){
|
||||||
|
currentValue = '0';
|
||||||
|
}
|
||||||
|
double parseValue = double.parse(currentValue);
|
||||||
|
if(widget.minimumPrice != null){
|
||||||
|
if(parseValue <= widget.minimumPrice!){
|
||||||
|
parseValue = widget.minimumPrice!.toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(widget.maximumPrice != null){
|
||||||
|
if(parseValue >= widget.maximumPrice!){
|
||||||
|
parseValue = widget.maximumPrice!.toDouble();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
// TODO: implement initState
|
// TODO: implement initState
|
||||||
|
if(widget.currentPrice != null){
|
||||||
|
inputController.text = NumberFormatter.numberCurrency(widget.currentPrice, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}else{
|
||||||
inputController.text = 'Rp 0';
|
inputController.text = 'Rp 0';
|
||||||
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,23 +72,25 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 16),
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
if(widget.currentPlan != null)
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(widget.selectedPlan,
|
Text(widget.currentPlan ?? '',
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
onTap: widget.changePlan,
|
||||||
|
child: const Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
||||||
SizedBox(width: 4),
|
SizedBox(width: 4),
|
||||||
@@ -69,28 +102,23 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
controller: inputController,
|
controller: inputController,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 28,
|
fontSize: 28,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
value = value.replaceAll('Rp ', '').replaceAll('.', '');
|
validationInputValue(value);
|
||||||
double parseValue = double.parse(value);
|
|
||||||
if(value.isNotEmpty){
|
|
||||||
inputController.text = NumberFormatter.numberCurrency(parseValue, 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
}else{
|
|
||||||
inputController.text = NumberFormatter.numberCurrency(0, 'Rp ', 'id_ID', decimalDigits: 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
enabledBorder: UnderlineInputBorder(
|
enabledBorder: UnderlineInputBorder(
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
@@ -99,30 +127,36 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Text('Minimum Budget Rp1,000,000',
|
if(widget.minimumPrice != null)
|
||||||
style: TextStyle(
|
Text('Minimum ${NumberFormatter.numberCurrency(widget.minimumPrice, 'Rp ', 'id_ID')}',
|
||||||
|
style: const TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
if(widget.maximumPrice != null)
|
||||||
|
Text('Maximum ${NumberFormatter.numberCurrency(widget.maximumPrice, 'Rp ', 'id_ID')}',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
NumericPad(onNumberSelected: (p0) {
|
NumericPad(onNumberSelected: (p0) {
|
||||||
String checkIsZeroInput = inputController.text.replaceAll('Rp ', '').replaceAll(',', '');
|
String currentValue = inputController.text;
|
||||||
String getNumeric = p0;
|
|
||||||
if(p0.isNotEmpty){
|
if(p0.isNotEmpty){
|
||||||
if(checkIsZeroInput != '0'){
|
if(currentValue != '0'){
|
||||||
getNumeric = checkIsZeroInput + getNumeric;
|
currentValue = currentValue + p0;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
getNumeric = checkIsZeroInput.substring(0, checkIsZeroInput.length - 1);
|
currentValue = currentValue.substring(0, currentValue.length - 1);
|
||||||
}
|
}
|
||||||
String formatNumeric = NumberFormatter.numberCurrency(
|
validationInputValue(currentValue);
|
||||||
double.parse(getNumeric), 'Rp ', 'id_ID', decimalDigits: 0).replaceAll('.', ',');
|
|
||||||
inputController.text = formatNumeric;
|
|
||||||
}),
|
}),
|
||||||
SizedBox(height: 8),
|
const SizedBox(height: 24),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -130,7 +164,7 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
},
|
},
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
contentPadding: EdgeInsets.symmetric(vertical: 16),
|
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -138,6 +172,6 @@ class _InputInvestmentViewState extends State<InputInvestmentView> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
@@ -72,6 +74,8 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
|||||||
disabled: !(selectedPlan.img != ''),
|
disabled: !(selectedPlan.img != ''),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
print('haloo');
|
||||||
|
print(selectedPlan.name);
|
||||||
widget.selectedPlan(selectedPlan.name);
|
widget.selectedPlan(selectedPlan.name);
|
||||||
},
|
},
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
@@ -91,6 +95,7 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
|||||||
if(plan.name == 'Create Plan'){
|
if(plan.name == 'Create Plan'){
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
|
isDismissible: false,
|
||||||
builder: (context) => modalCreatePlan(),
|
builder: (context) => modalCreatePlan(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -150,6 +155,9 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
setState(() {
|
||||||
|
selectedPlan = Plan('', '');
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: Icon(Icons.close_rounded),
|
child: Icon(Icons.close_rounded),
|
||||||
)
|
)
|
||||||
@@ -161,12 +169,12 @@ class _OtherPlanViewState extends State<OtherPlanView> {
|
|||||||
),
|
),
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Select',
|
name: 'Next',
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
disabled: !(createController.text != ''),
|
disabled: !(createController.text != ''),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context)..pop()..pop();
|
Navigator.of(context)..pop()..pop();
|
||||||
widget.selectedPlan(selectedPlan.name);
|
widget.selectedPlan(createController.text);
|
||||||
},
|
},
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/radio_agreement.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
@@ -6,29 +7,25 @@ import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view
|
|||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TotalPaymentView extends StatefulWidget {
|
class TotalPaymentView extends StatelessWidget {
|
||||||
final int totalInvest;
|
final int totalInvest;
|
||||||
final List<Product> listProduct;
|
final List<Product> listProduct;
|
||||||
|
final bool isAgree;
|
||||||
|
final void Function() onTapAgree;
|
||||||
const TotalPaymentView({
|
const TotalPaymentView({
|
||||||
super.key,
|
super.key,
|
||||||
required this.listProduct,
|
required this.listProduct,
|
||||||
required this.totalInvest,
|
required this.totalInvest,
|
||||||
|
required this.isAgree,
|
||||||
|
required this.onTapAgree,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
State<TotalPaymentView> createState() => _TotalPaymentViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TotalPaymentViewState extends State<TotalPaymentView> {
|
|
||||||
bool isAgreement = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return SingleChildScrollView(
|
||||||
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white, borderRadius: BorderRadius.circular(16)),
|
||||||
borderRadius: BorderRadius.circular(16)
|
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -37,56 +34,54 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text('Your Investment Today',
|
const Text(
|
||||||
|
'Your Investment Today',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16
|
fontSize: 16),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => Navigator.pop(context),
|
onTap: () => Navigator.pop(context),
|
||||||
child: const Icon(Icons.close_rounded)
|
child: const Icon(Icons.close_rounded))
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...widget.listProduct.asMap().entries.map((e) {
|
...listProduct.asMap().entries.map((e) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(left: 16, right: 24, bottom: 16, top: 16),
|
padding: const EdgeInsets.only(
|
||||||
|
left: 16, right: 24, bottom: 16, top: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border(
|
border: Border(
|
||||||
left: BorderSide(
|
left: BorderSide(
|
||||||
width: 8,
|
width: 8,
|
||||||
color: ColorPalette.investTypeColor[e.value.type]!
|
color:
|
||||||
)
|
ColorPalette.investTypeColor[e.value.type]!))),
|
||||||
)
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 5,
|
flex: 5,
|
||||||
child: Text(e.value.name ?? '',
|
child: Text(
|
||||||
|
e.value.name ?? '',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16
|
fontSize: 16),
|
||||||
),
|
)),
|
||||||
)
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 7,
|
flex: 7,
|
||||||
child: Text(
|
child: Text(
|
||||||
NumberFormatter.numberCurrency(widget.totalInvest * e.value.totalPercent!, 'Rp ', 'id_ID'),
|
NumberFormatter.numberCurrency(
|
||||||
|
totalInvest * e.value.totalPercent!,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800),
|
||||||
),
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -97,158 +92,164 @@ class _TotalPaymentViewState extends State<TotalPaymentView> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text('Purchase Commission',
|
Text(
|
||||||
|
'Purchase Commission',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16
|
fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
Text('Free',
|
'Free',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w700
|
fontWeight: FontWeight.w700),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16,),
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
color: ColorPalette.slate200.withOpacity(0.5),
|
color: ColorPalette.slate200.withOpacity(0.5),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text('Total',
|
const Text(
|
||||||
|
'Total',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16
|
fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'),
|
NumberFormatter.numberCurrency(
|
||||||
|
totalInvest, 'Rp ', 'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
buttonAgreement(),
|
RadioAgreement(
|
||||||
|
isAgree: isAgree,
|
||||||
|
desc: 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
|
||||||
|
onTap: () {
|
||||||
|
onTapAgree();
|
||||||
|
},
|
||||||
|
),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const Text('Total Payment',
|
const Text(
|
||||||
|
'Total Payment',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 16
|
fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'),
|
NumberFormatter.numberCurrency(
|
||||||
|
totalInvest, 'Rp ', 'id_ID'),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
disabled: !isAgreement,
|
disabled: !isAgree,
|
||||||
name: 'Subscribe Now',
|
name: 'Subscribe Now',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context, page: PaymentMethodView(
|
routePush(context,
|
||||||
totalInvest: widget.totalInvest,
|
page: PaymentMethodView(
|
||||||
|
totalInvest: totalInvest,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
||||||
textColor: isAgreement ? Colors.white : ColorPalette.slate400,
|
textColor: isAgree ? Colors.white : ColorPalette.slate400,
|
||||||
textWeight: FontWeight.w700,
|
textWeight: FontWeight.w700,
|
||||||
textSize: 20,
|
textSize: 20,
|
||||||
backgroundColor: ColorPalette.primary,
|
backgroundColor: ColorPalette.primary,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buttonAgreement() {
|
|
||||||
bool isAgree = isAgreement;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
setState(() {
|
|
||||||
isAgreement = !isAgreement;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: AnimatedContainer(
|
|
||||||
margin: const EdgeInsets.only(top: 4),
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
height: 16,
|
|
||||||
width: 16,
|
|
||||||
padding: const EdgeInsets.all(1),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
|
||||||
color: isAgree ? ColorPalette.primary : ColorPalette.slate200
|
|
||||||
)
|
|
||||||
),
|
|
||||||
child: AnimatedContainer(
|
|
||||||
duration: const Duration(milliseconds: 200),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isAgree ? ColorPalette.primary : ColorPalette.white,
|
|
||||||
shape: BoxShape.circle
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12,),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text('I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: ColorPalette.slate400
|
|
||||||
),
|
|
||||||
),
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
|
|
||||||
},
|
|
||||||
child: const Text('Read More',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
color: ColorPalette.primary
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Widget buttonAgreement() {
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
// child: Row(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// GestureDetector(
|
||||||
|
// onTap: () {
|
||||||
|
// },
|
||||||
|
// child: AnimatedContainer(
|
||||||
|
// margin: const EdgeInsets.only(top: 4),
|
||||||
|
// duration: const Duration(milliseconds: 200),
|
||||||
|
// height: 16,
|
||||||
|
// width: 16,
|
||||||
|
// padding: const EdgeInsets.all(1),
|
||||||
|
// alignment: Alignment.center,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// shape: BoxShape.circle,
|
||||||
|
// border: Border.all(
|
||||||
|
// color: isAgree
|
||||||
|
// ? ColorPalette.primary
|
||||||
|
// : ColorPalette.slate200)),
|
||||||
|
// child: AnimatedContainer(
|
||||||
|
// duration: const Duration(milliseconds: 200),
|
||||||
|
// child: Container(
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color:
|
||||||
|
// isAgree ? ColorPalette.primary : ColorPalette.white,
|
||||||
|
// shape: BoxShape.circle),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(
|
||||||
|
// width: 12,
|
||||||
|
// ),
|
||||||
|
// Expanded(
|
||||||
|
// child: Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: [
|
||||||
|
// const Text(
|
||||||
|
// 'I agree to buy the mutual fund on this page and have read and agreed to all the contents of the Prospectus and summary information and understand the risks of my investment decision.',
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 16,
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// color: ColorPalette.slate400),
|
||||||
|
// ),
|
||||||
|
// GestureDetector(
|
||||||
|
// onTap: () {},
|
||||||
|
// child: const Text(
|
||||||
|
// 'Read More',
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontSize: 16,
|
||||||
|
// fontWeight: FontWeight.w600,
|
||||||
|
// decoration: TextDecoration.underline,
|
||||||
|
// color: ColorPalette.primary),
|
||||||
|
// ))
|
||||||
|
// ],
|
||||||
|
// ))
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/take_picture_screen/take_picture_screen.dart';
|
import 'package:cims_apps/application/component/take_picture_screen/take_picture_screen.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -11,13 +12,35 @@ import 'package:cims_apps/features/auth/registration/view/submission_data/submis
|
|||||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
class DisplayPictureScreen extends StatelessWidget {
|
class DisplayPictureScreen extends StatefulWidget {
|
||||||
final String imagePath, content;
|
final String imagePath, content;
|
||||||
|
|
||||||
const DisplayPictureScreen(
|
const DisplayPictureScreen(
|
||||||
{super.key, required this.imagePath, required this.content});
|
{super.key, required this.imagePath, required this.content});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DisplayPictureScreen> createState() => _DisplayPictureScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DisplayPictureScreenState extends State<DisplayPictureScreen> {
|
||||||
|
Future<void> saveData() async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
if (widget.content == 'ktp') {
|
||||||
|
prefs.setString('imagePath', widget.imagePath);
|
||||||
|
} else {
|
||||||
|
prefs.setString('imagePathSelfie', widget.imagePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
saveData();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List listIcons = [
|
List listIcons = [
|
||||||
@@ -72,10 +95,8 @@ class DisplayPictureScreen extends StatelessWidget {
|
|||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: CustomAppBar(
|
||||||
title: const Text('Preview'),
|
height: SizeConfig.height * .08, title: 'Preview'),
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
),
|
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -85,7 +106,14 @@ class DisplayPictureScreen extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
height: SizeConfig.height * .4,
|
height: SizeConfig.height * .4,
|
||||||
child: Image.file(File(imagePath))),
|
child: Transform(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
transform: widget.content == 'selfie'
|
||||||
|
? Matrix4.rotationY(math.pi)
|
||||||
|
: Matrix4.rotationY(0),
|
||||||
|
child: Image.file(
|
||||||
|
File(widget.imagePath),
|
||||||
|
))),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 16.0),
|
padding: EdgeInsets.symmetric(vertical: 16.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -103,7 +131,8 @@ class DisplayPictureScreen extends StatelessWidget {
|
|||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
children: List.generate(4, (index) {
|
children: List.generate(4, (index) {
|
||||||
List filteredList = listIcons
|
List filteredList = listIcons
|
||||||
.where((element) => element['key'] == content)
|
.where(
|
||||||
|
(element) => element['key'] == widget.content)
|
||||||
.toList();
|
.toList();
|
||||||
final urlImg = filteredList[index]['urlImg'];
|
final urlImg = filteredList[index]['urlImg'];
|
||||||
final tag = filteredList[index]['tag'];
|
final tag = filteredList[index]['tag'];
|
||||||
@@ -162,10 +191,10 @@ class DisplayPictureScreen extends StatelessWidget {
|
|||||||
provider.initCamera().then((cameras) {
|
provider.initCamera().then((cameras) {
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: TakePictureScreen(
|
page: TakePictureScreen(
|
||||||
camera: content == 'ktp'
|
camera: widget.content == 'ktp'
|
||||||
? cameras[0]
|
? cameras[0]
|
||||||
: cameras[1],
|
: cameras[1],
|
||||||
takeContent: content,
|
takeContent: widget.content,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart';
|
import 'package:cims_apps/application/component/take_picture_screen/display_picture_screen.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
@@ -27,7 +28,6 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
late String _takeContent;
|
late String _takeContent;
|
||||||
|
|
||||||
Future<void> changeFlash() async {
|
Future<void> changeFlash() async {
|
||||||
await _controller.setFlashMode(FlashMode.auto);
|
|
||||||
setState(() {
|
setState(() {
|
||||||
isFlash = !isFlash;
|
isFlash = !isFlash;
|
||||||
});
|
});
|
||||||
@@ -44,6 +44,7 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
// Next, initialize the controller. This returns a Future.
|
// Next, initialize the controller. This returns a Future.
|
||||||
_initializeControllerFuture = _controller.initialize();
|
_initializeControllerFuture = _controller.initialize();
|
||||||
_takeContent = widget.takeContent;
|
_takeContent = widget.takeContent;
|
||||||
|
_controller.setFlashMode(isFlash ? FlashMode.torch : FlashMode.off);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -57,9 +58,10 @@ class TakePictureScreenState extends State<TakePictureScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Fill this out in the next steps.
|
// Fill this out in the next steps.
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: CustomAppBar(
|
||||||
title: const Text('Registration'),
|
title: 'Registration',
|
||||||
actions: [
|
height: SizeConfig.height * .08,
|
||||||
|
trailing: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
changeFlash();
|
changeFlash();
|
||||||
|
|||||||
@@ -139,9 +139,9 @@ class TextFormView extends StatelessWidget {
|
|||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
onEditingComplete: onSubmit,
|
onEditingComplete: onSubmit,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: fontColorDisabled ?? Colors.black,
|
color: fontColorDisabled ?? ColorPalette.slate800,
|
||||||
),
|
),
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
@@ -163,7 +163,7 @@ class TextFormView extends StatelessWidget {
|
|||||||
hintStyle: hintTextStyle ??
|
hintStyle: hintTextStyle ??
|
||||||
const TextStyle(
|
const TextStyle(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: ColorPalette.greyFont,
|
color: ColorPalette.slate400,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
),
|
),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ class ColorPalette {
|
|||||||
static const Color green100 = Color(0xFFDCFCE7);
|
static const Color green100 = Color(0xFFDCFCE7);
|
||||||
static const Color green400 = Color(0xFF4ADE80);
|
static const Color green400 = Color(0xFF4ADE80);
|
||||||
static const Color green500 = Color(0xFF16A34A);
|
static const Color green500 = Color(0xFF16A34A);
|
||||||
|
static const Color red600 = Color(0xffDC2626);
|
||||||
|
|
||||||
static const Map<String, Color> investTypeColor = {
|
static const Map<String, Color> investTypeColor = {
|
||||||
'Money Market': purple500,
|
'Money Market': purple500,
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class StringUtils {
|
class StringUtils {
|
||||||
static bool emailValidation(String email) {
|
static bool emailValidation(String email) {
|
||||||
return RegExp(
|
return RegExp(
|
||||||
@@ -13,4 +18,24 @@ class StringUtils {
|
|||||||
return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})')
|
return RegExp(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*?[\W_])(?=.{8,})')
|
||||||
.hasMatch(password);
|
.hasMatch(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String formatTime(DateTime? dateTime) {
|
||||||
|
if (dateTime != null) {
|
||||||
|
DateFormat formatter = DateFormat('HH:mm:ss');
|
||||||
|
return formatter.format(dateTime);
|
||||||
|
}
|
||||||
|
return '--:--:--';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iCopyToClipboard(BuildContext context,
|
||||||
|
{String? desc, required String text}) {
|
||||||
|
Clipboard.setData(ClipboardData(text: text));
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
.showSnackBar(SnackBar(
|
||||||
|
backgroundColor: ColorPalette.primary,
|
||||||
|
content: Text(desc ?? "Text copied to clipboard"),
|
||||||
|
))
|
||||||
|
.closed
|
||||||
|
.then((value) => ScaffoldMessenger.of(context).removeCurrentSnackBar());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,12 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
|
||||||
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/login/view/password_view.dart';
|
import 'package:cims_apps/features/auth/login/view/password_view.dart';
|
||||||
import 'package:cims_apps/features/auth/login/view/phone_number_view.dart';
|
import 'package:cims_apps/features/auth/login/view/phone_number_view.dart';
|
||||||
import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart';
|
import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view.dart';
|
|
||||||
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class LoginView extends StatefulWidget {
|
class LoginView extends StatefulWidget {
|
||||||
@@ -90,7 +83,11 @@ class _LoginViewState extends State<LoginView> {
|
|||||||
currentPage++;
|
currentPage++;
|
||||||
pageController.jumpToPage(1);
|
pageController.jumpToPage(1);
|
||||||
} else {
|
} else {
|
||||||
routePush(context, page: BottomNavigationView());
|
routePush(
|
||||||
|
context,
|
||||||
|
page: const BottomNavigationView(),
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,16 +10,19 @@ import 'package:provider/provider.dart';
|
|||||||
class PasswordView extends StatelessWidget {
|
class PasswordView extends StatelessWidget {
|
||||||
final void Function() nextStep;
|
final void Function() nextStep;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
const PasswordView({super.key, required this.nextStep, required this.controller});
|
const PasswordView(
|
||||||
|
{super.key, required this.nextStep, required this.controller});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<LoginViewModel>(
|
return Consumer<LoginViewModel>(builder: (context, provider, child) {
|
||||||
builder: (context, provider, child) {
|
|
||||||
return Container(
|
return Container(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
height: SizeConfig.height,
|
height: SizeConfig.height,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Form(
|
||||||
|
key: provider.formKey,
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -32,6 +35,15 @@ class PasswordView extends StatelessWidget {
|
|||||||
ctrl: controller,
|
ctrl: controller,
|
||||||
obscureText: !provider.showPassword,
|
obscureText: !provider.showPassword,
|
||||||
contentPadding: EdgeInsets.all(12),
|
contentPadding: EdgeInsets.all(12),
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Password must filled';
|
||||||
|
} else if (value.length < 8) {
|
||||||
|
return 'Minimum password 8 Character';
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
suffixIcon: GestureDetector(
|
suffixIcon: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
provider.changeShowPassword();
|
provider.changeShowPassword();
|
||||||
@@ -45,19 +57,14 @@ class PasswordView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(padding: EdgeInsets.all(0)),
|
||||||
padding: EdgeInsets.all(0)
|
onPressed: () {},
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
|
|
||||||
},
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'Forget the password?',
|
'Forget the password?',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
),
|
),
|
||||||
)
|
)),
|
||||||
),
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
@@ -67,13 +74,19 @@ class PasswordView extends StatelessWidget {
|
|||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
textSize: 18,
|
textSize: 18,
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
contentPadding:
|
||||||
onPressed: nextStep,
|
EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
onPressed: () {
|
||||||
|
if (provider.formKey.currentState!.validate()) {
|
||||||
|
nextStep();
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,42 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class PhoneNumberView extends StatelessWidget {
|
class PhoneNumberView extends StatelessWidget {
|
||||||
final void Function() nextStep;
|
final void Function() nextStep;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
const PhoneNumberView({super.key, required this.nextStep, required this.controller});
|
const PhoneNumberView(
|
||||||
|
{super.key, required this.nextStep, required this.controller});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => LoginViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
return Container(
|
return Container(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
height: SizeConfig.height,
|
height: SizeConfig.height,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
|
child:
|
||||||
|
Consumer<LoginViewModel>(builder: (context, provider, child) {
|
||||||
|
return Form(
|
||||||
|
key: provider.formKey,
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TextTitle(title: 'Enter your phone number', fontSize: 24),
|
const TextTitle(
|
||||||
|
title: 'Enter your phone number', fontSize: 24),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
@@ -82,8 +93,13 @@ class PhoneNumberView extends StatelessWidget {
|
|||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
onPressed: nextStep,
|
horizontal: 16, vertical: 12),
|
||||||
|
onPressed: () {
|
||||||
|
if (provider.formKey.currentState!.validate()) {
|
||||||
|
nextStep();
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@@ -99,20 +115,21 @@ class PhoneNumberView extends StatelessWidget {
|
|||||||
routePush(context, page: RegistrationView());
|
routePush(context, page: RegistrationView());
|
||||||
},
|
},
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
padding: EdgeInsets.all(0)
|
padding: EdgeInsets.all(0)),
|
||||||
),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'Sign Up',
|
'Sign Up',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorPalette.primary
|
color: ColorPalette.primary),
|
||||||
),
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class LoginViewModel extends ChangeNotifier {
|
class LoginViewModel extends ChangeNotifier {
|
||||||
bool showPassword = false;
|
bool showPassword = false;
|
||||||
|
var formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
void changeShowPassword() {
|
void changeShowPassword() {
|
||||||
showPassword = !showPassword;
|
showPassword = !showPassword;
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InitialRegistrationStep extends StatelessWidget {
|
class InitialRegistrationStep extends StatelessWidget {
|
||||||
@@ -92,12 +94,12 @@ class InitialRegistrationStep extends StatelessWidget {
|
|||||||
{
|
{
|
||||||
'desc': 'Personal Data',
|
'desc': 'Personal Data',
|
||||||
'isActive': true,
|
'isActive': true,
|
||||||
'isDone': true,
|
'isDone': false,
|
||||||
'isLast': false,
|
'isLast': false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'desc': 'Email',
|
'desc': 'Email',
|
||||||
'isActive': true,
|
'isActive': false,
|
||||||
'isDone': false,
|
'isDone': false,
|
||||||
'isLast': false,
|
'isLast': false,
|
||||||
},
|
},
|
||||||
@@ -146,9 +148,8 @@ class InitialRegistrationStep extends StatelessWidget {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar:
|
||||||
title: const Text('Registration'),
|
CustomAppBar(height: SizeConfig.height * .1, title: 'Registration'),
|
||||||
),
|
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -175,7 +176,7 @@ class InitialRegistrationStep extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: SizeConfig.height * .6,
|
height: SizeConfig.height * .55,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -192,12 +193,29 @@ class InitialRegistrationStep extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ButtonView(
|
||||||
|
name: 'Home Page',
|
||||||
|
marginVertical: 8.0,
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
isOutlined: true,
|
||||||
|
onPressed: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const BottomNavigationView(),
|
||||||
|
routeType: RouteType.pushReplace);
|
||||||
|
},
|
||||||
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Let’s Start',
|
name: 'Let’s Start',
|
||||||
marginVertical: 8.0,
|
marginVertical: 8.0,
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context, page: const SubmissionParent());
|
routePush(context, page: const SubmissionParent());
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/viewmodel/registration_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/registration_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -20,9 +21,8 @@ class RegistrationPasswordView extends StatelessWidget {
|
|||||||
create: (context) => RegistrationViewModel(),
|
create: (context) => RegistrationViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar:
|
||||||
title: const Text('Sign Up'),
|
CustomAppBar(height: SizeConfig.height * .1, title: 'Sign Up'),
|
||||||
),
|
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Consumer<RegistrationViewModel>(
|
child: Consumer<RegistrationViewModel>(
|
||||||
@@ -45,6 +45,8 @@ class RegistrationPasswordView extends StatelessWidget {
|
|||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value!.isEmpty) {
|
if (value!.isEmpty) {
|
||||||
return 'Password must filled';
|
return 'Password must filled';
|
||||||
|
} else if (value.length < 8) {
|
||||||
|
return 'Minimum password 8 Character';
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -139,7 +141,7 @@ class DialogSuccess extends StatelessWidget {
|
|||||||
marginVertical: 8.0,
|
marginVertical: 8.0,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: const SubmissionParent(),
|
page: const InitialRegistrationStep(),
|
||||||
routeType: RouteType.pushReplace);
|
routeType: RouteType.pushReplace);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class RegistrationSuccessView extends StatelessWidget {
|
||||||
|
const RegistrationSuccessView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Container(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgFinish),
|
||||||
|
const TextCaption(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
textAlignSubtitle: TextAlign.center,
|
||||||
|
title: 'Registration Successful!',
|
||||||
|
subtitle:
|
||||||
|
'Please wait for the data verification process so that you can start investing.',
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
marginVertical: 0.0,
|
||||||
|
onPressed: () {
|
||||||
|
routePush(
|
||||||
|
context,
|
||||||
|
page: const BottomNavigationView(),
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/otp/otp_view.dart';
|
import 'package:cims_apps/application/component/otp/otp_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
@@ -24,11 +25,17 @@ class RegistrationView extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
enableDrag: false,
|
enableDrag: false,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
|
var flutterView = View.of(context);
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: MediaQueryData.fromView(
|
top: MediaQueryData.fromView(
|
||||||
WidgetsBinding.instance.window,
|
flutterView,
|
||||||
).padding.top,
|
).padding.top,
|
||||||
),
|
),
|
||||||
child: const OtpView(
|
child: const OtpView(
|
||||||
@@ -46,10 +53,9 @@ class RegistrationView extends StatelessWidget {
|
|||||||
create: (context) => RegistrationViewModel(),
|
create: (context) => RegistrationViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar:
|
||||||
title: const Text('Sign Up'),
|
CustomAppBar(height: SizeConfig.height * .1, title: 'Sign Up'),
|
||||||
),
|
body: SingleChildScrollView(
|
||||||
body: Container(
|
|
||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
child: Consumer<RegistrationViewModel>(
|
child: Consumer<RegistrationViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
@@ -68,6 +74,7 @@ class RegistrationView extends StatelessWidget {
|
|||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
FilteringTextInputFormatter.deny(RegExp(r'^0'))
|
FilteringTextInputFormatter.deny(RegExp(r'^0'))
|
||||||
],
|
],
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
prefixIcon: Container(
|
prefixIcon: Container(
|
||||||
width: SizeConfig.width * .23,
|
width: SizeConfig.width * .23,
|
||||||
padding:
|
padding:
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/list_tile/list_tile_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ModelDataBank {
|
||||||
|
final String? title, subtitle;
|
||||||
|
ModelDataBank(this.title, this.subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfirmBankAccount extends StatelessWidget {
|
||||||
|
const ConfirmBankAccount({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final listDataBank =
|
||||||
|
ModalRoute.of(context)!.settings.arguments as List<ModelDataBank>;
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: 70,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
surfaceTintColor: Colors.white,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BackButtonView(),
|
||||||
|
const Text('Registration'),
|
||||||
|
SizedBox(
|
||||||
|
width: SizeConfig.width * 0.1,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
side: BorderSide(color: ColorPalette.slate200)),
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: SizedBox(
|
||||||
|
height: SizeConfig.height * .85,
|
||||||
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextCaption(title: 'Bank account confirmation'),
|
||||||
|
SizedBox(
|
||||||
|
height: SizeConfig.height * .6,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...listDataBank.map((e) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
e.title!,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
e.subtitle!,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
const ListTileView(
|
||||||
|
title:
|
||||||
|
'Make sure your data is correct as it will affect the disbursement process',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ButtonView(
|
||||||
|
name: 'Recheck',
|
||||||
|
isOutlined: true,
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Confirm',
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubmissionParent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ListBankView extends StatelessWidget {
|
||||||
|
final ValueChanged<String> onSelect;
|
||||||
|
const ListBankView({Key? key, required this.onSelect}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var textTheme = Theme.of(context).textTheme;
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: CustomAppBar(
|
||||||
|
height: SizeConfig.height * .1, title: 'Select Bank'),
|
||||||
|
body: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgGuideBank,
|
||||||
|
width: SizeConfig.width * .35,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Make sure the bank you choose is a bank account in your own name ',
|
||||||
|
style: textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
TextFormView(
|
||||||
|
name: '',
|
||||||
|
hintText: 'Search bank',
|
||||||
|
ctrl: provider.ctrlBankNameSearch,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(vertical: 0),
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.search,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: provider.listBank.asMap().entries.map((e) {
|
||||||
|
bool selectedBank =
|
||||||
|
e.key.toString() == provider.idx;
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: selectedBank
|
||||||
|
? ColorPalette.blue50
|
||||||
|
: Colors.white,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(
|
||||||
|
e.value.text,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: selectedBank
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
provider.changeBank(e.key.toString());
|
||||||
|
provider.selectBank(e.value.text);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Select',
|
||||||
|
marginVertical: 8.0,
|
||||||
|
onPressed: () {
|
||||||
|
onSelect(provider.valueBank);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,56 +1,164 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/guide_screen.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/guide_screen.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/list_bank_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import 'confirm_bank_account.dart';
|
||||||
|
|
||||||
class SubmitBankAccount extends StatelessWidget {
|
class SubmitBankAccount extends StatelessWidget {
|
||||||
const SubmitBankAccount({Key? key}) : super(key: key);
|
const SubmitBankAccount({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<ItemSelectForm> listForm = [
|
showSearchBank(TextEditingController valueCtrl) {
|
||||||
ItemSelectForm('key1', 'BCA'),
|
showModalBottomSheet(
|
||||||
ItemSelectForm('key2', 'BRI'),
|
context: context,
|
||||||
ItemSelectForm('key3', 'BNI'),
|
isScrollControlled: true,
|
||||||
ItemSelectForm('key4', 'BANK MANDIRI'),
|
enableDrag: false,
|
||||||
ItemSelectForm('key5', 'CIMB NIAGA'),
|
shape: const RoundedRectangleBorder(
|
||||||
];
|
borderRadius: BorderRadius.vertical(
|
||||||
return SingleChildScrollView(
|
top: Radius.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
var flutterView = View.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: MediaQueryData.fromView(
|
||||||
|
flutterView,
|
||||||
|
).padding.top,
|
||||||
|
),
|
||||||
|
child: ListBankView(
|
||||||
|
onSelect: (value) {
|
||||||
|
setState(() {
|
||||||
|
valueCtrl.text = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
builder: (context, child) {
|
||||||
|
return SizedBox(
|
||||||
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return SizedBox(
|
||||||
|
height: SizeConfig.height * .8,
|
||||||
|
child: Form(
|
||||||
|
key: provider.formKeySubmitDataBank,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const TextCaption(title: 'Input your bank account data'),
|
const TextCaption(title: 'Input your bank account data'),
|
||||||
SelectFormView(
|
TextFormView(
|
||||||
name: 'Bank Name',
|
name: 'Bank Name',
|
||||||
listItem: listForm,
|
hintText: 'Select bank',
|
||||||
onSelect: (value) {},
|
readOnly: true,
|
||||||
|
ctrl: provider.ctrlBankName,
|
||||||
|
onTap: () {
|
||||||
|
showSearchBank(provider.ctrlBankName);
|
||||||
|
},
|
||||||
|
suffixIcon: const Icon(
|
||||||
|
Icons.keyboard_arrow_down_outlined,
|
||||||
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
TextFormView(
|
TextFormView(
|
||||||
name: 'Account Number',
|
name: 'Account Number',
|
||||||
|
hintText: 'Input Account Number',
|
||||||
|
ctrl: provider.ctrlNoAccountBank,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
trailingTitleWidget: SizedBox(
|
trailingTitleWidget: SizedBox(
|
||||||
width: 24,
|
width: 24,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
routePush(context, page: GuideScreen());
|
routePush(context, page: const GuideScreen());
|
||||||
},
|
},
|
||||||
child: const ImageView(image: PathAssets.iconQuestion),
|
child:
|
||||||
|
const ImageView(image: PathAssets.iconQuestion),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextFormView(name: 'Account Owner Name'),
|
TextFormView(
|
||||||
|
name: 'Account Owner Name',
|
||||||
|
hintText: 'Input Account Name',
|
||||||
|
ctrl: provider.ctrlNameAccountBank,
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
const Text(
|
const Text(
|
||||||
"Make sure the account you use is in your name, not someone else's",
|
"Make sure the account you use is in your name, not someone else's",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.slate400,
|
color: ColorPalette.slate400,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: SizeConfig.height * .08),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () {
|
||||||
|
if (provider.formKeySubmitDataBank.currentState!
|
||||||
|
.validate()) {
|
||||||
|
provider
|
||||||
|
.submitDataBank(
|
||||||
|
bankName: provider.ctrlBankName.text,
|
||||||
|
accountNumber: provider.ctrlNoAccountBank.text,
|
||||||
|
accountName: provider.ctrlNameAccountBank.text,
|
||||||
|
)
|
||||||
|
.then((values) {
|
||||||
|
provider.next(context).then((value) {
|
||||||
|
if (value) {
|
||||||
|
routePush(context,
|
||||||
|
page: const ConfirmBankAccount(),
|
||||||
|
arguments: values);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,8 +56,12 @@ class _QuestionViewState extends State<QuestionView> {
|
|||||||
bottomNavigationBar: SizedBox(
|
bottomNavigationBar: SizedBox(
|
||||||
height: 84,
|
height: 84,
|
||||||
child: ButtonView(
|
child: ButtonView(
|
||||||
|
disabled: provider.listScore[currentPage] == 0,
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
marginVertical: 16,
|
marginVertical: 16,
|
||||||
|
disabledBgColor: ColorPalette.slate200,
|
||||||
|
textColor: provider.listScore[currentPage] == 0 ? ColorPalette.slate500 : Colors.white,
|
||||||
|
backgroundColor: ColorPalette.primary,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (currentPage > 3) {
|
if (currentPage > 3) {
|
||||||
int totalScore = provider.listScore
|
int totalScore = provider.listScore
|
||||||
@@ -65,8 +69,11 @@ class _QuestionViewState extends State<QuestionView> {
|
|||||||
provider.setTypeResult(totalScore);
|
provider.setTypeResult(totalScore);
|
||||||
routePush(context,
|
routePush(context,
|
||||||
page: ResultsView(
|
page: ResultsView(
|
||||||
totalScore: totalScore.toString(),
|
totalScore: totalScore,
|
||||||
typeResult: provider.typeResult));
|
typeResult: provider.typeResult
|
||||||
|
),
|
||||||
|
routeType: RouteType.pushReplace
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
currentPage += 1;
|
currentPage += 1;
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
|
||||||
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/risk_profile.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/registration_password_view.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/question_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view_model/risk_profile_view_model.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/terms_and_condition/terms_and_condition_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class ResultsView extends StatelessWidget {
|
class ResultsView extends StatelessWidget {
|
||||||
final String totalScore;
|
final int totalScore;
|
||||||
final RiskProfileResult typeResult;
|
final RiskProfileResult typeResult;
|
||||||
const ResultsView({super.key, required this.typeResult, required this.totalScore});
|
const ResultsView(
|
||||||
|
{super.key, required this.typeResult, required this.totalScore});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -26,134 +27,27 @@ class ResultsView extends StatelessWidget {
|
|||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
BackButtonView(),
|
const BackButtonView(),
|
||||||
const Text('Risk Profile', textAlign: TextAlign.center),
|
const Text('Risk Profile', textAlign: TextAlign.center),
|
||||||
SizedBox(
|
SizedBox(width: SizeConfig.width * 0.1)
|
||||||
width: SizeConfig.width * 0.1
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
side: BorderSide(color: ColorPalette.slate200)
|
side: BorderSide(color: ColorPalette.slate200)),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
RiskProfile(totalScore: totalScore, rowSuitableProduct: false),
|
||||||
borderRadius: BorderRadius.circular(8),
|
const SizedBox(
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: typeResult.color,
|
|
||||||
image: DecorationImage(image: AssetImage(typeResult.img), alignment: Alignment.centerRight)
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(24),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
typeResult.type,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 24,
|
|
||||||
color: ColorPalette.white
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 16,),
|
|
||||||
Text('Total Score :',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 16,
|
|
||||||
color: ColorPalette.white
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(totalScore,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 28,
|
|
||||||
color: ColorPalette.white
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 24,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
typeResult.desc,
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate500,
|
|
||||||
fontSize: 16
|
|
||||||
)
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 24,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'Suitable Product',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorPalette.slate800,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 16
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
|
||||||
Wrap(
|
|
||||||
runSpacing: 16,
|
|
||||||
children: typeResult.suitableProduct.map((e) {
|
|
||||||
return Container(
|
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.all(8),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
color: typeResult.color.withOpacity(0.1)
|
|
||||||
),
|
|
||||||
child: Image.asset(e['icon'], width: SizeConfig.width * 0.07, color: typeResult.color)
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 12,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text(e['desc'],
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: ColorPalette.slate800
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 32,
|
height: 32,
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Re-test',
|
name: 'Re-test',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
routePush(context, page: QuestionView(), routeType: RouteType.pushReplace);
|
||||||
},
|
},
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
backgroundColor: ColorPalette.white,
|
backgroundColor: ColorPalette.white,
|
||||||
@@ -162,21 +56,25 @@ class ResultsView extends StatelessWidget {
|
|||||||
isOutlined: true,
|
isOutlined: true,
|
||||||
textSize: 16,
|
textSize: 16,
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
contentPadding: EdgeInsets.all(16),
|
contentPadding: const EdgeInsets.all(16),
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Confirm',
|
name: 'Confirm',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context, page: DialogSuccess());
|
routePush(
|
||||||
|
context,
|
||||||
|
page: const TermsAndConditionView(),
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
textSize: 16,
|
textSize: 16,
|
||||||
heightWrapContent: true,
|
heightWrapContent: true,
|
||||||
contentPadding: EdgeInsets.all(16),
|
contentPadding: const EdgeInsets.all(16),
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
@@ -13,26 +12,9 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Container(
|
||||||
appBar: AppBar(
|
|
||||||
toolbarHeight: 70,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
surfaceTintColor: Colors.white,
|
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
title: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
const BackButtonView(),
|
|
||||||
const Text('Risk Profile', textAlign: TextAlign.center),
|
|
||||||
SizedBox(width: SizeConfig.width * 0.1)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
side: BorderSide(color: ColorPalette.slate200)),
|
|
||||||
),
|
|
||||||
body: Container(
|
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
height: SizeConfig.height,
|
height: SizeConfig.height * .8,
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -92,7 +74,7 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
ButtonView(
|
ButtonView(
|
||||||
name: "Let's Start",
|
name: "Let's Start",
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context, page: const QuestionView());
|
routePush(context, page: QuestionView());
|
||||||
},
|
},
|
||||||
marginVertical: 0,
|
marginVertical: 0,
|
||||||
)
|
)
|
||||||
@@ -100,7 +82,6 @@ class RiskProfileView extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/submit_bank_account.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/submit_bank_account.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/risk_profile/risk_profile_view.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_data_id_card.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_data_id_card.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_photo_ktp.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_photo_ktp.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_email.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_email.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_personal_data.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_personal_data.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_photo_selfie.dart';
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_photo_selfie.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_signature/initial_signature.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -22,13 +25,13 @@ class SubmissionParent extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SubmissionParentState extends State<SubmissionParent> {
|
class _SubmissionParentState extends State<SubmissionParent> {
|
||||||
Widget _stepItem({bool isCurrentStep = false, bool isDone = false}) {
|
Widget _stepItem({bool isCurrentStep = false}) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(right: 4.0, left: 4.0),
|
margin: const EdgeInsets.only(right: 0.0, left: 4.0),
|
||||||
height: 6,
|
height: 6,
|
||||||
width: SizeConfig.width * .08,
|
width: SizeConfig.width * .08,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isCurrentStep || isDone
|
color: isCurrentStep
|
||||||
? ColorPalette.primary
|
? ColorPalette.primary
|
||||||
: ColorPalette.greyBorderNeutrals,
|
: ColorPalette.greyBorderNeutrals,
|
||||||
borderRadius: BorderRadius.circular(50),
|
borderRadius: BorderRadius.circular(50),
|
||||||
@@ -51,17 +54,11 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
|||||||
case 6:
|
case 6:
|
||||||
return const SubmitBankAccount();
|
return const SubmitBankAccount();
|
||||||
case 7:
|
case 7:
|
||||||
return Container(
|
return const InitialSignature();
|
||||||
child: Text("Step 7"),
|
|
||||||
);
|
|
||||||
case 8:
|
case 8:
|
||||||
return Container(
|
return const RiskProfileView();
|
||||||
child: Text("Step 8"),
|
|
||||||
);
|
|
||||||
case 9:
|
case 9:
|
||||||
return Container(
|
return const Text("Step 9");
|
||||||
child: Text("Step 9"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,22 +67,33 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
|||||||
return ChangeNotifierProvider(
|
return ChangeNotifierProvider(
|
||||||
create: (context) => SubmissionDataViewModel(),
|
create: (context) => SubmissionDataViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return WillPopScope(
|
return PopScope(
|
||||||
onWillPop: () async {
|
canPop: false,
|
||||||
|
onPopInvoked: (didPop) async {
|
||||||
|
if (didPop) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await routePush(context,
|
await routePush(context,
|
||||||
page: const BottomNavigationView(),
|
page: const BottomNavigationView(),
|
||||||
routeType: RouteType.pushReplace);
|
routeType: RouteType.pushReplace);
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Registration'),
|
|
||||||
),
|
|
||||||
body: Stack(
|
|
||||||
children: [
|
|
||||||
Consumer<SubmissionDataViewModel>(
|
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Column(
|
return Scaffold(
|
||||||
|
appBar: CustomAppBar(
|
||||||
|
height: SizeConfig.height * .1,
|
||||||
|
title: 'Registration',
|
||||||
|
leading: BackButtonView(
|
||||||
|
onPress: () {
|
||||||
|
routePush(
|
||||||
|
context,
|
||||||
|
page: const BottomNavigationView(),
|
||||||
|
routeType: RouteType.pushReplace,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@@ -94,41 +102,25 @@ class _SubmissionParentState extends State<SubmissionParent> {
|
|||||||
horizontal: 16.0, vertical: 16.0),
|
horizontal: 16.0, vertical: 16.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: List.generate(
|
children: List.generate(provider.stepAmount, (index) {
|
||||||
provider.stepAmount,
|
return _stepItem(
|
||||||
(index) => _stepItem(
|
|
||||||
isCurrentStep:
|
isCurrentStep:
|
||||||
provider.getCurrentStep == index + 1,
|
provider.getCurrentStep == index + 1 ||
|
||||||
),
|
provider.getCurrentStep - 1 > index,
|
||||||
),
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: SingleChildScrollView(
|
||||||
padding:
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: _content(provider.getCurrentStep),
|
child: _content(provider.getCurrentStep),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
provider.getCurrentStep == 3 ||
|
|
||||||
provider.getCurrentStep == 4
|
|
||||||
? const SizedBox()
|
|
||||||
: Align(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
child: ButtonView(
|
|
||||||
name: 'Next',
|
|
||||||
marginVertical: 16.0,
|
|
||||||
onPressed: () {
|
|
||||||
provider.nextSubmission(context);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/date_picker/date_picker_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
class SubmitDataIdCard extends StatelessWidget {
|
class SubmitDataIdCard extends StatelessWidget {
|
||||||
const SubmitDataIdCard({Key? key}) : super(key: key);
|
const SubmitDataIdCard({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List listImg = [
|
|
||||||
{'urlImg': PathAssets.imgKtpClear, 'tag': 'ID Card'},
|
|
||||||
{'urlImg': PathAssets.imgSelfieClear, 'tag': 'Selfie with ID Card'},
|
|
||||||
];
|
|
||||||
|
|
||||||
bottomSheet() {
|
bottomSheet() {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -28,7 +31,7 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius:
|
borderRadius:
|
||||||
BorderRadius.vertical(top: Radius.circular(18))),
|
BorderRadius.vertical(top: Radius.circular(18))),
|
||||||
height: SizeConfig.height * .32,
|
height: SizeConfig.height * .35,
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -83,7 +86,7 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget photoDocument() {
|
Widget photoDocument(SubmissionDataViewModel provider) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -100,16 +103,28 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: listImg.map((e) {
|
children: provider.listImg.map((e) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: SizeConfig.height * .18,
|
height: SizeConfig.height * .18,
|
||||||
width: SizeConfig.width * .45,
|
width: SizeConfig.width * .45,
|
||||||
child: ImageView(
|
child: Transform(
|
||||||
image: e['urlImg'],
|
alignment: Alignment.center,
|
||||||
|
transform: e.key == 'selfie'
|
||||||
|
? Matrix4.rotationY(math.pi)
|
||||||
|
: Matrix4.rotationY(0),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: Image.file(
|
||||||
|
File(e.image),
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
borderRadius: 12,
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
return const Icon(
|
||||||
|
Icons.image_not_supported_outlined);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@@ -118,7 +133,7 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
e['tag'],
|
e.text,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
@@ -151,21 +166,56 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
builder: (context, child) {
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Form(
|
||||||
|
key: provider.formKeySubmitIdCard,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TextCaption(title: 'Check your ID card data for accuracy'),
|
const TextCaption(
|
||||||
TextFormView(name: 'NIK'),
|
title: 'Check your ID card data for accuracy'),
|
||||||
TextFormView(name: 'Full Name'),
|
|
||||||
TextFormView(
|
TextFormView(
|
||||||
|
name: 'NIK',
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextFormView(
|
||||||
|
name: 'Full Name',
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
DatePickerView(
|
||||||
name: 'Birth Date',
|
name: 'Birth Date',
|
||||||
suffixIcon: const Icon(
|
ctrl: provider.ctrlBirthDate,
|
||||||
Icons.calendar_today_rounded,
|
maxDate: DateTime.now(),
|
||||||
color: ColorPalette.slate400,
|
isMultipleSelection: false,
|
||||||
|
enabled: true,
|
||||||
|
validatorDate: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
photoDocument(provider),
|
||||||
photoDocument(),
|
|
||||||
Container(
|
Container(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
@@ -210,9 +260,26 @@ class SubmitDataIdCard extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () async {
|
||||||
|
if (provider.formKeySubmitIdCard.currentState!
|
||||||
|
.validate()) {
|
||||||
|
await provider.next(context).then((value) {
|
||||||
|
if (value) {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubmissionParent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -10,44 +15,70 @@ import 'package:provider/provider.dart';
|
|||||||
class SubmitEmail extends StatelessWidget {
|
class SubmitEmail extends StatelessWidget {
|
||||||
const SubmitEmail({Key? key}) : super(key: key);
|
const SubmitEmail({Key? key}) : super(key: key);
|
||||||
|
|
||||||
Widget _emailVerify() {
|
Widget _emailVerify(BuildContext context, SubmissionDataViewModel provider) {
|
||||||
return Column(
|
var textTheme = Theme.of(context).textTheme;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(24.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
const TextCaption(title: 'Check your e-mail'),
|
||||||
const ImageView(image: PathAssets.imgEmail),
|
const ImageView(image: PathAssets.imgEmail),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: RichText(
|
child: RichText(
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
text: TextSpan(children: [
|
text: TextSpan(children: [
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
'We have sent a verification link to your e-mail. \nPlease check your email for ',
|
'We have sent a verification link to your e-mail. \nPlease check your email for ',
|
||||||
style: TextStyle(
|
style: textTheme.displayMedium,
|
||||||
color: Colors.black,
|
|
||||||
decoration: TextDecoration.none,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () async {
|
||||||
print('object');
|
await provider.next(context).then((value) {
|
||||||
|
if (value) {
|
||||||
|
routePush(context, page: const SubmissionParent());
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
text: 'verification',
|
text: 'verification',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: ' to \ncontinue registration.',
|
text: ' to \ncontinue registration.',
|
||||||
style: TextStyle(
|
style: textTheme.displayMedium,
|
||||||
color: Colors.black,
|
|
||||||
decoration: TextDecoration.none,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
showEmailVerify(BuildContext context, SubmissionDataViewModel provider) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
enableDrag: false,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
top: Radius.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
builder: (context) {
|
||||||
|
var flutterView = View.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: MediaQueryData.fromView(flutterView).padding.top,
|
||||||
|
),
|
||||||
|
child: _emailVerify(context, provider),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,22 +89,42 @@ class SubmitEmail extends StatelessWidget {
|
|||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Column(
|
return SizedBox(
|
||||||
|
height: SizeConfig.height * .78,
|
||||||
|
child: Form(
|
||||||
|
key: provider.formKeySubmitEmail,
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
!provider.isEmailVerify
|
const TextCaption(title: 'Enter your e-mail'),
|
||||||
? const TextCaption(title: 'Enter your e-mail')
|
TextFormView(
|
||||||
: const TextCaption(title: 'Check your e-mail '),
|
|
||||||
!provider.isEmailVerify
|
|
||||||
? TextFormView(
|
|
||||||
name: 'E-mail Address',
|
name: 'E-mail Address',
|
||||||
hintText: 'Input e-mail address',
|
hintText: 'Input e-mail address',
|
||||||
onTap: () {
|
keyboardType: TextInputType.emailAddress,
|
||||||
provider.submitEmail();
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Filled cannot be empty';
|
||||||
|
} else if (!StringUtils.emailValidation(value)) {
|
||||||
|
return 'Format email wrong';
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(height: SizeConfig.height * .43),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () async {
|
||||||
|
if (provider.formKeySubmitEmail.currentState!
|
||||||
|
.validate()) {
|
||||||
|
showEmailVerify(context, provider);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: _emailVerify(),
|
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
||||||
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -10,45 +13,91 @@ class SubmitPersonalData extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
List<ItemSelectForm> listForm = [
|
|
||||||
ItemSelectForm('key1', 'text'),
|
|
||||||
ItemSelectForm('key2', 'text'),
|
|
||||||
ItemSelectForm('key3', 'text'),
|
|
||||||
ItemSelectForm('key4', 'text'),
|
|
||||||
ItemSelectForm('key5', 'text'),
|
|
||||||
];
|
|
||||||
return ChangeNotifierProvider(
|
return ChangeNotifierProvider(
|
||||||
create: (context) => SubmissionDataViewModel(),
|
create: (context) => SubmissionDataViewModel(),
|
||||||
builder: (context, child) {
|
builder: (context, child) {
|
||||||
return Consumer<SubmissionDataViewModel>(
|
return Consumer<SubmissionDataViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return SingleChildScrollView(
|
return SizedBox(
|
||||||
|
height: SizeConfig.height * .78,
|
||||||
|
child: Form(
|
||||||
|
key: provider.formKeyPersonalData,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
const TextCaption(title: 'Your personal details'),
|
const TextCaption(title: 'Your personal details'),
|
||||||
SelectFormView(
|
SelectFormView(
|
||||||
name: 'Occupation',
|
name: 'Occupation',
|
||||||
hintText: 'Select occupation ',
|
hintText: 'Select occupation ',
|
||||||
bottomSheetTitle: Row(
|
ctrl: provider.ctrlOccupation,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
listItem: provider.listOccupation,
|
||||||
children: [
|
|
||||||
const Text('Occupation'),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.clear,
|
|
||||||
size: 20,
|
|
||||||
color: ColorPalette.greyBase,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
listItem: listForm,
|
|
||||||
onSelect: (value) {},
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
SelectFormView(
|
||||||
|
name: 'Income Level (IDR)',
|
||||||
|
hintText: 'Select Income ',
|
||||||
|
ctrl: provider.ctrlIncome,
|
||||||
|
listItem: provider.listIncome,
|
||||||
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SelectFormView(
|
||||||
|
name: 'Marital Status',
|
||||||
|
hintText: 'Select Marital Status ',
|
||||||
|
ctrl: provider.ctrlMarital,
|
||||||
|
listItem: provider.listMarital,
|
||||||
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SelectFormView(
|
||||||
|
name: 'Source of Fund',
|
||||||
|
hintText: 'Select Source of Fund ',
|
||||||
|
ctrl: provider.ctrlSourceFund,
|
||||||
|
listItem: provider.listSourceFund,
|
||||||
|
onSelect: (value) {},
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Field must be filled';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
// SizedBox(height: SizeConfig.height * .18),
|
||||||
|
ButtonView(
|
||||||
|
marginVertical: 0,
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () async {
|
||||||
|
if (provider.formKeyPersonalData.currentState!
|
||||||
|
.validate()) {
|
||||||
|
await provider.next(context).then((value) {
|
||||||
|
if (value) {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubmissionParent());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/list_tile/list_tile_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submit_signature/submit_signature.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class InitialSignature extends StatelessWidget {
|
||||||
|
const InitialSignature({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MultiProvider(
|
||||||
|
providers: [
|
||||||
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
builder: (context, child) {
|
||||||
|
return Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return SizedBox(
|
||||||
|
height: SizeConfig.height * .8,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const TextCaption(title: 'Draw your digital sign'),
|
||||||
|
const ImageView(image: PathAssets.frameSignature),
|
||||||
|
const ListTileView(
|
||||||
|
title:
|
||||||
|
'Make sure the sign you draw is match with your ID Card'),
|
||||||
|
SizedBox(height: SizeConfig.height * .1),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
onPressed: () {
|
||||||
|
provider.next(context).then((value) {
|
||||||
|
if (value) {
|
||||||
|
routePush(context, page: const SubmitSignature());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/list_tile/list_tile_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_caption/text_caption.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/submission_parent.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
|
import 'package:dotted_border/dotted_border.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:syncfusion_flutter_signaturepad/signaturepad.dart';
|
||||||
|
|
||||||
|
class SubmitSignature extends StatelessWidget {
|
||||||
|
const SubmitSignature({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
GlobalKey<SfSignaturePadState> signaturePadKey = GlobalKey();
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: 70,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
surfaceTintColor: Colors.white,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BackButtonView(),
|
||||||
|
const Text('Registration'),
|
||||||
|
SizedBox(
|
||||||
|
width: SizeConfig.width * 0.1,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
side: BorderSide(color: ColorPalette.slate200)),
|
||||||
|
),
|
||||||
|
body: Container(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Consumer<SubmissionDataViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextCaption(title: 'Draw your digital sign'),
|
||||||
|
SizedBox(
|
||||||
|
height: SizeConfig.height * .28,
|
||||||
|
child: DottedBorder(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
borderType: BorderType.RRect,
|
||||||
|
radius: const Radius.circular(8),
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
strokeWidth: 2.0,
|
||||||
|
dashPattern: const [14, 0, 0, 8],
|
||||||
|
child: SfSignaturePad(
|
||||||
|
key: signaturePadKey,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const ListTileView(
|
||||||
|
title:
|
||||||
|
'Make sure the sign you draw is match with your ID Card'),
|
||||||
|
const Spacer(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ButtonView(
|
||||||
|
name: 'Delete',
|
||||||
|
isOutlined: true,
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () {
|
||||||
|
signaturePadKey.currentState?.clear();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
width: SizeConfig.width * .42,
|
||||||
|
onPressed: () async {
|
||||||
|
// ui.Image image = await _signaturePadKey.currentState!.toImage();
|
||||||
|
routePush(context, page: const SubmissionParent());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/set_pin_view/set_pin_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/viewmodel/submission_data_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class TermsAndConditionView extends StatelessWidget {
|
class TermsAndConditionView extends StatelessWidget {
|
||||||
const TermsAndConditionView({super.key});
|
const TermsAndConditionView({super.key});
|
||||||
@@ -22,69 +27,83 @@ class TermsAndConditionView extends StatelessWidget {
|
|||||||
'I am willing to provide my data and information from PT Gemilang Indonesia Manajemen Investasi to groups'
|
'I am willing to provide my data and information from PT Gemilang Indonesia Manajemen Investasi to groups'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => SubmissionDataViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar:
|
||||||
height: 70,
|
const CustomAppBar(height: 70, title: 'Terms And Condition'),
|
||||||
title: 'Terms And Condition'
|
|
||||||
),
|
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
'In relevance with the data that i have submitted and in relation to the purchase of Mutual Fund Products, I hereby declare that:',
|
'In relevance with the data that i have submitted and in relation to the purchase of Mutual Fund Products, I hereby declare that:',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 12),
|
||||||
SizedBox(height: 12),
|
|
||||||
...listRules.asMap().entries.map((e) {
|
...listRules.asMap().entries.map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: e.key != 0 ? 12 : 0),
|
padding: EdgeInsets.only(top: e.key != 0 ? 12 : 0),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text('${e.key + 1}', style: TextStyle(color: ColorPalette.slate500)),
|
Text('${e.key + 1}',
|
||||||
SizedBox(width: 12),
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate500)),
|
||||||
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(e.value, style: TextStyle(color: ColorPalette.slate500))
|
child: Text(e.value,
|
||||||
)
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate500)))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
}),
|
||||||
],
|
Consumer<SubmissionDataViewModel>(
|
||||||
),
|
builder: (context, provider, child) {
|
||||||
),
|
return Padding(
|
||||||
bottomNavigationBar: Container(
|
padding: const EdgeInsets.only(top: 24.0),
|
||||||
height: 84,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
color: Colors.red,
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ButtonView(
|
child: ButtonView(
|
||||||
name: 'Decline',
|
name: 'Decline',
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
marginVertical: 16,
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
height: SizeConfig.height * .06,
|
||||||
|
marginVertical: 0,
|
||||||
backgroundColor: ColorPalette.white,
|
backgroundColor: ColorPalette.white,
|
||||||
textColor: ColorPalette.primary,
|
textColor: ColorPalette.primary,
|
||||||
isOutlined: true,
|
isOutlined: true,
|
||||||
borderColor: ColorPalette.primary,
|
borderColor: ColorPalette.primary,
|
||||||
)
|
)),
|
||||||
),
|
const SizedBox(width: 16),
|
||||||
SizedBox(width: 16),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: ButtonView(
|
child: ButtonView(
|
||||||
name: 'Accept',
|
name: 'Accept',
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
marginVertical: 16
|
provider.nextSubmission(context);
|
||||||
)
|
routePush(context,
|
||||||
)
|
routeType: RouteType.pushReplace,
|
||||||
|
page: SetPinView(
|
||||||
|
currentPin: '',
|
||||||
|
submitPin: (context, pin) {},
|
||||||
|
));
|
||||||
|
},
|
||||||
|
height: SizeConfig.height * .06,
|
||||||
|
marginVertical: 0))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,71 @@
|
|||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
|
import 'package:cims_apps/application/component/select_form/select_form_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/submission_data/data_bank/confirm_bank_account.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
class SubmissionDataViewModel extends ChangeNotifier {
|
class SubmissionDataViewModel extends ChangeNotifier {
|
||||||
|
SubmissionDataViewModel() {
|
||||||
|
_getData();
|
||||||
|
}
|
||||||
|
|
||||||
static int _currentStep = 1;
|
static int _currentStep = 1;
|
||||||
int get getCurrentStep => _currentStep;
|
int get getCurrentStep => _currentStep;
|
||||||
int stepAmount = 9;
|
int stepAmount = 9;
|
||||||
bool _isEmailVerify = false;
|
bool _isEmailVerify = false;
|
||||||
bool get isEmailVerify => _isEmailVerify;
|
bool get isEmailVerify => _isEmailVerify;
|
||||||
|
var formKeyPersonalData = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitEmail = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitIdCard = GlobalKey<FormState>();
|
||||||
|
var formKeySubmitDataBank = GlobalKey<FormState>();
|
||||||
|
TextEditingController ctrlOccupation = TextEditingController();
|
||||||
|
TextEditingController ctrlIncome = TextEditingController();
|
||||||
|
TextEditingController ctrlMarital = TextEditingController();
|
||||||
|
TextEditingController ctrlSourceFund = TextEditingController();
|
||||||
|
TextEditingController ctrlBankName = TextEditingController();
|
||||||
|
TextEditingController ctrlNameAccountBank = TextEditingController();
|
||||||
|
TextEditingController ctrlNoAccountBank = TextEditingController();
|
||||||
|
TextEditingController ctrlBankNameSearch = TextEditingController();
|
||||||
|
TextEditingController ctrlBirthDate = TextEditingController();
|
||||||
|
int step = 1;
|
||||||
|
String? idx;
|
||||||
|
String valueBank = '';
|
||||||
|
|
||||||
|
List<ItemSelectForm> listOccupation = [
|
||||||
|
ItemSelectForm('key1', 'Student'),
|
||||||
|
ItemSelectForm('key2', 'Entrepreneur'),
|
||||||
|
ItemSelectForm('key3', 'Civil Servant'),
|
||||||
|
];
|
||||||
|
List<ItemSelectForm> listIncome = [
|
||||||
|
ItemSelectForm('key1', '< 10 million/year'),
|
||||||
|
ItemSelectForm('key2', '10 – 50 million/year'),
|
||||||
|
ItemSelectForm('key3', '50 – 100 million/year'),
|
||||||
|
];
|
||||||
|
List<ItemSelectForm> listMarital = [
|
||||||
|
ItemSelectForm('key1', 'Single'),
|
||||||
|
ItemSelectForm('key2', 'Married'),
|
||||||
|
ItemSelectForm('key3', 'Divorced'),
|
||||||
|
];
|
||||||
|
List<ItemSelectForm> listSourceFund = [
|
||||||
|
ItemSelectForm('key1', 'Revenue'),
|
||||||
|
ItemSelectForm('key2', 'Business Profit'),
|
||||||
|
ItemSelectForm('key3', 'Saving interest'),
|
||||||
|
];
|
||||||
|
|
||||||
|
List<ItemSelectForm> listBank = [
|
||||||
|
ItemSelectForm('0', 'BCA'),
|
||||||
|
ItemSelectForm('1', 'BRI'),
|
||||||
|
ItemSelectForm('2', 'BNI'),
|
||||||
|
ItemSelectForm('3', 'BANK MANDIRI'),
|
||||||
|
ItemSelectForm('4', 'CIMB NIAGA'),
|
||||||
|
ItemSelectForm('5', 'PERMATA'),
|
||||||
|
ItemSelectForm('6', 'BANK JATENG'),
|
||||||
|
];
|
||||||
|
|
||||||
|
List<ItemSelectForm> listImg = [
|
||||||
|
ItemSelectForm('ktp', 'ID Card', image: ''),
|
||||||
|
ItemSelectForm('selfie', 'Selfie with ID Card', image: ''),
|
||||||
|
];
|
||||||
|
|
||||||
Future<List<CameraDescription>> initCamera() async {
|
Future<List<CameraDescription>> initCamera() async {
|
||||||
final cameras = await availableCameras();
|
final cameras = await availableCameras();
|
||||||
@@ -34,6 +93,54 @@ class SubmissionDataViewModel extends ChangeNotifier {
|
|||||||
} else {
|
} else {
|
||||||
//ToDo : Go To next step after completing the submission
|
//ToDo : Go To next step after completing the submission
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> next(BuildContext context) async {
|
||||||
|
if (getCurrentStep < stepAmount) {
|
||||||
|
_currentStep++;
|
||||||
|
notifyListeners();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _getData() async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
String? imagePath = prefs.getString('imagePath');
|
||||||
|
String? imagePathSelfie = prefs.getString('imagePathSelfie');
|
||||||
|
if (imagePath != null && imagePathSelfie != null) {
|
||||||
|
listImg[0].image = imagePath;
|
||||||
|
listImg[1].image = imagePathSelfie;
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
changeBank(String key) {
|
||||||
|
idx = key;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectBank(String value) {
|
||||||
|
valueBank = value;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ModelDataBank> listDataBank = [];
|
||||||
|
|
||||||
|
Future<List<ModelDataBank>?> submitDataBank(
|
||||||
|
{required String bankName, accountNumber, accountName}) async {
|
||||||
|
List<ModelDataBank> listResponse = [
|
||||||
|
ModelDataBank('Bank Name', bankName),
|
||||||
|
ModelDataBank('Account Number', accountNumber),
|
||||||
|
ModelDataBank('Account Owner Name', accountName),
|
||||||
|
ModelDataBank('Name on ID card', accountName),
|
||||||
|
];
|
||||||
|
if (listResponse.first.subtitle != null) {
|
||||||
|
// listDataBank = listResponse;
|
||||||
|
return listResponse;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/homepage/homepage_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/plan_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/plan_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_view.dart';
|
||||||
|
import 'package:cims_apps/features/profile/view/profile_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/transaction_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
class BottomNavigationItem {
|
||||||
|
String icon, label;
|
||||||
|
|
||||||
|
BottomNavigationItem(this.icon, this.label);
|
||||||
|
}
|
||||||
|
|
||||||
class BottomNavigationView extends StatefulWidget {
|
class BottomNavigationView extends StatefulWidget {
|
||||||
const BottomNavigationView({Key? key}) : super(key: key);
|
const BottomNavigationView({Key? key}) : super(key: key);
|
||||||
@@ -18,41 +26,28 @@ class _BottomNavigationViewState extends State<BottomNavigationView> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
///TODO: masukan pagenya dilistWidget ini
|
List<Widget> listWidget = const [
|
||||||
List<Widget> listWidget = [
|
|
||||||
HomeView(),
|
HomeView(),
|
||||||
PlanView(),
|
PlanView(),
|
||||||
Container(),
|
TransactionView(),
|
||||||
PortofolioView(),
|
PortofolioView(),
|
||||||
Container(),
|
ProfileView(),
|
||||||
];
|
];
|
||||||
|
|
||||||
List<BottomNavigationBarItem> listNavigation = const [
|
List<BottomNavigationItem> listNavigation = [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationItem(PathAssets.iconNavigationHome, 'Home'),
|
||||||
icon: Icon(Icons.home_outlined),
|
BottomNavigationItem(PathAssets.iconNavigationPlan, 'Plan'),
|
||||||
label: 'Home',
|
BottomNavigationItem(PathAssets.iconNavigationTransaction, 'Transaction'),
|
||||||
),
|
BottomNavigationItem(PathAssets.iconNavigationPortfolio, 'Portfolio'),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationItem(PathAssets.iconNavigationProfile, 'Profile')
|
||||||
icon: Icon(Icons.file_open),
|
|
||||||
label: 'Plan',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.compare_arrows),
|
|
||||||
label: 'Transaction',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.pie_chart_rounded),
|
|
||||||
label: 'Portfolio',
|
|
||||||
),
|
|
||||||
BottomNavigationBarItem(
|
|
||||||
icon: Icon(Icons.person),
|
|
||||||
label: 'Profile',
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: listWidget[_selectedIndex],
|
body: listWidget[_selectedIndex],
|
||||||
bottomNavigationBar: Padding(
|
bottomNavigationBar: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(top: BorderSide(color: ColorPalette.slate200))
|
||||||
|
),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
child: BottomNavigationBar(
|
child: BottomNavigationBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -62,13 +57,25 @@ class _BottomNavigationViewState extends State<BottomNavigationView> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
currentIndex: _selectedIndex,
|
currentIndex: _selectedIndex,
|
||||||
items: listNavigation,
|
items: listNavigation.asMap().entries.map((e) {
|
||||||
|
return BottomNavigationBarItem(
|
||||||
|
icon: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4),
|
||||||
|
child: Image.asset(
|
||||||
|
e.value.icon,
|
||||||
|
width: SizeConfig.width * 0.06,
|
||||||
|
color: e.key == _selectedIndex ? ColorPalette.primary : ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
label: e.value.label
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
type: BottomNavigationBarType.fixed,
|
type: BottomNavigationBarType.fixed,
|
||||||
showUnselectedLabels: true,
|
showUnselectedLabels: true,
|
||||||
selectedItemColor: ColorPalette.primary,
|
selectedItemColor: ColorPalette.primary,
|
||||||
unselectedItemColor: Colors.black,
|
unselectedItemColor: Colors.black,
|
||||||
selectedLabelStyle: const TextStyle(color: ColorPalette.primary),
|
selectedLabelStyle: const TextStyle(color: ColorPalette.primary, fontSize: 12),
|
||||||
unselectedLabelStyle: const TextStyle(color: Colors.black),
|
unselectedLabelStyle: const TextStyle(color: Colors.black, fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import 'package:cims_apps/application/theme/color_palette.dart';
|
|||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart';
|
import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/invest_type/invest_type_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -50,14 +49,22 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
InvestType('Sharia', PathAssets.iconPortofolioSharia)
|
InvestType('Sharia', PathAssets.iconPortofolioSharia)
|
||||||
];
|
];
|
||||||
|
|
||||||
StepVerification listStepVerification = StepVerification(0, [
|
StepVerification listStepVerification =
|
||||||
'Registration', 'Verification', 'Complete'
|
StepVerification(0, ['Registration', 'Verification', 'Complete']);
|
||||||
]);
|
|
||||||
|
|
||||||
List<Article> listArticle = [
|
List<Article> listArticle = [
|
||||||
Article('Education', 'Menggali Potensi Pasar: Analisis Sebelum Memulai Investasi', PathAssets.imgArticles),
|
Article(
|
||||||
Article('News', 'Tren Investasi 2024: Peluang dan Risiko yang Perlu Diketahui', PathAssets.imgArticles),
|
'Education',
|
||||||
Article('Education', 'Investasi Berkelanjutan: Mengenal Portofolio Hijau untuk Masa Depan', PathAssets.imgArticles),
|
'Menggali Potensi Pasar: Analisis Sebelum Memulai Investasi',
|
||||||
|
PathAssets.imgArticles),
|
||||||
|
Article(
|
||||||
|
'News',
|
||||||
|
'Tren Investasi 2024: Peluang dan Risiko yang Perlu Diketahui',
|
||||||
|
PathAssets.imgArticles),
|
||||||
|
Article(
|
||||||
|
'Education',
|
||||||
|
'Investasi Berkelanjutan: Mengenal Portofolio Hijau untuk Masa Depan',
|
||||||
|
PathAssets.imgArticles),
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -85,22 +92,17 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700
|
fontWeight: FontWeight.w700),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {},
|
||||||
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
foregroundColor: const Color(0xff2563EB),
|
foregroundColor: const Color(0xff2563EB),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
shape: const CircleBorder()
|
shape: const CircleBorder()),
|
||||||
),
|
child: const Icon(Icons.notifications_outlined))
|
||||||
child: const Icon(Icons.notifications_outlined)
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -148,7 +150,8 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Text('Portofolio Value', style: TextStyle(color: Colors.white)),
|
const Text('Portofolio Value',
|
||||||
|
style: TextStyle(color: Colors.white)),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
@@ -158,8 +161,11 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
seePortofolioValue = !seePortofolioValue;
|
seePortofolioValue = !seePortofolioValue;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.visibility_outlined, color: Color(0xff93C5FD))
|
child: Icon(
|
||||||
)
|
seePortofolioValue
|
||||||
|
? Icons.visibility_off_outlined
|
||||||
|
: Icons.visibility_outlined,
|
||||||
|
color: const Color(0xff93C5FD)))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@@ -170,11 +176,17 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
AnimatedCrossFade(
|
AnimatedCrossFade(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
crossFadeState: seePortofolioValue ? CrossFadeState.showSecond : CrossFadeState.showFirst,
|
crossFadeState: seePortofolioValue
|
||||||
|
? CrossFadeState.showSecond
|
||||||
|
: CrossFadeState.showFirst,
|
||||||
firstChild: RichText(
|
firstChild: RichText(
|
||||||
text: const TextSpan(
|
text: const TextSpan(
|
||||||
text: 'Rp ',
|
text: 'Rp ',
|
||||||
style: TextStyle(fontSize: 32, color: Color(0xff93C5FD), fontFamily: 'Manrope',),
|
style: TextStyle(
|
||||||
|
fontSize: 32,
|
||||||
|
color: Color(0xff93C5FD),
|
||||||
|
fontFamily: 'Manrope',
|
||||||
|
),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '22.500.000',
|
text: '22.500.000',
|
||||||
@@ -185,9 +197,7 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
])),
|
||||||
)
|
|
||||||
),
|
|
||||||
secondChild: Padding(
|
secondChild: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
@@ -197,7 +207,8 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
Container(
|
Container(
|
||||||
width: 12,
|
width: 12,
|
||||||
height: 12,
|
height: 12,
|
||||||
decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle),
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white, shape: BoxShape.circle),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -219,10 +230,8 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
BoxShadow(
|
BoxShadow(
|
||||||
spreadRadius: 2,
|
spreadRadius: 2,
|
||||||
blurRadius: 4,
|
blurRadius: 4,
|
||||||
color: const Color(0xff1E293B).withOpacity(0.04)
|
color: const Color(0xff1E293B).withOpacity(0.04))
|
||||||
)
|
]),
|
||||||
]
|
|
||||||
),
|
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
spacing: 10,
|
spacing: 10,
|
||||||
children: listPortofolioType.asMap().entries.map((e) {
|
children: listPortofolioType.asMap().entries.map((e) {
|
||||||
@@ -235,7 +244,11 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
width: SizeConfig.width * .18,
|
width: SizeConfig.width * .18,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
ImageView(image: e.value.iconImage, height: SizeConfig.width * .12, width: SizeConfig.width * .12,),
|
ImageView(
|
||||||
|
image: e.value.iconImage,
|
||||||
|
height: SizeConfig.width * .12,
|
||||||
|
width: SizeConfig.width * .12,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
@@ -244,9 +257,7 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12, fontWeight: FontWeight.w600),
|
||||||
fontWeight: FontWeight.w600
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -277,15 +288,16 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
children: [
|
children: [
|
||||||
const Row(
|
const Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.verified, size: 18,),
|
Icon(
|
||||||
|
Icons.verified,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Verified by PT Gemilang',
|
'Verified by PT Gemilang',
|
||||||
style: TextStyle(
|
style: TextStyle(color: ColorPalette.slate500),
|
||||||
color: ColorPalette.slate500
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -294,9 +306,9 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
height: 16,
|
height: 16,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: const Color(0xffCBD5E1), width: 1.5),
|
border: Border.all(
|
||||||
shape: BoxShape.circle
|
color: const Color(0xffCBD5E1), width: 1.5),
|
||||||
),
|
shape: BoxShape.circle),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -309,15 +321,16 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
const Row(
|
const Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.verified, size: 18,),
|
Icon(
|
||||||
|
Icons.verified,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 12,
|
width: 12,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Verified by KSEI',
|
'Verified by KSEI',
|
||||||
style: TextStyle(
|
style: TextStyle(color: ColorPalette.slate500),
|
||||||
color: ColorPalette.slate500
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -326,9 +339,9 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
height: 16,
|
height: 16,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
border: Border.all(color: const Color(0xffCBD5E1), width: 1.5),
|
border: Border.all(
|
||||||
shape: BoxShape.circle
|
color: const Color(0xffCBD5E1), width: 1.5),
|
||||||
),
|
shape: BoxShape.circle),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -339,15 +352,12 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: ColorPalette.blue50,
|
color: ColorPalette.blue50,
|
||||||
borderRadius: BorderRadius.circular(12)
|
borderRadius: BorderRadius.circular(12)),
|
||||||
),
|
|
||||||
child: const Column(
|
child: const Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Your registration is currently being verified by PT Gemilang',
|
'Your registration is currently being verified by PT Gemilang',
|
||||||
style: TextStyle(
|
style: TextStyle(color: ColorPalette.slate500),
|
||||||
color: ColorPalette.slate500
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
@@ -355,17 +365,15 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text('Estimated:',
|
Text(
|
||||||
style: TextStyle(
|
'Estimated:',
|
||||||
color: ColorPalette.slate500
|
style: TextStyle(color: ColorPalette.slate500),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'January 30 2024',
|
'January 30 2024',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xff1E293B)
|
color: Color(0xff1E293B)),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -377,15 +385,12 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: ColorPalette.blue50,
|
color: ColorPalette.blue50,
|
||||||
borderRadius: BorderRadius.circular(12)
|
borderRadius: BorderRadius.circular(12)),
|
||||||
),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia",
|
"Let's start registering your data to start mutual fund investment at PT Gemilang Indonesia",
|
||||||
style: TextStyle(
|
style: TextStyle(color: ColorPalette.slate500),
|
||||||
color: ColorPalette.slate500
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
@@ -420,7 +425,11 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 30,
|
width: 30,
|
||||||
height: 30,
|
height: 30,
|
||||||
child: Divider(color: listStepVerification.currentStep >= e.key ? const Color(0xff2563EB) : const Color(0xffCBD5E1),),
|
child: Divider(
|
||||||
|
color: listStepVerification.currentStep >= e.key
|
||||||
|
? const Color(0xff2563EB)
|
||||||
|
: const Color(0xffCBD5E1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -429,18 +438,31 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
height: 30,
|
height: 30,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
color: listStepVerification.currentStep <= e.key ? Colors.white : const Color(0xff2563EB),
|
color: listStepVerification.currentStep <= e.key
|
||||||
|
? Colors.white
|
||||||
|
: const Color(0xff2563EB),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: listStepVerification.currentStep < e.key ? const Color(0xffCBD5E1) : const Color(0xff2563EB),
|
color: listStepVerification.currentStep < e.key
|
||||||
width: 2
|
? const Color(0xffCBD5E1)
|
||||||
)
|
: const Color(0xff2563EB),
|
||||||
|
width: 2)),
|
||||||
|
child: listStepVerification.currentStep <= e.key
|
||||||
|
? const SizedBox()
|
||||||
|
: const Icon(
|
||||||
|
Icons.done_rounded,
|
||||||
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
child: listStepVerification.currentStep <= e.key ? const SizedBox() : const Icon(Icons.done_rounded, color: Colors.white,),
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
Text(e.value, style: TextStyle(color: listStepVerification.currentStep == e.key ? const Color(0xff2563EB) : Colors.black),)
|
Text(
|
||||||
|
e.value,
|
||||||
|
style: TextStyle(
|
||||||
|
color: listStepVerification.currentStep == e.key
|
||||||
|
? const Color(0xff2563EB)
|
||||||
|
: Colors.black),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -455,7 +477,10 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const TextTitle(title: 'Info and Special Promo', color: ColorPalette.slate800,),
|
const TextTitle(
|
||||||
|
title: 'Info and Special Promo',
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
@@ -463,7 +488,11 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
items: [1, 2, 3].map((e) {
|
items: [1, 2, 3].map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
child: ImageView(image: PathAssets.imgCarousel, height: 150, width: SizeConfig.width * .9,),
|
child: ImageView(
|
||||||
|
image: PathAssets.imgCarousel,
|
||||||
|
height: 150,
|
||||||
|
width: SizeConfig.width * .9,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
options: CarouselOptions(
|
options: CarouselOptions(
|
||||||
@@ -493,14 +522,13 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
children: [
|
children: [
|
||||||
const TextTitle(title: 'Article', color: ColorPalette.slate800),
|
const TextTitle(title: 'Article', color: ColorPalette.slate800),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {},
|
||||||
|
child: const Text(
|
||||||
},
|
'See More',
|
||||||
child: const Text('See More',
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.primary,
|
color: ColorPalette.primary,
|
||||||
fontWeight: FontWeight.bold
|
fontWeight: FontWeight.bold),
|
||||||
),),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -514,7 +542,9 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
if (e.key != 0) ...[
|
if (e.key != 0) ...[
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 12),
|
padding: EdgeInsets.symmetric(vertical: 12),
|
||||||
child: Divider(color: ColorPalette.slate200,),
|
child: Divider(
|
||||||
|
color: ColorPalette.slate200,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
cardArticle(e.value),
|
cardArticle(e.value),
|
||||||
@@ -531,7 +561,12 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
ImageView(image: PathAssets.imgArticles, width: SizeConfig.width * .17, height: SizeConfig.height * .08, borderRadius: 8,),
|
ImageView(
|
||||||
|
image: PathAssets.imgArticles,
|
||||||
|
width: SizeConfig.width * .17,
|
||||||
|
height: SizeConfig.height * .08,
|
||||||
|
borderRadius: 8,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 16,
|
width: 16,
|
||||||
),
|
),
|
||||||
@@ -539,7 +574,8 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(article.title,
|
Text(
|
||||||
|
article.title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
@@ -548,22 +584,20 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
padding:
|
||||||
|
const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
color: ColorPalette.green100
|
color: ColorPalette.green100),
|
||||||
),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
article.type,
|
article.type,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: ColorPalette.green500
|
color: ColorPalette.green500),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
))
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,11 +20,25 @@ class InvestTypeView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _InvestTypeViewState extends State<InvestTypeView> {
|
class _InvestTypeViewState extends State<InvestTypeView> {
|
||||||
|
|
||||||
List<Product> listProduct = [
|
List<Product> listProduct = [
|
||||||
Product(name: 'Gemilang Dana Kas Maxima', type: '', yield: 8.17, priceUnit: 2600.79, funds: 6300000),
|
Product(
|
||||||
Product(name: 'Gemilang Dana Likuid', type: '', yield: 6.42, priceUnit: 1600.79, funds: 2340000),
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
Product(name: 'Gemilang Income Fund', type: '', yield: 8.17, priceUnit: 2600.79, funds: 6300000)
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000),
|
||||||
|
Product(
|
||||||
|
name: 'Gemilang Dana Likuid',
|
||||||
|
type: '',
|
||||||
|
yield: 6.42,
|
||||||
|
priceUnit: 1600.79,
|
||||||
|
funds: 2340000),
|
||||||
|
Product(
|
||||||
|
name: 'Gemilang Income Fund',
|
||||||
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000)
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -41,8 +55,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChangeNotifierProvider<ProductViewModel>(
|
return ChangeNotifierProvider<ProductViewModel>(
|
||||||
create: (context) => ProductViewModel(),
|
create: (context) => ProductViewModel(),
|
||||||
child: Consumer<ProductViewModel>(
|
child: Consumer<ProductViewModel>(builder: (context, provider, child) {
|
||||||
builder: (context, provider, child) {
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: SizedBox(
|
body: SizedBox(
|
||||||
width: SizeConfig.width,
|
width: SizeConfig.width,
|
||||||
@@ -52,8 +65,8 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
const ImageView(image: PathAssets.imgDashboardAccount),
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
SizedBox(
|
||||||
height: 50,
|
height: SizeConfig.height * .1,
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
@@ -71,12 +84,14 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
Container(
|
Expanded(
|
||||||
|
child: Container(
|
||||||
padding: const EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
color: Colors.white
|
color: Colors.white),
|
||||||
),
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
filters(),
|
filters(),
|
||||||
@@ -86,10 +101,12 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
provider.setSelectedProduct(e.value);
|
provider.setSelectedProduct(e.value);
|
||||||
routePush(context, page: ProductView(widget.title));
|
routePush(context,
|
||||||
|
page: ProductView(selectedProduct: e.value));
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: e.key != 0 ? 24 : 0),
|
padding: EdgeInsets.only(
|
||||||
|
top: e.key != 0 ? 24 : 0),
|
||||||
child: cardProduct(e.value),
|
child: cardProduct(e.value),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -98,14 +115,15 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,9 +133,25 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
segmentFilter(const Icon(Icons.filter_alt_outlined, color: ColorPalette.slate400,), 'Filter', () { }),
|
segmentFilter(
|
||||||
segmentFilter(const RotatedBox(quarterTurns: 1, child: Icon(Icons.compare_arrows, color: ColorPalette.slate400)), 'Sort', () { }),
|
const Icon(
|
||||||
segmentFilter(const Icon(Icons.dashboard_outlined, color: ColorPalette.slate400), 'Compare', () { }),
|
Icons.filter_alt_outlined,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
'Filter',
|
||||||
|
() {}),
|
||||||
|
segmentFilter(
|
||||||
|
const RotatedBox(
|
||||||
|
quarterTurns: 1,
|
||||||
|
child:
|
||||||
|
Icon(Icons.compare_arrows, color: ColorPalette.slate400)),
|
||||||
|
'Sort',
|
||||||
|
() {}),
|
||||||
|
segmentFilter(
|
||||||
|
const Icon(Icons.dashboard_outlined,
|
||||||
|
color: ColorPalette.slate400),
|
||||||
|
'Compare',
|
||||||
|
() {}),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -130,8 +164,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: ColorPalette.slate200),
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
borderRadius: BorderRadius.circular(56)
|
borderRadius: BorderRadius.circular(56)),
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
leading,
|
leading,
|
||||||
@@ -142,9 +175,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
text,
|
text,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: ColorPalette.slate500,
|
color: ColorPalette.slate500, fontWeight: FontWeight.w700),
|
||||||
fontWeight: FontWeight.w700
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -163,7 +194,10 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
ImageView(image: PathAssets.imgProduct, width: SizeConfig.width * .12,),
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .12,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 8,
|
width: 8,
|
||||||
),
|
),
|
||||||
@@ -171,9 +205,7 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
child: Text(
|
child: Text(
|
||||||
product.name ?? '',
|
product.name ?? '',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold, fontSize: 18),
|
||||||
fontSize: 18
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -187,36 +219,53 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('Yield', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),),
|
const Text(
|
||||||
|
'Yield',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${product.yield.toString()}%',
|
'${product.yield.toString()}%',
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: ColorPalette.green400,
|
color: ColorPalette.green400,
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Text('/'),
|
const Text('/'),
|
||||||
const Text('3year', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),)
|
const Text(
|
||||||
|
'3year',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('Price/unit', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),),
|
const Text(
|
||||||
|
'Price/unit',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.trending_up_outlined, size: 18, color: ColorPalette.green400,),
|
const Icon(
|
||||||
|
Icons.trending_up_outlined,
|
||||||
|
size: 18,
|
||||||
|
color: ColorPalette.green400,
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 2,
|
width: 2,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
NumberFormatter.numberCurrency(product.priceUnit, 'Rp', 'id_ID'),
|
NumberFormatter.numberCurrency(
|
||||||
style: const TextStyle(
|
product.priceUnit, 'Rp', 'id_ID'),
|
||||||
fontWeight: FontWeight.w600
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -224,14 +273,18 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('Managed funds', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),),
|
const Text(
|
||||||
|
'Managed funds',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
NumberFormatter.compactCurrency(product.funds, 'Rp ', 'id_ID'),
|
NumberFormatter.compactCurrency(
|
||||||
style: const TextStyle(
|
product.funds, 'Rp ', 'id_ID'),
|
||||||
fontWeight: FontWeight.w600
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -243,5 +296,4 @@ class _InvestTypeViewState extends State<InvestTypeView> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
import 'package:cims_apps/application/component/button/button_view.dart';
|
|
||||||
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart';
|
import 'package:cims_apps/application/component/subscribe/goal_investing_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
|
||||||
import 'package:cims_apps/application/component/risk_profile.dart';
|
import 'package:cims_apps/application/component/risk_profile.dart';
|
||||||
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/number_formatter.dart';
|
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/options_starting_invest.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/options_starting_invest.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
@@ -40,28 +36,34 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Scaffold(
|
return ChangeNotifierProvider(
|
||||||
appBar: CustomAppBar(height: 70, title: 'Investment Plan'),
|
create: (context) => PlanViewModel(),
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: CustomAppBar(
|
||||||
|
height: SizeConfig.height * 0.08,
|
||||||
|
title: 'Investment Plan',
|
||||||
|
leading: const SizedBox(),
|
||||||
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: EdgeInsets.all(24),
|
padding: const EdgeInsets.all(24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
RiskProfile(
|
const RiskProfile(
|
||||||
totalScore: 26,
|
totalScore: 26,
|
||||||
rowSuitableProduct: true
|
rowSuitableProduct: true
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 32,
|
height: 32,
|
||||||
),
|
),
|
||||||
Text('Your Goal in Investing',
|
const Text('Your Goal in Investing',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
fontSize: 18
|
fontSize: 18
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
GoalInvestingView(
|
GoalInvestingView(
|
||||||
@@ -78,6 +80,7 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +98,7 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("It's time to invest",
|
const Text("It's time to invest",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
@@ -105,17 +108,20 @@ class _PlanViewState extends State<PlanView> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
child: Icon(Icons.close_rounded)
|
child: const Icon(Icons.close_rounded)
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Divider(color: ColorPalette.slate200, height: 1),
|
const Divider(color: ColorPalette.slate200, height: 1),
|
||||||
InputInvestmentView(
|
InputInvestmentView(
|
||||||
selectedPlan: text,
|
currentPlan: text,
|
||||||
|
changePlan: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
nextMove: (value) {
|
nextMove: (value) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||||
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
|
showModalBottomSheet(context: context, builder: (context) => OptionsStartingInvest(totalInvest: formatIntParse));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,9 +3,14 @@ import 'package:cims_apps/application/component/button/button_view.dart';
|
|||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view/step_invest_plan/options_starting_invest.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view/product_view.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class ResultOptionsProduct extends StatelessWidget {
|
class ResultOptionsProduct extends StatelessWidget {
|
||||||
final int totalInvest;
|
final int totalInvest;
|
||||||
@@ -19,6 +24,10 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1)
|
Product(name: 'Gemilang Kas 2 Kelas A', type: 'Shares', totalPercent: 0.1)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => PlanViewModel(),
|
||||||
|
child: Consumer<PlanViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
@@ -28,10 +37,21 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.arrow_back, color: ColorPalette.slate500),
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return OptionsStartingInvest(totalInvest: totalInvest);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Icon(Icons.arrow_back, color: ColorPalette.slate500)
|
||||||
|
),
|
||||||
Text('Results from your risk profile',
|
Text('Results from your risk profile',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
@@ -39,7 +59,13 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
color: ColorPalette.slate800
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Icon(Icons.close_rounded, color: ColorPalette.slate400)
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Icon(Icons.close_rounded, color: ColorPalette.slate400)
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
@@ -111,6 +137,7 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
routePush(context, page: ProductView(selectedProduct: e.value, seeMore: true));
|
||||||
},
|
},
|
||||||
child: const Text('See More',
|
child: const Text('See More',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -131,13 +158,23 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
ButtonView(
|
ButtonView(
|
||||||
name: 'Next',
|
name: 'Next',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
TotalPaymentView(
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => PlanViewModel(),
|
||||||
|
child: Consumer<PlanViewModel>(
|
||||||
|
builder: (context, planProvider, _) {
|
||||||
|
return TotalPaymentView(
|
||||||
listProduct: listProduct,
|
listProduct: listProduct,
|
||||||
totalInvest: totalInvest,
|
totalInvest: totalInvest,
|
||||||
|
isAgree: planProvider.isAgree,
|
||||||
|
onTapAgree: planProvider.setAgree,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -150,4 +187,7 @@ class ResultOptionsProduct extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,10 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class PlanViewModel extends ChangeNotifier {
|
class PlanViewModel extends ChangeNotifier {
|
||||||
List<Product> listProduct = [];
|
List<Product> listProduct = [];
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class PortfolioDetailView extends StatelessWidget {
|
||||||
|
const PortfolioDetailView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<PortfolioProduct> listProduct = [
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
|
type: 'Money Market',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000,
|
||||||
|
totalUnit: 14520
|
||||||
|
),
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Likuid',
|
||||||
|
type: 'Sharia',
|
||||||
|
yield: 6.42,
|
||||||
|
priceUnit: 1600.79,
|
||||||
|
funds: 2340000,
|
||||||
|
totalUnit: 232,
|
||||||
|
),
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Income Fund',
|
||||||
|
type: 'Bonds',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000,
|
||||||
|
totalUnit: 2450,
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
body: SizedBox(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
height: SizeConfig.height,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 50,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const BackButtonView(),
|
||||||
|
const TextTitle(title: 'Education', color: Colors.white),
|
||||||
|
SizedBox(width: SizeConfig.width * 0.1,)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24,),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Portfolio Value',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.white,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text('Advantages',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.white,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14, color: Colors.white)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24,),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return ListView(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
children: listProduct.asMap().entries.map((e) {
|
||||||
|
return cardPortfolio(context, e.value);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardPortfolio(context, PortfolioProduct product) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: product.name ?? '', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor[product.type!]?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor[product.type!]?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
product.type ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor[product.type!],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
),
|
||||||
|
Wrap(
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
rowDescription('Present Value', 'Rp2.660.706', fontWeight: FontWeight.w700),
|
||||||
|
rowDescription('Investment Capital', 'Rp2.660.706'),
|
||||||
|
rowDescription('Advantages', 'Rp2.660.706'),
|
||||||
|
rowDescription('Purchase Price', NumberFormatter.numberCurrency(product.priceUnit, 'Rp ', 'id_ID')),
|
||||||
|
rowDescription('Number of Units', '${product.totalUnit ?? 0}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16,),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ButtonView(
|
||||||
|
name: 'Redeem',
|
||||||
|
marginVertical: 0,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
isOutlined: true,
|
||||||
|
heightWrapContent: true,
|
||||||
|
contentPadding: const EdgeInsets.all(12),
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
borderColor: ColorPalette.red600,
|
||||||
|
textColor: ColorPalette.red600,
|
||||||
|
onPressed: () {
|
||||||
|
Provider.of<RedeemProductViewModel>(context, listen: false).setProduct(product);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: ButtonView(
|
||||||
|
name: 'Buy',
|
||||||
|
marginVertical: 0,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
heightWrapContent: true,
|
||||||
|
contentPadding: const EdgeInsets.all(12),
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget rowDescription(String title, String value, {Color? color, FontWeight? fontWeight}) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(title,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(value,
|
||||||
|
style: TextStyle(
|
||||||
|
color: color ?? ColorPalette.slate800,
|
||||||
|
fontWeight: fontWeight ?? FontWeight.w600,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:cims_apps/application/assets/path_assets.dart';
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
import 'package:cims_apps/application/component/image/image_view.dart';
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/portfolio_detail_view.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
),
|
),
|
||||||
const Center(
|
const Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Portofolio',
|
'Portfolio',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
@@ -125,20 +126,22 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
const Text('Total Mutual Fund',
|
const Text(
|
||||||
|
'Total Mutual Fund',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
color: ColorPalette.slate400
|
color: ColorPalette.slate400),
|
||||||
),
|
),
|
||||||
),
|
Text(
|
||||||
Text(listInvestmentType.map((e) => e.mutualFunds).reduce((value, element) => value + element).toString(),
|
listInvestmentType
|
||||||
|
.map((e) => e.mutualFunds)
|
||||||
|
.reduce(
|
||||||
|
(value, element) => value + element)
|
||||||
|
.toString(),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 44,
|
fontSize: 44,
|
||||||
fontWeight: FontWeight.w700
|
fontWeight: FontWeight.w700)),
|
||||||
)
|
|
||||||
)
|
|
||||||
,
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
@@ -147,9 +150,31 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
),
|
),
|
||||||
menuPortofolio(),
|
menuPortofolio(),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 24,
|
height: 12,
|
||||||
),
|
),
|
||||||
...listColumnPortofolio(),
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: 'My Portfolio', fontSize: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.add, size: 18, color: ColorPalette.primary),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
const Text('Create',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// ...listColumnPortofolio(),
|
||||||
|
cardPortfolio()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -168,7 +193,7 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Text('Portofolio Value',
|
const Text('Portfolio Value',
|
||||||
style: TextStyle(color: Colors.white)),
|
style: TextStyle(color: Colors.white)),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 8,
|
width: 8,
|
||||||
@@ -179,8 +204,12 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
seePortofolioValue = !seePortofolioValue;
|
seePortofolioValue = !seePortofolioValue;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.visibility_outlined,
|
child: Icon(
|
||||||
color: Color(0xff93C5FD)))
|
seePortofolioValue
|
||||||
|
? Icons.visibility_off_outlined
|
||||||
|
: Icons.visibility_outlined,
|
||||||
|
size: 18,
|
||||||
|
color: const Color(0xff93C5FD)))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
@@ -197,7 +226,10 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
firstChild: RichText(
|
firstChild: RichText(
|
||||||
text: const TextSpan(
|
text: const TextSpan(
|
||||||
text: 'Rp ',
|
text: 'Rp ',
|
||||||
style: TextStyle(fontSize: 32, color: Color(0xff93C5FD), fontFamily: 'Manrope'),
|
style: TextStyle(
|
||||||
|
fontSize: 32,
|
||||||
|
color: Color(0xff93C5FD),
|
||||||
|
fontFamily: 'Manrope'),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '22.500.000',
|
text: '22.500.000',
|
||||||
@@ -205,8 +237,7 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
fontSize: 32,
|
fontSize: 32,
|
||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Colors.white
|
color: Colors.white),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
])),
|
])),
|
||||||
secondChild: Padding(
|
secondChild: Padding(
|
||||||
@@ -353,4 +384,85 @@ class _PortofolioViewState extends State<PortofolioView> {
|
|||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget cardPortfolio() {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context, page: const PortfolioDetailView());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorPalette.blue200.withOpacity(0.5),
|
||||||
|
borderRadius: BorderRadius.circular(8)
|
||||||
|
),
|
||||||
|
child: ImageView(
|
||||||
|
image: PathAssets.goalInvestIcon['Education'],
|
||||||
|
width: SizeConfig.width * 0.07
|
||||||
|
)
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: 'Education', fontSize: 16,),
|
||||||
|
Text('2 Subscriptions',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Divider(height: 1, color: ColorPalette.slate200),
|
||||||
|
),
|
||||||
|
const Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Portfolio Value',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14,)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text('Advantages',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextTitle(title: 'Rp 2.000.000', fontSize: 14)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,171 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/numeric_pad/numeric_pad.dart';
|
||||||
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ChangeAmount extends StatefulWidget {
|
||||||
|
final int totalAmount;
|
||||||
|
const ChangeAmount({super.key, required this.totalAmount});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChangeAmount> createState() => _ChangeAmountState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChangeAmountState extends State<ChangeAmount> {
|
||||||
|
TextEditingController amountController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// TODO: implement initState
|
||||||
|
super.initState();
|
||||||
|
amountController.text = NumberFormatter.numberCurrency(widget.totalAmount, 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
super.dispose();
|
||||||
|
amountController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_back_rounded)
|
||||||
|
),
|
||||||
|
const Text('Type amount',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.close_rounded)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(24),
|
||||||
|
child: cardProduct()
|
||||||
|
),
|
||||||
|
InputInvestmentView(
|
||||||
|
minimumPrice: (provider.getCurrentProduct.priceUnit! * 1).toInt(),
|
||||||
|
maximumPrice: (provider.getCurrentProduct.priceUnit! * provider.getCurrentProduct.totalUnit!).toInt(),
|
||||||
|
currentPrice: provider.getAmount!.toInt(),
|
||||||
|
nextMove: (value) {
|
||||||
|
String formatValueInput = value.replaceAll('Rp ', '').replaceAll('.', '');
|
||||||
|
provider.setAmount(double.parse(formatValueInput));
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16,)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct() {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Money Market' ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor['Money Market'],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/redeem_product.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ChangeDestinationAccount extends StatelessWidget {
|
||||||
|
const ChangeDestinationAccount({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Account> listAccount = [
|
||||||
|
Account('Muhamad Rosyidin', 'BRI', '902139012324'),
|
||||||
|
Account('Achmad Muhaimin', 'BCA', '21391283928')
|
||||||
|
];
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_back_rounded)
|
||||||
|
),
|
||||||
|
const Text('Change Destination Account',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 16,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.close_rounded)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
...listAccount.asMap().entries.map((e) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => provider.setSelectedAcc(e.value),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: e.key != 0 ? 16 : 0),
|
||||||
|
child: cardAccount(e.value, provider.selectedAccount?.number ?? provider.getCurrentAccount.number),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
GestureDetector(
|
||||||
|
child: const Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.add, size: 24, color: ColorPalette.primary),
|
||||||
|
SizedBox(width: 12,),
|
||||||
|
Text('New Bank',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Save',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
provider.setCurrentAcc(provider.selectedAccount!);
|
||||||
|
return const RedeemProduct();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardAccount(Account account, String numberSelected) {
|
||||||
|
List<String> listNumber = [];
|
||||||
|
|
||||||
|
List.generate(account.number.length, (index) {
|
||||||
|
if(index > 3 && index < account.number.length - 4){
|
||||||
|
listNumber.add('*');
|
||||||
|
}else{
|
||||||
|
listNumber.add(account.number[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(account.nameOwner,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${account.nameBank} - ${listNumber.join("")}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AnimatedContainer(
|
||||||
|
margin: const EdgeInsets.only(top: 4),
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
padding: const EdgeInsets.all(1),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color: numberSelected == account.number
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate200)),
|
||||||
|
child: AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color:
|
||||||
|
numberSelected == account.number ? ColorPalette.primary : ColorPalette.white,
|
||||||
|
shape: BoxShape.circle),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,360 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_amount.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/change_destination_account.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view/total_redeem.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class RedeemProduct extends StatefulWidget {
|
||||||
|
const RedeemProduct({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<RedeemProduct> createState() => _RedeemProductState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RedeemProductState extends State<RedeemProduct> {
|
||||||
|
TextEditingController amountController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
// TODO: implement initState
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
super.dispose();
|
||||||
|
amountController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
amountController.text = NumberFormatter.numberCurrency(provider.getAmount!.toInt(), 'Rp ', 'id_ID', decimalDigits: 0);
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Products to be Redeemed',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
cardProduct(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
segmentAmount(
|
||||||
|
context,
|
||||||
|
provider.getAmount!,
|
||||||
|
provider.getUnit!,
|
||||||
|
(value) {
|
||||||
|
provider.setUnit(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
segmentDestinationAcc(provider.getCurrentAccount),
|
||||||
|
const SizedBox(height: 36),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Redeem',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return TotalRedeem();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct() {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Gemilang Dana Kas Maxima', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(40),
|
||||||
|
color: ColorPalette.investTypeBgColor['Money Market']?.withOpacity(0.5) ?? Colors.white,
|
||||||
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor['Money Market']?.withOpacity(0.4) ?? Colors.white)
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Money Market' ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.investTypeColor['Money Market'],
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget segmentAmount(context, double currentAmount, double currentUnit, void Function(double value) setUnit) {
|
||||||
|
double sliderValue = currentUnit / Provider.of<RedeemProductViewModel>(context, listen: false).getCurrentProduct.totalUnit!;
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text('Amount',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
controller: amountController,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
enabledBorder: const UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: ColorPalette.slate200,
|
||||||
|
width: 1
|
||||||
|
),
|
||||||
|
),
|
||||||
|
suffixIcon: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return ChangeAmount(
|
||||||
|
totalAmount: currentAmount.toInt(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.edit, color: ColorPalette.primary),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text(' unit',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SliderTheme(
|
||||||
|
data: SliderTheme.of(context).copyWith(
|
||||||
|
trackHeight: 4.0,
|
||||||
|
thumbColor: ColorPalette.primary,
|
||||||
|
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10.0),
|
||||||
|
overlayColor:Colors.deepPurple,
|
||||||
|
inactiveTickMarkColor: ColorPalette.primary,
|
||||||
|
inactiveTrackColor: ColorPalette.slate200,
|
||||||
|
overlayShape: SliderComponentShape.noOverlay
|
||||||
|
),
|
||||||
|
child: Slider(
|
||||||
|
value: sliderValue,
|
||||||
|
onChanged: setUnit,
|
||||||
|
label: sliderValue.round().toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
|
Text('${(sliderValue * 100).toStringAsFixed(2)} %',
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w600
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget segmentDestinationAcc(Account account) {
|
||||||
|
List<String> listNumber = [];
|
||||||
|
|
||||||
|
List.generate(account.number.length, (index) {
|
||||||
|
if(index > 3 && index < account.number.length - 4){
|
||||||
|
listNumber.add('*');
|
||||||
|
}else{
|
||||||
|
listNumber.add(account.number[index]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Destination Account',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
border: Border.all(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(account.nameOwner,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('${account.nameBank} - ${listNumber.join("")}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) => const ChangeDestinationAccount(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(18),
|
||||||
|
color: ColorPalette.blue200.withOpacity(0.5)
|
||||||
|
),
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.change_circle_outlined, color: ColorPalette.primary, size: 20),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text('Change',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/radio_agreement.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/portfolio/redeem_product/view_model/redeem_product_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class TotalRedeem extends StatelessWidget {
|
||||||
|
const TotalRedeem({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => RedeemProductViewModel(),
|
||||||
|
child: Consumer<RedeemProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Investment Funds that You Cash Out',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => Navigator.pop(context),
|
||||||
|
child: const Icon(Icons.close_rounded, color: ColorPalette.slate800,)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1, color: ColorPalette.slate200,),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: cardProduct(provider.getCurrentProduct, provider.getUnit!),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Sales Commission',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Free',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text('Cash Out Method',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Regular',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontSize: 16
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16,),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
color: ColorPalette.slate200.withOpacity(0.5),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextTitle(
|
||||||
|
title: 'Estimated Funds Disbursed',
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
fontSize: 16,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
NumberFormatter.numberCurrency((provider.getCurrentProduct.priceUnit! * provider.getUnit!).toInt(), 'Rp ', 'id_ID', decimalDigits: 0),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RadioAgreement(
|
||||||
|
isAgree: provider.isAgree,
|
||||||
|
desc: 'I agree to the sale of the mutual funds listed on this page. I understand that the total funds disbursed are approximate. The amount received may change according to the closing price of the mutual fund on the day of sale.',
|
||||||
|
onTap: provider.setAgree
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
ButtonView(
|
||||||
|
disabled: !provider.isAgree,
|
||||||
|
name: 'Redeem',
|
||||||
|
textSize: 20,
|
||||||
|
marginVertical: 0,
|
||||||
|
disabledBgColor: ColorPalette.slate200.withOpacity(0.5),
|
||||||
|
textColor: !provider.isAgree ? ColorPalette.slate400 : Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return TotalRedeem();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget cardProduct(PortfolioProduct product, double currentUnit) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: ColorPalette.slate200),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: const Color(0xff1E293B).withOpacity(0.04),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .13,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextTitle(title: product.name ?? '', fontSize: 16,),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(currentUnit.toStringAsFixed(2).replaceAll('.', ','),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
|
color: ColorPalette.slate800
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Text(' unit',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate400
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Account {
|
||||||
|
String nameOwner, nameBank, number;
|
||||||
|
|
||||||
|
Account(this.nameOwner, this.nameBank, this.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PortfolioProduct {
|
||||||
|
String? name, type;
|
||||||
|
double? yield;
|
||||||
|
double? priceUnit, funds, totalPercent, totalUnit;
|
||||||
|
|
||||||
|
PortfolioProduct({this.name, this.type, this.yield, this.priceUnit, this.funds, this.totalPercent = 1, this.totalUnit});
|
||||||
|
}
|
||||||
|
|
||||||
|
class RedeemProductViewModel extends ChangeNotifier {
|
||||||
|
static Account currentAccount = Account('Muhamad Rosyidin', 'BRI', '902139012324');
|
||||||
|
static PortfolioProduct currentProduct =
|
||||||
|
PortfolioProduct(
|
||||||
|
name: 'Gemilang Dana Kas Maxima',
|
||||||
|
type: '',
|
||||||
|
yield: 8.17,
|
||||||
|
priceUnit: 2600.79,
|
||||||
|
funds: 6300000,
|
||||||
|
totalUnit: 25
|
||||||
|
);
|
||||||
|
|
||||||
|
static double? amount;
|
||||||
|
static double? unit;
|
||||||
|
Account? selectedAccount;
|
||||||
|
|
||||||
|
Account get getCurrentAccount => currentAccount;
|
||||||
|
PortfolioProduct get getCurrentProduct => currentProduct;
|
||||||
|
double? get getAmount => amount;
|
||||||
|
double? get getUnit => unit;
|
||||||
|
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
|
void setCurrentAcc(Account account) {
|
||||||
|
currentAccount = account;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSelectedAcc(Account account){
|
||||||
|
selectedAccount = account;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAmount(double amount) {
|
||||||
|
amount = amount;
|
||||||
|
unit = (amount / currentProduct.priceUnit!);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUnit(double value){
|
||||||
|
unit = currentProduct.totalUnit! * value;
|
||||||
|
amount = unit! * currentProduct.priceUnit!;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setProduct(PortfolioProduct product) {
|
||||||
|
currentProduct = product;
|
||||||
|
amount = product.priceUnit! * (product.totalUnit! / 2.0);
|
||||||
|
unit = (product.totalUnit! / 2.0);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,8 +24,9 @@ class Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProductView extends StatefulWidget {
|
class ProductView extends StatefulWidget {
|
||||||
final String investType;
|
final bool seeMore;
|
||||||
const ProductView(this.investType, {super.key});
|
final Product selectedProduct;
|
||||||
|
const ProductView({super.key, required this.selectedProduct, this.seeMore = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProductView> createState() => _ProductViewState();
|
State<ProductView> createState() => _ProductViewState();
|
||||||
@@ -144,7 +145,8 @@ class _ProductViewState extends State<ProductView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomNavigationBar: Container(
|
bottomNavigationBar: !widget.seeMore ?
|
||||||
|
Container(
|
||||||
height: SizeConfig.height * .1,
|
height: SizeConfig.height * .1,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
child: ButtonView(
|
child: ButtonView(
|
||||||
@@ -159,7 +161,7 @@ class _ProductViewState extends State<ProductView> {
|
|||||||
height: SizeConfig.height * 0.06,
|
height: SizeConfig.height * 0.06,
|
||||||
marginVertical: 16,
|
marginVertical: 16,
|
||||||
),
|
),
|
||||||
),
|
) : SizedBox(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -177,7 +179,7 @@ class _ProductViewState extends State<ProductView> {
|
|||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Gemilang Dana Kas Maxima',
|
widget.selectedProduct.name ?? '',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -190,17 +192,18 @@ class _ProductViewState extends State<ProductView> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 12),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(6),
|
padding: const EdgeInsets.all(6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(40),
|
borderRadius: BorderRadius.circular(40),
|
||||||
color: ColorPalette.investTypeBgColor[widget.investType] ?? Colors.white,
|
color: ColorPalette.investTypeBgColor[widget.selectedProduct.type] ?? Colors.white,
|
||||||
border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.investType] ?? Colors.white)
|
border: Border.all(width: 2, color: ColorPalette.investTypeColor[widget.selectedProduct.type] ?? Colors.white)
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.investType,
|
widget.selectedProduct.type ?? '',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ColorPalette.investTypeColor[widget.investType],
|
color: ColorPalette.investTypeColor[widget.selectedProduct.type],
|
||||||
fontWeight: FontWeight.w600
|
fontWeight: FontWeight.w600
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:cims_apps/application/component/subscribe/goal_investing_view.da
|
|||||||
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/input_investment_view.dart';
|
||||||
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
import 'package:cims_apps/application/component/subscribe/total_payment_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/plan/view_model/plan_view_model.dart';
|
||||||
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_account/view/product/view_model/product_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -11,10 +12,9 @@ class SelectGoalInvesting extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiProvider(
|
|
||||||
providers: [
|
return ChangeNotifierProvider(
|
||||||
ChangeNotifierProvider(create: (context) => ProductViewModel(),)
|
create: (context) => ProductViewModel(),
|
||||||
],
|
|
||||||
child: Consumer<ProductViewModel>(
|
child: Consumer<ProductViewModel>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
return Container(
|
return Container(
|
||||||
@@ -51,23 +51,50 @@ class SelectGoalInvesting extends StatelessWidget {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return InputInvestmentView(
|
return ChangeNotifierProvider(
|
||||||
selectedPlan: p0,
|
create: (context) => ProductViewModel(),
|
||||||
|
child: Consumer<ProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: InputInvestmentView(
|
||||||
|
currentPlan: p0,
|
||||||
|
changePlan: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) => SelectGoalInvesting(),
|
||||||
|
);
|
||||||
|
},
|
||||||
nextMove: (value) {
|
nextMove: (value) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll(',', ''));
|
int formatIntParse = int.parse(value.replaceAll('Rp ', '').replaceAll('.', ''));
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
TotalPaymentView(
|
ChangeNotifierProvider(
|
||||||
|
create: (context) => ProductViewModel(),
|
||||||
|
child: Consumer<ProductViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return TotalPaymentView(
|
||||||
listProduct: [
|
listProduct: [
|
||||||
provider.getSelectedProduct
|
provider.getSelectedProduct
|
||||||
],
|
],
|
||||||
totalInvest: formatIntParse,
|
totalInvest: formatIntParse,
|
||||||
|
isAgree: provider.isAgree,
|
||||||
|
onTapAgree: provider.setAgree,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class ProductViewModel extends ChangeNotifier {
|
|||||||
Product get getSelectedProduct => selectedProduct;
|
Product get getSelectedProduct => selectedProduct;
|
||||||
|
|
||||||
double totalInvestment = 0;
|
double totalInvestment = 0;
|
||||||
|
bool isAgree = false;
|
||||||
|
|
||||||
void setSelectedProduct(Product product) {
|
void setSelectedProduct(Product product) {
|
||||||
selectedProduct = product;
|
selectedProduct = product;
|
||||||
@@ -24,4 +25,9 @@ class ProductViewModel extends ChangeNotifier {
|
|||||||
totalInvestment = value;
|
totalInvestment = value;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setAgree() {
|
||||||
|
isAgree = !isAgree;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class LoginGmailModel {
|
||||||
|
String idToken;
|
||||||
|
String accessToken;
|
||||||
|
|
||||||
|
LoginGmailModel({
|
||||||
|
required this.idToken,
|
||||||
|
required this.accessToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
Map<String, String> toJson() => {
|
||||||
|
"idToken": idToken,
|
||||||
|
"accessToken": accessToken,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -6,8 +6,9 @@ import 'package:cims_apps/core/route/route.dart';
|
|||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:cims_apps/features/auth/login/view/login_view.dart';
|
import 'package:cims_apps/features/auth/login/view/login_view.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
||||||
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
import 'package:cims_apps/features/dashboard/dashboard_public/viewmodel/dashboard_public_viewmodel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class DashboardPublicView extends StatelessWidget {
|
class DashboardPublicView extends StatelessWidget {
|
||||||
static const routeName = '/DashboardPublicView';
|
static const routeName = '/DashboardPublicView';
|
||||||
@@ -37,16 +38,23 @@ class DashboardPublicView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => DashboardPublicViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Container(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.only(
|
||||||
vertical: 32.0,
|
bottom: 8.0,
|
||||||
horizontal: 24.0,
|
left: 24.0,
|
||||||
|
right: 24.0,
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Consumer<DashboardPublicViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
SizedBox(height: SizeConfig.height * .06),
|
||||||
ImageView(
|
ImageView(
|
||||||
image: PathAssets.icon1,
|
image: PathAssets.icon1,
|
||||||
width: SizeConfig.width * .35,
|
width: SizeConfig.width * .35,
|
||||||
@@ -59,7 +67,7 @@ class DashboardPublicView extends StatelessWidget {
|
|||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: ImageView(
|
child: ImageView(
|
||||||
image: PathAssets.imgDashboard,
|
image: PathAssets.imgDashboard,
|
||||||
width: SizeConfig.width * .7,
|
width: SizeConfig.width * .8,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
@@ -93,8 +101,11 @@ class DashboardPublicView extends StatelessWidget {
|
|||||||
image: PathAssets.iconGoogle,
|
image: PathAssets.iconGoogle,
|
||||||
width: 26,
|
width: 26,
|
||||||
),
|
),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
provider.loginGoogle(context);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
SizedBox(height: SizeConfig.height * .1),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@@ -113,8 +124,10 @@ class DashboardPublicView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/features/auth/registration/view/initial_registration_step.dart';
|
||||||
|
import 'package:cims_apps/features/dashboard/dashboard_public/model/login_gmail_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_sign_in/google_sign_in.dart';
|
||||||
|
|
||||||
|
class DashboardPublicViewModel extends ChangeNotifier {
|
||||||
|
String emailGoogle = '';
|
||||||
|
final GoogleSignIn googleSignIn = GoogleSignIn(
|
||||||
|
scopes: [
|
||||||
|
'email',
|
||||||
|
'https://www.googleapis.com/auth/contacts.readonly',
|
||||||
|
],
|
||||||
|
);
|
||||||
|
Future<LoginGmailModel?> _getGmail() async {
|
||||||
|
LoginGmailModel? loginGmailModel;
|
||||||
|
try {
|
||||||
|
final signInResult = await googleSignIn.signIn();
|
||||||
|
if (signInResult != null) {
|
||||||
|
emailGoogle = signInResult.email;
|
||||||
|
final signInAuth = await signInResult.authentication;
|
||||||
|
final accessToken = signInAuth.accessToken;
|
||||||
|
final idToken = signInAuth.idToken;
|
||||||
|
if (idToken != null && accessToken != null) {
|
||||||
|
loginGmailModel = LoginGmailModel(
|
||||||
|
accessToken: accessToken,
|
||||||
|
idToken: idToken,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('catch error $e');
|
||||||
|
}
|
||||||
|
return loginGmailModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> loginGoogle(BuildContext context) async {
|
||||||
|
bool loginSuccess = false;
|
||||||
|
loginSuccess = await _getGmail().then((payload) async {
|
||||||
|
bool result = false;
|
||||||
|
if (payload != null) {
|
||||||
|
debugPrint('objectzz ${payload.toJson()}');
|
||||||
|
routePush(context, page: InitialRegistrationStep());
|
||||||
|
googleSignIn.disconnect();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
return loginSuccess;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
lib/features/profile/model/list_menu_model.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ListMenuModel {
|
||||||
|
final String title, pathAsset;
|
||||||
|
final Widget page;
|
||||||
|
ListMenuModel(
|
||||||
|
{required this.title, required this.pathAsset, required this.page});
|
||||||
|
}
|
||||||
119
lib/features/profile/view/profile_view.dart
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/profile/model/list_menu_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ProfileView extends StatelessWidget {
|
||||||
|
const ProfileView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<ListMenuModel> listMenuGeneral = [
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Personal Data',
|
||||||
|
pathAsset: PathAssets.iconProfile,
|
||||||
|
page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Change Password',
|
||||||
|
pathAsset: PathAssets.iconLock,
|
||||||
|
page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Add Card', pathAsset: PathAssets.iconCard, page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Settings',
|
||||||
|
pathAsset: PathAssets.iconSetting,
|
||||||
|
page: Container()),
|
||||||
|
];
|
||||||
|
|
||||||
|
List<ListMenuModel> listMenuPreferences = [
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'FAQs', pathAsset: PathAssets.iconChat, page: Container()),
|
||||||
|
ListMenuModel(
|
||||||
|
title: 'Log Out',
|
||||||
|
pathAsset: PathAssets.iconLogout,
|
||||||
|
page: Container()),
|
||||||
|
];
|
||||||
|
TextStyle textStyle = const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget cardContent(
|
||||||
|
{required String title, required List<ListMenuModel> listMenu}) {
|
||||||
|
return Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12))),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(title),
|
||||||
|
...listMenu.map((e) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(e.title),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: ImageView(
|
||||||
|
image: e.pathAsset, width: SizeConfig.width * .08),
|
||||||
|
trailing: const Icon(Icons.arrow_forward_ios,
|
||||||
|
color: ColorPalette.slate400),
|
||||||
|
onTap: () {
|
||||||
|
// routePush(context, page: e.page);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: null,
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
ImageView(image: PathAssets.bgProfile, width: SizeConfig.width),
|
||||||
|
Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.only(top: 40.0, left: 16.0, right: 16.0),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.only(bottom: 60.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('Profile', style: textStyle),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 40.0, bottom: 8.0),
|
||||||
|
child: ImageView(
|
||||||
|
image: PathAssets.imgCatOutlined,
|
||||||
|
width: SizeConfig.width * .28,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text('Muhamad Rosyidin',
|
||||||
|
style: textStyle.copyWith(fontSize: 24)),
|
||||||
|
Text('Investor Conservative',
|
||||||
|
style: textStyle.copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: ColorPalette.green400,
|
||||||
|
)),
|
||||||
|
SizedBox(height: SizeConfig.height * .02),
|
||||||
|
cardContent(title: 'General', listMenu: listMenuGeneral),
|
||||||
|
SizedBox(height: SizeConfig.height * .03),
|
||||||
|
cardContent(
|
||||||
|
title: 'Preference', listMenu: listMenuPreferences),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
lib/features/transaction/view/cancel_view.dart
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class CancelView extends StatelessWidget {
|
||||||
|
const CancelView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Consumer<TransactionViewModel>(
|
||||||
|
builder: (context, provider, child) => Column(
|
||||||
|
children: [
|
||||||
|
if (provider.listCancelTransaction.isEmpty)
|
||||||
|
EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
...provider.listCancelTransaction.map((e) {
|
||||||
|
return CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconEducation,
|
||||||
|
type: 'Education',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'cancel',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
lib/features/transaction/view/done_view.dart
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class DoneView extends StatelessWidget {
|
||||||
|
const DoneView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Consumer<TransactionViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
if (provider.listDoneTransaction.isEmpty)
|
||||||
|
EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
...provider.listDoneTransaction.map((e) {
|
||||||
|
return CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconEducation,
|
||||||
|
type: 'Education',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'done',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
lib/features/transaction/view/onprocess_view.dart
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class OnProcessView extends StatelessWidget {
|
||||||
|
const OnProcessView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child:
|
||||||
|
Consumer<TransactionViewModel>(builder: (context, provider, child) {
|
||||||
|
return Column(children: [
|
||||||
|
if (provider.listOnProcessTransaction.isEmpty)
|
||||||
|
EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
...provider.listOnProcessTransaction.map((e) {
|
||||||
|
return CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'virtual',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconHome,
|
||||||
|
type: 'Home',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'on process',
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
516
lib/features/transaction/view/subscribe_detail_view.dart
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/back_button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/list_tile/list_tile_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SubscribeDetailView extends StatelessWidget {
|
||||||
|
final String type;
|
||||||
|
const SubscribeDetailView({Key? key, required this.type}) : super(key: key);
|
||||||
|
|
||||||
|
Widget _stepper(
|
||||||
|
TextTheme textTheme, {
|
||||||
|
required String description,
|
||||||
|
String? date,
|
||||||
|
time,
|
||||||
|
bool isActive = false,
|
||||||
|
bool isDone = false,
|
||||||
|
bool isLast = false,
|
||||||
|
}) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0, left: 16.0),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 2.0, top: 8.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle_rounded,
|
||||||
|
size: 10,
|
||||||
|
color: isDone
|
||||||
|
? ColorPalette.primary
|
||||||
|
: isActive
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!isLast)
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints.expand(
|
||||||
|
height: SizeConfig.width * .2, width: 0.0),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
||||||
|
child: VerticalDivider(
|
||||||
|
color:
|
||||||
|
isDone ? ColorPalette.primary : ColorPalette.slate400,
|
||||||
|
thickness: 2.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
description,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: isDone
|
||||||
|
? Colors.black87
|
||||||
|
: isActive
|
||||||
|
? ColorPalette.primary
|
||||||
|
: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
isDone
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Text(date ?? ''),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 4.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.circle,
|
||||||
|
size: 6,
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(time ?? ''),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _listProduct(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .1,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Gemilang Dana Kas Maxima',
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8.0, vertical: 2.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorPalette.purple100,
|
||||||
|
border: Border.all(
|
||||||
|
width: 1,
|
||||||
|
color: ColorPalette.purple,
|
||||||
|
),
|
||||||
|
borderRadius:
|
||||||
|
const BorderRadius.all(Radius.circular(24)),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'Money Market',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.purple500,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
const Text('Investment Amount'),
|
||||||
|
Text(
|
||||||
|
'Rp 2.000.000',
|
||||||
|
style: textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorPalette.slate200,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _cardVA(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.only(top: 16.0, bottom: 8.0),
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(height: SizeConfig.height * .02),
|
||||||
|
RichText(
|
||||||
|
text: const TextSpan(children: [
|
||||||
|
TextSpan(
|
||||||
|
text: 'Transfer to ',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate400,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: 'ABC Virtual Account',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
SizedBox(height: SizeConfig.height * .01),
|
||||||
|
const Text(
|
||||||
|
'Ferdy Maulana',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTileView(
|
||||||
|
title: '8785 0000 3165 5512',
|
||||||
|
prefixIcon: const SizedBox(),
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
margin: const EdgeInsets.only(top: 8.0, bottom: 8.0),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: ColorPalette.primary),
|
||||||
|
suffixIcon: ButtonView(
|
||||||
|
name: 'Copy',
|
||||||
|
width: SizeConfig.width * .3,
|
||||||
|
height: SizeConfig.height * .052,
|
||||||
|
sizeBorderRadius: 8.0,
|
||||||
|
widthPrefix: 8.0,
|
||||||
|
marginVertical: 10.0,
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.file_copy_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
StringUtils.iCopyToClipboard(
|
||||||
|
context,
|
||||||
|
text: '8785 0000 3165 5512',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(color: ColorPalette.slate200),
|
||||||
|
const Text(
|
||||||
|
'Amount to be transferred',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black87,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTileView(
|
||||||
|
title: 'Rp 10.000.000',
|
||||||
|
prefixIcon: const SizedBox(),
|
||||||
|
padding: const EdgeInsets.only(right: 16.0),
|
||||||
|
margin: const EdgeInsets.only(top: 8.0),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: ColorPalette.primary),
|
||||||
|
suffixIcon: ButtonView(
|
||||||
|
name: 'Copy',
|
||||||
|
width: SizeConfig.width * .3,
|
||||||
|
height: SizeConfig.height * .052,
|
||||||
|
sizeBorderRadius: 8.0,
|
||||||
|
widthPrefix: 8.0,
|
||||||
|
marginVertical: 10.0,
|
||||||
|
prefixIcon: const Icon(
|
||||||
|
Icons.file_copy_outlined,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
StringUtils.iCopyToClipboard(
|
||||||
|
context,
|
||||||
|
text: '10.000.000',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _cardContent(BuildContext context) {
|
||||||
|
TextTheme textTheme = Theme.of(context).textTheme;
|
||||||
|
List mySteps = const [
|
||||||
|
{
|
||||||
|
'desc': 'Payment Being Verified',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': true,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Successful Payment',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': true,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Investment Manager Verification',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'desc': 'Successful Purchase',
|
||||||
|
'date': '07 Feb 2024 ',
|
||||||
|
'time': '21:01',
|
||||||
|
'isActive': false,
|
||||||
|
'isDone': false,
|
||||||
|
'isLast': true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.access_time, color: ColorPalette.slate400),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
|
child: Text('Waiting for Payment'),
|
||||||
|
),
|
||||||
|
Text('23:56:42', style: textTheme.headlineSmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
type == 'virtual' ? _cardVA(context) : const SizedBox(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
child: Text('Purchase Details', style: textTheme.headlineSmall),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: ExpansionTile(
|
||||||
|
shape: ShapeBorder.lerp(
|
||||||
|
const StadiumBorder(side: BorderSide.none),
|
||||||
|
InputBorder.none,
|
||||||
|
0),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.iconEducation,
|
||||||
|
width: SizeConfig.width * .08,
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 8.0),
|
||||||
|
child: Text('Education'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
subtitle: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 40.0),
|
||||||
|
child: Text('3 Subscriptions', style: textTheme.bodyMedium),
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
_listProduct(context),
|
||||||
|
_listProduct(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...mySteps.map((e) {
|
||||||
|
return _stepper(
|
||||||
|
textTheme,
|
||||||
|
description: '${e['desc']}',
|
||||||
|
date: e['date'],
|
||||||
|
time: e['time'],
|
||||||
|
isActive: e['isActive'],
|
||||||
|
isDone: e['isDone'],
|
||||||
|
isLast: e['isLast'],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
// padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
border: Border.all(width: 1, color: ColorPalette.slate200),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: ExpansionTile(
|
||||||
|
shape: ShapeBorder.lerp(
|
||||||
|
const StadiumBorder(side: BorderSide.none),
|
||||||
|
InputBorder.none,
|
||||||
|
0),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(
|
||||||
|
child: Text('When Is My Purchase Complete?')),
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgExpandPurchase,
|
||||||
|
width: SizeConfig.width * .15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: SizedBox(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(height: SizeConfig.height * .05),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
BackButtonView(
|
||||||
|
onPress: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 80.0),
|
||||||
|
child: Text(
|
||||||
|
'Subscribe Detail',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
type == 'virtual'
|
||||||
|
? const Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 8.0),
|
||||||
|
child: Text(
|
||||||
|
'Virtual Account',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.imgProduct,
|
||||||
|
width: SizeConfig.width * .08,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
|
child: Text(
|
||||||
|
type == 'virtual' ? 'ABC' : 'Shopping Pay',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(top: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'No.Subscribe : ',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'PI9393084SDMI1',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(top: 32.0),
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(24),
|
||||||
|
topRight: Radius.circular(24)),
|
||||||
|
),
|
||||||
|
child: _cardContent(context)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
124
lib/features/transaction/view/transaction_view.dart
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/cancel_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/done_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/onprocess_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/waiting_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_toggle_tab/flutter_toggle_tab.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class TransactionView extends StatelessWidget {
|
||||||
|
const TransactionView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Tab> textTabs = const [
|
||||||
|
Tab(text: 'Waiting'),
|
||||||
|
Tab(text: 'On process'),
|
||||||
|
Tab(text: 'Done'),
|
||||||
|
Tab(text: 'Cancel'),
|
||||||
|
];
|
||||||
|
List<Widget> listTabBarView = const [
|
||||||
|
WaitingView(),
|
||||||
|
OnProcessView(),
|
||||||
|
DoneView(),
|
||||||
|
CancelView(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => TransactionViewModel(),
|
||||||
|
builder: (context, child) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: ColorPalette.primary,
|
||||||
|
body: SizedBox(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
const ImageView(image: PathAssets.imgDashboardAccount),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: SizeConfig.height * .05,
|
||||||
|
),
|
||||||
|
const Center(
|
||||||
|
child: Text(
|
||||||
|
'Transaction',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: SizeConfig.height * .04,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: FlutterToggleTab(
|
||||||
|
height: SizeConfig.height * .065,
|
||||||
|
width: SizeConfig.width * .2,
|
||||||
|
marginSelected: const EdgeInsets.all(8.0),
|
||||||
|
isScroll: false,
|
||||||
|
selectedTextStyle: const TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
unSelectedTextStyle: const TextStyle(
|
||||||
|
color: ColorPalette.blackFont,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
unSelectedBackgroundColors: const [
|
||||||
|
ColorPalette.blue50
|
||||||
|
],
|
||||||
|
selectedBackgroundColors: const [ColorPalette.white],
|
||||||
|
labels: const ['Subscribe', 'Reedem'],
|
||||||
|
selectedLabelIndex: (p0) {},
|
||||||
|
selectedIndex: 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: DefaultTabController(
|
||||||
|
length: textTabs.length,
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(top: 24),
|
||||||
|
padding: const EdgeInsets.only(top: 16.0),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(24),
|
||||||
|
topRight: Radius.circular(24)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TabBar(
|
||||||
|
tabs: textTabs,
|
||||||
|
indicatorColor: Colors.blueAccent,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16.0,
|
||||||
|
vertical: 4.0,
|
||||||
|
),
|
||||||
|
child: TabBarView(children: listTabBarView),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
49
lib/features/transaction/view/waiting_view.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/card_transaction_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/card_transaction/empty_card_transaction.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/number_formatter.dart';
|
||||||
|
import 'package:cims_apps/core/utils/string_utils.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/view/subscribe_detail_view.dart';
|
||||||
|
import 'package:cims_apps/features/transaction/viewmodel/transaction_viewmodel.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class WaitingView extends StatelessWidget {
|
||||||
|
const WaitingView({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child:
|
||||||
|
Consumer<TransactionViewModel>(builder: (context, provider, child) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
provider.listWaitingTransaction.isNotEmpty
|
||||||
|
? CardTransactionView(
|
||||||
|
onTap: () {
|
||||||
|
routePush(context,
|
||||||
|
page: const SubscribeDetailView(
|
||||||
|
type: 'normal',
|
||||||
|
));
|
||||||
|
},
|
||||||
|
iconPath: PathAssets.iconEducation,
|
||||||
|
type: 'Education',
|
||||||
|
amount: NumberFormatter.numberCurrency(
|
||||||
|
6000000,
|
||||||
|
'Rp ',
|
||||||
|
'id_ID',
|
||||||
|
decimalDigits: 0,
|
||||||
|
),
|
||||||
|
timeTransaction: StringUtils.formatTime(DateTime.now()),
|
||||||
|
subs: '3 Subscription',
|
||||||
|
step: 'waiting')
|
||||||
|
: EmptyCardTransaction(
|
||||||
|
onPressedButton: () {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class TransactionViewModel extends ChangeNotifier {
|
||||||
|
List listWaitingTransaction = [1];
|
||||||
|
List listOnProcessTransaction = [1];
|
||||||
|
List listDoneTransaction = [];
|
||||||
|
List listCancelTransaction = [];
|
||||||
|
}
|
||||||
@@ -33,16 +33,51 @@ class MyApp extends StatelessWidget {
|
|||||||
)),
|
)),
|
||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
scaffoldBackgroundColor: Colors.white,
|
scaffoldBackgroundColor: Colors.white,
|
||||||
|
textTheme: const TextTheme(
|
||||||
|
displaySmall: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
displayMedium: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
displayLarge: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
bodyMedium: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
bodyLarge: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
headlineSmall: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
headlineLarge: TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
),
|
||||||
colorScheme: const ColorScheme.light().copyWith(
|
colorScheme: const ColorScheme.light().copyWith(
|
||||||
primary: const Color(0xff2563EB),
|
primary: const Color(0xff2563EB),
|
||||||
onPrimary: const Color(0xFFFF9130),
|
onPrimary: const Color(0xFFFF9130),
|
||||||
secondary: const Color(0xFFFECDA6),
|
secondary: const Color(0xFFFECDA6),
|
||||||
onBackground: const Color(0xFFA9A9A9),
|
onBackground: const Color(0xFFA9A9A9),
|
||||||
),
|
),
|
||||||
bottomSheetTheme: BottomSheetThemeData(
|
bottomSheetTheme: const BottomSheetThemeData(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white, surfaceTintColor: Colors.white)
|
||||||
surfaceTintColor: Colors.white
|
|
||||||
)
|
|
||||||
// useMaterial3: true,
|
// useMaterial3: true,
|
||||||
),
|
),
|
||||||
initialRoute: initialRoute,
|
initialRoute: initialRoute,
|
||||||
|
|||||||
142
pubspec.lock
@@ -49,6 +49,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
|
calendar_date_picker2:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: calendar_date_picker2
|
||||||
|
sha256: b91d51b8d0928f9745e0113e86d06b161ac48c52b7530337a3b77283cbc6be27
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.3"
|
||||||
camera:
|
camera:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -153,6 +161,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.6"
|
version: "1.0.6"
|
||||||
|
dotted_border:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dotted_border
|
||||||
|
sha256: "108837e11848ca776c53b30bc870086f84b62ed6e01c503ed976e8f8c7df9c04"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -243,11 +259,67 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_toggle_tab:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_toggle_tab
|
||||||
|
sha256: "90ad0d050f656df677998825f985637d010117a1793828cd7e6dadada4ecd2c5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.1"
|
||||||
flutter_web_plugins:
|
flutter_web_plugins:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
google_identity_services_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_identity_services_web
|
||||||
|
sha256: "0c56c2c5d60d6dfaf9725f5ad4699f04749fb196ee5a70487a46ef184837ccf6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.0+2"
|
||||||
|
google_sign_in:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_sign_in
|
||||||
|
sha256: "0b8787cb9c1a68ad398e8010e8c8766bfa33556d2ab97c439fb4137756d7308f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.2.1"
|
||||||
|
google_sign_in_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_sign_in_android
|
||||||
|
sha256: bfd42c81c30c6faba16e0f62968d5505a87504aaa672b3155ee931461abb0a49
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "6.1.21"
|
||||||
|
google_sign_in_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_sign_in_ios
|
||||||
|
sha256: f3336d9e44d4d28063ac90271f6db5caf99f0480cb07281330e7a432edb95226
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.7.3"
|
||||||
|
google_sign_in_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_sign_in_platform_interface
|
||||||
|
sha256: "1f6e5787d7a120cc0359ddf315c92309069171306242e181c09472d1b00a2971"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.4.5"
|
||||||
|
google_sign_in_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_sign_in_web
|
||||||
|
sha256: a278ea2d01013faf341cbb093da880d0f2a552bbd1cb6ee90b5bebac9ba69d77
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.3+2"
|
||||||
group_button:
|
group_button:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -284,10 +356,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b"
|
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.0"
|
version: "0.7.1"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -480,6 +552,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.27.7"
|
version: "0.27.7"
|
||||||
|
shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: shared_preferences
|
||||||
|
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
shared_preferences_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_foundation
|
||||||
|
sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.5"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
shared_preferences_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_windows
|
||||||
|
sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -561,18 +689,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: syncfusion_flutter_core
|
name: syncfusion_flutter_core
|
||||||
sha256: e8580e201c7197feac830b501889e877796a9fabbe20dcdbe90a981603939101
|
sha256: "9f98e2726af42967497eaef68f3373261700bbfcd33bd97da4ec85cb56fcdaf7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "24.2.4"
|
version: "24.2.7"
|
||||||
syncfusion_flutter_signaturepad:
|
syncfusion_flutter_signaturepad:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: syncfusion_flutter_signaturepad
|
name: syncfusion_flutter_signaturepad
|
||||||
sha256: "878e1063b909a83c83677627261780d42d532d0b5e7e259d84da805008e7fb0d"
|
sha256: d51d5e346c70b938a8e1f2318a073213172aea7b99e33073c379657b1066c001
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "24.2.4"
|
version: "24.2.7"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -663,4 +791,4 @@ packages:
|
|||||||
version: "6.5.0"
|
version: "6.5.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.2.3 <4.0.0"
|
dart: ">=3.2.3 <4.0.0"
|
||||||
flutter: ">=3.13.0"
|
flutter: ">=3.16.0"
|
||||||
|
|||||||