mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-17 10:35:10 +00:00
profile page with HomeCubit
This commit is contained in:
@ -22,6 +22,7 @@ import 'package:syncrow_app/features/scene/view/scene_view.dart';
|
|||||||
import 'package:syncrow_app/generated/assets.dart';
|
import 'package:syncrow_app/generated/assets.dart';
|
||||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
import 'package:syncrow_app/services/api/profile_api.dart';
|
||||||
import 'package:syncrow_app/services/api/spaces_api.dart';
|
import 'package:syncrow_app/services/api/spaces_api.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
import 'package:syncrow_app/utils/helpers/custom_page_route.dart';
|
||||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
@ -33,6 +34,7 @@ part 'home_state.dart';
|
|||||||
class HomeCubit extends Cubit<HomeState> {
|
class HomeCubit extends Cubit<HomeState> {
|
||||||
HomeCubit._() : super(HomeInitial()) {
|
HomeCubit._() : super(HomeInitial()) {
|
||||||
checkIfNotificationPermissionGranted();
|
checkIfNotificationPermissionGranted();
|
||||||
|
fetchUserInfo();
|
||||||
if (selectedSpace == null) {
|
if (selectedSpace == null) {
|
||||||
fetchUnitsByUserId();
|
fetchUnitsByUserId();
|
||||||
// .then((value) {
|
// .then((value) {
|
||||||
@ -42,7 +44,7 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static UserModel? user;
|
||||||
static HomeCubit? _instance;
|
static HomeCubit? _instance;
|
||||||
static HomeCubit getInstance() {
|
static HomeCubit getInstance() {
|
||||||
// If an instance already exists, return it
|
// If an instance already exists, return it
|
||||||
@ -50,6 +52,19 @@ class HomeCubit extends Cubit<HomeState> {
|
|||||||
return _instance!;
|
return _instance!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future fetchUserInfo() async {
|
||||||
|
try {
|
||||||
|
print('fetchUserInfo');
|
||||||
|
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
||||||
|
user = await ProfileApi().fetchUserInfo(uuid);
|
||||||
|
emit(HomeUserInfoLoaded(user!)); // Emit state after fetching user info
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void emitSafe(HomeState newState) {
|
void emitSafe(HomeState newState) {
|
||||||
final cubit = this;
|
final cubit = this;
|
||||||
if (!cubit.isClosed) {
|
if (!cubit.isClosed) {
|
||||||
|
@ -58,3 +58,9 @@ class RoomSelected extends HomeState {
|
|||||||
class RoomUnSelected extends HomeState {}
|
class RoomUnSelected extends HomeState {}
|
||||||
|
|
||||||
class NavChangePage extends HomeState {}
|
class NavChangePage extends HomeState {}
|
||||||
|
// Define new state classes
|
||||||
|
class HomeUserInfoLoaded extends HomeState {
|
||||||
|
final UserModel user;
|
||||||
|
|
||||||
|
HomeUserInfoLoaded(this.user);
|
||||||
|
}
|
||||||
|
@ -184,14 +184,10 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
key: Token.loginAccessTokenKey,
|
key: Token.loginAccessTokenKey,
|
||||||
value: token.accessToken
|
value: token.accessToken
|
||||||
);
|
);
|
||||||
await fetchUserInfo();
|
|
||||||
const FlutterSecureStorage().write(
|
const FlutterSecureStorage().write(
|
||||||
key: UserModel.userUuidKey,
|
key: UserModel.userUuidKey,
|
||||||
value: Token.decodeToken(token.accessToken)['uuid'].toString()
|
value: Token.decodeToken(token.accessToken)['uuid'].toString()
|
||||||
).then((value) async {
|
);
|
||||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
|
||||||
user = await ProfileApi.fetchUserInfo(uuid);
|
|
||||||
},);
|
|
||||||
user = UserModel.fromToken(token);
|
user = UserModel.fromToken(token);
|
||||||
emailController.clear();
|
emailController.clear();
|
||||||
passwordController.clear();
|
passwordController.clear();
|
||||||
@ -330,16 +326,6 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future fetchUserInfo() async {
|
|
||||||
try {
|
|
||||||
emit(AuthLoading());
|
|
||||||
var uuid = await const FlutterSecureStorage().read(key: UserModel.userUuidKey);
|
|
||||||
user = await ProfileApi.fetchUserInfo(uuid);
|
|
||||||
emit(AuthLoginSuccess());
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:syncrow_app/features/auth/model/token.dart';
|
import 'package:syncrow_app/features/auth/model/token.dart';
|
||||||
|
|
||||||
class UserModel {
|
class UserModel {
|
||||||
@ -6,7 +9,7 @@ class UserModel {
|
|||||||
final String? email;
|
final String? email;
|
||||||
final String? firstName;
|
final String? firstName;
|
||||||
final String? lastName;
|
final String? lastName;
|
||||||
final String? profilePicture;
|
final Uint8List? profilePicture;
|
||||||
final String? phoneNumber;
|
final String? phoneNumber;
|
||||||
final bool? isEmailVerified;
|
final bool? isEmailVerified;
|
||||||
final String? regionName;
|
final String? regionName;
|
||||||
@ -33,38 +36,39 @@ class UserModel {
|
|||||||
email: json['email'],
|
email: json['email'],
|
||||||
firstName: json['firstName'],
|
firstName: json['firstName'],
|
||||||
lastName: json['lastName'],
|
lastName: json['lastName'],
|
||||||
profilePicture: json['profilePicture'],
|
profilePicture: UserModel.decodeBase64Image(json['profilePicture']),
|
||||||
phoneNumber: json['phoneNumber'],
|
phoneNumber: json['phoneNumber'],
|
||||||
isEmailVerified: json['isEmailVerified'],
|
isEmailVerified: json['isEmailVerified'],
|
||||||
isAgreementAccepted: json['isAgreementAccepted'],
|
isAgreementAccepted: json['isAgreementAccepted'],
|
||||||
regionName: json['region']?['regionName'], // Extract regionName
|
regionName: json['region']?['regionName'], // Extract regionName
|
||||||
timeZone: json['timeZone']?['timeZoneOffset'], // Extract regionName
|
timeZone: json['timeZone']?['timeZoneOffset'], // Extract regionName
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//uuid to json
|
//uuid to json
|
||||||
|
|
||||||
//from token
|
//from token
|
||||||
factory UserModel.fromToken(Token token) {
|
factory UserModel.fromToken(Token token) {
|
||||||
Map<String, dynamic> tempJson = Token.decodeToken(token.accessToken);
|
Map<String, dynamic> tempJson = Token.decodeToken(token.accessToken);
|
||||||
|
|
||||||
return UserModel(
|
return UserModel(
|
||||||
uuid: tempJson['uuid'].toString(),
|
uuid: tempJson['uuid'].toString(),
|
||||||
email: tempJson['email'],
|
email: tempJson['email'],
|
||||||
lastName: tempJson['lastName'],
|
lastName: tempJson['lastName'],
|
||||||
firstName:tempJson['firstName'] ,
|
firstName:tempJson['firstName'] ,
|
||||||
profilePicture: tempJson['profilePicture'],
|
profilePicture: UserModel.decodeBase64Image(tempJson['profilePicture']),
|
||||||
phoneNumber: null,
|
phoneNumber: null,
|
||||||
isEmailVerified: null,
|
isEmailVerified: null,
|
||||||
isAgreementAccepted: null,
|
isAgreementAccepted: null,
|
||||||
regionName: tempJson['region']?['regionName'],
|
regionName: tempJson['region']?['regionName'],
|
||||||
timeZone: tempJson['timezone']?['timeZoneOffset'],
|
timeZone: tempJson['timezone']?['timeZoneOffset'],
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Uint8List? decodeBase64Image(String? base64String) {
|
||||||
|
if (base64String != null) {
|
||||||
|
return base64.decode(base64String);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'id': uuid,
|
'id': uuid,
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.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/profile_state.dart';
|
||||||
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_model.dart';
|
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_model.dart';
|
||||||
@ -16,6 +15,7 @@ import 'package:image_picker/image_picker.dart';
|
|||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
||||||
|
|
||||||
bool isSaving = false;
|
bool isSaving = false;
|
||||||
bool editName = false;
|
bool editName = false;
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
@ -24,7 +24,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
|||||||
String timeZoneSelected = '';
|
String timeZoneSelected = '';
|
||||||
String regionSelected = '';
|
String regionSelected = '';
|
||||||
final TextEditingController searchController = TextEditingController();
|
final TextEditingController searchController = TextEditingController();
|
||||||
final TextEditingController nameController = TextEditingController(text: '${AuthCubit.user!.firstName} ${AuthCubit.user!.lastName}');
|
final TextEditingController nameController = TextEditingController(text: '${HomeCubit.user!.firstName} ${HomeCubit.user!.lastName}');
|
||||||
List<TimeZone>? timeZoneList;
|
List<TimeZone>? timeZoneList;
|
||||||
List<RegionModel>? regionList;
|
List<RegionModel>? regionList;
|
||||||
|
|
||||||
@ -42,14 +42,30 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
|||||||
on<SelectRegionEvent>(selectRegion);
|
on<SelectRegionEvent>(selectRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List? decodeBase64Image(String? base64String) {
|
Future<void> saveName(SaveNameEvent event, Emitter<ProfileState> emit) async {
|
||||||
if (base64String != null) {
|
if (_validateInputs()) return;
|
||||||
final startIndex = base64String.indexOf('base64,') + 7;
|
try {
|
||||||
final pureBase64String = base64String.substring(startIndex);
|
add(const ChangeNameEvent(value: false));
|
||||||
return base64.decode(pureBase64String);
|
isSaving = true;
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
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());
|
||||||
|
final homeCubit = event.context.read<HomeCubit>();
|
||||||
|
await homeCubit.fetchUserInfo();
|
||||||
|
Navigator.of(event.context).pop(true);
|
||||||
|
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||||
|
emit(SaveState());
|
||||||
|
} catch (_) {
|
||||||
|
// Handle the error
|
||||||
|
} finally {
|
||||||
|
isSaving = false;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _changeName(ChangeNameEvent event, Emitter<ProfileState> emit) {
|
void _changeName(ChangeNameEvent event, Emitter<ProfileState> emit) {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
editName = event.value!;
|
editName = event.value!;
|
||||||
@ -66,7 +82,7 @@ class ProfileBloc extends Bloc<ProfileEvent, ProfileState> {
|
|||||||
void _fetchUserInfo(InitialProfileEvent event, Emitter<ProfileState> emit) async {
|
void _fetchUserInfo(InitialProfileEvent event, Emitter<ProfileState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
AuthCubit.user = await ProfileApi.fetchUserInfo(AuthCubit.user!.uuid);
|
HomeCubit.user = await ProfileApi().fetchUserInfo(HomeCubit.user!.uuid);
|
||||||
emit(SaveState());
|
emit(SaveState());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(FailedState(errorMessage: e.toString()));
|
emit(FailedState(errorMessage: e.toString()));
|
||||||
@ -212,28 +228,7 @@ 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(LoadingInitialState());
|
|
||||||
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() {
|
bool _validateInputs() {
|
||||||
if (nameController.text.length < 2) {
|
if (nameController.text.length < 2) {
|
||||||
|
@ -1,98 +1,90 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/widgets/profile/profile_view.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/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.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';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
|
||||||
class ProfileTab extends StatelessWidget {
|
class ProfileTab extends StatelessWidget {
|
||||||
final String? name;
|
const ProfileTab({super.key,});
|
||||||
const ProfileTab({super.key, this.name});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<AuthCubit, AuthState>(
|
return BlocBuilder<HomeCubit, HomeState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final user = AuthCubit.user;
|
return _buildProfileContent(context );
|
||||||
Uint8List? imageBytes;
|
},
|
||||||
if (user!.profilePicture != null) {
|
);
|
||||||
final base64String = user.profilePicture!;
|
}
|
||||||
final startIndex = base64String.indexOf('base64,') + 7;
|
|
||||||
final pureBase64String = base64String.substring(startIndex);
|
Widget _buildProfileContent(BuildContext context) {
|
||||||
imageBytes = base64.decode(pureBase64String);
|
final homeCubit = context.read<HomeCubit>();
|
||||||
}
|
return Padding(
|
||||||
return Padding(
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
child: InkWell(
|
||||||
child: InkWell(
|
onTap: () {
|
||||||
onTap: () {
|
Navigator.of(context)
|
||||||
Navigator.of(context)
|
.push(
|
||||||
.push(
|
MaterialPageRoute(
|
||||||
MaterialPageRoute(
|
builder: (context) => const ProfileView(),
|
||||||
builder: (context) => const ProfileView(),
|
),
|
||||||
),
|
).then((result) {
|
||||||
)
|
context.read<HomeCubit>().fetchUserInfo();
|
||||||
.then((result) {
|
});
|
||||||
if (result == true) {
|
},
|
||||||
context.read<AuthCubit>().fetchUserInfo();
|
child: Stack(
|
||||||
}
|
children: [
|
||||||
});
|
Column(
|
||||||
},
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
child: Stack(
|
|
||||||
children: [
|
children: [
|
||||||
Column(
|
const SizedBox(height: 20),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
DefaultContainer(
|
||||||
children: [
|
child: Column(
|
||||||
const SizedBox(height: 20),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
DefaultContainer(
|
children: [
|
||||||
child: Column(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
BodyMedium(
|
||||||
children: [
|
text: '${HomeCubit.user!.firstName ?? ''} ',
|
||||||
BodyMedium(
|
fontWeight: FontWeight.bold,
|
||||||
text: '${user.firstName!} ',
|
),
|
||||||
fontWeight: FontWeight.bold,
|
BodyMedium(
|
||||||
),
|
text: HomeCubit.user!.lastName ?? '',
|
||||||
BodyMedium(
|
fontWeight: FontWeight.bold,
|
||||||
text: user.lastName!,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const BodySmall(text: "Syncrow Account"),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
const 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: ClipOval(
|
||||||
|
child: HomeCubit.user?.profilePicture != null
|
||||||
|
? Image.memory(
|
||||||
|
HomeCubit.user!.profilePicture!,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
width: 110,
|
||||||
|
height: 110,
|
||||||
|
)
|
||||||
|
: Icon(Icons.person, size: 70), // Fallback if no image
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.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_bloc.dart';
|
||||||
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.dart';
|
import 'package:syncrow_app/features/menu/bloc/profile_bloc/profile_event.dart';
|
||||||
@ -18,14 +19,12 @@ class ProfileView extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (BuildContext context) => ProfileBloc()..add(InitialProfileEvent()),
|
create: (BuildContext context) => ProfileBloc()..add(InitialProfileEvent()),
|
||||||
child: BlocConsumer<ProfileBloc, ProfileState>(
|
child: BlocConsumer<ProfileBloc, ProfileState>(
|
||||||
listener: (context, state) {},
|
listener: (context, state) {},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final profileBloc = BlocProvider.of<ProfileBloc>(context);
|
final profileBloc = BlocProvider.of<ProfileBloc>(context);
|
||||||
Uint8List? imageBytes = profileBloc.decodeBase64Image(AuthCubit.user!.profilePicture);
|
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: 'Syncrow Account',
|
title: 'Syncrow Account',
|
||||||
child:
|
child:
|
||||||
@ -54,10 +53,10 @@ class ProfileView extends StatelessWidget {
|
|||||||
: FileImage(profileBloc.image!),
|
: FileImage(profileBloc.image!),
|
||||||
child: profileBloc.image != null
|
child: profileBloc.image != null
|
||||||
? null
|
? null
|
||||||
:imageBytes != null
|
:HomeCubit.user!.profilePicture != null
|
||||||
? ClipOval(
|
? ClipOval(
|
||||||
child: Image.memory(
|
child: Image.memory(
|
||||||
imageBytes,
|
HomeCubit.user!.profilePicture!,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
width: 110,
|
width: 110,
|
||||||
height: 110,
|
height: 110,
|
||||||
@ -121,11 +120,8 @@ class ProfileView extends StatelessWidget {
|
|||||||
vertical: 5,
|
vertical: 5,
|
||||||
),
|
),
|
||||||
child:
|
child:
|
||||||
BlocBuilder<AuthCubit, AuthState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
final user = AuthCubit.user;
|
|
||||||
|
|
||||||
return Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@ -137,17 +133,16 @@ class ProfileView extends StatelessWidget {
|
|||||||
builder: (context) => const RegionPage(),
|
builder: (context) => const RegionPage(),
|
||||||
),
|
),
|
||||||
).then((result) {
|
).then((result) {
|
||||||
context.read<AuthCubit>().fetchUserInfo();
|
profileBloc.add(InitialProfileEvent());
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 20, bottom: 20),
|
padding: const EdgeInsets.only(top: 20, bottom: 20),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const BodyMedium(text: 'Region '),
|
const BodyMedium(text: 'Region '),
|
||||||
Flexible(child: BodyMedium(text: user!.regionName??'No Region')),
|
Flexible(child: BodyMedium(text: HomeCubit.user!.regionName ?? 'No Region')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -164,24 +159,25 @@ class ProfileView extends StatelessWidget {
|
|||||||
builder: (context) => const TimeZoneScreenPage(),
|
builder: (context) => const TimeZoneScreenPage(),
|
||||||
),
|
),
|
||||||
).then((result) {
|
).then((result) {
|
||||||
context.read<AuthCubit>().fetchUserInfo();
|
profileBloc.add(InitialProfileEvent());
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
const BodyMedium(text: 'Time Zone '),
|
const BodyMedium(text: 'Time Zone '),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: BodyMedium(text: user.timeZone??"No Time Zone"),
|
child: BodyMedium(text: HomeCubit.user!.timeZone ?? "No Time Zone"),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);}),
|
)
|
||||||
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -61,8 +61,7 @@ class RegionPage extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
profileBloc.add(SelectRegionEvent(
|
profileBloc.add(SelectRegionEvent(
|
||||||
val: regionList[index].id,
|
val: regionList[index].id, context: context));
|
||||||
context: context));
|
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
@ -18,7 +18,6 @@ class _SplashViewState extends State<SplashView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
AuthCubit.get(context).getTokenAndValidate();
|
AuthCubit.get(context).getTokenAndValidate();
|
||||||
AuthCubit.get(context).fetchUserInfo();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||||
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||||
import 'package:syncrow_app/features/menu/bloc/profile_bloc/region_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';
|
import 'package:syncrow_app/features/menu/bloc/profile_bloc/time_zone_model.dart';
|
||||||
@ -12,7 +12,7 @@ class ProfileApi {
|
|||||||
static Future<Map<String, dynamic>> saveName({String? firstName, String? lastName,}) async {
|
static Future<Map<String, dynamic>> saveName({String? firstName, String? lastName,}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.saveName.replaceAll('{userUuid}', AuthCubit.user!.uuid!),
|
path: ApiEndpoints.saveName.replaceAll('{userUuid}', HomeCubit.user!.uuid!),
|
||||||
body: {
|
body: {
|
||||||
"firstName": firstName,
|
"firstName": firstName,
|
||||||
"lastName": lastName
|
"lastName": lastName
|
||||||
@ -30,7 +30,7 @@ class ProfileApi {
|
|||||||
static Future saveRegion({String? regionUuid,}) async {
|
static Future saveRegion({String? regionUuid,}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.saveRegion.replaceAll('{userUuid}', AuthCubit.user!.uuid!),
|
path: ApiEndpoints.saveRegion.replaceAll('{userUuid}', HomeCubit.user!.uuid!),
|
||||||
body: {
|
body: {
|
||||||
"regionUuid": regionUuid,
|
"regionUuid": regionUuid,
|
||||||
},
|
},
|
||||||
@ -46,7 +46,7 @@ class ProfileApi {
|
|||||||
static Future saveTimeZone({String? regionUuid,}) async {
|
static Future saveTimeZone({String? regionUuid,}) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.saveTimeZone.replaceAll('{userUuid}', AuthCubit.user!.uuid!),
|
path: ApiEndpoints.saveTimeZone.replaceAll('{userUuid}', HomeCubit.user!.uuid!),
|
||||||
body: {
|
body: {
|
||||||
"timezoneUuid": regionUuid,
|
"timezoneUuid": regionUuid,
|
||||||
},
|
},
|
||||||
@ -63,7 +63,7 @@ class ProfileApi {
|
|||||||
static Future<Map<String, dynamic>> saveImage(String image) async {
|
static Future<Map<String, dynamic>> saveImage(String image) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.put(
|
final response = await _httpService.put(
|
||||||
path: ApiEndpoints.sendPicture.replaceAll('{userUuid}', AuthCubit.user!.uuid!),
|
path: ApiEndpoints.sendPicture.replaceAll('{userUuid}', HomeCubit.user!.uuid!),
|
||||||
body: {
|
body: {
|
||||||
"profilePicture": 'data:image/png;base64,$image'
|
"profilePicture": 'data:image/png;base64,$image'
|
||||||
},
|
},
|
||||||
@ -77,11 +77,13 @@ class ProfileApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future fetchUserInfo(userId) async {
|
Future fetchUserInfo(userId) async {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId!),
|
path: ApiEndpoints.getUser.replaceAll('{userUuid}', userId!),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) =>UserModel.fromJson(json)
|
expectedResponseModel: (json) {
|
||||||
|
return UserModel.fromJson(json);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user