diff --git a/lib/programs screen/social_winter_of_code.dart b/lib/programs screen/social_winter_of_code.dart index 6f7a524..ff0a503 100644 --- a/lib/programs screen/social_winter_of_code.dart +++ b/lib/programs screen/social_winter_of_code.dart @@ -9,16 +9,13 @@ import 'package:opso/programs_info_pages/swoc_info.dart'; import 'package:opso/widgets/swoc_project_widget.dart'; import 'package:opso/widgets/year_button.dart'; - class SWOCScreen extends StatefulWidget { const SWOCScreen({super.key}); - @override State createState() => _SWOCScreenState(); } - class _SWOCScreenState extends State { String currentPage = "/social_winter_of_code"; String currentProject = "Social Winter of Code"; @@ -35,21 +32,18 @@ class _SWOCScreenState extends State { List projectList = []; Future? getProjectFunction; - Future initializeProjectLists() async { await _loadProjects('assets/projects/swoc/swoc2024.json', swoc2024); await _loadProjects('assets/projects/swoc/swoc2023.json', swoc2023); await _loadProjects('assets/projects/swoc/swoc2021.json', swoc2021); await _loadProjects('assets/projects/swoc/swoc2020.json', swoc2020); - // Populate all unique organizations and languages allOrganizations = _extractUniqueValues((project) => project.owner); allLanguages = languages; projectList = List.from(swoc2024); // Default year } - List languages = [ 'All', 'Js', @@ -69,13 +63,14 @@ class _SWOCScreenState extends State { 'Dart' ]; - Future _loadProjects(String path, List list) async { try { String response = await rootBundle.loadString(path); if (response.isNotEmpty) { var jsonList = json.decode(response) as List; - list.addAll(jsonList.map((data) => SwocProjectModal.getDataFromJson(data)).toList()); + list.addAll(jsonList + .map((data) => SwocProjectModal.getDataFromJson(data)) + .toList()); print('Loaded projects from $path: ${list.length}'); } else { print('Error: JSON data is null or empty in $path'); @@ -85,11 +80,8 @@ class _SWOCScreenState extends State { } } - - - - - List _extractUniqueValues(String Function(SwocProjectModal) extractor) { + List _extractUniqueValues( + String Function(SwocProjectModal) extractor) { return { 'All', ...swoc2024.map(extractor), @@ -99,8 +91,8 @@ class _SWOCScreenState extends State { }.toList(); } - - List _extractUniqueLanguages(List Function(SwocProjectModal) extractor) { + List _extractUniqueLanguages( + List Function(SwocProjectModal) extractor) { final allLanguages = [ for (var project in swoc2024) ...extractor(project), for (var project in swoc2023) ...extractor(project), @@ -110,7 +102,6 @@ class _SWOCScreenState extends State { return ['All', ...allLanguages.toSet()]; } - @override void initState() { super.initState(); @@ -118,7 +109,6 @@ class _SWOCScreenState extends State { _checkBookmarkStatus(); } - Future _checkBookmarkStatus() async { bool bookmarkStatus = await HandleBookmark.isBookmarked(currentProject); setState(() { @@ -126,45 +116,40 @@ class _SWOCScreenState extends State { }); } - void filterProjects() { // Filter projects by year first projectList = _getProjectsByYear(); - // Filter projects by selected languages if (!selectedLanguages.contains('All')) { - projectList = projectList.where((project) => - selectedLanguages.every((language) => project.techstack.contains(language)) - ).toList(); + projectList = projectList + .where((project) => selectedLanguages + .every((language) => project.techstack.contains(language))) + .toList(); } - // Update the list of organizations based on the filtered projects by language _updateOrganizationList(); - // Filter projects by selected organizations if (!selectedOrganizations.contains('All')) { - projectList = projectList.where((project) => selectedOrganizations.contains(project.owner)).toList(); + projectList = projectList + .where((project) => selectedOrganizations.contains(project.owner)) + .toList(); } - // Ensure state is updated to reflect changes setState(() {}); } - - - void _updateOrganizationList() { allOrganizations = _extractUniqueValues((project) => project.owner) - .where((organization) => projectList.any((project) => project.owner == organization)) + .where((organization) => + projectList.any((project) => project.owner == organization)) .toList(); allOrganizations.insert(0, 'All'); } - List _getProjectsByYear() { switch (selectedYear) { case 2020: @@ -180,7 +165,6 @@ class _SWOCScreenState extends State { } } - Future _refresh() async { await initializeProjectLists(); setState(() { @@ -190,54 +174,51 @@ class _SWOCScreenState extends State { }); } - @override Widget build(BuildContext context) { - var height = MediaQuery.of(context).size.height; - var width = MediaQuery.of(context).size.width; - - return RefreshIndicator( onRefresh: _refresh, child: Scaffold( appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back_ios), - - onPressed: () => Navigator.of(context).pop(), - ), - centerTitle: true, - title: const Text('SWoC'), actions: [ - IconButton( - icon: (isBookmarked) - ? const Icon(Icons.bookmark_add_rounded) - : const Icon(Icons.bookmark_add_outlined), - onPressed: () { - setState(() { - isBookmarked = !isBookmarked; - }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(isBookmarked ? 'Bookmark added' : 'Bookmark removed'), - duration: const Duration(seconds: 2), - ), - ); - if (isBookmarked) { - HandleBookmark.addBookmark(currentProject, currentPage); - } else { - HandleBookmark.deleteBookmark(currentProject); - } - }, - ), - IconButton( - icon: Icon(Icons.info_outline), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => SWOCInfo()), ); - }, - ), - ]), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios), + onPressed: () => Navigator.of(context).pop(), + ), + centerTitle: true, + title: const Text('SWoC'), + actions: [ + IconButton( + icon: (isBookmarked) + ? const Icon(Icons.bookmark_add_rounded) + : const Icon(Icons.bookmark_add_outlined), + onPressed: () { + setState(() { + isBookmarked = !isBookmarked; + }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + isBookmarked ? 'Bookmark added' : 'Bookmark removed'), + duration: const Duration(seconds: 2), + ), + ); + if (isBookmarked) { + HandleBookmark.addBookmark(currentProject, currentPage); + } else { + HandleBookmark.deleteBookmark(currentProject); + } + }, + ), + IconButton( + icon: Icon(Icons.info_outline), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => SWOCInfo()), + ); + }, + ), + ]), body: FutureBuilder( future: getProjectFunction, builder: (context, snapshot) { @@ -246,9 +227,11 @@ class _SWOCScreenState extends State { } else if (snapshot.connectionState == ConnectionState.done) { return SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 48, vertical: 8), + padding: + const EdgeInsets.symmetric(horizontal: 48, vertical: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildSearchBar(), const SizedBox(height: 20), @@ -261,14 +244,15 @@ class _SWOCScreenState extends State { buttonText: "Filter by Language", onConfirm: (results) { setState(() { - selectedLanguages = results.isNotEmpty ? results : ['All']; + selectedLanguages = + results.isNotEmpty ? results : ['All']; filterProjects(); }); }, ), const SizedBox(height: 20), const SizedBox(height: 20), - _buildProjectList(height, width), + _buildProjectList(), ], ), ), @@ -282,7 +266,6 @@ class _SWOCScreenState extends State { ); } - Widget _buildSearchBar() { return TextFormField( decoration: InputDecoration( @@ -305,12 +288,14 @@ class _SWOCScreenState extends State { borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFFEEEEEE)), ), - contentPadding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 20.0), + contentPadding: + const EdgeInsets.symmetric(vertical: 12.0, horizontal: 20.0), ), onFieldSubmitted: (value) { setState(() { projectList = _getProjectsByYear() - .where((project) => project.name.toLowerCase().contains(value.toLowerCase())) + .where((project) => + project.name.toLowerCase().contains(value.toLowerCase())) .toList(); }); }, @@ -324,7 +309,6 @@ class _SWOCScreenState extends State { ); } - Widget _buildYearButtons() { return SizedBox( height: MediaQuery.sizeOf(context).height * 0.2, @@ -346,7 +330,9 @@ class _SWOCScreenState extends State { filterProjects(); }); }, - backgroundColor: selectedYear == 2020 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), + backgroundColor: selectedYear == 2020 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), ), YearButton( year: "2021", @@ -357,7 +343,9 @@ class _SWOCScreenState extends State { filterProjects(); }); }, - backgroundColor: selectedYear == 2021 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), + backgroundColor: selectedYear == 2021 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), ), YearButton( year: "2023", @@ -368,7 +356,9 @@ class _SWOCScreenState extends State { filterProjects(); }); }, - backgroundColor: selectedYear == 2023 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), + backgroundColor: selectedYear == 2023 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), ), YearButton( year: "2024", @@ -379,14 +369,15 @@ class _SWOCScreenState extends State { filterProjects(); }); }, - backgroundColor: selectedYear == 2024 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), + backgroundColor: selectedYear == 2024 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), ), ], ), ); } - Widget _buildMultiSelectField({ required List items, required List selectedValues, @@ -399,7 +390,8 @@ class _SWOCScreenState extends State { backgroundColor: isDarkMode ? Colors.grey.shade100 : Colors.white, items: items.map((e) => MultiSelectItem(e, e)).toList(), initialValue: selectedValues, - title: Text(title,style: TextStyle(color: isDarkMode ? Colors.black : Colors.black)), + title: Text(title, + style: TextStyle(color: isDarkMode ? Colors.black : Colors.black)), buttonText: Text(buttonText), onConfirm: onConfirm, decoration: BoxDecoration( @@ -409,25 +401,17 @@ class _SWOCScreenState extends State { ); } - - Widget _buildProjectList(double height, double width) { - return SizedBox( - height: height, - child: ListView.builder( - itemCount: projectList.length, - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: SwocProjectWidget( - index: index + 1, - modal: projectList[index], - height: height * 0.2, - width: width, - ), - ); - }, - ), + Widget _buildProjectList() { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: projectList.length, + itemBuilder: (BuildContext context, int index) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: SwocProjectWidget(index: index + 1, modal: projectList[index]), + ); + }, ); } } - diff --git a/lib/widgets/swoc_project_widget.dart b/lib/widgets/swoc_project_widget.dart index 4884c6f..6fde0a7 100644 --- a/lib/widgets/swoc_project_widget.dart +++ b/lib/widgets/swoc_project_widget.dart @@ -4,16 +4,12 @@ import 'package:url_launcher/url_launcher.dart'; class SwocProjectWidget extends StatelessWidget { final SwocProjectModal modal; - final double height; - final double width; final int index; const SwocProjectWidget({ super.key, required this.modal, - required this.index, - this.height = 100, - this.width = 100, + required this.index }); @override @@ -29,8 +25,6 @@ class SwocProjectWidget extends StatelessWidget { } }, child: Container( - width: width, - constraints: BoxConstraints(minHeight: height), decoration: BoxDecoration( border: Border.all( color: isDarkMode ? Colors.orange.shade100 : Colors.orange.shade300,