396 lines
13 KiB
Dart
396 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import '../services/googleAuthService.dart';
|
|
import 'package:insparkspokalen_ui/services/backend/teamService.dart';
|
|
import 'package:insparkspokalen_ui/services/backend/userService.dart';
|
|
import 'package:insparkspokalen_ui/services/image_service.dart';
|
|
import 'package:insparkspokalen_ui/models/userModel.dart';
|
|
import 'package:insparkspokalen_ui/models/teamModel.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:insparkspokalen_ui/services/teamUserSyncService.dart';
|
|
|
|
class ProfilePage extends StatefulWidget {
|
|
const ProfilePage({super.key});
|
|
|
|
@override
|
|
State<ProfilePage> createState() => _ProfilePageState();
|
|
}
|
|
|
|
class _ProfilePageState extends State<ProfilePage> {
|
|
String? userName;
|
|
String? profilePicture;
|
|
List<UserModel> teamMembers = [];
|
|
bool isLoadingTeamMembers = false;
|
|
TeamModel? team;
|
|
int? userTeamId;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_initializeSyncService();
|
|
_loadUser();
|
|
_loadTeamMembers();
|
|
// _debugCheckEndpoints();
|
|
}
|
|
|
|
void _loadUser() {
|
|
final user = GoogleAuthService.getCurrentUser();
|
|
print('DEBUG _loadUser: Current user: ${user?.profilePicture}'); // todo remove debug
|
|
print('DEBUG _loadUser: Current user: ${user?.teamId}'); // todo remove debug
|
|
|
|
if (user != null && user.profilePicture != null) {
|
|
setState(() {
|
|
userName = user.name;
|
|
profilePicture = user.profilePicture;
|
|
print('DEBUG profilepictureurl: $profilePicture'); // todo remove debug
|
|
});
|
|
|
|
//Hämtar profilbild direkt från Google -- fundera på annan lösning?
|
|
if (profilePicture == null || profilePicture!.isEmpty) {
|
|
final account = GoogleAuthService.getCurrentUser();
|
|
if (account != null && account.profilePicture != null) {
|
|
setState(() {
|
|
profilePicture = account.profilePicture;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> _initializeSyncService() async {
|
|
final currentUser = GoogleAuthService.getCurrentUser();
|
|
if (currentUser != null) {
|
|
GoogleAuthService.setCurrentUser(currentUser);
|
|
}
|
|
}
|
|
|
|
Future<void> _loadTeamMembers() async {
|
|
setState(() => isLoadingTeamMembers = true);
|
|
try {
|
|
print('DEBUG: Starting to load team members...');
|
|
final currentUser = GoogleAuthService.getCurrentUser();
|
|
print('DEBUG: Current user: ${currentUser?.toJson()}');
|
|
if (currentUser == null) { // User is not logged in
|
|
setState(() => isLoadingTeamMembers = false);
|
|
return;
|
|
}
|
|
|
|
if (currentUser.teamId == null) { // if teamId is null
|
|
setState(() {
|
|
teamMembers = [];
|
|
isLoadingTeamMembers = false;
|
|
});
|
|
return;
|
|
}
|
|
|
|
final team = await TeamService().getTeamById(currentUser.teamId);
|
|
if (team != null) {
|
|
setState(() {
|
|
this.team = team;
|
|
});
|
|
}
|
|
|
|
final members = await TeamService().getTeamMembers(currentUser.teamId);
|
|
|
|
final filteredMembers =
|
|
members.where((member) => member.email != currentUser.email).toList();
|
|
|
|
for (var member in members) {
|
|
print(
|
|
'👤 DEBUG: Member: ${member.name} (${member.email}) - Picture: ${member.profilePicture}',
|
|
);
|
|
}
|
|
|
|
setState(() {
|
|
teamMembers = filteredMembers;
|
|
isLoadingTeamMembers = false;
|
|
});
|
|
} catch (e, stackTrace) {
|
|
print('DEBUG: Error loading team members: $e');
|
|
print('DEBUG: Stack trace: $stackTrace');
|
|
setState(() => isLoadingTeamMembers = false);
|
|
}
|
|
}
|
|
|
|
//Method to show the initial if they dont have a picture
|
|
Widget _buildAvatar({
|
|
required String? imageUrl,
|
|
double radius = 25,
|
|
String? name,
|
|
}) {
|
|
final bool isFirebaseSvg = imageUrl != null && imageUrl.contains('firebasestorage.googleapis.com');
|
|
|
|
return Container(
|
|
width: radius * 2,
|
|
height: radius * 2,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: Colors.grey[700],
|
|
),
|
|
child: ClipOval(
|
|
child: imageUrl != null && imageUrl.isNotEmpty
|
|
? isFirebaseSvg
|
|
? SvgPicture.network(
|
|
imageUrl,
|
|
width: radius * 2,
|
|
height: radius * 2,
|
|
fit: BoxFit.cover,
|
|
placeholderBuilder: (context) =>
|
|
Center(child: CircularProgressIndicator()),
|
|
)
|
|
: Image.network(
|
|
imageUrl,
|
|
width: radius * 2,
|
|
height: radius * 2,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (_, __, ___) => Center(
|
|
child: Icon(Icons.broken_image, color: Colors.white),
|
|
),
|
|
)
|
|
: Center(
|
|
child: name != null && name.isNotEmpty
|
|
? Text(
|
|
name[0].toUpperCase(),
|
|
style: TextStyle(
|
|
fontSize: radius * 0.8,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
)
|
|
: Icon(Icons.person, size: radius, color: Colors.grey),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
|
|
Future<void> _pickAndUploadTeamImage() async {
|
|
final picker = ImagePicker();
|
|
|
|
final source = await showModalBottomSheet<ImageSource>(
|
|
context: context,
|
|
builder:
|
|
(_) => Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
ListTile(
|
|
leading: const Icon(Icons.camera_alt),
|
|
title: const Text("Ta bild"),
|
|
onTap: () => Navigator.pop(context, ImageSource.camera),
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.photo_library),
|
|
title: const Text("Välj från galleri"),
|
|
onTap: () => Navigator.pop(context, ImageSource.gallery),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
if (source == null) return;
|
|
|
|
try {
|
|
final pickedImage = await picker.pickImage(source: source);
|
|
if (pickedImage == null) return;
|
|
|
|
final imageService = ImageService();
|
|
final downloadUrl = await imageService.upload(pickedImage);
|
|
|
|
if (downloadUrl == null) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Misslyckades med att ladda upp bilden')),
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (userTeamId == null) {
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(SnackBar(content: Text('Ingen teamId hittades')));
|
|
return;
|
|
}
|
|
|
|
// Skicka URL till backend
|
|
await TeamService().setTeamProfilePicture(userTeamId!, downloadUrl);
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Profilbild för laget uppladdad!')),
|
|
);
|
|
} catch (e) {
|
|
print('Fel vid uppladdning: $e');
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(SnackBar(content: Text('Något gick fel. Försök igen.')));
|
|
}
|
|
}
|
|
//
|
|
// void _debugCheckEndpoints() async {
|
|
// try {
|
|
//
|
|
// final teamService = TeamService();
|
|
//
|
|
//
|
|
// // Try to get all teams to test connection
|
|
// final teams = await teamService.showTeams();
|
|
// print('DEBUG: Can connect to backend. Found ${teams.length} teams');
|
|
// } catch (e) {
|
|
// print('DEBUG: Cannot connect to backend: $e');
|
|
// }
|
|
// }
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: const Color(0xFF212121),
|
|
appBar: AppBar(
|
|
backgroundColor: const Color(0xFF212121),
|
|
elevation: 0,
|
|
iconTheme: const IconThemeData(color: Color(0xFFDAA520)),
|
|
title: const Text('Profil', style: TextStyle(color: Color(0xFFDAA520))),
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.logout, color: Color(0xFFDAA520)),
|
|
onPressed: () async {
|
|
await GoogleAuthService.logout(context);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: SafeArea(
|
|
child: Center(
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
_buildAvatar(
|
|
imageUrl: profilePicture,
|
|
radius: 50,
|
|
name: userName,
|
|
),
|
|
const SizedBox(height: 20),
|
|
Text(
|
|
userName ?? 'Inloggad som gäst',
|
|
style: const TextStyle(
|
|
fontSize: 24,
|
|
color: Color(0xFFDAA520),
|
|
),
|
|
),
|
|
if (team?.name != null) ...[
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 6,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFDAA520).withOpacity(0.2),
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(
|
|
color: Color(0xFFDAA520).withOpacity(0.5),
|
|
),
|
|
),
|
|
child: Text(
|
|
'${team?.name}',
|
|
style: const TextStyle(
|
|
fontSize: 16,
|
|
color: Color(0xFFDAA520),
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
const SizedBox(height: 20),
|
|
Container(
|
|
padding: const EdgeInsets.all(10),
|
|
width: MediaQuery.of(context).size.width * 0.8,
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[800],
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'Lagmedlemmar:',
|
|
style: TextStyle(color: Colors.white, fontSize: 18),
|
|
),
|
|
const SizedBox(height: 10),
|
|
isLoadingTeamMembers
|
|
? const Center(child: CircularProgressIndicator())
|
|
: teamMembers.isEmpty
|
|
? FutureBuilder<int?>(
|
|
future: UserService().getUserTeamByEmail(
|
|
GoogleAuthService.getCurrentUser()?.email ?? '',
|
|
),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasData &&
|
|
snapshot.data != null &&
|
|
snapshot.data != 0) {
|
|
return const Text(
|
|
'Du är ensam i ditt lag.',
|
|
style: TextStyle(color: Colors.white70),
|
|
);
|
|
} else {
|
|
return const Text(
|
|
'Logga in för att se dina lagmedlemmar',
|
|
style: TextStyle(color: Colors.white70),
|
|
);
|
|
}
|
|
},
|
|
)
|
|
: ListView.builder(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount: teamMembers.length,
|
|
itemBuilder: (context, index) {
|
|
final member = teamMembers[index];
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 12),
|
|
child: ListTile(
|
|
leading: _buildAvatar(
|
|
imageUrl: member.profilePicture,
|
|
name: member.name,
|
|
),
|
|
title: Text(
|
|
member.name,
|
|
style: const TextStyle(color: Colors.white),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 24),
|
|
OutlinedButton.icon(
|
|
onPressed: _pickAndUploadTeamImage,
|
|
icon: const Icon(Icons.upload, color: Color(0xFFDAA520)),
|
|
label: const Text(
|
|
'Ladda upp lagets profilbild',
|
|
style: TextStyle(color: Color(0xFFDAA520)),
|
|
),
|
|
style: OutlinedButton.styleFrom(
|
|
backgroundColor: Color(0xFFDAA520).withOpacity(0.2),
|
|
side: BorderSide(color: Color(0xFFDAA520).withOpacity(0.5)),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 24,
|
|
vertical: 14,
|
|
),
|
|
),
|
|
),
|
|
|
|
const SizedBox(height: 40),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|