211 lines
7.6 KiB
Dart
211 lines
7.6 KiB
Dart
|
import 'package:flutter/material.dart';
|
||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||
|
import 'package:image_picker/image_picker.dart';
|
||
|
import 'dart:io';
|
||
|
|
||
|
import '../constants.dart';
|
||
|
|
||
|
class EditProfilePage extends StatefulWidget {
|
||
|
final Map<String, dynamic> userData;
|
||
|
|
||
|
const EditProfilePage({super.key, required this.userData});
|
||
|
|
||
|
@override
|
||
|
EditProfilePageState createState() => EditProfilePageState();
|
||
|
}
|
||
|
|
||
|
class EditProfilePageState extends State<EditProfilePage> {
|
||
|
final _formKey = GlobalKey<FormState>();
|
||
|
late TextEditingController _nameController;
|
||
|
late TextEditingController _bioController;
|
||
|
late String? profileImageUrl;
|
||
|
File? _profileImage;
|
||
|
|
||
|
@override
|
||
|
void initState() {
|
||
|
super.initState();
|
||
|
_nameController = TextEditingController(
|
||
|
text: widget.userData[Constants.dbFieldUsersName]);
|
||
|
_bioController =
|
||
|
TextEditingController(text: widget.userData[Constants.dbFieldUsersBio]);
|
||
|
if (widget.userData[Constants.dbFieldUsersProfilePic] != null) {
|
||
|
profileImageUrl = widget.userData[Constants.dbFieldUsersProfilePic];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Future<void> _pickImage() async {
|
||
|
final pickedFile =
|
||
|
await ImagePicker().pickImage(source: ImageSource.gallery);
|
||
|
if (pickedFile != null) {
|
||
|
setState(() {
|
||
|
_profileImage = File(pickedFile.path);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void _clearProfileImage() {
|
||
|
setState(() {
|
||
|
_profileImage = null;
|
||
|
widget.userData[Constants.dbFieldUsersProfilePic] = null;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Future<void> _saveProfile() async {
|
||
|
if (_formKey.currentState!.validate()) {
|
||
|
String uid = FirebaseAuth.instance.currentUser!.uid;
|
||
|
|
||
|
if (_profileImage != null) {
|
||
|
final storageRef = FirebaseStorage.instance
|
||
|
.ref()
|
||
|
.child(Constants.dbStoragePathProfiles)
|
||
|
.child(uid); // filename = userid
|
||
|
await storageRef.putFile(_profileImage!);
|
||
|
profileImageUrl = await storageRef.getDownloadURL();
|
||
|
} else {
|
||
|
profileImageUrl = null;
|
||
|
}
|
||
|
|
||
|
String name = _nameController.text;
|
||
|
String bio = _bioController.text;
|
||
|
|
||
|
await FirebaseFirestore.instance
|
||
|
.collection(Constants.dbCollectionUsers)
|
||
|
.doc(uid)
|
||
|
.update({
|
||
|
Constants.dbFieldUsersName: name,
|
||
|
Constants.dbFieldUsersBio: bio,
|
||
|
//if (profileImageUrl != null)
|
||
|
Constants.dbFieldUsersProfilePic: profileImageUrl,
|
||
|
});
|
||
|
|
||
|
Navigator.pop(context, {
|
||
|
Constants.dbFieldUsersProfilePic: profileImageUrl,
|
||
|
Constants.dbFieldUsersName: name,
|
||
|
Constants.dbFieldUsersBio: bio,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return Scaffold(
|
||
|
appBar: AppBar(
|
||
|
title: const Text('Edit Profile'),
|
||
|
),
|
||
|
body: Padding(
|
||
|
padding: const EdgeInsets.all(16.0),
|
||
|
child: Form(
|
||
|
key: _formKey,
|
||
|
child: ListView(
|
||
|
children: [
|
||
|
Center(
|
||
|
child: Row(
|
||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||
|
children: [
|
||
|
GestureDetector(
|
||
|
onTap: _pickImage,
|
||
|
child: Stack(
|
||
|
children: [
|
||
|
CircleAvatar(
|
||
|
radius: 50,
|
||
|
backgroundImage: _profileImage != null
|
||
|
? FileImage(_profileImage!) as ImageProvider
|
||
|
: (widget.userData[
|
||
|
Constants.dbFieldUsersProfilePic] !=
|
||
|
null
|
||
|
? NetworkImage(widget.userData[
|
||
|
Constants.dbFieldUsersProfilePic])
|
||
|
as ImageProvider
|
||
|
: null),
|
||
|
child: ClipOval(
|
||
|
child: _profileImage == null &&
|
||
|
widget.userData[Constants
|
||
|
.dbFieldUsersProfilePic] ==
|
||
|
null
|
||
|
? const Icon(Icons.person, size: 50)
|
||
|
: SizedBox(
|
||
|
width: 100,
|
||
|
height: 100,
|
||
|
child: _profileImage != null
|
||
|
? Image.file(
|
||
|
_profileImage!,
|
||
|
fit: BoxFit.cover,
|
||
|
)
|
||
|
: (widget.userData[Constants
|
||
|
.dbFieldUsersProfilePic] !=
|
||
|
null
|
||
|
? Image.network(
|
||
|
widget.userData[Constants
|
||
|
.dbFieldUsersProfilePic],
|
||
|
fit: BoxFit.cover,
|
||
|
)
|
||
|
: null),
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
Positioned(
|
||
|
bottom: 0,
|
||
|
right: 0,
|
||
|
child: IconButton(
|
||
|
icon: Ink(
|
||
|
decoration: ShapeDecoration(
|
||
|
color: Theme.of(context).colorScheme.primary,
|
||
|
shape: const CircleBorder(),
|
||
|
),
|
||
|
child: const Icon(Icons.edit)),
|
||
|
onPressed: _pickImage,
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
if (_profileImage != null)
|
||
|
IconButton(
|
||
|
icon: Ink(
|
||
|
decoration: const ShapeDecoration(
|
||
|
shape: CircleBorder(),
|
||
|
),
|
||
|
child: const Icon(
|
||
|
Icons.delete,
|
||
|
color: Colors.red,
|
||
|
size: 32,
|
||
|
),
|
||
|
),
|
||
|
onPressed: _clearProfileImage,
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
const SizedBox(height: 16),
|
||
|
TextFormField(
|
||
|
controller: _nameController,
|
||
|
decoration: const InputDecoration(labelText: 'Name'),
|
||
|
validator: (value) {
|
||
|
if (value == null || value.isEmpty) {
|
||
|
return 'Please enter a name';
|
||
|
}
|
||
|
return null;
|
||
|
},
|
||
|
),
|
||
|
const SizedBox(height: 16),
|
||
|
TextFormField(
|
||
|
controller: _bioController,
|
||
|
decoration: const InputDecoration(labelText: 'Bio'),
|
||
|
maxLines: 3,
|
||
|
),
|
||
|
const SizedBox(height: 16),
|
||
|
ElevatedButton(
|
||
|
onPressed: _saveProfile,
|
||
|
child: const Text('Save'),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|