From 8f4d2e2874b1ca923c7c0d10af4affb5632770f8 Mon Sep 17 00:00:00 2001 From: Louismaestre Date: Sun, 24 Dec 2023 17:05:10 -0800 Subject: [PATCH 1/5] [ADD] display containers in the app created in web --- .../lib/pages/container/container_list.dart | 82 ++++++++++++ .../lib/pages/container/container_page.dart | 10 ++ .../lib/pages/container/container_state.dart | 119 ++++++++++++++++++ Application/server/server.js | 18 +-- 4 files changed, 220 insertions(+), 9 deletions(-) create mode 100644 Application/mobile/app_code/lib/pages/container/container_list.dart create mode 100644 Application/mobile/app_code/lib/pages/container/container_page.dart create mode 100644 Application/mobile/app_code/lib/pages/container/container_state.dart diff --git a/Application/mobile/app_code/lib/pages/container/container_list.dart b/Application/mobile/app_code/lib/pages/container/container_list.dart new file mode 100644 index 000000000..5b4403a2e --- /dev/null +++ b/Application/mobile/app_code/lib/pages/container/container_list.dart @@ -0,0 +1,82 @@ +// import 'dart:ffi'; + +import 'package:flutter/material.dart'; + +class ContainerList { + final int? id; + final dynamic? createdAt; + final dynamic? organization; + final int? organizationId; + final dynamic? containerMapping; + final int? price; + + ContainerList({ + required this.id, + required this.createdAt, + required this.organization, + required this.organizationId, + required this.containerMapping, + required this.price, + }); + + factory ContainerList.fromJson(Map json) { + return ContainerList( + id: json['id'], + createdAt: json['createdAt'], + organization: json['organization'], + organizationId: json['organizationId'], + containerMapping: json['containerMapping'], + price: json['price'], + ); + } + Map toMap() { + return { + 'id': id, + 'createdAt': createdAt, + 'organization': organization, + 'organizationId': organizationId, + 'containerMapping': containerMapping, + 'price': price, + }; + } +} + +class ContainerCard extends StatelessWidget { + final ContainerList container; + + const ContainerCard({super.key, required this.container}); + + @override + Widget build(BuildContext context) { + return Container( + height: 120, + margin: EdgeInsets.only(right:25.0, left: 25.0, top: 10.0), // Adjust the padding here + child: Container( + child: Card( + elevation: 5, + shadowColor: Colors.blueAccent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + child: Column( + children: [ + ListTile( + title: Text(container.id.toString()), + // subtitle: Text(container.price.toString()), + leading: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 10, + ), + Text("name"), + ], + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/Application/mobile/app_code/lib/pages/container/container_page.dart b/Application/mobile/app_code/lib/pages/container/container_page.dart new file mode 100644 index 000000000..1f13d5979 --- /dev/null +++ b/Application/mobile/app_code/lib/pages/container/container_page.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +import 'container_state.dart'; + +class ContainerPage extends StatefulWidget { + const ContainerPage({Key? key}) : super(key: key); + + @override + State createState() => ContainerPageState(); +} \ No newline at end of file diff --git a/Application/mobile/app_code/lib/pages/container/container_state.dart b/Application/mobile/app_code/lib/pages/container/container_state.dart new file mode 100644 index 000000000..249df62aa --- /dev/null +++ b/Application/mobile/app_code/lib/pages/container/container_state.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:risu/components/alert_dialog.dart'; +import 'package:risu/components/appbar.dart'; +import 'package:risu/components/bottomnavbar.dart'; +import 'package:risu/globals.dart'; +import 'package:risu/pages/article/list_page.dart'; +import 'package:risu/pages/map/map_page.dart'; +import 'package:risu/pages/profile/profile_page.dart'; +import 'package:risu/utils/check_signin.dart'; +import 'package:risu/utils/theme.dart'; +import 'package:http/http.dart' as http; + +import 'container_page.dart'; +import 'container_list.dart'; +import 'dart:convert'; + +class ContainerPageState extends State { + List containers = []; + + @override + void initState() { + super.initState(); + getLocations(); + } + + void getLocations() async { + print("one passadf"); + try { + final response = await http.get( + Uri.parse('http://$serverIp:3000/api/container/listAll'), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + ); + if (response.statusCode == 200) { + final Map responseData = json.decode(response.body); + final List containersData = responseData["container"]; + setState(() { + containers = containersData.map((data) => ContainerList.fromJson(data)).toList(); + }); + } else { + print('Error getLocations(): ${response.statusCode}'); + } + } catch (e) { + print('Error getLocations(): $e'); + } + } + + // Future fetchContainers() async { + // print("je passe la"); + // final response = + // await http.get(Uri.parse('http://localhost:3000/api/container/listAll')); + // if (response.statusCode == 200) { + // final Map responseData = json.decode(response.body); + // final List containersData = responseData["container"]; + // setState(() { + // containers = containersData.map((data) => ContainerList.fromJson(data)).toList(); + // }); + // } else { + // // Fluttertoast.showToast( + // // msg: 'Erreur lors de la récupération: ${response.statusCode}', + // // toastLength: Toast.LENGTH_SHORT, + // // gravity: ToastGravity.CENTER, + // // ); + // } + // } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: MyAppBar( + curveColor: context.select((ThemeProvider themeProvider) => + themeProvider.currentTheme.secondaryHeaderColor), + showBackButton: false, + showLogo: true, + showBurgerMenu: false, + ), + body: SingleChildScrollView( + child: Center( + child: Container( + margin: EdgeInsets.only( + left: 10.0, right: 10.0, top: 20.0, bottom: 20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 30), + Text( + 'Liste des conteneurs', + style: TextStyle( + fontSize: 36, + fontWeight: FontWeight.bold, + color: Color(0xFF4682B4), + ), + ), + SizedBox(height: 30), + Column( + children: [ + ListView.builder( + shrinkWrap: + true, + itemCount: containers.length, + itemBuilder: (context, index) { + final product = containers[index]; + return ContainerCard( + container: product, + ); + }, + ), + ], + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/Application/server/server.js b/Application/server/server.js index c589359cc..afd8ce7b1 100644 --- a/Application/server/server.js +++ b/Application/server/server.js @@ -485,15 +485,15 @@ app.post('/api/user/password', async (req, res) => { } }) -app.get('/api/container/listall', async (req, res) => { - try { - const users = await database.prisma.Containers.findMany() - res.status(200).json(users) - } catch (err) { - console.log(err) - return res.status(400).json('An error occured.') - } -}) +// app.get('/api/container/listall', async (req, res) => { +// try { +// const users = await database.prisma.Containers.findMany() +// res.status(200).json(users) +// } catch (err) { +// console.log(err) +// return res.status(400).json('An error occured.') +// } +// }) app.post('/api/rent/article', async (req, res) => { try { From 45acf200f6d7830a99243b73c1956b37aeb04b52 Mon Sep 17 00:00:00 2001 From: Louismaestre Date: Sun, 24 Dec 2023 17:42:59 -0800 Subject: [PATCH 2/5] [UPDATE] fix code and add test --- .../lib/pages/container/container_list.dart | 4 +- .../lib/pages/container/container_state.dart | 36 +++------- .../mobile/app_code/test/container_test.dart | 69 +++++++++++++++++++ 3 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 Application/mobile/app_code/test/container_test.dart diff --git a/Application/mobile/app_code/lib/pages/container/container_list.dart b/Application/mobile/app_code/lib/pages/container/container_list.dart index 5b4403a2e..5bb150352 100644 --- a/Application/mobile/app_code/lib/pages/container/container_list.dart +++ b/Application/mobile/app_code/lib/pages/container/container_list.dart @@ -1,5 +1,3 @@ -// import 'dart:ffi'; - import 'package:flutter/material.dart'; class ContainerList { @@ -79,4 +77,4 @@ class ContainerCard extends StatelessWidget { ), ); } -} +} \ No newline at end of file diff --git a/Application/mobile/app_code/lib/pages/container/container_state.dart b/Application/mobile/app_code/lib/pages/container/container_state.dart index 249df62aa..41e9da7a8 100644 --- a/Application/mobile/app_code/lib/pages/container/container_state.dart +++ b/Application/mobile/app_code/lib/pages/container/container_state.dart @@ -21,11 +21,10 @@ class ContainerPageState extends State { @override void initState() { super.initState(); - getLocations(); + getContainer(); } - void getLocations() async { - print("one passadf"); + void getContainer() async { try { final response = await http.get( Uri.parse('http://$serverIp:3000/api/container/listAll'), @@ -40,32 +39,13 @@ class ContainerPageState extends State { containers = containersData.map((data) => ContainerList.fromJson(data)).toList(); }); } else { - print('Error getLocations(): ${response.statusCode}'); + print('Error getContainer(): ${response.statusCode}'); } } catch (e) { - print('Error getLocations(): $e'); + print('Error getContainer(): $e'); } } - // Future fetchContainers() async { - // print("je passe la"); - // final response = - // await http.get(Uri.parse('http://localhost:3000/api/container/listAll')); - // if (response.statusCode == 200) { - // final Map responseData = json.decode(response.body); - // final List containersData = responseData["container"]; - // setState(() { - // containers = containersData.map((data) => ContainerList.fromJson(data)).toList(); - // }); - // } else { - // // Fluttertoast.showToast( - // // msg: 'Erreur lors de la récupération: ${response.statusCode}', - // // toastLength: Toast.LENGTH_SHORT, - // // gravity: ToastGravity.CENTER, - // // ); - // } - // } - @override Widget build(BuildContext context) { return Scaffold( @@ -79,13 +59,13 @@ class ContainerPageState extends State { body: SingleChildScrollView( child: Center( child: Container( - margin: EdgeInsets.only( + margin: const EdgeInsets.only( left: 10.0, right: 10.0, top: 20.0, bottom: 20.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(height: 30), - Text( + const SizedBox(height: 30), + const Text( 'Liste des conteneurs', style: TextStyle( fontSize: 36, @@ -93,7 +73,7 @@ class ContainerPageState extends State { color: Color(0xFF4682B4), ), ), - SizedBox(height: 30), + const SizedBox(height: 30), Column( children: [ ListView.builder( diff --git a/Application/mobile/app_code/test/container_test.dart b/Application/mobile/app_code/test/container_test.dart new file mode 100644 index 000000000..f16a3236b --- /dev/null +++ b/Application/mobile/app_code/test/container_test.dart @@ -0,0 +1,69 @@ +import 'dart:ffi'; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:risu/pages/container/container_list.dart'; +import 'package:risu/pages/container/container_page.dart'; +import 'package:provider/provider.dart'; +import 'package:risu/utils/theme.dart'; + +void main() { + testWidgets('ContainerMobilePage displays message details', + (WidgetTester tester) async { + final List containers = []; + containers.add( + ContainerList( + id: 1, + price: 10, + createdAt: null, + organization: null, + organizationId: 2, + containerMapping: null, + ), + ); + + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: Column( + children: [ + ListView.builder( + shrinkWrap: true, + itemCount: containers.length, + itemBuilder: (context, index) { + final product = containers[index]; + return ContainerCard( + container: product, + ); + }, + ), + ], + ), + ), + ), + ); + + // expect(find.text("""), findsOneWidget); + expect(find.text("1"), findsOneWidget); + }); + + testWidgets('ContainerMobileCard displays message details', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: ContainerCard( + container: ContainerList( + id: 1, + price: 10, + createdAt: null, + organization: null, + organizationId: 1, + containerMapping: null, + ), + ), + ), + ); + + expect(find.text("1"), findsOneWidget); + }); +} From 16cfd77104c49a1d6cc8040bae7fdd65131f8dae Mon Sep 17 00:00:00 2001 From: Louismaestre Date: Sun, 24 Dec 2023 17:48:10 -0800 Subject: [PATCH 3/5] [DELETE] useless function in server.js (mobile) --- Application/server/server.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Application/server/server.js b/Application/server/server.js index afd8ce7b1..47d00b81b 100644 --- a/Application/server/server.js +++ b/Application/server/server.js @@ -485,16 +485,6 @@ app.post('/api/user/password', async (req, res) => { } }) -// app.get('/api/container/listall', async (req, res) => { -// try { -// const users = await database.prisma.Containers.findMany() -// res.status(200).json(users) -// } catch (err) { -// console.log(err) -// return res.status(400).json('An error occured.') -// } -// }) - app.post('/api/rent/article', async (req, res) => { try { const token = req.headers.authorization From 2fa4dd72dd6df77b94af2e1609aa8490ba6a087d Mon Sep 17 00:00:00 2001 From: Louismaestre Date: Mon, 1 Jan 2024 15:38:29 -0800 Subject: [PATCH 4/5] [UPDATE] if the call in the back end fail or is empty that put a text : No containers --- .../lib/pages/container/container_state.dart | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/Application/mobile/app_code/lib/pages/container/container_state.dart b/Application/mobile/app_code/lib/pages/container/container_state.dart index 41e9da7a8..26297091a 100644 --- a/Application/mobile/app_code/lib/pages/container/container_state.dart +++ b/Application/mobile/app_code/lib/pages/container/container_state.dart @@ -36,7 +36,9 @@ class ContainerPageState extends State { final Map responseData = json.decode(response.body); final List containersData = responseData["container"]; setState(() { - containers = containersData.map((data) => ContainerList.fromJson(data)).toList(); + containers = containersData + .map((data) => ContainerList.fromJson(data)) + .toList(); }); } else { print('Error getContainer(): ${response.statusCode}'); @@ -76,17 +78,24 @@ class ContainerPageState extends State { const SizedBox(height: 30), Column( children: [ - ListView.builder( - shrinkWrap: - true, - itemCount: containers.length, - itemBuilder: (context, index) { - final product = containers[index]; - return ContainerCard( - container: product, - ); - }, - ), + containers.isEmpty + ? const Text( + 'Aucun conteneur trouvé.', + style: TextStyle( + fontSize: 18, + color: Color(0xFF4682B4), + ), + ) + : ListView.builder( + shrinkWrap: true, + itemCount: containers.length, + itemBuilder: (context, index) { + final product = containers[index]; + return ContainerCard( + container: product, + ); + }, + ), ], ), ], From 89850bdfd5ed5f8ea752d145ff17bd52fae5dd09 Mon Sep 17 00:00:00 2001 From: Louismaestre Date: Tue, 2 Jan 2024 13:54:33 -0800 Subject: [PATCH 5/5] [UPDATE] increase coverage in container --- .../mobile/app_code/test/container_test.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Application/mobile/app_code/test/container_test.dart b/Application/mobile/app_code/test/container_test.dart index f16a3236b..b4fcba022 100644 --- a/Application/mobile/app_code/test/container_test.dart +++ b/Application/mobile/app_code/test/container_test.dart @@ -8,6 +8,25 @@ import 'package:provider/provider.dart'; import 'package:risu/utils/theme.dart'; void main() { + testWidgets('ContainerStat full info', (WidgetTester tester) async { + await tester.pumpWidget( + MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => ThemeProvider(false), + ), + ], + child: const MaterialApp( + home: ContainerPage(), + ), + ), + ); + await tester.pump(); + expect(find.text("Liste des conteneurs"), findsOneWidget); + expect(find.byType(ListView), findsNothing); + + }); + testWidgets('ContainerMobilePage displays message details', (WidgetTester tester) async { final List containers = [];