From d8cd22a2fe51b6e6f8cf5321372e6a5f1143e501 Mon Sep 17 00:00:00 2001 From: Prashant Andoriya <121665385+andoriyaprashant@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:54:11 +0530 Subject: [PATCH] Revert "GSoC Bugs Fixed" --- lib/modals/GSoC/Gsoc.dart | 160 +++-- .../google_summer_of_code_screen.dart | 579 ++++++++++-------- lib/widgets/gsoc/GsocProjectWidget.dart | 116 ++-- 3 files changed, 482 insertions(+), 373 deletions(-) diff --git a/lib/modals/GSoC/Gsoc.dart b/lib/modals/GSoC/Gsoc.dart index 9f585de..11c41ba 100644 --- a/lib/modals/GSoC/Gsoc.dart +++ b/lib/modals/GSoC/Gsoc.dart @@ -1,56 +1,112 @@ -class GsocModel { - String? organization; - String? organizationUrl; - String? technicalWriter; - String? mentor; - String? project; - String? projectUrl; - String? report; - String? reportUrl; - String? originalProjectProposal; - String? acceptedProjectProposalUrl; - int? year; - - GsocModel( - {this.organization, - this.organizationUrl, - this.technicalWriter, - this.mentor, - this.project, - this.projectUrl, - this.report, - this.reportUrl, - this.originalProjectProposal, - this.acceptedProjectProposalUrl, - this.year}); - - GsocModel.fromJson(Map json) { - organization = json['organization_name']; - organizationUrl = json['organization_url']; - technicalWriter = json['technical_writer']; - mentor = json['mentor']; - project = json['project']; - projectUrl = json['project_url']; - report = json['report']; - reportUrl = json['report_url']; - originalProjectProposal = json['accepted_project_proposal']; - acceptedProjectProposalUrl = json['accepted_project_proposal_url']; - year = json['year']; +class Gsoc { + final int year; + final String archiveUrl; + final List organizations; + + Gsoc({ + required this.year, + required this.archiveUrl, + required this.organizations, + }); + + factory Gsoc.fromJson(Map json) { + return Gsoc( + year: json['year'], + archiveUrl: json['archive_url'] ?? '', + organizations: (json['organizations'] as List) + .map((org) => Organization.fromJson(org)) + .toList(), + ); + } +} + +class Organization { + final String name; + final String imageUrl; + final String imageBackgroundColor; + final String description; + final String url; + final int numProjects; + final String category; + final String projectsUrl; + final String ircChannel; + final String contactEmail; + final String mailingList; + final String twitterUrl; + final String blogUrl; + final List topics; + final List technologies; + final List projects; + + Organization({ + required this.name, + required this.imageUrl, + required this.imageBackgroundColor, + required this.description, + required this.url, + required this.numProjects, + required this.category, + required this.projectsUrl, + required this.ircChannel, + required this.contactEmail, + required this.mailingList, + required this.twitterUrl, + required this.blogUrl, + required this.topics, + required this.technologies, + required this.projects, + }); + + factory Organization.fromJson(Map json) { + return Organization( + name: json['name'] ?? '', + imageUrl: json['image_url'] ?? '', + imageBackgroundColor: json['image_background_color'] ?? '', + description: json['description'] ?? '', + url: json['url'] ?? '', + numProjects: json['num_projects'] ?? 0, + category: json['category'] ?? '', + projectsUrl: json['projects_url'] ?? '', + ircChannel: json['irc_channel'] ?? '', + contactEmail: json['contact_email'] ?? '', + mailingList: json['mailing_list'] ?? '', + twitterUrl: json['twitter_url'] ?? '', + blogUrl: json['blog_url'] ?? '', + topics: (json['topics'] as List?)?.map((item) => item as String).toList() ?? [], + technologies: (json['technologies'] as List?)?.map((item) => item as String).toList() ?? [], + projects: (json['projects'] as List?) + ?.map((project) => Project.fromJson(project)) + .toList() ?? + [], + ); } +} + +class Project { + final String title; + final String shortDescription; + final String description; + final String studentName; + final String codeUrl; + final String projectUrl; + + Project({ + required this.title, + required this.shortDescription, + required this.description, + required this.studentName, + required this.codeUrl, + required this.projectUrl, + }); - Map toJson() { - final Map data = new Map(); - data['organization_name'] = this.organization; - data['organization_url'] = this.organizationUrl; - data['technical_writer'] = this.technicalWriter; - data['mentor'] = this.mentor; - data['project'] = this.project; - data['project_url'] = this.projectUrl; - data['report'] = this.report; - data['report_url'] = this.reportUrl; - data['accepted_project_proposal'] = this.originalProjectProposal; - data['accepted_project_proposal_url'] = this.acceptedProjectProposalUrl; - data['year'] = this.year; - return data; + factory Project.fromJson(Map json) { + return Project( + title: json['title'] ?? '', + shortDescription: json['short_description'] ?? '', + description: json['description'] ?? '', + studentName: json['student_name'] ?? '', + codeUrl: json['code_url'] ?? '', + projectUrl: json['project_url'] ?? '', + ); } } \ No newline at end of file diff --git a/lib/programs screen/google_summer_of_code_screen.dart b/lib/programs screen/google_summer_of_code_screen.dart index a6eff26..a9cba72 100644 --- a/lib/programs screen/google_summer_of_code_screen.dart +++ b/lib/programs screen/google_summer_of_code_screen.dart @@ -1,64 +1,40 @@ -import 'dart:convert'; +import 'dart:ffi'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:opso/modals/book_mark_model.dart'; import 'package:opso/programs_info_pages/gsoc_info.dart'; import 'package:opso/widgets/gsoc/GsocProjectWidget.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:multi_select_flutter/multi_select_flutter.dart'; import '../modals/GSoC/Gsoc.dart'; -import '../widgets/gsoc/GsocProjectWidget.dart'; -import 'package:flutter/services.dart'; -import 'package:multi_select_flutter/dialog/multi_select_dialog_field.dart'; -import 'package:multi_select_flutter/util/multi_select_item.dart'; -import 'package:opso/modals/book_mark_model.dart'; -import 'package:opso/widgets/year_button.dart'; - -class GoogleSummerOfCodeScreen extends StatefulWidget { - const GoogleSummerOfCodeScreen({super.key}); +import '../services/ApiService.dart'; +import '../widgets/SearchandFilterWidget.dart'; +import '../widgets/year_button.dart'; +class GoogleSummerOfCodeScreen extends StatefulWidget { @override - State createState() => _GoogleSummerOfCodeScreenState(); + State createState() => + _GoogleSummerOfCodeScreenState(); } class _GoogleSummerOfCodeScreenState extends State { + bool _isRefreshing = false; + bool isBookmarked = true; String currentPage = "/Google_summer_of_code"; - String currentProject = "Google Summer of Code"; - List gsoc2023 = []; - List gsoc2022 = []; - List gsoc2021 = []; - List gsoc2019 = []; - List gsoc2020 = []; - List allGsocModels = []; - List allLanguages = []; - List selectedGsocModels = ['All']; - List selectedLanguages = ['All']; + String currentProject = "GoogleSummerOfCodeScreen"; + String selectedOrg = ''; // Ensure this is defined + List gsoc2024 = []; + List gsoc2023 = []; + List gsoc2022 = []; + List gsoc2021 = []; int selectedYear = 2024; - bool isBookmarked = true; - List projectList = []; - Future? getProjectFunction; - - - Future initializeProjectLists() async { - await _loadProjects('assets/projects/gsod/gsod2019.json', gsoc2019); - await _loadProjects('assets/projects/gsod/gsod2023.json', gsoc2023); - await _loadProjects('assets/projects/gsod/gsod2022.json', gsoc2022); - await _loadProjects('assets/projects/gsod/gsod2021.json', gsoc2021); - await _loadProjects('assets/projects/gsod/gsod2020.json', gsoc2020); - - - // Populate all unique GsocModels and languages - allGsocModels = _extractUniqueValues((project) => project.organization!); - allLanguages = languages; - projectList = List.from(gsoc2023); - } - - List languages = [ - 'All', - 'Js', - 'Python', - 'React', + 'js', + 'python', + 'django', 'Angular', 'Bootstrap', 'Firebase', @@ -66,53 +42,29 @@ class _GoogleSummerOfCodeScreenState extends State { 'MongoDb', 'Express', 'Next', - 'CSS', - 'HTML', - 'JavaScript', - 'Flutter', + 'css', + 'html', + 'javascript', + 'flutter', 'Dart' ]; + List orgList = []; + List selectedLanguages = []; + List allOrganizations = []; + List selectedOrganizations = []; + late Future _dataFetchFuture; - Future _loadProjects(String path, List list) async { - String response = await rootBundle.loadString(path); - var jsonList = json.decode(response) as List; - list.addAll(jsonList.map((data) => GsocModel.fromJson(data)).toList()); - } - - - List _extractUniqueValues(String Function(GsocModel) extractor) { - return { - 'All', - ...gsoc2020.map(extractor), - ...gsoc2023.map(extractor), - ...gsoc2022.map(extractor), - ...gsoc2021.map(extractor), - ...gsoc2019.map(extractor), - }.toList(); - } - - - List _extractUniqueLanguages(List Function(GsocModel) extractor) { - final allLanguages = [ - for (var project in gsoc2020) ...extractor(project), - for (var project in gsoc2023) ...extractor(project), - for (var project in gsoc2022) ...extractor(project), - for (var project in gsoc2021) ...extractor(project), - for (var project in gsoc2019) ...extractor(project), - ]; - return ['All', ...allLanguages.toSet()]; - } @override void initState() { super.initState(); - getProjectFunction = initializeProjectLists(); + _refresh(); + _dataFetchFuture = getProjectData(); _checkBookmarkStatus(); } - Future _checkBookmarkStatus() async { bool bookmarkStatus = await HandleBookmark.isBookmarked(currentProject); setState(() { @@ -121,82 +73,148 @@ class _GoogleSummerOfCodeScreenState extends State { } - void filterProjects() { - // Filter projects by year first - projectList = _getProjectsByYear(); + + Future getProjectData() async { + ApiService apiService = ApiService(); + try { + Gsoc orgData2021 = await apiService.getOrgByYear('2021'); + Gsoc orgData2022 = await apiService.getOrgByYear('2022'); + Gsoc orgData2023 = await apiService.getOrgByYear('2023'); + Gsoc orgData2024 = await apiService.getOrgByYear('2024'); + + + + + setState(() { + gsoc2021 = orgData2021.organizations ?? []; + gsoc2022 = orgData2022.organizations ?? []; + gsoc2023 = orgData2023.organizations ?? []; + gsoc2024 = orgData2024.organizations ?? []; + orgList = gsoc2024; // Default to the latest year + allOrganizations = [...orgList.map((org) => org.name!).toSet()]; + }); + } catch (e) { + print('Error: $e'); + } + } + - // Filter projects by selected languages + + void filterProjects() { + orgList = _getOrganizationsByYear(selectedYear); + if(selectedLanguages.length>=2){ + selectedLanguages.removeAt(0); + } + if(selectedOrganizations.length>=2){ + selectedOrganizations.removeAt(0); + } if (!selectedLanguages.contains('All')) { - projectList = projectList.where((project) => - selectedLanguages.every((language) => project.organizationUrl!.contains(language)) + orgList = orgList.where((project) => + selectedLanguages.every((language) => project.technologies?.contains(language) == true) ).toList(); } - // Update the list of GsocModels based on the filtered projects by language - _updateGsocModelList(); - // Filter projects by selected GsocModels - if (!selectedGsocModels.contains('All')) { - projectList = projectList.where((project) => selectedGsocModels.contains(project.organization)).toList(); + + + if (!selectedOrganizations.contains('All')) { + orgList = orgList + .where((project) => selectedOrganizations.contains(project.name)) + .toList(); } - // Ensure state is updated to reflect changes - setState(() {}); - } + + // Update organization filter based on selected languages + allOrganizations = [ + ..._getOrganizationsByYear(selectedYear) + .where((org) => + selectedLanguages.contains('All') || + org.technologies?.any(selectedLanguages.contains) == true) + .map((org) => org.name!) + .toSet() + ]; - void _updateGsocModelList() { - allGsocModels = _extractUniqueValues((project) => project.organization!) - .where((GsocModel) => projectList.any((project) => project.organization == GsocModel)) - .toList(); - allGsocModels.insert(0, 'All'); + setState(() {}); } - List _getProjectsByYear() { - switch (selectedYear) { + + + List _getOrganizationsByYear(int year) { + switch (year) { case 2021: return gsoc2021; case 2022: return gsoc2022; case 2023: return gsoc2023; - case 2020: - return gsoc2020; - case 2019: - return gsoc2019; + case 2024: + return gsoc2024; default: return []; } } + + Future _refresh() async { - await initializeProjectLists(); setState(() { - selectedYear = 2023; - selectedGsocModels = ['All']; + _isRefreshing = true; + }); + await getProjectData(); + setState(() { + selectedYear = 2024; selectedLanguages = ['All']; + selectedOrganizations = ['All']; + filterProjects(); + _isRefreshing = false; + }); + } + + + + + // Add this method to the _GoogleSummerOfCodeScreenState class + void search(String searchText) { + setState(() { + selectedOrg = 'All'; // Reset selectedOrg to avoid mismatch + if (searchText.isEmpty) { + orgList = _getOrganizationsByYear(selectedYear); + } else { + orgList = _getOrganizationsByYear(selectedYear) + .where((element) => + element.name + ?.toLowerCase() + .contains(searchText.toLowerCase()) == + true) + .toList(); + } }); } + + @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( + appBar: AppBar( title: const Text('Google Summer of Code'), actions: [IconButton( icon: (isBookmarked) @@ -232,44 +250,219 @@ class _GoogleSummerOfCodeScreenState extends State { ),], ), body: FutureBuilder( - future: getProjectFunction, + future: _dataFetchFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); - } else if (snapshot.connectionState == ConnectionState.done) { + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else { return SingleChildScrollView( child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 48, vertical: 8), + padding: + const EdgeInsets.symmetric(horizontal: 46, vertical: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - _buildSearchBar(), + TextFormField( + decoration: InputDecoration( + filled: true, + hintText: 'Search', + suffixIcon: const Icon(Icons.search), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color(0xFFEEEEEE), + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color(0xFFEEEEEE), + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color(0xFFEEEEEE), + ), + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color(0xFFEEEEEE), + ), + ), + contentPadding: const EdgeInsets.symmetric( + vertical: 12.0, horizontal: 20.0), + ), + onFieldSubmitted: (value) { + search(value.trim()); + }, + onChanged: (value) { + if (value.isEmpty) { + search(value); + } + }, + ), const SizedBox(height: 20), - _buildYearButtons(), + SizedBox( + height: height * 0.2, + width: width, + child: GridView( + physics: const NeverScrollableScrollPhysics(), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 1.5 / 0.6, + crossAxisSpacing: 15, + mainAxisSpacing: 15, + ), + children: [ + YearButton( + year: "2021", + isEnabled: selectedYear == 2021, + onTap: () { + setState(() { + selectedYear = 2021; + selectedLanguages = []; + selectedOrganizations = []; + filterProjects(); + }); + }, + backgroundColor: selectedYear == 2021 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), + ), + YearButton( + year: "2022", + isEnabled: selectedYear == 2022, + onTap: () { + setState(() { + selectedYear = 2022; + selectedLanguages = []; + selectedOrganizations = []; + filterProjects(); + }); + }, + backgroundColor: selectedYear == 2022 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), + ), + YearButton( + year: "2023", + isEnabled: selectedYear == 2023, + onTap: () { + setState(() { + selectedYear = 2023; + selectedLanguages = []; + selectedOrganizations = []; + filterProjects(); + }); + }, + backgroundColor: selectedYear == 2023 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), + ), + YearButton( + isEnabled: selectedYear == 2024, + year: "2024", + onTap: () { + setState(() { + selectedYear = 2024; + selectedLanguages = []; + selectedOrganizations = []; + filterProjects(); + }); + }, + backgroundColor: selectedYear == 2024 + ? Colors.white + : const Color.fromRGBO(255, 183, 77, 1), + ), + ], + ), + ), const SizedBox(height: 20), _buildMultiSelectField( - items: allLanguages, + items: languages, selectedValues: selectedLanguages, title: "Select Languages", buttonText: "Filter by Language", onConfirm: (results) { setState(() { - selectedLanguages = results.isNotEmpty ? results : ['All']; + selectedLanguages = + results.isNotEmpty ? results : []; print(selectedLanguages); filterProjects(); }); }, ), const SizedBox(height: 20), - const SizedBox(height: 20), - _buildProjectList(height, width), + orgList.isEmpty + ? _isRefreshing + ? Column( + children: const [ + Center( + child: Column( + children: [ + CircularProgressIndicator(), + SizedBox(height: 10), + Text('Refreshing...'), + ], + ) + ), + SizedBox(height: 20), + ], + ) + : Column( + children: [ + const Center(child: Text('No projects found')), + const SizedBox(height: 20), + TextButton( + onPressed: () { + _refresh(); + }, + child: const Text('Refresh'), + ), + ], + ) + : Container( + height: height, + child: ListView.builder( + itemCount: orgList.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 2, + blurRadius: 5, + offset: Offset(0, 3), // changes position of shadow + ), + ], + ), + child: GsocProjectWidget( + index: index + 1, + modal: orgList[index], + height: height * 0.2, + width: width, + ), + ), + ); + }, + ), + ), + + ], ), ), ); - } else { - return const Center(child: Text("Some error occurred")); } }, ), @@ -278,120 +471,6 @@ class _GoogleSummerOfCodeScreenState extends State { } - Widget _buildSearchBar() { - return TextFormField( - decoration: InputDecoration( - filled: true, - hintText: 'Search', - suffixIcon: const Icon(Icons.search), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide(color: Color(0xFFEEEEEE)), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide(color: Color(0xFFEEEEEE)), - ), - disabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide(color: Color(0xFFEEEEEE)), - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: const BorderSide(color: Color(0xFFEEEEEE)), - ), - contentPadding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 20.0), - ), - onFieldSubmitted: (value) { - setState(() { - projectList = _getProjectsByYear() - .where((project) => project.organization!.toLowerCase().contains(value.toLowerCase())) - .toList(); - }); - }, - onChanged: (value) { - if (value.isEmpty) { - setState(() { - projectList = _getProjectsByYear(); - }); - } - }, - ); - } - - - Widget _buildYearButtons() { - var height = MediaQuery.sizeOf(context).height; - return SizedBox( - height: height * 0.3, - child: GridView( - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - childAspectRatio: 1.5 / 0.6, - crossAxisCount: 2, - crossAxisSpacing: 15, - mainAxisSpacing: 15, - ), - children: [ - YearButton( - year: "2019", - isEnabled: selectedYear == 2019, - onTap: () { - setState(() { - selectedYear = 2019; - filterProjects(); - }); - }, - backgroundColor: selectedYear == 2019 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), - ), - YearButton( - year: "2020", - isEnabled: selectedYear == 2020, - onTap: () { - setState(() { - selectedYear = 2020; - filterProjects(); - }); - }, - backgroundColor: selectedYear == 2020 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), - ), - YearButton( - year: "2021", - isEnabled: selectedYear == 2021, - onTap: () { - setState(() { - selectedYear = 2021; - filterProjects(); - }); - }, - backgroundColor: selectedYear == 2021 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), - ), - YearButton( - year: "2022", - isEnabled: selectedYear == 2022, - onTap: () { - setState(() { - selectedYear = 2022; - filterProjects(); - }); - }, - backgroundColor: selectedYear == 2022 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), - ), - YearButton( - year: "2023", - isEnabled: selectedYear == 2023, - onTap: () { - setState(() { - selectedYear = 2023; - filterProjects(); - }); - }, - backgroundColor: selectedYear == 2023 ? Colors.white : const Color.fromRGBO(255, 183, 77, 1), - ), - ], - ), - ); - } Widget _buildMultiSelectField({ @@ -406,7 +485,8 @@ class _GoogleSummerOfCodeScreenState 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( @@ -415,26 +495,13 @@ class _GoogleSummerOfCodeScreenState extends State { ), ); } +} - Widget _buildProjectList(double height, double width) { - return Container( - height: double.maxFinite, // Set a specific height here - child: ListView.builder( - physics: NeverScrollableScrollPhysics(), - itemCount: projectList.length, - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: GsocProjectWidget( - index: index + 1, - modal: projectList[index], - height: height * 0.2, - width: width, - ), - ); - }, - ), - ); - } + + +void main() { + runApp(MaterialApp( + home: GoogleSummerOfCodeScreen(), + )); } \ No newline at end of file diff --git a/lib/widgets/gsoc/GsocProjectWidget.dart b/lib/widgets/gsoc/GsocProjectWidget.dart index c85aff3..8345941 100644 --- a/lib/widgets/gsoc/GsocProjectWidget.dart +++ b/lib/widgets/gsoc/GsocProjectWidget.dart @@ -1,14 +1,12 @@ import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; - import '../../modals/GSoC/Gsoc.dart'; class GsocProjectWidget extends StatelessWidget { - final GsocModel modal; + final Organization modal; final double height; final double width; final int index; - const GsocProjectWidget({ Key? key, required this.modal, @@ -16,14 +14,12 @@ class GsocProjectWidget extends StatelessWidget { this.height = 100, this.width = 100, }) : super(key: key); - Future _launchUrl(String url) async { final Uri uri = Uri.parse(url); if (!await launchUrl(uri)) { throw 'Could not launch $url'; } } - @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; @@ -32,9 +28,7 @@ class GsocProjectWidget extends StatelessWidget { return GestureDetector( onTap: () async { - if (modal.projectUrl != null) { - await _launchUrl(modal.projectUrl!); - } + await _launchUrl(modal.url); }, child: Container( width: width, @@ -53,91 +47,83 @@ class GsocProjectWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "$index. ${modal.organization}", + "$index. ${modal.name}", style: TextStyle( color: Colors.orange, fontSize: 20, fontWeight: FontWeight.bold, ), ), - if (modal.originalProjectProposal != null) ...[ - Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text( - "Description : ${modal.originalProjectProposal}", - style: TextStyle( - color: textColor, - ), - ), - ), - ], - if (modal.mentor != null) ...[ - Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text( - "Mentor: ${modal.mentor}", - style: TextStyle( - color: textColor, - ), - ), - ), - ], - if (modal.technicalWriter != null) ...[ - Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text( - "Technical Writer: ${modal.technicalWriter}", - style: TextStyle( - color: textColor, - ), + Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Text( + "By ${modal.description}", + style: TextStyle( + color: textColor, ), ), - ], + ), Padding( padding: const EdgeInsets.only(top: 20.0), child: Wrap( spacing: 10, runSpacing: 10, children: [ - if (modal.organizationUrl != null && - modal.organizationUrl!.isNotEmpty) + if (modal.contactEmail.isNotEmpty) ElevatedButton.icon( onPressed: () { - _launchUrl(modal.organizationUrl!); + _launchUrl('mailto:${modal.contactEmail}'); }, - icon: Icon(Icons.web, color: Colors.white), - label: Text("Org Website"), + icon: Icon(Icons.email, color: Colors.white), + label: Text("Email"), style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Colors.orange, + foregroundColor: Colors.white, backgroundColor: Colors.orange, ), ), - if (modal.reportUrl != null && modal.reportUrl!.isNotEmpty) + if (modal.blogUrl.isNotEmpty) ElevatedButton.icon( onPressed: () { - _launchUrl(modal.reportUrl!); + _launchUrl(modal.blogUrl); }, - icon: Icon(Icons.description, color: Colors.white), - label: Text("Report"), + icon: Icon(Icons.web, color: Colors.white), + label: Text("Blog"), style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Colors.orange, + foregroundColor: Colors.white, backgroundColor: Colors.orange, ), ), - if (modal.acceptedProjectProposalUrl != null && - modal.acceptedProjectProposalUrl!.isNotEmpty) - ElevatedButton.icon( - onPressed: () { - _launchUrl(modal.acceptedProjectProposalUrl!); - }, - icon: Icon(Icons.file_present, color: Colors.white), - label: Text("Proposal"), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: Colors.orange, + ], + ), + ), + Padding( + padding: const EdgeInsets.only(top: 20.0), + child: Wrap( + alignment: WrapAlignment.start, + runSpacing: 10, + children: List.generate( + modal.technologies.length, + (index) => Container( + margin: const EdgeInsets.only(right: 10), + decoration: BoxDecoration( + color: const Color.fromARGB(255, 249, 241, 226), + borderRadius: BorderRadius.circular(20), + ), + child: IntrinsicWidth( + stepWidth: 30, + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Center( + child: Text( + modal.technologies[index], + style: TextStyle( + color: Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + ), ), ), - ], + ), + ), ), ), ],