#10 Ranking

Đã hợp nhất
iwa-13 đã nhập 6 commit từ iwa-13/ranking vào [3]s 3 năm trước cách đây

+ 2 - 1
app/android/app/build.gradle

@@ -45,7 +45,8 @@ android {
         // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
         applicationId "com.example.physigo"
         minSdkVersion 23
-        targetSdkVersion flutter.targetSdkVersion
+        multiDexEnabled true
+        targetSdkVersion 31
         versionCode flutterVersionCode.toInteger()
         versionName flutterVersionName
     }

+ 46 - 0
app/android/app/google-services.json

@@ -0,0 +1,46 @@
+{
+  "project_info": {
+    "project_number": "33414107403",
+    "project_id": "physigo",
+    "storage_bucket": "physigo.appspot.com"
+  },
+  "client": [
+    {
+      "client_info": {
+        "mobilesdk_app_id": "1:33414107403:android:aaf9d5af5ed2a103a1920e",
+        "android_client_info": {
+          "package_name": "com.example.physigo"
+        }
+      },
+      "oauth_client": [
+        {
+          "client_id": "33414107403-f05g2s2bhagi9kdqqbfc4aac98t7s9f2.apps.googleusercontent.com",
+          "client_type": 3
+        }
+      ],
+      "api_key": [
+        {
+          "current_key": "AIzaSyBUb8raBFHQA_AwR5cUrdCT6TkoWjj_jO8"
+        }
+      ],
+      "services": {
+        "appinvite_service": {
+          "other_platform_oauth_client": [
+            {
+              "client_id": "33414107403-f05g2s2bhagi9kdqqbfc4aac98t7s9f2.apps.googleusercontent.com",
+              "client_type": 3
+            },
+            {
+              "client_id": "33414107403-7e3vb8825iemlec2geietj4b00ldhbbj.apps.googleusercontent.com",
+              "client_type": 2,
+              "ios_info": {
+                "bundle_id": "com.example.physigo"
+              }
+            }
+          ]
+        }
+      }
+    }
+  ],
+  "configuration_version": "1"
+}

+ 23 - 13
app/lib/Services/AuthService.dart

@@ -1,3 +1,4 @@
+import 'package:cloud_firestore/cloud_firestore.dart';
 import 'package:firebase_auth/firebase_auth.dart';
 import 'package:physigo/Services/DatabaseManager.dart';
 
@@ -5,33 +6,42 @@ class AuthenticationServices {
   final FirebaseAuth _auth = FirebaseAuth.instance;
 
   //Register a user
-  Future createNewUser(String address, bool anonymous, String birth,
-      String name, String email, String password, String phone, String sharedID,
-      String surname) async {
+  Future createNewUser(String address, bool anonymous, String birth, String name, String email, String password,
+      String phone, String sharedID, String surname) async {
     try {
-      UserCredential result = await _auth.createUserWithEmailAndPassword(
-          email: email, password: password);
+      UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
       User? user = result.user;
-      await DatabaseManager().createUserData(
-          address, anonymous, birth, DateTime.now(), DateTime.now(), email,
-          name, phone, sharedID, surname, 0, DateTime.now(), 'null', user!.uid);
+      await DatabaseManager("total_points").createUserData(address, anonymous, birth, DateTime.now(), DateTime.now(),
+          email, name, phone, sharedID, surname, 0, DateTime.now(), 'null', user!.uid);
 
       return user;
     } catch (e) {
-      print('catch auto');
       print(e.toString());
-      print('catch auto2');
     }
   }
 
   //LogIn with user
   Future loginUser(String email, String password) async {
     try {
-      UserCredential result = await _auth.signInWithEmailAndPassword(
-          email: email, password: password);
+      UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
       return result.user;
-    } catch(e) {
+    } catch (e) {
       print(e.toString());
     }
   }
+
+  Future<dynamic> getCurrentUser() async {
+    User? user = _auth.currentUser;
+    var querySnapshot =
+        await FirebaseFirestore.instance.collection('profileInfo').where('mail', isEqualTo: user?.email).get();
+    return querySnapshot;
+  }
+
+  Stream<int> getPlace(dynamic user) async* {
+    var users = await FirebaseFirestore.instance
+        .collection('Users')
+        .where("total_points", isGreaterThan: user["total_points"])
+        .get();
+    yield users.docs.length + 1;
+  }
 }

+ 5 - 8
app/lib/Services/DatabaseManager.dart

@@ -1,10 +1,14 @@
 //import 'package:cloud_firestore/cloud_firestore.dart';
 import 'package:cloud_firestore/cloud_firestore.dart';
-import 'package:flutter/cupertino.dart';
 
 class DatabaseManager {
+  late final String points;
   final CollectionReference profileList =
   FirebaseFirestore.instance.collection('profileInfo');
+  CollectionReference usersList =
+  FirebaseFirestore.instance.collection("Users");
+
+  DatabaseManager(this.points);
 
   Future<void> createUserData(String address,
       bool anonymous,
@@ -37,11 +41,4 @@ class DatabaseManager {
       'weekly_place': weeklyplace,
     });
   }
-
-  Future getusersList(String id) async {
-  }
 }
