import 'dart:convert'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; class ProfilePage extends StatefulWidget { @override _ProfilePageState createState() => _ProfilePageState(); } class _ProfilePageState extends State { bool _isLoading = true; String? _name; int? _uid; int? _elo; List _matches = []; final String _getProfileApiUrl = 'http://api.dthpp.mercurio.moe/getprofile'; @override void initState() { super.initState(); _fetchProfileData(); } Future _fetchProfileData() async { final prefs = await SharedPreferences.getInstance(); final String? token = prefs.getString('token'); if (token == null) { _showToast('No token found. Please login again.'); return; } try { final response = await http.post( Uri.parse(_getProfileApiUrl), headers: {'Content-Type': 'application/json'}, body: json.encode({'token': token}), ); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { _name = data['name']; _uid = data['uid']; _elo = data['elo']; _matches = data['matches']; _isLoading = false; }); } else { _showToast('Failed to fetch profile data.'); } } catch (e) { _showToast('Error: $e'); } } Color _generateRandomColor() { final random = Random(); return Color.fromARGB( 255, random.nextInt(256), random.nextInt(256), random.nextInt(256), ); } void _showToast(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); } @override Widget build(BuildContext context) { return Scaffold( body: _isLoading ? Center(child: CircularProgressIndicator()) : RefreshIndicator( onRefresh: _fetchProfileData, child: Column( children: [ // Profile Details Container( padding: EdgeInsets.all(16.0), child: Row( children: [ // Profile Icon CircleAvatar( backgroundColor: _generateRandomColor(), child: Text( _name != null && _name!.isNotEmpty ? _name![0].toUpperCase() : '?', style: TextStyle(fontSize: 24, color: Colors.white), ), radius: 40, ), SizedBox(width: 16), // Profile Info Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _name ?? 'Name not available', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), SizedBox(height: 8), Text('UID: ${_uid ?? 'N/A'}'), Text('ELO: ${_elo ?? 'N/A'}'), ], ), ], ), ), SizedBox(height: 16), // Recent Matches Expanded( child: _matches.isEmpty ? Center( child: Text( "You haven't played any matches yet", style: TextStyle( fontSize: 16, color: Colors.grey, ), ), ) : ListView.builder( itemCount: _matches.length, itemBuilder: (context, index) { final match = _matches[index]; final result = match['result']; final eloChange = match['elo_change']; return Card( margin: EdgeInsets.symmetric( horizontal: 16.0, vertical: 8.0), child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Match ID: ${match['match_id']}', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), Text('Opponent: ${match['opponent_name']}'), Row( children: [ Text( '$result', style: TextStyle( fontWeight: FontWeight.bold, color: result == 'Win' ? Colors.green : Colors.red, ), ), SizedBox(width: 16), if (eloChange != null) Text( 'ELO Change: ${eloChange > 0 ? '+' : ''}$eloChange', style: TextStyle( color: eloChange > 0 ? Colors.green : Colors.red, ), ), ], ), ], ), ), ); }, ), ), ], ), ), ); } }