This commit is contained in:
mohammad
2024-07-23 16:16:31 +03:00
parent 8a4a158af5
commit e5e839248d
17 changed files with 457 additions and 516 deletions
-81
View File
@@ -9,85 +9,4 @@ class MenuCubit extends Cubit<MenuState> {
String name = '';
// List<MenuListModel> menuLists = [
// MenuListModel(
// label: 'Home Management',
// listItems: [
// ListItemModel(
// label: 'Create a Home',
// ),
// ListItemModel(
// label: 'Join a Home',
// ),
// ListItemModel(
// label: 'Manage Your Home',
// ),
// ],
// ),
// MenuListModel(
// label: 'General Settings',
// listItems: [
// ListItemModel(
// label: 'Voice Assistant',
// ),
// ListItemModel(
// label: 'Temperature unit',
// ),
// ListItemModel(
// label: 'Touch tone on panel',
// ),
// ListItemModel(
// label: 'Language',
// ),
// ListItemModel(
// label: 'Network diagnosis',
// ),
// ListItemModel(
// label: 'Clear cache',
// ),
// ],
// ),
// MenuListModel(
// label: 'Messages Center',
// listItems: [
// ListItemModel(
// label: 'Alerts',
// ),
// ListItemModel(
// label: 'Messages',
// ),
// ListItemModel(
// label: 'FAQs',
// ),
// ListItemModel(
// label: 'Help & Feedback',
// ),
// ],
// ),
// MenuListModel(
// label: 'Security and Privacy',
// listItems: [
// ListItemModel(
// label: 'Security',
// ),
// ListItemModel(
// label: 'privacy',
// ),
// ],
// ),
// MenuListModel(
// label: 'Legal Information',
// listItems: [
// ListItemModel(
// label: 'About',
// ),
// ListItemModel(
// label: 'Privacy Policy',
// ),
// ListItemModel(
// label: 'User Agreement',
// ),
// ],
// ),
// ];
}
@@ -1,19 +1,21 @@
import 'dart:convert';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_state.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_model.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/time_zone_model.dart';
import 'package:syncrow_app/services/api/profile_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
final String userId;
bool isSaving = false;
bool editName = false;
final FocusNode focusNode = FocusNode();
@@ -22,12 +24,13 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
String timeZoneSelected = '';
String regionSelected = '';
final TextEditingController searchController = TextEditingController();
final TextEditingController nameController = TextEditingController(text: 'asd alsdkasdd ');
final TextEditingController nameController = TextEditingController(text: '${AuthCubit.user!.firstName} ${AuthCubit.user!.lastName}');
List<TimeZone>? timeZoneList;
List<RegionModel>? regionList;
ProfileBloc({required this.userId}) : super(InitialState()) {
on<InitialEvent>(_fetchUserInfo);
ProfileBloc() : super(InitialState()) {
on<InitialProfileEvent>(_fetchUserInfo);
on<TimeZoneInitialEvent>(_fetchTimeZone);
on<RegionInitialEvent>(_fetchRegion);
on<SaveNameEvent>(saveName);
@@ -35,46 +38,18 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
on<ChangeNameEvent>(_changeName);
on<SelectTimeZoneEvent>(selectTimeZone);
on<SearchRegionEvent>(searchRegion);
on<SearchTimeZoneEvent>(searchTimeZone);
on<SelectRegionEvent>(selectRegion);
}
List<Map<String, String>> timeZone=
[
{"name": "GMT-12:00", "offset": "-12:00","id":'1'},
{"name": "GMT-11:00", "offset": "-11:00","id":'2'},
{"name": "GMT-10:00", "offset": "-10:00","id":'3'},
{"name": "GMT-09:00", "offset": "-09:00","id":'4'},
{"name": "GMT-08:00", "offset": "-08:00","id":'5'},
{"name": "GMT-07:00", "offset": "-07:00","id":'6'},
{"name": "GMT-06:00", "offset": "-06:00","id":'7'},
{"name": "GMT-05:00", "offset": "-05:00","id":'8'},
{"name": "GMT-04:00", "offset": "-04:00","id":'9'},
];
List<Map<String, String>> region=
[
{"name": "region 1", "id":'1'},
{"name": "region 2", "id":'2'},
{"name": "region 3","id":'3'},
{"name": "region 4", "id":'4'},
{"name": "region 5","id":'5'},
{"name": "region 6","id":'6'},
{"name": "region 7","id":'7'},
{"name": "region 8", "id":'8'},
];
Uint8List? decodeBase64Image(String? base64String) {
if (base64String != null) {
final startIndex = base64String.indexOf('base64,') + 7;
final pureBase64String = base64String.substring(startIndex);
return base64.decode(pureBase64String);
}
return null;
}
void _changeName(ChangeNameEvent event, Emitter<ProfileState> emit) {
emit(LoadingInitialState());
editName = event.value!;
@@ -88,30 +63,21 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
emit(NameEditingState(editName: editName));
}
void _fetchUserInfo(InitialEvent event, Emitter<ProfileState> emit) async {
void _fetchUserInfo(InitialProfileEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
// var response = await ProfileApi.fetchUserInfo(userId);
// List<StatusModel> statusModelList = [];
// for (var status in response['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// }
AuthCubit.user = await ProfileApi.fetchUserInfo(AuthCubit.user!.uuid);
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
Future _fetchTimeZone(
TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
Future _fetchTimeZone(TimeZoneInitialEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
timeZoneList = timeZone.map((zone) => TimeZone.fromJson(zone)).toList();
// List<StatusModel> statusModelList = [];
// for (var status in response['status']) {
// statusModelList.add(StatusModel.fromJson(status));
// }
emit(UpdateState(timeZoneList: timeZoneList!)); // Make sure UpdateState accepts the list
timeZoneList = await ProfileApi.fetchTimeZone();
emit(UpdateState(timeZoneList: timeZoneList!));
return timeZoneList;
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
@@ -119,26 +85,25 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future selectTimeZone(SelectTimeZoneEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
timeZoneSelected= event.val;
emit(LoadingInitialState());
timeZoneSelected = event.val;
await ProfileApi.saveTimeZone(regionUuid: event.val);
CustomSnackBar.displaySnackBar('Save Successfully');
Navigator.pop(event.context);
return timeZoneList;
emit(SaveState());
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
Future selectRegion(SelectRegionEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
try {
regionSelected= event.val;
emit(LoadingInitialState());
await ProfileApi.saveRegion(regionUuid:event.val );
CustomSnackBar.displaySnackBar('Save Successfully');
Navigator.pop(event.context);
return timeZoneList;
emit(SaveState());
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
@@ -146,26 +111,43 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
Future searchRegion(SearchRegionEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if(event.query.isEmpty){
regionList = region.map((zone) => RegionModel.fromJson(zone)).toList();
}else{
if(event.query.isNotEmpty){
final filteredRegions = regionList?.where((region) {
return region.name.toLowerCase().contains(query);
}).toList() ?? [];
regionList = filteredRegions;// Assume this fetches the regions
emit(RegionsLoadedState(regions: filteredRegions));
}else{
regionList = await ProfileApi.fetchRegion();
emit(RegionsLoadedState(regions: regionList!));
}
}
Future searchTimeZone(SearchTimeZoneEvent event, Emitter<ProfileState> emit) async {
emit(LoadingInitialState());
final query = event.query.toLowerCase();
if(event.query.isNotEmpty){
final filtered = timeZoneList?.where((region) {
return region.name.toLowerCase().contains(query);
}).toList() ?? [];
timeZoneList = filtered;
emit(TimeZoneLoadedState(regions: filtered));
}else{
timeZoneList = await ProfileApi.fetchTimeZone();
emit(UpdateState(timeZoneList: timeZoneList!));
}
}
void _fetchRegion(RegionInitialEvent event, Emitter<ProfileState> emit) async {
try {
emit(LoadingInitialState());
regionList = region.map((zone) => RegionModel.fromJson(zone)).toList();
emit(UpdateState(timeZoneList: timeZoneList!));
regionList = await ProfileApi.fetchRegion();
emit(RegionsLoadedState(regions: regionList!));
} catch (e) {
emit(FailedState(errorMessage: e.toString()));
return;
}
}
@@ -182,7 +164,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
image=null;
CustomSnackBar.displaySnackBar('Image size must be 1 MB or less');
}else{
await saveImage();
await _saveImage();
}
} else {
print('No image selected.');
@@ -193,54 +175,15 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
}
}
Future<void> saveImage() async {
Future<void> _saveImage() async {
emit(ChangeImageState());
List<int> imageBytes = image!.readAsBytesSync();
String base64Image = base64Encode(imageBytes);
print(base64Image);
var response = await ProfileApi.saveImage(base64Image);
emit(ImageSelectedState());
}
Future<bool> _requestPermission() async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if (Platform.isAndroid ) {
PermissionStatus status = await Permission.photos.status;
if(androidInfo.version.sdkInt<= 33){
if (status.isDenied) {
PermissionStatus status = await Permission.storage.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}else{
if (status.isGranted) {
return true;
} else if (status.isDenied) {
PermissionStatus status = await Permission.photos.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}
return false;
} else {
SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
bool firstClick = sharedPreferences.getBool('firstPermission') ?? true;
await sharedPreferences.setBool('firstPermission', false);
if (firstClick == false) {
var status = await Permission.photos.status;
return status.isGranted;
} else {
return true;
}
}
}
void _showPermissionDeniedDialog(BuildContext context) {
showDialog(
@@ -272,129 +215,72 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
Future<void> saveName(SaveNameEvent event, Emitter<ProfileState> emit) async {
if (_validateInputs()) return;
try {
add(const ChangeNameEvent(value: false));
isSaving = true;
emit(LoadingSaveState());
final fullName = nameController.text;
final nameParts = fullName.split(' ');
final firstName = nameParts[0];
final lastName = nameParts.length > 1 ? nameParts[1] : '';
var response = await ProfileApi.saveName(firstName: firstName, lastName: lastName);
add(InitialProfileEvent());
AuthCubit.get(event.context).fetchUserInfo();
Navigator.of(event.context).pop(true);
CustomSnackBar.displaySnackBar('Save Successfully');
emit(SaveState());
} catch (_) {
// Handle the error
} finally {
isSaving = false;
}
}
bool _validateInputs() {
if (nameController.text.length < 7) {
CustomSnackBar.displaySnackBar('Password less than 7');
return true;
}
if (nameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password required');
return true;
}
if (nameController.text.isEmpty) {
CustomSnackBar.displaySnackBar('Password name required');
if (nameController.text.length < 2) {
CustomSnackBar.displaySnackBar('Name Must More than 2 ');
return true;
}
return false;
}
void showRenameDialog(BuildContext context) {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: SizedBox(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.only(
top: 25,
),
child: Text(
'Change Name',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const Spacer(),
const Spacer(),
Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 0.5,
),
top: BorderSide(
color: Colors.grey,
width: 0.5,
),
),
),
child: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'Cancel',
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
),
),
const VerticalDivider(
thickness: 1,
width: 1,
),
Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: Colors.grey,
width: 0.5,
),
top: BorderSide(
color: Colors.grey,
width: 0.5,
),
),
),
child: TextButton(
onPressed: () {
// Handle save action
},
child: const Text(
'Save',
style: TextStyle(
fontSize: 18,
color: Colors.grey,
),
),
),
),
),
],
),
],
),
),
);
},
);
Future<bool> _requestPermission() async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
if (Platform.isAndroid ) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
PermissionStatus status = await Permission.photos.status;
if(androidInfo.version.sdkInt<= 33){
if (status.isDenied) {
PermissionStatus status = await Permission.storage.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}else{
if (status.isGranted) {
return true;
} else if (status.isDenied) {
PermissionStatus status = await Permission.photos.request();
if (status.isGranted) {
return true;
} else {
return false;
}
}
}
return false;
} else {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
bool firstClick = sharedPreferences.getBool('firstPermission') ?? true;
await sharedPreferences.setBool('firstPermission', false);
if (firstClick == false) {
var status = await Permission.photos.status;
return status.isGranted;
} else {
return true;
}
}
}
}
@@ -8,7 +8,7 @@ abstract class ProfileEvent extends Equatable {
List<Object> get props => [];
}
class InitialEvent extends ProfileEvent {}
class InitialProfileEvent extends ProfileEvent {}
class TimeZoneInitialEvent extends ProfileEvent {}
@@ -20,13 +20,6 @@ class ChangeNameEvent extends ProfileEvent {
class RegionInitialEvent extends ProfileEvent {}
class UpdateLockEvent extends ProfileEvent {
final bool value;
const UpdateLockEvent({required this.value});
@override
List<Object> get props => [value];
}
class SaveNameEvent extends ProfileEvent {
final BuildContext context;
const SaveNameEvent({required this.context});
@@ -71,5 +64,13 @@ class SearchRegionEvent extends ProfileEvent {
List<Object> get props => [query];
}
class SearchTimeZoneEvent extends ProfileEvent {
final String query;
const SearchTimeZoneEvent({required this.query});
@override
List<Object> get props => [query];
}
@@ -1,5 +1,4 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/smart_door_model.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_model.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/time_zone_model.dart';
@@ -26,13 +25,7 @@ class NameEditingState extends ProfileState {
NameEditingState({required this.editName});
}
class LoadingNewSate extends ProfileState {
final SmartDoorModel smartDoorModel;
const LoadingNewSate({required this.smartDoorModel});
@override
List<Object> get props => [smartDoorModel];
}
class FailedState extends ProfileState {
final String errorMessage;
@@ -43,20 +36,9 @@ class FailedState extends ProfileState {
List<Object> get props => [errorMessage];
}
class GeneratePasswordState extends ProfileState {}
class ImageSelectedState extends ProfileState {}
class ImageTooLargeState extends ProfileState {}
class IsRepeatState extends ProfileState {}
class IsStartEndState extends ProfileState {}
class ChangeStartTimeState extends ProfileState {}
class ChangeEndTimeState extends ProfileState {}
class ChangeImageState extends ProfileState {}
class SaveState extends ProfileState {}
@@ -66,4 +48,10 @@ class RegionsLoadedState extends ProfileState {
final List<RegionModel> regions;
const RegionsLoadedState({required this.regions});
}
class TimeZoneLoadedState extends ProfileState {
final List<TimeZone> regions;
const TimeZoneLoadedState({required this.regions});
}
@@ -11,15 +11,15 @@ class RegionModel {
factory RegionModel.fromJson(Map<String, dynamic> json) {
return RegionModel(
name: json['name'],
id: json['id'].toString(), // Ensure id is a String
name: json['regionName'],
id: json['uuid'].toString(), // Ensure id is a String
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'id': id,
'regionName': name,
'uuid': id,
};
}
}
@@ -11,9 +11,9 @@ class TimeZone {
factory TimeZone.fromJson(Map<String, dynamic> json) {
return TimeZone(
name: json['name'],
offset: json['offset'],
id: json['id'].toString(), // Ensure id is a String
name: json['cityName'],
offset: json['timeZoneOffset'],
id: json['uuid'].toString(), // Ensure id is a String
);
}
+1 -1
View File
@@ -25,7 +25,7 @@ class MenuView extends StatelessWidget {
physics: const BouncingScrollPhysics(),
child: Column(
children: [
ProfileTab(name:profileBloc.name),
ProfileTab(),
for (var section in menuSections)
MenuList(
section: section,
@@ -1,62 +1,98 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/syncrow_logo.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class ProfileTab extends StatelessWidget {
final String? name;
const ProfileTab({super.key,this.name});
const ProfileTab({super.key, this.name});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: InkWell(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const ProfileView(),
),
);
},
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
return BlocBuilder<AuthCubit, AuthState>(
builder: (context, state) {
final user = AuthCubit.user;
Uint8List? imageBytes;
if (user!.profilePicture != null) {
final base64String = user.profilePicture!;
final startIndex = base64String.indexOf('base64,') + 7;
final pureBase64String = base64String.substring(startIndex);
imageBytes = base64.decode(pureBase64String);
}
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: InkWell(
onTap: () {
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) => const ProfileView(),
),
)
.then((result) {
if (result == true) {
context.read<AuthCubit>().fetchUserInfo();
}
});
},
child: Stack(
children: [
const SizedBox(height: 20),
DefaultContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyMedium(
text: name!,
fontWeight: FontWeight.bold,
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 20),
DefaultContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
BodyMedium(
text: '${user.firstName!} ',
fontWeight: FontWeight.bold,
),
BodyMedium(
text: user.lastName!,
fontWeight: FontWeight.bold,
),
],
),
const BodySmall(text: "Syncrow Account"),
],
),
BodySmall(text: "Syncrow Account")
],
),
],
),
Positioned(
right: 20,
top: 0,
child: CircleAvatar(
radius: 38,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 37,
backgroundColor: Colors.grey,
child: ClipOval(
child: Image.memory(
imageBytes!,
fit: BoxFit.cover,
width: 110, // You can adjust the width and height as needed
height: 110,
)),
),
),
),
],
),
Positioned(
right: 20,
top: 0,
child: CircleAvatar(
radius: 38,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 37,
backgroundColor: Colors.grey,
child: SyncrowLogo(),
),
),
),
],
),
),
),
);
},
);
}
}
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_bloc.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.dart';
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_state.dart';
@@ -13,29 +14,29 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class ProfileView extends StatelessWidget {
const ProfileView({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => ProfileBloc(userId: ''),
child: BlocConsumer<ProfileBloc, ProfileState>(listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage),
backgroundColor: Colors.red,
),
);
}
}, builder: (context, state) {
create: (BuildContext context) => ProfileBloc()..add(InitialProfileEvent()),
child: BlocConsumer<ProfileBloc, ProfileState>(
listener: (context, state) {},
builder: (context, state) {
final profileBloc = BlocProvider.of<ProfileBloc>(context);
Uint8List? imageBytes = profileBloc.decodeBase64Image(AuthCubit.user!.profilePicture);
return DefaultScaffold(
title: 'Syncrow Account',
child: Column(
children: [
SizedBox(height: MediaQuery.of(context).size.height*0.05,),
SizedBox(
height: MediaQuery.of(context).size.height * 0.05,
),
InkWell(
onTap: () {
profileBloc.add(SelectImageEvent(context: context, isSelected: false));
profileBloc.add(
SelectImageEvent(context: context, isSelected: false));
},
child: SizedBox.square(
dimension: 125,
@@ -48,6 +49,18 @@ class ProfileView extends StatelessWidget {
backgroundImage: profileBloc.image == null
? null
: FileImage(profileBloc.image!),
child: profileBloc.image != null
? null
:imageBytes != null
? ClipOval(
child: Image.memory(
imageBytes,
fit: BoxFit.cover,
width: 110,
height: 110,
),
)
: null,
),
),
),
@@ -70,7 +83,7 @@ class ProfileView extends StatelessWidget {
controller: profileBloc.nameController,
enabled: profileBloc.editName,
onEditingComplete: () {
profileBloc.add(const ChangeNameEvent(value: false));
profileBloc.add(SaveNameEvent(context: context));
},
decoration: const InputDecoration(
hintText: "Your Name",
@@ -98,89 +111,80 @@ class ProfileView extends StatelessWidget {
),
),
const SizedBox(height: 10),
//Info
// Info
DefaultContainer(
padding: const EdgeInsets.symmetric(
horizontal: 25,
vertical: 5,
),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// const BodyMedium(text: 'Email '),
// Flexible(
// child: TextField(
// textAlign: TextAlign.end,
// decoration: InputDecoration(
// hintText: ' [email protected]',
// hintStyle:
// context.bodyMedium.copyWith(color: Colors.grey),
// border: InputBorder.none,
// ),
// ),
// ),
// ],
// ),
// Container(
// height: 1,
// color: ColorsManager.greyColor,
// ),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const RegionPage(),
));
},
child: const Padding(
padding: EdgeInsets.only(top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(text: 'Region '),
Flexible(
child: BodyMedium(text: 'United Arab Emirates')
),
],
),
)),
Container(
height: 1,
color: ColorsManager.greyColor,
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const TimeZoneScreenPage(),
));
},
child: const Padding(
padding: EdgeInsets.only(top: 15, bottom: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
BodyMedium(text: 'Time Zone '),
Flexible(
child: BodyMedium(text: 'GMT +4')
),
],
padding: const EdgeInsets.symmetric(
horizontal: 25,
vertical: 5,
),
child:
BlocBuilder<AuthCubit, AuthState>(
builder: (context, state) {
final user = AuthCubit.user;
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const RegionPage(),
),
).then((result) {
context.read<AuthCubit>().fetchUserInfo();
});
},
child: Padding(
padding: const EdgeInsets.only(top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodyMedium(text: 'Region '),
Flexible(child: BodyMedium(text: user!.regionName??'No Region')),
],
),
),
],
)),
),
Container(
height: 1,
color: ColorsManager.greyColor,
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TimeZoneScreenPage(),
),
).then((result) {
context.read<AuthCubit>().fetchUserInfo();
});
},
child: Padding(
padding: const EdgeInsets.only(top: 15, bottom: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BodyMedium(text: 'Time Zone '),
Flexible(
child: BodyMedium(text: user.timeZone??"No Time Zone"),
),
],
),
),
),
],
);}),
),
],
),
);
}));
},
),
);
}
}
@@ -13,7 +13,7 @@ class RegionPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => ProfileBloc(userId: '')..add(RegionInitialEvent()),
create: (BuildContext context) => ProfileBloc()..add(RegionInitialEvent()),
child: BlocConsumer<ProfileBloc, ProfileState>(listener: (context, state) {
if (state is FailedState) {
ScaffoldMessenger.of(context).showSnackBar(
@@ -15,7 +15,7 @@ class TimeZoneScreenPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (BuildContext context) => ProfileBloc(userId: '')..add(TimeZoneInitialEvent()),
create: (BuildContext context) => ProfileBloc()..add(TimeZoneInitialEvent()),
child:
BlocConsumer<ProfileBloc, ProfileState>(listener: (context, state) {
if (state is FailedState) {
@@ -38,6 +38,10 @@ class TimeZoneScreenPage extends StatelessWidget {
: Column(
children: [
TextFormField(
controller:profileBloc.searchController ,
onChanged: (value) {
profileBloc.add(SearchTimeZoneEvent(query: value));
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.search),
hintText: 'Search',
@@ -59,7 +63,6 @@ class TimeZoneScreenPage extends StatelessWidget {
itemBuilder: (context, index) {
return InkWell(
onTap: () {
profileBloc.add(SelectTimeZoneEvent(
val: timeZoneList[index].id,
context: context));