-//  FirebaseFirestore.instance.collection('profileInfo').doc(arguments['id'])
-//         .get().then((DocumentSnapshot) =>
-//         print('____'+DocumentSnapshot.data().toString())
-//     );

+ 0 - 1
app/lib/SignupPage.dart

@@ -1,7 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:physigo/Services/AuthService.dart';
 
-import 'Services/DatabaseManager.dart';
 
 //Fields..
 TextEditingController _name = TextEditingController();

+ 69 - 0
app/lib/currentUser.dart

@@ -0,0 +1,69 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'Services/AuthService.dart';
+
+class CurrentUser extends StatefulWidget {
+  const CurrentUser( {
+    required this.name, Key? key}):super(key: key);
+  final String name;
+  @override
+  State<CurrentUser> createState() => _CurrentUserState();
+}
+
+class _CurrentUserState extends State<CurrentUser> {
+  final AuthenticationServices _auth = AuthenticationServices();
+  late dynamic user = _auth.getCurrentUser();
+
+  @override
+  Widget build(BuildContext context) {
+    return FutureBuilder<dynamic>(
+      future: user,
+      builder: (context, snapshot) {
+        if(snapshot.connectionState == ConnectionState.waiting){
+          return const Text('Wait a moment');
+        }
+        else if(snapshot.connectionState == ConnectionState.done) {
+          dynamic user2 = snapshot.data.docs[0];
+          // DatabaseManager manager = DatabaseManager(widget.name);
+           Stream<int> place = _auth.getPlace(user2);
+          return Row(
+            children: [
+              SizedBox(
+                height: 100,
+                width: 55,
+              ),
+              SizedBox(
+                height: 100,
+                width: 50,
+              child: StreamBuilder(
+                stream: place,
+                builder: (context, snapshot){
+                  return Text(
+                      "${snapshot.data}");
+                },
+              ),
+              ),
+              SizedBox(
+                height: 100,
+                width: 135,
+                child: Text(user2["shared_id"]),
+              ),
+              SizedBox(
+                height: 100,
+                width: 60,
+                child: Text(user2["name"]),
+              ),
+              SizedBox(
+                height: 100,
+                width: 50,
+                child: Text("${user2[widget.name]}"),
+              ),
+            ],
+          );
+        }
+        return const Text('Something went wrong');
+      },
+    );
+  }
+}

+ 3 - 6
app/lib/main.dart

@@ -5,6 +5,7 @@ import 'firebase_options.dart';
 import 'push_notifications_initializer.dart';
 import 'package:physigo/logIn.dart';
 import 'package:physigo/profilePage.dart';
+import 'package:physigo/widgets/rankingNavigation.dart';
 import 'package:physigo/SignupPage.dart';
 import 'package:physigo/mainPage.dart';
 import 'package:physigo/welcomeScreen.dart';
@@ -30,16 +31,12 @@ class PhysiGo extends StatelessWidget {
       ),
       initialRoute: '/',
       routes: {
-        '/': (context) => MyHomePage(
-              title: '',
-            ),
+        '/': (context) => MyHomePage(title: ''),
         '/register': (context) => SignupPage(),
         //'/register2': (context) => RegisterScreen2(title: ''),
         //'/register3': (context) => RegisterScreen3(title: ''),
         '/login': (context) => LogIn(title: ''),
-        '/profilePage': (context) => ProfilePage(
-              title: '',
-            ),
+        '/profilePage': (context) => ProfilePage(title: ''),
         '/mainPage': (context) => MainPage()
       },
       //home: const MyHomePage(title: 'Flutter Demo Home Page'),

+ 128 - 0
app/lib/widgets/datatable.dart

