Skip to content

Commit 0b68e0a

Browse files
CopilotBeelzenef
andcommitted
Improve documentation: README, guide, app/README and Dart docstrings
Co-authored-by: Beelzenef <6389665+Beelzenef@users.noreply.github.com>
1 parent ab1672c commit 0b68e0a

12 files changed

Lines changed: 271 additions & 6 deletions

File tree

README.md

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,38 @@ CoffeeShop app preview:
88

99
![Four screenshots for different screens in the app: product catalog, cart, user profile and order history](./imgs/workshop_preview.png)
1010

11-
## Requirements:
12-
13-
### Required:
11+
## What you'll learn
12+
13+
By completing this workshop you will be able to:
14+
15+
- Create a multi-screen Flutter app using `BottomNavigationBar`
16+
- Build common UI layouts with widgets such as `Column`, `ListView`, `ListTile`, `Card`, and `CircleAvatar`
17+
- Navigate between pages (both tab-based and stack-based with `Navigator.push`)
18+
- Define simple Dart data models (classes with named constructors)
19+
- Manage shared app state without an external library
20+
- Use hot-reload to see live changes during development
21+
22+
## Project structure
23+
24+
```
25+
app/
26+
└── lib/
27+
├── main.dart # App entry point and bottom-navigation host
28+
├── coffee_manager.dart # Lightweight in-memory state container
29+
├── models/
30+
│ ├── product.dart # Product data model
31+
│ ├── user.dart # User data model
32+
│ └── order.dart # Order data model
33+
└── pages/
34+
├── catalog.dart # Product listing screen
35+
├── cart.dart # Shopping cart screen
36+
├── profile.dart # User profile screen
37+
└── orders.dart # Order history screen
38+
```
39+
40+
## Requirements
41+
42+
### Required
1443

1544
- Bring Your Own Device (BYOD)
1645
- Basic/medium programming knowledge
@@ -30,7 +59,30 @@ To choose:
3059
- Android emulator device
3160
- Physical device (developer mode and USB debugging enabled)
3261

33-
## About code:
62+
## Running the app
63+
64+
```bash
65+
# Navigate to the app directory
66+
cd app
67+
68+
# Fetch dependencies
69+
flutter pub get
70+
71+
# Run on a connected device or emulator
72+
flutter run
73+
```
74+
75+
To add support for additional platforms:
76+
77+
```bash
78+
# Web
79+
flutter create --platforms=web .
80+
81+
# Linux
82+
flutter create --platforms=linux .
83+
```
84+
85+
## About the code
3486

3587
No state management libraries/tools/engines are used.
3688

@@ -46,6 +98,11 @@ This workshop focuses on the development of UI, to learn the basics of Flutter,
4698

4799
Clone this repo and checkout to [`workshop`](https://github.com/Beelzenef/workshop_flutter/tree/workshop) branch.
48100

101+
> 💡 Don't want to use Git? Download the starter project directly from
102+
> [download-directory.github.io](https://download-directory.github.io/?url=https%3A%2F%2Fgithub.com%2Fzelonware%2Fworkshop_flutter%2Ftree%2Fworkshop%2Fapp).
103+
104+
For a detailed step-by-step guide see [`docs/guide.md`](./docs/guide.md).
105+
49106
## More info
50107

51108
General:

app/README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
11
# coffee_shop
22

3-
A new Flutter app!
3+
# CoffeeShop – Flutter Workshop App
4+
5+
A beginner-friendly Flutter application built during a hands-on workshop. It demonstrates core Flutter concepts including multi-screen navigation, stateful widgets, and simple in-memory state management.
6+
7+
## Getting started
8+
9+
```bash
10+
flutter pub get
11+
flutter run
12+
```
13+
14+
See the [root README](../README.md) and [workshop guide](../docs/guide.md) for full setup instructions and the step-by-step workshop walkthrough.

app/lib/coffee_manager.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,39 @@ import 'package:coffee_shop/models/order.dart';
22
import 'package:coffee_shop/models/product.dart';
33
import 'package:coffee_shop/models/user.dart';
44

5+
/// Lightweight in-memory state container for the CoffeeShop app.
6+
///
7+
/// [CoffeeManager] holds all mutable application data – the current user,
8+
/// the shopping cart, and the order history – and exposes simple methods to
9+
/// manipulate that data. A single instance is created in [CoffeeShopApp] and
10+
/// shared across all pages through the static [CoffeeShopApp.manager] accessor.
11+
///
12+
/// > **Note:** This class does **not** use any state management library and
13+
/// > does **not** persist data between app restarts. It is intentionally simple
14+
/// > for workshop / learning purposes.
515
class CoffeeManager {
16+
/// The currently logged-in user. Pre-populated with placeholder data.
617
final User user =
718
User(name: 'Awesome', mail: 'you@awesome.com', phone: '666-666-66');
819

20+
/// Products that have been added to the cart but not yet paid for.
921
final List<Product> productsInCart = [];
22+
23+
/// Completed orders placed during the current session.
1024
final List<Order> orders = [];
1125

26+
/// Running total of all items currently in [productsInCart], in whole
27+
/// currency units. Updated automatically whenever the cart changes.
1228
int total = 0;
1329

30+
/// Adds [product] to the cart and recalculates [total].
1431
void addToCart(Product product) {
1532
productsInCart.add(product);
1633
_calculateTotal();
1734
}
1835

36+
/// Recalculates [total] by summing the prices of all items in [productsInCart].
37+
/// Resets [total] to 0 when the cart is empty.
1938
void _calculateTotal() {
2039
if (productsInCart.isNotEmpty) {
2140
var prices = productsInCart.map((e) => e.price).toList();
@@ -25,6 +44,8 @@ class CoffeeManager {
2544
}
2645
}
2746

47+
/// Converts the current cart into a new [Order], appends it to [orders],
48+
/// and clears the cart. Does nothing if the cart is empty.
2849
void makeOrder() {
2950
if (productsInCart.isNotEmpty) {
3051
int howManyProducts = productsInCart.length;
@@ -37,6 +58,7 @@ class CoffeeManager {
3758
}
3859
}
3960

61+
/// Removes all products from the cart and resets [total] to 0.
4062
void clearCart() {
4163
productsInCart.clear();
4264
_calculateTotal();

app/lib/main.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ void main() {
99
runApp(const CoffeeShopApp());
1010
}
1111

12+
/// Root widget of the CoffeeShop application.
13+
///
14+
/// Configures [MaterialApp] with the app theme and sets [HomePage] as the
15+
/// initial route. A single shared [CoffeeManager] instance is stored here and
16+
/// accessed by child widgets via `CoffeeShopApp.manager`.
1217
class CoffeeShopApp extends StatelessWidget {
1318
const CoffeeShopApp({super.key});
1419

20+
/// Shared state manager accessible from any widget in the tree.
1521
static final manager = CoffeeManager();
1622

1723
@override
@@ -28,18 +34,27 @@ class CoffeeShopApp extends StatelessWidget {
2834
}
2935
}
3036

37+
/// The main scaffold of the app, hosting the [BottomNavigationBar] and
38+
/// switching between the three top-level pages.
3139
class HomePage extends StatefulWidget {
3240
const HomePage({super.key, required this.title});
3341

42+
/// Title displayed in the [AppBar].
3443
final String title;
3544

3645
@override
3746
State<HomePage> createState() => _HomePageState();
3847
}
3948

4049
class _HomePageState extends State<HomePage> {
50+
/// Index of the currently selected bottom-navigation tab.
4151
int index = 0;
4252

53+
/// Returns the page widget that corresponds to the selected [index].
54+
///
55+
/// - 0 → [CatalogPage]
56+
/// - 1 → [CartPage]
57+
/// - 2 → [ProfilePage]
4358
Widget navigateToPage() {
4459
switch (index) {
4560
case 1:

app/lib/models/order.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
/// Represents a completed purchase order.
12
class Order {
3+
/// Creates an [Order] with the number of [products] purchased,
4+
/// the [total] price paid, and the [orderedAt] timestamp.
25
Order({required this.products, required this.total, required this.orderedAt});
36

7+
/// Number of products included in this order.
48
final int products;
9+
10+
/// Total cost of the order in whole currency units.
511
final int total;
12+
13+
/// Date and time at which the order was placed.
614
final DateTime orderedAt;
715
}

app/lib/models/product.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
/// Represents a coffee product available in the catalog.
12
class Product {
3+
/// Creates a [Product] with a [name], [price] in whole currency units,
4+
/// and a [pic] URL (may be empty in the workshop starter).
25
Product({required this.name, required this.price, required this.pic});
36

7+
/// Display name of the product (e.g. "Espresso").
48
final String name;
9+
10+
/// Price of the product in whole currency units (e.g. 2 for €2).
511
final int price;
12+
13+
/// URL or asset path for the product image. May be an empty string.
614
final String pic;
715
}

app/lib/models/user.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
/// Represents the logged-in user of the coffee shop app.
12
class User {
3+
/// Creates a [User] with a display [name], [mail] address and [phone] number.
24
User({required this.name, required this.mail, required this.phone});
35

6+
/// Display name shown in the profile and catalog greeting.
47
final String name;
8+
9+
/// Email address of the user.
510
final String mail;
11+
12+
/// Phone number of the user.
613
final String phone;
714
}

app/lib/pages/cart.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import 'package:coffee_shop/main.dart';
22

33
import 'package:flutter/material.dart';
44

5+
/// Displays the products currently in the shopping cart together with the
6+
/// running total. Provides **PAY** and **REMOVE ORDERS** actions.
7+
///
8+
/// - **PAY** calls [CoffeeManager.makeOrder], which converts the cart into a
9+
/// completed [Order] and clears it.
10+
/// - **REMOVE ORDERS** calls [CoffeeManager.clearCart], discarding all items
11+
/// without creating an order.
512
class CartPage extends StatefulWidget {
613
const CartPage({super.key});
714

app/lib/pages/catalog.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import 'package:coffee_shop/models/product.dart';
33

44
import 'package:flutter/material.dart';
55

6+
/// Displays the list of available coffee products and allows the user to add
7+
/// items to the cart by tapping them.
68
class CatalogPage extends StatefulWidget {
79
const CatalogPage({super.key});
810

@@ -43,6 +45,10 @@ class _CatalogPageState extends State<CatalogPage> {
4345
);
4446
}
4547

48+
/// Builds a single [ListTile] for [p].
49+
///
50+
/// Tapping the tile calls [CoffeeManager.addToCart] and triggers a
51+
/// `setState` so that any UI depending on the cart is rebuilt.
4652
ListTile buildCatalogItem(Product p) {
4753
String price = p.price.toString();
4854

@@ -56,6 +62,7 @@ class _CatalogPageState extends State<CatalogPage> {
5662
);
5763
}
5864

65+
/// Shows a [SnackBar] confirming that a product was added to the cart.
5966
void showToast(BuildContext context) {
6067
final scaffold = ScaffoldMessenger.of(context);
6168
scaffold.showSnackBar(

app/lib/pages/orders.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ import 'package:coffee_shop/models/order.dart';
33
import 'package:flutter/material.dart';
44
import 'package:intl/intl.dart';
55

6+
/// Shows the full list of completed orders for the current session.
7+
///
8+
/// Receives the [orders] list from [ProfilePage] and renders each entry as a
9+
/// coloured card showing the number of products, total cost, and the formatted
10+
/// date/time of the purchase.
611
class OrdersPage extends StatelessWidget {
12+
/// The list of orders to display.
713
final List<Order> orders;
14+
15+
/// Formatter used to display [Order.orderedAt] as `dd-MM-yyyy (HH:mm)`.
816
final DateFormat formatter = DateFormat('dd-MM-yyyy (HH:mm)');
917

1018
OrdersPage({super.key, required this.orders});

0 commit comments

Comments
 (0)