Anzahl an Events werden angezeigt.
This commit is contained in:
parent
33d5cf6ece
commit
451a27c6a4
|
|
@ -0,0 +1,3 @@
|
|||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
|
|
@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:Emma_home/screens/home.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'screens/MainScreen.dart';
|
||||
import 'utils/data.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
//import 'package:learn_project/screens/account_page.dart';
|
||||
//import 'package:learn_project/screens/login_page.dart';
|
||||
//import 'package:learn_project/screens/splash_page.dart';
|
||||
|
|
@ -19,7 +21,14 @@ Future<void> main() async {
|
|||
//url:'http://192.168.179.86:8000/',//
|
||||
// annonKey: //Constants.supabaseAnnonKey,//'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE2NTIsImV4cCI6MjAzMTU5NzY1Mn0.1bp5V61Oguo5zLUhCFJmCabUY1sujeISr_CR2XUKvh4',//
|
||||
);
|
||||
runApp(MyApp());
|
||||
var singleCategories = Categories.instance;
|
||||
singleCategories.updateCategoryAmount('Ingosltadt');
|
||||
runApp(
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => Categories.instance,
|
||||
child: MyApp(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Supabase client
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ String extractTime24h(String timestamp) {
|
|||
// Dann den richtigen Eintrag in Data identifizieren udn die Farbe auswählen
|
||||
Color extractColor(String categoryID)
|
||||
{
|
||||
final result = Data.recipes.where((recipe) => recipe.category == categoryID).firstOrNull;
|
||||
var single_categories = Categories.instance;
|
||||
final result = single_categories.categories.where((recipe) => recipe.category == categoryID).firstOrNull;
|
||||
Color categorie_color= Color.fromARGB(255, 255, 255, 255);
|
||||
if (result!=null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,11 +3,22 @@ import 'package:Emma_home/screens/details_db.dart';
|
|||
import 'package:Emma_home/utils/data.dart';
|
||||
import 'package:Emma_home/screens/subheader_Datepicker.dart';
|
||||
import 'package:Emma_home/screens/detail_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:Emma_home/main.dart';
|
||||
import 'package:Emma_home/utils/data.dart';
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
const HomePage({super.key});
|
||||
class HomePage extends StatefulWidget {
|
||||
@override
|
||||
_HomePage createState() => _HomePage();
|
||||
}
|
||||
class _HomePage extends State<HomePage> {
|
||||
late Future<void> _fetchDataFuture;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchDataFuture = Categories.instance.updateCategoryAmount('Ingolstadt');
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> _loadData() async {
|
||||
final _data = await supabase.from('events').select();
|
||||
|
|
@ -84,12 +95,14 @@ class HomePage extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
|
||||
//var single_categories = Categories.instance;
|
||||
//single_categories.updateCategoryAmount('Ingolstadt');
|
||||
/*24 is for notification bar on Android*/
|
||||
final double itemHeight = (size.height - kToolbarHeight - 140) / 5;
|
||||
final double itemWidth = size.width / 2.3;
|
||||
final double itemHeight = (size.height - kToolbarHeight - 180) / 5;
|
||||
final double itemWidth = (size.width-40)/ 2;
|
||||
MediaQueryData queryData;
|
||||
queryData = MediaQuery.of(context);
|
||||
|
||||
var appBar = AppBar(
|
||||
leading: SizedBox(
|
||||
height: 60,
|
||||
|
|
@ -157,7 +170,9 @@ class HomePage extends StatelessWidget {
|
|||
flexibleSpace: Container(),
|
||||
);
|
||||
var body = SafeArea(
|
||||
child: Column(
|
||||
child:Consumer<Categories>(
|
||||
builder: (context, single_categories, child) {return
|
||||
Column(
|
||||
children: <Widget>[
|
||||
//Header Container
|
||||
//HeaderSection(),
|
||||
|
|
@ -189,7 +204,7 @@ class HomePage extends StatelessWidget {
|
|||
itemHeight), // Anzahl der Spalten im Grid
|
||||
),
|
||||
itemCount:
|
||||
Data.recipes.length, // Anzahl der Elemente im Grid
|
||||
single_categories.categories.length, // Anzahl der Elemente im Grid
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
|
|
@ -198,13 +213,13 @@ class HomePage extends StatelessWidget {
|
|||
/* List<Map<String, dynamic>> events =
|
||||
await _loadData(); */
|
||||
List<Map<String, dynamic>> events2 =
|
||||
await fetchEvents(Data.recipes[index].category);
|
||||
await fetchEvents(single_categories.categories[index].category);
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Frame28(
|
||||
events: events2,
|
||||
color: Data.recipes[index].color,
|
||||
color: single_categories.categories[index].color,
|
||||
screen_size: queryData,
|
||||
)));
|
||||
},
|
||||
|
|
@ -223,14 +238,14 @@ class HomePage extends StatelessWidget {
|
|||
decoration: ShapeDecoration(
|
||||
image: DecorationImage(
|
||||
image:
|
||||
AssetImage(Data.recipes[index].imageUrl),
|
||||
AssetImage(single_categories.categories[index].imageUrl),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
shadows: [
|
||||
BoxShadow(
|
||||
color: Data.recipes[index].color,
|
||||
color: single_categories.categories[index].color,
|
||||
blurRadius: 0,
|
||||
offset: Offset(0, 10),
|
||||
spreadRadius: 0,
|
||||
|
|
@ -243,7 +258,7 @@ class HomePage extends StatelessWidget {
|
|||
left: 16,
|
||||
top: 15,
|
||||
child: Text(
|
||||
'64',
|
||||
single_categories.categories[index].amount.toString(),
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
|
|
@ -255,14 +270,14 @@ class HomePage extends StatelessWidget {
|
|||
),
|
||||
Positioned(
|
||||
left: 13,
|
||||
top: Data.recipes[index].textheight, //86, //TODO Bootom?
|
||||
top: single_categories.categories[index].textheight, //86, //TODO Bootom?
|
||||
child:
|
||||
Container(
|
||||
width: itemWidth-20,// Set a fixed width or use constraints
|
||||
child: Wrap(
|
||||
children: [
|
||||
Text(
|
||||
Data.recipes[index].title,
|
||||
single_categories.categories[index].title,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24,
|
||||
|
|
@ -272,8 +287,6 @@ class HomePage extends StatelessWidget {
|
|||
),
|
||||
), ],
|
||||
),),
|
||||
|
||||
|
||||
),
|
||||
Positioned(
|
||||
right:20,
|
||||
|
|
@ -283,7 +296,7 @@ class HomePage extends StatelessWidget {
|
|||
width: 32,
|
||||
height: 32,
|
||||
child: Image.asset(
|
||||
Data.recipes[index].iconUrl,
|
||||
single_categories.categories[index].iconUrl,
|
||||
), ),
|
||||
|
||||
),
|
||||
|
|
@ -299,53 +312,7 @@ class HomePage extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
/* Card(
|
||||
color: Data.recipes[index].color,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
),
|
||||
child: Container(
|
||||
//width: (MediaQuery.of(context).size.width / 2),
|
||||
//height: 20,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(6.0),
|
||||
topRight: Radius.circular(6.0),
|
||||
),
|
||||
child: Hero(
|
||||
tag: Data.recipes[index].id,
|
||||
child: FadeInImage(
|
||||
image: AssetImage(
|
||||
Data.recipes[index].imageUrl,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
placeholder: AssetImage(
|
||||
'assets/images/loading.gif',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
Data.recipes[index].title,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(1.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
), */
|
||||
),
|
||||
), ),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
@ -361,13 +328,14 @@ class HomePage extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);})
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: appBar,
|
||||
body: body,
|
||||
body: Consumer<Categories>(
|
||||
builder: (context, single_categories, child) {return body;}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,21 @@
|
|||
import 'dart:ui';
|
||||
|
||||
class Nutrients {
|
||||
String name;
|
||||
String weight;
|
||||
double percent;
|
||||
Nutrients({required this.name, required this.weight, required this.percent});
|
||||
}
|
||||
|
||||
class Recipe {
|
||||
class Category {
|
||||
String id, imageUrl, iconUrl,title,category;
|
||||
Color color;
|
||||
double? textheight;
|
||||
//List<String> steps;
|
||||
//List<String> ingredients;
|
||||
//List<Nutrients> nutrients;
|
||||
Recipe(
|
||||
int amount;
|
||||
|
||||
Category(
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.imageUrl,
|
||||
required this.iconUrl,
|
||||
//required this.steps,
|
||||
//required this.ingredients,
|
||||
//required this.nutrients,
|
||||
required this.color,
|
||||
required this.category,
|
||||
required this.textheight});
|
||||
required this.textheight,
|
||||
required this.amount});
|
||||
|
||||
void add(Category category) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,20 @@ import 'package:intl/intl.dart' as intl;
|
|||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
const Duration fakeAPIDuration = Duration(milliseconds: 50);
|
||||
const Duration debounceDuration = Duration(milliseconds: 50);
|
||||
class Data {
|
||||
static List<Recipe> recipes = [
|
||||
Recipe(
|
||||
|
||||
class Categories extends ChangeNotifier{
|
||||
// Private constructor
|
||||
Categories._privateConstructor();
|
||||
|
||||
// Static instance
|
||||
static final Categories _instance = Categories._privateConstructor();
|
||||
|
||||
// Static method to access the instance
|
||||
static Categories get instance => _instance;
|
||||
|
||||
// Your singleton methods and properties
|
||||
static List<Category> _categories = [
|
||||
Category(
|
||||
id: '1',
|
||||
title: 'Musik',
|
||||
imageUrl: 'assets/images/Musik.png',
|
||||
|
|
@ -18,23 +29,9 @@ class Data {
|
|||
color: Color.fromARGB(255, 249, 171, 21), //FD4949 //Musik
|
||||
category: '34725c49-740b-45c5-8a51-7c742f92a621',
|
||||
textheight: 86,
|
||||
/* nutrients: [
|
||||
Nutrients(name: 'Calories', weight: '200', percent: 0.7),
|
||||
Nutrients(name: 'Protein', weight: '10gm', percent: 0.5),
|
||||
Nutrients(name: 'Carb', weight: '50gm', percent: 0.9),
|
||||
],
|
||||
steps: [
|
||||
'Gather the ingredients.',
|
||||
'Pull a double shot of espresso into a cappuccino cup.',
|
||||
'Foam the milk to double its original volume.'
|
||||
'Top the espresso with foamed milk right after foaming. When initially poured, cappuccinos are only espresso and foam, but the liquid milk quickly settles out of the foam to create the (roughly) equal parts foam, steamed milk, and espresso for which cappuccino is known.',
|
||||
'Serve immediately.'
|
||||
],
|
||||
ingredients: [
|
||||
'2 shots espresso (a double shot)',
|
||||
'4 ounces milk'
|
||||
] */),
|
||||
Recipe(
|
||||
amount:0,
|
||||
),
|
||||
Category(
|
||||
id: '2',
|
||||
title: 'Nachtleben',
|
||||
imageUrl: 'assets/images/Nachtleben.png',
|
||||
|
|
@ -42,8 +39,9 @@ class Data {
|
|||
color: Color.fromARGB(255, 253, 73, 73), //FD4949 //Nachtleben
|
||||
category: '2d8c714e-3290-4d8c-8a95-e3b100ad8599',
|
||||
textheight: 86,
|
||||
amount:0,
|
||||
),
|
||||
Recipe(
|
||||
Category(
|
||||
id: '3',
|
||||
title: 'Kunst & Kultur',
|
||||
imageUrl: 'assets/images/Kultur.png',
|
||||
|
|
@ -51,73 +49,128 @@ class Data {
|
|||
color: Color.fromARGB(255, 80, 168, 250), //50A8FA//Kunst
|
||||
category: '09d1f862-2b56-47af-8ee6-3c50056e3fa2',
|
||||
textheight: 58,
|
||||
amount:0,
|
||||
),
|
||||
Recipe(
|
||||
Category(
|
||||
id: '4',
|
||||
title: 'Sport & Verein',
|
||||
imageUrl: 'assets/images/Sport.png',
|
||||
iconUrl:'assets/images/Icons/Icon_Sport.png',
|
||||
color: Color.fromARGB(255, 80, 240, 250), //50F0FA //Sport
|
||||
category: '15119876-9ff0-41e5-8fe5-c3675af5e054',
|
||||
textheight: 58,
|
||||
textheight: 58,
|
||||
amount:0,
|
||||
),
|
||||
Recipe(
|
||||
Category(
|
||||
id: '5',
|
||||
title: 'Gesundheit',
|
||||
imageUrl: 'assets/images/Gesundheit.png',
|
||||
iconUrl:'assets/images/Icons/Icon_Gesundheit.png',
|
||||
color: Color.fromARGB(255,130, 73, 253), //8249FD //Gesundheit
|
||||
category: '4ad3ac2d-04fc-4aa1-afae-17ec7bfc1714',
|
||||
textheight: 86,
|
||||
textheight: 86,
|
||||
amount:0,
|
||||
),
|
||||
Recipe(
|
||||
Category(
|
||||
id: '6',
|
||||
title: 'Essen & Trinken',
|
||||
imageUrl: 'assets/images/Essen.png',
|
||||
iconUrl:'assets/images/Icons/Icon_Essen.png',
|
||||
color: Color.fromARGB(255,253, 73,73), //FD4949//Essen
|
||||
category: 'ef83c4d3-228a-44e1-8a5d-8b47d2dfc351',
|
||||
textheight: 58,
|
||||
),
|
||||
Recipe(
|
||||
textheight: 58,
|
||||
amount:0,
|
||||
),
|
||||
Category(
|
||||
id: '7',
|
||||
title: 'Soziales',
|
||||
imageUrl: 'assets/images/Soziales.png',
|
||||
iconUrl:'assets/images/Icons/Icon_Soziales.png',
|
||||
color: Color.fromARGB(255,255,0,199), //FF00C7//Essen
|
||||
category: '53a1782b-e07b-491d-b778-d99ef9cf57e2',
|
||||
textheight: 86,
|
||||
textheight: 86,
|
||||
amount:0,
|
||||
),
|
||||
Recipe(
|
||||
Category(
|
||||
id: '8',
|
||||
title: 'Familie',
|
||||
imageUrl: 'assets/images/Familie.png',
|
||||
iconUrl:'assets/images/Icons/Icon_Familie.png',
|
||||
color: Color.fromARGB(255,66,255,0), //42FF00//Essen //HSL 104 100 50 100
|
||||
category: '30cb3481-c425-4068-9714-adc86df85d3f',
|
||||
textheight: 86,
|
||||
textheight: 86,
|
||||
amount:0,
|
||||
),
|
||||
];
|
||||
|
||||
//color: Color.fromARGB(255, 255, 0, 199), //FF00C7//Soziales
|
||||
//color: Color.fromARGB(255, 66, 255, 0), //42FF00//Familie,
|
||||
void addCategory(Category category) {
|
||||
category.add(category);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
void updateCategory(int index, Category updatedCategory) {
|
||||
if (index >= 0 && index < _categories.length) {
|
||||
_categories[index] = updatedCategory;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void removeCategory(int index) {
|
||||
if (index >= 0 && index < _categories.length) {
|
||||
_categories.removeAt(index);
|
||||
notifyListeners();
|
||||
}}
|
||||
|
||||
Future<void> updateCategoryAmount (String cityName) async{
|
||||
try {
|
||||
for (var index = 0; index < _categories.length; index++) {
|
||||
final response = await supabase
|
||||
.from("events")
|
||||
.select(
|
||||
'id,name,main_category_id,location(name),event_category!inner(event_id)')
|
||||
.eq('event_category.category_id', _categories[index].category);
|
||||
var temp =(response.length);
|
||||
_categories[index].amount= temp;
|
||||
notifyListeners();
|
||||
|
||||
}return; } catch (e) {
|
||||
throw Exception('Failed to fetch data: $e');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to get all items
|
||||
List<Category> get categories => List.unmodifiable(_categories);
|
||||
|
||||
// Method to clear all items
|
||||
void clearItems() {
|
||||
_categories.clear();
|
||||
}
|
||||
|
||||
// Method to get item count
|
||||
int get itemCount => _categories.length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class SupabaseDataService {
|
||||
|
||||
|
||||
|
||||
Future<List<Map<String, dynamic>>> fetchEvents(String cathegory) async {
|
||||
Future<List<Map<String, dynamic>>> fetchEvents(String category) async {
|
||||
try {
|
||||
final today = DateTime.now().toUtc().toString().split(' ')[0];
|
||||
final response = await supabase
|
||||
.from("events")
|
||||
.select('id,name,description,detail,subheader,location(name),time(startdate)')
|
||||
.eq('category(id)',cathegory);
|
||||
//select('id, name, cities(id, name)')
|
||||
//find all events mit Ort und zusatzinfos die die Kathegorie haben welche ausgewählt wurde am heutigen Tag dann kommender Tag usw.
|
||||
.from("events")
|
||||
.select(
|
||||
'id,name,description,detail,subheader,main_category_id,location(name),time!inner(*),event_category!inner(event_id)')
|
||||
.eq('event_category.category_id', category);
|
||||
//.gte('time.start_date', DateTime.now().toIso8601String().split('T')[0]) // Beginn des heutigen Tages
|
||||
//.lt('time.start_date', DateTime.now().add(Duration(days: 1)).toIso8601String().split('T')[0]); // Morgen;
|
||||
//select('id, name, cities(id, name)')
|
||||
//find all events mit Ort und zusatzinfos die die Kathegorie haben welche ausgewählt wurde am heutigen Tag dann kommender Tag usw.
|
||||
//final test = response[0]['time'][0]['start_date'];
|
||||
return (response as List).cast<Map<String, dynamic>>();
|
||||
} catch (e) {
|
||||
throw Exception('Failed to fetch data: $e');
|
||||
|
|
@ -138,50 +191,6 @@ class SupabaseDataService {
|
|||
throw Exception('Failed to fetch record: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/* Future<void> insertData(String tableName, Map<String, dynamic> data) async {
|
||||
try {
|
||||
final response = await supabase
|
||||
.from(tableName)
|
||||
.insert(data);
|
||||
|
||||
if (response.error != null) {
|
||||
throw response.error!;
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to insert data: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateData(String tableName, String id, Map<String, dynamic> data) async {
|
||||
try {
|
||||
final response = await supabase
|
||||
.from(tableName)
|
||||
.update(data)
|
||||
.eq('id', id);
|
||||
|
||||
if (response.error != null) {
|
||||
throw response.error!;
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update data: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteData(String tableName, String id) async {
|
||||
try {
|
||||
final response = await _supabase
|
||||
.from(tableName)
|
||||
.delete()
|
||||
.eq('id', id);
|
||||
|
||||
if (response.error != null) {
|
||||
throw response.error!;
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete data: $e');
|
||||
}
|
||||
} */
|
||||
}
|
||||
/* class _AsyncAutocomplete extends StatefulWidget {
|
||||
const _AsyncAutocomplete();
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:Emma_home/utils/class.dart';
|
||||
|
||||
class CircleIndicator extends StatefulWidget {
|
||||
final double percent;
|
||||
final Nutrients nutrient;
|
||||
|
||||
CircleIndicator({this.percent = 0.5, required this.nutrient});
|
||||
@override
|
||||
_CircleIndicatorState createState() => _CircleIndicatorState();
|
||||
}
|
||||
|
||||
class _CircleIndicatorState extends State<CircleIndicator>
|
||||
with SingleTickerProviderStateMixin {
|
||||
double fraction = 0.0;
|
||||
late Animation<double> animation;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
var controller = AnimationController(
|
||||
duration: Duration(milliseconds: 1000), vsync: this);
|
||||
|
||||
animation = Tween(begin: 0.0, end: widget.percent).animate(controller)
|
||||
..addListener(() {
|
||||
setState(() {
|
||||
fraction = animation.value;
|
||||
});
|
||||
});
|
||||
|
||||
controller.forward();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Stack(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 70,
|
||||
height: 70,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
widget.nutrient.name,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
Text(
|
||||
widget.nutrient.weight,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 70,
|
||||
height: 70,
|
||||
child: CustomPaint(
|
||||
foregroundPainter: CirclePainter(fraction),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CirclePainter extends CustomPainter {
|
||||
late Paint _paint;
|
||||
double _fraction;
|
||||
|
||||
CirclePainter(this._fraction) {
|
||||
_paint = Paint()
|
||||
..color = Color(0xff8DB646)
|
||||
..strokeWidth = 5.0
|
||||
..strokeCap = StrokeCap.round
|
||||
..style = PaintingStyle.stroke;
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
var rect = Offset(0.0, 0.0) & size;
|
||||
canvas.drawArc(rect, -pi / 2, pi * 2 * _fraction, false, _paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CirclePainter oldDelegate) {
|
||||
return oldDelegate._fraction != _fraction;
|
||||
}
|
||||
}
|
||||
16
pubspec.lock
16
pubspec.lock
|
|
@ -368,6 +368,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -448,6 +456,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
realtime_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ dependencies:
|
|||
supabase_flutter: ^2.7.0
|
||||
timeago: ^3.1.0
|
||||
image_picker: ^1.1.2
|
||||
provider: ^6.0.5
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
|
|
|
|||
Loading…
Reference in New Issue