diff --git a/project/FrontEnd/collaborative_science_platform/lib/helpers/.gitkeep b/project/FrontEnd/collaborative_science_platform/lib/helpers/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/project/FrontEnd/collaborative_science_platform/lib/helpers/search_helper.dart b/project/FrontEnd/collaborative_science_platform/lib/helpers/search_helper.dart new file mode 100644 index 00000000..2e1b6fe0 --- /dev/null +++ b/project/FrontEnd/collaborative_science_platform/lib/helpers/search_helper.dart @@ -0,0 +1,5 @@ +import 'package:collaborative_science_platform/widgets/app_search_bar.dart'; + +class SearchHelper { + static SearchType searchType = SearchType.theorem; +} diff --git a/project/FrontEnd/collaborative_science_platform/lib/models/small_node.dart b/project/FrontEnd/collaborative_science_platform/lib/models/small_node.dart index 1b8cf88a..5673749a 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/models/small_node.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/models/small_node.dart @@ -1,8 +1,3 @@ - -import 'package:collaborative_science_platform/models/account.dart'; -import 'package:collaborative_science_platform/models/basic_user.dart'; -import 'package:collaborative_science_platform/models/contributor_user.dart'; - class SmallNode { int nodeId; String nodeTitle; @@ -23,7 +18,8 @@ class SmallNode { nodeId: 0, nodeTitle: "Lorem Ipsum $id", contributors: ["Marcus Tullius Cicero", "Jesus Christ", "Remus", "Romulus", "Julius Caesar"], - theorem: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", + theorem: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", publishDate: DateTime(1989, 10, 29, 8, 0, 0), ); } diff --git a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/home_page.dart b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/home_page.dart index 42e9255a..4257978a 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/home_page.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/home_page.dart @@ -1,3 +1,4 @@ +import 'package:collaborative_science_platform/helpers/search_helper.dart'; import 'package:collaborative_science_platform/models/profile_data.dart'; import 'package:collaborative_science_platform/models/small_node.dart'; import 'package:collaborative_science_platform/screens/home_page/home_page_appbar.dart'; @@ -21,7 +22,7 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { final searchBarController = TextEditingController(); final searchBarFocusNode = FocusNode(); - bool searchBarActive = false; + SearchType searchType = SearchHelper.searchType; @override void dispose() { @@ -30,7 +31,11 @@ class _HomePageState extends State { super.dispose(); } - void search(SearchType searchType) { } + void search() { + setState(() { + searchType = SearchHelper.searchType; + }); + } @override Widget build(BuildContext context) { @@ -38,6 +43,7 @@ class _HomePageState extends State { searchBarFocusNode: searchBarFocusNode, searchBarController: searchBarController, onSearch: search, + searchType: searchType, ); } } @@ -54,24 +60,26 @@ class DesktopMobilePage extends StatelessWidget { class MobileHomePage extends StatelessWidget { final FocusNode searchBarFocusNode; final TextEditingController searchBarController; - final Function(SearchType) onSearch; + final Function onSearch; + final SearchType searchType; const MobileHomePage({ super.key, required this.searchBarFocusNode, required this.searchBarController, required this.onSearch, + required this.searchType, }); @override Widget build(BuildContext context) { return PageWithAppBar( appBar: const HomePageAppBar(), - child: SizedBox( - width: Responsive.getGenericPageWidth(context), - child: SingleChildScrollView( - primary: false, - scrollDirection: Axis.vertical, + child: SingleChildScrollView( + primary: false, + scrollDirection: Axis.vertical, + child: SizedBox( + width: Responsive.getGenericPageWidth(context), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, @@ -86,27 +94,7 @@ class MobileHomePage extends StatelessWidget { ), Padding( padding: const EdgeInsets.only(bottom: 8.0), - child: ListView.builder( - physics: const NeverScrollableScrollPhysics(), // Prevents a conflict with SingleChildScrollView - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: 10, - itemBuilder: (context, index) { - return HomePageUserCard( - profileData: ProfileData.getLoremIpsum(index+1), - onTap: () { /* Navigate to the Profile Page of the User */ }, - color: AppColors.primaryLightColor, - profilePagePath: (index % 2 == 0) ? "assets/images/gumball.jpg" : null, - ); - - /* - return HomePageNodeCard( - smallNode: SmallNode.getLoremIpsum(index+1), - onTap: () { /* Navigate to the Screen of the Node */ }, - ); - */ - }, - ), + child: (searchType == SearchType.theorem) ? const NodeCards() : const UserCards(), ), ], ), @@ -115,3 +103,49 @@ class MobileHomePage extends StatelessWidget { ); } } + +class NodeCards extends StatelessWidget { + const NodeCards({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return ListView.builder( + physics: const NeverScrollableScrollPhysics(), // Prevents a conflict with SingleChildScrollView + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: 10, + itemBuilder: (context, index) { + return HomePageNodeCard( + smallNode: SmallNode.getLoremIpsum(index + 1), + onTap: () {/* Navigate to the Screen of the Node */}, + ); + }, + ); + } +} + +class UserCards extends StatelessWidget { + const UserCards({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return ListView.builder( + physics: const NeverScrollableScrollPhysics(), // Prevents a conflict with SingleChildScrollView + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: 10, + itemBuilder: (context, index) { + return HomePageUserCard( + profileData: ProfileData.getLoremIpsum(index + 1), + onTap: () {/* Navigate to the Profile Page of the User */}, + color: AppColors.primaryLightColor, + profilePagePath: "assets/images/gumball.jpg", + ); + }, + ); + } +} diff --git a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_node_card.dart b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_node_card.dart index b1c9c3ab..5d690e14 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_node_card.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_node_card.dart @@ -1,78 +1,76 @@ - import 'package:collaborative_science_platform/helpers/date_to_string.dart'; import 'package:collaborative_science_platform/models/small_node.dart'; import 'package:flutter/material.dart'; class HomePageNodeCard extends StatelessWidget { final SmallNode smallNode; - final Color color; + final Color? color; final Function() onTap; const HomePageNodeCard({ super.key, required this.smallNode, - required this.color, + this.color, required this.onTap, }); @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: onTap, // Navigate to the Screen of the Node - child: Card( - color: color, - elevation: 4.0, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + return Card( + elevation: 4.0, + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: InkWell( + onTap: onTap, // Navigate to the screen of the Node + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + smallNode.nodeTitle, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18.0, + ), + ), + const SizedBox(height: 8.0), + Text( + smallNode.contributors.join(", "), + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14.0, + color: Colors.grey, + ), + ), + const SizedBox(height: 8.0), + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - Row( - children: [ - Flexible( - child: Text( - smallNode.nodeTitle, - overflow: TextOverflow.ellipsis, - maxLines: 1, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16.0, - ), - ), - ), - const SizedBox(width: 10.0), - Text( - getDurationFromNow(smallNode.publishDate), - style: TextStyle( - color: Colors.grey.shade600, - fontWeight: FontWeight.bold, - ), - ), - ], - ), Text( - smallNode.contributors.join(", "), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 14.0, - color: Colors.grey.shade600, + getDurationFromNow(smallNode.publishDate), + style: const TextStyle( + color: Colors.grey, + fontWeight: FontWeight.w600, ), ), - Text( - smallNode.theorem, - maxLines: 4, - overflow: TextOverflow.ellipsis, - ), ], ), - ), + // SizedBox(height: 12.0), + // Text( + // smallNode.theorem, + // maxLines: 4, + // overflow: TextOverflow.ellipsis, + // style: TextStyle( + // fontSize: 14.0, + // ), + // ), + ], ), ), ), diff --git a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_user_card.dart b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_user_card.dart index a2cf196e..9c4aff86 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_user_card.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/screens/home_page/widgets/home_page_user_card.dart @@ -1,4 +1,3 @@ - import 'package:collaborative_science_platform/models/profile_data.dart'; import 'package:collaborative_science_platform/utils/colors.dart'; import 'package:flutter/material.dart'; @@ -17,82 +16,62 @@ class HomePageUserCard extends StatelessWidget { this.profilePagePath, }); + // Remove this function when it is no longer needed + Widget profilePhoto() { + return CircleAvatar( + radius: 48.0, + backgroundColor: AppColors.primaryColor, + backgroundImage: profilePagePath != null ? AssetImage(profilePagePath!) : null, + child: profilePagePath == null + ? const Icon( + Icons.person, + size: 36.0, + color: Colors.white, + ) + : null, + ); + } + @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0), - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: onTap, //Navigate to the Profile Page of the User - child: Card( - color: color, - elevation: 8.0, - shadowColor: AppColors.primaryColor, - child: Padding( - padding: const EdgeInsets.all(10.0), + return Card( + elevation: 2.0, // Reduced elevation for a subtle shadow + margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + ), + child: InkWell( + onTap: onTap, // Navigate to the Profile Page of the User + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + profilePhoto(), + const SizedBox(width: 16.0), + Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - CircleAvatar( - radius: 32.0, - backgroundColor: AppColors.primaryColor, - child: (profilePagePath != null) ? Container( - width: 60.0, - height: 60.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - image: DecorationImage( - fit: BoxFit.fill, - image: AssetImage(profilePagePath!), - ) - ) - ) : const CircleAvatar( - radius: 30.0, - backgroundColor: Colors.grey, - child: Icon( - Icons.person, - size: 36.0, - color: Colors.white, - ), - ), - ), - const SizedBox(width: 10.0), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "${profileData.name} ${profileData.surname}", - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Colors.grey.shade600, - fontWeight: FontWeight.bold, - fontSize: 16.0, - ), - ), - const SizedBox(height: 4.0), - Text( - profileData.email, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Colors.grey.shade600, - fontWeight: FontWeight.w500, - fontSize: 16.0, - ), - ), - ], - ), - ], + Text( + "${profileData.name} ${profileData.surname}", + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18.0, + ), + ), + const SizedBox(height: 8.0), + Text( + profileData.email, + style: const TextStyle( + fontWeight: FontWeight.w500, + fontSize: 16.0, + color: Colors.grey, + ), ), - const SizedBox(height: 10.0), + const SizedBox(height: 8.0), Text( profileData.aboutMe, maxLines: 3, @@ -101,7 +80,8 @@ class HomePageUserCard extends StatelessWidget { ], ), ), - ), + ], + ), ), ), ); diff --git a/project/FrontEnd/collaborative_science_platform/lib/screens/page_with_appbar.dart b/project/FrontEnd/collaborative_science_platform/lib/screens/page_with_appbar.dart index 5f45cb4c..7f04f9c2 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/screens/page_with_appbar.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/screens/page_with_appbar.dart @@ -25,7 +25,7 @@ class PageWithAppBar extends StatelessWidget { {required this.child, required this.appBar, this.pageColor = Colors.white, - this.isScrollable = true, + this.isScrollable = false, this.navigator, super.key}); diff --git a/project/FrontEnd/collaborative_science_platform/lib/widgets/app_search_bar.dart b/project/FrontEnd/collaborative_science_platform/lib/widgets/app_search_bar.dart index 44c8dc30..83994a19 100644 --- a/project/FrontEnd/collaborative_science_platform/lib/widgets/app_search_bar.dart +++ b/project/FrontEnd/collaborative_science_platform/lib/widgets/app_search_bar.dart @@ -1,49 +1,51 @@ +import 'package:collaborative_science_platform/helpers/search_helper.dart'; import 'package:collaborative_science_platform/utils/responsive/responsive.dart'; import 'package:flutter/material.dart'; -enum SearchType {theorem, user, author } +enum SearchType { theorem, user, author } class AppSearchBar extends StatefulWidget { - final Function(SearchType) onSearch; + final Function onSearch; final FocusNode focusNode; final TextEditingController controller; - const AppSearchBar({ - required this.onSearch, - required this.controller, - required this.focusNode, - super.key - }); + const AppSearchBar({required this.onSearch, required this.controller, required this.focusNode, super.key}); @override State createState() => _AppSearchBarState(); } class _AppSearchBarState extends State { - SearchType searchType = SearchType.theorem; + SearchType searchType = SearchHelper.searchType; Widget searchTypeSelector() { if (Responsive.isMobile(context)) { return Icon( - (searchType == SearchType.theorem) ? Icons.description_rounded - : (searchType == SearchType.user) ? Icons.person - : Icons.science_rounded, + (searchType == SearchType.theorem) + ? Icons.description_rounded + : (searchType == SearchType.user) + ? Icons.person + : Icons.science_rounded, color: Colors.indigo.shade500, ); } else { return Row( children: [ Icon( - (searchType == SearchType.theorem) ? Icons.description_rounded - : (searchType == SearchType.user) ? Icons.person - : Icons.science_rounded, + (searchType == SearchType.theorem) + ? Icons.description_rounded + : (searchType == SearchType.user) + ? Icons.person + : Icons.science_rounded, color: Colors.indigo.shade500, ), const SizedBox(width: 4.0), Text( - (searchType == SearchType.theorem) ? "Theorem" - : (searchType == SearchType.user) ? "User" - : "Author", + (searchType == SearchType.theorem) + ? "Theorem" + : (searchType == SearchType.user) + ? "User" + : "Author", style: TextStyle( color: Colors.indigo.shade500, fontWeight: FontWeight.w500, @@ -68,7 +70,7 @@ class _AppSearchBarState extends State { MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( - onTap: widget.onSearch(searchType), + onTap: () => widget.onSearch(), child: Container( decoration: BoxDecoration( color: Colors.grey[100], @@ -93,6 +95,8 @@ class _AppSearchBarState extends State { textAlignVertical: TextAlignVertical.center, controller: widget.controller, focusNode: widget.focusNode, + textInputAction: TextInputAction.search, + onSubmitted: (String value) => widget.onSearch(), decoration: InputDecoration( hintText: "Search", border: InputBorder.none, @@ -108,6 +112,7 @@ class _AppSearchBarState extends State { onSelected: (SearchType newSearchType) { setState(() { searchType = newSearchType; + SearchHelper.searchType = newSearchType; }); }, initialValue: searchType,