Completed language selection bottomSheet in profile with bloc state management

This commit is contained in:
Vinayakkadge04
2025-10-15 11:22:54 +05:30
parent f6aaf121ca
commit f7a6199332
14 changed files with 206 additions and 70 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/icons/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -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<LanguageEvent , LanguageState>{
LanguageBloc() : super(LanguageState("English / Englis")){
on<UpdateLanguage>((event, emit){
emit(LanguageState(event.language));
});
}
}

View File

@@ -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<NavigationBloc>().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(

View File

@@ -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<String> 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<LanguageBloc, LanguageState>(
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<LanguageBloc>().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),
),
);
},
),
);
},
),
],
),
);
}
}

View File

@@ -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),

View File

@@ -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:

View File

@@ -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

View File

@@ -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),

View File

@@ -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';

View File

@@ -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),

View File

@@ -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

View File

@@ -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),