import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; 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', theme: ThemeData(useMaterial3: true), 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 createState() => _MyHomePageState(); } class Recipe { String name; String icon; Recipe(this.name, this.icon); factory Recipe.fromMap(Map json) { return Recipe(json['Name'], json['Icon']); } factory Recipe.fromJson(Map json) { return Recipe(json['Name'], json['Icon']); } } Future> 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>(); return parsed.map((json) => Recipe.fromMap(json)).toList(); } else { throw Exception("Failed to fetch recipes"); } } class _MyHomePageState extends State { @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. return Container( child: Column(children: [ Padding( padding: EdgeInsetsDirectional.all(16.0), child: Image(image: AssetImage("assets/banner.png"))), Text(textAlign: TextAlign.start, "Einkaufsliste"), FutureBuilder>( future: fetchRecipes(), builder: (context, snapshot) { if (snapshot.hasError) print(snapshot.error); if (snapshot.hasData) { List rows = List.empty(growable: true); for (Recipe recipe in snapshot.data!) { var image = Image.network(fit: BoxFit.fitHeight, height: 32.0, "http://localhost:8080/api/image/${recipe.icon}"); rows.add(TableRow(children: [TableCell(child: image), TableCell(child: Text(recipe.name))])); } return Table(children: rows); } else { return Center(child: CircularProgressIndicator()); } }) ])); } }