location page

This commit is contained in:
Mikkel Troels Kongsted 2025-02-05 14:38:39 +01:00
parent d669fc50f3
commit 21484b9f8e
6 changed files with 126 additions and 10 deletions

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -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',

View File

@ -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<LocationImageRepo>(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;
}

View File

@ -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<AddToCartStateRepo>();
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);

View File

@ -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<void> load() async {
final ByteData data = await rootBundle.load('assets/floor_plan.png');
final Uint8List list = data.buffer.asUint8List();
final Completer<ui.Image> completer = Completer();
ui.decodeImageFromList(list, (ui.Image img) {
image = img;
notifyListeners();
completer.complete(img);
});
await completer.future;
}
}

View File

@ -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});
}