feat: profile page

This commit is contained in:
Prajna Prayoga 2024-02-29 17:14:05 +07:00
parent d1adfd2ab0
commit eb99ad9d7f
18 changed files with 220 additions and 27 deletions

BIN
assets/icons/icon-card.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/icons/icon-cat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
assets/icons/icon-faqs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

@ -55,6 +55,13 @@ class PathAssets {
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 iconCat = 'assets/icons/icon-cat.png';
static const String iconProfile = 'assets/icons/icon-profile.png';
static const String iconPadlock = 'assets/icons/icon-padlock.png';
static const String iconCard = 'assets/icons/icon-card.png';
static const String iconSetting = 'assets/icons/icon-setting.png';
static const String iconFaqs = 'assets/icons/icon-faqs.png';
static const String iconLogout = 'assets/icons/icon-logout.png';
/// IMAGE
static const String imgSplashLogo = 'assets/images/splash-logo.png';
@ -92,6 +99,8 @@ class PathAssets {
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 imgDashboardProfile =
'assets/images/img-dashboard-profile.png';
static const Map<String, String> goalInvestIcon = {
'Education': iconToga,

View File

@ -1,5 +1,3 @@
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';
@ -86,7 +84,7 @@ class NumericPad extends StatelessWidget {
}
Widget spaceWidget() {
return Expanded(
return const Expanded(
child: SizedBox()
);
}
@ -98,11 +96,12 @@ class NumericPad extends StatelessWidget {
onNumberSelected(number);
},
child: Container(
color: Colors.transparent,
padding: EdgeInsets.symmetric(vertical: SizeConfig.height * .028),
child: Text(
number,
textAlign: TextAlign.center,
style: TextStyle(
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: ColorPalette.slate800
@ -119,11 +118,15 @@ class NumericPad extends StatelessWidget {
onTap: () {
onNumberSelected('');
},
child: Icon(
child: Container(
color: Colors.transparent,
padding: EdgeInsets.symmetric(vertical: SizeConfig.height * .028),
child: const Icon(
Icons.backspace_outlined,
size: 28,
color: ColorPalette.slate800,
),
),
)
);
}

View File

@ -5,17 +5,20 @@ class TextTitle extends StatelessWidget {
final String title;
final Color? color;
final double? fontSize;
final TextAlign? textAlign;
const TextTitle({
Key? key,
required this.title,
this.color,
this.fontSize,
this.textAlign,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
title,
textAlign: textAlign,
style: TextStyle(
fontSize: fontSize ?? 20,
fontWeight: FontWeight.w700,

View File

@ -75,6 +75,7 @@ class ColorPalette {
static const Color backgroundBlueLight = Color(0xFFEBF3FD);
static const Color blue50 = Color(0xFFEFF6FF);
static const Color blue200 = Color(0xFFBFDBFE);
static const Color blue600 = Color(0xFF2563EB);
static const Color blue900 = Color(0xFF1E3A8A);
static const Color slate50 = Color(0xFFF8FAFC);
static const Color slate200 = Color(0xFFE2E8F0);
@ -90,9 +91,11 @@ class ColorPalette {
static const Color cyan100 = Color(0xFFCFFAFE);
static const Color cyan500 = Color(0xFF06B6D4);
static const Color green100 = Color(0xFFDCFCE7);
static const Color green300 = Color(0xFF86EFAC);
static const Color green400 = Color(0xFF4ADE80);
static const Color green500 = Color(0xFF16A34A);
static const Color red600 = Color(0xffDC2626);
static const Color red600 = Color(0xFFDC2626);
static const Color red50 = Color(0xFFFEF2F2);
static const Map<String, Color> investTypeColor = {
'Money Market': purple500,
@ -107,4 +110,16 @@ class ColorPalette {
'Sharia': green100,
'Bonds': cyan100
};
static const Map<String, Color> riskColor = {
'Moderate': orange500,
'Conservative': green500,
'Aggressive': cyan500
};
static const Map<String, Color> textRiskColor = {
'Moderate': orange500,
'Conservative': green300,
'Aggressive': cyan500
};
}

View File

@ -4,7 +4,7 @@ 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/plan/view/plan_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/dashboard/dashboard_account/view/profile/view/profile_view.dart';
import 'package:cims_apps/features/transaction/view/transaction_view.dart';
import 'package:flutter/material.dart';

View File

@ -388,7 +388,7 @@ class _PortofolioViewState extends State<PortofolioView> {
Widget cardPortfolio() {
return GestureDetector(
onTap: () {
routePush(context, page: const PortfolioDetailView());
// routePush(context, page: const PortfolioDetailView());
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 24),

View File

@ -0,0 +1,165 @@
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/text_title/text_title.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/profile/view_model/profile_view_model.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class RouteNavigation {
String icon;
String title;
Widget destination;
RouteNavigation(this.icon, this.title, this.destination);
}
class ProfileView extends StatelessWidget {
const ProfileView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
List<RouteNavigation> listGeneral = [
RouteNavigation(PathAssets.iconProfile, 'Personal Data', Container()),
RouteNavigation(PathAssets.iconPadlock, 'Change Password', Container()),
RouteNavigation(PathAssets.iconCard, 'Add Card', Container()),
RouteNavigation(PathAssets.iconSetting, 'Settings', Container())
];
List<RouteNavigation> listPreferences = [
RouteNavigation(PathAssets.iconFaqs, 'FAQs', Container()),
RouteNavigation(PathAssets.iconLogout, 'Log Out', Container())
];
return Provider(
create: (context) => ProfileViewModel(),
child: Scaffold(
body: SizedBox(
width: SizeConfig.width,
height: SizeConfig.height,
child: Stack(
children: [
const Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: ImageView(image: PathAssets.imgDashboardProfile)
),
Consumer<ProfileViewModel>(
builder: (context, provider, child) {
return ListView(
padding: const EdgeInsets.all(0),
children: [
const SizedBox(
height: 50,
),
const Center(
child: TextTitle(title: 'Profile', color: Colors.white, fontSize: 20,)
),
SizedBox(
height: SizeConfig.height * 0.05,
),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
border: Border.all(color: ColorPalette.slate200, width: 1.5)
),
padding: const EdgeInsets.all(8),
child: ImageView(image: PathAssets.iconCat, width: SizeConfig.width * 0.14,),
),
const SizedBox(height: 16),
Center(
child: TextTitle(title: provider.getUser.name ?? '', color: Colors.white, fontSize: 24,)),
Text('Investor ${provider.getUser.risk}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: ColorPalette.textRiskColor[provider.getUser.risk]
),
),
const SizedBox(height: 24),
boxNavigation('General', listGeneral),
const SizedBox(height: 24),
boxNavigation('Preferences', listPreferences)
],
);
}
)
],
),
),
),
);
}
Widget boxNavigation(String title, List<RouteNavigation> list) {
return Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.symmetric(horizontal: 24),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: ColorPalette.slate400
),
),
const SizedBox(height: 16),
Wrap(
runSpacing: 16,
children: list.map((e) {
return rowNavigation(
e.icon,
e.title,
e.destination
);
}).toList(),
)
],
),
);
}
Widget rowNavigation(String icon, String text, Widget destination) {
bool isLogout = text == 'Log Out';
Color textColor = isLogout ? ColorPalette.red600 : ColorPalette.slate800;
Color bgLeadingColor = isLogout ? ColorPalette.red50 : ColorPalette.blue50;
Color iconColor = isLogout ? ColorPalette.red600 : ColorPalette.blue600;
return Row(
children: [
Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: bgLeadingColor
),
child: Image.asset(icon, width: SizeConfig.width * 0.05, color: iconColor)
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(text,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: textColor
),
),
),
),
const Icon(Icons.chevron_right_outlined, size: 28, color: ColorPalette.slate400)
],
);
}
}

View File

@ -0,0 +1,11 @@
class User {
String? name, risk;
User({this.name, this.risk});
}
class ProfileViewModel {
static final User _user = User(name: 'Muhammad Rosyidin', risk: 'Conservative');
User get getUser => _user;
}

View File

@ -44,7 +44,7 @@ class DashboardPublicView extends StatelessWidget {
return Scaffold(
body: SingleChildScrollView(
padding: const EdgeInsets.only(
bottom: 8.0,
bottom: 24.0,
left: 24.0,
right: 24.0,
),
@ -59,6 +59,7 @@ class DashboardPublicView extends StatelessWidget {
image: PathAssets.icon1,
width: SizeConfig.width * .35,
),
SizedBox(height: SizeConfig.height * .02),
Align(
alignment: Alignment.center,
heightFactor: 1,
@ -105,7 +106,7 @@ class DashboardPublicView extends StatelessWidget {
provider.loginGoogle(context);
},
),
SizedBox(height: SizeConfig.height * .1),
SizedBox(height: SizeConfig.height * .07),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [

View File

@ -1,14 +0,0 @@
import 'package:cims_apps/application/component/custom_app_bar/custom_app_bar.dart';
import 'package:cims_apps/core/utils/size_config.dart';
import 'package:flutter/material.dart';
class ProfileView extends StatelessWidget {
const ProfileView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(height: SizeConfig.height * .08, title: 'Profile'),
);
}
}