Skip to content

Commit

Permalink
Enhance user profile navigation and details
Browse files Browse the repository at this point in the history
Fixes #391

Add functionality to surf other user profiles and update user profile details.

* **User Profile Page (`lib/src/pages/home/profile.dart`)**
  - Add a new constructor parameter `user` to the `UserProfile` class to accept a `User` object.
  - Update the `getProfilePicture`, `build`, and `initState` methods to use the `user` parameter instead of `currentUser`.
  - Update various UI elements to display the `user` details instead of `currentUser`.

* **Global Leaderboard Page (`lib/src/pages/leaderboards/global_leaderboard.dart`)**
  - Update the `ListTile` widget to include an `onTap` callback that navigates to the `UserProfile` page with the selected user.

* **Monthly Leaderboard Page (`lib/src/pages/leaderboards/monthly_leaderboard.dart`)**
  - Update the `ListTile` widget to include an `onTap` callback that navigates to the `UserProfile` page with the selected user.

* **Issue Detail Page (`lib/src/pages/issues/issue_detail.dart`)**
  - Update the `Markdown` widget to include an `onTapLink` callback that navigates to the `UserProfile` page with the selected user.

* **State Provider (`lib/src/pages/sizzle/sizzle_state_provider.dart`)**
  - Add a new `StateProvider<User?>` to store the selected user for profile navigation.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/OWASP-BLT/BLT-Flutter/issues/391?shareId=XXXX-XXXX-XXXX-XXXX).
  • Loading branch information
