Small changes done.

This commit is contained in:
Niklas 2024-12-27 21:44:52 +01:00
parent 9c0124fc18
commit 5c94a129b4
4 changed files with 415 additions and 384 deletions

View File

@ -1,231 +0,0 @@
import 'package:Emma_home/utils/class.dart';
import 'package:flutter/material.dart';
import 'package:Emma_home/screens/subheader_Datepicker.dart';
//import 'package:learn_project/main.dart';
import 'package:intl/intl.dart';
import 'package:Emma_home/utils/data.dart';
//import 'package:supabase_flutter/supabase_flutter.dart';
class Event_Card_small extends StatelessWidget {
//final List<Map<String, dynamic>> events;
final List<Map<String, dynamic>> event_grouped;
final Color color;
final MediaQueryData screen_size;
final Category category;
const Event_Card_small(
{super.key,
required this.event_grouped,
required this.color,
required this.screen_size,
required this.category});
void toggleExpanded() {}
/* void initState() {
super.initState();
_loadData();
} */
/* */
@override
Widget build(BuildContext context) {
var appBar = AppBar(
leading: SizedBox(
height: 60,
width: 63,
child: IconButton(
icon: Image.asset('assets/images/logo.png'),
onPressed: () {
// Open drawer or perform action
},
),
),
title: Row(
children: [
const SizedBox(
height: 10, //height of button
width: 20, //width of button
child: Icon(Icons.keyboard_arrow_down),
),
const SizedBox(
//width of button
width: 10,
),
SizedBox(
width: 100.0,
child: TextField(
controller: TextEditingController(text: "Ingolstadt"),
decoration: const InputDecoration(
border: UnderlineInputBorder(),
),
),
),
],
),
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {
// Perform search action
},
),
const SizedBox(
height: 40,
child: VerticalDivider(
thickness: 1,
width: 20,
color: Colors.black,
),
),
SizedBox(
height: 50, //height of button
//width of button
child: IconButton(
icon: Image.asset('assets/images/Login.png'),
onPressed: () {},
),
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1.0),
child: Container(
color: Colors.black,
height: 1.0,
),
),
flexibleSpace: Container(),
);
//_loadData();
var body = CustomScrollView(slivers: [
SliverSafeArea(
//minimum: EdgeInsets.zero,
bottom: false,
sliver: SliverToBoxAdapter(
child: Container(
alignment: Alignment.center,
child: Column(children: <Widget>[
Container(height: 10),
Container(
height: 35,
padding: const EdgeInsets.all(0),
child: TimeButtonSection(
onToggle: toggleExpanded), // Dein Button-Bereich
),
Container(
height: 10,
),
SizedBox(
height: 35,
child: Cat_Sub_Header(
name: category.title, icon: category.iconUrl),
),
//Container(),
])),
),
),
// Gruppierte Events mit SliverMainAxisGroup
...event_grouped.map((group) {
final String startDate = group['start_date'];
final List<Map<String, dynamic>> events = group['events'];
return SliverMainAxisGroup(
slivers: [
// Gruppierungs-Header
SliverToBoxAdapter(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// TODO: muss noch angepasst werden jedes mal wenn ein neuer Tag ist wieder diesen Text anzeigen
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(
left: 20.0), // Abstand von 16 Pixeln zum linken Rand
child: Text(
DateFormat('dd.MM.yyyy')
.format(DateTime.parse(startDate)),
style: const TextStyle(
color: Color(0xFF171717),
fontSize: 12,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
height: 0,
),
),
),
//Kurze Zwischenbereich zum trennen
const SizedBox(height: 4),
],
),
),
// Liste der Events
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final event = events[index];
return EventCard2Section(
title: event['name'],
description: event['description'],
location: event['location_name'] ?? '',
start_time: extractTime24h(event['start']),
color: event['main_category_id'] != null
? extractColor(event['main_category_id'])
: color,
//extractColor(events[index]['main_category_id']),
// oder ein beliebiger Standardwert
screen_size: screen_size,
);
},
childCount: events.length,
),
),
],
);
}),
SliverToBoxAdapter(
child: Column(children: [
const LostEvents(),
Container(height: 20),
const Footer(),
]),
),
]);
return Scaffold(
backgroundColor: Colors.white,
appBar: appBar,
body: body,
);
}
}
String extractTime24h(String timestamp) {
try {
DateTime dateTime = DateTime.parse(timestamp);
String hours = dateTime.hour.toString().padLeft(2, '0');
String minutes = dateTime.minute.toString().padLeft(2, '0');
return '$hours:$minutes';
} catch (e) {
print('Error parsing timestamp: $e');
return '--:--'; // or some other error indicator
}
}
//TODO: Color muss anhand der Categorie entschieden werden
// Also herauslesen welche Category das Event hat
// Dann den richtigen Eintrag in Data identifizieren udn die Farbe auswählen
Color extractColor(String categoryID) {
var singleCategories = Categories.instance;
final result = singleCategories.categories
.where((recipe) => recipe.category == categoryID)
.firstOrNull;
Color categorieColor = const Color.fromARGB(255, 255, 255, 255);
if (result != null) {
categorieColor = result.color;
}
return categorieColor;
}

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.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:Emma_home/screens/result_event_list.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:Emma_home/main.dart';
@ -87,6 +87,13 @@ class _HomePage extends State<HomePage> {
}
}
Future<void> _refresh() async {
setState(() {
// Aktualisiere die Liste (Beispiel: Einfügen neuer Daten)
_fetchDataFuture = Categories.instance.updateCategoryAmount('Ingolstadt');
});
}
Future<List<Map<String, dynamic>>> fetchEventsTomorrow(
String category) async {
try {
@ -211,167 +218,170 @@ class _HomePage extends State<HomePage> {
),
flexibleSpace: Container(),
);
var body = SafeArea(child:
Consumer<Categories>(builder: (context, singleCategories, child) {
return SingleChildScrollView(
physics: isScrollable
? const AlwaysScrollableScrollPhysics()
: const NeverScrollableScrollPhysics(),
child: Column(
children: <Widget>[
//Header Container
//HeaderSection(),
Container(height: 14),
Container(
height: 35,
padding: const EdgeInsets.all(0),
child: TimeButtonSection(
onToggle: toggleExpanded), // Dein Button-Bereich
),
GridView.builder(
controller: scrollController,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap:
true, // Damit der GridView korrekt in die Column passt
//physics: NeverScrollableScrollPhysics(), // Deaktiviert das Scrolling des GridView
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // Anzahl der Spalten im Grid
//crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: (itemWidth / itemHeight),
),
itemCount: singleCategories
.categories.length, // Anzahl der Elemente im Grid
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(6.0),
child: InkWell(
onTap: () async {
final events = await fetchGroupedEvents(
singleCategories.categories[index].category);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Event_Card_small(
event_grouped: events,
color: singleCategories
.categories[index].color,
screen_size: queryData,
category:
singleCategories.categories[index],
)));
},
child: SizedBox(
width: itemWidth,
height: itemHeight.toDouble(),
child: Stack(
children: [
Positioned(
left: 0,
top: 0,
child: Container(
width: itemWidth,
height: itemHeight.toDouble(),
decoration: ShapeDecoration(
image: DecorationImage(
image: AssetImage(singleCategories
.categories[index].imageUrl),
fit: BoxFit.cover,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
shadows: [
BoxShadow(
color: singleCategories
.categories[index].color,
blurRadius: 0,
offset: const Offset(0, 10),
spreadRadius: 0,
)
],
),
),
),
Positioned(
left: 16,
top: 15,
child: Text(
singleCategories.categories[index].amount
.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 0,
),
),
),
Positioned(
left: 13,
top: singleCategories.categories[index]
.textheight, //86, //TODO Bootom?
child: SizedBox(
width: itemWidth -
20, // Set a fixed width or use constraints
child: Wrap(
children: [
Text(
singleCategories.categories[index].title,
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontFamily: 'Inter',
fontWeight: FontWeight.w800,
height: 0,
var body = RefreshIndicator(
onRefresh: _refresh,
child: SafeArea(child:
Consumer<Categories>(builder: (context, singleCategories, child) {
return SingleChildScrollView(
physics: isScrollable
? const AlwaysScrollableScrollPhysics()
: const NeverScrollableScrollPhysics(),
child: Column(
children: <Widget>[
//Header Container
//HeaderSection(),
Container(height: 14),
Container(
height: 35,
padding: const EdgeInsets.all(0),
child: TimeButtonSection(
onToggle: toggleExpanded), // Dein Button-Bereich
),
GridView.builder(
controller: scrollController,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap:
true, // Damit der GridView korrekt in die Column passt
//physics: NeverScrollableScrollPhysics(), // Deaktiviert das Scrolling des GridView
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // Anzahl der Spalten im Grid
//crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
childAspectRatio: (itemWidth / itemHeight),
),
itemCount: singleCategories
.categories.length, // Anzahl der Elemente im Grid
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(6.0),
child: InkWell(
onTap: () async {
final events = await fetchGroupedEvents(
singleCategories.categories[index].category);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Event_Card_small(
event_grouped: events,
color: singleCategories
.categories[index].color,
screen_size: queryData,
category:
singleCategories.categories[index],
)));
},
child: SizedBox(
width: itemWidth,
height: itemHeight.toDouble(),
child: Stack(
children: [
Positioned(
left: 0,
top: 0,
child: Container(
width: itemWidth,
height: itemHeight.toDouble(),
decoration: ShapeDecoration(
image: DecorationImage(
image: AssetImage(singleCategories
.categories[index].imageUrl),
fit: BoxFit.cover,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
shadows: [
BoxShadow(
color: singleCategories
.categories[index].color,
blurRadius: 0,
offset: const Offset(0, 10),
spreadRadius: 0,
)
],
),
],
),
),
),
),
Positioned(
right: 20,
top: 10,
child: SizedBox(
width: 32,
height: 32,
child: SvgPicture.asset(
singleCategories.categories[index].iconUrl,
colorFilter: const ColorFilter.mode(
Colors.white, BlendMode.srcIn),
Positioned(
left: 16,
top: 15,
child: Text(
singleCategories.categories[index].amount
.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 0,
),
),
),
/* Image.asset(
Positioned(
left: 13,
top: singleCategories.categories[index]
.textheight, //86, //TODO Bootom?
child: SizedBox(
width: itemWidth -
20, // Set a fixed width or use constraints
child: Wrap(
children: [
Text(
singleCategories
.categories[index].title,
style: const TextStyle(
color: Colors.white,
fontSize: 24,
fontFamily: 'Inter',
fontWeight: FontWeight.w800,
height: 0,
),
),
],
),
),
),
Positioned(
right: 20,
top: 10,
child: SizedBox(
width: 32,
height: 32,
child: SvgPicture.asset(
singleCategories.categories[index].iconUrl,
colorFilter: const ColorFilter.mode(
Colors.white, BlendMode.srcIn),
),
/* Image.asset(
singleCategories.categories[index].iconUrl,
), */
),
),
),
Positioned(
left: 127,
top: 9,
child: Container(
width: 31,
height: 31,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(),
),
),
],
),
Positioned(
left: 127,
top: 9,
child: Container(
width: 31,
height: 31,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(),
),
),
],
),
),
),
),
);
},
);
},
),
//Body Container
Container(
height: 20,
),
const Footer(),
],
),
//Body Container
Container(
height: 20,
),
const Footer(),
],
),
);
}));
);
})));
return Scaffold(
backgroundColor: Colors.white,

View File

@ -0,0 +1,224 @@
import 'package:Emma_home/utils/class.dart';
import 'package:flutter/material.dart';
import 'package:Emma_home/screens/subheader_Datepicker.dart';
//import 'package:learn_project/main.dart';
import 'package:intl/intl.dart';
import 'package:Emma_home/utils/data.dart';
import 'package:Emma_home/utils/helper_functions.dart';
//import 'package:supabase_flutter/supabase_flutter.dart';
class Event_Card_small extends StatefulWidget {
@override
_Event_Card_small createState() => _Event_Card_small();
final List<Map<String, dynamic>> event_grouped;
final Color color;
final MediaQueryData screen_size;
final Category category;
const Event_Card_small(
{super.key,
required this.event_grouped,
required this.color,
required this.screen_size,
required this.category});
}
class _Event_Card_small extends State<Event_Card_small> {
//final List<Map<String, dynamic>> events;
void toggleExpanded() {}
/* void initState() {
super.initState();
_loadData();
} */
/* */
@override
State<StatefulWidget> createState() {
// TODO: implement createState
throw UnimplementedError();
}
Future<void> _refresh() async {
//setState(() {
// Aktualisiere die Liste (Beispiel: Einfügen neuer Daten)
//_fetchDataFuture = Categories.instance.updateCategoryAmount('Ingolstadt');
//});
}
@override
Widget build(BuildContext context) {
var appBar = AppBar(
leading: SizedBox(
height: 60,
width: 63,
child: IconButton(
icon: Image.asset('assets/images/logo.png'),
onPressed: () {
// Open drawer or perform action
},
),
),
title: Row(
children: [
const SizedBox(
height: 10, //height of button
width: 20, //width of button
child: Icon(Icons.keyboard_arrow_down),
),
const SizedBox(
//width of button
width: 10,
),
SizedBox(
width: 100.0,
child: TextField(
controller: TextEditingController(text: "Ingolstadt"),
decoration: const InputDecoration(
border: UnderlineInputBorder(),
),
),
),
],
),
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {
// Perform search action
},
),
const SizedBox(
height: 40,
child: VerticalDivider(
thickness: 1,
width: 20,
color: Colors.black,
),
),
SizedBox(
height: 50, //height of button
//width of button
child: IconButton(
icon: Image.asset('assets/images/Login.png'),
onPressed: () {},
),
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1.0),
child: Container(
color: Colors.black,
height: 1.0,
),
),
flexibleSpace: Container(),
);
//_loadData();
var body = RefreshIndicator(
onRefresh: _refresh,
child: CustomScrollView(slivers: [
SliverSafeArea(
//minimum: EdgeInsets.zero,
bottom: false,
sliver: SliverToBoxAdapter(
child: Container(
alignment: Alignment.center,
child: Column(children: <Widget>[
Container(height: 10),
Container(
height: 35,
padding: const EdgeInsets.all(0),
child: TimeButtonSection(
onToggle: toggleExpanded), // Dein Button-Bereich
),
Container(
height: 10,
),
SizedBox(
height: 35,
child: Cat_Sub_Header(
name: widget.category.title,
icon: widget.category.iconUrl),
),
//Container(),
])),
),
),
// Gruppierte Events mit SliverMainAxisGroup
...widget.event_grouped.map((group) {
final String startDate = group['start_date'];
final List<Map<String, dynamic>> events = group['events'];
return SliverMainAxisGroup(
slivers: [
// Gruppierungs-Header
SliverToBoxAdapter(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// TODO: muss noch angepasst werden jedes mal wenn ein neuer Tag ist wieder diesen Text anzeigen
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(
left:
20.0), // Abstand von 16 Pixeln zum linken Rand
child: Text(
DateFormat('dd.MM.yyyy')
.format(DateTime.parse(startDate)),
style: const TextStyle(
color: Color(0xFF171717),
fontSize: 12,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
height: 0,
),
),
),
//Kurze Zwischenbereich zum trennen
const SizedBox(height: 4),
],
),
),
// Liste der Events
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final event = events[index];
return EventCard2Section(
title: event['name'],
description: event['description'],
location: event['location_name'] ?? '',
start_time: extractTime24h(event['start']),
color: event['main_category_id'] != null
? extractColor(event['main_category_id'])
: widget.color,
//extractColor(events[index]['main_category_id']),
// oder ein beliebiger Standardwert
screen_size: widget.screen_size,
);
},
childCount: events.length,
),
),
],
);
}),
SliverToBoxAdapter(
child: Column(children: [
const LostEvents(),
Container(height: 20),
const Footer(),
]),
),
]));
return Scaffold(
backgroundColor: Colors.white,
appBar: appBar,
body: body,
);
}
}

