Skip to content

Commit

Permalink
added profile page
Browse files Browse the repository at this point in the history
  • Loading branch information
adelp13 committed Feb 1, 2025
1 parent 83fd86b commit 62080bc
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 35 deletions.
16 changes: 12 additions & 4 deletions backend/controllers/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ RouterPlus authRouter() {

router.get('/details', (Request req) async {
final user = await getUser(req);
return {
'id' : user!.id,
'name': user.userMetadata?['name'],
};
if (user != null) {
//print("User Data: ${user.toJson()}");
print(user.createdAt);
return {
'id': user.id,
'name': user.userMetadata?['name'],
'email': user.email,
'lastSignIn': user.lastSignInAt,
'createdAt': user.createdAt,
};
}
return {'error': 'User not found'};
});

router.post('/login', (Request req) async {
Expand Down
7 changes: 6 additions & 1 deletion lib/Library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import 'Widgets/media_widgets.dart';

import 'Main.dart';
import 'UserSystem.dart';
import 'ProfilePage.dart';

class Library<MT extends MediaType> extends StatefulWidget {
late final bool isWishlist;
Expand Down Expand Up @@ -434,7 +435,11 @@ class LibraryState<MT extends MediaType> extends State<Library> {
tooltip: 'Toggle dark mode',
),
TextButton(
onPressed: () {}, // TODO: profile page
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => ProfilePage()),
);
},
style: navigationButton(context)
.filledButtonTheme
.style,
Expand Down
85 changes: 55 additions & 30 deletions lib/Menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'Models/movie.dart';
import 'Models/tv_series.dart';
import 'package:flutter/material.dart';
import 'package:adaptive_theme/adaptive_theme.dart';
import 'ProfilePage.dart';

class MenuPage extends StatelessWidget {
const MenuPage({super.key});
Expand Down Expand Up @@ -95,6 +96,9 @@ class MenuState extends State<Menu> {
@override
Widget build(BuildContext context) {
MenuMediaType currentRendering = MenuMediaType.Game;
Map<MenuMediaType, bool> hoverState = {
for (var type in MenuMediaType.values) type: false
};

return Scaffold(
appBar: AppBar(
Expand All @@ -109,6 +113,15 @@ class MenuState extends State<Menu> {
icon: const Icon(Icons.dark_mode),
tooltip: 'Toggle dark mode',
),
IconButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => ProfilePage()),
);
},
icon: const Icon(Icons.account_circle),
tooltip: 'Go to Profile',
),
IconButton(
onPressed: () async {
UserSystem.instance.logout();
Expand All @@ -124,45 +137,56 @@ class MenuState extends State<Menu> {
),
body: StatefulBuilder(
builder: (context, setState) {
Widget option(MenuMediaType type) => InkWell(
child: Container(
constraints: const BoxConstraints(
minHeight: 50,
minWidth: 130,
),
child: Card(
child: Center(
widthFactor: 1,
heightFactor: 1,
child: Text(
mapping[type]!['name'],
style: titleStyle,
Widget option(MenuMediaType type) => MouseRegion(
onEnter: (_) {
setState(() {
currentRendering = type;
hoverState[type] = true;
});
},
onExit: (_) {
setState(() {
hoverState[type] = false;
});
},
child: GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => mapping[type]!['library']!,
));
},
child: Container(
constraints: const BoxConstraints(
minHeight: 50,
minWidth: 130,
),
decoration: BoxDecoration(
color: (hoverState[type] ?? false) ? Colors.greenAccent : Colors.blue,
borderRadius: BorderRadius.circular(16),
),
child: Card(
child: Center(
widthFactor: 1,
heightFactor: 1,
child: Text(
mapping[type]!['name'],
style: titleStyle.copyWith(
fontSize: (hoverState[type] ?? false) ? 19 : 18,
// fontWeight: FontWeight.bold,
// color: Colors.white,
),
),
),
borderOnForeground: true,
),
borderOnForeground: true,
),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(16),
),
),
onHover: (bool hover) {
if (hover) {
currentRendering = type;
setState(() {});
}
},
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => mapping[type]!['library']!,
));
},
);

return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: mapping[currentRendering]!['backgroundImage'],
image: NetworkImage(mapping[currentRendering]!['backgroundImageHref']),
fit: BoxFit.cover,
),
),
Expand All @@ -185,4 +209,5 @@ class MenuState extends State<Menu> {
),
);
}

}
146 changes: 146 additions & 0 deletions lib/ProfilePage.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'UserSystem.dart';

class ProfilePage extends StatefulWidget {
const ProfilePage({super.key});

@override
_ProfilePageState createState() => _ProfilePageState();
}

class _ProfilePageState extends State<ProfilePage> {
var name = UserSystem.instance.currentUserData!['name'] ?? 'Unknown User';
var email = UserSystem.instance.currentUserData!['email'] ?? 'Unknown Email';
var lastSignInRaw = UserSystem.instance.currentUserData!['lastSignIn'] ?? '';
var memberSinceRaw = UserSystem.instance.currentUserData!['createdAt'] ?? '';

String _profileImageUrl = 'https://picsum.photos/200/200?random=1';

String formatLastLogin(String dateString) {
if (dateString.isEmpty) return "Unknown";
DateTime date = DateTime.parse(dateString);
return DateFormat('dd MMM yyyy HH:mm').format(date);
}

String formatMemberSince(String dateString) {
if (dateString.isEmpty) return "Unknown";
DateTime date = DateTime.parse(dateString);
return DateFormat('dd MMM yyyy').format(date);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Profile Page'),
backgroundColor: Colors.black,
foregroundColor: Colors.white,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: _showImageSelectionDialog,
child: CircleAvatar(
radius: 50,
backgroundImage: NetworkImage(_profileImageUrl),
backgroundColor: Colors.grey,
),
),
const SizedBox(height: 16),
Text(
name == 'Guest' ? 'This account is a guest' : name,
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
if (name != 'Guest') ...[
Text(
email,
style: const TextStyle(
fontSize: 16,
color: Colors.white,
),
),
],
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_infoCard(context, "Last Login", formatLastLogin(lastSignInRaw), "Member Since", formatMemberSince(memberSinceRaw)),
],
),
],
),
),
);
}

void _showImageSelectionDialog() {
List<String> imageUrls = List.generate(
10, (index) => 'https://picsum.photos/200/200?random=${index + 1}'
);

showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Choose Profile Picture', style: TextStyle(color: Colors.white)),
backgroundColor: Colors.black,
content: SingleChildScrollView(
child: Wrap(
spacing: 8.0,
children: imageUrls.map((imageUrl) {
return GestureDetector(
onTap: () {
setState(() {
_profileImageUrl = imageUrl;
});
Navigator.of(context).pop();
},
child: Padding(
padding: const EdgeInsets.all(4.0),
child: CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(imageUrl),
backgroundColor: Colors.grey,
),
),
);
}).toList(),
),
),
);
},
);
}

Widget _infoCard(BuildContext context, String title1, String value1, String title2, String value2) {
return Container(
padding: const EdgeInsets.all(16),
width: MediaQuery.of(context).size.width / 2.5,
decoration: BoxDecoration(
color: Colors.grey[800],
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.grey.shade600),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title1, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.white)),
const SizedBox(height: 4),
Text(value1, style: const TextStyle(fontSize: 14, color: Colors.white)),
const SizedBox(height: 12),
Text(title2, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.white)),
const SizedBox(height: 4),
Text(value2, style: const TextStyle(fontSize: 14, color: Colors.white)),
],
),
);
}
}

0 comments on commit 62080bc

Please sign in to comment.