DonnieBLT committed Oct 16, 2024
1 parent 6e1f072 commit ebd9f8c
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 30 deletions.
56 changes: 29 additions & 27 deletions lib/src/pages/home/profile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import 'package:http/http.dart' as http;
/// Page that displays the stats of a user registered on BLT,
/// shows dummy data for Guest login.
class UserProfile extends ConsumerStatefulWidget {
final User user;

const UserProfile({
Key? key,
User? user,
required this.user,
}) : super(key: key);

@override
Expand All @@ -19,10 +21,10 @@ class _UserProfileState extends ConsumerState<UserProfile> {
late Future<List<Issue>?> getFlaggedList;

ImageProvider<Object> getProfilePicture() {
if (currentUser!.pfpLink == null) {
if (widget.user.pfpLink == null) {
return AssetImage("assets/default_profile.png");
} else {
return NetworkImage(currentUser!.pfpLink!);
return NetworkImage(widget.user.pfpLink!);
}
}

Expand Down Expand Up @@ -335,30 +337,30 @@ class _UserProfileState extends ConsumerState<UserProfile> {

@override
void initState() {
getLikedList = (currentUser! == guestUser)
getLikedList = (widget.user == guestUser)
? getAnonymousUserIssueList()
: getIssueList(
currentUser!.likedIssueId != null
? (currentUser!.likedIssueId!.length > 0
? currentUser!.likedIssueId!
widget.user.likedIssueId != null
? (widget.user.likedIssueId!.length > 0
? widget.user.likedIssueId!
: null)
: null,
);
getSavedList = (currentUser! == guestUser)
getSavedList = (widget.user == guestUser)
? getAnonymousUserIssueList()
: getIssueList(
currentUser!.savedIssueId != null
? (currentUser!.savedIssueId!.length > 0
? currentUser!.savedIssueId!
widget.user.savedIssueId != null
? (widget.user.savedIssueId!.length > 0
? widget.user.savedIssueId!
: null)
: null,
);
getFlaggedList = (currentUser! == guestUser)
getFlaggedList = (widget.user == guestUser)
? getAnonymousUserIssueList()
: getIssueList(
currentUser!.flaggedIssueId != null
? (currentUser!.flaggedIssueId!.length > 0
? currentUser!.flaggedIssueId!
widget.user.flaggedIssueId != null
? (widget.user.flaggedIssueId!.length > 0
? widget.user.flaggedIssueId!
: null)
: null,
);
Expand All @@ -381,7 +383,7 @@ class _UserProfileState extends ConsumerState<UserProfile> {
Navigator.of(context).pop();
},
),
title: Text(currentUser!.username!),
title: Text(widget.user.username!),
actions: [
IconButton(
onPressed: () async {
Expand Down Expand Up @@ -412,7 +414,7 @@ class _UserProfileState extends ConsumerState<UserProfile> {
AppLocalizations.of(context)!.updatingProfilePicture),
);
ScaffoldMessenger.of(context).showSnackBar(updatingSnack);
await UserApiClient.updatePfp(image, currentUser!);
await UserApiClient.updatePfp(image, widget.user);
setState(() {});
break;

Expand Down Expand Up @@ -472,7 +474,7 @@ class _UserProfileState extends ConsumerState<UserProfile> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
currentUser!.username!,
widget.user.username!,
style: GoogleFonts.ubuntu(
textStyle: TextStyle(
color: Color(0xFFDC4654),
Expand All @@ -482,7 +484,7 @@ class _UserProfileState extends ConsumerState<UserProfile> {
),
),
Text(
'#${currentUser!.id!}',
'#${widget.user.id!}',
style: GoogleFonts.aBeeZee(
textStyle: TextStyle(
color: Color(0xFF737373).withOpacity(0.5),
Expand All @@ -497,8 +499,8 @@ class _UserProfileState extends ConsumerState<UserProfile> {
vertical: 5.0,
),
child: Text(
(currentUser!.description != null)
? currentUser!.description!
(widget.user.description != null)
? widget.user.description!
: AppLocalizations.of(context)!
.noDescriptionWriteOne,
style: GoogleFonts.aBeeZee(
Expand All @@ -511,11 +513,11 @@ class _UserProfileState extends ConsumerState<UserProfile> {
),
),
SizedBox(
child: (currentUser!.following != null)
child: (widget.user.following != null)
? TextButton(
onPressed: () {},
child: Text(
currentUser!.following!.length.toString() +
widget.user.following!.length.toString() +
AppLocalizations.of(context)!.following,
style: GoogleFonts.aBeeZee(
textStyle: TextStyle(
Expand All @@ -531,12 +533,12 @@ class _UserProfileState extends ConsumerState<UserProfile> {
thickness: 2,
),
SizedBox(
child: (currentUser!.following != null)
child: (widget.user.following != null)
? TextButton(
onPressed: () {},
child: Text(
(currentUser!.totalScore != null)
? "${AppLocalizations.of(context)!.score} : ${currentUser!.totalScore!} "
(widget.user.totalScore != null)
? "${AppLocalizations.of(context)!.score} : ${widget.user.totalScore!} "
: "${AppLocalizations.of(context)!.score} : 0 ",
style: GoogleFonts.aBeeZee(
textStyle: TextStyle(
Expand Down Expand Up @@ -732,7 +734,7 @@ class _UserProfileState extends ConsumerState<UserProfile> {
Center(
child: TextButton(
onPressed: () async {
if (currentUser == guestUser) {
if (widget.user == guestUser) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Anonymous User !!")));
} else {
Expand Down
14 changes: 13 additions & 1 deletion lib/src/pages/issues/issue_detail.dart
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,19 @@ class IssueDetailPage extends StatelessWidget {
padding: EdgeInsets.all(0),
selectable: true,
onTapLink: (text, href, title) {
_launchUrl(href!);
if (href != null && href.startsWith('user:')) {
final username = href.substring(5);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfile(
user: User(username: username),
),
),
);
} else {
_launchUrl(href!);
}
},
styleSheet: MarkdownStyleSheet.fromTheme(
ThemeData(
Expand Down
11 changes: 10 additions & 1 deletion lib/src/pages/leaderboards/global_leaderboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,16 @@ class _GlobalLeaderBoardPageState extends State<GlobalLeaderBoardPage> {
itemBuilder: (context, index) {
int title = list[index].title;
return ListTile(
onTap: () {},
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfile(
user: list[index].user,
),
),
);
},
shape: RoundedRectangleBorder(
borderRadius: index == 0
? BorderRadius.only(
Expand Down
11 changes: 10 additions & 1 deletion lib/src/pages/leaderboards/monthly_leaderboard.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,16 @@ class _MonthlyLeaderBoardPageState
itemCount: list.length,
itemBuilder: (context, index) {
return ListTile(
onTap: () {},
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfile(
user: list[index].user,
),
),
);
},
shape: RoundedRectangleBorder(
borderRadius: index == 0
? BorderRadius.only(
Expand Down
2 changes: 2 additions & 0 deletions lib/src/pages/sizzle/sizzle_state_provider.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:blt/src/models/user_model.dart';

// Define your providers here
final usernameProvider = StateProvider<String?>((ref) => null);
final selectedUserProvider = StateProvider<User?>((ref) => null);

0 comments on commit ebd9f8c

Please sign in to comment.