notification and chart changes done

This commit is contained in:
venbaittech 2025-02-15 18:31:52 +05:30
parent f4186a876b
commit 4917749f65
9 changed files with 931 additions and 724 deletions

View File

@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
def flutterVersionCode = localProperties.getProperty("flutter.versionCode") def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = "17" flutterVersionCode = "20"
} }
def flutterVersionName = localProperties.getProperty("flutter.versionName") def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) { if (flutterVersionName == null) {
flutterVersionName = "1.0.16" flutterVersionName = "1.0.19"
} }
def keystorePropertiesFile = rootProject.file("key.properties") def keystorePropertiesFile = rootProject.file("key.properties")

View File

@ -15,6 +15,11 @@
"exit": "خروج", "exit": "خروج",
"bookmark_title": "إشارة مرجعية", "bookmark_title": "إشارة مرجعية",
"failed_To_Remove": "فشلت الإزالة",
"removed_from_Bookmark": "تمت الإزالة من الإشارة المرجعية",
"added_to_Bookmark":"تمت إضافته إلى الإشارة المرجعية",
"guide_title": "نموذج الملاحظات",
"notification": "إشعار",
"guide_title": "نموذج الملاحظات", "guide_title": "نموذج الملاحظات",

View File

@ -16,6 +16,10 @@
"cancel": "Cancel", "cancel": "Cancel",
"exit": "Exit", "exit": "Exit",
"bookmark_title": "Bookmark", "bookmark_title": "Bookmark",
"failed_To_Remove": "Failed to Remove",
"removed_from_Bookmark": "Removed from Bookmark",
"added_to_Bookmark": "Added to Bookmark.",
"notification": "Notification",
"register_title": "Register", "register_title": "Register",
"register_details": "Please enter your details", "register_details": "Please enter your details",

File diff suppressed because it is too large Load Diff

View File

