diff --git a/assets/icons/radio_button_checked.png b/assets/icons/radio_button_checked.png new file mode 100644 index 0000000..d2b362a Binary files /dev/null and b/assets/icons/radio_button_checked.png differ diff --git a/assets/icons/radio_button_unchecked.png b/assets/icons/radio_button_unchecked.png new file mode 100644 index 0000000..05ba521 Binary files /dev/null and b/assets/icons/radio_button_unchecked.png differ diff --git a/assets/icons/search.png b/assets/icons/search.png new file mode 100644 index 0000000..aa4b3bb Binary files /dev/null and b/assets/icons/search.png differ diff --git a/lib/common_bloc/language_selection_bloc.dart b/lib/common_bloc/language_selection_bloc.dart new file mode 100644 index 0000000..7297176 --- /dev/null +++ b/lib/common_bloc/language_selection_bloc.dart @@ -0,0 +1,22 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +abstract class LanguageEvent{} + +class UpdateLanguage extends LanguageEvent{ + final String language; + UpdateLanguage(this.language); +} + + +class LanguageState{ + final String selectedLanguage; + LanguageState(this.selectedLanguage); +} + +class LanguageBloc extends Bloc{ + LanguageBloc() : super(LanguageState("English / Englis")){ + on((event, emit){ + emit(LanguageState(event.language)); + }); + } +} \ No newline at end of file diff --git a/lib/common_packages/custom_bottom_navbar.dart b/lib/common_packages/custom_bottom_navbar.dart index 6dc6f1d..06b1865 100644 --- a/lib/common_packages/custom_bottom_navbar.dart +++ b/lib/common_packages/custom_bottom_navbar.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; - import '../common_bloc/bottom_navigation_bloc.dart'; - class CustomBottomNavBar extends StatelessWidget { const CustomBottomNavBar({super.key}); @@ -74,7 +72,6 @@ class CustomBottomNavBar extends StatelessWidget { required bool isActive, }) { final color = isActive ? const Color(0xFFBB474A) : Color(0xFFBB474A).withOpacity(0.6); - return GestureDetector( onTap: () => context.read().add(NavigationTabChanged(index)), @@ -93,7 +90,6 @@ class CustomBottomNavBar extends StatelessWidget { ) else const SizedBox(height: 7), - Image.asset(iconPath, scale: 4, color: color), const SizedBox(height: 4), Text( diff --git a/lib/common_packages/language_selection_bottomsheet.dart b/lib/common_packages/language_selection_bottomsheet.dart new file mode 100644 index 0000000..40c79f8 --- /dev/null +++ b/lib/common_packages/language_selection_bottomsheet.dart @@ -0,0 +1,113 @@ +import 'package:citycards_customer/common_bloc/language_selection_bloc.dart'; +import 'package:citycards_customer/common_packages/custom_text.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class LanguageSelectionBottomsheet extends StatelessWidget { + LanguageSelectionBottomsheet({super.key}); + + List languages = [ + "English / Englis", + "Dutch / Nederlands", + "Spanish / Español", + "French / Français", + "Japanese / 日本語", + ]; + + TextEditingController searchController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40, + height: 4, + decoration: BoxDecoration( + color: Color(0xFF2D3134), + borderRadius: BorderRadius.circular(4), + ), + ), + const SizedBox(height: 20), + Align( + alignment: Alignment.topLeft, + child: const Text( + "Change Language", + style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500), + ), + ), + const SizedBox(height: 22), + TextField( + controller: searchController, + decoration: InputDecoration( + hintText: "Search Languages", + hintStyle: TextStyle( + fontSize: 14, + color: Color(0xBBC83B61).withOpacity(0.4), + ), + suffixIcon: Image.asset("assets/icons/search.png", scale: 4), + contentPadding: const EdgeInsets.symmetric(horizontal: 24), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Color(0xBBC83B61).withOpacity(0.4), + width: .4, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color(0xFFF95F62), + width: 1, + ), + ), + ), + ), + const SizedBox(height: 12), + + BlocBuilder( + builder: (context, state) { + return Expanded( + child: ListView.builder( + itemCount: languages.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final item = languages[index]; + return ListTile( + dense: true, + leading: GestureDetector( + onTap: () { + context.read().add( + UpdateLanguage(item), + ); + }, + child: state.selectedLanguage == item + ? Image.asset( + "assets/icons/radio_button_checked.png", + scale: 4, + ) + : Image.asset( + "assets/icons/radio_button_unchecked.png", + scale: 4, + ), + ), + title: CustomText( + text: item, + size: 16, + color: state.selectedLanguage == item ? Color(0xFFF95F62) : Color(0xFF000000).withOpacity(.6), + ), + ); + }, + ), + ); + }, + ), + ], + ), + ); + } +} diff --git a/lib/contact_us/contact_us_view.dart b/lib/contact_us/contact_us_view.dart index 6e5f1c2..fc5d4f6 100644 --- a/lib/contact_us/contact_us_view.dart +++ b/lib/contact_us/contact_us_view.dart @@ -1,3 +1,4 @@ +import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:flutter/material.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; import 'package:citycards_customer/common_packages/custom_textfield.dart'; @@ -22,20 +23,13 @@ class ContactUsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header bar - Container( - padding: const EdgeInsets.only(bottom: 10), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(color: Color(0xFFD9D9D9), width: 0.7), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset("assets/logo/logo_city_cards.png", scale: 4), - Image.asset("assets/icons/shopping_cart.png", scale: 4), - ], - ), + CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox( + height: 12, + ), + Divider( + height: 1, + color: Color(0xFFD9D9D9), ), const SizedBox(height: 22), diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 04bfcd0..25d5da2 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -1,4 +1,5 @@ import 'package:citycards_customer/Profile/profile_page_view.dart'; +import 'package:citycards_customer/common_bloc/language_selection_bloc.dart'; import 'package:citycards_customer/contact_us/contact_us_view.dart'; import 'package:citycards_customer/edit_profile/edit_profile_view.dart'; import 'package:citycards_customer/faq/faq_view.dart'; @@ -10,7 +11,6 @@ import '../common_bloc/bottom_navigation_bloc.dart'; import '../home/views/home_page_view.dart'; import 'route_constants.dart'; - class AppRouter { Route onGenerateRoute(RouteSettings settings) { switch (settings.name) { @@ -18,14 +18,20 @@ class AppRouter { case RouteConstants.home: return MaterialPageRoute( builder: (_) { - return BlocProvider(create: (_) => NavigationBloc(), child: const HomePage()); + return BlocProvider( + create: (_) => NavigationBloc(), + child: const HomePage(), + ); }, ); case RouteConstants.profile: return MaterialPageRoute( builder: (_) { - return const ProfilePage(); + return BlocProvider( + create: (_) => LanguageBloc(), + child: const ProfilePage(), + ); }, ); case RouteConstants.editProfile: diff --git a/lib/edit_profile/edit_profile_view.dart b/lib/edit_profile/edit_profile_view.dart index 048d382..e052655 100644 --- a/lib/edit_profile/edit_profile_view.dart +++ b/lib/edit_profile/edit_profile_view.dart @@ -24,6 +24,13 @@ class EditProfilePage extends StatelessWidget { children: [ // Header CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox( + height: 12, + ), + Divider( + height: 1, + color: Color(0xFFD9D9D9), + ), const SizedBox(height: 22), // Back + title diff --git a/lib/faq/faq_view.dart b/lib/faq/faq_view.dart index e649e87..274c31f 100644 --- a/lib/faq/faq_view.dart +++ b/lib/faq/faq_view.dart @@ -1,3 +1,4 @@ +import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_expansion_tile.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; import 'package:flutter/material.dart'; @@ -16,20 +17,13 @@ class FaqPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - padding: const EdgeInsets.only(bottom: 10), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(color: Color(0xFFD9D9D9), width: 0.7), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset("assets/logo/logo_city_cards.png", scale: 4), - Image.asset("assets/icons/shopping_cart.png", scale: 4), - ], - ), + CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox( + height: 12, + ), + Divider( + height: 1, + color: Color(0xFFD9D9D9), ), const SizedBox(height: 22), diff --git a/lib/main.dart b/lib/main.dart index 37d63ad..e068a09 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; - import 'core/app_router.dart'; import 'core/route_constants.dart'; diff --git a/lib/privacy/privacy_view.dart b/lib/privacy/privacy_view.dart index b3bd19e..e871f2f 100644 --- a/lib/privacy/privacy_view.dart +++ b/lib/privacy/privacy_view.dart @@ -1,3 +1,4 @@ +import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; import 'package:flutter/material.dart'; @@ -13,20 +14,13 @@ class PrivacyPolicyPage extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: Column( children: [ - Container( - padding: const EdgeInsets.only(bottom: 10), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(color: Color(0xFFD9D9D9), width: 0.7), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset("assets/logo/logo_city_cards.png", scale: 4), - Image.asset("assets/icons/shopping_cart.png", scale: 4), - ], - ), + CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox( + height: 12, + ), + Divider( + height: 1, + color: Color(0xFFD9D9D9), ), const SizedBox(height: 22), diff --git a/lib/profile/profile_page_view.dart b/lib/profile/profile_page_view.dart index 8f60fce..eef124b 100644 --- a/lib/profile/profile_page_view.dart +++ b/lib/profile/profile_page_view.dart @@ -1,7 +1,10 @@ +import 'package:citycards_customer/common_bloc/language_selection_bloc.dart'; import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; +import 'package:citycards_customer/common_packages/language_selection_bottomsheet.dart'; import 'package:citycards_customer/core/route_constants.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; class ProfilePage extends StatelessWidget { const ProfilePage({super.key}); @@ -17,14 +20,17 @@ class ProfilePage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox(height: 12), + Divider(height: 1, color: Color(0xFFD9D9D9)), SizedBox(height: 22), Row( children: [ GestureDetector( - onTap: (){ - Navigator.pop(context); - }, - child: Icon(Icons.arrow_back, size: 24)), + onTap: () { + Navigator.pop(context); + }, + child: Icon(Icons.arrow_back, size: 24), + ), SizedBox(width: 8), Text("My profile", style: TextStyle(fontSize: 12)), ], @@ -96,9 +102,20 @@ class ProfilePage extends StatelessWidget { _buildListTile( icon: "assets/icons/change_language.png", title: 'Change language', - onTap: () {}, + onTap: () { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(12), + ), + ), + builder: (context) => BlocProvider( + create: (_)=> LanguageBloc(), + child: LanguageSelectionBottomsheet()), + ); + }, ), - const SizedBox(height: 24), // Support & Legal Section diff --git a/lib/terms_and_condition/terms_and_condition_view.dart b/lib/terms_and_condition/terms_and_condition_view.dart index 52264e8..5a6b75d 100644 --- a/lib/terms_and_condition/terms_and_condition_view.dart +++ b/lib/terms_and_condition/terms_and_condition_view.dart @@ -1,3 +1,4 @@ +import 'package:citycards_customer/common_packages/app_bar.dart'; import 'package:citycards_customer/common_packages/custom_text.dart'; import 'package:flutter/material.dart'; @@ -13,20 +14,13 @@ class TermsAndCondition extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), child: Column( children: [ - Container( - padding: const EdgeInsets.only(bottom: 10), - decoration: const BoxDecoration( - border: Border( - bottom: BorderSide(color: Color(0xFFD9D9D9), width: 0.7), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Image.asset("assets/logo/logo_city_cards.png", scale: 4), - Image.asset("assets/icons/shopping_cart.png", scale: 4), - ], - ), + CommonAppBar(isWhiteLogo: false, isProfilePage: true), + SizedBox( + height: 12, + ), + Divider( + height: 1, + color: Color(0xFFD9D9D9), ), const SizedBox(height: 22),