Menü erstellt
Menü Navigation bereitgestellt Rezept Funktionalität eingebaut Test Anfänge bereitgestellt Readme.md befülltdetached
parent
4d0cc78b88
commit
d1a83c8a9d
|
@ -7,9 +7,11 @@ Ein Bild wie die Applikation aussehen soll findet man unter assets/images mit de
|
||||||
1. Die App soll grundsätzlich im Browser als auch auf Mobilen Endgeräten laufen. (entweder iOS oder Android)
|
1. Die App soll grundsätzlich im Browser als auch auf Mobilen Endgeräten laufen. (entweder iOS oder Android)
|
||||||
2. Es soll möglich sein Rezepte abzuspeichern und neue anzulegen.
|
2. Es soll möglich sein Rezepte abzuspeichern und neue anzulegen.
|
||||||
3. Man soll Bilder für Rezepte hochladen können.
|
3. Man soll Bilder für Rezepte hochladen können.
|
||||||
4. Es soll möglich sein alte handgeschriebene Texte mit Texterkennung auf Bildern zu importieren und zu formatieren.
|
4. Es soll möglich sein alte handgeschriebene Texte Bildern zu importieren.
|
||||||
5. Rezepte sollen beliebig sortiert und ergänzt werden können.
|
5. Rezepte sollen gelöscht werden können.
|
||||||
6. Falls der Umfang der App nicht umfangreich genug sein sollte dann noch die Möglichkeit von anderen Nutzern Rezepte anzuschauen.
|
|
||||||
|
|
||||||
|
6. Bonus: Texterkennung wenn die Packages es auch für Web zulassen.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,5 @@
|
||||||
# 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
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
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.dev/lints.
|
|
||||||
#
|
|
||||||
# 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:
|
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
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ android {
|
||||||
applicationId "com.example.kochkomplize"
|
applicationId "com.example.kochkomplize"
|
||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 21
|
||||||
targetSdkVersion flutter.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "460915828512",
|
||||||
|
"firebase_url": "https://kochkomplize-default-rtdb.europe-west1.firebasedatabase.app",
|
||||||
|
"project_id": "kochkomplize",
|
||||||
|
"storage_bucket": "kochkomplize.appspot.com"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:460915828512:android:73914cecf1d06ff0771945",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.example.kochkomplize"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyBzHwDZscVmyTuyJx9darx_8KkhpiCcNNQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "2"
|
||||||
|
}
|
|
@ -30,4 +30,5 @@
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
</application>
|
</application>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 681 KiB |
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyDn1MhJq7gjUtyFJaewgC425jwJmAVCrDk</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>460915828512</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.example.kochkomplize</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>kochkomplize</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>kochkomplize.appspot.com</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:460915828512:ios:ec4610516aa6bb0d771945</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -45,5 +45,9 @@
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>Wir benötigen Zugriff auf Ihre Fotos, um Bilder auszuwählen.</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Wir benötigen Zugriff auf Ihre Kamera, um Fotos aufzunehmen.</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"file_generated_by": "FlutterFire CLI",
|
||||||
|
"purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
|
||||||
|
"GOOGLE_APP_ID": "1:460915828512:ios:ec4610516aa6bb0d771945",
|
||||||
|
"FIREBASE_PROJECT_ID": "kochkomplize",
|
||||||
|
"GCM_SENDER_ID": "460915828512"
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
// File generated by FlutterFire CLI.
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
|
||||||
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
|
import 'package:flutter/foundation.dart'
|
||||||
|
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
||||||
|
|
||||||
|
class DefaultFirebaseOptions {
|
||||||
|
static FirebaseOptions get currentPlatform {
|
||||||
|
if (kIsWeb) {
|
||||||
|
return web;
|
||||||
|
}
|
||||||
|
switch (defaultTargetPlatform) {
|
||||||
|
case TargetPlatform.android:
|
||||||
|
return android;
|
||||||
|
case TargetPlatform.iOS:
|
||||||
|
return ios;
|
||||||
|
case TargetPlatform.macOS:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for macos - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
case TargetPlatform.windows:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for windows - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
case TargetPlatform.linux:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for linux - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions are not supported for this platform.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const FirebaseOptions web = FirebaseOptions(
|
||||||
|
apiKey: 'AIzaSyAACZYqWGQre2FqeXxC5qid1E0K2yuXD5Q',
|
||||||
|
appId: '1:460915828512:web:4db5d6cfa1e11481771945',
|
||||||
|
messagingSenderId: '460915828512',
|
||||||
|
projectId: 'kochkomplize',
|
||||||
|
authDomain: 'kochkomplize.firebaseapp.com',
|
||||||
|
databaseURL: 'https://kochkomplize-default-rtdb.europe-west1.firebasedatabase.app',
|
||||||
|
storageBucket: 'kochkomplize.appspot.com',
|
||||||
|
measurementId: 'G-0W73YW74KY',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const FirebaseOptions android = FirebaseOptions(
|
||||||
|
apiKey: 'AIzaSyBzHwDZscVmyTuyJx9darx_8KkhpiCcNNQ',
|
||||||
|
appId: '1:460915828512:android:73914cecf1d06ff0771945',
|
||||||
|
messagingSenderId: '460915828512',
|
||||||
|
projectId: 'kochkomplize',
|
||||||
|
databaseURL: 'https://kochkomplize-default-rtdb.europe-west1.firebasedatabase.app',
|
||||||
|
storageBucket: 'kochkomplize.appspot.com',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const FirebaseOptions ios = FirebaseOptions(
|
||||||
|
apiKey: 'AIzaSyDn1MhJq7gjUtyFJaewgC425jwJmAVCrDk',
|
||||||
|
appId: '1:460915828512:ios:ec4610516aa6bb0d771945',
|
||||||
|
messagingSenderId: '460915828512',
|
||||||
|
projectId: 'kochkomplize',
|
||||||
|
databaseURL: 'https://kochkomplize-default-rtdb.europe-west1.firebasedatabase.app',
|
||||||
|
storageBucket: 'kochkomplize.appspot.com',
|
||||||
|
iosBundleId: 'com.example.kochkomplize',
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'menu_content.dart';
|
|
||||||
|
|
||||||
//todo implement logik for image import
|
|
||||||
|
|
||||||
class ImportContent implements MenuContent {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// Hier wird der Inhalt für Menüpunkt 2 erstellt
|
|
||||||
return const Text('Inhalt für Menüpunkt 2 - Import');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,18 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'startpage.dart';
|
||||||
|
import 'recipeformpage.dart';
|
||||||
import 'menu.dart';
|
import 'menu.dart';
|
||||||
import 'menu_content.dart';
|
import 'menu_content.dart';
|
||||||
import 'recipes.dart';
|
import 'recipesoverview.dart';
|
||||||
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
|
import 'firebase_options.dart';
|
||||||
|
|
||||||
|
void main() async {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
await Firebase.initializeApp(
|
||||||
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
);
|
||||||
|
|
||||||
void main() {
|
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,18 +44,32 @@ class MyHomePage extends StatefulWidget {
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
MenuContent? _selectedMenuContent;
|
MenuContent? _selectedMenuContent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedMenuContent = Startpage(); // Initialisiere mit Startseite
|
||||||
|
}
|
||||||
|
|
||||||
void _onMenuItemSelected(String menuItem) {
|
void _onMenuItemSelected(String menuItem) {
|
||||||
setState(() {
|
setState(() {
|
||||||
switch (menuItem) {
|
switch (menuItem) {
|
||||||
case 'Meine Rezepte':
|
case 'Meine Rezepte':
|
||||||
_selectedMenuContent = RecipesContent();
|
_selectedMenuContent = RecipesOverview();
|
||||||
break;
|
break;
|
||||||
|
case 'Startseite':
|
||||||
|
_selectedMenuContent = Startpage();
|
||||||
|
break;
|
||||||
|
// case 'Texterkennung Bild':
|
||||||
|
// _selectedMenuContent = TextScan();
|
||||||
|
// break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _importImage() {
|
void _addRecipe() {
|
||||||
//todo
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(builder: (context) => const Recipeformpage()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -58,11 +81,14 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
),
|
),
|
||||||
drawer: Menu(onMenuItemSelected: _onMenuItemSelected),
|
drawer: Menu(onMenuItemSelected: _onMenuItemSelected),
|
||||||
body: _selectedMenuContent?.build(context) ?? Container(),
|
body: _selectedMenuContent?.build(context) ?? Container(),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: _selectedMenuContent is RecipesOverview
|
||||||
onPressed: _importImage,
|
? FloatingActionButton(
|
||||||
tooltip: 'Import',
|
onPressed: _addRecipe,
|
||||||
|
tooltip: 'Rezept hinzufügen',
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
),
|
)
|
||||||
|
: null, // Kein Button für andere Seiten
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ class Menu extends StatelessWidget {
|
||||||
child: Text('Hauptmenü', style: TextStyle(color: Colors.black, fontSize: 20.0)),
|
child: Text('Hauptmenü', style: TextStyle(color: Colors.black, fontSize: 20.0)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
_buildListTile(context, 'Startseite'),
|
||||||
_buildListTile(context, 'Meine Rezepte'),
|
_buildListTile(context, 'Meine Rezepte'),
|
||||||
_buildListTile(context, 'Rezept importieren'),
|
//_buildListTile(context, 'Rezept importieren'),
|
||||||
_buildListTile(context, 'Texterkennung Bild'),
|
//_buildListTile(context, 'Texterkennung Bild'),
|
||||||
_buildListTile(context, '(Beta) Rezepte finden'),
|
//_buildListTile(context, '(Beta) Rezepte finden'),
|
||||||
// Füge hier weitere ListTiles für zusätzliche Menüpunkte hinzu
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class RecipeDetailPage extends StatelessWidget {
|
|
||||||
final Map<String, dynamic> recipe;
|
|
||||||
|
|
||||||
const RecipeDetailPage({Key? key, required this.recipe}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(recipe["title"]),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Image.network(recipe["image"]),
|
|
||||||
Text(recipe["title"]),
|
|
||||||
// Weitere Details oder Inhalte für die Detailseite
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
// ignore_for_file: use_build_context_synchronously
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
|
||||||
|
class RecipeDetailPage extends StatelessWidget {
|
||||||
|
final String recipeId;
|
||||||
|
|
||||||
|
const RecipeDetailPage({Key? key, required this.recipeId, required Map recipe}) : super(key: key);
|
||||||
|
|
||||||
|
Future<void> _showDeleteDialog(BuildContext context) async {
|
||||||
|
bool confirmDelete = await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Rezept löschen'),
|
||||||
|
content: const Text('Sind Sie sicher, dass Sie dieses Rezept löschen möchten?'),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: const Text('Abbrechen'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: const Text('Löschen'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
) ?? false; // Dialog-Abbruch auch als "Nicht löschen" werten
|
||||||
|
|
||||||
|
if (confirmDelete) {
|
||||||
|
await _deleteRecipe(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _deleteRecipe(BuildContext context) async {
|
||||||
|
DatabaseReference recipeRef = FirebaseDatabase.instance.ref('rezepte/$recipeId');
|
||||||
|
DataSnapshot snapshot = await recipeRef.get();
|
||||||
|
if (snapshot.exists) {
|
||||||
|
Map<dynamic, dynamic> recipe = snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
|
||||||
|
// Lösche die Bilder aus dem Storage, wenn URLs vorhanden sind
|
||||||
|
for (final key in ['bild1', 'bild2', 'bild3']) {
|
||||||
|
final String? imageUrl = recipe[key];
|
||||||
|
if (imageUrl != null && imageUrl.isNotEmpty) {
|
||||||
|
try {
|
||||||
|
await FirebaseStorage.instance.refFromURL(imageUrl).delete();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("Fehler beim Löschen von $imageUrl: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lösche den Rezepteintrag aus der Datenbank
|
||||||
|
await recipeRef.remove();
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Rezept konnte nicht gefunden werden.')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Rezept Details'),
|
||||||
|
),
|
||||||
|
body: FutureBuilder<DataSnapshot>(
|
||||||
|
future: FirebaseDatabase.instance.ref('rezepte/$recipeId').get(),
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<DataSnapshot> snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!snapshot.hasData || snapshot.data?.value == null) {
|
||||||
|
return const Center(child: Text('Rezept nicht gefunden'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var recipeData = snapshot.data!.value as Map<dynamic, dynamic>;
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (recipeData['bild1'] != null)
|
||||||
|
Image.network(recipeData['bild1']),
|
||||||
|
Text(recipeData['titel'] ?? 'Kein Titel', style: Theme.of(context).textTheme.titleLarge),
|
||||||
|
Text(recipeData['beschreibung1'] ?? 'Keine Beschreibung'),
|
||||||
|
Text(recipeData['beschreibung2'] ?? 'Keine Beschreibung'),
|
||||||
|
Text(recipeData['beschreibung3'] ?? 'Keine Beschreibung'),
|
||||||
|
if (recipeData['bild2'] != null && recipeData['bild2'].isNotEmpty)
|
||||||
|
Image.network(recipeData['bild2']),
|
||||||
|
if (recipeData['bild3'] != null && recipeData['bild3'].isNotEmpty)
|
||||||
|
Image.network(recipeData['bild3']),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () => _showDeleteDialog(context),
|
||||||
|
tooltip: 'Löschen',
|
||||||
|
child: const Icon(Icons.delete),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
|
||||||
|
class Recipeformpage extends StatefulWidget {
|
||||||
|
const Recipeformpage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
RecipeformpageState createState() => RecipeformpageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecipeformpageState extends State<Recipeformpage> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
String title = '';
|
||||||
|
String description1 = '';
|
||||||
|
String description2 = '';
|
||||||
|
String description3 = '';
|
||||||
|
String image1 = '';
|
||||||
|
String image2 = '';
|
||||||
|
String image3 = '';
|
||||||
|
|
||||||
|
final ImagePicker _picker = ImagePicker();
|
||||||
|
|
||||||
|
Future<void> _pickAndUploadImage(String fieldName) async {
|
||||||
|
final XFile? pickedFile = await _picker.pickImage(source: ImageSource.gallery);
|
||||||
|
if (pickedFile != null) {
|
||||||
|
// Lese die Datei als Byte-Array ein
|
||||||
|
Uint8List fileBytes = await pickedFile.readAsBytes();
|
||||||
|
String fileName = basename(pickedFile.path);
|
||||||
|
Reference storageRef = FirebaseStorage.instance.ref().child('rezeptbilder/$fileName');
|
||||||
|
|
||||||
|
// Starte den Upload-Prozess
|
||||||
|
UploadTask uploadTask = storageRef.putData(fileBytes);
|
||||||
|
|
||||||
|
// Warte auf das Ende des Uploads
|
||||||
|
await uploadTask.whenComplete(() {});
|
||||||
|
|
||||||
|
// Erhalte die Download-URL
|
||||||
|
String downloadUrl = await storageRef.getDownloadURL();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
// Aktualisiere den entsprechenden Bild-URL-Zustand
|
||||||
|
switch (fieldName) {
|
||||||
|
case 'image1':
|
||||||
|
image1 = downloadUrl;
|
||||||
|
break;
|
||||||
|
case 'image2':
|
||||||
|
image2 = downloadUrl;
|
||||||
|
break;
|
||||||
|
case 'image3':
|
||||||
|
image3 = downloadUrl;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _saveForm(BuildContext context) async {
|
||||||
|
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_formKey.currentState!.save();
|
||||||
|
|
||||||
|
DatabaseReference databaseRef = FirebaseDatabase.instance.ref().child('rezepte');
|
||||||
|
String? rezeptId = databaseRef.push().key; // Eindeutiger Schlüssel für das neue Rezept
|
||||||
|
|
||||||
|
databaseRef.child(rezeptId!).set({
|
||||||
|
'titel': title,
|
||||||
|
'beschreibung1': description1,
|
||||||
|
'beschreibung2': description2,
|
||||||
|
'beschreibung3': description3,
|
||||||
|
'bild1': image1,
|
||||||
|
'bild2': image2,
|
||||||
|
'bild3': image3,
|
||||||
|
});
|
||||||
|
|
||||||
|
Navigator.of(context).pop(); // Schließt das Formular nach dem Speichern
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Neues Rezept"),
|
||||||
|
),
|
||||||
|
body: Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
children: <Widget>[
|
||||||
|
TextFormField(
|
||||||
|
decoration: const InputDecoration(labelText: 'Titel'),
|
||||||
|
onSaved: (value) => title = value ?? '',
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Bitte einen Titel eingeben';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
decoration: const InputDecoration(labelText: 'Zutaten: '),
|
||||||
|
onSaved: (value) => description1 = value ?? '',
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
decoration: const InputDecoration(labelText: 'Anleitung: '),
|
||||||
|
onSaved: (value) => description2 = value ?? '',
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
decoration: const InputDecoration(labelText: 'Anmerkungen: '),
|
||||||
|
onSaved: (value) => description3 = value ?? '',
|
||||||
|
),
|
||||||
|
_imageField('Anzeigebild', 'image1'),
|
||||||
|
_imageField('Handgeschriebenes Rezept', 'image2'),
|
||||||
|
_imageField('Textscan', 'image3'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 16,
|
||||||
|
bottom: 16,
|
||||||
|
child: FloatingActionButton(
|
||||||
|
onPressed: () => _saveForm(context),
|
||||||
|
tooltip: 'Rezept speichern',
|
||||||
|
child: const Icon(Icons.save),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Widget _imageField(String label, String fieldName) {
|
||||||
|
String? imageUrl;
|
||||||
|
switch (fieldName) {
|
||||||
|
case 'image1':
|
||||||
|
imageUrl = image1;
|
||||||
|
break;
|
||||||
|
case 'image2':
|
||||||
|
imageUrl = image2;
|
||||||
|
break;
|
||||||
|
case 'image3':
|
||||||
|
imageUrl = image3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (imageUrl != null && imageUrl.isNotEmpty)
|
||||||
|
Image.network(imageUrl, width: 100, height: 100),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
decoration: InputDecoration(labelText: label),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.photo_camera),
|
||||||
|
onPressed: () => _pickAndUploadImage(fieldName),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'menu_content.dart';
|
|
||||||
import 'recipe.dart';
|
|
||||||
|
|
||||||
class RecipesContent implements MenuContent {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// Datenquelle exemplarisch definiert
|
|
||||||
List<Map<String, dynamic>> recipes = [
|
|
||||||
{"title": "Rezept 1", "image": "assets/images/burger.png"},
|
|
||||||
{"title": "Rezept 2", "image": "assets/images/spaghetti.png"},
|
|
||||||
// weitere Rezepte
|
|
||||||
];
|
|
||||||
|
|
||||||
return ListView.builder(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
itemCount: recipes.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => RecipeDetailPage(recipe: recipes[index]),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Image.network(recipes[index]["image"], width: 100, height: 100),
|
|
||||||
Text(recipes[index]["title"]),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
import 'menu_content.dart';
|
||||||
|
import 'recipedetailpage.dart';
|
||||||
|
|
||||||
|
class RecipesOverview implements MenuContent {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StreamBuilder(
|
||||||
|
stream: FirebaseDatabase.instance.ref('rezepte').onValue,
|
||||||
|
builder: (context, AsyncSnapshot<DatabaseEvent> snapshot) {
|
||||||
|
if (snapshot.hasData && !snapshot.hasError && snapshot.data!.snapshot.value != null) {
|
||||||
|
Map<dynamic, dynamic> recipes = snapshot.data!.snapshot.value as Map<dynamic, dynamic>;
|
||||||
|
return ListView.builder(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
itemCount: recipes.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
String key = recipes.keys.elementAt(index);
|
||||||
|
var value = recipes[key];
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => RecipeDetailPage(recipeId: key, recipe: const {},),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.network(value["bild1"], width: 100, height: 100),
|
||||||
|
Text(value["titel"]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'menu_content.dart';
|
||||||
|
|
||||||
|
class Startpage implements MenuContent {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: 1 / 1, // Für ein quadratisches Logo
|
||||||
|
child: Image.asset('assets/images/Logo.png', fit: BoxFit.contain),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,11 @@
|
||||||
// textscan.dart
|
// import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'menu_content.dart';
|
// import 'package:image_picker/image_picker.dart';
|
||||||
|
// import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
|
||||||
|
// import 'menu_content.dart';
|
||||||
|
//import 'package:ocr_scan_text/ocr_scan_text.dart';
|
||||||
|
|
||||||
//todo Logik implementieren
|
|
||||||
//links
|
|
||||||
//https://davidserrano.io/text-recognition-in-flutter-create-ocr-scanner-app
|
|
||||||
//https://www.google.com/search?q=textscan+flutter&oq=textscan+flutter&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIICAEQABgWGB7SAQgzMDg0ajBqN6gCALACAA&sourceid=chrome&ie=UTF-8
|
|
||||||
|
|
||||||
class TextScanContent implements MenuContent {
|
//todo https://pub.dev/packages/ocr_scan_text/install
|
||||||
@override
|
//todo https://pub.dev/packages/google_mlkit_text_recognition/install
|
||||||
Widget build(BuildContext context) {
|
//todo https://pub.dev/packages/flutter_tesseract_ocr
|
||||||
// Hier wird der Inhalt für Menüpunkt 3 erstellt
|
|
||||||
return const Text('Inhalt für Menüpunkt 3 - Text Scan');
|
|
||||||
}
|
|
||||||
}
|
|
344
pubspec.lock
344
pubspec.lock
|
@ -1,6 +1,14 @@
|
||||||
# Generated by pub
|
# Generated by pub
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||||
packages:
|
packages:
|
||||||
|
_flutterfire_internals:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: _flutterfire_internals
|
||||||
|
sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.16"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -41,6 +49,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.18.0"
|
||||||
|
cross_file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cross_file
|
||||||
|
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.3+8"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -57,6 +73,118 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
|
ffi:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: ffi
|
||||||
|
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
|
file_selector_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file_selector_linux
|
||||||
|
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.2+1"
|
||||||
|
file_selector_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file_selector_macos
|
||||||
|
sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.3+3"
|
||||||
|
file_selector_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file_selector_platform_interface
|
||||||
|
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.6.2"
|
||||||
|
file_selector_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file_selector_windows
|
||||||
|
sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.3+1"
|
||||||
|
firebase_core:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_core
|
||||||
|
sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.24.2"
|
||||||
|
firebase_core_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_platform_interface
|
||||||
|
sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.0"
|
||||||
|
firebase_core_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_web
|
||||||
|
sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.10.0"
|
||||||
|
firebase_database:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_database
|
||||||
|
sha256: "8568ad41f9312ab1f162f70c1e3e7cb7420b8bc8d07e4d543e575bb0cb41f8a5"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "10.4.0"
|
||||||
|
firebase_database_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_database_platform_interface
|
||||||
|
sha256: "4366ade2390f8799a317bb13af29c2a1fdfc84f4d04372094756b86a6cbfd305"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.5+16"
|
||||||
|
firebase_database_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_database_web
|
||||||
|
sha256: "4920a83b917493b37fd408cbb01c289ef8a422d9ed48982f908a9850290262f9"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.3+16"
|
||||||
|
firebase_storage:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_storage
|
||||||
|
sha256: "75e6cb6bed65138b5bbd86bfd7cf9bc9a175fb0c31aacc400e9203df117ffbe6"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "11.6.0"
|
||||||
|
firebase_storage_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_storage_platform_interface
|
||||||
|
sha256: "545a3a8edf337850403bb0fa03c8074a53deb87c0107d19755c77a82ce07919e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.3"
|
||||||
|
firebase_storage_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_storage_web
|
||||||
|
sha256: ee6870ff79aa304b8996ba18a4aefe1e8b3fc31fd385eab6574180267aa8d393
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.6.17"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -70,11 +198,128 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.3"
|
||||||
|
flutter_plugin_android_lifecycle:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_plugin_android_lifecycle
|
||||||
|
sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.17"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
google_mlkit_commons:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: google_mlkit_commons
|
||||||
|
sha256: "046586b381cdd139f7f6a05ad6998f7e339d061bd70158249907358394b5f496"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.1"
|
||||||
|
google_mlkit_text_recognition:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: google_mlkit_text_recognition
|
||||||
|
sha256: d484de2a10961a6f0ff8b54cc92b71bfbb0e65509be0903edca0e1f9256ca4c2
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.11.0"
|
||||||
|
http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
|
image_picker:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: image_picker
|
||||||
|
sha256: "26222b01a0c9a2c8fe02fc90b8208bd3325da5ed1f4a2acabf75939031ac0bdd"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.7"
|
||||||
|
image_picker_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_android
|
||||||
|
sha256: "1a27bf4cc0330389cebe465bab08fe6dec97e44015b4899637344bb7297759ec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.9+2"
|
||||||
|
image_picker_for_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_for_web
|
||||||
|
sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
image_picker_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_ios
|
||||||
|
sha256: eac0a62104fa12feed213596df0321f57ce5a572562f72a68c4ff81e9e4caacf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.9"
|
||||||
|
image_picker_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_linux
|
||||||
|
sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1+1"
|
||||||
|
image_picker_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_macos
|
||||||
|
sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1+1"
|
||||||
|
image_picker_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_platform_interface
|
||||||
|
sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.9.3"
|
||||||
|
image_picker_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image_picker_windows
|
||||||
|
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1+1"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.7"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -107,14 +352,86 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.10.0"
|
||||||
path:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
path:
|
||||||
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.3"
|
version: "1.8.3"
|
||||||
|
path_provider:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: path_provider
|
||||||
|
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_android
|
||||||
|
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.2"
|
||||||
|
path_provider_foundation:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_foundation
|
||||||
|
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.3.1"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.2"
|
||||||
|
path_provider_windows:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_windows
|
||||||
|
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.1"
|
||||||
|
platform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: platform
|
||||||
|
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.4"
|
||||||
|
plugin_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: plugin_platform_interface
|
||||||
|
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.8"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -168,6 +485,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.1"
|
version: "0.6.1"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.3.2"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -184,5 +509,22 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.0"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.2.0"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.2.0 <4.0.0"
|
dart: ">=3.2.0 <4.0.0"
|
||||||
|
flutter: ">=3.10.0"
|
||||||
|
|
17
pubspec.yaml
17
pubspec.yaml
|
@ -1,7 +1,5 @@
|
||||||
name: kochkomplize
|
name: kochkomplize
|
||||||
description: "A new Flutter project."
|
description: "Kochhilfe mit Rezepten und Texterkennung"
|
||||||
# The following line prevents the package from being accidentally published to
|
|
||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
@ -13,6 +11,18 @@ dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
cupertino_icons: ^1.0.2
|
cupertino_icons: ^1.0.2
|
||||||
|
#sqflite: ^2.3.0
|
||||||
|
#sqlite3_flutter_libs: ^0.5.18
|
||||||
|
#sqlite3: ^2.3.0
|
||||||
|
firebase_core: ^2.24.2
|
||||||
|
firebase_database: ^10.4.0
|
||||||
|
firebase_storage: ^11.6.0
|
||||||
|
path_provider: ^2.1.2
|
||||||
|
image_picker: ^1.0.7
|
||||||
|
#cloud_firestore: ^4.14.0
|
||||||
|
#ocr_scan_text: 1.3.1
|
||||||
|
google_mlkit_text_recognition: ^0.11.0
|
||||||
|
path: ^1.8.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -23,5 +33,6 @@ flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/images/
|
- assets/images/
|
||||||
|
- assets/database/Kochkomplize.db
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
// import 'package:flutter/material.dart';
|
||||||
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
|
// import 'package:kochkomplize/main.dart';
|
||||||
|
// import 'package:kochkomplize/menu.dart';
|
||||||
|
//
|
||||||
|
// Widget buildMenu() {
|
||||||
|
// return MaterialApp(
|
||||||
|
// home: Scaffold(
|
||||||
|
// body: Menu(onMenuItemSelected: (menuItem) {}),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void main() {
|
||||||
|
// testWidgets('Check menu text', (WidgetTester tester) async {
|
||||||
|
// await tester.pumpWidget(buildMenu());
|
||||||
|
// expect(find.text('Meine Rezepte'), findsOneWidget);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// testWidgets('Check number of list items', (WidgetTester tester) async {
|
||||||
|
// await tester.pumpWidget(const MyApp());
|
||||||
|
// expect(find.byType(GestureDetector), findsNWidgets(2));
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// }
|
|
@ -0,0 +1,22 @@
|
||||||
|
// import 'package:flutter_test/flutter_test.dart';
|
||||||
|
// import 'package:firebase_core/firebase_core.dart';
|
||||||
|
// import 'package:kochkomplize/main.dart';
|
||||||
|
// import 'package:kochkomplize/recipesoverview.dart';
|
||||||
|
// import 'package:kochkomplize/startpage.dart';
|
||||||
|
//
|
||||||
|
// void main() {
|
||||||
|
// test('_MyHomePageState should update selected menu content', () {
|
||||||
|
// final state = _MyHomePageState();
|
||||||
|
//
|
||||||
|
// state._onMenuItemSelected('Meine Rezepte');
|
||||||
|
// expect(state._selectedMenuContent, isInstanceOf<RecipesOverview>());
|
||||||
|
//
|
||||||
|
// state._onMenuItemSelected('Startseite');
|
||||||
|
// expect(state._selectedMenuContent, isInstanceOf<Startpage>());
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// test('Firebase initializes correctly', () async {
|
||||||
|
// await main(); // Ihr main-Methodenaufruf
|
||||||
|
// expect(Firebase.apps.length, isNonZero);
|
||||||
|
// });
|
||||||
|
// }
|
|
@ -1,50 +1,21 @@
|
||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:kochkomplize/main.dart';
|
import 'package:kochkomplize/main.dart';
|
||||||
import 'package:kochkomplize/menu.dart';
|
import 'package:kochkomplize/recipesoverview.dart';
|
||||||
|
|
||||||
Widget buildMenu() {
|
|
||||||
return MaterialApp(
|
|
||||||
home: Scaffold(
|
|
||||||
body: Menu(onMenuItemSelected: (menuItem) {}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Check menu text', (WidgetTester tester) async {
|
testWidgets('Menu navigation test', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(buildMenu());
|
|
||||||
expect(find.text('Meine Rezepte'), findsOneWidget);
|
|
||||||
});
|
|
||||||
|
|
||||||
testWidgets('Check number of list items', (WidgetTester tester) async {
|
|
||||||
await tester.pumpWidget(const MyApp());
|
await tester.pumpWidget(const MyApp());
|
||||||
expect(find.byType(GestureDetector), findsNWidgets(3));
|
|
||||||
});
|
|
||||||
|
|
||||||
// testWidgets('Check display of recipe titles', (WidgetTester tester) async {
|
// Öffne das Menü
|
||||||
// await tester.pumpWidget(const MyApp());
|
await tester.tap(find.byIcon(Icons.menu));
|
||||||
// expect(find.text('Rezept 1'), findsOneWidget);
|
await tester.pumpAndSettle();
|
||||||
// expect(find.text('Rezept 2'), findsOneWidget);
|
|
||||||
// });
|
// Wähle einen Menüpunkt
|
||||||
//
|
await tester.tap(find.text('Meine Rezepte'));
|
||||||
// testWidgets('Check display of recipe images', (WidgetTester tester) async {
|
await tester.pumpAndSettle();
|
||||||
// await tester.pumpWidget(const MyApp());
|
|
||||||
// expect(find.byType(Image), findsNWidgets(2));
|
// Überprüfe, ob das richtige Widget angezeigt wird
|
||||||
// });
|
expect(find.byType(RecipesOverview), findsOneWidget);
|
||||||
//
|
});
|
||||||
// testWidgets('Check navigation to recipe detail page', (WidgetTester tester) async {
|
}
|
||||||
// await tester.pumpWidget(const MyApp());
|
|
||||||
// await tester.tap(find.text('Rezept 1'));
|
|
||||||
// await tester.pumpAndSettle(); // Warte darauf, dass die Navigation abgeschlossen ist
|
|
||||||
// expect(find.text('Details für Rezept 1'), findsOneWidget);
|
|
||||||
// });
|
|
||||||
}
|
|
Loading…
Reference in New Issue