2024-10-28 14:40:34 +00:00
|
|
|
import 'dart:convert';
|
|
|
|
|
2024-10-28 13:38:56 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2024-10-28 14:40:34 +00:00
|
|
|
import 'package:http/http.dart' as http;
|
2024-10-28 13:38:56 +00:00
|
|
|
|
|
|
|
void main() {
|
|
|
|
runApp(const MyApp());
|
|
|
|
}
|
|
|
|
|
|
|
|
class MyApp extends StatelessWidget {
|
|
|
|
const MyApp({super.key});
|
|
|
|
|
|
|
|
// This widget is the root of your application.
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return MaterialApp(
|
|
|
|
title: 'Flutter Demo',
|
2024-10-28 14:40:34 +00:00
|
|
|
theme: ThemeData(useMaterial3: true),
|
2024-10-28 13:38:56 +00:00
|
|
|
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class MyHomePage extends StatefulWidget {
|
|
|
|
const MyHomePage({super.key, required this.title});
|
|
|
|
|
|
|
|
// This widget is the home page of your application. It is stateful, meaning
|
|
|
|
// that it has a State object (defined below) that contains fields that affect
|
|
|
|
// how it looks.
|
|
|
|
|
|
|
|
// This class is the configuration for the state. It holds the values (in this
|
|
|
|
// case the title) provided by the parent (in this case the App widget) and
|
|
|
|
// used by the build method of the State. Fields in a Widget subclass are
|
|
|
|
// always marked "final".
|
|
|
|
|
|
|
|
final String title;
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<MyHomePage> createState() => _MyHomePageState();
|
|
|
|
}
|
|
|
|
|
2024-10-28 14:40:34 +00:00
|
|
|
class Recipe {
|
|
|
|
String name;
|
|
|
|
String icon;
|
|
|
|
|
|
|
|
Recipe(this.name, this.icon);
|
|
|
|
|
|
|
|
factory Recipe.fromMap(Map<String, dynamic> json) {
|
|
|
|
return Recipe(json['Name'], json['Icon']);
|
2024-10-28 13:38:56 +00:00
|
|
|
}
|
2024-10-28 14:40:34 +00:00
|
|
|
factory Recipe.fromJson(Map<String, dynamic> json) {
|
|
|
|
return Recipe(json['Name'], json['Icon']);
|
|
|
|
}
|
|
|
|
}
|
2024-10-28 13:38:56 +00:00
|
|
|
|
2024-10-28 14:40:34 +00:00
|
|
|
Future<List<Recipe>> fetchRecipes() async {
|
|
|
|
final response = await http.get(
|
|
|
|
Uri(scheme: "http", host: "localhost", port: 8080, path: "api/recipes"));
|
|
|
|
|
|
|
|
if (response.statusCode == 200) {
|
|
|
|
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
|
|
|
|
return parsed.map<Recipe>((json) => Recipe.fromMap(json)).toList();
|
|
|
|
} else {
|
|
|
|
throw Exception("Failed to fetch recipes");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _MyHomePageState extends State<MyHomePage> {
|
2024-10-28 13:38:56 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
// This method is rerun every time setState is called, for instance as done
|
|
|
|
// by the _incrementCounter method above.
|
|
|
|
//
|
|
|
|
// The Flutter framework has been optimized to make rerunning build methods
|
|
|
|
// fast, so that you can just rebuild anything that needs updating rather
|
|
|
|
// than having to individually change instances of widgets.
|
2024-10-28 14:40:34 +00:00
|
|
|
return Container(
|
|
|
|
child: Column(children: [
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsetsDirectional.all(16.0),
|
|
|
|
child: Image(image: AssetImage("assets/banner.png"))),
|
|
|
|
Text(textAlign: TextAlign.start, "Einkaufsliste"),
|
|
|
|
FutureBuilder<List<Recipe>>(
|
|
|
|
future: fetchRecipes(),
|
|
|
|
builder: (context, snapshot) {
|
|
|
|
if (snapshot.hasError) print(snapshot.error);
|
|
|
|
|
|
|
|
if (snapshot.hasData) {
|
|
|
|
List<TableRow> rows = List.empty(growable: true);
|
|
|
|
|
|
|
|
for (Recipe recipe in snapshot.data!) {
|
|
|
|
rows.add(TableRow(children: [Text(recipe.name)]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return Table(children: rows);
|
|
|
|
} else {
|
|
|
|
return Center(child: CircularProgressIndicator());
|
|
|
|
}
|
|
|
|
})
|
|
|
|
]));
|
2024-10-28 13:38:56 +00:00
|
|
|
}
|
|
|
|
}
|