View File

@ -1,4 +1,5 @@
import 'dart:math';
import 'package:Emma_home/utils/data.dart';
import 'package:flutter/material.dart';
String shortenText(String text, int maxLength) {
@ -21,6 +22,33 @@ String shortenText(String text, int maxLength) {
return '$shortened ...';
}
String extractTime24h(String timestamp) {
try {
DateTime dateTime = DateTime.parse(timestamp);
String hours = dateTime.hour.toString().padLeft(2, '0');
String minutes = dateTime.minute.toString().padLeft(2, '0');
return '$hours:$minutes';
} catch (e) {
print('Error parsing timestamp: $e');
return '--:--'; // or some other error indicator
}
}
//TODO: Color muss anhand der Categorie entschieden werden
// Also herauslesen welche Category das Event hat
// Dann den richtigen Eintrag in Data identifizieren udn die Farbe auswählen
Color extractColor(String categoryID) {
var singleCategories = Categories.instance;
final result = singleCategories.categories
.where((recipe) => recipe.category == categoryID)
.firstOrNull;
Color categorieColor = const Color.fromARGB(255, 255, 255, 255);
if (result != null) {
categorieColor = result.color;
}
return categorieColor;
}
class ScaleSize {
static double textScaleFactor(BuildContext context,
{double maxTextScaleFactor = 2}) {