notification and chart changes done
This commit is contained in:
parent
f4186a876b
commit
4917749f65
@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = "17"
|
||||
flutterVersionCode = "20"
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = "1.0.16"
|
||||
flutterVersionName = "1.0.19"
|
||||
}
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||
|
||||
@ -15,6 +15,11 @@
|
||||
"exit": "خروج",
|
||||
|
||||
"bookmark_title": "إشارة مرجعية",
|
||||
"failed_To_Remove": "فشلت الإزالة",
|
||||
"removed_from_Bookmark": "تمت الإزالة من الإشارة المرجعية",
|
||||
"added_to_Bookmark":"تمت إضافته إلى الإشارة المرجعية",
|
||||
"guide_title": "نموذج الملاحظات",
|
||||
"notification": "إشعار",
|
||||
|
||||
"guide_title": "نموذج الملاحظات",
|
||||
|
||||
|
||||
@ -16,6 +16,10 @@
|
||||
"cancel": "Cancel",
|
||||
"exit": "Exit",
|
||||
"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_details": "Please enter your details",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -231,6 +231,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder<int?>(
|
||||
@ -307,6 +316,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
AspectRatio(
|
||||
aspectRatio: 1.5,
|
||||
@ -522,6 +540,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -624,6 +651,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Expanded(
|
||||
@ -631,8 +667,8 @@ class ChartWidget extends StatelessWidget {
|
||||
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
||||
padding: const EdgeInsets.only(right: 40),
|
||||
child: SizedBox(
|
||||
width: (uniqueXValues.length * 80) +
|
||||
80, // Adjust width dynamically
|
||||
width: (uniqueXValues.length * 50) +
|
||||
50, // Adjust width dynamically
|
||||
child: LineChart(LineChartData(
|
||||
lineTouchData: lineTouchData1(),
|
||||
gridData: gridData(),
|
||||
@ -735,6 +771,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -742,8 +787,8 @@ class ChartWidget extends StatelessWidget {
|
||||
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
|
||||
padding: const EdgeInsets.only(right: 40),
|
||||
child: SizedBox(
|
||||
width: (uniqueXValues.length * 80) +
|
||||
80, // Adjust width dynamically
|
||||
width: (uniqueXValues.length * 50) +
|
||||
50, // Adjust width dynamically
|
||||
child: LineChart(
|
||||
LineChartData(
|
||||
lineTouchData: lineTouchData1(),
|
||||
@ -753,6 +798,7 @@ class ChartWidget extends StatelessWidget {
|
||||
lineBarsData: lineBars,
|
||||
minX: 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,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -888,6 +943,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -1019,6 +1083,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -1224,6 +1297,15 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
chartData['chart_sub_heading'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
// Chart
|
||||
Expanded(
|
||||
@ -1790,12 +1872,15 @@ class ChartWidget extends StatelessWidget {
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
interval: 1, // Ensure each year is shown only once
|
||||
interval: 10, // Ensure each year is shown only once
|
||||
getTitlesWidget: (value, meta) {
|
||||
if (xValues.contains(value)) {
|
||||
return Text(
|
||||
value.toInt().toString(),
|
||||
style: TextStyle(color: Colors.black, fontSize: 12),
|
||||
return Transform.rotate(
|
||||
angle: -0.5, // Slight rotation to improve readability
|
||||
child: Text(
|
||||
value.toInt().toString(),
|
||||
style: TextStyle(color: Colors.black, fontSize: 12),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SizedBox.shrink(); // Hide non-relevant labels
|
||||
|
||||
@ -21,6 +21,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
int _sortColumnIndex = 0;
|
||||
bool _isAscending = true;
|
||||
List<User> filteredUserData = [];
|
||||
bool isLoading = true;
|
||||
|
||||
// final List<String> statusOptions = ['Approved', 'Denied', 'Pending'];
|
||||
|
||||
@ -52,9 +53,9 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
);
|
||||
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
userData = result.map((record) {
|
||||
final createdDate =
|
||||
DateTime.parse(record.created); // Parse the created date
|
||||
final createdDate = DateTime.parse(record.created).add(Duration(hours: 4));// Parse the created date
|
||||
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
|
||||
return User(
|
||||
id: record.id, // Correctly passing the ID
|
||||
@ -64,7 +65,17 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
status: record.getStringValue('status'),
|
||||
);
|
||||
}).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);
|
||||
|
||||
isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
print('Error fetching unverified users: $e');
|
||||
@ -337,6 +348,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
image: ExactAssetImage(MiscIconAssetPath.search),
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: Color(0xFFAA8E83)
|
||||
),
|
||||
|
||||
|
||||
@ -348,10 +360,13 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(vertical: 8.0, horizontal: 18.0),
|
||||
),
|
||||
onChanged: filterUsers,
|
||||
),),
|
||||
),
|
||||
SizedBox(height: myheight / 40),
|
||||
filteredUserData.isEmpty
|
||||
isLoading
|
||||
? Center(child: CircularProgressIndicator())
|
||||
:filteredUserData.isEmpty
|
||||
? Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
import '../../custom_drawer_routes.dart';
|
||||
|
||||
class NotificationPage extends StatefulWidget {
|
||||
@ -9,23 +11,63 @@ class NotificationPage extends StatefulWidget {
|
||||
|
||||
class _NotificationPageState extends State<NotificationPage> {
|
||||
// Example notification data
|
||||
List<Map<String, dynamic>> notifications = [
|
||||
{"title": "Social datasets are updated", "date": "04 Nov 2024 08:25 PM", "category": "Social"},
|
||||
{"title": "New feature updated", "date": "04 Nov 2024 08:25 PM", "category": "App updates"},
|
||||
];
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
List<Map<String, dynamic>> notifications = [];
|
||||
|
||||
// Current selected tab index
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
// 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
|
||||
Widget build(BuildContext context) {
|
||||
// Filter notifications based on the selected tab
|
||||
List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0
|
||||
? notifications
|
||||
: notifications.where((notification) => notification["category"] == tabs[selectedTabIndex]).toList();
|
||||
: notifications
|
||||
.where((notification) =>
|
||||
notification["category"] == tabs[selectedTabIndex])
|
||||
.toList();
|
||||
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
@ -49,49 +91,51 @@ class _NotificationPageState extends State<NotificationPage> {
|
||||
Expanded(
|
||||
child: selectedTabIndex == 1
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/backgrounds/Notification/Update_notific.png',
|
||||
height: 200,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
filteredNotifications.isNotEmpty
|
||||
? filteredNotifications[0]['title']
|
||||
: 'No updates available.',
|
||||
style: TextStyle(fontSize: 16, color: Colors.grey),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/backgrounds/Notification/Update_notific.png',
|
||||
height: 200,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
filteredNotifications.isNotEmpty
|
||||
? filteredNotifications[0]['title']
|
||||
: 'No updates available.',
|
||||
style: TextStyle(fontSize: 16, color: Colors.grey),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: filteredNotifications.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.info_outline, size: 100, color: Colors.grey[400]),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
'No notifications available.',
|
||||
style: TextStyle(fontSize: 16, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: filteredNotifications.length,
|
||||
itemBuilder: (context, index) {
|
||||
final notification = filteredNotifications[index];
|
||||
return NotificationTile(
|
||||
title: notification["title"]!,
|
||||
date: notification["date"]!,
|
||||
category: notification["category"]!,
|
||||
);
|
||||
},
|
||||
),
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.info_outline,
|
||||
size: 100, color: Colors.grey[400]),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
'No notifications available.',
|
||||
style:
|
||||
TextStyle(fontSize: 16, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: filteredNotifications.length,
|
||||
itemBuilder: (context, index) {
|
||||
final notification = filteredNotifications[index];
|
||||
return NotificationTile(
|
||||
title: notification['title'] ?? 'No Title',
|
||||
date: formatDate(notification['created'] ?? ''),
|
||||
category: notification['category'] ?? 'Unknown',
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -128,8 +172,11 @@ class TabBarHeader extends StatelessWidget {
|
||||
TextButton(
|
||||
onPressed: () => onTabSelected(index),
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.resolveWith((states) {
|
||||
return selectedIndex == index ? Color(0xFF985400) : Colors.grey[700];
|
||||
foregroundColor:
|
||||
MaterialStateProperty.resolveWith((states) {
|
||||
return selectedIndex == index
|
||||
? Color(0xFF985400)
|
||||
: Colors.grey[700];
|
||||
}),
|
||||
),
|
||||
child: Text(text),
|
||||
@ -169,7 +216,8 @@ class NotificationTile extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
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)),
|
||||
subtitle: Text(date),
|
||||
);
|
||||
|
||||
@ -42,11 +42,11 @@ class BaseScaffold extends ConsumerStatefulWidget {
|
||||
});
|
||||
final Widget body;
|
||||
final Widget title;
|
||||
final Widget? navBackArrow;
|
||||
final Widget? navBackArrow;
|
||||
final Color? dividerColor;
|
||||
final bool showDivider;
|
||||
final bool showBackButton;
|
||||
final bool colorChange;
|
||||
final bool colorChange;
|
||||
final bool? mycenterTitle;
|
||||
final List<Widget>? actions;
|
||||
final Color? bottomColor;
|
||||
@ -640,7 +640,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
title: Padding(
|
||||
title: Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
@ -698,9 +698,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
),
|
||||
],
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(top: 7.0,left: 4),
|
||||
padding: const EdgeInsets.only(top: 7.0, left: 4),
|
||||
child: Row(
|
||||
mainAxisSize:MainAxisSize.min,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (widget.showBackButton == true)
|
||||
SizedBox(
|
||||
@ -721,7 +721,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(width: 7,),
|
||||
SizedBox(
|
||||
width: 7,
|
||||
),
|
||||
Builder(
|
||||
builder: (BuildContext context) {
|
||||
return SizedBox(
|
||||
@ -743,8 +745,6 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
),
|
||||
drawer: Drawer(
|
||||
backgroundColor: Colors.white,
|
||||
@ -824,21 +824,22 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
if (userId != 'guest')
|
||||
ListTile(
|
||||
leading: Icon(Icons.notifications_none),
|
||||
title: const Text('Notification'),
|
||||
title: Text(AppLocalizations.of(context)!.notification),
|
||||
onTap: () => _navigateTo(context, '/notification'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.message_outlined),
|
||||
// leading: Image.asset(
|
||||
// DrawerAssetIconPath.feedback,
|
||||
// color: Colors.black,
|
||||
// width: 20,
|
||||
// height: 20,
|
||||
// ),
|
||||
// title: const Text('Feedback'),
|
||||
title: Text(AppLocalizations.of(context)!.feedback_title),
|
||||
onTap: () => _navigateTo(context, '/feedback', extra: userName),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.message_outlined),
|
||||
// leading: Image.asset(
|
||||
// DrawerAssetIconPath.feedback,
|
||||
// color: Colors.black,
|
||||
// width: 20,
|
||||
// height: 20,
|
||||
// ),
|
||||
// title: const Text('Feedback'),
|
||||
title: Text(AppLocalizations.of(context)!.feedback_title),
|
||||
onTap: () =>
|
||||
_navigateTo(context, '/feedback', extra: userName),
|
||||
),
|
||||
if (role == 'admin')
|
||||
ListTile(
|
||||
leading: Icon(Icons.manage_accounts_outlined),
|
||||
@ -1012,6 +1013,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
body: widget.body,
|
||||
);
|
||||
}
|
||||
|
||||
//drawer close code
|
||||
void _navigateTo(BuildContext context, String route, {Object? extra}) {
|
||||
Navigator.pop(context); // Close the drawer
|
||||
@ -1049,4 +1051,4 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
name: uae_stat
|
||||
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
||||
publish_to: "none"
|
||||
version: 1.0.16+17
|
||||
version: 1.0.19+20
|
||||
|
||||
environment:
|
||||
sdk: ">=3.2.3 <4.0.0"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user