@ -231,6 +231,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 20), SizedBox(height: 20),
Expanded( Expanded(
child: ValueListenableBuilder<int?>( child: ValueListenableBuilder<int?>(
@ -307,6 +316,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
AspectRatio( AspectRatio(
aspectRatio: 1.5, aspectRatio: 1.5,
@ -522,6 +540,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -624,6 +651,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
Expanded( Expanded(
@ -631,8 +667,8 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40), padding: const EdgeInsets.only(right: 40),
child: SizedBox( child: SizedBox(
width: (uniqueXValues.length * 80) + width: (uniqueXValues.length * 50) +
80, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart(LineChartData( child: LineChart(LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
gridData: gridData(), gridData: gridData(),
@ -735,6 +771,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -742,8 +787,8 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40), padding: const EdgeInsets.only(right: 40),
child: SizedBox( child: SizedBox(
width: (uniqueXValues.length * 80) + width: (uniqueXValues.length * 50) +
80, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart( child: LineChart(
LineChartData( LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
@ -753,6 +798,7 @@ class ChartWidget extends StatelessWidget {
lineBarsData: lineBars, lineBarsData: lineBars,
minX: uniqueXValues.reduce((a, b) => a < b ? a : b), minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
minY: 0,
), ),
), ),
), ),
@ -781,6 +827,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -888,6 +943,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -1019,6 +1083,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -1224,6 +1297,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -1790,12 +1872,15 @@ class ChartWidget extends StatelessWidget {
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
interval: 1, // Ensure each year is shown only once interval: 10, // Ensure each year is shown only once
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
if (xValues.contains(value)) { if (xValues.contains(value)) {
return Text( return Transform.rotate(
value.toInt().toString(), angle: -0.5, // Slight rotation to improve readability
style: TextStyle(color: Colors.black, fontSize: 12), child: Text(
value.toInt().toString(),
style: TextStyle(color: Colors.black, fontSize: 12),
),
); );
} else { } else {
return SizedBox.shrink(); // Hide non-relevant labels return SizedBox.shrink(); // Hide non-relevant labels

View File

@ -21,6 +21,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
int _sortColumnIndex = 0; int _sortColumnIndex = 0;
bool _isAscending = true; bool _isAscending = true;
List<User> filteredUserData = []; List<User> filteredUserData = [];
bool isLoading = true;
// final List<String> statusOptions = ['Approved', 'Denied', 'Pending']; // final List<String> statusOptions = ['Approved', 'Denied', 'Pending'];
@ -52,9 +53,9 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
); );
setState(() { setState(() {
isLoading = true;
userData = result.map((record) { userData = result.map((record) {
final createdDate = final createdDate = DateTime.parse(record.created).add(Duration(hours: 4));// Parse the created date
DateTime.parse(record.created); // Parse the created date
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate); final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
return User( return User(
id: record.id, // Correctly passing the ID id: record.id, // Correctly passing the ID
@ -64,7 +65,17 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
status: record.getStringValue('status'), status: record.getStringValue('status'),
); );
}).toList(); }).toList();
userData.sort((a,b){
DateTime dateA= DateFormat('dd/MM/yyyy').parse(a.registrationDate);
DateTime dateB = DateFormat('dd/MM/yyyy').parse(b.registrationDate);
return dateB.compareTo(dateA);
});
filteredUserData = List.from(userData); filteredUserData = List.from(userData);
isLoading = false;
}); });
} catch (e) { } catch (e) {
print('Error fetching unverified users: $e'); print('Error fetching unverified users: $e');
@ -337,6 +348,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
image: ExactAssetImage(MiscIconAssetPath.search), image: ExactAssetImage(MiscIconAssetPath.search),
width: 24, width: 24,
height: 24, height: 24,
color: Color(0xFFAA8E83)
), ),
@ -348,10 +360,13 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
contentPadding: contentPadding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 18.0), EdgeInsets.symmetric(vertical: 8.0, horizontal: 18.0),
), ),
onChanged: filterUsers,
),), ),),
), ),
SizedBox(height: myheight / 40), SizedBox(height: myheight / 40),
filteredUserData.isEmpty isLoading
? Center(child: CircularProgressIndicator())
:filteredUserData.isEmpty
? Center( ? Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:pocketbase/pocketbase.dart';
import '../../custom_drawer_routes.dart'; import '../../custom_drawer_routes.dart';
class NotificationPage extends StatefulWidget { class NotificationPage extends StatefulWidget {
@ -9,23 +11,63 @@ class NotificationPage extends StatefulWidget {
class _NotificationPageState extends State<NotificationPage> { class _NotificationPageState extends State<NotificationPage> {
// Example notification data // Example notification data
List<Map<String, dynamic>> notifications = [ final _pb = PocketBase('https://pb.venbait.in');
{"title": "Social datasets are updated", "date": "04 Nov 2024 08:25 PM", "category": "Social"}, List<Map<String, dynamic>> notifications = [];
{"title": "New feature updated", "date": "04 Nov 2024 08:25 PM", "category": "App updates"},
];
// Current selected tab index // Current selected tab index
int selectedTabIndex = 0; int selectedTabIndex = 0;
// Tab categories // Tab categories
final List<String> tabs = ["All updates", "App updates", "Social", "Economy", "Environment", "Favourites"]; final List<String> tabs = [
"All updates",
"App updates",
"Social",
"Economy",
"Environment",
"Favourites"
];
String formatDate(String dateString) {
try {
DateTime dateTime =
DateTime.parse(dateString); // Convert API date to DateTime
return DateFormat('dd MMM yyyy hh:mm a')
.format(dateTime); // Format DateTime
} catch (e) {
return 'Invalid Date'; // Handle parsing errors
}
}
Future<void> fetchNotifications() async {
try {
await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final result = await _pb.collection('notification').getFullList();
setState(() {
notifications = result.map((record) => record.toJson()).toList();
});
} catch (e) {
print('Error fetching notifications: $e');
}
}
@override
void initState() {
super.initState();
fetchNotifications();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Filter notifications based on the selected tab // Filter notifications based on the selected tab
List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0 List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0
? notifications ? notifications
: notifications.where((notification) => notification["category"] == tabs[selectedTabIndex]).toList(); : notifications
.where((notification) =>
notification["category"] == tabs[selectedTabIndex])
.toList();
return PopScope( return PopScope(
canPop: false, canPop: false,
@ -49,49 +91,51 @@ class _NotificationPageState extends State<NotificationPage> {
Expanded( Expanded(
child: selectedTabIndex == 1 child: selectedTabIndex == 1
? Center( ? Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Image.asset( Image.asset(
'assets/backgrounds/Notification/Update_notific.png', 'assets/backgrounds/Notification/Update_notific.png',
height: 200, height: 200,
), ),
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
filteredNotifications.isNotEmpty filteredNotifications.isNotEmpty
? filteredNotifications[0]['title'] ? filteredNotifications[0]['title']
: 'No updates available.', : 'No updates available.',
style: TextStyle(fontSize: 16, color: Colors.grey), style: TextStyle(fontSize: 16, color: Colors.grey),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],
), ),
) )
: filteredNotifications.isEmpty : filteredNotifications.isEmpty
? Center( ? Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.info_outline, size: 100, color: Colors.grey[400]), Icon(Icons.info_outline,
SizedBox(height: 16), size: 100, color: Colors.grey[400]),
Text( SizedBox(height: 16),
'No notifications available.', Text(
style: TextStyle(fontSize: 16, color: Colors.grey), 'No notifications available.',
), style:
], TextStyle(fontSize: 16, color: Colors.grey),
), ),
) ],
: ListView.builder( ),
itemCount: filteredNotifications.length, )
itemBuilder: (context, index) { : ListView.builder(
final notification = filteredNotifications[index]; itemCount: filteredNotifications.length,
return NotificationTile( itemBuilder: (context, index) {
title: notification["title"]!, final notification = filteredNotifications[index];
date: notification["date"]!, return NotificationTile(
category: notification["category"]!, title: notification['title'] ?? 'No Title',
); date: formatDate(notification['created'] ?? ''),
}, category: notification['category'] ?? 'Unknown',
), );
},
),
), ),
], ],
), ),
@ -128,8 +172,11 @@ class TabBarHeader extends StatelessWidget {
TextButton( TextButton(
onPressed: () => onTabSelected(index), onPressed: () => onTabSelected(index),
style: ButtonStyle( style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith((states) { foregroundColor:
return selectedIndex == index ? Color(0xFF985400) : Colors.grey[700]; MaterialStateProperty.resolveWith((states) {
return selectedIndex == index
? Color(0xFF985400)
: Colors.grey[700];
}), }),
), ),
child: Text(text), child: Text(text),
@ -169,7 +216,8 @@ class NotificationTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: Icon(Icons.circle, size: 12, color: category == "Social" ? Colors.red : Colors.grey), leading: Icon(Icons.circle,
size: 12, color: category == "Social" ? Colors.red : Colors.grey),
title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)), title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text(date), subtitle: Text(date),
); );

