Skip to content
This repository has been archived by the owner on Nov 13, 2023. It is now read-only.

Commit

Permalink
Added assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas-Lieske committed Nov 12, 2023
1 parent 239ce81 commit 1d38008
Show file tree
Hide file tree
Showing 18 changed files with 500 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.DS_Store
68 changes: 68 additions & 0 deletions assignment/README.md
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>

29 changes: 29 additions & 0 deletions assignment/app/analysis_options.yaml
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
40 changes: 40 additions & 0 deletions assignment/app/lib/main.dart
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;
},
);
}
}
6 changes: 6 additions & 0 deletions assignment/app/lib/models/favorite_item.dart
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 = ''});
}
75 changes: 75 additions & 0 deletions assignment/app/lib/screens/add_item_screen.dart
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();
}
}
22 changes: 22 additions & 0 deletions assignment/app/lib/screens/details_screen.dart
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),
),
);
}
}
48 changes: 48 additions & 0 deletions assignment/app/lib/screens/home_screen.dart
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),
),
);
}
}
38 changes: 38 additions & 0 deletions assignment/app/lib/widgets/favorite_item_card.dart
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)
],
),
),
);
}
}
33 changes: 33 additions & 0 deletions assignment/app/pubspec.yaml
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
Binary file added assignment/app/web/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assignment/app/web/icons/Icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assignment/app/web/icons/Icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assignment/app/web/icons/Icon-maskable-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assignment/app/web/icons/Icon-maskable-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 1d38008

Please sign in to comment.