Internet Connectivity UI

This commit is contained in:
VINISTAN 2025-01-21 19:08:06 +05:30
commit 58970a13d0
11 changed files with 1134 additions and 530 deletions

View File

@ -372,14 +372,20 @@ final GoRouter router = GoRouter(
// Retrieve query parameter // Retrieve query parameter
final bgColor = state.uri.queryParameters['bgColor'] ?? final bgColor = state.uri.queryParameters['bgColor'] ??
'0xFFFFFFFF'; // Default white '0xFFFFFFFF'; // Default white
final mainTopic = state.uri.queryParameters['mainTopic'] ?? '';
final title = state.uri.queryParameters['title'] ?? '';
print('Router dataSets: $dataSets'); print('Router dataSets: $dataSets');
print('Router bgColor: $bgColor'); print('Router bgColor: $bgColor');
print('Router mainTopic: $mainTopic');
print('Router title: $title');
// Pass both values to the screen // Pass both values to the screen
return ChartScreen1( return ChartScreen1(
dataSets: dataSets, dataSets: dataSets,
bgColor: bgColor, bgColor: bgColor,
mainTopic: mainTopic,
title: title,
); );
}, },
), ),

View File

@ -102,12 +102,8 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
isExpanded: isFirstTile, isExpanded: isFirstTile,
title: mainTopic['main_topic'], title: mainTopic['main_topic'],
titleBackgroundColor: backgroundColor, titleBackgroundColor: backgroundColor,
children: _buildSubTopics( children: _buildSubTopics(mainTopic['sub_topics'] ?? [], mywidth,
mainTopic['sub_topics'] ?? [], borderColor, colorPattern, mainTopic['main_topic']),
mywidth,
borderColor,
colorPattern,
),
); );
}), }),
], ],
@ -116,7 +112,7 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
} }
List<Widget> _buildSubTopics(List<dynamic> subTopics, double myWidth, List<Widget> _buildSubTopics(List<dynamic> subTopics, double myWidth,
Color borderColor, String colorPattern) { Color borderColor, String colorPattern, mainTopic) {
print('colorPattern123 $borderColor'); print('colorPattern123 $borderColor');
// Sort sub-topics based on `sub_topic_list_order` // Sort sub-topics based on `sub_topic_list_order`
subTopics.sort((a, b) => (a['sub_topic_list_order'] ?? 0) subTopics.sort((a, b) => (a['sub_topic_list_order'] ?? 0)
@ -128,14 +124,14 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
children: [ children: [
buildCategoryTitle(subTopic['sub_topic'], borderColor), buildCategoryTitle(subTopic['sub_topic'], borderColor),
..._buildDataSetCards(subTopic['tile_data'] ?? [], myWidth, ..._buildDataSetCards(subTopic['tile_data'] ?? [], myWidth,
borderColor, colorPattern), borderColor, colorPattern, mainTopic),
], ],
)) ))
.toList(); .toList();
} }
List<Widget> _buildDataSetCards( List<Widget> _buildDataSetCards(List<dynamic> tileData, double myWidth,
List<dynamic> tileData, double myWidth, Color borderColor, colorPattern) { Color borderColor, colorPattern, mainTopic) {
// Sort datasets based on `data_set_list_order` // Sort datasets based on `data_set_list_order`
tileData.sort((a, b) => (a['data_set_list_order'] ?? 0) tileData.sort((a, b) => (a['data_set_list_order'] ?? 0)
.compareTo(b['data_set_list_order'] ?? 0)); .compareTo(b['data_set_list_order'] ?? 0));
@ -170,7 +166,8 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
borderColor, borderColor,
borderColor, borderColor,
colorPattern, colorPattern,
cardWidth, // Pass the calculated width cardWidth,
mainTopic // Pass the calculated width
), ),
), ),
); );
@ -220,11 +217,20 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
Color boldColor, Color boldColor,
colorPattern, colorPattern,
double mywidth, double mywidth,
) { String mainTopic) {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
print(colorPattern); // print('checking data');
context.go('/chartScreen/$data_set?bgColor=$colorPattern'); // print(mainTopic);
// print(title);
// print(subtitle);
// print(data_set);
final encodedMainTopic = Uri.encodeComponent(mainTopic);
final encodedTitle = Uri.encodeComponent(title);
// Pass mainTopic and title as query parameters
context.go(
'/chartScreen/$data_set?bgColor=$colorPattern&mainTopic=$encodedMainTopic&title=$encodedTitle');
// context.go('/chartScreen/$data_set'); // context.go('/chartScreen/$data_set');
}, },
child: Card( child: Card(

View File

@ -297,15 +297,16 @@ class _RegisterScreenState extends State<RegisterScreen> {
Consumer( Consumer(
builder: (context, ref, _) { builder: (context, ref, _) {
final locale = ref.watch(localeProvider); // Current locale final locale = ref.watch(localeProvider); // Current locale
return return MyToggle(
MyToggle(isOn: locale?.languageCode == 'en', isOn: locale?.languageCode == 'en',
knobTextWhenOn: 'ع', knobTextWhenOn: 'ع',
knobTextWhenOff: 'EN', knobTextWhenOff: 'EN',
pathColorWhenOn: Colors.grey.shade300, pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300,
onTap: () { onTap: () {
ref.read(localeProvider.notifier).toggleLocale(); ref.read(localeProvider.notifier).toggleLocale();
},); },
);
// IconButton( // IconButton(
// icon: Icon(locale?.languageCode == 'en' // icon: Icon(locale?.languageCode == 'en'
// ? Icons.toggle_off_outlined // ? Icons.toggle_off_outlined
@ -329,7 +330,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
buildIconContainer(Icons.report, Color(0xFF7DAFBC)), buildIconContainer(Icons.report, Color(0xFF7DAFBC)),
SizedBox(height: 20), SizedBox(height: 20),
Text( Text(
"Your registration is pending for Admin Approval.", "Your registration is pending for verification.",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
@ -338,7 +339,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
), ),
SizedBox(height: 10), SizedBox(height: 10),
Text( Text(
"Access will be granted once your account is approved.", "Kindly verify your mail to proceed further.",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
@ -452,7 +453,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
focusNode: _focusNodes[0], focusNode: _focusNodes[0],
decoration: InputDecoration( decoration: InputDecoration(
// hintText: _showHints[0] ? 'Username' : null, // hintText: _showHints[0] ? 'Username' : null,
hintText: _showHints[0] ? AppLocalizations.of(context)!.register_name : null, hintText: _showHints[0]
? AppLocalizations.of(context)!.register_name
: null,
prefixIcon: Icon( prefixIcon: Icon(
Icons.person, Icons.person,
color: Colors.blue, color: Colors.blue,
@ -471,8 +474,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
focusNode: _focusNodes[1], focusNode: _focusNodes[1],
decoration: InputDecoration( decoration: InputDecoration(
// hintText: 'Enter your email', // hintText: 'Enter your email',
hintText: hintText: _showHints[1]
_showHints[1] ? AppLocalizations.of(context)!.register_email : null, ? AppLocalizations.of(context)!.register_email
: null,
// _showHints[1] ? 'Enter your email' : null, // _showHints[1] ? 'Enter your email' : null,
prefixIcon: Icon( prefixIcon: Icon(
Icons.email, Icons.email,
@ -495,8 +499,10 @@ class _RegisterScreenState extends State<RegisterScreen> {
focusNode: _focusNodes[2], focusNode: _focusNodes[2],
obscureText: _obscurePassword, obscureText: _obscurePassword,
decoration: InputDecoration( decoration: InputDecoration(
hintText: hintText: _showHints[2]
_showHints[2] ? AppLocalizations.of(context)!.register_password : null, ? AppLocalizations.of(context)!
.register_password
: null,
// _showHints[2] ? 'Enter your password' : null, // _showHints[2] ? 'Enter your password' : null,
prefixIcon: Icon( prefixIcon: Icon(
Icons.lock, Icons.lock,
@ -528,8 +534,10 @@ class _RegisterScreenState extends State<RegisterScreen> {
focusNode: _focusNodes[3], focusNode: _focusNodes[3],
obscureText: _obscureConfirmPassword, obscureText: _obscureConfirmPassword,
decoration: InputDecoration( decoration: InputDecoration(
hintText: hintText: _showHints[3]
_showHints[3] ? AppLocalizations.of(context)!.register_Confirm_password : null, ? AppLocalizations.of(context)!
.register_Confirm_password
: null,
// _showHints[3] ? 'Confirm password' : null, // _showHints[3] ? 'Confirm password' : null,
prefixIcon: Icon( prefixIcon: Icon(
Icons.lock, Icons.lock,
@ -583,16 +591,22 @@ class _RegisterScreenState extends State<RegisterScreen> {
// text: 'I agree to ', // text: 'I agree to ',
children: [ children: [
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.terms_conditions, text: AppLocalizations.of(context)!
.terms_conditions,
// text: 'Terms & Conditions', // text: 'Terms & Conditions',
style: TextStyle(color: Colors.blue), style: TextStyle(color: Colors.blue),
), ),
TextSpan(text: AppLocalizations.of(context)!.t_and),
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.privacy_policy, text: AppLocalizations.of(context)!
.t_and),
TextSpan(
text: AppLocalizations.of(context)!
.privacy_policy,
style: TextStyle(color: Colors.blue), style: TextStyle(color: Colors.blue),
), ),
TextSpan(text: AppLocalizations.of(context)!.conditions), TextSpan(
text: AppLocalizations.of(context)!
.conditions),
], ],
), ),
), ),
@ -632,7 +646,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
children: [ children: [
Text( Text(
// "Register", // "Register",
AppLocalizations.of(context)!.register_title, AppLocalizations.of(context)!
.register_title,
style: TextStyle( style: TextStyle(
fontSize: 16, color: Colors.white), fontSize: 16, color: Colors.white),
), ),

View File

@ -8,9 +8,16 @@ import '../filters/search_filter_helper.dart';
class ChartScreen1 extends StatefulWidget { class ChartScreen1 extends StatefulWidget {
final String dataSets; final String dataSets;
final String bgColor; final String bgColor;
final String mainTopic;
final String title;
const ChartScreen1( const ChartScreen1({
{Key? key, required this.dataSets, required String this.bgColor}); Key? key,
required this.dataSets,
required String this.bgColor,
required this.mainTopic,
required this.title,
});
@override @override
_ChartScreen1State createState() => _ChartScreen1State(); _ChartScreen1State createState() => _ChartScreen1State();
} }
@ -24,17 +31,89 @@ class _ChartScreen1State extends State<ChartScreen1> {
List<dynamic> nonChartData = []; List<dynamic> nonChartData = [];
List<dynamic> filterData = []; List<dynamic> filterData = [];
List<dynamic> chartsData = []; List<dynamic> chartsData = [];
List<dynamic> tabFilteredChartData = [];
List<dynamic> tabFilteredCardData = [];
List<dynamic> cardData = []; List<dynamic> cardData = [];
List<dynamic> originalChartsData = []; List<dynamic> originalChartsData = [];
List<dynamic> originalCardData = []; List<dynamic> originalCardData = [];
List<dynamic> originalTabCardData = [];
List<dynamic> originalTabChartsData = [];
late Color backgroundColor; late Color backgroundColor;
final ScrollController _scrollController = ScrollController();
int _activeTabIndex = 0;
dynamic _tabsData = [];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
final String bgColor = widget.bgColor; final String bgColor = widget.bgColor;
print(' bgColor $bgColor'); print(' bgColor $bgColor');
fetchChartData(widget.dataSets); // fetchChartData(widget.dataSets);
fetchChartData(widget.dataSets).then((_) {
if (_tabsData.isNotEmpty) {
// Call onTabSelected for the first tab
onTabSelected(_tabsData[0]['id']);
}
});
}
void _scrollToIndex(int index) {
double scrollPosition = index * 120.0; // Adjust based on tab size
_scrollController.animateTo(
scrollPosition,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void _scrollLeft() {
if (_activeTabIndex > 0) {
setState(() {
_activeTabIndex--;
});
_scrollToIndex(_activeTabIndex);
onTabSelected(_tabsData[_activeTabIndex]['id']!); // Pass the tab's id
}
}
void _scrollRight() {
if (_activeTabIndex < _tabsData.length - 1) {
setState(() {
_activeTabIndex++;
});
_scrollToIndex(_activeTabIndex);
onTabSelected(_tabsData[_activeTabIndex]['id']!); // Pass the tab's id
}
}
void processChartData(chartsData) {
// Group data by 'kpi'
Map<String, List<Map<String, dynamic>>> groupedData = {};
for (var chart in chartsData) {
String kpi = chart['kpi'] ?? '';
if (!groupedData.containsKey(kpi)) {
groupedData[kpi] = [];
}
groupedData[kpi]!.add(chart);
}
// Format 'kpi' values for _tabs
List<Map<String, String>> _tabs = groupedData.keys.map((kpi) {
String name = kpi
.split('_') // Split by underscore
.map(
(word) => word[0].toUpperCase() + word.substring(1)) // Capitalize
.join(' '); // Join words with space
return {'id': kpi, 'name': name};
}).toList();
print('Grouped Data: $groupedData');
print('Tabs: $_tabs');
setState(() {
_tabsData = _tabs;
});
} }
Future<void> fetchChartData(String dataSets) async { Future<void> fetchChartData(String dataSets) async {
@ -49,6 +128,9 @@ class _ChartScreen1State extends State<ChartScreen1> {
chartsData = isChartData; chartsData = isChartData;
cardData = nonChartData; cardData = nonChartData;
processChartData(chartsData);
print('chartsData :- $chartsData'); print('chartsData :- $chartsData');
print('cardData :- $cardData'); print('cardData :- $cardData');
print('filterData :- $filterData'); print('filterData :- $filterData');
@ -64,8 +146,9 @@ class _ChartScreen1State extends State<ChartScreen1> {
// Check if all filter_data is empty // Check if all filter_data is empty
if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) { if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) {
setState(() { setState(() {
chartsData = List.from(originalChartsData); // Restore the original data chartsData =
cardData = List.from(originalCardData); // Restore the original data List.from(originalTabChartsData); // Restore the original data
cardData = List.from(originalTabCardData); // Restore the original data
}); });
print('Returning as no filters are selected'); print('Returning as no filters are selected');
Navigator.pop(context); Navigator.pop(context);
@ -151,6 +234,14 @@ class _ChartScreen1State extends State<ChartScreen1> {
Navigator.pop(context); Navigator.pop(context);
} }
String capitalizeAndSplit(String text) {
if (text.isEmpty) return text;
return text
.split('_') // Split by underscores
.map((word) => word[0].toUpperCase() + word.substring(1).toLowerCase())
.join(' '); // Join words with a space
}
void showRightSideModal(BuildContext context, List filters, List data) { void showRightSideModal(BuildContext context, List filters, List data) {
// Initialize selected filters structure from the stored value, if exists // Initialize selected filters structure from the stored value, if exists
List<Map<String, dynamic>> selectedFilters = List<Map<String, dynamic>> selectedFilters =
@ -215,7 +306,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
filterKey, capitalizeAndSplit(filterKey),
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -330,8 +421,8 @@ class _ChartScreen1State extends State<ChartScreen1> {
filter["filter_data"].clear(); filter["filter_data"].clear();
}); });
setState(() { setState(() {
chartsData = List.from(originalChartsData); chartsData = List.from(originalTabChartsData);
cardData = List.from(originalCardData); cardData = List.from(originalTabCardData);
}); });
// Reset the selectedFiltersStorage to empty when clearing // Reset the selectedFiltersStorage to empty when clearing
selectedFiltersStorage.clear(); selectedFiltersStorage.clear();
@ -347,8 +438,8 @@ class _ChartScreen1State extends State<ChartScreen1> {
print( print(
"Selected Filters before applying: $selectedFilters"); "Selected Filters before applying: $selectedFilters");
setState(() { setState(() {
chartsData = originalChartsData; chartsData = originalTabChartsData;
cardData = originalCardData; cardData = originalTabCardData;
}); });
applyFilters(context, filters, chartsData, cardData, applyFilters(context, filters, chartsData, cardData,
@ -372,8 +463,68 @@ class _ChartScreen1State extends State<ChartScreen1> {
); );
} }
void onTabSelected(String tabId) {
print('Selected Tab: $tabId');
selectedFiltersStorage.clear();
setState(() {
chartsData = originalChartsData;
cardData = originalCardData;
});
performActionForTab(tabId);
}
void performActionForTab(String tabId) {
print('Selected Tab: $tabId');
// Filter the chartsData array based on the tabId
tabFilteredChartData = chartsData.where((chart) {
// Assuming each chart item has a 'kpi' field that matches tabId
return chart['kpi'] == tabId;
}).toList(); // Convert to list after filtering
print('tabFilteredChartData Data for Tab $tabId: $tabFilteredChartData');
setState(() {
chartsData = tabFilteredChartData;
originalTabChartsData =
List.from(tabFilteredChartData); // Store original data
});
// Filter the chartsData array based on the tabId
tabFilteredCardData = cardData.where((chart) {
// Assuming each chart item has a 'kpi' field that matches tabId
return chart['kpi'] == tabId;
}).toList(); // Convert to list after filtering
print('tabFilteredCardData Data for Tab $tabId: $tabFilteredCardData');
setState(() {
cardData = tabFilteredCardData;
originalTabCardData = List.from(tabFilteredCardData);
});
// You can perform further actions with the filteredData, like updating the UI
// For example, you can update the chart data or display the results
}
double calculateAspectRatio(int itemCount) {
// Modify the logic based on your layout requirements
if (itemCount <= 2) {
return 190.5 / 180;
} else if (itemCount == 3) {
return 180.0 / 300;
} else if (itemCount == 4) {
return 190.5 / 180;
} else {
return 180.0 / 260; // Default for more items
// return 190.5 / 180;
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
final color = final color =
Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16)); Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16));
return Scaffold( return Scaffold(
@ -385,7 +536,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white), icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () { onPressed: () {
context.go('/myhomepage'); context.go('/uaenumbers');
}, },
), ),
title: Text( title: Text(
@ -397,6 +548,55 @@ class _ChartScreen1State extends State<ChartScreen1> {
? Center(child: CircularProgressIndicator()) ? Center(child: CircularProgressIndicator())
: Column( : Column(
children: [ children: [
Container(
// height: myheight / 5,
width: double.infinity,
color: color,
child: Padding(
padding: EdgeInsets.only(
left: 30, right: 30, top: 10, bottom: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.mainTopic ?? '',
style: TextStyle(
color: Colors.white,
fontSize: 26,
),
),
Container(
width: mywidth / 4,
child: Divider(
thickness: 8,
color: Colors.white,
)),
Text(
widget.title,
style: TextStyle(color: Colors.white, fontSize: 20),
),
// Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
// IconButton(
// onPressed: () {},
// icon: Icon(
// Icons.bookmark_add_outlined,
// color: Colors.white,
// size: 40,
// )),
// IconButton(
// onPressed: () {},
// icon: Icon(
// Icons.share,
// color: Colors.white,
// size: 30,
// )),
// ],
// ),
],
),
)),
Expanded( Expanded(
child: ListView( child: ListView(
children: [ children: [
@ -404,8 +604,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment mainAxisAlignment: MainAxisAlignment.end,
.end, // Aligns the row's content to the right
children: [ children: [
Row( Row(
children: [ children: [
@ -416,12 +615,12 @@ class _ChartScreen1State extends State<ChartScreen1> {
color: Colors.white, color: Colors.white,
), ),
), ),
SizedBox(width: 5),
Icon(Icons.bookmark_add_outlined, Icon(Icons.bookmark_add_outlined,
color: Colors.white, size: 18), color: Colors.white, size: 18),
], ],
), ),
SizedBox( SizedBox(width: 10),
width: 10), // Horizontal space between items
Row( Row(
children: [ children: [
Text( Text(
@ -431,15 +630,16 @@ class _ChartScreen1State extends State<ChartScreen1> {
color: Colors.white, color: Colors.white,
), ),
), ),
SizedBox(width: 5),
Icon(Icons.share_sharp, Icon(Icons.share_sharp,
color: Colors.white, size: 18), color: Colors.white, size: 18),
], ],
), ),
SizedBox( SizedBox(
width: 10), // Horizontal space between items width: 5), // Horizontal space between items
IconButton( IconButton(
icon: Icon(Icons.filter_alt_outlined, icon: Icon(Icons.filter_alt_outlined,
color: Colors.white, size: 18), color: Colors.white, size: 28),
onPressed: () { onPressed: () {
showRightSideModal( showRightSideModal(
context, filterData, chartsData); context, filterData, chartsData);
@ -449,19 +649,67 @@ class _ChartScreen1State extends State<ChartScreen1> {
), ),
], ],
), ),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Left arrow button
_buildArrowButton(
onPressed: _activeTabIndex > 0 ? _scrollLeft : null,
icon: Icons.arrow_back_ios_new,
),
// Tabs with horizontal scroll
Expanded(
child: SingleChildScrollView(
controller: _scrollController,
scrollDirection: Axis.horizontal,
child: Row(
children:
List.generate(_tabsData.length, (index) {
return _buildTab(
_tabsData[index],
isActive: index == _activeTabIndex,
);
}),
),
),
),
// Right arrow button
_buildArrowButton(
onPressed: _activeTabIndex < _tabsData.length - 1
? _scrollRight
: null,
icon: Icons.arrow_forward_ios,
),
],
),
// Expanded(
// child: Center(
// child: Text(
// 'Selected Tab: ${_tabsData.isNotEmpty ? _tabsData[_activeTabIndex] : 'None'}',
// style: const TextStyle(fontSize: 18),
// ),
// ),
// ),
// nonChartData Cards // nonChartData Cards
GridView.builder( Padding(
padding: const EdgeInsets.all(3.34),
child: GridView.builder(
itemCount: cardData.length, itemCount: cardData.length,
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
gridDelegate: gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount( SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // 2 cards per row crossAxisCount: cardData.length == 2
crossAxisSpacing: 10, ? 2
mainAxisSpacing: 10, : cardData.length == 3
childAspectRatio: 190.5 / ? 3
200, // Adjusted to maintain width and fixed height : cardData.length == 4
), ? 2
: 3, // Default to 3 if more than 4 items // 2 cards per row
crossAxisSpacing: 2,
mainAxisSpacing: 5,
childAspectRatio:
calculateAspectRatio(cardData.length)),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = cardData[index]; final item = cardData[index];
print('item item item $item'); print('item item item $item');
@ -500,26 +748,27 @@ class _ChartScreen1State extends State<ChartScreen1> {
fontSize: 11, color: Colors.grey), fontSize: 11, color: Colors.grey),
), ),
Text( Text(
apiService apiService.formatAmount(
.formatAmount(data['lastYearValue']), data['lastYearValue']),
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5), color: Color(0xFF90B0D5),
), ),
), ),
SizedBox( SizedBox(
height: 5, // Height of the divider height: 2, // Height of the divider
child: Divider( child: Divider(
color: Colors.grey, color: Colors.grey,
thickness: 1, // Divider line thickness thickness:
1, // Divider line thickness
), ),
), ),
Text( Text(
apiService.formatAmount( apiService.formatAmount(
data['secondLastYearValue']), data['secondLastYearValue']),
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFFD83731), color: Color(0xFFD83731),
), ),
@ -565,9 +814,9 @@ class _ChartScreen1State extends State<ChartScreen1> {
Text( Text(
'${data['roundedAverage'] ?? 'NA'}', '${data['roundedAverage'] ?? 'NA'}',
style: const TextStyle( style: const TextStyle(
fontSize: 26, fontSize: 22,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
color: Color(0xFF11AF22), color: Color(0xFF90B0D5),
), ),
), ),
], ],
@ -580,6 +829,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
} }
}, },
), ),
),
// chartsData Cards // chartsData Cards
ListView.builder( ListView.builder(
itemCount: chartsData.length, itemCount: chartsData.length,
@ -612,4 +862,58 @@ class _ChartScreen1State extends State<ChartScreen1> {
), ),
); );
} }
Widget _buildArrowButton(
{required VoidCallback? onPressed, required IconData icon}) {
final color =
Color(int.parse(widget.bgColor.replaceFirst('0x', ''), radix: 16));
return Container(
margin: EdgeInsets.symmetric(horizontal: 5.0),
width: 35.0, // Set the width of the circle
height: 35.0,
decoration: BoxDecoration(
color: onPressed == null ? Colors.grey[400] : Colors.white,
shape: BoxShape.circle,
// boxShadow: [
// BoxShadow(
// color: Colors.black26,
// blurRadius: 4.0,
// offset: Offset(2, 2),
// ),
// ],
),
child: IconButton(
onPressed: onPressed,
icon: Icon(icon, color: onPressed == null ? Colors.grey : color),
iconSize: 15.0,
),
);
}
Widget _buildTab(Map<String, String> tab, {bool isActive = false}) {
return GestureDetector(
onTap: () {
setState(() {
_activeTabIndex = _tabsData.indexOf(tab);
});
_scrollToIndex(_activeTabIndex);
onTabSelected(tab['id']!);
},
child: Container(
margin: EdgeInsets.symmetric(horizontal: 8.0),
padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 16.0),
decoration: BoxDecoration(
color: isActive ? Colors.white : Colors.grey[400],
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
tab['name']!,
style: TextStyle(
color: isActive ? Colors.black : Colors.white,
fontWeight: isActive ? FontWeight.w500 : FontWeight.w400,
),
),
),
);
}
} }

View File

@ -294,46 +294,64 @@ class ChartWidget extends StatelessWidget {
aspectRatio: 1.5, aspectRatio: 1.5,
child: BarChart( child: BarChart(
BarChartData( BarChartData(
alignment: BarChartAlignment.spaceBetween, alignment: BarChartAlignment.start,
barTouchData: BarTouchData( barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
// tooltipBgColor: Colors.black.withOpacity(0.8),
fitInsideHorizontally: true,
fitInsideVertically: false,
tooltipPadding: const EdgeInsets.all(8),
tooltipMargin: 16,
getTooltipItem: getTooltipItem:
(groupData, groupIndex, rodData, rodIndex) { (groupData, groupIndex, rodData, rodIndex) {
// print('groupData $groupData'); // Get the list of group names dynamically
// print('groupIndex $groupIndex'); List<String> groupNames = [];
// print('rodData $rodData'); for (var entry in chartData['response']) {
// print('rodIndex $rodIndex'); String groupValue = entry['ObsKey'][groupByKey];
// Assume groupedData is passed as a parameter if (!groupNames.contains(groupValue)) {
// List<String> timePeriods = groupNames.add(groupValue);
// groupedData.values.first.keys.toList(); }
// String timePeriod = timePeriods[groupIndex]; }
// List<BarChartRodStackItem> rodStackItems =
// rodData.rodStackItems; // Accessing the stacked rod items and calculating the tooltip text
// List<BarChartRodStackItem> rodStackItems =
// String tooltipText = ''; rodData.rodStackItems;
// for (int i = 0; i < rodStackItems.length; i++) { List<TextSpan> tooltipTextSpans = [];
// double fromY = rodStackItems[i].fromY;
// double toY = rodStackItems[i].toY; for (int i = 0; i < rodStackItems.length; i++) {
// double value = toY - fromY; double fromY = rodStackItems[i].fromY;
// String groupName = groupedData.keys.elementAt(i); double toY = rodStackItems[i].toY;
// double value = toY - fromY;
// tooltipText += String groupName = groupNames[i];
// '$timePeriod - ${value.toStringAsFixed(0)} - $groupName\n';
// } // Get the color for the current group
// Color groupColor = _getColorForGroup(
// return BarTooltipItem( i); // Replace with your color logic
// tooltipText,
// TextStyle(color: Colors.white, fontSize: 12), // Add a TextSpan for the colored circle and the group name with value
// ); tooltipTextSpans.addAll([
TextSpan(
text: '',
style: TextStyle(
color: groupColor,
fontSize: 14), // Circle color
),
TextSpan(
text:
'$groupName - ${value.toStringAsFixed(0)}\n',
style:
TextStyle(color: Colors.white, fontSize: 12),
),
]);
}
return BarTooltipItem(
'',
TextStyle(color: Colors.white, fontSize: 12),
children: tooltipTextSpans,
);
}, },
), ),
// touchCallback: (BarTouchResponse touchResponse) {
// // Handle touch events, such as hover
// if (touchResponse.touchInput is PointerDownEvent) {
// // If you want to handle touch down events, you can add your logic here.
// print('Bar touched: ${touchResponse.touchInput}');
// }
// },
handleBuiltInTouches: true, // Enable built-in touch events handleBuiltInTouches: true, // Enable built-in touch events
), ),
titlesData: FlTitlesData( titlesData: FlTitlesData(
@ -359,7 +377,7 @@ class ChartWidget extends StatelessWidget {
rightTitles: rightTitles:
AxisTitles(sideTitles: SideTitles(showTitles: false)), AxisTitles(sideTitles: SideTitles(showTitles: false)),
), ),
gridData: FlGridData(show: true), gridData: FlGridData(show: false),
borderData: FlBorderData(show: false), borderData: FlBorderData(show: false),
barGroups: _generateBarGroups(chartData, groupByKey), barGroups: _generateBarGroups(chartData, groupByKey),
), ),
@ -389,11 +407,23 @@ class ChartWidget extends StatelessWidget {
), ),
), ),
SizedBox(width: 5), SizedBox(width: 5),
Text( Tooltip(
group, message: group,
waitDuration: Duration(milliseconds: 500),
showDuration: Duration(seconds: 2),
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(4),
),
textStyle: TextStyle(color: Colors.white),
child: Text(
group.length > 10
? '${group.substring(0, 10)}...'
: group,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 11), style: TextStyle(fontSize: 11),
), ),
)
], ],
); );
}).toList(); }).toList();

