Compare commits
43 Commits
feature/ad
...
main
Author | SHA1 | Date | |
---|---|---|---|
1c21f59420 | |||
7441af6f13 | |||
4f4b0b609c | |||
2e6814c33d | |||
909b321158 | |||
6641c7938c | |||
8904032265 | |||
9d35a59ba6 | |||
303447ff1e | |||
32532246eb | |||
452faf05d8 | |||
3a64f1ae36 | |||
afae3293c4 | |||
600bf8d2f4 | |||
ec7a286074 | |||
6c1c650fa1 | |||
7468c5f24c | |||
1bcc8372c6 | |||
510e366216 | |||
52580c6568 | |||
4f7c8f60d0 | |||
ce2a061bf0 | |||
04f4b7ce8e | |||
78ea5f0c10 | |||
395d3390cf | |||
daef20db66 | |||
9df499d198 | |||
e7afe8fddb | |||
5c2a58e484 | |||
e8bb2f6180 | |||
e4d8648fcc | |||
7f3240242d | |||
c936a02836 | |||
3352bab860 | |||
c31e275dae | |||
38e9908533 | |||
47c014cdda | |||
729e0ce1ca | |||
5c2fa27aa7 | |||
9846c614a1 | |||
d46f268c1b | |||
b0477c889c | |||
6fdb5cb2fe |
@ -6,6 +6,9 @@
|
|||||||
android:label="covas_mobile"
|
android:label="covas_mobile"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||||
|
android:value="ca-app-pub-4855855675386260~3438207239"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
flutter.compileSdkVersion=35
|
@ -47,5 +47,8 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string>Your location is needed for showing nearby events</string>
|
<string>Your location is needed for showing nearby events</string>
|
||||||
|
<key>GADApplicationIdentifier</key>
|
||||||
|
<string>ca-app-pub-4855855675386260~3438207239</string>
|
||||||
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -9,7 +9,9 @@ import 'alert.dart';
|
|||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
import '../main.dart';
|
import '../pages/LoginDemo.dart';
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv
|
||||||
|
import 'package:encrypt_shared_preferences/provider.dart';
|
||||||
|
|
||||||
class MyDrawer extends StatelessWidget with ShowAlertDialog {
|
class MyDrawer extends StatelessWidget with ShowAlertDialog {
|
||||||
Future<void> logout(BuildContext context) async {
|
Future<void> logout(BuildContext context) async {
|
||||||
@ -24,43 +26,54 @@ class MyDrawer extends StatelessWidget with ShowAlertDialog {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
||||||
});
|
});
|
||||||
|
|
||||||
print("Status code logout ${response.statusCode}");
|
print("Status code logout ${response.statusCode}");
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
await prefs.setString("access_token", ""); // Clear the token
|
await prefs.remove("access_token");
|
||||||
Navigator.pushReplacement(
|
await dotenv.load(fileName: ".env"); // Load .env file
|
||||||
context, MaterialPageRoute(builder: (_) => LoginDemo()));
|
|
||||||
|
final keyEncrypt = dotenv.env['KEY_ENCRYPT'] ?? '';
|
||||||
|
if (keyEncrypt.isNotEmpty) {
|
||||||
|
await EncryptedSharedPreferences.initialize(keyEncrypt);
|
||||||
|
var sharedPref = EncryptedSharedPreferences.getInstance();
|
||||||
|
String username = sharedPref.getString("username") ?? "";
|
||||||
|
String password = sharedPref.getString("password") ?? "";
|
||||||
|
if ((username.isEmpty) || (password.isEmpty)) {
|
||||||
|
sharedPref.remove("username");
|
||||||
|
sharedPref.remove("password");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => LoginDemo()),
|
||||||
|
(route) => false, // Remove all previous routes
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
|
String errorMessage;
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 400:
|
case 400:
|
||||||
print("Bad Request: Please check your input.");
|
errorMessage = "Bad Request: Please check your input.";
|
||||||
showAlertDialog(
|
|
||||||
context, "Bad Request", "Please check your input.");
|
|
||||||
break;
|
break;
|
||||||
case 401:
|
case 401:
|
||||||
print("Unauthorized: Invalid credentials.");
|
errorMessage = "Unauthorized: Invalid credentials.";
|
||||||
showAlertDialog(context, "Unauthorized", "Invalid credentials.");
|
|
||||||
break;
|
break;
|
||||||
case 403:
|
case 403:
|
||||||
print("Forbidden: You don't have permission.");
|
errorMessage = "Forbidden: You don't have permission.";
|
||||||
showAlertDialog(context, "Forbidden",
|
|
||||||
"You don't have permission to access this.");
|
|
||||||
break;
|
break;
|
||||||
case 404:
|
case 404:
|
||||||
print("Not Found: The resource was not found.");
|
errorMessage = "Not Found: The resource was not found.";
|
||||||
showAlertDialog(
|
|
||||||
context, "Not Found", "The resource was not found.");
|
|
||||||
break;
|
break;
|
||||||
case 500:
|
case 500:
|
||||||
print("Server Error: Something went wrong on the server.");
|
errorMessage =
|
||||||
showAlertDialog(context, "Server Error",
|
"Server Error: Something went wrong on the server.";
|
||||||
"Something went wrong on the server.");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
print("Unexpected Error: ${response.statusCode}");
|
errorMessage = "Unexpected Error: ${response.statusCode}";
|
||||||
showAlertDialog(context, "Error", "Unexpected Error occurred.");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
print(errorMessage);
|
||||||
|
showAlertDialog(context, "Error", errorMessage);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error: $e");
|
print("Error: $e");
|
||||||
@ -68,7 +81,7 @@ class MyDrawer extends StatelessWidget with ShowAlertDialog {
|
|||||||
context, "Error", "An error occurred. Please try again.");
|
context, "Error", "An error occurred. Please try again.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showAlertDialog(context, "Error", "Token invalide.");
|
showAlertDialog(context, "Error", "Invalid token.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
covas_mobile/lib/classes/ad_helper.dart
Normal file
27
covas_mobile/lib/classes/ad_helper.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||||
|
|
||||||
|
class AdHelper {
|
||||||
|
static Future<BannerAd> createBannerAd(Function setStateCallback) async {
|
||||||
|
await dotenv.load(fileName: ".env");
|
||||||
|
final adUnitId = dotenv.env['AD_UNIT_ID'] ?? '';
|
||||||
|
|
||||||
|
BannerAd bannerAd = BannerAd(
|
||||||
|
adUnitId: adUnitId,
|
||||||
|
size: AdSize.banner,
|
||||||
|
request: AdRequest(),
|
||||||
|
listener: BannerAdListener(
|
||||||
|
onAdLoaded: (ad) {
|
||||||
|
setStateCallback(() {});
|
||||||
|
},
|
||||||
|
onAdFailedToLoad: (ad, error) {
|
||||||
|
print('Banner Ad failed to load: $error');
|
||||||
|
ad.dispose();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
bannerAd.load();
|
||||||
|
return bannerAd;
|
||||||
|
}
|
||||||
|
}
|
141
covas_mobile/lib/classes/auth_service.dart
Normal file
141
covas_mobile/lib/classes/auth_service.dart
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import '../variable/globals.dart' as globals;
|
||||||
|
import 'dart:io';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:encrypt_shared_preferences/provider.dart';
|
||||||
|
import '../pages/LoginDemo.dart';
|
||||||
|
import 'package:flutter_dotenv/flutter_dotenv.dart'; // Import dotenv
|
||||||
|
|
||||||
|
class AuthService {
|
||||||
|
// Login with username and password
|
||||||
|
Future<bool> login(String username, String password,
|
||||||
|
{bool rememberMe = false}) async {
|
||||||
|
final url = Uri.parse("${globals.api}/token");
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.post(
|
||||||
|
url,
|
||||||
|
headers: {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: {"username": username, "password": password},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
if (rememberMe) {
|
||||||
|
await dotenv.load(fileName: ".env"); // Load .env file
|
||||||
|
|
||||||
|
final keyEncrypt = dotenv.env['KEY_ENCRYPT'] ?? '';
|
||||||
|
if (keyEncrypt.isNotEmpty) {
|
||||||
|
await EncryptedSharedPreferences.initialize(keyEncrypt);
|
||||||
|
var sharedPref = EncryptedSharedPreferences.getInstance();
|
||||||
|
sharedPref.setString("username", username);
|
||||||
|
sharedPref.setString("password", password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final cookies = response.headers["set-cookie"]?.split(";") ?? [];
|
||||||
|
|
||||||
|
for (final cookie in cookies) {
|
||||||
|
final cookieParts = cookie.split(",");
|
||||||
|
for (final part in cookieParts) {
|
||||||
|
final keyValue = part.split("=");
|
||||||
|
if (keyValue.length == 2 && keyValue[0] == "access_token") {
|
||||||
|
prefs.setString("access_token", keyValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Login error: $e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logout
|
||||||
|
Future<void> logout() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.remove("access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> isLoggedIn() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
final accessToken = prefs.getString("access_token");
|
||||||
|
|
||||||
|
if (accessToken == null || accessToken.isEmpty) {
|
||||||
|
print("No access token found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Checking token validity...");
|
||||||
|
var url = Uri.parse("${globals.api}/token");
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await http.get(
|
||||||
|
url,
|
||||||
|
headers: {
|
||||||
|
HttpHeaders.cookieHeader: "access_token=$accessToken",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
print("Token is valid.");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
print("Token is invalid. Status code: ${response.statusCode}");
|
||||||
|
await dotenv.load(fileName: ".env"); // Load .env file
|
||||||
|
|
||||||
|
final keyEncrypt = dotenv.env['KEY_ENCRYPT'] ?? '';
|
||||||
|
if (keyEncrypt.isNotEmpty) {
|
||||||
|
await EncryptedSharedPreferences.initialize(keyEncrypt);
|
||||||
|
var sharedPref = EncryptedSharedPreferences.getInstance();
|
||||||
|
String username = sharedPref.getString("username") ?? "";
|
||||||
|
String password = sharedPref.getString("password") ?? "";
|
||||||
|
if ((username.isEmpty) || (password.isEmpty)) {
|
||||||
|
sharedPref.remove("username");
|
||||||
|
sharedPref.remove("password");
|
||||||
|
await prefs.remove("access_token"); // Clear invalid token
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return login(username, password);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print("Error while checking token: $e");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> checkTokenStatus(context) async {
|
||||||
|
bool loggedIn = await isLoggedIn();
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
if (!loggedIn) {
|
||||||
|
await prefs.remove("access_token"); // Correctly remove the token
|
||||||
|
|
||||||
|
Navigator.pushAndRemoveUntil(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (_) => LoginDemo()),
|
||||||
|
(route) => false, // Remove all previous routes
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get stored access token
|
||||||
|
Future<String?> getAccessToken() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getString("access_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login with Google
|
||||||
|
}
|
@ -1,20 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'pages/LoginDemo.dart';
|
||||||
|
|
||||||
import 'dart:convert';
|
void main() async {
|
||||||
import 'dart:io';
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
|
|
||||||
//import 'MyHomePage.dart';
|
|
||||||
import 'pages/ListItemMenu.dart';
|
|
||||||
import 'pages/AddProfile.dart';
|
|
||||||
|
|
||||||
import 'classes/alert.dart';
|
|
||||||
|
|
||||||
import 'variable/globals.dart' as globals;
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,234 +18,3 @@ class MyApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoginDemo extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_LoginDemoState createState() => _LoginDemoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LoginDemoState extends State<LoginDemo> with ShowAlertDialog {
|
|
||||||
TextEditingController inputPseudo = TextEditingController();
|
|
||||||
TextEditingController inputPassword = TextEditingController();
|
|
||||||
Future<void> _login(BuildContext context) async {
|
|
||||||
final url = Uri.parse("${globals.api}/token");
|
|
||||||
final pseudo = inputPseudo.text;
|
|
||||||
final password = inputPassword.text;
|
|
||||||
|
|
||||||
print("Attempting login");
|
|
||||||
if (pseudo.isEmpty || password.isEmpty) {
|
|
||||||
showAlertDialog(context, "Erreur", "Champ vide");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
print("Request URL: $url");
|
|
||||||
try {
|
|
||||||
final response = await http.post(
|
|
||||||
url,
|
|
||||||
headers: {
|
|
||||||
'accept': 'application/json',
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
"username": pseudo,
|
|
||||||
"password": password,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
print("Response status code: ${response.statusCode}");
|
|
||||||
|
|
||||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
|
||||||
final cookies = response.headers["set-cookie"]?.split(";") ?? [];
|
|
||||||
|
|
||||||
for (final cookie in cookies) {
|
|
||||||
final cookieParts = cookie.split(",");
|
|
||||||
for (final part in cookieParts) {
|
|
||||||
final keyValue = part.split("=");
|
|
||||||
if (keyValue.length == 2 && keyValue[0] == "access_token") {
|
|
||||||
prefs.setString("access_token", keyValue[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(builder: (_) => ListItemMenu()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_handleErrorResponse(context, response.statusCode);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showAlertDialog(context, "Erreur", e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _handleErrorResponse(BuildContext context, int statusCode) {
|
|
||||||
final errorMessages = {
|
|
||||||
400: "Requête mal construite",
|
|
||||||
406: "Mot de passe incorrect",
|
|
||||||
404: "Utilisateur inconnu",
|
|
||||||
403: "Utilisateur désactivé",
|
|
||||||
410: "Token invalide",
|
|
||||||
500: "Problème interne du serveur",
|
|
||||||
};
|
|
||||||
|
|
||||||
final errorMessage =
|
|
||||||
errorMessages[statusCode] ?? "Problème d'authentification inconnu";
|
|
||||||
showAlertDialog(context, "Erreur serveur", errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() async {
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
var access_token = prefs.getString("access_token") ?? "";
|
|
||||||
print("Get access token");
|
|
||||||
|
|
||||||
if (access_token.isNotEmpty) {
|
|
||||||
print("Appel HTTP");
|
|
||||||
var urlToken = Uri.parse("${globals.api}/token");
|
|
||||||
|
|
||||||
var responseToken = await http.get(urlToken,
|
|
||||||
headers: {HttpHeaders.cookieHeader: 'access_token: ${access_token}'});
|
|
||||||
print(responseToken.statusCode);
|
|
||||||
if (responseToken.statusCode == 200) {
|
|
||||||
print("route to item list");
|
|
||||||
Navigator.push(
|
|
||||||
context, MaterialPageRoute(builder: (_) => ListItemMenu()));
|
|
||||||
} else {
|
|
||||||
prefs.remove("access_token");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
_checkLocationPermission();
|
|
||||||
start();
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _checkLocationPermission() async {
|
|
||||||
PermissionStatus status = await Permission.location.status;
|
|
||||||
|
|
||||||
if (status.isGranted) {
|
|
||||||
print("Location permission granted");
|
|
||||||
} else if (status.isDenied) {
|
|
||||||
print("Location permission denied");
|
|
||||||
_requestLocationPermission();
|
|
||||||
} else if (status.isPermanentlyDenied) {
|
|
||||||
print("Location permission permanently denied");
|
|
||||||
openAppSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Request location permission
|
|
||||||
Future<void> _requestLocationPermission() async {
|
|
||||||
PermissionStatus status = await Permission.location.request();
|
|
||||||
|
|
||||||
if (status.isGranted) {
|
|
||||||
print("Location permission granted");
|
|
||||||
} else if (status.isDenied) {
|
|
||||||
print("Location permission denied");
|
|
||||||
} else if (status.isPermanentlyDenied) {
|
|
||||||
print("Location permission permanently denied");
|
|
||||||
openAppSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open app settings to allow user to grant permission manually
|
|
||||||
Future<void> _openAppSettings() async {
|
|
||||||
bool opened = await openAppSettings();
|
|
||||||
if (opened) {
|
|
||||||
print("App settings opened");
|
|
||||||
} else {
|
|
||||||
print("Failed to open app settings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text("Login Page"),
|
|
||||||
backgroundColor: Colors.blue,
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
body: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 60.0),
|
|
||||||
child: Center(
|
|
||||||
child: Container(
|
|
||||||
width: 200,
|
|
||||||
height: 150,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.red,
|
|
||||||
borderRadius: BorderRadius.circular(50.0)),
|
|
||||||
child: Image.asset('./images/flutter.png')),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
//padding: const EdgeInsets.only(left:15.0,right: 15.0,top:0,bottom: 0),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
|
||||||
child: TextField(
|
|
||||||
controller: inputPseudo,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Pseudo',
|
|
||||||
hintText: 'Enter pseudo existent'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
|
||||||
//padding: EdgeInsets.symmetric(horizontal: 15),
|
|
||||||
child: TextField(
|
|
||||||
controller: inputPassword,
|
|
||||||
obscureText: true,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Password',
|
|
||||||
hintText: 'Enter secure password'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
//TODO FORGOT PASSWORD SCREEN GOES HERE
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Forgot Password',
|
|
||||||
style: TextStyle(color: Colors.blue, fontSize: 15),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
height: 50,
|
|
||||||
width: 250,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.blue, borderRadius: BorderRadius.circular(20)),
|
|
||||||
child: TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
_login(context);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'Login',
|
|
||||||
style: TextStyle(color: Colors.white, fontSize: 25),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 130,
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
child: Text('New User? Create Account'),
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context, MaterialPageRoute(builder: (_) => AddProfile()));
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -5,13 +5,18 @@ import 'package:intl/intl.dart';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import '../main.dart';
|
import '../pages/LoginDemo.dart';
|
||||||
|
|
||||||
import '../classes/alert.dart';
|
import '../classes/alert.dart';
|
||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +38,8 @@ class AddProfile extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _AddProfileState extends State<AddProfile> with ShowAlertDialog {
|
class _AddProfileState extends State<AddProfile> with ShowAlertDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
|
||||||
TextEditingController inputUserName = TextEditingController();
|
TextEditingController inputUserName = TextEditingController();
|
||||||
|
|
||||||
TextEditingController inputName = TextEditingController();
|
TextEditingController inputName = TextEditingController();
|
||||||
@ -133,6 +140,12 @@ class _AddProfileState extends State<AddProfile> with ShowAlertDialog {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
@ -154,6 +167,12 @@ class _AddProfileState extends State<AddProfile> with ShowAlertDialog {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
@ -7,6 +6,7 @@ import '../classes/MyDrawer.dart';
|
|||||||
import 'DisplayPictureScreen.dart';
|
import 'DisplayPictureScreen.dart';
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
// Ensure that plugin services are initialized so that `availableCameras()`
|
// Ensure that plugin services are initialized so that `availableCameras()`
|
||||||
@ -46,12 +46,14 @@ class Camera extends StatefulWidget {
|
|||||||
class CameraState extends State<Camera> {
|
class CameraState extends State<Camera> {
|
||||||
late CameraController _controller;
|
late CameraController _controller;
|
||||||
late Future<void> _initializeControllerFuture;
|
late Future<void> _initializeControllerFuture;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// To display the current output from the Camera,
|
// To display the current output from the Camera,
|
||||||
// create a CameraController.
|
// create a CameraController.
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
_controller = CameraController(
|
_controller = CameraController(
|
||||||
// Get a specific camera from the list of available cameras.
|
// Get a specific camera from the list of available cameras.
|
||||||
@ -95,7 +97,6 @@ class CameraState extends State<Camera> {
|
|||||||
// camera preview. Use a FutureBuilder to display a loading spinner until the
|
// camera preview. Use a FutureBuilder to display a loading spinner until the
|
||||||
// controller has finished initializing.
|
// controller has finished initializing.
|
||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
|
|
||||||
body: FutureBuilder<void>(
|
body: FutureBuilder<void>(
|
||||||
future: _initializeControllerFuture,
|
future: _initializeControllerFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -7,6 +7,7 @@ import 'package:image_picker/image_picker.dart';
|
|||||||
import 'EditEvent.dart';
|
import 'EditEvent.dart';
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
// Ensure that plugin services are initialized so that `availableCameras()`
|
// Ensure that plugin services are initialized so that `availableCameras()`
|
||||||
@ -45,10 +46,13 @@ class CameraEdit extends StatefulWidget {
|
|||||||
class CameraEditState extends State<CameraEdit> {
|
class CameraEditState extends State<CameraEdit> {
|
||||||
late CameraController _controller;
|
late CameraController _controller;
|
||||||
late Future<void> _initializeControllerFuture;
|
late Future<void> _initializeControllerFuture;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
// To display the current output from the Camera,
|
// To display the current output from the Camera,
|
||||||
// create a CameraController.
|
// create a CameraController.
|
||||||
|
|
||||||
@ -95,7 +99,6 @@ class CameraEditState extends State<CameraEdit> {
|
|||||||
// camera preview. Use a FutureBuilder to display a loading spinner until the
|
// camera preview. Use a FutureBuilder to display a loading spinner until the
|
||||||
// controller has finished initializing.
|
// controller has finished initializing.
|
||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
|
|
||||||
body: FutureBuilder<void>(
|
body: FutureBuilder<void>(
|
||||||
future: _initializeControllerFuture,
|
future: _initializeControllerFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -14,7 +14,13 @@ import 'dart:convert';
|
|||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,9 +62,21 @@ class DisplayPictureScreen extends StatefulWidget {
|
|||||||
// A widget that displays the picture taken by the user.
|
// A widget that displays the picture taken by the user.
|
||||||
class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
||||||
with ShowDescImageAdd, ShowAlertDialog, TickerProviderStateMixin {
|
with ShowDescImageAdd, ShowAlertDialog, TickerProviderStateMixin {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
late AnimationController controller;
|
late AnimationController controller;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
controller = AnimationController(
|
controller = AnimationController(
|
||||||
/// [AnimationController]s can be created with `vsync: this` because of
|
/// [AnimationController]s can be created with `vsync: this` because of
|
||||||
/// [TickerProviderStateMixin].
|
/// [TickerProviderStateMixin].
|
||||||
@ -68,7 +86,6 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
controller.repeat(reverse: false);
|
controller.repeat(reverse: false);
|
||||||
super.initState();
|
|
||||||
|
|
||||||
_getEventInfosFromImage();
|
_getEventInfosFromImage();
|
||||||
}
|
}
|
||||||
@ -85,6 +102,41 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
"L'IA de Google n'a pas su analyser l'image. Recommecer avec une autre");
|
"L'IA de Google n'a pas su analyser l'image. Recommecer avec une autre");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showErrorDialog(BuildContext context, String title, String message) {
|
||||||
|
showAlertDialog(context, title, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>?> _fetchGeolocation(String place) async {
|
||||||
|
final apiKey = dotenv.env['PLACE_API_KEY'] ?? '';
|
||||||
|
final response = await http.get(Uri.parse(
|
||||||
|
'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${place}}&key=$apiKey'));
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
if (data['results'].isNotEmpty) {
|
||||||
|
return data['results'][0]['geometry']['location'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _isDuplicateEvent(String accessToken,
|
||||||
|
Map<String, dynamic> jsonData, Map<String, dynamic> location) async {
|
||||||
|
final url = Uri.parse(
|
||||||
|
"${globals.api}/events/search?item=${jsonData["name"]}&date_event=${jsonData["start_date"]}"
|
||||||
|
"&min_lat=${location['lat']}&max_lat=${location['lat']}"
|
||||||
|
"&min_lon=${location['lng']}&max_lon=${location['lng']}");
|
||||||
|
|
||||||
|
final response = await http.get(url,
|
||||||
|
headers: {HttpHeaders.cookieHeader: 'access_token=$accessToken'});
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final events = jsonDecode(utf8.decode(response.bodyBytes));
|
||||||
|
return events.isNotEmpty;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> searchEvents(String json, String imagePath) async {
|
Future<void> searchEvents(String json, String imagePath) async {
|
||||||
print(json.replaceAll("'''json", '').replaceAll("'''", ""));
|
print(json.replaceAll("'''json", '').replaceAll("'''", ""));
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
@ -99,13 +151,22 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
var accessToken = prefs.getString("access_token") ?? "";
|
var accessToken = prefs.getString("access_token") ?? "";
|
||||||
|
|
||||||
if (accessToken.isNotEmpty) {
|
if (accessToken.isNotEmpty) {
|
||||||
var urlGet = Uri.parse(
|
final location = await _fetchGeolocation(place);
|
||||||
"${globals.api}/events/search?item=${name}&date_event=${date}");
|
if (location == null) {
|
||||||
|
_showErrorDialog(
|
||||||
|
context, "Erreur serveur", "Aucune donnée geographique");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var responseGet = await http.get(urlGet,
|
final url = Uri.parse(
|
||||||
headers: {HttpHeaders.cookieHeader: 'access_token=${accessToken}'});
|
"${globals.api}/events/search?item=${name}&date_event=${date}"
|
||||||
if (responseGet.statusCode == 200) {
|
"&min_lat=${location['lat']}&max_lat=${location['lat']}"
|
||||||
var events = jsonDecode(utf8.decode(responseGet.bodyBytes));
|
"&min_lon=${location['lng']}&max_lon=${location['lng']}");
|
||||||
|
|
||||||
|
final response = await http.get(url,
|
||||||
|
headers: {HttpHeaders.cookieHeader: 'access_token=$accessToken'});
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
var events = jsonDecode(utf8.decode(response.bodyBytes));
|
||||||
print("reponse http : ${events.length}");
|
print("reponse http : ${events.length}");
|
||||||
if (events.length == 0) {
|
if (events.length == 0) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@ -121,7 +182,7 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showAlertDialog(context, 'Erreur de reponse',
|
showAlertDialog(context, 'Erreur de reponse',
|
||||||
"response status code update : ${responseGet.statusCode}");
|
"response status code update : ${response.statusCode}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showAlertDialog(context, "Erreur de reponse", "Erreur de token");
|
showAlertDialog(context, "Erreur de reponse", "Erreur de token");
|
||||||
@ -145,7 +206,7 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
gemini
|
gemini
|
||||||
.textAndImage(
|
.textAndImage(
|
||||||
text:
|
text:
|
||||||
"Peux-tu donner le nom, la date avec l'année actuelle ou d'une année future proche et le lieu de l'évènement sous format JSON (sans le caratère json au début de la chaine de caractère) avec les valeurs suivantes : name, place, description, tags (tableau sans espace), organizers (tableau), start_date et end_date (si le end_date est vide, alors donnez une valeur de six de plus par rapport à start_date) sous le format en YYYY-MM-DD HH:mm:ssZ",
|
"Peux-tu donner le nom, la date (si l'année n'est pas précisé, mettez l'année actuelle ou future) et le lieu de l'évènement sous format JSON (sans le caratère json au début de la chaine de caractère) avec les valeurs suivantes : name, place, description, tags (tableau sans espace), organizers (tableau), start_date et end_date (si le end_date est vide, alors donnez une valeur de six de plus par rapport à start_date) sous le format en YYYY-MM-DD HH:mm:ssZ",
|
||||||
images: [file.readAsBytesSync()],
|
images: [file.readAsBytesSync()],
|
||||||
modelName: "models/gemini-1.5-pro-latest")
|
modelName: "models/gemini-1.5-pro-latest")
|
||||||
.then((value) => searchEvents(
|
.then((value) => searchEvents(
|
||||||
@ -160,12 +221,17 @@ class DisplayPictureScreenState extends State<DisplayPictureScreen>
|
|||||||
// The image is stored as a file on the device. Use the `Image.file`
|
// The image is stored as a file on the device. Use the `Image.file`
|
||||||
// constructor with the given path to display the image.
|
// constructor with the given path to display the image.
|
||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
|
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Text(
|
Text(
|
||||||
'Analyse de l\'image en cours',
|
'Analyse de l\'image en cours',
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
@ -9,12 +9,9 @@ import 'package:textfield_tags/textfield_tags.dart';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'dart:typed_data';
|
|
||||||
import '../classes/events.dart';
|
import '../classes/events.dart';
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
|
|
||||||
import 'ItemMenu.dart';
|
|
||||||
import 'CameraEdit.dart';
|
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
|
|
||||||
import '../classes/alert.dart';
|
import '../classes/alert.dart';
|
||||||
@ -22,7 +19,13 @@ import '../classes/eventAdded.dart';
|
|||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +57,9 @@ class EditEvent extends StatefulWidget {
|
|||||||
|
|
||||||
class _EditEventState extends State<EditEvent>
|
class _EditEventState extends State<EditEvent>
|
||||||
with ShowAlertDialog, ShowEventDialog {
|
with ShowAlertDialog, ShowEventDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
TextEditingController inputName = TextEditingController();
|
TextEditingController inputName = TextEditingController();
|
||||||
|
|
||||||
TextEditingController inputDate = TextEditingController();
|
TextEditingController inputDate = TextEditingController();
|
||||||
@ -159,177 +165,163 @@ class _EditEventState extends State<EditEvent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateEvent(BuildContext context) async {
|
Future<void> _updateEvent(BuildContext context) async {
|
||||||
var name = inputName.text;
|
if (!_isEventInFuture()) {
|
||||||
var place = inputGeo.text;
|
_showErrorDialog(context, "Erreur evenement", "Evenement non futur");
|
||||||
var description = inputDesc.text;
|
return;
|
||||||
List<String> tags = List<String>.from(_stringTagController.getTags as List);
|
|
||||||
List<String> organizers =
|
|
||||||
List<String>.from(_stringOrgaController.getTags as List);
|
|
||||||
|
|
||||||
var startDateFormat = formatDate(startDatepicker.text);
|
|
||||||
//DateTime startDateCompare = DateTime.parse(startDateFormat);
|
|
||||||
DateTime dateNow = DateTime.now();
|
|
||||||
var endDateFormat = formatDate(endDatepicker.text);
|
|
||||||
var startDate =
|
|
||||||
"${startDateFormat}T${startTimepicker.text.replaceAll('-', ':')}";
|
|
||||||
var endDate = "${endDateFormat}T${endTimepicker.text.replaceAll('-', ':')}";
|
|
||||||
DateTime startDateCompare = DateTime.parse(startDate);
|
|
||||||
if (startDateCompare.isAfter(dateNow)) {
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
var accessToken = prefs.getString("access_token") ?? "";
|
|
||||||
|
|
||||||
if (accessToken.isNotEmpty) {
|
|
||||||
try {
|
|
||||||
await dotenv.load();
|
|
||||||
final ApiTokenGoogle = dotenv.env['PLACE_API_KEY'] ?? '';
|
|
||||||
// Searchbox API for geocoding the place (No session token)
|
|
||||||
final searchboxUrl = Uri.parse(
|
|
||||||
'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${place}&key=${ApiTokenGoogle}');
|
|
||||||
|
|
||||||
// Perform the request
|
|
||||||
final searchboxResponse = await http.get(searchboxUrl);
|
|
||||||
|
|
||||||
if (searchboxResponse.statusCode == 200) {
|
|
||||||
final data = json.decode(searchboxResponse.body);
|
|
||||||
print("data : ${data}");
|
|
||||||
|
|
||||||
if (data['results'].isNotEmpty) {
|
|
||||||
place = data['results'][0]['formatted_address'];
|
|
||||||
final coordinates = data['results'][0]['geometry']['location'];
|
|
||||||
final longitude = coordinates["lng"]; // Longitude
|
|
||||||
final latitude = coordinates["lat"]; // Latitude
|
|
||||||
var urlGet = Uri.parse(
|
|
||||||
"${globals.api}/events/search?item=${name}&date_event=${startDate}&min_lat=$latitude&max_lat=$latitude"
|
|
||||||
"&min_lon=$longitude&max_lon=$longitude");
|
|
||||||
|
|
||||||
var responseGet = await http.get(urlGet, headers: {
|
|
||||||
HttpHeaders.cookieHeader: 'access_token=${accessToken}'
|
|
||||||
});
|
|
||||||
if (responseGet.statusCode == 200) {
|
|
||||||
var events = jsonDecode(utf8.decode(responseGet.bodyBytes));
|
|
||||||
if (events.length > 0) {
|
|
||||||
if (events[0]["id"] != widget.events!.id) {
|
|
||||||
showAlertDialog(
|
|
||||||
context, "Info evenement", "Evenement deja existant");
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widget.imgPath.isNotEmpty) {
|
|
||||||
final params = {
|
|
||||||
'expiration': '15552000',
|
|
||||||
'key': dotenv.env["IMGBB_API_KEY"],
|
|
||||||
};
|
|
||||||
print("Post Img");
|
|
||||||
final urlPost = Uri.parse('https://api.imgbb.com/1/upload')
|
|
||||||
.replace(queryParameters: params);
|
|
||||||
File image = File(widget.imgPath);
|
|
||||||
Uint8List _bytes = await image.readAsBytes();
|
|
||||||
String _base64String = base64.encode(_bytes);
|
|
||||||
|
|
||||||
final req = http.MultipartRequest('POST', urlPost)
|
|
||||||
..fields['image'] = _base64String;
|
|
||||||
|
|
||||||
final stream = await req.send();
|
|
||||||
final res = await http.Response.fromStream(stream);
|
|
||||||
|
|
||||||
final status = res.statusCode;
|
|
||||||
print("code status imgbb ${status}");
|
|
||||||
if (status != 200) {
|
|
||||||
showAlertDialog(context, "Erreur image", "Image non posté");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var body = json.decode(utf8.decode(res.bodyBytes));
|
|
||||||
imgUrl = body["data"]["url"];
|
|
||||||
}
|
|
||||||
var urlPut =
|
|
||||||
Uri.parse("${globals.api}/events/${widget.events!.id}");
|
|
||||||
var responsePut = await http.put(urlPut,
|
|
||||||
headers: {
|
|
||||||
HttpHeaders.cookieHeader: 'access_token=${accessToken}',
|
|
||||||
HttpHeaders.acceptHeader:
|
|
||||||
'application/json, text/plain, */*',
|
|
||||||
HttpHeaders.contentTypeHeader: 'application/json'
|
|
||||||
},
|
|
||||||
body: jsonEncode({
|
|
||||||
'name': name,
|
|
||||||
'place': place,
|
|
||||||
'start_date': startDate,
|
|
||||||
'end_date': endDate,
|
|
||||||
'organizers': organizers,
|
|
||||||
'latitude': latitude,
|
|
||||||
'longitude': longitude,
|
|
||||||
'description': description,
|
|
||||||
"imgUrl": imgUrl,
|
|
||||||
"tags": tags
|
|
||||||
}));
|
|
||||||
print(responsePut.statusCode);
|
|
||||||
if ((responsePut.statusCode == 200) ||
|
|
||||||
(responsePut.statusCode == 201)) {
|
|
||||||
showEventDialog(context, "Evenement ${name} modifie");
|
|
||||||
} else {
|
|
||||||
var text = "";
|
|
||||||
switch (responsePut.statusCode) {
|
|
||||||
case 400:
|
|
||||||
{
|
|
||||||
text = "Requête mal construite";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 406:
|
|
||||||
{
|
|
||||||
text = "Mot de passe incorrect";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 404:
|
|
||||||
{
|
|
||||||
text = "Utilisateur inconnu";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 403:
|
|
||||||
{
|
|
||||||
text = "Utilisateur desactive";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 410:
|
|
||||||
{
|
|
||||||
text = "Token invalide";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 500:
|
|
||||||
{
|
|
||||||
text = "Probleme interne du serveur";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
text = "Probleme d'authentification inconnu";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
showAlertDialog(context, "Erreur serveur", text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showAlertDialog(
|
|
||||||
context, "Erreur serveur", "Aucune donnée geographique");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showAlertDialog(context, "Erreur serveur", "Mapbox non accessible");
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showAlertDialog(context, "Erreur serveur", "${e}");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showAlertDialog(context, "Erreur utilisateur", "Champ vide");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showAlertDialog(context, "Erreur evenement", "Evenement non futur");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final accessToken = await _getAccessToken();
|
||||||
|
if (accessToken.isEmpty) {
|
||||||
|
_showErrorDialog(context, "Erreur utilisateur", "Champ vide");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dotenv.load();
|
||||||
|
final geolocation = await _fetchGeolocation();
|
||||||
|
if (geolocation == null) {
|
||||||
|
_showErrorDialog(
|
||||||
|
context, "Erreur serveur", "Aucune donnée geographique");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await _isDuplicateEvent(accessToken, geolocation)) {
|
||||||
|
_showErrorDialog(context, "Info evenement", "Evenement deja existant");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.imgPath.isNotEmpty) {
|
||||||
|
imgUrl = await _uploadImage(widget.imgPath);
|
||||||
|
if (imgUrl.isEmpty) {
|
||||||
|
_showErrorDialog(context, "Erreur image", "Image non postée");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await _updateEventData(accessToken, geolocation);
|
||||||
|
showEventDialog(context, "Evenement ${inputName.text} modifie");
|
||||||
|
} catch (e) {
|
||||||
|
_showErrorDialog(context, "Erreur serveur", "$e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isEventInFuture() {
|
||||||
|
DateTime startDateCompare = DateTime.parse(
|
||||||
|
"${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}");
|
||||||
|
return startDateCompare.isAfter(DateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _getAccessToken() async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getString("access_token") ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>?> _fetchGeolocation() async {
|
||||||
|
final apiKey = dotenv.env['PLACE_API_KEY'] ?? '';
|
||||||
|
final response = await http.get(Uri.parse(
|
||||||
|
'https://maps.googleapis.com/maps/api/place/textsearch/json?query=${inputGeo.text}&key=$apiKey'));
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = json.decode(response.body);
|
||||||
|
if (data['results'].isNotEmpty) {
|
||||||
|
return data['results'][0]['geometry']['location'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _isDuplicateEvent(
|
||||||
|
String accessToken, Map<String, dynamic> location) async {
|
||||||
|
final url = Uri.parse(
|
||||||
|
"${globals.api}/events/search?item=${inputName.text}&date_event=${formatDate(startDatepicker.text)}"
|
||||||
|
"&min_lat=${location['lat']}&max_lat=${location['lat']}"
|
||||||
|
"&min_lon=${location['lng']}&max_lon=${location['lng']}");
|
||||||
|
|
||||||
|
final response = await http.get(url,
|
||||||
|
headers: {HttpHeaders.cookieHeader: 'access_token=$accessToken'});
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final events = jsonDecode(utf8.decode(response.bodyBytes));
|
||||||
|
return events.isNotEmpty && events[0]["id"] != widget.events!.id;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> _uploadImage(String imagePath) async {
|
||||||
|
final params = {
|
||||||
|
'expiration': '15552000',
|
||||||
|
'key': dotenv.env["IMGBB_API_KEY"]
|
||||||
|
};
|
||||||
|
final url = Uri.parse('https://api.imgbb.com/1/upload')
|
||||||
|
.replace(queryParameters: params);
|
||||||
|
|
||||||
|
final image = File(imagePath);
|
||||||
|
final req = http.MultipartRequest('POST', url)
|
||||||
|
..fields['image'] = base64.encode(await image.readAsBytes());
|
||||||
|
|
||||||
|
final response = await http.Response.fromStream(await req.send());
|
||||||
|
return response.statusCode == 200
|
||||||
|
? json.decode(response.body)["data"]["url"]
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _updateEventData(
|
||||||
|
String accessToken, Map<String, dynamic> location) async {
|
||||||
|
final url = Uri.parse("${globals.api}/events/${widget.events!.id}");
|
||||||
|
final response = await http.put(url,
|
||||||
|
headers: {
|
||||||
|
HttpHeaders.cookieHeader: 'access_token=$accessToken',
|
||||||
|
HttpHeaders.acceptHeader: 'application/json, text/plain, */*',
|
||||||
|
HttpHeaders.contentTypeHeader: 'application/json'
|
||||||
|
},
|
||||||
|
body: jsonEncode({
|
||||||
|
'name': inputName.text,
|
||||||
|
'place': inputGeo.text,
|
||||||
|
'start_date':
|
||||||
|
"${formatDate(startDatepicker.text)}T${startTimepicker.text.replaceAll('-', ':')}",
|
||||||
|
'end_date':
|
||||||
|
"${formatDate(endDatepicker.text)}T${endTimepicker.text.replaceAll('-', ':')}",
|
||||||
|
'organizers':
|
||||||
|
List<String>.from(_stringOrgaController.getTags as List),
|
||||||
|
'latitude': location['lat'],
|
||||||
|
'longitude': location['lng'],
|
||||||
|
'description': inputDesc.text,
|
||||||
|
"imgUrl": imgUrl,
|
||||||
|
"tags": List<String>.from(_stringTagController.getTags as List)
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
|
_handleErrorResponse(context, response.statusCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleErrorResponse(BuildContext context, int statusCode) {
|
||||||
|
final messages = {
|
||||||
|
400: "Requête mal construite",
|
||||||
|
406: "Mot de passe incorrect",
|
||||||
|
404: "Utilisateur inconnu",
|
||||||
|
403: "Utilisateur désactivé",
|
||||||
|
410: "Token invalide",
|
||||||
|
500: "Problème interne du serveur"
|
||||||
|
};
|
||||||
|
_showErrorDialog(context, "Erreur serveur",
|
||||||
|
messages[statusCode] ?? "Problème d'authentification inconnu");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showErrorDialog(BuildContext context, String title, String message) {
|
||||||
|
showAlertDialog(context, title, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
inputName.text = widget.events!.name ?? "";
|
inputName.text = widget.events!.name ?? "";
|
||||||
startDatepicker.text = DateFormat("dd/MM/yyyy")
|
startDatepicker.text = DateFormat("dd/MM/yyyy")
|
||||||
.format(DateTime.parse(
|
.format(DateTime.parse(
|
||||||
@ -353,7 +345,6 @@ class _EditEventState extends State<EditEvent>
|
|||||||
inputDesc.text = widget.events!.description ?? "";
|
inputDesc.text = widget.events!.description ?? "";
|
||||||
initialTags = List<String>.from(widget.events!.tags as List);
|
initialTags = List<String>.from(widget.events!.tags as List);
|
||||||
initialOrga = List<String>.from(widget.events!.organizers as List);
|
initialOrga = List<String>.from(widget.events!.organizers as List);
|
||||||
super.initState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
@ -467,7 +458,6 @@ class _EditEventState extends State<EditEvent>
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("Add or Update a event"),
|
title: Text("Add or Update a event"),
|
||||||
backgroundColor: Colors.blue,
|
backgroundColor: Colors.blue,
|
||||||
@ -478,6 +468,12 @@ class _EditEventState extends State<EditEvent>
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
if (widget.imgPath.isNotEmpty)
|
if (widget.imgPath.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 60.0),
|
padding: const EdgeInsets.only(top: 60.0),
|
||||||
|
@ -8,14 +8,20 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
import '../main.dart';
|
import '../pages/LoginDemo.dart';
|
||||||
|
|
||||||
import '../classes/alert.dart';
|
import '../classes/alert.dart';
|
||||||
import '../classes/eventAdded.dart';
|
import '../classes/eventAdded.dart';
|
||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +44,9 @@ class EditProfile extends StatefulWidget {
|
|||||||
|
|
||||||
class _EditProfileState extends State<EditProfile>
|
class _EditProfileState extends State<EditProfile>
|
||||||
with ShowAlertDialog, ShowEventDialog {
|
with ShowAlertDialog, ShowEventDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
TextEditingController inputUserName = TextEditingController();
|
TextEditingController inputUserName = TextEditingController();
|
||||||
|
|
||||||
TextEditingController inputName = TextEditingController();
|
TextEditingController inputName = TextEditingController();
|
||||||
@ -192,6 +201,13 @@ class _EditProfileState extends State<EditProfile>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
_getInfoProfile();
|
_getInfoProfile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +231,12 @@ class _EditProfileState extends State<EditProfile>
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
||||||
|
@ -10,7 +10,13 @@ import '../classes/MyDrawer.dart';
|
|||||||
import '../classes/alert.dart';
|
import '../classes/alert.dart';
|
||||||
import '../classes/eventAdded.dart';
|
import '../classes/eventAdded.dart';
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +39,9 @@ class EditSettings extends StatefulWidget {
|
|||||||
|
|
||||||
class _EditProfileState extends State<EditSettings>
|
class _EditProfileState extends State<EditSettings>
|
||||||
with ShowAlertDialog, ShowEventDialog {
|
with ShowAlertDialog, ShowEventDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
TextEditingController inputUserName = TextEditingController();
|
TextEditingController inputUserName = TextEditingController();
|
||||||
int? kilometer;
|
int? kilometer;
|
||||||
|
|
||||||
@ -54,6 +63,13 @@ class _EditProfileState extends State<EditSettings>
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
getParameter();
|
getParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +87,12 @@ class _EditProfileState extends State<EditSettings>
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 15.0,
|
left: 15.0,
|
||||||
@ -125,7 +147,7 @@ class _EditProfileState extends State<EditSettings>
|
|||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Mettre à jour les paramètres',
|
'Mettre à jour',
|
||||||
style: TextStyle(color: Colors.white, fontSize: 25),
|
style: TextStyle(color: Colors.white, fontSize: 25),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
158
covas_mobile/lib/pages/ForgotPassword.dart
Normal file
158
covas_mobile/lib/pages/ForgotPassword.dart
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import '../main.dart';
|
||||||
|
|
||||||
|
import '../classes/alert.dart';
|
||||||
|
|
||||||
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
home: PasswordForgot(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordForgot extends StatefulWidget {
|
||||||
|
const PasswordForgot({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PasswordForgotState createState() => _PasswordForgotState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PasswordForgotState extends State<PasswordForgot> with ShowAlertDialog {
|
||||||
|
TextEditingController inputEmail = TextEditingController();
|
||||||
|
|
||||||
|
convertNulltoEmptyString(var check) {
|
||||||
|
if (check == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertNulltoArray(List<String> check) {
|
||||||
|
if (check == null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatDate(String date) {
|
||||||
|
var splitedDate = date.split("/");
|
||||||
|
|
||||||
|
var day = splitedDate[0];
|
||||||
|
var month = splitedDate[1];
|
||||||
|
var year = splitedDate[2];
|
||||||
|
|
||||||
|
return "${year}-${month}-${day}";
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _forgotPassword(BuildContext context) async {
|
||||||
|
var email = inputEmail.text;
|
||||||
|
|
||||||
|
var urlPut = Uri.parse("${globals.api}/password/forgot");
|
||||||
|
|
||||||
|
var responsePost = await http.post(urlPut,
|
||||||
|
headers: {
|
||||||
|
HttpHeaders.acceptHeader: 'application/json, text/plain, */*',
|
||||||
|
HttpHeaders.contentTypeHeader: 'application/json'
|
||||||
|
},
|
||||||
|
body: jsonEncode({
|
||||||
|
'email': email,
|
||||||
|
}));
|
||||||
|
print(responsePost.statusCode);
|
||||||
|
if (responsePost.statusCode == 200) {
|
||||||
|
showAlertDialog(context, "Creation", "Un email a été envoyé à ${email}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final errorMessages = {
|
||||||
|
400: "Requête mal construite",
|
||||||
|
406: "Mot de passe incorrect",
|
||||||
|
404: "Utilisateur inconnu",
|
||||||
|
403: "Utilisateur désactivé",
|
||||||
|
410: "Token invalide",
|
||||||
|
500: "Problème interne du serveur",
|
||||||
|
};
|
||||||
|
|
||||||
|
final text = errorMessages[responsePost.statusCode] ??
|
||||||
|
"Problème d'authentification inconnu";
|
||||||
|
showAlertDialog(context, "Erreur serveur", text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
String? _validateField(String? value) {
|
||||||
|
return value!.isEmpty ? 'Champ requis' : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("Mot de passe oublie"),
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
body: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 15.0, right: 15.0, top: 15, bottom: 0),
|
||||||
|
//padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: inputEmail,
|
||||||
|
validator: (value) => _validateField(value),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelText: 'Email',
|
||||||
|
hintText: 'Modifier l\'adresse mail'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
width: 250,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue,
|
||||||
|
borderRadius: BorderRadius.circular(20)),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_forgotPassword(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Envoyer le mail',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 25),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,13 @@ import 'MapboxPages.dart';
|
|||||||
import 'ListItemByOrganizers.dart';
|
import 'ListItemByOrganizers.dart';
|
||||||
import 'EditEvent.dart';
|
import 'EditEvent.dart';
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
|
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +75,9 @@ class ItemMenu extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
|
class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
String listUser = "";
|
String listUser = "";
|
||||||
String eventName = "";
|
String eventName = "";
|
||||||
String eventStartDate = "";
|
String eventStartDate = "";
|
||||||
@ -84,6 +93,13 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
_getEventInfos();
|
_getEventInfos();
|
||||||
}
|
}
|
||||||
@ -174,6 +190,12 @@ class _ItemMenuState extends State<ItemMenu> with ShowAlertDialog {
|
|||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 60.0),
|
padding: const EdgeInsets.only(top: 60.0),
|
||||||
child: Image.network(
|
child: Image.network(
|
||||||
|
@ -11,10 +11,16 @@ import 'package:intl/date_symbol_data_local.dart';
|
|||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
// app starting point
|
// app starting point
|
||||||
void main() {
|
void main() async {
|
||||||
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
await initializeDateFormatting("fr_FR", null);
|
||||||
|
|
||||||
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@ -23,6 +29,14 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
localizationsDelegates: [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: [
|
||||||
|
const Locale('fr', 'FR'),
|
||||||
|
],
|
||||||
home: const ListItemOrganizers(organizer: "default"),
|
home: const ListItemOrganizers(organizer: "default"),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
@ -41,15 +55,55 @@ class ListItemOrganizers extends StatefulWidget {
|
|||||||
|
|
||||||
// homepage state
|
// homepage state
|
||||||
class _MyHomePageState extends State<ListItemOrganizers> {
|
class _MyHomePageState extends State<ListItemOrganizers> {
|
||||||
|
int _fetchCount = 0;
|
||||||
|
bool _isLoading = false;
|
||||||
|
late ScrollController _scrollController;
|
||||||
|
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
|
void _incrementFetchCount() {
|
||||||
|
setState(() {
|
||||||
|
_fetchCount++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scrollListener() {
|
||||||
|
if (_scrollController.position.pixels ==
|
||||||
|
_scrollController.position.maxScrollExtent) {
|
||||||
|
_incrementFetchCount();
|
||||||
|
_fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchData() async {
|
||||||
|
print("Counter : ${_fetchCount}");
|
||||||
|
if (_isLoading) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
getPosts(widget.organizer, count: _fetchCount);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// variable to call and store future list of posts
|
// variable to call and store future list of posts
|
||||||
|
|
||||||
// function to fetch data from api and return future list of posts
|
// function to fetch data from api and return future list of posts
|
||||||
static Future<List<Events>> getPosts(organizer) async {
|
static Future<List<Events>> getPosts(organizer, {count = 0}) async {
|
||||||
|
await initializeDateFormatting("fr_FR", null);
|
||||||
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
var accessToken = prefs.getString("access_token") ?? "";
|
var accessToken = prefs.getString("access_token") ?? "";
|
||||||
final List<Events> body = [];
|
final List<Events> body = [];
|
||||||
if (accessToken.isNotEmpty) {
|
if (accessToken.isNotEmpty) {
|
||||||
var url = Uri.parse("${globals.api}/events?organizers=${organizer}");
|
DateTime currentDatetime = DateTime.now();
|
||||||
|
num limit = 20 * (count + 1);
|
||||||
|
var url = Uri.parse(
|
||||||
|
"${globals.api}/events?organizers=${organizer}&limit=${limit}¤t_datetime=${currentDatetime.toString()}");
|
||||||
final response = await http.get(url, headers: {
|
final response = await http.get(url, headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
||||||
@ -60,6 +114,20 @@ class _MyHomePageState extends State<ListItemOrganizers> {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
_scrollController.addListener(_scrollListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// build function
|
// build function
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -100,16 +168,20 @@ class _MyHomePageState extends State<ListItemOrganizers> {
|
|||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
body: ListView.separated(
|
body: ListView.separated(
|
||||||
itemCount: posts.length,
|
controller: _scrollController,
|
||||||
|
itemCount: posts.isNotEmpty
|
||||||
|
? posts.length + (_isLoading ? 1 : 0) // Add 1 only if loading
|
||||||
|
: 0,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final post = posts[index];
|
final post = posts[index];
|
||||||
final startDate = DateTime.parse(post.startDate!);
|
final startDate = DateTime.parse(post.startDate!);
|
||||||
final date = DateFormat.yMd().format(startDate);
|
|
||||||
final time = DateFormat.Hm().format(startDate);
|
final dateLongue =
|
||||||
|
DateFormat('EEEE d MMMM y', 'fr_FR').format(startDate);
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${post.name!}'),
|
title: Text('${post.name!}'),
|
||||||
subtitle: Text('${post.place!}\n${date} ${time}'),
|
subtitle: Text('${post.place!}\n${dateLongue}'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
@ -12,10 +12,16 @@ import 'package:intl/date_symbol_data_local.dart';
|
|||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
// app starting point
|
// app starting point
|
||||||
void main() {
|
void main() async {
|
||||||
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
await initializeDateFormatting("fr_FR", null);
|
||||||
|
|
||||||
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@ -24,6 +30,14 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
localizationsDelegates: [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: [
|
||||||
|
const Locale('fr', 'FR'),
|
||||||
|
],
|
||||||
home: const ListItemTags(tags: "default"),
|
home: const ListItemTags(tags: "default"),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
@ -43,13 +57,55 @@ class ListItemTags extends StatefulWidget {
|
|||||||
class _MyHomePageState extends State<ListItemTags> {
|
class _MyHomePageState extends State<ListItemTags> {
|
||||||
// variable to call and store future list of posts
|
// variable to call and store future list of posts
|
||||||
|
|
||||||
|
int _fetchCount = 0;
|
||||||
|
bool _isLoading = false;
|
||||||
|
late ScrollController _scrollController;
|
||||||
|
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
|
void _incrementFetchCount() {
|
||||||
|
setState(() {
|
||||||
|
_fetchCount++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scrollListener() {
|
||||||
|
if (_scrollController.position.pixels ==
|
||||||
|
_scrollController.position.maxScrollExtent) {
|
||||||
|
_incrementFetchCount();
|
||||||
|
|
||||||
|
_fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchData() async {
|
||||||
|
print("Counter : ${_fetchCount}");
|
||||||
|
if (_isLoading) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
getPosts(widget.tags, count: _fetchCount);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// function to fetch data from api and return future list of posts
|
// function to fetch data from api and return future list of posts
|
||||||
static Future<List<Events>> getPosts(tags) async {
|
static Future<List<Events>> getPosts(tags, {count = 0}) async {
|
||||||
|
await initializeDateFormatting("fr_FR", null);
|
||||||
|
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
var accessToken = prefs.getString("access_token") ?? "";
|
var accessToken = prefs.getString("access_token") ?? "";
|
||||||
final List<Events> body = [];
|
final List<Events> body = [];
|
||||||
if (accessToken.isNotEmpty) {
|
if (accessToken.isNotEmpty) {
|
||||||
var url = Uri.parse("${globals.api}/events?tags=${tags}");
|
DateTime currentDatetime = DateTime.now();
|
||||||
|
num limit = 20 * (count + 1);
|
||||||
|
|
||||||
|
var url = Uri.parse(
|
||||||
|
"${globals.api}/events?tags=${tags}&limit=${limit}¤t_datetime=${currentDatetime.toString()}");
|
||||||
final response = await http.get(url, headers: {
|
final response = await http.get(url, headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
||||||
@ -60,6 +116,21 @@ class _MyHomePageState extends State<ListItemTags> {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
_scrollController.addListener(_scrollListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// build function
|
// build function
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -99,16 +170,19 @@ class _MyHomePageState extends State<ListItemTags> {
|
|||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
body: ListView.separated(
|
body: ListView.separated(
|
||||||
itemCount: posts.length,
|
controller: _scrollController,
|
||||||
|
itemCount: posts.isNotEmpty
|
||||||
|
? posts.length + (_isLoading ? 1 : 0) // Add 1 only if loading
|
||||||
|
: 0,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final post = posts[index];
|
final post = posts[index];
|
||||||
final startDate = DateTime.parse(post.startDate!);
|
final startDate = DateTime.parse(post.startDate!);
|
||||||
final date = DateFormat.yMd().format(startDate);
|
final dateLongue =
|
||||||
final time = DateFormat.Hm().format(startDate);
|
DateFormat('EEEE d MMMM y', 'fr_FR').format(startDate);
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${post.name!}'),
|
title: Text('${post.name!}'),
|
||||||
subtitle: Text('${post.place!}\n${date} ${time}'),
|
subtitle: Text('${post.place!}\n${dateLongue}'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
@ -16,8 +16,18 @@ import 'package:permission_handler/permission_handler.dart';
|
|||||||
import "Camera.dart";
|
import "Camera.dart";
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
initializeDateFormatting("fr_FR", null).then((_) => runApp(const MyApp()));
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
|
await initializeDateFormatting("fr_FR", null);
|
||||||
|
|
||||||
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@ -26,6 +36,14 @@ class MyApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
localizationsDelegates: [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
supportedLocales: [
|
||||||
|
const Locale('fr', 'FR'),
|
||||||
|
],
|
||||||
home: const ListItemMenu(),
|
home: const ListItemMenu(),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
@ -40,6 +58,12 @@ class ListItemMenu extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<ListItemMenu> {
|
class _MyHomePageState extends State<ListItemMenu> {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
late ScrollController _scrollController;
|
||||||
|
int _fetchCount = 0;
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
Future<List<Events>> postsFuture = getPosts();
|
Future<List<Events>> postsFuture = getPosts();
|
||||||
List<Events> filteredPosts = [];
|
List<Events> filteredPosts = [];
|
||||||
String geographicalZone = '';
|
String geographicalZone = '';
|
||||||
@ -62,6 +86,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
bool showInputTag = true;
|
bool showInputTag = true;
|
||||||
// Fetching events from API
|
// Fetching events from API
|
||||||
static Future<List<Events>> getPosts() async {
|
static Future<List<Events>> getPosts() async {
|
||||||
|
await initializeDateFormatting("fr_FR");
|
||||||
PermissionStatus status = await Permission.location.status;
|
PermissionStatus status = await Permission.location.status;
|
||||||
final List<Events> body = [];
|
final List<Events> body = [];
|
||||||
var url = Uri.parse("${globals.api}/events");
|
var url = Uri.parse("${globals.api}/events");
|
||||||
@ -135,13 +160,59 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
return "${year}-${month}-${day}";
|
return "${year}-${month}-${day}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _incrementFetchCount() {
|
||||||
|
setState(() {
|
||||||
|
_fetchCount++;
|
||||||
|
});
|
||||||
|
_fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scrollListener() {
|
||||||
|
if (_scrollController.position.pixels ==
|
||||||
|
_scrollController.position.maxScrollExtent) {
|
||||||
|
_incrementFetchCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll to top
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchData() async {
|
||||||
|
print("Counter : ${_fetchCount}");
|
||||||
|
if (_isLoading) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
fetchPostsByLocation();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
_scrollController.addListener(_scrollListener);
|
||||||
|
|
||||||
// Initialize data fetch when the page loads
|
// Initialize data fetch when the page loads
|
||||||
_getCurrentLocation();
|
_getCurrentLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Get the device's current location
|
// Get the device's current location
|
||||||
Future<void> _getCurrentLocation() async {
|
Future<void> _getCurrentLocation() async {
|
||||||
PermissionStatus status = await Permission.location.status;
|
PermissionStatus status = await Permission.location.status;
|
||||||
@ -331,8 +402,10 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
} else {
|
} else {
|
||||||
queryParameters = dateParameter;
|
queryParameters = dateParameter;
|
||||||
}
|
}
|
||||||
|
int limit = 20 * (_fetchCount + 1);
|
||||||
|
|
||||||
return Uri.parse("${globals.api}/$endpoint?$queryParameters");
|
return Uri.parse(
|
||||||
|
"${globals.api}/$endpoint?$queryParameters&limit=${limit}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> searchSuggestionsByItem(String input) async {
|
Future<void> searchSuggestionsByItem(String input) async {
|
||||||
@ -343,7 +416,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
var url = await getUrlForEvents();
|
var url = await getUrlForEvents();
|
||||||
final response = await http.get(url, headers: {
|
final response = await http.get(url, headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
HttpHeaders.cookieHeader: "access_token=$accessToken"
|
HttpHeaders.cookieHeader: "acce0ss_token=$accessToken"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
@ -407,16 +480,17 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final List<dynamic> body = json.decode(utf8.decode(response.bodyBytes));
|
final List<dynamic> body = json.decode(utf8.decode(response.bodyBytes));
|
||||||
print("results fetch : ${body}");
|
print("results fetch : ${body}");
|
||||||
|
print("fetch count : ${_fetchCount}");
|
||||||
// Update state after getting the response
|
// Update state after getting the response
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
if (body.isNotEmpty) {
|
int counter = filteredPosts.length;
|
||||||
// If we have results, map them to Events
|
// If we have results, map them to Events
|
||||||
filteredPosts = body
|
filteredPosts = body
|
||||||
.map((e) => Events.fromJson(e as Map<String, dynamic>))
|
.map((e) => Events.fromJson(e as Map<String, dynamic>))
|
||||||
.toList();
|
.toList();
|
||||||
} else {
|
if (counter == filteredPosts.length) {
|
||||||
// If no results, clear filteredPosts
|
_fetchCount--;
|
||||||
filteredPosts.clear();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -543,11 +617,19 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
drawer: MyDrawer(),
|
drawer: MyDrawer(),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!),
|
||||||
|
),
|
||||||
if (showInputSearch)
|
if (showInputSearch)
|
||||||
_buildSearchField(
|
_buildSearchField(
|
||||||
controller: inputItem,
|
controller: inputItem,
|
||||||
labelText: 'Search by item',
|
labelText: 'Search by item',
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
_fetchCount = 0;
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
itemName = value;
|
itemName = value;
|
||||||
@ -565,6 +647,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClear: () {
|
onClear: () {
|
||||||
|
_fetchCount = 0;
|
||||||
setState(() {
|
setState(() {
|
||||||
inputItem.clear();
|
inputItem.clear();
|
||||||
itemName = '';
|
itemName = '';
|
||||||
@ -576,6 +659,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
},
|
},
|
||||||
suggestions: suggestionsItem,
|
suggestions: suggestionsItem,
|
||||||
onSuggestionTap: (suggestion) async {
|
onSuggestionTap: (suggestion) async {
|
||||||
|
_fetchCount = 0;
|
||||||
setState(() {
|
setState(() {
|
||||||
itemName = suggestion['name'];
|
itemName = suggestion['name'];
|
||||||
inputItem.text = itemName;
|
inputItem.text = itemName;
|
||||||
@ -591,6 +675,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
controller: inputTags,
|
controller: inputTags,
|
||||||
labelText: 'Search by tags',
|
labelText: 'Search by tags',
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
_fetchCount = 0;
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
itemTags = value;
|
itemTags = value;
|
||||||
@ -608,6 +693,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClear: () {
|
onClear: () {
|
||||||
|
_fetchCount = 0;
|
||||||
setState(() {
|
setState(() {
|
||||||
inputTags.clear();
|
inputTags.clear();
|
||||||
});
|
});
|
||||||
@ -615,6 +701,8 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
},
|
},
|
||||||
suggestions: suggestionsTags,
|
suggestions: suggestionsTags,
|
||||||
onSuggestionTap: (suggestion) async {
|
onSuggestionTap: (suggestion) async {
|
||||||
|
_fetchCount = 0;
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
itemTags = suggestion['name'];
|
itemTags = suggestion['name'];
|
||||||
inputTags.text = itemTags;
|
inputTags.text = itemTags;
|
||||||
@ -638,6 +726,8 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
controller: inputGeo,
|
controller: inputGeo,
|
||||||
labelText: 'Search by geographical zone',
|
labelText: 'Search by geographical zone',
|
||||||
onChanged: (value) async {
|
onChanged: (value) async {
|
||||||
|
_fetchCount = 0;
|
||||||
|
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
setState(() {
|
setState(() {
|
||||||
geographicalZone = value;
|
geographicalZone = value;
|
||||||
@ -659,6 +749,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClear: () async {
|
onClear: () async {
|
||||||
|
_fetchCount = 0;
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
prefs.remove("city_lat");
|
prefs.remove("city_lat");
|
||||||
prefs.remove("city_long");
|
prefs.remove("city_long");
|
||||||
@ -674,6 +765,7 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
},
|
},
|
||||||
suggestions: suggestionsGeo,
|
suggestions: suggestionsGeo,
|
||||||
onSuggestionTap: (suggestion) async {
|
onSuggestionTap: (suggestion) async {
|
||||||
|
_fetchCount = 0;
|
||||||
final latitude = suggestion['geometry']['coordinates'][1];
|
final latitude = suggestion['geometry']['coordinates'][1];
|
||||||
final longitude = suggestion['geometry']['coordinates'][0];
|
final longitude = suggestion['geometry']['coordinates'][0];
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -748,15 +840,26 @@ class _MyHomePageState extends State<ListItemMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
itemCount: displayedPosts.length,
|
controller: _scrollController,
|
||||||
|
itemCount: displayedPosts.isNotEmpty
|
||||||
|
? displayedPosts.length +
|
||||||
|
(_isLoading ? 1 : 0) // Add 1 only if loading
|
||||||
|
: 0,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
|
if (index >= displayedPosts.length) {
|
||||||
|
return _isLoading
|
||||||
|
? Center(child: CircularProgressIndicator())
|
||||||
|
: SizedBox.shrink();
|
||||||
|
}
|
||||||
final post = displayedPosts[index];
|
final post = displayedPosts[index];
|
||||||
final startDate = DateTime.parse(post.startDate!);
|
final startDate = DateTime.parse(post.startDate!);
|
||||||
final date = DateFormat.yMd().format(startDate);
|
//final date = DateFormat.yMd().format(startDate);
|
||||||
final time = DateFormat.Hm().format(startDate);
|
//final time = DateFormat.Hm().format(startDate);
|
||||||
|
final dateLongue =
|
||||||
|
DateFormat('EEEE d MMMM y', 'fr_FR').format(startDate);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text('${post.name!}'),
|
title: Text('${post.name!}'),
|
||||||
subtitle: Text('${post.place!}\n${date} ${time}'),
|
subtitle: Text('${post.place!}\n${dateLongue}'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
154
covas_mobile/lib/pages/LoginDemo.dart
Normal file
154
covas_mobile/lib/pages/LoginDemo.dart
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
import '../pages/ListItemMenu.dart';
|
||||||
|
import '../pages/AddProfile.dart';
|
||||||
|
import '../pages/ForgotPassword.dart';
|
||||||
|
import '../classes/alert.dart';
|
||||||
|
import '../classes/ad_helper.dart';
|
||||||
|
|
||||||
|
class LoginDemo extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_LoginDemoState createState() => _LoginDemoState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginDemoState extends State<LoginDemo> with ShowAlertDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
TextEditingController inputPseudo = TextEditingController();
|
||||||
|
TextEditingController inputPassword = TextEditingController();
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
bool _rememberMe = false;
|
||||||
|
|
||||||
|
Future<void> _login(BuildContext context) async {
|
||||||
|
final pseudo = inputPseudo.text;
|
||||||
|
final password = inputPassword.text;
|
||||||
|
|
||||||
|
if (pseudo.isEmpty || password.isEmpty) {
|
||||||
|
showAlertDialog(context, "Erreur", "Champ vide");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success =
|
||||||
|
await _authService.login(pseudo, password, rememberMe: _rememberMe);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
Navigator.push(
|
||||||
|
context, MaterialPageRoute(builder: (_) => ListItemMenu()));
|
||||||
|
} else {
|
||||||
|
showAlertDialog(context, "Erreur", "Échec de l'authentification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
_checkLocationPermission();
|
||||||
|
_checkLoginStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _checkLoginStatus() async {
|
||||||
|
bool loggedIn = await _authService.isLoggedIn();
|
||||||
|
if (loggedIn) {
|
||||||
|
Navigator.push(
|
||||||
|
context, MaterialPageRoute(builder: (_) => ListItemMenu()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _checkLocationPermission() async {
|
||||||
|
PermissionStatus status = await Permission.location.status;
|
||||||
|
if (!status.isGranted) {
|
||||||
|
await Permission.location.request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text("Login Page"),
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
child: TextField(
|
||||||
|
controller: inputPseudo,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelText: 'Pseudo',
|
||||||
|
hintText: 'Enter pseudo existant',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||||
|
child: TextField(
|
||||||
|
controller: inputPassword,
|
||||||
|
obscureText: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelText: 'Password',
|
||||||
|
hintText: 'Enter secure password',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CheckboxListTile(
|
||||||
|
title: Text("Se souvenir de moi"),
|
||||||
|
value: _rememberMe,
|
||||||
|
onChanged: (newValue) {
|
||||||
|
setState(() {
|
||||||
|
_rememberMe = newValue ?? false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(context,
|
||||||
|
MaterialPageRoute(builder: (_) => PasswordForgot()));
|
||||||
|
},
|
||||||
|
child: Text('Forgot Password',
|
||||||
|
style: TextStyle(color: Colors.blue, fontSize: 15)),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 50,
|
||||||
|
width: 250,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.blue, borderRadius: BorderRadius.circular(20)),
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: () => _login(context),
|
||||||
|
child: Text('Login',
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 25)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 130),
|
||||||
|
InkWell(
|
||||||
|
child: Text('New User? Create Account'),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context, MaterialPageRoute(builder: (_) => AddProfile()));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import 'package:geolocator/geolocator.dart'; // For getting the user's location
|
|||||||
import '../classes/alert.dart'; // Assuming this contains your error dialog code.
|
import '../classes/alert.dart'; // Assuming this contains your error dialog code.
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
import '../classes/MyDrawer.dart';
|
import '../classes/MyDrawer.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
await dotenv.load(fileName: ".env"); // Load .env file
|
await dotenv.load(fileName: ".env"); // Load .env file
|
||||||
@ -44,6 +45,8 @@ class MapboxPages extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
|
class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
late MapboxMapController mapController;
|
late MapboxMapController mapController;
|
||||||
late String mapboxAccessToken;
|
late String mapboxAccessToken;
|
||||||
List<LatLng> routeCoordinates = [];
|
List<LatLng> routeCoordinates = [];
|
||||||
@ -58,6 +61,8 @@ class _MapboxPagesState extends State<MapboxPages> with ShowAlertDialog {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
_getUserLocation();
|
_getUserLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,13 @@ import '../classes/eventAdded.dart';
|
|||||||
|
|
||||||
import '../variable/globals.dart' as globals;
|
import '../variable/globals.dart' as globals;
|
||||||
|
|
||||||
void main() {
|
import '../classes/ad_helper.dart';
|
||||||
|
import 'package:google_mobile_ads/google_mobile_ads.dart';
|
||||||
|
import '../classes/auth_service.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await MobileAds.instance.initialize();
|
||||||
runApp(MyApp());
|
runApp(MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +51,9 @@ class UpdateeventImage extends StatefulWidget {
|
|||||||
|
|
||||||
class _UpdateeventImageState extends State<UpdateeventImage>
|
class _UpdateeventImageState extends State<UpdateeventImage>
|
||||||
with ShowAlertDialog, ShowEventDialog {
|
with ShowAlertDialog, ShowEventDialog {
|
||||||
|
BannerAd? _bannerAd;
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
TextEditingController inputName = TextEditingController();
|
TextEditingController inputName = TextEditingController();
|
||||||
|
|
||||||
TextEditingController inputDate = TextEditingController();
|
TextEditingController inputDate = TextEditingController();
|
||||||
@ -308,8 +317,15 @@ class _UpdateeventImageState extends State<UpdateeventImage>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
start();
|
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_authService.checkTokenStatus(context);
|
||||||
|
|
||||||
|
AdHelper.createBannerAd(() => setState(() {})).then((ad) {
|
||||||
|
setState(() {
|
||||||
|
_bannerAd = ad;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
@ -426,6 +442,12 @@ class _UpdateeventImageState extends State<UpdateeventImage>
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
_bannerAd == null
|
||||||
|
? SizedBox.shrink()
|
||||||
|
: SizedBox(
|
||||||
|
height: _bannerAd!.size.height.toDouble(),
|
||||||
|
width: _bannerAd!.size.width.toDouble(),
|
||||||
|
child: AdWidget(ad: _bannerAd!)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 60.0),
|
padding: const EdgeInsets.only(top: 60.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -10,6 +10,7 @@ import geolocator_apple
|
|||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
import webview_flutter_wkwebview
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
@ -17,4 +18,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
|
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin"))
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.1"
|
version: "3.6.1"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.0"
|
||||||
|
asn1lib:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: asn1lib
|
||||||
|
sha256: "4bae5ae63e6d6dd17c4aac8086f3dec26c0236f6a0f03416c6c19d830c367cf5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.8"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -89,6 +105,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.2"
|
||||||
cross_file:
|
cross_file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -137,6 +161,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
encrypt:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: encrypt
|
||||||
|
sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.3"
|
||||||
|
encrypt_shared_preferences:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: encrypt_shared_preferences
|
||||||
|
sha256: "35cd218e5e9d12fe4a63a545f46f2144d861909e4c4f2c4606fc75ffb53d9a46"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.8"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -230,6 +270,11 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
flutter_localizations:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -304,6 +349,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.3"
|
version: "0.2.3"
|
||||||
|
google_mobile_ads:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_mobile_ads
|
||||||
|
sha256: "0d4a3744b5e8ed1b8be6a1b452d309f811688855a497c6113fc4400f922db603"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.3.1"
|
||||||
http:
|
http:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -640,6 +693,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
version: "2.1.8"
|
||||||
|
pointycastle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: pointycastle
|
||||||
|
sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.9.1"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -877,6 +938,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
webview_flutter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter
|
||||||
|
sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.10.0"
|
||||||
|
webview_flutter_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_android
|
||||||
|
sha256: "512c26ccc5b8a571fd5d13ec994b7509f142ff6faf85835e243dde3538fdc713"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.3.2"
|
||||||
|
webview_flutter_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_platform_interface
|
||||||
|
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.10.0"
|
||||||
|
webview_flutter_wkwebview:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_wkwebview
|
||||||
|
sha256: d183aa3d0fbc1f4d0715ce06c5a44cad636598c3340ae8d359fbc61b4016fb60
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.18.3"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -29,6 +29,9 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
@ -50,6 +53,8 @@ dependencies:
|
|||||||
permission_handler: ^11.3.1
|
permission_handler: ^11.3.1
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
mapbox_gl: ^0.16.0
|
mapbox_gl: ^0.16.0
|
||||||
|
google_mobile_ads: ^5.3.1
|
||||||
|
encrypt_shared_preferences: ^0.8.8
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -67,6 +72,7 @@ dev_dependencies:
|
|||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
# The following section is specific to Flutter packages.
|
||||||
flutter:
|
flutter:
|
||||||
|
generate: true
|
||||||
|
|
||||||
# The following line ensures that the Material Icons font is
|
# The following line ensures that the Material Icons font is
|
||||||
# included with your application, so that you can use the icons in
|
# included with your application, so that you can use the icons in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user