mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 16:24:07 +02:00
bottom navigation bar and product page
This commit is contained in:
parent
f5d9507427
commit
66a8f6c7aa
@ -21,6 +21,7 @@ linter:
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
prefer_const_constructors: true
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
|
BIN
mobile/assets/Frilands Øko Supermælk.png
Normal file
BIN
mobile/assets/Frilands Øko Supermælk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 625 KiB |
BIN
mobile/assets/Letmælk.png
Normal file
BIN
mobile/assets/Letmælk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
BIN
mobile/assets/Minimælk.png
Normal file
BIN
mobile/assets/Minimælk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
3
mobile/devtools_options.yaml
Normal file
3
mobile/devtools_options.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
114
mobile/lib/all_products_page.dart
Normal file
114
mobile/lib/all_products_page.dart
Normal file
@ -0,0 +1,114 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/product.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'product_page.dart';
|
||||
|
||||
class ProductListItem extends StatelessWidget {
|
||||
final String name;
|
||||
final int price;
|
||||
final String imagePath;
|
||||
final ProductPage productPage;
|
||||
const ProductListItem(
|
||||
{super.key,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.imagePath,
|
||||
required this.productPage});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFFFFFF),
|
||||
border: Border.all(color: const Color(0xFF666666)),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10))),
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Colors.transparent),
|
||||
elevation: WidgetStateProperty.all(0),
|
||||
shape: WidgetStateProperty.all(const RoundedRectangleBorder()),
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
splashFactory: NoSplash.splashFactory),
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => productPage));
|
||||
},
|
||||
child: Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.fromLTRB(10, 10, 0, 10),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
style:
|
||||
const TextStyle(fontSize: 20, color: Colors.black),
|
||||
),
|
||||
Text(
|
||||
"${price.toString()} kr",
|
||||
style:
|
||||
const TextStyle(fontSize: 16, color: Colors.black),
|
||||
)
|
||||
],
|
||||
)),
|
||||
ClipRRect(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(10),
|
||||
bottomRight: Radius.circular(10)),
|
||||
child: Image(
|
||||
image: AssetImage(imagePath),
|
||||
fit: BoxFit.contain,
|
||||
width: 100,
|
||||
))
|
||||
],
|
||||
))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AllProductsPage extends StatelessWidget {
|
||||
const AllProductsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(children: [
|
||||
const Row(
|
||||
children: [
|
||||
BackButton(),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
decoration: InputDecoration(
|
||||
label: Text("Search"),
|
||||
contentPadding: EdgeInsets.only(top: 20))),
|
||||
),
|
||||
],
|
||||
),
|
||||
Consumer<ProductRepo>(builder: (_, productRepo, __) {
|
||||
final products = productRepo.allProducts();
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (_, idx) => ProductListItem(
|
||||
name: products[idx].name,
|
||||
price: products[idx].price,
|
||||
imagePath: "assets/${products[idx].name}.png",
|
||||
productPage: ProductPage(product: products[idx]),
|
||||
),
|
||||
itemCount: products.length,
|
||||
);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
10
mobile/lib/cart_page.dart
Normal file
10
mobile/lib/cart_page.dart
Normal file
@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CartPage extends StatelessWidget {
|
||||
const CartPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold();
|
||||
}
|
||||
}
|
@ -1,98 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'global_components.dart';
|
||||
import 'package:mobile/all_products_page.dart';
|
||||
import 'package:mobile/cart_page.dart';
|
||||
import 'package:mobile/receipts_page.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProductListItem extends StatelessWidget {
|
||||
final String name;
|
||||
final int price;
|
||||
final String imagePath;
|
||||
const ProductListItem(
|
||||
{super.key,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.imagePath});
|
||||
class BottomNavigationBarProvider extends ChangeNotifier {
|
||||
int currentIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.all(10),
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFFFFFFF),
|
||||
border: Border.all(),
|
||||
borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all(Colors.transparent),
|
||||
elevation: WidgetStateProperty.all(0),
|
||||
shape: WidgetStateProperty.all(RoundedRectangleBorder()),
|
||||
padding: WidgetStateProperty.all(EdgeInsets.zero),
|
||||
splashFactory: NoSplash.splashFactory),
|
||||
onPressed: () {},
|
||||
child: Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.fromLTRB(10, 10, 0, 10),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
style: TextStyle(fontSize: 24, color: Colors.black),
|
||||
),
|
||||
Text(
|
||||
"${price.toString()} kr",
|
||||
style: TextStyle(fontSize: 16, color: Colors.black),
|
||||
)
|
||||
],
|
||||
)),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(10),
|
||||
bottomRight: Radius.circular(10)),
|
||||
child:
|
||||
Image(image: AssetImage(imagePath), fit: BoxFit.contain))
|
||||
],
|
||||
))),
|
||||
);
|
||||
void setIndex(int index) {
|
||||
currentIndex = index;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class Dashboard extends StatelessWidget {
|
||||
const Dashboard({super.key});
|
||||
final List<StatelessWidget> pages = [
|
||||
const AllProductsPage(),
|
||||
const CartPage(),
|
||||
const ReceiptsPage(),
|
||||
];
|
||||
|
||||
Dashboard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pageIndexProvider = Provider.of<BottomNavigationBarProvider>(context);
|
||||
int currentIndex = pageIndexProvider.currentIndex;
|
||||
|
||||
return Scaffold(
|
||||
body: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
label: Text("Search"),
|
||||
contentPadding: EdgeInsets.only(top: 20))),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
ProductListItem(
|
||||
name: "idk",
|
||||
price: 12,
|
||||
imagePath: "assets/boykisser.png",
|
||||
),
|
||||
ProductListItem(
|
||||
name: "idk",
|
||||
price: 12,
|
||||
imagePath: "assets/boykisser.png",
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
]),
|
||||
),
|
||||
],
|
||||
));
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
onTap: (index) => pageIndexProvider.setIndex(index),
|
||||
currentIndex: currentIndex,
|
||||
items: <BottomNavigationBarItem>[
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(currentIndex == 0 ? Icons.home : Icons.home_outlined),
|
||||
label: "Home"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(currentIndex == 1
|
||||
? Icons.shopping_cart
|
||||
: Icons.shopping_cart_outlined),
|
||||
label: "Cart"),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(currentIndex == 2
|
||||
? Icons.receipt_long
|
||||
: Icons.receipt_long_outlined),
|
||||
label: "Receipts")
|
||||
],
|
||||
),
|
||||
body: pages[currentIndex],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//Consumer<ProductRepo>(builder: (_, productRepo, __) {
|
||||
// final products = productRepo.allProducts();
|
||||
// return ListView.builder(
|
||||
// shrinkWrap: true,
|
||||
// itemBuilder: (_, idx) => ProductListItem(
|
||||
// name: products[idx].name,
|
||||
// price: products[idx].price,
|
||||
// imagePath: "assets/${products[idx].name}.png",
|
||||
// productPage: ProductPage(product: products[idx]),
|
||||
// ),
|
||||
// itemCount: products.length,
|
||||
// );
|
||||
// })
|
||||
|
@ -22,8 +22,8 @@ class LogInPage extends StatelessWidget {
|
||||
label: "Password", placeholderText: "*********", obscure: true),
|
||||
PrimaryButton(
|
||||
onPressed: () => {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => const Dashboard()))
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => Dashboard()))
|
||||
},
|
||||
child: const Text("Log ind"))
|
||||
],
|
||||
|
@ -1,4 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/dashboard.dart';
|
||||
import 'package:mobile/product.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'landing_page.dart';
|
||||
|
||||
void main() {
|
||||
@ -10,14 +13,20 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Fresh Plaza',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
|
||||
scaffoldBackgroundColor: const Color(0xECF6F0FF),
|
||||
useMaterial3: true,
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => ProductRepo()),
|
||||
ChangeNotifierProvider(create: (_) => BottomNavigationBarProvider())
|
||||
],
|
||||
child: MaterialApp(
|
||||
title: 'Fresh Plaza',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
|
||||
scaffoldBackgroundColor: const Color(0xECF6F0FF),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'Fresh Plaza'),
|
||||
),
|
||||
home: const MyHomePage(title: 'Fresh Plaza'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
43
mobile/lib/product.dart
Normal file
43
mobile/lib/product.dart
Normal file
@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ProductRepo extends ChangeNotifier {
|
||||
final List<Product> _products = [
|
||||
Product(
|
||||
id: 0,
|
||||
name: "Minimælk",
|
||||
price: 12,
|
||||
description: "Konventionel minimælk med fedtprocent på 0,4%"),
|
||||
Product(
|
||||
id: 1,
|
||||
name: "Letmælk",
|
||||
price: 13,
|
||||
description: "Konventionel letmælk med fedtprocent på 1,5%"),
|
||||
Product(
|
||||
id: 2,
|
||||
name: "Frilands Øko Supermælk",
|
||||
price: 20,
|
||||
description:
|
||||
"Økologisk mælk af frilandskøer med fedtprocent på 3,5%. Ikke homogeniseret eller pasteuriseret. Skaber store muskler og styrker knoglerne 💪")
|
||||
];
|
||||
|
||||
List<Product> allProducts() {
|
||||
return _products;
|
||||
}
|
||||
|
||||
void changePrice(int idx, int price) {
|
||||
_products[idx].price = price;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class Product {
|
||||
final int id;
|
||||
final String name;
|
||||
final String description;
|
||||
int price;
|
||||
Product(
|
||||
{required this.id,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.description});
|
||||
}
|
83
mobile/lib/product_page.dart
Normal file
83
mobile/lib/product_page.dart
Normal file
@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/global_components.dart';
|
||||
import 'package:mobile/product.dart';
|
||||
|
||||
class ProductPage extends StatelessWidget {
|
||||
final Product product;
|
||||
|
||||
const ProductPage({super.key, required this.product});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
margin: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
color: const Color(0xFFFFFFFF),
|
||||
border: Border.all(color: const Color(0xFF666666)),
|
||||
),
|
||||
child: Column(children: [
|
||||
Row(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BackButton(),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
product.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${product.price} kr",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
)
|
||||
])
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Image(
|
||||
image: AssetImage("assets/${product.name}.png"),
|
||||
height: 250,
|
||||
fit: BoxFit.fitHeight,
|
||||
),
|
||||
Text(
|
||||
product.name,
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
Text(
|
||||
"${product.price} kr",
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20, bottom: 20),
|
||||
child: Text(product.description),
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () {}, child: const Text("Find i butik")),
|
||||
PrimaryButton(
|
||||
onPressed: () {},
|
||||
child: const Text("Tilføj til indkøbskurv")),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
10
mobile/lib/receipts_page.dart
Normal file
10
mobile/lib/receipts_page.dart
Normal file
@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ReceiptsPage extends StatelessWidget {
|
||||
const ReceiptsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold();
|
||||
}
|
||||
}
|
@ -131,6 +131,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -139,6 +147,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -34,6 +34,7 @@ dependencies:
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.8
|
||||
provider: ^6.1.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
x
Reference in New Issue
Block a user