View File

@ -149,7 +149,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
); );
print('userDetails: $userDetailsResponse'); print('userDetails: $userDetailsResponse');
setState(() { setState(() {
_usernameController.text = userDetailsResponse.data['username'] ?? ''; _usernameController.text = userDetailsResponse.data['uname'] ?? '';
_emailController.text = userDetailsResponse.data['email'] ?? ''; _emailController.text = userDetailsResponse.data['email'] ?? '';
role = userDetailsResponse.data['role'] ?? ''; role = userDetailsResponse.data['role'] ?? '';
}); });

View File

@ -21,6 +21,9 @@ import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_r
import '../../Screens/auth_verification/registration.dart'; import '../../Screens/auth_verification/registration.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import '../../components/indicators/locale_provider.dart';
import '../../components/my_toggle.dart';
class LoginRoute extends HookConsumerWidget { class LoginRoute extends HookConsumerWidget {
final pb = PocketBase('https://pb.venbait.in'); final pb = PocketBase('https://pb.venbait.in');
// final _pb = PocketBase('http://127.0.0.1:8090'); // final _pb = PocketBase('http://127.0.0.1:8090');
@ -82,6 +85,7 @@ class LoginRoute extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final locale = ref.watch(localeProvider);
final emailCtl = useTextEditingController(); final emailCtl = useTextEditingController();
final pwCtl = useTextEditingController(); final pwCtl = useTextEditingController();
final forgotPwBtn = TextButton( final forgotPwBtn = TextButton(
@ -514,9 +518,16 @@ class LoginRoute extends HookConsumerWidget {
), ),
children: [ children: [
36.verticalSpace, 36.verticalSpace,
const Align( Align(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
child: LangToggle(), child: MyToggle(isOn: locale?.languageCode == 'en',
knobTextWhenOn: 'ع',
knobTextWhenOff: 'EN',
pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300,
onTap: (){
ref.read(localeProvider.notifier).toggleLocale();
},),
), ),
16.verticalSpace, 16.verticalSpace,
helloAndPleaseLoginTexts, helloAndPleaseLoginTexts,

View File

@ -175,18 +175,28 @@ class MyHomePage extends StatefulWidget {
State<MyHomePage> createState() => _MyHomePageState(); State<MyHomePage> createState() => _MyHomePageState();
} }
void handleInfoCardClick(BuildContext context, String data) { void handleInfoCardClick(BuildContext context, String data, Color color) {
// Handle navigation and pass dynamic data // Handle navigation and pass dynamic data
print(data); print(data);
final dataSets = data; final dataSets = data;
print(dataSets); if (dataSets != null) {
if (dataSets == 'hotels') { // Perform navigation
context.go('/chartScreen/$dataSets');
} else if (dataSets == 'divorces') {
context.go('/chartScreen/$dataSets');
} else if (dataSets == 'marriages') {
context.go('/chartScreen/$dataSets'); context.go('/chartScreen/$dataSets');
} else {
// Show error if dataSet is null
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('No dataset available')),
);
} }
// final dataSets = data;
// print(dataSets);
// if (dataSets == 'hotels') {
// context.go('/chartScreen/$dataSets');
// } else if (dataSets == 'divorces') {
// context.go('/chartScreen/$dataSets');
// } else if (dataSets == 'marriages') {
// context.go('/Chart/$dataSets');
// }
} }
class _MyHomePageState extends State<MyHomePage> { class _MyHomePageState extends State<MyHomePage> {
@ -195,243 +205,294 @@ class _MyHomePageState extends State<MyHomePage> {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold( return BaseScaffold(
mycenterTitle: true, title: Center(
title: SizedBox( child: SizedBox(
height: myheight / 5, height: myheight / 5,
width: mywidth / 3, width: mywidth / 3,
child: Image(image: AssetImage('assets/logos/uae_stat.png'))), child: Image(image: AssetImage('assets/logos/uae_stat.png')))),
body: EconomyStats(), body: EconomyStatsWidget(),
); );
} }
} }
class EconomyStats extends StatelessWidget { class EconomyStatsWidget extends StatefulWidget {
const EconomyStats({Key? key}) : super(key: key); const EconomyStatsWidget({super.key});
@override @override
EconomyStatsState createState() => EconomyStatsState();
}
class EconomyStatsState extends State<EconomyStatsWidget> {
List<dynamic> data = [];
bool isLoading = true;
@override
void initState() {
super.initState();
fetchData();
}
Future<void> fetchData() async {
const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
try {
final response = await http.get(Uri.parse(baseUrl));
if (response.statusCode == 200) {
setState(() {
data = json.decode(response.body);
// print("HomeDAta $data");
// Sort data after fetching to ensure the correct order
data.forEach((mainTopic) {
if (mainTopic['tile_data'] != null) {
// print('Original tile_data: ${mainTopic['tile_data']}');
mainTopic['tile_data']?.sort((a, b) {
try {
final aOrder = int.tryParse(
a['data_set_list_order']?.toString() ?? '0') ??
0;
final bOrder = int.tryParse(
b['data_set_list_order']?.toString() ?? '0') ??
0;
return aOrder.compareTo(bOrder);
} catch (e) {
// Handle any errors during sorting
print('Error during sorting: $e');
return 0; // In case of an error, don't alter the order
}
});
// Print the sorted tile_data
// print('Sorted tile_data: ${mainTopic['tile_data']}');
}
});
isLoading = false;
});
} else {
throw Exception('Failed to load data');
}
} catch (e) {
setState(() {
isLoading = false;
});
print('Error fetching data: $e');
}
}
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SingleChildScrollView( double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width;
if (isLoading) {
return Center(child: CircularProgressIndicator());
} else if (data.isEmpty) {
return Center(child: Text("No data available"));
}
return Container(
height: myheight,
// color: Colors.cyan,
child: Padding( child: Padding(
padding: EdgeInsets.only(left: 10, right: 10), padding: EdgeInsets.only(left: 10, right: 10),
child: Column( child: Column(
children: data.map((mainTopic) {
String colorPattern = mainTopic['color_pattern'];
// Color backgroundColor = Color(int.parse(colorPattern));
Color backgroundColor;
try {
backgroundColor = Color(int.parse(colorPattern));
} catch (e) {
backgroundColor = Colors.grey; // Fallback color
print('Invalid color format: $colorPattern');
}
Color borderColor =
backgroundColor; // Use the same color for the border
// final totalTiles = mainTopic['sub_topics']
// .expand((subTopic) => (subTopic['tile_data'] as List<dynamic>? ?? []))
// .length;
final totalTiles =
(mainTopic['tile_data'] as List<dynamic>?)?.length ?? 0;
// Compute crossAxisCount dynamically
// final crossAxisCount = (totalTiles / 2).ceil(); // Divide by 2 and round up
// final crossAxisCount = (totalTiles / 2).ceil().clamp(1, 2); // Safeguard
final crossAxisCount =
totalTiles > 0 ? (totalTiles / 2).ceil().clamp(1, 2) : 1;
return Expanded(
child: Container(
// color: Colors.cyan,
height:
myheight, // Set the background color for the entire Column
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Header Section
RoundedCornerContainer( RoundedCornerContainer(
text: 'ECONOMY', text: mainTopic['main_topic'],
backgroundColor: Color(0xFF7DAFBC), backgroundColor: backgroundColor,
textStyle: const TextStyle( textStyle: const TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
color: Colors.white, color: Colors.white,
), ),
), ),
// Grid Section SizedBox(
height: myheight / 4.8, // Set dynamic height
child: Container(
// color: Colors.grey[200], // Set a background color for the scrollable container
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 2,
),
child: MasonryGridView.builder(
gridDelegate:
SliverSimpleGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
),
physics: const NeverScrollableScrollPhysics(),
itemCount: totalTiles,
itemBuilder: (context, index) {
final tileDataList =
(mainTopic['tile_data'] as List<dynamic>?) ??
[];
// ECONOMY DETAILS final tileData = Map<String, String>.from(
Padding( tileDataList[index],
padding: const EdgeInsets.only( );
top: 10,
),
child: Column(
children: [
// First Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'GDP (Constant)',
subtitle: '(2022) (AED)',
value: '1.62T',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'Inflation'),
),
InfoCard(
title: 'Inflation Rate',
subtitle: '(2022)',
value: '4.82%',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'Inflation'),
),
],
),
const SizedBox(height: 10),
// Second Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Trade Value',
subtitle: '(Jan - Jan 2024) - AED',
value: '215.4B',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'commodities'),
),
InfoCard(
title: 'Hotel Guests',
subtitle: '(2022)',
value: '25.21M',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(context, 'hotels'),
),
],
),
const SizedBox(height: 10),
RoundedCornerContainer(
text: 'SOCIAL',
backgroundColor: Colors.brown[200]!,
textStyle: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
// SOCIAL DETAILS return Container(
Padding( margin: const EdgeInsets.all(0),
padding: const EdgeInsets.only( height:
top: 10, myheight / 9.2, // Variable height for tiles
), width: mywidth / 3,
padding:
const EdgeInsets.only(bottom: 3, top: 3),
// color: Colors.yellowAccent.shade100, // Tile background color
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// First Row Expanded(
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Divorces',
subtitle: '(2022)',
value: '0',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'divorces'),
),
InfoCard(
title: 'Marriages',
subtitle: '(2022)',
value: '0',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'marriages'),
),
],
),
const SizedBox(height: 10),
// Second Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Hospitals (Gov)',
subtitle: '(Jan - Jan 2024) - AED',
value: '215.4B',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'Hospitals'),
),
InfoCard(
title: 'Schools',
subtitle: '(2022)',
value: '25.21M',
bordercolor: Colors.brown[200]!,
textcolor: Colors.brown[200]!,
onTap: () =>
handleInfoCardClick(context, 'Schools'),
),
],
),
const SizedBox(height: 10),
RoundedCornerContainer(
text: 'ENVIRONMENT',
backgroundColor: Color(0xFF7DAFBC),
textStyle: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
// ENVIRONMENT DETAILS
Padding(
padding: const EdgeInsets.only(
top: 10,
),
child: Column( child: Column(
children: [ crossAxisAlignment:
// First Row CrossAxisAlignment.start,
Row( children: _buildRows(
mainAxisAlignment: [tileData],
MainAxisAlignment.spaceEvenly, borderColor,
children: [ mainTopic['color_pattern']),
InfoCard(
title: 'Electricity',
subtitle: '(2022) (AED)',
value: '1.62T',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(
context, 'Electricity'),
),
InfoCard(
title: 'Cruid oil',
subtitle: '(2022)',
value: '4.82%',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'Cruid'),
),
],
),
const SizedBox(height: 10),
// Second Row
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
InfoCard(
title: 'Export of oil',
subtitle: '(Jan - Jan 2024) - AED',
value: '215.4B',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () =>
handleInfoCardClick(context, 'Export'),
),
InfoCard(
title: 'Desalinated water',
subtitle: '(2022)',
value: '25.21M',
bordercolor: Color(0xFF7DAFBC),
textcolor: Color(0xFF7DAFBC),
onTap: () => handleInfoCardClick(
context, 'Desalinated'),
),
],
),
],
), ),
), ),
], ],
), ),
);
},
),
), ),
],
), ),
), ),
], ],
), ),
), ),
); );
}).toList(),
),
),
);
} }
} }
//
// List<Widget> _buildRows(List<Map<String, String>> tileData, Color borderColor) {
//
//
// List<Widget> rows = [];
//
//
// for (int i = 0; i < tileData.length; i += 2) {
// // Adding a row for every two items
// rows.add(
// Container(
// // color: Colors.grey[200], // Set background color for the row
// // padding: EdgeInsets.symmetric(vertical: 7.0), // Optional padding
// padding: EdgeInsets.only(top:5, bottom:2),
// child: Expanded(
// child: Row(
// mainAxisAlignment: MainAxisAlignment.start,
// children: tileData
// .sublist(i, i + 2 > tileData.length ? tileData.length : i + 2)
// .map((tile) {
// return Expanded(
// child: InfoCard(
// title: tile['data_set_tile_heading']!,
// subtitle: tile['value_source']!,
// value: tile['value']!,
// dataset:tile['data_set']!,
// bordercolor: borderColor,
// textcolor: borderColor,
// backgroundColor: Colors.white, // Set background color for InfoCard
// onTap: () => {},
//
// ),
// );
// }).toList(),
// ),
// ),
// ),
// );
// // rows.add(SizedBox(height: 1)); // Add space between rows
// }
//
// return rows;
// }
List<Widget> _buildRows(
List<Map<String, dynamic>> tileData, Color borderColor, color_pattern) {
// tileData.sort((a, b) =>
// (a['data_set_list_order'] ?? 0).compareTo(b['data_set_list_order'] ?? 0),);
List<Widget> rows = [];
// print('tileDataLength: $tileData.length');
for (int i = 0; i < tileData.length; i += 2) {
// Adding a row for every two items
rows.add(
Container(
padding: EdgeInsets.only(top: 5, bottom: 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: tileData
.sublist(i, i + 2 > tileData.length ? tileData.length : i + 2)
.map((tile) {
return Expanded(
child: InfoCard(
// title: tile['data_set_tile_heading']!,
title: tile['data_set_tile_heading'] ?? 'Unknown Title',
subtitle: tile['value_source']!,
value: tile['value']!,
dataset: tile['data_set']!,
bordercolor: borderColor,
textcolor: borderColor,
backgroundColor:
Colors.white, // Set background color for InfoCard
onTap: () {},
),
);
}).toList(),
),
),
);
}
return rows;
}
class RoundedCornerContainer extends StatelessWidget { class RoundedCornerContainer extends StatelessWidget {
final String text; final String text;
final Color backgroundColor; final Color backgroundColor;
@ -449,7 +510,7 @@ class RoundedCornerContainer extends StatelessWidget {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: backgroundColor, color: backgroundColor,
borderRadius: BorderRadius.circular(12), // Rounded corners borderRadius: BorderRadius.circular(16), // Rounded corners
), ),
child: Center( child: Center(
child: Text( child: Text(
@ -470,18 +531,22 @@ class InfoCard extends StatelessWidget {
final String title; final String title;
final String subtitle; final String subtitle;
final String value; final String value;
final String dataset;
final Color bordercolor; final Color bordercolor;
final Color? textcolor; final Color? textcolor;
final VoidCallback onTap; // New callback parameter final VoidCallback onTap;
final Color backgroundColor;
const InfoCard({ const InfoCard({
Key? key, Key? key,
required this.title, required this.title,
required this.subtitle, required this.subtitle,
required this.value, required this.value,
required this.dataset,
required this.bordercolor, required this.bordercolor,
this.textcolor, this.textcolor,
required this.onTap, // Initialize in constructor required this.onTap,
required this.backgroundColor,
}) : super(key: key); }) : super(key: key);
@override @override
@ -489,52 +554,88 @@ class InfoCard extends StatelessWidget {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return Expanded( return GestureDetector(
child: GestureDetector( onTap: () {
onTap: onTap, // Use callback for handling clicks // Call handleInfoCardClick and pass the title and color
handleInfoCardClick(
context, dataset, bordercolor); // Pass 'title' to the function
},
child: Container( child: Container(
height: myheight / 9, height: myheight / 12,
width: mywidth / 4, width: mywidth / 4,
margin: const EdgeInsets.symmetric(horizontal: 8), margin: const EdgeInsets.symmetric(horizontal: 8),
// padding: const EdgeInsets.all(10),
padding: const EdgeInsets.only(bottom: 1, top: 1, left: 10, right: 10),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: bordercolor), border: Border.all(color: bordercolor),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Expanded( Flexible(
fit: FlexFit.loose,
child: FittedBox(
fit: BoxFit.contain, // Adjust text to fit within the bounds
child: Padding(
// padding: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 4, bottom: 0),
child: Text( child: Text(
title, title,
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 11,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w400,
color: Colors.black, // color: Colors.black,
color: Color(0xFF000000),
), ),
), ),
), ),
const SizedBox(height: 2), ),
),
const SizedBox(height: 0.5),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
children: [
Text( Text(
subtitle, subtitle,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 11,
color: Colors.grey, fontWeight: FontWeight.w400,
), color: Color(0xFF8E8E8E),
),
const SizedBox(height: 2),
Text(
value,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: textcolor ?? Colors.black,
), ),
), ),
], ],
), ),
), ),
), ),
const SizedBox(height: 1),
// Flexible(
// fit: FlexFit.loose,
// child: FittedBox(
// fit: BoxFit.scaleDown,
// child:
Text(
value,
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
color: textcolor ?? Colors.black,
),
),
// ),
// ),
],
),
),
); );
} }
} }

