From 21484b9f8e2b75d4bbe30e0502707c0b32e287c1 Mon Sep 17 00:00:00 2001 From: Mikkel Troels Kongsted Date: Wed, 5 Feb 2025 14:38:39 +0100 Subject: [PATCH] location page --- ...sh_plaza_floor_plan.png => floor_plan.png} | Bin mobile/lib/main.dart | 2 + mobile/lib/pages/product_location_page.dart | 80 ++++++++++++++++++ mobile/lib/pages/product_page.dart | 10 ++- mobile/lib/repos/location_image.dart | 22 +++++ mobile/lib/repos/product.dart | 22 +++-- 6 files changed, 126 insertions(+), 10 deletions(-) rename mobile/assets/{fresh_plaza_floor_plan.png => floor_plan.png} (100%) create mode 100644 mobile/lib/pages/product_location_page.dart create mode 100644 mobile/lib/repos/location_image.dart diff --git a/mobile/assets/fresh_plaza_floor_plan.png b/mobile/assets/floor_plan.png similarity index 100% rename from mobile/assets/fresh_plaza_floor_plan.png rename to mobile/assets/floor_plan.png diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 4cebfda..b9fb5bf 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mobile/repos/add_to_cart_state.dart'; import 'package:mobile/repos/cart.dart'; +import 'package:mobile/repos/location_image.dart'; import 'package:mobile/repos/paying_state.dart'; import 'package:mobile/repos/product.dart'; import 'package:mobile/repos/receipt.dart'; @@ -25,6 +26,7 @@ class MyApp extends StatelessWidget { ChangeNotifierProvider(create: (_) => ReceiptRepo()), ChangeNotifierProvider(create: (_) => PayingStateRepo()), ChangeNotifierProvider(create: (_) => AddToCartStateRepo()), + ChangeNotifierProvider(create: (_) => LocationImageRepo()), ], child: MaterialApp( title: 'Fresh Plaza', diff --git a/mobile/lib/pages/product_location_page.dart b/mobile/lib/pages/product_location_page.dart new file mode 100644 index 0000000..b838c1c --- /dev/null +++ b/mobile/lib/pages/product_location_page.dart @@ -0,0 +1,80 @@ +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:mobile/repos/location_image.dart'; +import 'package:mobile/repos/product.dart'; +import 'package:provider/provider.dart'; + +class ProductLocationPage extends StatelessWidget { + final Product product; + const ProductLocationPage({super.key, required this.product}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Row( + children: [ + const BackButton(), + Text(product.name), + ], + ), + Consumer(builder: (context, locationImage, child) { + locationImage.load(); + if (locationImage.image == null) { + return const CircularProgressIndicator( + color: Colors.blue, + ); + } + if (product.location == null) { + return Text("Lokation af ${product.name} kunne ikke findes"); + } + return LayoutBuilder( + builder: (context, constraints) { + double parentWidth = constraints.maxWidth; + + final image = locationImage.image!; + // Maintain aspect ratio + double imageWidth = image.width.toDouble(); + double imageHeight = image.height.toDouble(); + double scale = (parentWidth / imageWidth).clamp(0.0, 1.0); + + return CustomPaint( + size: Size(imageWidth * scale, imageHeight * scale), + painter: LocationImagePainter( + image: locationImage.image!, + location: product.location!, + scale: scale), + ); + }, + ); + }) + ], + )); + } +} + +class LocationImagePainter extends CustomPainter { + final ui.Image image; + final Coordinate location; + final double scale; + + LocationImagePainter( + {required this.image, required this.location, required this.scale}); + + @override + void paint(Canvas canvas, Size size) { + Paint paint = Paint(); + + canvas.scale(scale, scale); + + canvas.drawImage(image, const Offset(0, 0), paint); + + Paint circlePaint = Paint()..color = Colors.red; + canvas.drawCircle(Offset(location.x, location.y), 50, circlePaint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => true; +} diff --git a/mobile/lib/pages/product_page.dart b/mobile/lib/pages/product_page.dart index 5c67441..6100d07 100644 --- a/mobile/lib/pages/product_page.dart +++ b/mobile/lib/pages/product_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mobile/pages/product_location_page.dart'; import 'package:mobile/repos/add_to_cart_state.dart'; import 'package:mobile/repos/cart.dart'; import 'package:mobile/repos/product.dart'; @@ -16,7 +17,7 @@ class ProductPage extends StatelessWidget { context.watch(); return Scaffold( body: Card( -color: Colors.white, + color: Colors.white, margin: const EdgeInsets.all(10), child: Container( padding: const EdgeInsets.symmetric(vertical: 10), @@ -71,7 +72,12 @@ color: Colors.white, child: Text(product.description), ), PrimaryButton( - onPressed: () {}, child: const Text("Find i butik")), + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => + ProductLocationPage(product: product))); + }, + child: const Text("Find i butik")), PrimaryButton( onPressed: () { final snackBarDuration = const Duration(seconds: 2); diff --git a/mobile/lib/repos/location_image.dart b/mobile/lib/repos/location_image.dart new file mode 100644 index 0000000..9a1113b --- /dev/null +++ b/mobile/lib/repos/location_image.dart @@ -0,0 +1,22 @@ +import 'dart:async'; +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class LocationImageRepo extends ChangeNotifier { + ui.Image? image; + + Future load() async { + final ByteData data = await rootBundle.load('assets/floor_plan.png'); + final Uint8List list = data.buffer.asUint8List(); + + final Completer completer = Completer(); + ui.decodeImageFromList(list, (ui.Image img) { + image = img; + notifyListeners(); + completer.complete(img); + }); + + await completer.future; + } +} diff --git a/mobile/lib/repos/product.dart b/mobile/lib/repos/product.dart index 08db4f0..bf2ad57 100644 --- a/mobile/lib/repos/product.dart +++ b/mobile/lib/repos/product.dart @@ -15,11 +15,6 @@ class ProductRepo extends ChangeNotifier { return products; } - void changePrice(int idx, int price) { - products[idx].price = price; - notifyListeners(); - } - void _addAllProducts() { products = [ Product( @@ -31,7 +26,8 @@ class ProductRepo extends ChangeNotifier { id: _nextId++, name: "Letmælk", price: 13, - description: "Konventionel letmælk med fedtprocent på 1,5%"), + description: "Konventionel letmælk med fedtprocent på 1,5%", + location: Coordinate(x: 1800, y: 100)), Product( id: _nextId++, name: "Frilands Øko Supermælk", @@ -66,14 +62,24 @@ class ProductRepo extends ChangeNotifier { } } +class Coordinate { + final double x; + final double y; + + Coordinate({required this.x, required this.y}); +} + class Product { final int id; final String name; final String description; - int price; + final int price; + final Coordinate? location; + Product( {required this.id, required this.name, required this.price, - required this.description}); + required this.description, + this.location}); }