288 lines
8.6 KiB
Dart
288 lines
8.6 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
import "ItemMenu.dart";
|
|
import "Camera.dart";
|
|
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:flutter/material.dart';
|
|
import '../classes/events.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:intl/date_symbol_data_local.dart';
|
|
import 'package:camera/camera.dart';
|
|
|
|
import '../variable/globals.dart' as globals;
|
|
|
|
// app starting point
|
|
void main() {
|
|
initializeDateFormatting("fr_FR", null).then((_) => (const MyApp()));
|
|
}
|
|
|
|
class MyApp extends StatelessWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
home: const ListItemMenu(),
|
|
debugShowCheckedModeBanner: false,
|
|
);
|
|
}
|
|
}
|
|
|
|
// homepage class
|
|
class ListItemMenu extends StatefulWidget {
|
|
const ListItemMenu({super.key});
|
|
|
|
@override
|
|
State<ListItemMenu> createState() => _MyHomePageState();
|
|
}
|
|
|
|
// homepage state
|
|
class _MyHomePageState extends State<ListItemMenu> {
|
|
// variable to call and store future list of posts
|
|
Future<List<Events>> postsFuture = getPosts();
|
|
List<Events> filteredPosts = [];
|
|
late SearchBar searchBar;
|
|
|
|
String geographicalZone = '';
|
|
String query = '';
|
|
|
|
// function to fetch data from api and return future list of posts
|
|
static Future<List<Events>> getPosts() async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
var accessToken = prefs.getString("access_token") ?? "";
|
|
final List<Events> body = [];
|
|
if (accessToken.isNotEmpty) {
|
|
var url = Uri.parse("${globals.api}/events");
|
|
final response = await http.get(url, headers: {
|
|
"Content-Type": "application/json",
|
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
|
});
|
|
final List body = json.decode(utf8.decode(response.bodyBytes));
|
|
return body.map((e) => Events.fromJson(e)).toList();
|
|
}
|
|
return body;
|
|
}
|
|
|
|
Future<List<Events>> searchPosts(String query) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
var accessToken = prefs.getString("access_token") ?? "";
|
|
final List<Events> body = [];
|
|
if (accessToken.isNotEmpty) {
|
|
var url = Uri.parse("${globals.api}/events/search?item=$query");
|
|
final response = await http.get(url, headers: {
|
|
"Content-Type": "application/json",
|
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
|
});
|
|
final List body = json.decode(utf8.decode(response.bodyBytes));
|
|
return body.map((e) => Events.fromJson(e)).toList();
|
|
}
|
|
return body;
|
|
}
|
|
|
|
Future<void> popCamera() async {
|
|
await availableCameras().then((value) => Navigator.push(context,
|
|
MaterialPageRoute(builder: (_) => Camera(camera: value.first))));
|
|
}
|
|
|
|
void _filterPosts() async {
|
|
if (query.isNotEmpty || geographicalZone.isNotEmpty) {
|
|
List<Events> results = await searchPosts(query);
|
|
setState(() {
|
|
filteredPosts = _applyFilters(results);
|
|
});
|
|
} else {
|
|
setState(() {
|
|
filteredPosts.clear();
|
|
});
|
|
}
|
|
}
|
|
|
|
List<Events> _applyFilters(List<Events> posts) {
|
|
return posts.where((post) {
|
|
final matchesQuery =
|
|
post.name!.toLowerCase().contains(query.toLowerCase());
|
|
final matchesZone = geographicalZone.isEmpty ||
|
|
post.place!.toLowerCase().contains(geographicalZone.toLowerCase());
|
|
return matchesQuery && matchesZone;
|
|
}).toList();
|
|
}
|
|
|
|
// build function
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text("Item list menu"),
|
|
backgroundColor: Colors.blue,
|
|
foregroundColor: Colors.white,
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.search),
|
|
onPressed: () {
|
|
showSearch(
|
|
context: context,
|
|
delegate: SearchDelegateExample(),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
body: Column(
|
|
children: [
|
|
// New Search Bar for Geographical Zone
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: TextField(
|
|
decoration: InputDecoration(
|
|
labelText: 'Search by geographical zone',
|
|
border: OutlineInputBorder(),
|
|
),
|
|
onChanged: (value) {
|
|
setState(() {
|
|
geographicalZone = value;
|
|
});
|
|
_filterPosts(); // Call the filtering function
|
|
},
|
|
),
|
|
),
|
|
Expanded(
|
|
child: FutureBuilder<List<Events>>(
|
|
future: postsFuture,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const CircularProgressIndicator();
|
|
} else if (snapshot.hasData) {
|
|
final posts = snapshot.data!;
|
|
final displayedPosts =
|
|
filteredPosts.isEmpty ? posts : filteredPosts;
|
|
return buildPosts(displayedPosts);
|
|
} else {
|
|
return const Text("No data available");
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
// function to display fetched data on screen
|
|
Widget buildPosts(List<Events> posts) {
|
|
// ListView Builder to show data in a list
|
|
return Scaffold(
|
|
body: ListView.separated(
|
|
itemCount: posts.length,
|
|
itemBuilder: (context, index) {
|
|
final post = posts[index];
|
|
final startDate = DateTime.parse(post.startDate!);
|
|
final date = DateFormat.yMd().format(startDate);
|
|
final time = DateFormat.Hm().format(startDate);
|
|
|
|
return ListTile(
|
|
title: Text('${post.name!}'),
|
|
subtitle: Text('${post.place!}\n${date} ${time}'),
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => ItemMenu(title: post.id!)));
|
|
});
|
|
},
|
|
separatorBuilder: (context, index) {
|
|
return Divider();
|
|
},
|
|
),
|
|
floatingActionButton: FloatingActionButton(
|
|
onPressed: popCamera,
|
|
backgroundColor: Colors.blue,
|
|
tooltip: 'Recherche',
|
|
child: const Icon(Icons.camera_alt, color: Colors.white),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class SearchDelegateExample extends SearchDelegate {
|
|
@override
|
|
List<Widget> buildActions(BuildContext context) {
|
|
return [
|
|
IconButton(
|
|
icon: const Icon(Icons.clear),
|
|
onPressed: () {
|
|
query = '';
|
|
},
|
|
),
|
|
];
|
|
}
|
|
|
|
@override
|
|
Widget buildLeading(BuildContext context) {
|
|
return IconButton(
|
|
icon: const Icon(Icons.arrow_back),
|
|
onPressed: () {
|
|
close(context, null);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget buildResults(BuildContext context) {
|
|
// Perform the search and return the results
|
|
return FutureBuilder<List<Events>>(
|
|
future: searchPosts(query),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
} else if (snapshot.hasData) {
|
|
final posts = snapshot.data!;
|
|
return ListView.builder(
|
|
itemCount: posts.length,
|
|
itemBuilder: (context, index) {
|
|
final post = posts[index];
|
|
return ListTile(
|
|
title: Text(post.name!),
|
|
subtitle: Text(post.place!),
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => ItemMenu(title: post.id!),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
} else {
|
|
return const Center(child: Text("No results found"));
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget buildSuggestions(BuildContext context) {
|
|
// Show suggestions as the user types
|
|
return Container(); // Implement suggestions if needed
|
|
}
|
|
|
|
Future<List<Events>> searchPosts(String query) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
var accessToken = prefs.getString("access_token") ?? "";
|
|
final List<Events> body = [];
|
|
if (accessToken.isNotEmpty) {
|
|
var url = Uri.parse("${globals.api}/events/search?item=$query");
|
|
final response = await http.get(url, headers: {
|
|
"Content-Type": "application/json",
|
|
HttpHeaders.cookieHeader: "access_token=${accessToken}"
|
|
});
|
|
final List body = json.decode(utf8.decode(response.bodyBytes));
|
|
return body.map((e) => Events.fromJson(e)).toList();
|
|
}
|
|
return body;
|
|
}
|
|
}
|