View File

@ -159,7 +159,7 @@ class _EditProfileState extends State<EditProfile> {
); );
print('userDetails: $userDetailsResponse'); print('userDetails: $userDetailsResponse');
setState(() { setState(() {
_usernameController.text = userDetailsResponse.data['username'] ?? ''; _usernameController.text = userDetailsResponse.data['uname'] ?? '';
_emailController.text = userDetailsResponse.data['email'] ?? ''; _emailController.text = userDetailsResponse.data['email'] ?? '';
_fullNameController.text = userDetailsResponse.data['full_name'] ?? ''; _fullNameController.text = userDetailsResponse.data['full_name'] ?? '';
_selectedCountry = userDetailsResponse.data['country_region'] ?? ''; _selectedCountry = userDetailsResponse.data['country_region'] ?? '';
@ -710,12 +710,15 @@ class _EditProfileState extends State<EditProfile> {
SizedBox(height: 10), SizedBox(height: 10),
Text.rich( Text.rich(
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.agree, text: AppLocalizations.of(context)!
.agree,
style: style:
TextStyle(color: Colors.black), TextStyle(color: Colors.black),
children: [ children: [
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.terms_conditions, text: AppLocalizations.of(
context)!
.terms_conditions,
style: TextStyle( style: TextStyle(
color: Colors.blue, color: Colors.blue,
decoration: decoration:
@ -728,12 +731,16 @@ class _EditProfileState extends State<EditProfile> {
}, },
), ),
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.t_and, text: AppLocalizations.of(
context)!
.t_and,
style: TextStyle( style: TextStyle(
color: Colors.black), color: Colors.black),
), ),
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.privacy_policy, text: AppLocalizations.of(
context)!
.privacy_policy,
style: TextStyle( style: TextStyle(
color: Colors.blue, color: Colors.blue,
decoration: decoration:
@ -746,7 +753,9 @@ class _EditProfileState extends State<EditProfile> {
}, },
), ),
TextSpan( TextSpan(
text: AppLocalizations.of(context)!.conditions, text: AppLocalizations.of(
context)!
.conditions,
style: TextStyle( style: TextStyle(
color: Colors.black), color: Colors.black),
), ),

View File

@ -467,7 +467,8 @@ class _FeedbackFormState extends State<FeedbackForm>
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 10), const SizedBox(height: 10),
Text(AppLocalizations.of(context)!.feedback_failed_msg, Text(AppLocalizations.of(context)!.feedback_failed_msg,
style: const TextStyle(fontSize: 16), textAlign: TextAlign.center), style: const TextStyle(fontSize: 16),
textAlign: TextAlign.center),
const SizedBox(height: 30), const SizedBox(height: 30),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {

View File

@ -1,9 +1,16 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class BaseScaffold extends StatefulWidget { import '../../components/indicators/locale_provider.dart';
import '../../components/my_toggle.dart';
class BaseScaffold extends ConsumerStatefulWidget {
final Widget body; final Widget body;
final Widget title; final Widget title;
final bool? showBackButton; final bool? showBackButton;
@ -26,7 +33,7 @@ class BaseScaffold extends StatefulWidget {
_BaseScaffoldState createState() => _BaseScaffoldState(); _BaseScaffoldState createState() => _BaseScaffoldState();
} }
class _BaseScaffoldState extends State<BaseScaffold> { class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
final _pb = PocketBase('https://pb.venbait.in'); final _pb = PocketBase('https://pb.venbait.in');
String _avatarUrl = ''; String _avatarUrl = '';
dynamic userId; dynamic userId;
@ -34,6 +41,13 @@ class _BaseScaffoldState extends State<BaseScaffold> {
String? userEmail; String? userEmail;
String? userAvatar; String? userAvatar;
String? role; String? role;
String? userNames;
String? userEmails;
String? userAvatars;
String? roles;
String? collectionIds;
String? collectionId;
@override @override
void initState() { void initState() {
@ -55,39 +69,125 @@ class _BaseScaffoldState extends State<BaseScaffold> {
userId = fetchedUserId; userId = fetchedUserId;
}); });
//print('NAVUser ID: $userId'); //print('NAVUser ID: $userId');
_fetchUserData(); _initializeUserData();
} else { } else {
print('No userId found'); print('No userId found');
// Handle the case where userId is not available // Handle the case where userId is not available
} }
} }
// Future<void> _fetchUserData() async {
// try {
// final adminAuth = await _pb.admins
// .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
// final adminToken = adminAuth.token;
// //print('adminToken- ${adminToken}');
// final userDetailsResponse = await _pb.collection('users').getOne(
// userId!,
// headers: {
// 'Authorization': 'Bearer $adminToken',
// },
// );
// print('NAVuserDetails: $userDetailsResponse');
//
// setState(() {
// userName = userDetailsResponse.data['uname'] ?? '';
// userEmail = userDetailsResponse.data['email'] ?? '';
// userAvatar = userDetailsResponse.data['avatar'] ?? '';
// role = userDetailsResponse.data['role'] ?? '';
// String recordId = userId;
// String collectionId =
// userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
//
// if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
// _avatarUrl =
// 'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar';
// } else {
// _avatarUrl = ''; // Reset to default or empty
// }
// });
// } catch (e) {
// print('Error fetching user details: $e');
// }
// }
Future<void> _initializeUserData() async {
print("Laoding 1");
final prefs = await SharedPreferences.getInstance();
// final userDataString = prefs.getString('userData');
if (prefs.containsKey('userData')) {
// print("Loading user data from local storage: $userData");
final String? userDataString = prefs.getString('userData');
if (userDataString != null) {
// Decode the JSON string into a Map
final Map<String, dynamic> userData = jsonDecode(userDataString);
// Access the userName field
setState(() {
userName = userData['userNames'];
userEmail = userData['userEmails'];
userAvatar = userData['userAvatars'];
role = userData['roles'];
String recordId = userId;
String collectionId = userData['collectionIds'];
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl =
'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar';
} else {
_avatarUrl = ''; // Reset to default or empty
}
});
} else {
print("No user data found in local storage.");
}
} else {
// Fetch data from server and save it to local storage
await _fetchUserData();
}
}
Future<void> _fetchUserData() async { Future<void> _fetchUserData() async {
try { try {
// print("Fetching _fetchUserData");
final adminAuth = await _pb.admins final adminAuth = await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final adminToken = adminAuth.token; final adminToken = adminAuth.token;
//print('adminToken- ${adminToken}');
final userDetailsResponse = await _pb.collection('users').getOne( final userDetailsResponse = await _pb.collection('users').getOne(
userId!, userId!,
headers: { headers: {
'Authorization': 'Bearer $adminToken', 'Authorization': 'Bearer $adminToken',
}, },
); );
print('NAVuserDetails: $userDetailsResponse'); // print('User details fetched from server: $userDetailsResponse');
final userData = {
'userNames': userDetailsResponse.data['uname'] ?? '',
'userEmails': userDetailsResponse.data['email'] ?? '',
'userAvatars': userDetailsResponse.data['avatar'] ?? '',
'roles': userDetailsResponse.data['role'] ?? '',
'collectionIds':
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_',
};
final prefs = await SharedPreferences.getInstance();
await prefs.setString('userData', jsonEncode(userData));
setState(() { setState(() {
userName = userDetailsResponse.data['uname'] ?? ''; userNames = userData['userNames'];
userEmail = userDetailsResponse.data['email'] ?? ''; userEmails = userData['userEmails'];
userAvatar = userDetailsResponse.data['avatar'] ?? ''; userAvatars = userData['userAvatars'];
role = userDetailsResponse.data['role'] ?? ''; roles = userData['roles'];
String recordId = userId; String recordId = userId;
String collectionId = collectionIds = userData['collectionIds'];
userDetailsResponse.data['collectionId'] ?? '_pb_users_auth_';
if (userAvatar!.isNotEmpty && recordId.isNotEmpty) { if (userAvatars!.isNotEmpty && recordId.isNotEmpty) {
_avatarUrl = _avatarUrl =
'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar'; 'https://pb.venbait.in/api/files/$collectionIds/$recordId/$userAvatars';
} else { } else {
_avatarUrl = ''; // Reset to default or empty _avatarUrl = ''; // Reset to default or empty
} }
@ -97,8 +197,16 @@ class _BaseScaffoldState extends State<BaseScaffold> {
} }
} }
Future<void> logout() async {
final prefs = await SharedPreferences.getInstance();
prefs.clear();
context.go('/');
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final locale = ref.watch(localeProvider);
final localeNotifier = ref.read(localeProvider.notifier);
String currentRoute = GoRouterState.of(context).matchedLocation; String currentRoute = GoRouterState.of(context).matchedLocation;
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
@ -109,10 +217,18 @@ class _BaseScaffoldState extends State<BaseScaffold> {
backgroundColor: widget.appbarColor, backgroundColor: widget.appbarColor,
actions: widget.actions ?? actions: widget.actions ??
[ [
IconButton( // IconButton(
onPressed: () {}, // onPressed: () {},
icon: const Icon(Icons.toggle_off_outlined), // icon: const Icon(Icons.toggle_off_outlined),
), // ),
MyToggle(isOn: locale?.languageCode == 'en',
knobTextWhenOn: 'ع',
knobTextWhenOff: 'EN',
pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300,
onTap: (){
ref.read(localeProvider.notifier).toggleLocale();
},),
], ],
leading: Stack( leading: Stack(
children: [ children: [
@ -216,7 +332,8 @@ class _BaseScaffoldState extends State<BaseScaffold> {
if (role == 'admin') if (role == 'admin')
ListTile( ListTile(
leading: Icon(Icons.manage_accounts), leading: Icon(Icons.manage_accounts),
title: const Text('Manage User'), // title: Text('Manage User'),
title: Text(AppLocalizations.of(context)!.manage_user,),
onTap: () => context.go('/manageuser'), onTap: () => context.go('/manageuser'),
), ),
ListTile( ListTile(
@ -227,7 +344,7 @@ class _BaseScaffoldState extends State<BaseScaffold> {
ListTile( ListTile(
leading: Icon(Icons.logout), leading: Icon(Icons.logout),
title: const Text('Logout'), title: const Text('Logout'),
onTap: () => context.go('/'), onTap: () => logout(),
), ),
], ],
), ),
@ -239,19 +356,23 @@ class _BaseScaffoldState extends State<BaseScaffold> {
items: [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.home), icon: Icon(Icons.home),
label: 'Home', // label: 'Home',
label: AppLocalizations.of(context)!.nav_home,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.map), icon: Icon(Icons.map),
label: 'UAE Numbers', // label: 'UAE Numbers'
label: AppLocalizations.of(context)!.nav_uae,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.bar_chart), icon: Icon(Icons.bar_chart),
label: 'Competitiveness', // label: 'Competitiveness',
label: AppLocalizations.of(context)!.nav_competitiveness,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.public), icon: Icon(Icons.public),
label: 'Country Profile', // label: 'Country Profile',
label: AppLocalizations.of(context)!.country_profile,
), ),
], ],
selectedItemColor: Colors.black, selectedItemColor: Colors.black,