bayu/dev #15
| @@ -24,11 +24,10 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Container( | ||||
|     return SingleChildScrollView( | ||||
|       child: Container( | ||||
|         decoration: BoxDecoration( | ||||
|           color: Colors.white, | ||||
|           borderRadius: BorderRadius.circular(16) | ||||
|       ), | ||||
|             color: Colors.white, borderRadius: BorderRadius.circular(16)), | ||||
|         child: Column( | ||||
|           mainAxisSize: MainAxisSize.min, | ||||
|           children: [ | ||||
| @@ -37,56 +36,54 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|               child: Row( | ||||
|                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                 children: [ | ||||
|                 const Text('Your Investment Today', | ||||
|                   const Text( | ||||
|                     'Your Investment Today', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate800, | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                       fontSize: 16 | ||||
|                   ), | ||||
|                         fontSize: 16), | ||||
|                   ), | ||||
|                   GestureDetector( | ||||
|                       onTap: () => Navigator.pop(context), | ||||
|                     child: const Icon(Icons.close_rounded) | ||||
|                 ) | ||||
|                       child: const Icon(Icons.close_rounded)) | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|             ...widget.listProduct.asMap().entries.map((e) { | ||||
|               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( | ||||
|                     border: Border( | ||||
|                         left: BorderSide( | ||||
|                             width: 8, | ||||
|                         color: ColorPalette.investTypeColor[e.value.type]! | ||||
|                       ) | ||||
|                   ) | ||||
|               ), | ||||
|                             color: | ||||
|                                 ColorPalette.investTypeColor[e.value.type]!))), | ||||
|                 child: Row( | ||||
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                   children: [ | ||||
|                     Expanded( | ||||
|                         flex: 5, | ||||
|                       child: Text(e.value.name ?? '', | ||||
|                         child: Text( | ||||
|                           e.value.name ?? '', | ||||
|                           style: const TextStyle( | ||||
|                               color: ColorPalette.slate400, | ||||
|                               fontWeight: FontWeight.w600, | ||||
|                             fontSize: 16 | ||||
|                         ), | ||||
|                       ) | ||||
|                   ), | ||||
|                               fontSize: 16), | ||||
|                         )), | ||||
|                     Expanded( | ||||
|                         flex: 7, | ||||
|                         child: Text( | ||||
|                         NumberFormatter.numberCurrency(widget.totalInvest * e.value.totalPercent!, 'Rp ', 'id_ID'), | ||||
|                           NumberFormatter.numberCurrency( | ||||
|                               widget.totalInvest * e.value.totalPercent!, | ||||
|                               'Rp ', | ||||
|                               'id_ID'), | ||||
|                           textAlign: TextAlign.end, | ||||
|                           style: const TextStyle( | ||||
|                               fontWeight: FontWeight.w700, | ||||
|                               fontSize: 18, | ||||
|                             color: ColorPalette.slate800 | ||||
|                         ), | ||||
|                       ) | ||||
|                   ) | ||||
|                               color: ColorPalette.slate800), | ||||
|                         )) | ||||
|                   ], | ||||
|                 ), | ||||
|               ); | ||||
| @@ -97,44 +94,47 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|               child: Row( | ||||
|                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                 children: [ | ||||
|                 Text('Purchase Commission', | ||||
|                   Text( | ||||
|                     'Purchase Commission', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate400, | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                       fontSize: 16 | ||||
|                         fontSize: 16), | ||||
|                   ), | ||||
|                 ), | ||||
|                 Text('Free', | ||||
|                   Text( | ||||
|                     'Free', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.primary, | ||||
|                         fontSize: 18, | ||||
|                       fontWeight: FontWeight.w700 | ||||
|                   ), | ||||
|                         fontWeight: FontWeight.w700), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
|             ), | ||||
|           const SizedBox(height: 16,), | ||||
|             const SizedBox( | ||||
|               height: 16, | ||||
|             ), | ||||
|             Container( | ||||
|               color: ColorPalette.slate200.withOpacity(0.5), | ||||
|               padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), | ||||
|               child: Row( | ||||
|                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                 children: [ | ||||
|                 const Text('Total', | ||||
|                   const Text( | ||||
|                     'Total', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate400, | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                       fontSize: 16 | ||||
|                         fontSize: 16), | ||||
|                   ), | ||||
|                 ), | ||||
|                 Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'), | ||||
|                   Text( | ||||
|                     NumberFormatter.numberCurrency( | ||||
|                         widget.totalInvest, 'Rp ', 'id_ID'), | ||||
|                     textAlign: TextAlign.end, | ||||
|                     style: const TextStyle( | ||||
|                         fontWeight: FontWeight.w700, | ||||
|                         fontSize: 18, | ||||
|                       color: ColorPalette.slate800 | ||||
|                   ), | ||||
|                         color: ColorPalette.slate800), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
| @@ -145,20 +145,21 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|               child: Row( | ||||
|                 mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|                 children: [ | ||||
|                 const Text('Total Payment', | ||||
|                   const Text( | ||||
|                     'Total Payment', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate400, | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                       fontSize: 16 | ||||
|                         fontSize: 16), | ||||
|                   ), | ||||
|                 ), | ||||
|                 Text(NumberFormatter.numberCurrency(widget.totalInvest, 'Rp ', 'id_ID'), | ||||
|                   Text( | ||||
|                     NumberFormatter.numberCurrency( | ||||
|                         widget.totalInvest, 'Rp ', 'id_ID'), | ||||
|                     textAlign: TextAlign.end, | ||||
|                     style: const TextStyle( | ||||
|                         fontWeight: FontWeight.w700, | ||||
|                         fontSize: 18, | ||||
|                       color: ColorPalette.slate800 | ||||
|                   ), | ||||
|                         color: ColorPalette.slate800), | ||||
|                   ) | ||||
|                 ], | ||||
|               ), | ||||
| @@ -167,7 +168,8 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|               disabled: !isAgreement, | ||||
|               name: 'Subscribe Now', | ||||
|               onPressed: () { | ||||
|               routePush(context, page: PaymentMethodView( | ||||
|                 routePush(context, | ||||
|                     page: PaymentMethodView( | ||||
|                       totalInvest: widget.totalInvest, | ||||
|                     )); | ||||
|               }, | ||||
| @@ -179,6 +181,7 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -205,48 +208,46 @@ class _TotalPaymentViewState extends State<TotalPaymentView> { | ||||
|               decoration: BoxDecoration( | ||||
|                   shape: BoxShape.circle, | ||||
|                   border: Border.all( | ||||
|                       color: isAgree ? ColorPalette.primary : ColorPalette.slate200 | ||||
|                   ) | ||||
|               ), | ||||
|                       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 | ||||
|                       color: | ||||
|                           isAgree ? ColorPalette.primary : ColorPalette.white, | ||||
|                       shape: BoxShape.circle), | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|           const SizedBox( | ||||
|             width: 12, | ||||
|           ), | ||||
|           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.', | ||||
|               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 | ||||
|                     ), | ||||
|                     color: ColorPalette.slate400), | ||||
|               ), | ||||
|               GestureDetector( | ||||
|                       onTap: () { | ||||
|  | ||||
|                       }, | ||||
|                       child: const Text('Read More', | ||||
|                   onTap: () {}, | ||||
|                   child: const Text( | ||||
|                     'Read More', | ||||
|                     style: TextStyle( | ||||
|                         fontSize: 16, | ||||
|                         fontWeight: FontWeight.w600, | ||||
|                         decoration: TextDecoration.underline, | ||||
|                             color: ColorPalette.primary | ||||
|                         ), | ||||
|                       ) | ||||
|                   ) | ||||
|                         color: ColorPalette.primary), | ||||
|                   )) | ||||
|             ], | ||||
|               ) | ||||
|           ) | ||||
|           )) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -20,11 +20,25 @@ class InvestTypeView extends StatefulWidget { | ||||
| } | ||||
|  | ||||
| class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|    | ||||
|   List<Product> listProduct = [ | ||||
|     Product(name: 'Gemilang Dana Kas Maxima', 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) | ||||
|     Product( | ||||
|         name: 'Gemilang Dana Kas Maxima', | ||||
|         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 | ||||
| @@ -41,8 +55,7 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|   Widget build(BuildContext context) { | ||||
|     return ChangeNotifierProvider<ProductViewModel>( | ||||
|       create: (context) => ProductViewModel(), | ||||
|       child: Consumer<ProductViewModel>( | ||||
|         builder: (context, provider, child) { | ||||
|       child: Consumer<ProductViewModel>(builder: (context, provider, child) { | ||||
|         return Scaffold( | ||||
|           body: SizedBox( | ||||
|             width: SizeConfig.width, | ||||
| @@ -52,8 +65,8 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|                 const ImageView(image: PathAssets.imgDashboardAccount), | ||||
|                 Column( | ||||
|                   children: [ | ||||
|                       const SizedBox( | ||||
|                         height: 50, | ||||
|                     SizedBox( | ||||
|                       height: SizeConfig.height * .1, | ||||
|                     ), | ||||
|                     Padding( | ||||
|                       padding: const EdgeInsets.symmetric(horizontal: 24), | ||||
| @@ -71,12 +84,14 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|                     const SizedBox( | ||||
|                       height: 24, | ||||
|                     ), | ||||
|                       Container( | ||||
|                     Expanded( | ||||
|                       child: Container( | ||||
|                         padding: const EdgeInsets.all(24), | ||||
|                         decoration: BoxDecoration( | ||||
|                             borderRadius: BorderRadius.circular(16), | ||||
|                           color: Colors.white | ||||
|                         ), | ||||
|                             color: Colors.white), | ||||
|                         child: SingleChildScrollView( | ||||
|                           scrollDirection: Axis.vertical, | ||||
|                           child: Column( | ||||
|                             children: [ | ||||
|                               filters(), | ||||
| @@ -86,10 +101,12 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|                                   return GestureDetector( | ||||
|                                     onTap: () { | ||||
|                                       provider.setSelectedProduct(e.value); | ||||
|                                     routePush(context, page: ProductView(widget.title)); | ||||
|                                       routePush(context, | ||||
|                                           page: ProductView(widget.title)); | ||||
|                                     }, | ||||
|                                     child: Padding( | ||||
|                                     padding: EdgeInsets.only(top: e.key != 0 ? 24 : 0), | ||||
|                                       padding: EdgeInsets.only( | ||||
|                                           top: e.key != 0 ? 24 : 0), | ||||
|                                       child: cardProduct(e.value), | ||||
|                                     ), | ||||
|                                   ); | ||||
| @@ -98,14 +115,15 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|                             ], | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                   ], | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|         } | ||||
|       ), | ||||
|       }), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @@ -115,9 +133,25 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|       child: Row( | ||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|         children: [ | ||||
|           segmentFilter(const Icon(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', () { }), | ||||
|           segmentFilter( | ||||
|               const Icon( | ||||
|                 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), | ||||
|         decoration: BoxDecoration( | ||||
|             border: Border.all(color: ColorPalette.slate200), | ||||
|             borderRadius: BorderRadius.circular(56) | ||||
|         ), | ||||
|             borderRadius: BorderRadius.circular(56)), | ||||
|         child: Row( | ||||
|           children: [ | ||||
|             leading, | ||||
| @@ -142,9 +175,7 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|               text, | ||||
|               overflow: TextOverflow.ellipsis, | ||||
|               style: const TextStyle( | ||||
|                 color: ColorPalette.slate500, | ||||
|                 fontWeight: FontWeight.w700 | ||||
|               ), | ||||
|                   color: ColorPalette.slate500, fontWeight: FontWeight.w700), | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
| @@ -163,7 +194,10 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|         children: [ | ||||
|           Row( | ||||
|             children: [ | ||||
|               ImageView(image: PathAssets.imgProduct, width: SizeConfig.width * .12,), | ||||
|               ImageView( | ||||
|                 image: PathAssets.imgProduct, | ||||
|                 width: SizeConfig.width * .12, | ||||
|               ), | ||||
|               const SizedBox( | ||||
|                 width: 8, | ||||
|               ), | ||||
| @@ -171,9 +205,7 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|                 child: Text( | ||||
|                   product.name ?? '', | ||||
|                   style: const TextStyle( | ||||
|                     fontWeight: FontWeight.bold, | ||||
|                     fontSize: 18 | ||||
|                   ), | ||||
|                       fontWeight: FontWeight.bold, fontSize: 18), | ||||
|                 ), | ||||
|               ) | ||||
|             ], | ||||
| @@ -187,36 +219,53 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|             children: [ | ||||
|               Column( | ||||
|                 children: [ | ||||
|                   const Text('Yield', style: TextStyle(color: ColorPalette.slate400, fontWeight: FontWeight.w600),), | ||||
|                   const Text( | ||||
|                     'Yield', | ||||
|                     style: TextStyle( | ||||
|                         color: ColorPalette.slate400, | ||||
|                         fontWeight: FontWeight.w600), | ||||
|                   ), | ||||
|                   Row( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         '${product.yield.toString()}%', | ||||
|                         style: const TextStyle( | ||||
|                             color: ColorPalette.green400, | ||||
|                           fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                             fontWeight: FontWeight.w600), | ||||
|                       ), | ||||
|                       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( | ||||
|                 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( | ||||
|                     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( | ||||
|                         width: 2, | ||||
|                       ), | ||||
|                       Text( | ||||
|                         NumberFormatter.numberCurrency(product.priceUnit, 'Rp', 'id_ID'), | ||||
|                         style: const TextStyle( | ||||
|                           fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                         NumberFormatter.numberCurrency( | ||||
|                             product.priceUnit, 'Rp', 'id_ID'), | ||||
|                         style: const TextStyle(fontWeight: FontWeight.w600), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ) | ||||
| @@ -224,14 +273,18 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|               ), | ||||
|               Column( | ||||
|                 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( | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         NumberFormatter.compactCurrency(product.funds, 'Rp ', 'id_ID'), | ||||
|                         style: const TextStyle( | ||||
|                             fontWeight: FontWeight.w600 | ||||
|                         ), | ||||
|                         NumberFormatter.compactCurrency( | ||||
|                             product.funds, 'Rp ', 'id_ID'), | ||||
|                         style: const TextStyle(fontWeight: FontWeight.w600), | ||||
|                       ), | ||||
|                     ], | ||||
|                   ) | ||||
| @@ -243,5 +296,4 @@ class _InvestTypeViewState extends State<InvestTypeView> { | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import 'package:cims_apps/core/route/route.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/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:provider/provider.dart'; | ||||
| @@ -102,7 +103,8 @@ class DashboardPublicView extends StatelessWidget { | ||||
|                         width: 26, | ||||
|                       ), | ||||
|                       onPressed: () { | ||||
|                         provider.loginGoogle(context); | ||||
|                         // provider.loginGoogle(context); | ||||
|                         routePush(context, page: const BottomNavigationView()); | ||||
|                       }, | ||||
|                     ), | ||||
|                     Row( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user