View File

@ -42,11 +42,11 @@ class BaseScaffold extends ConsumerStatefulWidget {
}); });
final Widget body; final Widget body;
final Widget title; final Widget title;
final Widget? navBackArrow; final Widget? navBackArrow;
final Color? dividerColor; final Color? dividerColor;
final bool showDivider; final bool showDivider;
final bool showBackButton; final bool showBackButton;
final bool colorChange; final bool colorChange;
final bool? mycenterTitle; final bool? mycenterTitle;
final List<Widget>? actions; final List<Widget>? actions;
final Color? bottomColor; final Color? bottomColor;
@ -640,7 +640,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBar( appBar: AppBar(
title: Padding( title: Padding(
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
@ -698,9 +698,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
], ],
leading: Padding( leading: Padding(
padding: const EdgeInsets.only(top: 7.0,left: 4), padding: const EdgeInsets.only(top: 7.0, left: 4),
child: Row( child: Row(
mainAxisSize:MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (widget.showBackButton == true) if (widget.showBackButton == true)
SizedBox( SizedBox(
@ -721,7 +721,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
}, },
), ),
), ),
SizedBox(width: 7,), SizedBox(
width: 7,
),
Builder( Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
return SizedBox( return SizedBox(
@ -743,8 +745,6 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
], ],
), ),
), ),
), ),
drawer: Drawer( drawer: Drawer(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -824,21 +824,22 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
if (userId != 'guest') if (userId != 'guest')
ListTile( ListTile(
leading: Icon(Icons.notifications_none), leading: Icon(Icons.notifications_none),
title: const Text('Notification'), title: Text(AppLocalizations.of(context)!.notification),
onTap: () => _navigateTo(context, '/notification'), onTap: () => _navigateTo(context, '/notification'),
), ),
ListTile( ListTile(
leading: Icon(Icons.message_outlined), leading: Icon(Icons.message_outlined),
// leading: Image.asset( // leading: Image.asset(
// DrawerAssetIconPath.feedback, // DrawerAssetIconPath.feedback,
// color: Colors.black, // color: Colors.black,
// width: 20, // width: 20,
// height: 20, // height: 20,
// ), // ),
// title: const Text('Feedback'), // title: const Text('Feedback'),
title: Text(AppLocalizations.of(context)!.feedback_title), title: Text(AppLocalizations.of(context)!.feedback_title),
onTap: () => _navigateTo(context, '/feedback', extra: userName), onTap: () =>
), _navigateTo(context, '/feedback', extra: userName),
),
if (role == 'admin') if (role == 'admin')
ListTile( ListTile(
leading: Icon(Icons.manage_accounts_outlined), leading: Icon(Icons.manage_accounts_outlined),
@ -1012,6 +1013,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
body: widget.body, body: widget.body,
); );
} }
//drawer close code //drawer close code
void _navigateTo(BuildContext context, String route, {Object? extra}) { void _navigateTo(BuildContext context, String route, {Object? extra}) {
Navigator.pop(context); // Close the drawer Navigator.pop(context); // Close the drawer
@ -1049,4 +1051,4 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
break; break;
} }
} }
} }

View File

@ -1,7 +1,7 @@
name: uae_stat name: uae_stat
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
publish_to: "none" publish_to: "none"
version: 1.0.16+17 version: 1.0.19+20
environment: environment:
sdk: ">=3.2.3 <4.0.0" sdk: ">=3.2.3 <4.0.0"