@@ -0,0 +1,128 @@
+import 'dart:async';
+
+import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:flutter/material.dart';
+
+class MyDataTable extends StatefulWidget {
+
+  const MyDataTable( {
+    required this.name, Key? key}):super(key: key);
+  final String name;
+  @override
+  State<MyDataTable> createState() => _MyDataTableState();
+}
+
+class _MyDataTableState extends State<MyDataTable> {
+  CollectionReference usersList =
+  FirebaseFirestore.instance.collection("Users");
+  @override
+  Widget build(BuildContext context) {
+    Future<List> userList = getUsersList();
+
+    return  Container(
+      height: 450,
+      alignment: const Alignment(0,-1),
+      child: Scrollbar(
+        child:SingleChildScrollView(
+            child: FutureBuilder<dynamic>(
+              future: userList,
+              builder: (context, snapshot) {
+                if(snapshot.connectionState == ConnectionState.waiting){
+                  return const Text('Wait a moment');
+                }
+                if(snapshot.connectionState == ConnectionState.done) {
+                  return buildDataTable(snapshot.data, widget.name);
+                }
+                if(snapshot.hasError) {
+                  return const Text('Something went wrong');
+                }
+                return const Text("  ");
+                },
+          ),
+        ),
+      ),
+      );
+  }
+  @override
+  void initState() {
+    super.initState();
+  }
+
+
+  Future<List> getUsersList() async {
+    var querySnapshot = await usersList.orderBy(widget.name, descending: true).get();
+      return querySnapshot.docs;
+  }
+  }
+
+  Widget buildDataTable(snapshotData, String name) {
+    final columns = ['Place', 'ID', 'Name', 'points'];
+
+    return DataTable(
+      columnSpacing: 10.0,
+      columns: getColumns(columns),
+      rows: getRows(snapshotData, name),
+    );
+  }
+  List<DataColumn> getColumns(List<String> columns) {
+    return columns.map((String column) {
+      return DataColumn(
+
+        label: Text(column),
+      );
+    }).toList();
+  }
+
+  List<DataRow> getRows(dynamic snapshotData, String name) {
+    List<DataRow> rows = [];
+    int length = snapshotData.length;
+    for(int i = 0; i < length; i++){
+      dynamic user = snapshotData[i];
+      bool anonymous = user["anonymous"];
+      if (anonymous) {
+        rows.add(
+            DataRow(
+                cells: [
+                  DataCell(
+                      Text("${i+1}")
+                  ),
+                  const DataCell(
+                    Text("anonym"),
+                  ),
+                  const DataCell(
+                    Text("name"),
+                  ),
+                  DataCell(
+                    Text("${user[name]}"),
+                  ),
+                ]
+            )
+        );
+      }
+      else {
+        rows.add(
+            DataRow(
+                cells: [
+                  DataCell(
+                      Text("${i+1}")
+                  ),
+                  DataCell(
+                    Text("${user["shared_id"]}"),
+                  ),
+                  DataCell(
+                      Text(user["name"]),
+                  ),
+                  DataCell(
+                    Text("${user[name]}"),
+                  ),
+                ]
+            )
+        );
+      }
+    }
+    return rows;
+  }
+
+
+
+

+ 77 - 0
app/lib/widgets/rankingNavigation.dart

@@ -0,0 +1,77 @@
+import 'package:flutter/cupertino.dart';
+import 'package:flutter/material.dart';
+import '../currentUser.dart';
+import 'datatable.dart';
+
+
+class RankingNavigation extends StatefulWidget {
+  const RankingNavigation({Key? key}) : super(key: key);
+
+  @override
+  State<RankingNavigation> createState() => _RankingNavigationState();
+}
+
+class _RankingNavigationState extends State<RankingNavigation> {
+  int _selectedIndex = 0;
+  static const List<Widget> _widgetOptions = <Widget>[
+    MyDataTable(name: 'daily_points'),
+    MyDataTable(name: 'weekly_points'),
+    MyDataTable(name: 'total_points'),
+    ];
+  static const List<Widget> _widgetOptions2 = <Widget>[
+    CurrentUser(name: 'daily_points'),
+    CurrentUser(name: 'weekly_points'),
+    CurrentUser(name: 'total_points'),
+  ];
+
+  void _onItemTapped(int index) {
+    setState(() {
+      _selectedIndex = index;
+    });
+  }
+
+
+  @override
+  Widget build(BuildContext context) {
+
+    return Scaffold(
+      appBar: AppBar(
+        toolbarHeight: 50,
+        title: const Text('Ranking'),
+      ),
+      body: SafeArea(
+        child: Column(
+        children: [
+          SizedBox(
+            height: 350,
+          child:_widgetOptions.elementAt(_selectedIndex),
+        ),
+        Container(
+          child:_widgetOptions2.elementAt(_selectedIndex),
+        )
+      ],
+      )
+      ),
+
+      bottomNavigationBar: BottomNavigationBar(
+        items: const <BottomNavigationBarItem>[
+          BottomNavigationBarItem(
+            icon: Icon(Icons.event),
+            label: 'Daily',
+          ),
+          BottomNavigationBarItem(
+            icon: Icon(Icons.event),
+            label: 'Weekly',
+          ),
+          BottomNavigationBarItem(
+            icon: Icon(Icons.event),
+            label: 'Monthly',
+          ),
+        ],
+        currentIndex: _selectedIndex,
+        selectedItemColor: Colors.amber[800],
+        onTap: _onItemTapped,
+      ),
+    );
+  }
+}

+ 14 - 0
app/pubspec.lock

@@ -324,6 +324,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.0"
+  nested:
+    dependency: transitive
+    description:
+      name: nested
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
   path:
     dependency: transitive
     description:
@@ -394,6 +401,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.0.0"
+  provider:
+    dependency: "direct main"
+    description:
+      name: provider
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "6.0.3"
   quiver:
     dependency: transitive
     description:

+ 1 - 0
app/pubspec.yaml

@@ -48,6 +48,7 @@ dependencies:
   firebase_auth: ^3.3.17
   flutter_activity_recognition: ^1.3.0
   geolocator: ^8.2.1
+  provider: ^6.0.1
 
 dev_dependencies:
   flutter_test: