This repository has been archived by the owner on Nov 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
239ce81
commit 1d38008
Showing
18 changed files
with
500 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# 🚀 Overview | ||
<img style="float: right; height: 300px" src="docs/app_preview_mockup.png"> | ||
This Flutter app is designed for the Enterprise Software Development (ESD) workshop to introduce the basics of Flutter and Dart programming. The app, titled "My Favorite Things", allows users to create a list of their favorite items, view details, and add new items. It demonstrates fundamental Flutter concepts like navigation, state management, and UI design. | ||
|
||
# 🛠️ Task | ||
For the interactive part of the workshop you can clone this repo on [Flutlab.io](https://flutlab.io) and try to understand or even extend the functionalities. This is your playground to be creative. | ||
The app is designed for ease of understanding and feature richness, rather than strict adherence to best practices. | ||
|
||
## 💡 Ideas | ||
Feel free to explore any additions or modifications you desire. If you're looking for inspiration, here are some suggestions: | ||
- **Shopping List Transformation:** 🛒 Convert the app into a shopping list. Implement features like item deletion, marking items as purchased, and sorting by priority or categories. | ||
- **Personal Diary:** 📔 Turn it into a personal diary or journal app. Introduce features to add entries with dates, edit entries, and perhaps include mood icons or weather. | ||
- **Task Manager:** 📋 Morph it into a task management app. Add functionalities for setting deadlines, reminders, categorizing tasks, and marking them as complete. | ||
- **Photo Album:** 📸 Convert the app into a photo album. Allow users to add photos, captions, and organize them into albums or by dates. | ||
- **Recipe Book:** 🍳 Transform it into a recipe book where users can add, view, and categorize recipes. Include features for ingredients, cooking steps, and preparation time. | ||
|
||
# 📖 Explanation | ||
|
||
## 🌈 Functionalities | ||
- **List Display:** 📝 The home screen shows a list of favorite items. | ||
- **Navigation:** 🚦 Users can navigate between the home screen, details screen, and add item screen. | ||
- **Add New Item:** ➕ Users can add new items to the list which will be displayed on the home screen. | ||
- **View Details:** 🔍 Users can view more details about an item by tapping on it. | ||
|
||
## 📁 File Structure | ||
The project is organized into several directories for clarity and maintainability: | ||
|
||
<pre> | ||
lib/ | ||
├── main.dart # The entry point of the application. | ||
├── models/ | ||
│ └── favorite_item.dart # Defines the FavoriteItem class. | ||
├── screens/ | ||
│ ├── home_screen.dart # Home page, displays the list of favorite items. | ||
│ ├── details_screen.dart # Page showing detailed info about a selected item. | ||
│ └── add_item_screen.dart # Page for adding a new favorite item. | ||
└── widgets/ | ||
└── favorite_item_card.dart # Reusable widget for displaying an item in the list. | ||
</pre> | ||
|
||
|
||
## 🔧 Code Structure | ||
<pre> | ||
├── main.dart | ||
│ ▶️ Sets up the MaterialApp | ||
│ ▶️ Defines routes | ||
│ ▶️ Applies the app theme | ||
│ | ||
├── models/ | ||
│ └── favorite_item.dart | ||
│ ▶️ Contains the model for favorite items | ||
│ | ||
├── screens/ | ||
│ ├── home_screen.dart | ||
│ │ ▶️ Displays a list of items using ListView.builder | ||
│ │ ▶️ Implements navigation to the details and add item screens | ||
│ │ | ||
│ ├── details_screen.dart | ||
│ │ ▶️ Shows details of a selected item, passed through navigation | ||
│ │ | ||
│ └── add_item_screen.dart | ||
│ ▶️ Contains a form to add new items and passes them back to the home screen | ||
│ | ||
└── widgets/ | ||
└── favorite_item_card.dart | ||
▶️ Custom widget to display each item in a card format | ||
</pre> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# This file configures the analyzer, which statically analyzes Dart code to | ||
# check for errors, warnings, and lints. | ||
# | ||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled | ||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be | ||
# invoked from the command line by running `flutter analyze`. | ||
|
||
# The following line activates a set of recommended lints for Flutter apps, | ||
# packages, and plugins designed to encourage good coding practices. | ||
include: package:flutter_lints/flutter.yaml | ||
|
||
linter: | ||
# The lint rules applied to this project can be customized in the | ||
# section below to disable rules from the `package:flutter_lints/flutter.yaml` | ||
# included above or to enable additional rules. A list of all available lints | ||
# and their documentation is published at | ||
# https://dart-lang.github.io/linter/lints/index.html. | ||
# | ||
# Instead of disabling a lint rule for the entire project in the | ||
# section below, it can also be suppressed for a single line of code | ||
# or a specific dart file by using the `// ignore: name_of_lint` and | ||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file | ||
# producing the lint. | ||
rules: | ||
# avoid_print: false # Uncomment to disable the `avoid_print` rule | ||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule | ||
|
||
# Additional information about this file can be found at | ||
# https://dart.dev/guides/language/analysis-options |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'screens/home_screen.dart'; | ||
import 'screens/details_screen.dart'; | ||
import 'screens/add_item_screen.dart'; | ||
import 'models/favorite_item.dart'; | ||
|
||
void main() { | ||
runApp(const MyApp()); | ||
} | ||
|
||
class MyApp extends StatelessWidget { | ||
const MyApp({Key? key}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialApp( | ||
title: 'My Favorite Things', | ||
theme: ThemeData(primarySwatch: Colors.deepPurple), | ||
home: const HomeScreen(), | ||
// Static routes | ||
routes: { | ||
HomeScreen.routeName: (context) => const HomeScreen(), | ||
AddItemScreen.routeName: (context) => const AddItemScreen(), | ||
}, | ||
// Routes with args | ||
onGenerateRoute: (settings) { | ||
if (settings.name == DetailsScreen.routeName) { | ||
final args = settings.arguments as FavoriteItem; | ||
return MaterialPageRoute( | ||
builder: (context) { | ||
return DetailsScreen(item: args); | ||
}, | ||
); | ||
} | ||
assert(false, 'Need to implement ${settings.name}'); | ||
return null; | ||
}, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class FavoriteItem { | ||
String title; | ||
String description; | ||
|
||
FavoriteItem({required this.title, this.description = ''}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import 'package:app/models/favorite_item.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class AddItemScreen extends StatefulWidget { | ||
static const routeName = "/addItemScreen"; | ||
|
||
const AddItemScreen({Key? key}) : super(key: key); | ||
|
||
@override | ||
State<AddItemScreen> createState() => _AddItemScreenState(); | ||
} | ||
|
||
class _AddItemScreenState extends State<AddItemScreen> { | ||
final _formKey = GlobalKey<FormState>(); | ||
final _titleController = TextEditingController(); | ||
final _descriptionController = TextEditingController(); | ||
|
||
void _saveItem() { | ||
if (_formKey.currentState!.validate()) { | ||
final newItem = FavoriteItem( | ||
title: _titleController.text, | ||
description: _descriptionController.text, | ||
); | ||
|
||
// Pop the screen and pass back the new item | ||
Navigator.of(context).pop(newItem); | ||
} | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Text('Add a New Favorite Thing'), | ||
), | ||
body: Form( | ||
key: _formKey, | ||
child: Padding( | ||
padding: const EdgeInsets.all(16.0), | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.stretch, | ||
children: [ | ||
TextFormField( | ||
controller: _titleController, | ||
decoration: const InputDecoration(labelText: 'Title'), | ||
validator: (value) { | ||
if (value == null || value.isEmpty) { | ||
return 'Please enter a title'; | ||
} | ||
return null; | ||
}, | ||
), | ||
TextFormField( | ||
controller: _descriptionController, | ||
decoration: const InputDecoration(labelText: 'Description'), | ||
), | ||
ElevatedButton( | ||
onPressed: _saveItem, | ||
child: const Text('Save'), | ||
), | ||
], | ||
), | ||
), | ||
), | ||
); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
// Clean up the controller when the widget is disposed. | ||
_titleController.dispose(); | ||
_descriptionController.dispose(); | ||
super.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import 'package:app/models/favorite_item.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class DetailsScreen extends StatelessWidget { | ||
static const routeName = "/detailsScreen"; | ||
final FavoriteItem item; | ||
|
||
const DetailsScreen({Key? key, required this.item}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: Text(item.title), | ||
), | ||
body: Padding( | ||
padding: const EdgeInsets.all(16.0), | ||
child: Text(item.description), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import 'package:app/models/favorite_item.dart'; | ||
import 'package:app/screens/add_item_screen.dart'; | ||
import 'package:app/widgets/favorite_item_card.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class HomeScreen extends StatefulWidget { | ||
static const routeName = "/homeScreen"; | ||
|
||
const HomeScreen({Key? key}) : super(key: key); | ||
|
||
@override | ||
State<HomeScreen> createState() => _HomeScreenState(); | ||
} | ||
|
||
class _HomeScreenState extends State<HomeScreen> { | ||
final List<FavoriteItem> items = [ | ||
FavoriteItem(title: 'Pizza', description: 'Cheesy and delicious'), | ||
]; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: const Text('My Favorite Things'), | ||
), | ||
body: ListView( | ||
children: [...items.map((e) => FavoriteItemCard(item: e))], | ||
), | ||
floatingActionButton: FloatingActionButton( | ||
onPressed: () async { | ||
// Navigate to AddItemScreen and wait for the result | ||
final result = await Navigator.push( | ||
context, | ||
MaterialPageRoute(builder: (context) => const AddItemScreen()), | ||
); | ||
|
||
// Check if the result is a FavoriteItem and add it to the list | ||
if (result is FavoriteItem) { | ||
setState(() { | ||
items.add(result); | ||
}); | ||
} | ||
}, | ||
child: const Icon(Icons.add), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import 'package:app/models/favorite_item.dart'; | ||
import 'package:app/screens/details_screen.dart'; | ||
import 'package:flutter/material.dart'; | ||
|
||
class FavoriteItemCard extends StatelessWidget { | ||
final FavoriteItem item; | ||
|
||
const FavoriteItemCard({Key? key, required this.item}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return GestureDetector( | ||
onTap: () { | ||
Navigator.pushNamed( | ||
context, | ||
DetailsScreen.routeName, | ||
arguments: item, | ||
); | ||
}, | ||
child: Container( | ||
height: 50, | ||
decoration: BoxDecoration( | ||
color: Theme.of(context).cardColor, | ||
border: Border.all(color: Colors.black12)), | ||
child: Row( | ||
children: [ | ||
Expanded( | ||
child: Container( | ||
margin: const EdgeInsets.symmetric(horizontal: 10), | ||
child: Text(item.title, | ||
style: const TextStyle(fontSize: 25)))), | ||
const Icon(Icons.arrow_right) | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: app | ||
description: Simple example app for the ESD course. | ||
|
||
version: 1.0.0+1 | ||
|
||
environment: | ||
sdk: ">=2.19.0 <4.0.0" | ||
|
||
dependencies: | ||
flutter: | ||
sdk: flutter | ||
|
||
dev_dependencies: | ||
flutter_test: | ||
sdk: flutter | ||
flutter_lints: ^2.0.2 | ||
|
||
flutter: | ||
uses-material-design: true | ||
# assets: | ||
# - images/a_dot_burr.jpeg | ||
# - images/a_dot_ham.jpeg | ||
# fonts: | ||
# - family: Schyler | ||
# fonts: | ||
# - asset: fonts/Schyler-Regular.ttf | ||
# - asset: fonts/Schyler-Italic.ttf | ||
# style: italic | ||
# - family: Trajan Pro | ||
# fonts: | ||
# - asset: fonts/TrajanPro.ttf | ||
# - asset: fonts/TrajanPro_Bold.ttf | ||
# weight: 700 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.