From 117b482eb983472c7b025e64ade8bf36cc3fdf58 Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Wed, 21 Aug 2024 18:49:35 +0300 Subject: [PATCH 1/8] feat: added dao page --- .../dao page/data/dao_card_model.dart | 12 ++ .../features/dao page/data/dummy_data.dart | 34 ++++ .../dao page/presentation/pages/dao_page.dart | 78 ++++++++ .../presentation/widgets/active_widget.dart | 46 +++++ .../presentation/widgets/dao_card.dart | 158 ++++++++++++++++ .../widgets/executable_widget.dart | 46 +++++ .../widgets/show_result_dialog.dart | 168 ++++++++++++++++++ .../presentation/widgets/vote_dialog.dart | 126 +++++++++++++ threefold_connect/lib/main.dart | 3 +- threefold_connect/lib/theme/theme.dart | 2 + threefold_connect/lib/widgets/app_bar.dart | 4 +- 11 files changed, 675 insertions(+), 2 deletions(-) create mode 100644 threefold_connect/lib/features/dao page/data/dao_card_model.dart create mode 100644 threefold_connect/lib/features/dao page/data/dummy_data.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart diff --git a/threefold_connect/lib/features/dao page/data/dao_card_model.dart b/threefold_connect/lib/features/dao page/data/dao_card_model.dart new file mode 100644 index 0000000..9fcd9c2 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/dao_card_model.dart @@ -0,0 +1,12 @@ +class DaoCardDetails { + String text; + String description; + String date; + + DaoCardDetails({ + required this.text, + required this.description, + required this.date, + }); +} + diff --git a/threefold_connect/lib/features/dao page/data/dummy_data.dart b/threefold_connect/lib/features/dao page/data/dummy_data.dart new file mode 100644 index 0000000..c40a960 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/dummy_data.dart @@ -0,0 +1,34 @@ + + +import 'dao_card_model.dart'; + +var daoDetailsList = [ + DaoCardDetails( + text: 'Test', + description: 'Dummy description', + date: 'Tue Aug 13 2024 19:53:49 GMT+0300', + ), + DaoCardDetails( + text: 'Test 1', + description: 'Dummy description', + date: 'Tue Aug 13 2024 19:53:49 GMT+0300', + ), + DaoCardDetails( + text: 'Test 2', + description: 'Dummy description', + date: 'Tue Aug 13 2024 19:53:49 GMT+0300', + ), + DaoCardDetails( + text: 'Test 3', + description: 'Dummy description', + date: 'Tue Aug 13 2024 19:53:49 GMT+0300', + ), + DaoCardDetails( + text: 'Test 4', + description: 'Dummy description', + date: 'Tue Aug 13 2024 19:53:49 GMT+0300', + ), +]; + + +var farmList =['Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List' , 'Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List' , 'Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List']; \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart new file mode 100644 index 0000000..89279c8 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/active_widget.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/executable_widget.dart'; +import 'package:threefold_connect/theme/theme.dart'; +import 'package:threefold_connect/widgets/app_bar.dart'; + +class DaoPage extends StatefulWidget { + const DaoPage({super.key}); + + @override + State createState() => _DaoPageState(); +} + +//TODO : Executable page +class _DaoPageState extends State { + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 2, + child: Scaffold( + appBar: const MyAppBar( title: 'Dao page'), + body: Column( + children: [ + PreferredSize( + preferredSize: const Size.fromHeight(50.0), + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: TabBar( + labelColor: Theme.of(context).colorScheme.primary, + indicatorColor: primaryColor, + unselectedLabelColor: white, + dividerColor: Theme.of(context).scaffoldBackgroundColor, + tabs: const [ + Tab(text: 'Active'), + Tab(text: 'Executable'), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(10), + child: SizedBox( + height: 40, + child: SearchBar( + trailing: const [ + Icon( + Icons.search, + color: grey, + ) + ], + backgroundColor: MaterialStateProperty.all(secondryColor), + hintText: "Search by proposal description", + hintStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + textStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), + ), + ), + ), + ), + const Expanded( + child: TabBarView( + children: [ + ActiveWidget(), + ExecutableWidget(), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart new file mode 100644 index 0000000..a96ef4e --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; +import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; + + +class ActiveWidget extends StatefulWidget { + const ActiveWidget({super.key}); + + @override + State createState() => _ActiveWidgetState(); +} + +class _ActiveWidgetState extends State { + List daoList=[]; + + @override + void initState() { + // TODO: Fetch list an update it and remove this dummy data line + daoList= daoDetailsList; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: _buildDaoCardList(daoList), + ), + ), + ); + } +} + + +List _buildDaoCardList(List list) { + return list.map((item) { + return DaoCard( + text: item.text, + description: item.description, + date: item.date, + ); + }).toList(); +} \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart new file mode 100644 index 0000000..2015782 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/show_result_dialog.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/vote_dialog.dart'; +import 'package:threefold_connect/theme/theme.dart'; + + +class DaoCard extends StatefulWidget { + final String text; + final String description; + final String date; + const DaoCard({ + required this.text, + required this.description, + required this.date, + super.key, + }); + + @override + State createState() => _DaoCardState(); +} + +class _DaoCardState extends State { + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.all(10), + padding: const EdgeInsets.all(15), + color: Theme.of(context).colorScheme.secondary, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + widget.text, + style: TextStyle( + color: white, + fontFamily: inter, + ), + textAlign: TextAlign.start, + ), + ), + const Divider( + thickness: 2, + color: grey, + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text( + widget.description, + style: TextStyle( + color: white, + fontFamily: inter, + ), + textAlign: TextAlign.start, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: TextButton( + onPressed: () {}, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(2), + ), + side: const BorderSide( + color: teritaryColor, + ), + ), + child: SizedBox( + width: double.infinity, + child: Text( + 'Go to proposal', + style: TextStyle( + color: teritaryColor, + fontFamily: interBold, + ), + textAlign: TextAlign.center, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + 'You can vote until :', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + textAlign: TextAlign.start, + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Align( + alignment: Alignment.centerLeft, + child: Text( + widget.date, + style: TextStyle( + color: white, + fontFamily: inter, + ), + textAlign: TextAlign.start, + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () { + showDialog( + context: context, builder: (_) => const ShowResultDialog()); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: backgroundColor, + ), + child: Text( + 'Show result', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + TextButton( + onPressed: () { + showDialog( + context: context, builder: (_) => const VoteDialog()); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: primaryColor, + ), + child: Text( + 'Vote', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart new file mode 100644 index 0000000..5ef9a98 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; +import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; + + +class ExecutableWidget extends StatefulWidget { + const ExecutableWidget({super.key}); + + @override + State createState() => _ExecutableWidgetState(); +} + +class _ExecutableWidgetState extends State { + List daoList=[]; + + @override + void initState() { + // TODO: Fetch list an update it and remove this dummy data line + daoList= daoDetailsList; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: _buildDaoCardList(daoList), + ), + ), + ); + } +} + + +List _buildDaoCardList(List list) { + return list.map((item) { + return DaoCard( + text: item.text, + description: item.description, + date: item.date, + ); + }).toList(); +} \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart new file mode 100644 index 0000000..4b19b56 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:threefold_connect/theme/theme.dart'; + +class ShowResultDialog extends StatefulWidget { + const ShowResultDialog({super.key}); + + @override + State createState() => _ShowResultDialogState(); +} + +class _ShowResultDialogState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _noAnimation; + late Animation _yesAnimation; + late Animation _thresholdAnimation; + int got = 0; + int total = 0; + int yes = 0; + int no = 0; + + @override + void initState() { + //TODO: Fetch api to get number of yes, no , got , total and remove dummy data below + got = 1; + total = 5; + yes = 60; + no = 40; + + _animationController = AnimationController( + duration: const Duration(seconds: 1), + vsync: this, + ); + + _noAnimation = Tween( + begin: 0.0, + end: (no / (yes + no)), + ).animate(_animationController); + + _yesAnimation = Tween( + begin: 0.0, + end: (yes / (yes + no)), + ).animate(_animationController); + + _thresholdAnimation = Tween( + begin: 0.0, + end: (got / total), + ).animate(_animationController); + + _animationController.forward(); + super.initState(); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + backgroundColor: backgroundGrey, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 30 , horizontal: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Stack( + alignment: Alignment.center, + children: [ + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + minHeight: 40, + value: _thresholdAnimation.value, + color: primaryColor, + backgroundColor: backgroundColor, + ); + }, + ), + Center( + child: Text( + 'Threshold $got/$total', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ), + ], + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Yes', + style: TextStyle( + color: Colors.white, + fontFamily: interBold, + fontSize: 16, + ), + ), + Text( + '${(yes / (yes + no)) * 100}%', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ], + ), + const SizedBox(height: 5), + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + value: _yesAnimation.value, + color: primaryColor, + backgroundColor: grey, + ); + }, + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'No', + style: TextStyle( + color: Colors.white, + fontFamily: interBold, + fontSize: 16, + ), + ), + Text( + '${(no / (yes + no)) * 100}%', + style: TextStyle( + color: Colors.white, + fontFamily: inter, + fontSize: 14, + ), + ), + ], + ), + const SizedBox(height: 5), + AnimatedBuilder( + animation: _animationController, + builder: (context, child) { + return LinearProgressIndicator( + value: _noAnimation.value, + color: darkred, + backgroundColor: grey, + ); + }, + ), + ]), + ), + ); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart new file mode 100644 index 0000000..cebe317 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -0,0 +1,126 @@ +import 'package:flutter/material.dart'; + +import '../../../../theme/theme.dart'; +import '../../data/dummy_data.dart'; + +class VoteDialog extends StatefulWidget { + const VoteDialog({super.key}); + + @override + State createState() => _VoteDialogState(); +} + +class _VoteDialogState extends State { + String selectedFarm = ""; + List farms = []; + + @override + void initState() { + // TODO: Fetch Farms List and remove this dummy data + farms = farmList; + super.initState(); + } + + List> _buildDropdownMenuEntries( + List farms) { + return farms.map((farm) { + return DropdownMenuEntry( + value: farm, + label: farm, + labelWidget: Text( + farm, + style: TextStyle(color: Colors.white, fontFamily: interBold), + ), + ); + }).toList(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + backgroundColor: backgroundGrey, + child: Padding( + padding: const EdgeInsets.all(30), + child: Flex( + direction: Axis.vertical, + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + fit: FlexFit.loose, + child: DropdownMenu( + menuHeight: MediaQuery.sizeOf(context).width * 0.5, + enableFilter: true, + width: MediaQuery.sizeOf(context).width * 0.6, + textStyle: TextStyle(color: white, fontFamily: interBold), + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: secondryColor, + ), + menuStyle: MenuStyle( + backgroundColor: MaterialStateProperty.all(secondryColor), + ), + label: Text( + 'Select Farm', + style: TextStyle(color: white, fontFamily: interBold), + ), + dropdownMenuEntries: _buildDropdownMenuEntries(farms), + onSelected: (String? value) { + if (value != null) { + selectedFarm = value; + } + }, + ), + ), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + TextButton( + onPressed: () { + //TODO: Call api to vote Yes + Navigator.pop(context); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: Theme.of(context).colorScheme.primary, + ), + child: Text( + 'Yes', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + TextButton( + onPressed: () { + //TODO: Call api to vote No + Navigator.pop(context); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + backgroundColor: Theme.of(context).colorScheme.secondary, + ), + child: Text( + 'No', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/threefold_connect/lib/main.dart b/threefold_connect/lib/main.dart index e06c0c4..0c0d8f0 100644 --- a/threefold_connect/lib/main.dart +++ b/threefold_connect/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/pages/dao_page.dart'; import 'package:threefold_connect/theme/theme.dart'; void main() { runApp(const MyApp()); @@ -13,7 +14,7 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Flutter Demo', theme: threefoldTheme, - home: const MyHomePage(title: 'Flutter Demo Home Page'), + home: const DaoPage(), ); } } diff --git a/threefold_connect/lib/theme/theme.dart b/threefold_connect/lib/theme/theme.dart index f92309c..5491d44 100644 --- a/threefold_connect/lib/theme/theme.dart +++ b/threefold_connect/lib/theme/theme.dart @@ -9,6 +9,8 @@ const backgroundColor = Color(0xFF383434); const white = Color(0xFFFFFFFF); const darkred = Color(0xFFA11A1A); const grey = Color(0xFF818181); +const backgroundGrey = Color(0xFF323232); + // Fonts var poppins = GoogleFonts.poppins().fontFamily; diff --git a/threefold_connect/lib/widgets/app_bar.dart b/threefold_connect/lib/widgets/app_bar.dart index d843bfe..4e22286 100644 --- a/threefold_connect/lib/widgets/app_bar.dart +++ b/threefold_connect/lib/widgets/app_bar.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import '../theme/theme.dart'; + class MyAppBar extends StatelessWidget implements PreferredSizeWidget { final String title; @@ -8,7 +10,7 @@ class MyAppBar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( - title: Text(title), + title: Text(title , style: TextStyle(fontFamily: poppins),), leading: IconButton( icon: const Icon(Icons.menu), onPressed: () {}, From 9daee025510379f22d8722222b036a8e8cf413ec Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 22 Aug 2024 10:30:16 +0300 Subject: [PATCH 2/8] refactor: used colors from theme instead of using the consts --- .../lib/features/dao page/presentation/pages/dao_page.dart | 6 +++--- .../features/dao page/presentation/widgets/dao_card.dart | 4 ++-- .../dao page/presentation/widgets/show_result_dialog.dart | 4 ++-- .../features/dao page/presentation/widgets/vote_dialog.dart | 2 +- threefold_connect/lib/widgets/app_bar.dart | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart index 89279c8..68afa8c 100644 --- a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -18,7 +18,7 @@ class _DaoPageState extends State { return DefaultTabController( length: 2, child: Scaffold( - appBar: const MyAppBar( title: 'Dao page'), + appBar: const MyAppBar( title: 'Dao'), body: Column( children: [ PreferredSize( @@ -27,7 +27,7 @@ class _DaoPageState extends State { color: Theme.of(context).scaffoldBackgroundColor, child: TabBar( labelColor: Theme.of(context).colorScheme.primary, - indicatorColor: primaryColor, + indicatorColor: Theme.of(context).colorScheme.primary, unselectedLabelColor: white, dividerColor: Theme.of(context).scaffoldBackgroundColor, tabs: const [ @@ -48,7 +48,7 @@ class _DaoPageState extends State { color: grey, ) ], - backgroundColor: MaterialStateProperty.all(secondryColor), + backgroundColor: MaterialStateProperty.all(Theme.of(context).colorScheme.secondary), hintText: "Search by proposal description", hintStyle: MaterialStateProperty.all( TextStyle(color: grey, fontFamily: inter, fontSize: 14)), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index 2015782..80fc7a3 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -72,7 +72,7 @@ class _DaoCardState extends State { child: Text( 'Go to proposal', style: TextStyle( - color: teritaryColor, + color: Theme.of(context).colorScheme.tertiary, fontFamily: interBold, ), textAlign: TextAlign.center, @@ -139,7 +139,7 @@ class _DaoCardState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), - backgroundColor: primaryColor, + backgroundColor: Theme.of(context).colorScheme.primary, ), child: Text( 'Vote', diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart index 4b19b56..d02b68c 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -78,7 +78,7 @@ class _ShowResultDialogState extends State return LinearProgressIndicator( minHeight: 40, value: _thresholdAnimation.value, - color: primaryColor, + color: Theme.of(context).colorScheme.primary, backgroundColor: backgroundColor, ); }, @@ -123,7 +123,7 @@ class _ShowResultDialogState extends State builder: (context, child) { return LinearProgressIndicator( value: _yesAnimation.value, - color: primaryColor, + color: Theme.of(context).colorScheme.primary, backgroundColor: grey, ); }, diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index cebe317..f999f83 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -60,7 +60,7 @@ class _VoteDialogState extends State { fillColor: secondryColor, ), menuStyle: MenuStyle( - backgroundColor: MaterialStateProperty.all(secondryColor), + backgroundColor: MaterialStateProperty.all(Theme.of(context).colorScheme.secondary), ), label: Text( 'Select Farm', diff --git a/threefold_connect/lib/widgets/app_bar.dart b/threefold_connect/lib/widgets/app_bar.dart index 4e22286..20a4244 100644 --- a/threefold_connect/lib/widgets/app_bar.dart +++ b/threefold_connect/lib/widgets/app_bar.dart @@ -10,7 +10,7 @@ class MyAppBar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( - title: Text(title , style: TextStyle(fontFamily: poppins),), + title: Text(title , style: TextStyle(fontFamily: interBold , fontSize: 16),), leading: IconButton( icon: const Icon(Icons.menu), onPressed: () {}, From 651ad772e2ee9d7a3e7ed8d8704b9cef8c723469 Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 22 Aug 2024 10:45:37 +0300 Subject: [PATCH 3/8] format: formatted the files --- .../dao page/presentation/pages/dao_page.dart | 31 ++++++++++--------- .../presentation/widgets/active_widget.dart | 10 +++--- .../presentation/widgets/dao_card.dart | 4 +-- .../widgets/executable_widget.dart | 10 +++--- .../widgets/show_result_dialog.dart | 6 ++-- .../presentation/widgets/vote_dialog.dart | 5 +-- threefold_connect/lib/main.dart | 3 +- threefold_connect/lib/widgets/app_bar.dart | 5 ++- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart index 68afa8c..93f29b8 100644 --- a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -18,25 +18,25 @@ class _DaoPageState extends State { return DefaultTabController( length: 2, child: Scaffold( - appBar: const MyAppBar( title: 'Dao'), + appBar: const MyAppBar(title: 'Dao'), body: Column( children: [ PreferredSize( - preferredSize: const Size.fromHeight(50.0), - child: Container( - color: Theme.of(context).scaffoldBackgroundColor, - child: TabBar( - labelColor: Theme.of(context).colorScheme.primary, - indicatorColor: Theme.of(context).colorScheme.primary, - unselectedLabelColor: white, - dividerColor: Theme.of(context).scaffoldBackgroundColor, - tabs: const [ - Tab(text: 'Active'), - Tab(text: 'Executable'), - ], + preferredSize: const Size.fromHeight(50.0), + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: TabBar( + labelColor: Theme.of(context).colorScheme.primary, + indicatorColor: Theme.of(context).colorScheme.primary, + unselectedLabelColor: white, + dividerColor: Theme.of(context).scaffoldBackgroundColor, + tabs: const [ + Tab(text: 'Active'), + Tab(text: 'Executable'), + ], + ), ), ), - ), Padding( padding: const EdgeInsets.all(10), child: SizedBox( @@ -48,7 +48,8 @@ class _DaoPageState extends State { color: grey, ) ], - backgroundColor: MaterialStateProperty.all(Theme.of(context).colorScheme.secondary), + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.secondary), hintText: "Search by proposal description", hintStyle: MaterialStateProperty.all( TextStyle(color: grey, fontFamily: inter, fontSize: 14)), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart index a96ef4e..4d92c8f 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart @@ -3,7 +3,6 @@ import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; - class ActiveWidget extends StatefulWidget { const ActiveWidget({super.key}); @@ -12,15 +11,15 @@ class ActiveWidget extends StatefulWidget { } class _ActiveWidgetState extends State { - List daoList=[]; + List daoList = []; @override void initState() { // TODO: Fetch list an update it and remove this dummy data line - daoList= daoDetailsList; + daoList = daoDetailsList; super.initState(); } - + @override Widget build(BuildContext context) { return Scaffold( @@ -34,7 +33,6 @@ class _ActiveWidgetState extends State { } } - List _buildDaoCardList(List list) { return list.map((item) { return DaoCard( @@ -43,4 +41,4 @@ List _buildDaoCardList(List list) { date: item.date, ); }).toList(); -} \ No newline at end of file +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index 80fc7a3..27375f7 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -3,7 +3,6 @@ import 'package:threefold_connect/features/dao%20page/presentation/widgets/show_ import 'package:threefold_connect/features/dao%20page/presentation/widgets/vote_dialog.dart'; import 'package:threefold_connect/theme/theme.dart'; - class DaoCard extends StatefulWidget { final String text; final String description; @@ -114,7 +113,8 @@ class _DaoCardState extends State { TextButton( onPressed: () { showDialog( - context: context, builder: (_) => const ShowResultDialog()); + context: context, + builder: (_) => const ShowResultDialog()); }, style: TextButton.styleFrom( shape: RoundedRectangleBorder( diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart index 5ef9a98..2011695 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart @@ -3,7 +3,6 @@ import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; - class ExecutableWidget extends StatefulWidget { const ExecutableWidget({super.key}); @@ -12,15 +11,15 @@ class ExecutableWidget extends StatefulWidget { } class _ExecutableWidgetState extends State { - List daoList=[]; + List daoList = []; @override void initState() { // TODO: Fetch list an update it and remove this dummy data line - daoList= daoDetailsList; + daoList = daoDetailsList; super.initState(); } - + @override Widget build(BuildContext context) { return Scaffold( @@ -34,7 +33,6 @@ class _ExecutableWidgetState extends State { } } - List _buildDaoCardList(List list) { return list.map((item) { return DaoCard( @@ -43,4 +41,4 @@ List _buildDaoCardList(List list) { date: item.date, ); }).toList(); -} \ No newline at end of file +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart index d02b68c..bc4f8ee 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -65,10 +65,8 @@ class _ShowResultDialogState extends State ), backgroundColor: backgroundGrey, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 30 , horizontal: 20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ + padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), + child: Column(mainAxisSize: MainAxisSize.min, children: [ Stack( alignment: Alignment.center, children: [ diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index f999f83..4498373 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -39,7 +39,7 @@ class _VoteDialogState extends State { Widget build(BuildContext context) { return Dialog( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), + borderRadius: BorderRadius.circular(0), ), backgroundColor: backgroundGrey, child: Padding( @@ -60,7 +60,8 @@ class _VoteDialogState extends State { fillColor: secondryColor, ), menuStyle: MenuStyle( - backgroundColor: MaterialStateProperty.all(Theme.of(context).colorScheme.secondary), + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.secondary), ), label: Text( 'Select Farm', diff --git a/threefold_connect/lib/main.dart b/threefold_connect/lib/main.dart index 0c0d8f0..9c8f38b 100644 --- a/threefold_connect/lib/main.dart +++ b/threefold_connect/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:threefold_connect/features/dao%20page/presentation/pages/dao_page.dart'; import 'package:threefold_connect/theme/theme.dart'; + void main() { runApp(const MyApp()); } @@ -13,7 +14,7 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', - theme: threefoldTheme, + theme: threefoldTheme, home: const DaoPage(), ); } diff --git a/threefold_connect/lib/widgets/app_bar.dart b/threefold_connect/lib/widgets/app_bar.dart index 20a4244..04c6f35 100644 --- a/threefold_connect/lib/widgets/app_bar.dart +++ b/threefold_connect/lib/widgets/app_bar.dart @@ -10,7 +10,10 @@ class MyAppBar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( - title: Text(title , style: TextStyle(fontFamily: interBold , fontSize: 16),), + title: Text( + title, + style: TextStyle(fontFamily: interBold, fontSize: 16), + ), leading: IconButton( icon: const Icon(Icons.menu), onPressed: () {}, From f4f167de3a48187d999ac0bc1c5d17d880437e07 Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 22 Aug 2024 10:51:06 +0300 Subject: [PATCH 4/8] fix: edited a spelling mistake --- .../features/dao page/presentation/widgets/dao_card.dart | 2 +- .../dao page/presentation/widgets/vote_dialog.dart | 2 +- threefold_connect/lib/theme/theme.dart | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index 27375f7..22df586 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -63,7 +63,7 @@ class _DaoCardState extends State { borderRadius: BorderRadius.circular(2), ), side: const BorderSide( - color: teritaryColor, + color: tertiaryColor, ), ), child: SizedBox( diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index 4498373..27bef9d 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -57,7 +57,7 @@ class _VoteDialogState extends State { textStyle: TextStyle(color: white, fontFamily: interBold), inputDecorationTheme: const InputDecorationTheme( filled: true, - fillColor: secondryColor, + fillColor: secondaryColor, ), menuStyle: MenuStyle( backgroundColor: MaterialStateProperty.all( diff --git a/threefold_connect/lib/theme/theme.dart b/threefold_connect/lib/theme/theme.dart index 5491d44..54c014d 100644 --- a/threefold_connect/lib/theme/theme.dart +++ b/threefold_connect/lib/theme/theme.dart @@ -3,8 +3,8 @@ import 'package:google_fonts/google_fonts.dart'; // Colors const primaryColor = Color(0xFF1AA18F); -const secondryColor = Color(0xFF212121); -const teritaryColor = Color(0xFF74DDC3); +const secondaryColor = Color(0xFF212121); +const tertiaryColor = Color(0xFF74DDC3); const backgroundColor = Color(0xFF383434); const white = Color(0xFFFFFFFF); const darkred = Color(0xFFA11A1A); @@ -34,8 +34,8 @@ ThemeData threefoldTheme = ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: backgroundColor, primary: primaryColor, - secondary: secondryColor, - tertiary: teritaryColor, + secondary: secondaryColor, + tertiary: tertiaryColor, surfaceTint: Colors.transparent, ), textTheme: const TextTheme(headlineMedium: TextStyle(color: white)), From 6a52bdf0b2988830be79ecb40e9ea4b39fb88713 Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Wed, 28 Aug 2024 16:15:20 +0300 Subject: [PATCH 5/8] feat: connected tfchain_client to the app and fetched proposal,proposal votes + changing the styling of both dialogs + adding the url_launcher --- .../dao page/data/dao_card_model.dart | 12 -- .../features/dao page/data/dummy_data.dart | 34 ------ .../lib/features/dao page/data/get_dao.dart | 16 +++ .../dao page/data/get_proposal_votes.dart | 15 +++ .../lib/features/dao page/data/vote.dart | 17 +++ .../dao page/presentation/pages/dao_page.dart | 30 ++++- .../presentation/widgets/active_widget.dart | 35 +++--- .../presentation/widgets/dao_card.dart | 105 ++++++++++++------ .../widgets/executable_widget.dart | 36 +++--- .../widgets/show_result_dialog.dart | 50 +++++---- .../presentation/widgets/vote_dialog.dart | 40 +++++-- threefold_connect/pubspec.yaml | 7 ++ 12 files changed, 252 insertions(+), 145 deletions(-) delete mode 100644 threefold_connect/lib/features/dao page/data/dao_card_model.dart delete mode 100644 threefold_connect/lib/features/dao page/data/dummy_data.dart create mode 100644 threefold_connect/lib/features/dao page/data/get_dao.dart create mode 100644 threefold_connect/lib/features/dao page/data/get_proposal_votes.dart create mode 100644 threefold_connect/lib/features/dao page/data/vote.dart diff --git a/threefold_connect/lib/features/dao page/data/dao_card_model.dart b/threefold_connect/lib/features/dao page/data/dao_card_model.dart deleted file mode 100644 index 9fcd9c2..0000000 --- a/threefold_connect/lib/features/dao page/data/dao_card_model.dart +++ /dev/null @@ -1,12 +0,0 @@ -class DaoCardDetails { - String text; - String description; - String date; - - DaoCardDetails({ - required this.text, - required this.description, - required this.date, - }); -} - diff --git a/threefold_connect/lib/features/dao page/data/dummy_data.dart b/threefold_connect/lib/features/dao page/data/dummy_data.dart deleted file mode 100644 index c40a960..0000000 --- a/threefold_connect/lib/features/dao page/data/dummy_data.dart +++ /dev/null @@ -1,34 +0,0 @@ - - -import 'dao_card_model.dart'; - -var daoDetailsList = [ - DaoCardDetails( - text: 'Test', - description: 'Dummy description', - date: 'Tue Aug 13 2024 19:53:49 GMT+0300', - ), - DaoCardDetails( - text: 'Test 1', - description: 'Dummy description', - date: 'Tue Aug 13 2024 19:53:49 GMT+0300', - ), - DaoCardDetails( - text: 'Test 2', - description: 'Dummy description', - date: 'Tue Aug 13 2024 19:53:49 GMT+0300', - ), - DaoCardDetails( - text: 'Test 3', - description: 'Dummy description', - date: 'Tue Aug 13 2024 19:53:49 GMT+0300', - ), - DaoCardDetails( - text: 'Test 4', - description: 'Dummy description', - date: 'Tue Aug 13 2024 19:53:49 GMT+0300', - ), -]; - - -var farmList =['Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List' , 'Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List' , 'Option 1', 'Option 2', 'Option 3' , 'List', 'Option 1', 'Option 2', 'Option 3' , 'List']; \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/data/get_dao.dart b/threefold_connect/lib/features/dao page/data/get_dao.dart new file mode 100644 index 0000000..037e688 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_dao.dart @@ -0,0 +1,16 @@ + +import 'package:tfchain_client/models/dao.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +Future?>> getProposals() async { + try { + + final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); + await client.connect(); + final json= await client.dao.get(); + await client.disconnect(); + return json; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart new file mode 100644 index 0000000..c37f6d7 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart @@ -0,0 +1,15 @@ + +import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +Future getProposalVotes(String hash) async { + try { + final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); + await client.connect(); + final votes= await client.dao.getProposalVotes(hash: hash); + await client.disconnect(); + return votes; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/data/vote.dart b/threefold_connect/lib/features/dao page/data/vote.dart new file mode 100644 index 0000000..d094046 --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/vote.dart @@ -0,0 +1,17 @@ +import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; +import 'package:tfchain_client/tfchain_client.dart'; + +Future vote(bool vote, String hash, int farmId) async { + try { + const mnemonic = "print also path fish pizza cannon seminar prison piano merry endorse flight"; //TO-DO NEED TO BE CHANGED WITH USER ACTUAL MNEMONIC + final client = + Client("wss://tfchain.dev.grid.tf/ws", mnemonic, "sr25519"); + client.connect(); + final daoVotes = await client.dao.vote(farmId: farmId, hash: hash, approve: vote); + await client.disconnect(); + print(daoVotes.toJson()); + return daoVotes; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart index 93f29b8..58870dc 100644 --- a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; import 'package:threefold_connect/features/dao%20page/presentation/widgets/active_widget.dart'; import 'package:threefold_connect/features/dao%20page/presentation/widgets/executable_widget.dart'; import 'package:threefold_connect/theme/theme.dart'; import 'package:threefold_connect/widgets/app_bar.dart'; +import '../../data/get_dao.dart'; + class DaoPage extends StatefulWidget { const DaoPage({super.key}); @@ -11,8 +14,24 @@ class DaoPage extends StatefulWidget { State createState() => _DaoPageState(); } -//TODO : Executable page class _DaoPageState extends State { + List? activeList = []; + List? inactiveList = []; + + void setActiveList() async { + final proposals = await getProposals(); + setState(() { + activeList = proposals['activeProposals']; + inactiveList = proposals['inactiveProposals']; + }); + } + + @override + void initState() { + setActiveList(); + super.initState(); + } + @override Widget build(BuildContext context) { return DefaultTabController( @@ -42,6 +61,7 @@ class _DaoPageState extends State { child: SizedBox( height: 40, child: SearchBar( + // onChanged: filter trailing: const [ Icon( Icons.search, @@ -63,11 +83,13 @@ class _DaoPageState extends State { ), ), ), - const Expanded( + Expanded( child: TabBarView( children: [ - ActiveWidget(), - ExecutableWidget(), + ActiveWidget(activeProposals: activeList), + ExecutableWidget( + inactiveProposals: inactiveList, + ), ], ), ), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart index 4d92c8f..de6795c 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart @@ -1,44 +1,53 @@ import 'package:flutter/material.dart'; -import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; -import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; +import 'package:tfchain_client/models/dao.dart'; + +import 'dao_card.dart'; class ActiveWidget extends StatefulWidget { - const ActiveWidget({super.key}); + List? activeProposals; + ActiveWidget({super.key, required this.activeProposals}); @override State createState() => _ActiveWidgetState(); } class _ActiveWidgetState extends State { - List daoList = []; + List? activeProposals=[]; @override void initState() { - // TODO: Fetch list an update it and remove this dummy data line - daoList = daoDetailsList; + activeProposals = widget.activeProposals; super.initState(); } + @override + void didUpdateWidget(covariant ActiveWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.activeProposals != oldWidget.activeProposals) { + setState(() { + activeProposals = widget.activeProposals; + }); + } + } + @override Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: _buildDaoCardList(daoList), + children: _buildDaoCardList(activeProposals) ?? + [const Text('No active proposal at the moment')], ), ), ); } } -List _buildDaoCardList(List list) { - return list.map((item) { +List? _buildDaoCardList(List? list) { + return list?.map((item) { return DaoCard( - text: item.text, - description: item.description, - date: item.date, + proposal: item, ); }).toList(); } diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index 22df586..e1f6943 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -1,16 +1,17 @@ import 'package:flutter/material.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/show_result_dialog.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/vote_dialog.dart'; +import 'package:tfchain_client/models/dao.dart'; import 'package:threefold_connect/theme/theme.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../data/get_proposal_votes.dart'; +import 'show_result_dialog.dart'; +import 'vote_dialog.dart'; class DaoCard extends StatefulWidget { - final String text; - final String description; - final String date; + final Proposal proposal; + const DaoCard({ - required this.text, - required this.description, - required this.date, + required this.proposal, super.key, }); @@ -19,6 +20,18 @@ class DaoCard extends StatefulWidget { } class _DaoCardState extends State { + @override + void initState() { + super.initState(); + } + + Future _launchUrl() async { + final Uri _url = Uri.parse(widget.proposal.link); + if (!await launchUrl(_url)) { + throw Exception('Could not launch $_url'); + } + } + @override Widget build(BuildContext context) { return Container( @@ -31,10 +44,11 @@ class _DaoCardState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Text( - widget.text, + widget.proposal.action, style: TextStyle( color: white, - fontFamily: inter, + fontFamily: interBold, + fontSize: 16, ), textAlign: TextAlign.start, ), @@ -46,7 +60,7 @@ class _DaoCardState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Text( - widget.description, + widget.proposal.description, style: TextStyle( color: white, fontFamily: inter, @@ -57,7 +71,7 @@ class _DaoCardState extends State { Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: TextButton( - onPressed: () {}, + onPressed: _launchUrl, style: TextButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(2), @@ -98,7 +112,7 @@ class _DaoCardState extends State { child: Align( alignment: Alignment.centerLeft, child: Text( - widget.date, + widget.proposal.end.formatDateTime(), style: TextStyle( color: white, fontFamily: inter, @@ -110,42 +124,61 @@ class _DaoCardState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton( - onPressed: () { - showDialog( - context: context, - builder: (_) => const ShowResultDialog()); - }, - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4), + SizedBox( + child: TextButton( + onPressed: () async { + final votes = await getProposalVotes(widget.proposal.hash); + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (_) => ShowResultDialog( + totalVotes: votes.ayes.length + votes.nays.length, + noVotes: votes.nays.length, + yesVotes: votes.ayes.length, + threshold: votes.threshold, + )); + }, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5), + ), + backgroundColor: backgroundColor, ), - backgroundColor: backgroundColor, - ), - child: Text( - 'Show result', - style: TextStyle( - color: white, - fontFamily: interBold, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Show result', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + ), ), ), ), TextButton( onPressed: () { showDialog( - context: context, builder: (_) => const VoteDialog()); + context: context, + builder: (_) => VoteDialog( + proposal: widget.proposal, + )); }, style: TextButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(4), + borderRadius: BorderRadius.circular(5), ), backgroundColor: Theme.of(context).colorScheme.primary, ), - child: Text( - 'Vote', - style: TextStyle( - color: white, - fontFamily: interBold, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Vote', + style: TextStyle( + color: white, + fontFamily: interBold, + ), + textAlign: TextAlign.center, ), ), ), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart index 2011695..94e4066 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart @@ -1,44 +1,54 @@ import 'package:flutter/material.dart'; -import 'package:threefold_connect/features/dao%20page/data/dao_card_model.dart'; -import 'package:threefold_connect/features/dao%20page/data/dummy_data.dart'; +import 'package:tfchain_client/models/dao.dart'; import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; + +// ignore: must_be_immutable class ExecutableWidget extends StatefulWidget { - const ExecutableWidget({super.key}); + List? inactiveProposals; + ExecutableWidget({super.key , required this.inactiveProposals}); @override State createState() => _ExecutableWidgetState(); } class _ExecutableWidgetState extends State { - List daoList = []; - + List? inactiveProposals; @override void initState() { - // TODO: Fetch list an update it and remove this dummy data line - daoList = daoDetailsList; + inactiveProposals = widget.inactiveProposals; super.initState(); } + + @override + void didUpdateWidget(covariant ExecutableWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.inactiveProposals != oldWidget.inactiveProposals) { + setState(() { + inactiveProposals = widget.inactiveProposals; + }); + } + } + @override Widget build(BuildContext context) { return Scaffold( body: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - children: _buildDaoCardList(daoList), + children: _buildDaoCardList(inactiveProposals) ?? [const Text('No active proposal at the moment')], ), ), ); } } -List _buildDaoCardList(List list) { - return list.map((item) { +List? _buildDaoCardList(List? list) { + return list?.map((item) { return DaoCard( - text: item.text, - description: item.description, - date: item.date, + proposal: item, ); }).toList(); } + \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart index bc4f8ee..c57223e 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -2,7 +2,17 @@ import 'package:flutter/material.dart'; import 'package:threefold_connect/theme/theme.dart'; class ShowResultDialog extends StatefulWidget { - const ShowResultDialog({super.key}); + final int totalVotes; + final int noVotes; + final int yesVotes; + final int threshold; + const ShowResultDialog({ + required this.threshold, + required this.noVotes, + required this.yesVotes, + required this.totalVotes, + super.key, + }); @override State createState() => _ShowResultDialogState(); @@ -13,20 +23,12 @@ class _ShowResultDialogState extends State late AnimationController _animationController; late Animation _noAnimation; late Animation _yesAnimation; - late Animation _thresholdAnimation; - int got = 0; - int total = 0; - int yes = 0; - int no = 0; + late Animation _Animation; + + @override void initState() { - //TODO: Fetch api to get number of yes, no , got , total and remove dummy data below - got = 1; - total = 5; - yes = 60; - no = 40; - _animationController = AnimationController( duration: const Duration(seconds: 1), vsync: this, @@ -34,17 +36,22 @@ class _ShowResultDialogState extends State _noAnimation = Tween( begin: 0.0, - end: (no / (yes + no)), + end: widget.totalVotes != 0 + ? (widget.noVotes /widget.totalVotes * 1.0) + : 0, ).animate(_animationController); _yesAnimation = Tween( begin: 0.0, - end: (yes / (yes + no)), + end: widget.totalVotes != 0 + ? (widget.yesVotes / widget.totalVotes * 1.0) + : 0, ).animate(_animationController); - _thresholdAnimation = Tween( + _Animation = Tween( begin: 0.0, - end: (got / total), + end: (widget.totalVotes / + widget.threshold), ).animate(_animationController); _animationController.forward(); @@ -63,7 +70,7 @@ class _ShowResultDialogState extends State shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), - backgroundColor: backgroundGrey, + backgroundColor: secondaryColor, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 20), child: Column(mainAxisSize: MainAxisSize.min, children: [ @@ -75,15 +82,16 @@ class _ShowResultDialogState extends State builder: (context, child) { return LinearProgressIndicator( minHeight: 40, - value: _thresholdAnimation.value, + value: _Animation.value, color: Theme.of(context).colorScheme.primary, backgroundColor: backgroundColor, + borderRadius: const BorderRadius.all(Radius.circular(5)), ); }, ), Center( child: Text( - 'Threshold $got/$total', + 'threshold ${widget.totalVotes} / ${widget.threshold}', style: TextStyle( color: Colors.white, fontFamily: inter, @@ -106,7 +114,7 @@ class _ShowResultDialogState extends State ), ), Text( - '${(yes / (yes + no)) * 100}%', + widget.totalVotes==0 ? '0%':'${(widget.yesVotes / widget.totalVotes) * 100}%', style: TextStyle( color: Colors.white, fontFamily: inter, @@ -139,7 +147,7 @@ class _ShowResultDialogState extends State ), ), Text( - '${(no / (yes + no)) * 100}%', + widget.totalVotes==0 ? '0%': '${widget.noVotes / widget.totalVotes* 100}%', style: TextStyle( color: Colors.white, fontFamily: inter, diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index 27bef9d..c0a35af 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -1,10 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; import '../../../../theme/theme.dart'; -import '../../data/dummy_data.dart'; +import '../../data/vote.dart'; class VoteDialog extends StatefulWidget { - const VoteDialog({super.key}); + final Proposal proposal; + const VoteDialog({ + required this.proposal, + super.key, + }); @override State createState() => _VoteDialogState(); @@ -17,7 +22,7 @@ class _VoteDialogState extends State { @override void initState() { // TODO: Fetch Farms List and remove this dummy data - farms = farmList; + //farms = farmList; super.initState(); } @@ -41,7 +46,7 @@ class _VoteDialogState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0), ), - backgroundColor: backgroundGrey, + backgroundColor: secondaryColor, child: Padding( padding: const EdgeInsets.all(30), child: Flex( @@ -57,11 +62,22 @@ class _VoteDialogState extends State { textStyle: TextStyle(color: white, fontFamily: interBold), inputDecorationTheme: const InputDecorationTheme( filled: true, - fillColor: secondaryColor, + fillColor: backgroundColor, + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15)), + borderSide: BorderSide.none, + ), ), menuStyle: MenuStyle( - backgroundColor: MaterialStateProperty.all( - Theme.of(context).colorScheme.secondary), + backgroundColor: + MaterialStateProperty.all(backgroundColor), + surfaceTintColor: + MaterialStateProperty.all(Colors.transparent), + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + ), ), label: Text( 'Select Farm', @@ -80,8 +96,8 @@ class _VoteDialogState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TextButton( - onPressed: () { - //TODO: Call api to vote Yes + onPressed: () async { + //vote(true, widget.proposal.hash, 4979); // Fix FarmID Navigator.pop(context); }, style: TextButton.styleFrom( @@ -99,15 +115,15 @@ class _VoteDialogState extends State { ), ), TextButton( - onPressed: () { - //TODO: Call api to vote No + onPressed: () async { + //vote(false, widget.proposal.hash, 0); // Fix FarmID Navigator.pop(context); }, style: TextButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4), ), - backgroundColor: Theme.of(context).colorScheme.secondary, + backgroundColor: backgroundColor, ), child: Text( 'No', diff --git a/threefold_connect/pubspec.yaml b/threefold_connect/pubspec.yaml index aa8abf8..09bb68f 100644 --- a/threefold_connect/pubspec.yaml +++ b/threefold_connect/pubspec.yaml @@ -30,12 +30,19 @@ environment: dependencies: flutter: sdk: flutter + tfchain_client: + git: + url: https://github.com/codescalers/tfgrid-sdk-dart.git + ref: main + path: packages/tfchain_client/ # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 google_fonts: 6.1.0 + url_launcher: ^6.3.0 + dev_dependencies: From e3e5a67220c21eeeff7345611b78a1b3361f3e2d Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 29 Aug 2024 11:20:09 +0300 Subject: [PATCH 6/8] feat: added search functionality + refactored some code (combing active and excutable widget into one widget to avoid code repetition + moving the search functionality to be inside of this widget instead) --- .../dao page/presentation/pages/dao_page.dart | 36 +----- .../widgets/active_executable_widget.dart | 105 ++++++++++++++++++ .../presentation/widgets/active_widget.dart | 53 --------- .../presentation/widgets/dao_card.dart | 6 +- .../widgets/executable_widget.dart | 54 --------- .../widgets/show_result_dialog.dart | 6 +- .../presentation/widgets/vote_dialog.dart | 4 +- 7 files changed, 117 insertions(+), 147 deletions(-) create mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart delete mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart delete mode 100644 threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart index 58870dc..d847ac9 100644 --- a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:tfchain_client/models/dao.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/active_widget.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/executable_widget.dart'; +import 'package:threefold_connect/features/dao%20page/presentation/widgets/active_executable_widget.dart'; import 'package:threefold_connect/theme/theme.dart'; import 'package:threefold_connect/widgets/app_bar.dart'; @@ -56,39 +55,12 @@ class _DaoPageState extends State { ), ), ), - Padding( - padding: const EdgeInsets.all(10), - child: SizedBox( - height: 40, - child: SearchBar( - // onChanged: filter - trailing: const [ - Icon( - Icons.search, - color: grey, - ) - ], - backgroundColor: MaterialStateProperty.all( - Theme.of(context).colorScheme.secondary), - hintText: "Search by proposal description", - hintStyle: MaterialStateProperty.all( - TextStyle(color: grey, fontFamily: inter, fontSize: 14)), - textStyle: MaterialStateProperty.all( - TextStyle(color: grey, fontFamily: inter, fontSize: 14)), - shape: MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(15), - ), - ), - ), - ), - ), Expanded( child: TabBarView( children: [ - ActiveWidget(activeProposals: activeList), - ExecutableWidget( - inactiveProposals: inactiveList, + ActiveOrExecutableWidget(proposals: activeList), + ActiveOrExecutableWidget( + proposals: inactiveList, ), ], ), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart new file mode 100644 index 0000000..45a1f21 --- /dev/null +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:tfchain_client/models/dao.dart'; + +import '../../../../theme/theme.dart'; +import 'dao_card.dart'; + +class ActiveOrExecutableWidget extends StatefulWidget { + List? proposals; + ActiveOrExecutableWidget({super.key, required this.proposals}); + + @override + State createState() => + _ActiveOrExecutableWidgetState(); +} + +class _ActiveOrExecutableWidgetState extends State { + List? proposals = []; + + @override + void initState() { + proposals = widget.proposals; + super.initState(); + } + + @override + void didUpdateWidget(covariant ActiveOrExecutableWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.proposals != oldWidget.proposals) { + setState(() { + proposals = widget.proposals; + }); + } + } + + void search(String searchWord) { + setState(() { + final String filterText = searchWord.toLowerCase(); + if (searchWord == "") { + setState(() { + proposals = widget.proposals; + }); + } + else if (widget.proposals != null) { + setState(() { + proposals = widget.proposals + ?.where((Proposal entry) => + entry.action.toLowerCase().contains(filterText)) + .toList(); + }); + } + }); + } + + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: PreferredSize( + preferredSize: const Size.fromHeight(60.0), + child: Padding( + padding: const EdgeInsets.all(10), + child: SizedBox( + height: 40, + child: SearchBar( + onChanged: search, + trailing: const [ + Icon( + Icons.search, + color: grey, + ) + ], + backgroundColor: MaterialStateProperty.all( + Theme.of(context).colorScheme.secondary), + hintText: "Search by proposal description", + hintStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + textStyle: MaterialStateProperty.all( + TextStyle(color: grey, fontFamily: inter, fontSize: 14)), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15), + ), + ), + ), + ), + ), + ), + body: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: _buildDaoCardList(proposals) ?? + [const Text('No active proposal at the moment')], + ), + ), + ); + } +} + +List? _buildDaoCardList(List? list) { + return list?.map((item) { + return DaoCard( + proposal: item, + ); + }).toList(); +} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart deleted file mode 100644 index de6795c..0000000 --- a/threefold_connect/lib/features/dao page/presentation/widgets/active_widget.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:tfchain_client/models/dao.dart'; - -import 'dao_card.dart'; - -class ActiveWidget extends StatefulWidget { - List? activeProposals; - ActiveWidget({super.key, required this.activeProposals}); - - @override - State createState() => _ActiveWidgetState(); -} - -class _ActiveWidgetState extends State { - List? activeProposals=[]; - - @override - void initState() { - activeProposals = widget.activeProposals; - super.initState(); - } - - @override - void didUpdateWidget(covariant ActiveWidget oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.activeProposals != oldWidget.activeProposals) { - setState(() { - activeProposals = widget.activeProposals; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: _buildDaoCardList(activeProposals) ?? - [const Text('No active proposal at the moment')], - ), - ), - ); - } -} - -List? _buildDaoCardList(List? list) { - return list?.map((item) { - return DaoCard( - proposal: item, - ); - }).toList(); -} diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index e1f6943..e484a88 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -26,9 +26,9 @@ class _DaoCardState extends State { } Future _launchUrl() async { - final Uri _url = Uri.parse(widget.proposal.link); - if (!await launchUrl(_url)) { - throw Exception('Could not launch $_url'); + final Uri url = Uri.parse(widget.proposal.link); + if (!await launchUrl(url)) { + throw Exception('Could not launch $url'); } } diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart deleted file mode 100644 index 94e4066..0000000 --- a/threefold_connect/lib/features/dao page/presentation/widgets/executable_widget.dart +++ /dev/null @@ -1,54 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:tfchain_client/models/dao.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/dao_card.dart'; - - -// ignore: must_be_immutable -class ExecutableWidget extends StatefulWidget { - List? inactiveProposals; - ExecutableWidget({super.key , required this.inactiveProposals}); - - @override - State createState() => _ExecutableWidgetState(); -} - -class _ExecutableWidgetState extends State { - List? inactiveProposals; - @override - void initState() { - inactiveProposals = widget.inactiveProposals; - super.initState(); - } - - - @override - void didUpdateWidget(covariant ExecutableWidget oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.inactiveProposals != oldWidget.inactiveProposals) { - setState(() { - inactiveProposals = widget.inactiveProposals; - }); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: _buildDaoCardList(inactiveProposals) ?? [const Text('No active proposal at the moment')], - ), - ), - ); - } -} - -List? _buildDaoCardList(List? list) { - return list?.map((item) { - return DaoCard( - proposal: item, - ); - }).toList(); -} - \ No newline at end of file diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart index c57223e..c2f7fcc 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -23,7 +23,7 @@ class _ShowResultDialogState extends State late AnimationController _animationController; late Animation _noAnimation; late Animation _yesAnimation; - late Animation _Animation; + late Animation _animation; @@ -48,7 +48,7 @@ class _ShowResultDialogState extends State : 0, ).animate(_animationController); - _Animation = Tween( + _animation = Tween( begin: 0.0, end: (widget.totalVotes / widget.threshold), @@ -82,7 +82,7 @@ class _ShowResultDialogState extends State builder: (context, child) { return LinearProgressIndicator( minHeight: 40, - value: _Animation.value, + value: _animation.value, color: Theme.of(context).colorScheme.primary, backgroundColor: backgroundColor, borderRadius: const BorderRadius.all(Radius.circular(5)), diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index c0a35af..751a7dd 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -97,7 +97,7 @@ class _VoteDialogState extends State { children: [ TextButton( onPressed: () async { - //vote(true, widget.proposal.hash, 4979); // Fix FarmID + vote(true, widget.proposal.hash, 4979); // Fix FarmID Navigator.pop(context); }, style: TextButton.styleFrom( @@ -116,7 +116,7 @@ class _VoteDialogState extends State { ), TextButton( onPressed: () async { - //vote(false, widget.proposal.hash, 0); // Fix FarmID + vote(false, widget.proposal.hash, 0); // Fix FarmID Navigator.pop(context); }, style: TextButton.styleFrom( From c3be41998531820493a75d9d61ebcbcc0986bbdc Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 29 Aug 2024 14:01:12 +0300 Subject: [PATCH 7/8] feat:- connected to grid_proxy + formated the code and made variables names clearer --- .../{get_dao.dart => get_dao_proposals.dart} | 10 ++--- .../dao page/data/get_farms_list.dart | 15 +++++++ .../dao page/data/get_proposal_votes.dart | 5 +-- .../lib/features/dao page/data/vote.dart | 12 +++--- .../dao page/presentation/pages/dao_page.dart | 5 +-- .../widgets/active_executable_widget.dart | 4 +- .../presentation/widgets/dao_card.dart | 11 +++-- .../widgets/show_result_dialog.dart | 15 +++---- .../presentation/widgets/vote_dialog.dart | 41 ++++++++++++------- threefold_connect/pubspec.yaml | 10 ++++- 10 files changed, 82 insertions(+), 46 deletions(-) rename threefold_connect/lib/features/dao page/data/{get_dao.dart => get_dao_proposals.dart} (69%) create mode 100644 threefold_connect/lib/features/dao page/data/get_farms_list.dart diff --git a/threefold_connect/lib/features/dao page/data/get_dao.dart b/threefold_connect/lib/features/dao page/data/get_dao_proposals.dart similarity index 69% rename from threefold_connect/lib/features/dao page/data/get_dao.dart rename to threefold_connect/lib/features/dao page/data/get_dao_proposals.dart index 037e688..26541bd 100644 --- a/threefold_connect/lib/features/dao page/data/get_dao.dart +++ b/threefold_connect/lib/features/dao page/data/get_dao_proposals.dart @@ -1,16 +1,14 @@ - import 'package:tfchain_client/models/dao.dart'; import 'package:tfchain_client/tfchain_client.dart'; -Future?>> getProposals() async { +Future?>> getProposals() async { try { - final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); await client.connect(); - final json= await client.dao.get(); + final proposals = await client.dao.get(); await client.disconnect(); - return json; + return proposals; } catch (e) { throw Exception("Error occurred: $e"); } -} \ No newline at end of file +} diff --git a/threefold_connect/lib/features/dao page/data/get_farms_list.dart b/threefold_connect/lib/features/dao page/data/get_farms_list.dart new file mode 100644 index 0000000..46d6fbb --- /dev/null +++ b/threefold_connect/lib/features/dao page/data/get_farms_list.dart @@ -0,0 +1,15 @@ +import 'package:gridproxy_client/gridproxy_client.dart'; +import 'package:gridproxy_client/models/farms.dart'; +import 'package:threefold_connect/main.reflectable.dart'; + +Future> getMyFarms(int twinId) async { + try { + initializeReflectable(); + GridProxyClient client = GridProxyClient('https://gridproxy.dev.grid.tf/'); + final farms = + await client.farms.list(ListFarmsQueryParameters(twin_id: twinId)); + return farms; + } catch (e) { + throw Exception("Error occurred: $e"); + } +} diff --git a/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart index c37f6d7..246e796 100644 --- a/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart +++ b/threefold_connect/lib/features/dao page/data/get_proposal_votes.dart @@ -1,4 +1,3 @@ - import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; import 'package:tfchain_client/tfchain_client.dart'; @@ -6,10 +5,10 @@ Future getProposalVotes(String hash) async { try { final client = QueryClient("wss://tfchain.dev.grid.tf/ws"); await client.connect(); - final votes= await client.dao.getProposalVotes(hash: hash); + final votes = await client.dao.getProposalVotes(hash: hash); await client.disconnect(); return votes; } catch (e) { throw Exception("Error occurred: $e"); } -} \ No newline at end of file +} diff --git a/threefold_connect/lib/features/dao page/data/vote.dart b/threefold_connect/lib/features/dao page/data/vote.dart index d094046..f3a03f5 100644 --- a/threefold_connect/lib/features/dao page/data/vote.dart +++ b/threefold_connect/lib/features/dao page/data/vote.dart @@ -1,15 +1,17 @@ import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes.dart'; import 'package:tfchain_client/tfchain_client.dart'; +//TODO: mnemonic need to be changed with user mnemonic +const mnemonic = + "print also path fish pizza cannon seminar prison piano merry endorse flight"; + Future vote(bool vote, String hash, int farmId) async { try { - const mnemonic = "print also path fish pizza cannon seminar prison piano merry endorse flight"; //TO-DO NEED TO BE CHANGED WITH USER ACTUAL MNEMONIC - final client = - Client("wss://tfchain.dev.grid.tf/ws", mnemonic, "sr25519"); + final client = Client("wss://tfchain.dev.grid.tf/ws", mnemonic, "sr25519"); client.connect(); - final daoVotes = await client.dao.vote(farmId: farmId, hash: hash, approve: vote); + final daoVotes = + await client.dao.vote(farmId: farmId, hash: hash, approve: vote); await client.disconnect(); - print(daoVotes.toJson()); return daoVotes; } catch (e) { throw Exception("Error occurred: $e"); diff --git a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart index d847ac9..f0dcc04 100644 --- a/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart +++ b/threefold_connect/lib/features/dao page/presentation/pages/dao_page.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:tfchain_client/models/dao.dart'; -import 'package:threefold_connect/features/dao%20page/presentation/widgets/active_executable_widget.dart'; import 'package:threefold_connect/theme/theme.dart'; import 'package:threefold_connect/widgets/app_bar.dart'; - -import '../../data/get_dao.dart'; +import '../../data/get_dao_proposals.dart'; +import '../widgets/active_executable_widget.dart'; class DaoPage extends StatefulWidget { const DaoPage({super.key}); diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart index 45a1f21..6191c8e 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/active_executable_widget.dart @@ -39,8 +39,7 @@ class _ActiveOrExecutableWidgetState extends State { setState(() { proposals = widget.proposals; }); - } - else if (widget.proposals != null) { + } else if (widget.proposals != null) { setState(() { proposals = widget.proposals ?.where((Proposal entry) => @@ -51,7 +50,6 @@ class _ActiveOrExecutableWidgetState extends State { }); } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart index e484a88..1b66158 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/dao_card.dart @@ -26,9 +26,14 @@ class _DaoCardState extends State { } Future _launchUrl() async { - final Uri url = Uri.parse(widget.proposal.link); - if (!await launchUrl(url)) { - throw Exception('Could not launch $url'); + if (widget.proposal.link != "") { + final Uri url = Uri.parse(widget.proposal.link); + if (!await launchUrl(url)) { + const SnackBar( + content: Text( + "Can't go to proposal at this moment please try again later"), + ); + } } } diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart index c2f7fcc..754cfa3 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/show_result_dialog.dart @@ -25,8 +25,6 @@ class _ShowResultDialogState extends State late Animation _yesAnimation; late Animation _animation; - - @override void initState() { _animationController = AnimationController( @@ -37,7 +35,7 @@ class _ShowResultDialogState extends State _noAnimation = Tween( begin: 0.0, end: widget.totalVotes != 0 - ? (widget.noVotes /widget.totalVotes * 1.0) + ? (widget.noVotes / widget.totalVotes * 1.0) : 0, ).animate(_animationController); @@ -50,8 +48,7 @@ class _ShowResultDialogState extends State _animation = Tween( begin: 0.0, - end: (widget.totalVotes / - widget.threshold), + end: (widget.totalVotes / widget.threshold), ).animate(_animationController); _animationController.forward(); @@ -114,7 +111,9 @@ class _ShowResultDialogState extends State ), ), Text( - widget.totalVotes==0 ? '0%':'${(widget.yesVotes / widget.totalVotes) * 100}%', + widget.totalVotes == 0 + ? '0%' + : '${(widget.yesVotes / widget.totalVotes) * 100}%', style: TextStyle( color: Colors.white, fontFamily: inter, @@ -147,7 +146,9 @@ class _ShowResultDialogState extends State ), ), Text( - widget.totalVotes==0 ? '0%': '${widget.noVotes / widget.totalVotes* 100}%', + widget.totalVotes == 0 + ? '0%' + : '${widget.noVotes / widget.totalVotes * 100}%', style: TextStyle( color: Colors.white, fontFamily: inter, diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index 751a7dd..1eb0858 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:gridproxy_client/models/farms.dart'; import 'package:tfchain_client/models/dao.dart'; import '../../../../theme/theme.dart'; +import '../../data/get_farms_list.dart'; import '../../data/vote.dart'; class VoteDialog extends StatefulWidget { @@ -16,24 +18,29 @@ class VoteDialog extends StatefulWidget { } class _VoteDialogState extends State { - String selectedFarm = ""; - List farms = []; + int? farmId; + List farms = []; + + void setFarms() async { + List farmsList = await getMyFarms(8711); //TODO: replace with actual twin id + setState(() { + farms = farmsList; + }); + } @override void initState() { - // TODO: Fetch Farms List and remove this dummy data - //farms = farmList; + setFarms(); super.initState(); } - List> _buildDropdownMenuEntries( - List farms) { + List> _buildDropdownMenuEntries(List farms) { return farms.map((farm) { - return DropdownMenuEntry( - value: farm, - label: farm, + return DropdownMenuEntry( + value: farm.farmID, + label: farm.name, labelWidget: Text( - farm, + farm.name, style: TextStyle(color: Colors.white, fontFamily: interBold), ), ); @@ -73,7 +80,7 @@ class _VoteDialogState extends State { MaterialStateProperty.all(backgroundColor), surfaceTintColor: MaterialStateProperty.all(Colors.transparent), - shape: MaterialStateProperty.all( + shape: MaterialStateProperty.all( const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10)), ), @@ -84,9 +91,9 @@ class _VoteDialogState extends State { style: TextStyle(color: white, fontFamily: interBold), ), dropdownMenuEntries: _buildDropdownMenuEntries(farms), - onSelected: (String? value) { + onSelected: (int? value) { if (value != null) { - selectedFarm = value; + farmId = value; } }, ), @@ -97,7 +104,9 @@ class _VoteDialogState extends State { children: [ TextButton( onPressed: () async { - vote(true, widget.proposal.hash, 4979); // Fix FarmID + if (farmId != null) { + vote(true, widget.proposal.hash, farmId!); + } Navigator.pop(context); }, style: TextButton.styleFrom( @@ -116,7 +125,9 @@ class _VoteDialogState extends State { ), TextButton( onPressed: () async { - vote(false, widget.proposal.hash, 0); // Fix FarmID + if (farmId != null) { + vote(false, widget.proposal.hash, farmId!); + } Navigator.pop(context); }, style: TextButton.styleFrom( diff --git a/threefold_connect/pubspec.yaml b/threefold_connect/pubspec.yaml index 09bb68f..759acf3 100644 --- a/threefold_connect/pubspec.yaml +++ b/threefold_connect/pubspec.yaml @@ -36,12 +36,20 @@ dependencies: ref: main path: packages/tfchain_client/ - # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 google_fonts: 6.1.0 url_launcher: ^6.3.0 + gridproxy_client: + git: + url: https://github.com/codescalers/tfgrid-sdk-dart.git + ref: tfchain_gridproxy + path: packages/gridproxy_client/ + + +dependency_overrides: + meta: ^1.11.0 From 1a8c36d3ef0eb677b5ce36fecb61fa502b08216f Mon Sep 17 00:00:00 2001 From: mariammahrous23 Date: Thu, 29 Aug 2024 19:49:28 +0300 Subject: [PATCH 8/8] refactor: changed the design of drop down menu --- .../lib/features/dao page/data/vote.dart | 3 +- .../presentation/widgets/vote_dialog.dart | 87 ++++++++++-------- threefold_connect/lib/main.dart | 88 ------------------- 3 files changed, 53 insertions(+), 125 deletions(-) diff --git a/threefold_connect/lib/features/dao page/data/vote.dart b/threefold_connect/lib/features/dao page/data/vote.dart index f3a03f5..87fa65f 100644 --- a/threefold_connect/lib/features/dao page/data/vote.dart +++ b/threefold_connect/lib/features/dao page/data/vote.dart @@ -2,8 +2,7 @@ import 'package:tfchain_client/generated/dev/types/pallet_dao/proposal/dao_votes import 'package:tfchain_client/tfchain_client.dart'; //TODO: mnemonic need to be changed with user mnemonic -const mnemonic = - "print also path fish pizza cannon seminar prison piano merry endorse flight"; +const mnemonic = ""; Future vote(bool vote, String hash, int farmId) async { try { diff --git a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart index 1eb0858..fba2c11 100644 --- a/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart +++ b/threefold_connect/lib/features/dao page/presentation/widgets/vote_dialog.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:gridproxy_client/models/farms.dart'; import 'package:tfchain_client/models/dao.dart'; @@ -22,7 +23,8 @@ class _VoteDialogState extends State { List farms = []; void setFarms() async { - List farmsList = await getMyFarms(8711); //TODO: replace with actual twin id + List farmsList = + await getMyFarms(0); //TODO: replace with actual twin id setState(() { farms = farmsList; }); @@ -60,50 +62,65 @@ class _VoteDialogState extends State { direction: Axis.vertical, mainAxisSize: MainAxisSize.min, children: [ - Flexible( - fit: FlexFit.loose, - child: DropdownMenu( - menuHeight: MediaQuery.sizeOf(context).width * 0.5, - enableFilter: true, - width: MediaQuery.sizeOf(context).width * 0.6, - textStyle: TextStyle(color: white, fontFamily: interBold), - inputDecorationTheme: const InputDecorationTheme( - filled: true, - fillColor: backgroundColor, - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(15)), - borderSide: BorderSide.none, + DropdownMenu( + menuHeight: MediaQuery.sizeOf(context).height * 0.3, + enableFilter: true, + width: MediaQuery.sizeOf(context).width * 0.55, + textStyle: + TextStyle(color: white, fontFamily: interBold, fontSize: 14), + trailingIcon: const Icon( + CupertinoIcons.chevron_down, + color: white, + size: 18, + ), + selectedTrailingIcon: const Icon( + CupertinoIcons.chevron_up, + color: white, + size: 18, + ), + inputDecorationTheme: const InputDecorationTheme( + filled: true, + fillColor: backgroundColor, + enabledBorder: UnderlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(4)), + borderSide: BorderSide( + color: secondaryColor, + width: 8.0, ), ), - menuStyle: MenuStyle( - backgroundColor: - MaterialStateProperty.all(backgroundColor), - surfaceTintColor: - MaterialStateProperty.all(Colors.transparent), - shape: MaterialStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(10)), - ), + contentPadding: EdgeInsets.only(right: 5, left: 15), + ), + menuStyle: MenuStyle( + backgroundColor: + MaterialStateProperty.all(backgroundColor), + surfaceTintColor: + MaterialStateProperty.all(Colors.transparent), + shape: MaterialStateProperty.all( + const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(4)), ), ), - label: Text( - 'Select Farm', - style: TextStyle(color: white, fontFamily: interBold), - ), - dropdownMenuEntries: _buildDropdownMenuEntries(farms), - onSelected: (int? value) { - if (value != null) { - farmId = value; - } - }, + padding: MaterialStateProperty.all( + const EdgeInsets.only(right: 5, left: 15, bottom: 5)), + ), + label: Text( + 'Select Farm', + style: TextStyle( + color: white, fontFamily: interBold, fontSize: 14), ), + dropdownMenuEntries: _buildDropdownMenuEntries(farms), + onSelected: (int? value) { + if (value != null) { + farmId = value; + } + }, ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TextButton( - onPressed: () async { + onPressed: () { if (farmId != null) { vote(true, widget.proposal.hash, farmId!); } @@ -124,7 +141,7 @@ class _VoteDialogState extends State { ), ), TextButton( - onPressed: () async { + onPressed: () { if (farmId != null) { vote(false, widget.proposal.hash, farmId!); } diff --git a/threefold_connect/lib/main.dart b/threefold_connect/lib/main.dart index 9c8f38b..5edbd71 100644 --- a/threefold_connect/lib/main.dart +++ b/threefold_connect/lib/main.dart @@ -9,7 +9,6 @@ void main() { class MyApp extends StatelessWidget { const MyApp({super.key}); - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( @@ -20,90 +19,3 @@ class MyApp extends StatelessWidget { } } -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } -}