Compare commits

..

No commits in common. "72e42a1f47b16d2d7690cd3d83d4037997121a6c" and "aec64cefc31342375c109c72a1c521dbae5aa7a1" have entirely different histories.

10 changed files with 276 additions and 422 deletions

View File

@ -32,16 +32,5 @@
</application>
<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Devices running Android 12L (API level 32) or lower -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Devices running Android 13 (API level 33) or higher -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- To handle the reselection within the app on devices running Android 14
or higher if your app targets Android 14 (API level 34) or higher. -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<!-- ... -->
</manifest>

View File

@ -14,10 +14,6 @@
<string>6.0</string>
<key>CFBundleName</key>
<string>Montomo</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Photo Library Access Warning</string>
<key>NSCameraUsageDescription</key>
<string>This app requires access to the camera.</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>

View File

@ -9,6 +9,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
//import 'package:learn_project/screens/login_page.dart';
//import 'package:learn_project/screens/splash_page.dart';
import 'utils/constants.dart';
import 'package:flutter/services.dart';
Future<void> main() async {
@ -19,18 +20,19 @@ Future<void> main() async {
throw Exception('Error loading .env file: $e'); // Print error if any
}
await Supabase.initialize(
url: dotenv.env['NEXT_PUBLIC_SUPABASE_URL'] ?? 'default_url',
anonKey: dotenv.env['NEXT_PUBLIC_SUPABASE_ANON_KEY'] ?? 'default_key',
url : dotenv.env['NEXT_PUBLIC_SUPABASE_URL'] ?? 'default_url',
anonKey : dotenv.env['NEXT_PUBLIC_SUPABASE_ANON_KEY'] ?? 'default_key',
);
await autoLogin();
var singleCategories = Categories.instance;
var singleCategories = Categories.instance;
singleCategories.updateCategoryAmount('Ingosltadt');
runApp(
ChangeNotifierProvider(
create: (context) => Categories.instance,
child: const MyApp(),
),
);
);
}
/// Supabase client
@ -50,17 +52,16 @@ Future<void> autoLogin() async {
print('AppUser erfolgreich eingeloggt');
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
//set initial orentation to langscape
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown,
DeviceOrientation.portraitUp,
]);
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitDown,
DeviceOrientation.portraitUp,
]);
return MaterialApp(
debugShowCheckedModeBanner: false,
//title: 'Recipes',

View File

@ -6,21 +6,16 @@ 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;
class Frame28 extends StatelessWidget {
final List<Map<String, dynamic>> events;
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() {}
const Frame28({super.key, required this.events, required this.color, required this.screen_size, required this.category});
void toggleExpanded() {
}
/* void initState() {
super.initState();
_loadData();
@ -104,96 +99,100 @@ class Event_Card_small extends StatelessWidget {
child: Container(
alignment: Alignment.center,
child: Column(children: <Widget>[
//Header Container
//HeaderSection(),
Container(height: 10),
Container(
height: 35,
padding: const EdgeInsets.all(0),
child: TimeButtonSection(
onToggle: toggleExpanded), // Dein Button-Bereich
child: TimeButtonSection(onToggle: toggleExpanded), // Dein Button-Bereich
),
Container(
height: 10,
height: 10,
),
SizedBox(
height: 35,
child:
MusikHeader(name: category.title, icon: category.iconUrl),
child: MusikHeader(name:category.title , icon: category.iconUrl),
),
//Container(),
Column(
children: [
SizedBox(
width: 380,
//height: 259,
child: const 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
SizedBox(height: 10),
Padding(
padding: EdgeInsets.only(left: 20.0), // Abstand von 16 Pixeln zum linken Rand
child: Text(
'Heute',
style: TextStyle(
color: Color(0xFF171717),
fontSize: 12,
fontFamily: 'Inter',
fontWeight: FontWeight.w600,
height: 0,
),
),
),
//Kurze Zwischenbereich zum trennen
SizedBox(height: 4),
//EventCard2Section(),
/* const SizedBox(height: 20),
EventCard2Section(),
const SizedBox(height: 20),
Text('Morgen', style: TextStyle(color: Color(0xFF171717), fontSize: 12, fontFamily: 'Inter', fontWeight: FontWeight.w600, height: 0,),),
//Kurze Zwischenbereich zum trennen
const SizedBox(height: 4),
EventCard2Section(),
const SizedBox(height: 20), */
],
),
),
],
),
])),
),
),
// 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))
as String,
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,
),
),
],
);
}).toList(),
SliverToBoxAdapter(
child: Column(children: [
LostEvents(),
Container(height: 20),
Footer(),
]),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return EventCard2Section(
title: events[index]['name'],
description: events[index]['description'],
location: events[index]['location']['name'],
start_time:
extractTime24h(events[index]['time'][0]['start_date']),
color: events[index]['main_category_id'] != null
? extractColor(events[index]['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:[
LostEvents(),
Container(
height: 20),
Footer(),]),
),
]);
return Scaffold(
backgroundColor: Colors.white,
@ -216,16 +215,16 @@ String extractTime24h(String timestamp) {
}
//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;
}
// 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

@ -40,27 +40,9 @@ class _HomePage extends State<HomePage> {
// Überprüfe, ob der Insert erfolgreich war
}
//fetchGroupedEvents
Future<List<Map<String, dynamic>>> fetchGroupedEvents(String category) async {
try {
final response = await supabase
.rpc('get_events_grouped_by_date', params: {'cat_id': category});
// Cast auf die gewünschte Struktur
return (response as List)
.map((entry) => {
'start_date': entry['start_date'], // Das Gruppierungsdatum
'events': (entry['events'] as List)
.cast<Map<String, dynamic>>() // Event-Details
})
.toList();
} catch (e) {
throw Exception('Failed to fetch data: $e');
}
}
Future<List<Map<String, dynamic>>> fetchEvents(String category) async {
try {
//final today = DateTime.now().toUtc().toString().split(' ')[0];
final today = DateTime.now().toUtc().toString().split(' ')[0];
final response = await supabase
.from("events")
//.innerJoin('event_category', 'events.id = event_category.event_id')
@ -262,16 +244,14 @@ class _HomePage extends State<HomePage> {
child: InkWell(
onTap: () async {
/* List<Map<String, dynamic>> events =
await _loadData();
await _loadData(); */
List<Map<String, dynamic>> events2 = await fetchEvents(
singleCategories.categories[index].category);*/
final events = await fetchGroupedEvents(
singleCategories.categories[index].category);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Event_Card_small(
event_grouped: events,
builder: (context) => Frame28(
events: events2,
color: singleCategories
.categories[index].color,
screen_size: queryData,

View File

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:Emma_home/screens/details_db.dart';
import 'package:Emma_home/utils/data.dart';
@ -10,16 +8,8 @@ import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:Emma_home/main.dart';
import 'package:Emma_home/utils/data.dart';
import 'dart:math';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class MissingEvent extends StatefulWidget {
@override
_MissingEvent createState() => _MissingEvent();
}
class _MissingEvent extends State<MissingEvent> {
class MissingEvent extends StatelessWidget {
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
@ -57,87 +47,6 @@ class _MissingEvent extends State<MissingEvent> {
final double itemWidth = (size.width - 40) / 2;
MediaQueryData queryData;
queryData = MediaQuery.of(context);
late File imageFile = File("");
bool isloaded = false;
final ImagePicker _picker = ImagePicker();
Future<void> pickImage() async {
final XFile? image = await _picker.pickImage(
source: ImageSource.gallery,
// Add any desired options, such as image quality
//imageQuality: 100,
//maxWidth: 800,
//maxHeight: 600,
);
if (image != null) {
setState(() {
imageFile = File(image.path);
isloaded = true;
setState(() {});
});
// Use the image file
final String imagePath = image.path;
try {
final fileBytes = await image.readAsBytes();
DateTime now = DateTime.now();
// Datums- und Zeitformat definieren
DateFormat formatter = DateFormat(
'yyyyMMddHHmmss'); // Beachte das große 'HH' für 24-Stunden-Format
// Datum und Uhrzeit als String formatieren
String formattedDateTime = formatter.format(now);
final fileName = '${formattedDateTime}_${image.name}';
await supabase.storage.from('event_upload').uploadBinary(
fileName,
fileBytes,
);
setState(() {});
} catch (e) {
print(e);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error uploading file: ${e.toString()}'),
),
);
}
print('Image path: $imagePath');
dialogSave(context);
} else {
print('No image selected.');
}
}
Future<void> captureImage() async {
final XFile? image = await _picker.pickImage(
source: ImageSource.camera,
//imageQuality: 100,
);
if (image != null) {
final String imagePath = image.path;
try {
final fileBytes = await image.readAsBytes();
final fileName = '${TimeOfDay.now()}_${image.name}';
await supabase.storage.from('event_upload').uploadBinary(
fileName,
fileBytes,
);
setState(() {});
} catch (e) {
print(e);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error uploading file: ${e.toString()}'),
),
);
}
print('Image path: $imagePath');
dialogSave(context);
} else {
print('No image captured.');
}
}
var appBar = AppBar(
leading: SizedBox(
@ -230,12 +139,12 @@ class _MissingEvent extends State<MissingEvent> {
Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: double.infinity,
width: 329,
height: 144,
child: RichText(
text: TextSpan(
text:
'Du hast unterwegs ein Event gesehen, welches noch nicht bei uns in der Liste steht? Schicke uns das Foto von dem Event zu. Wir werden diese, wenn nicht schon geschehen den Events hinzufügen. Danke für deine Unterstützung!',
'Du hast unterwegs ein Event gesehen, \nwelches noch nicht bei uns in der Liste \nsteht? Schicke uns das Foto von dem Event\nzu. Wir werden diese, wenn nicht schon \ngeschehen den Events hinzufügen. \nDanke für deine Unterstützung!',
style: TextStyle(
color: Colors.black,
fontSize: 16,
@ -249,9 +158,9 @@ class _MissingEvent extends State<MissingEvent> {
),
const SizedBox(height: 10),
Container(
width: 300,
height: 200,
padding: const EdgeInsets.symmetric(horizontal: 70, vertical: 85),
width: 329,
height: 155,
padding: const EdgeInsets.symmetric(horizontal: 95, vertical: 35),
decoration: ShapeDecoration(
color: Color(0xFFEDEDED),
shape: RoundedRectangleBorder(
@ -262,42 +171,41 @@ class _MissingEvent extends State<MissingEvent> {
borderRadius: BorderRadius.circular(10),
),
),
child: SizedBox(
width: 200, // Breite des Buttons
height: 50,
child: OutlinedButton.icon(
icon: const Icon(
Icons.image,
size: 10,
),
onPressed: () {
pickImage();
},
style: ButtonStyle(
side: WidgetStateProperty.all(
const BorderSide(
color: Colors.red,
width: 1,
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
/* Container(
width: 36,
height: 36,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(),
child: FlutterLogo(),
), */
const SizedBox(height: 10),
Text(
'Bild hochladen',
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
height: 0,
),
),
],
),
),
label: const Text(
'Bild hochladen',
),
),
],
),
),
/* Padding(
padding: const EdgeInsets.all(8.0),
child: !isloaded
? Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/No_image_available.svg/2048px-No_image_available.svg.png",
width: 100, // Maximalbreite des Bildes
height: 100, // Maximalhöhe des Bildes
fit: BoxFit.contain,
)
: Image.file(imageFile)), */
const SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.min,
@ -339,17 +247,7 @@ class _MissingEvent extends State<MissingEvent> {
Container(
width: 23,
height: 20.70,
child: IconButton(
icon: FaIcon(FontAwesomeIcons.camera, size: 20),
onPressed: () {
// Füge hier die YouTube-Aktion hinzu
captureImage();
},
padding: EdgeInsets
.zero, // Entfernt das Padding des IconButton
constraints:
BoxConstraints(), // Entfernt die Standardbeschränkungen
),
child: Stack(),
),
],
),
@ -359,7 +257,7 @@ class _MissingEvent extends State<MissingEvent> {
const SizedBox(height: 10),
Row(
children: [
/* Container(
Container(
width: 160,
height: 44,
padding: const EdgeInsets.all(10),
@ -374,7 +272,7 @@ class _MissingEvent extends State<MissingEvent> {
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
Text(
'Abrechen',
style: TextStyle(
color: Colors.black,
@ -414,13 +312,13 @@ class _MissingEvent extends State<MissingEvent> {
fontWeight: FontWeight.w500,
height: 0.07,
),
),
),
],
),
),*/
),
],
),
/* const SizedBox(height: 10),
const SizedBox(height: 10),
Text(
'Bock dein Event bei uns zu \npräsentieren? ',
style: TextStyle(
@ -462,7 +360,7 @@ class _MissingEvent extends State<MissingEvent> {
],
),
),
), */
),
],
),
);
@ -474,29 +372,3 @@ class _MissingEvent extends State<MissingEvent> {
);
}
}
Future<void> dialogSave(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Bild wurde gespeichert'),
content: const Text(
'Vielen Dank!\n'
'Das Bild wurde erfolgreich hochgeladen!\n',
),
actions: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: Theme.of(context).textTheme.labelLarge,
),
child: const Text('OK'),
onPressed: () {
Navigator.popUntil(context, (route) => route.isFirst);
},
),
],
);
},
);
}

14
lib/utils/constants.dart Normal file
View File

@ -0,0 +1,14 @@
/// Environment variables and shared app constants.
abstract class Constants {
static const String supabaseUrl = String.fromEnvironment(
//'http://192.168.179.86:8000/', //local
'https://vvtefqdqahcpzgolvupv.supabase.co',
//defaultValue: '',
);
static const String supabaseAnnonKey = String.fromEnvironment(
//'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE2NTIsImV4cCI6MjAzMTU5NzY1Mn0.1bp5V61Oguo5zLUhCFJmCabUY1sujeISr_CR2XUKvh4', // local
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZ2dGVmcWRxYWhjcHpnb2x2dXB2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MTYwMjE3ODksImV4cCI6MjAzMTU5Nzc4OX0.6g5EtS9HrgxC6cpCYgOT0HLpA4lEnASQbKs9mfnUM7k',
//defaultValue: '',
);
}

View File

@ -6,11 +6,10 @@ import 'package:Emma_home/utils/class.dart';
import 'package:Emma_home/main.dart';
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 Categories extends ChangeNotifier {
class Categories extends ChangeNotifier{
// Private constructor
Categories._privateConstructor();
@ -23,88 +22,87 @@ class Categories extends ChangeNotifier {
// Your singleton methods and properties
static final List<Category> _categories = [
Category(
id: '1',
title: 'Musik',
imageUrl: 'assets/images/Musik.png',
iconUrl: 'assets/images/Icons/Icon_Musik.png',
color: const Color.fromARGB(255, 249, 171, 21), //FD4949 //Musik
category: '34725c49-740b-45c5-8a51-7c742f92a621',
textheight: 86,
amount: 0,
),
id: '1',
title: 'Musik',
imageUrl: 'assets/images/Musik.png',
iconUrl:'assets/images/Icons/Icon_Musik.png',
color: const Color.fromARGB(255, 249, 171, 21), //FD4949 //Musik
category: '34725c49-740b-45c5-8a51-7c742f92a621',
textheight: 86,
amount:0,
),
Category(
id: '2',
title: 'Nachtleben',
imageUrl: 'assets/images/Nachtleben.png',
iconUrl: 'assets/images/Icons/Icon_Nachtleben.png',
color: const Color.fromARGB(255, 253, 73, 73), //FD4949 //Nachtleben
category: '2d8c714e-3290-4d8c-8a95-e3b100ad8599',
textheight: 86,
amount: 0,
),
id: '2',
title: 'Nachtleben',
imageUrl: 'assets/images/Nachtleben.png',
iconUrl:'assets/images/Icons/Icon_Nachtleben.png',
color: const Color.fromARGB(255, 253, 73, 73), //FD4949 //Nachtleben
category: '2d8c714e-3290-4d8c-8a95-e3b100ad8599',
textheight: 86,
amount:0,
),
Category(
id: '3',
title: 'Kunst & Kultur',
imageUrl: 'assets/images/Kultur.png',
iconUrl: 'assets/images/Icons/Icon_Kultur.png',
color: const Color.fromARGB(255, 80, 168, 250), //50A8FA//Kunst
category: '09d1f862-2b56-47af-8ee6-3c50056e3fa2',
textheight: 58,
amount: 0,
),
id: '3',
title: 'Kunst & Kultur',
imageUrl: 'assets/images/Kultur.png',
iconUrl:'assets/images/Icons/Icon_Kultur.png',
color: const Color.fromARGB(255, 80, 168, 250), //50A8FA//Kunst
category: '09d1f862-2b56-47af-8ee6-3c50056e3fa2',
textheight: 58,
amount:0,
),
Category(
id: '4',
title: 'Sport & Verein',
imageUrl: 'assets/images/Sport.png',
iconUrl: 'assets/images/Icons/Icon_Sport.png',
color: const Color.fromARGB(255, 80, 240, 250), //50F0FA //Sport
category: '15119876-9ff0-41e5-8fe5-c3675af5e054',
textheight: 58,
amount: 0,
),
id: '4',
title: 'Sport & Verein',
imageUrl: 'assets/images/Sport.png',
iconUrl:'assets/images/Icons/Icon_Sport.png',
color: const Color.fromARGB(255, 80, 240, 250), //50F0FA //Sport
category: '15119876-9ff0-41e5-8fe5-c3675af5e054',
textheight: 58,
amount:0,
),
Category(
id: '5',
title: 'Gesundheit',
imageUrl: 'assets/images/Gesundheit.png',
iconUrl: 'assets/images/Icons/Icon_Gesundheit.png',
color: const Color.fromARGB(255, 130, 73, 253), //8249FD //Gesundheit
category: '4ad3ac2d-04fc-4aa1-afae-17ec7bfc1714',
textheight: 86,
amount: 0,
),
id: '5',
title: 'Gesundheit',
imageUrl: 'assets/images/Gesundheit.png',
iconUrl:'assets/images/Icons/Icon_Gesundheit.png',
color: const Color.fromARGB(255,130, 73, 253), //8249FD //Gesundheit
category: '4ad3ac2d-04fc-4aa1-afae-17ec7bfc1714',
textheight: 86,
amount:0,
),
Category(
id: '6',
title: 'Essen & Trinken',
imageUrl: 'assets/images/Essen.png',
iconUrl: 'assets/images/Icons/Icon_Essen.png',
color: const Color.fromARGB(255, 253, 73, 73), //FD4949//Essen
category: 'ef83c4d3-228a-44e1-8a5d-8b47d2dfc351',
textheight: 58,
amount: 0,
),
id: '6',
title: 'Essen & Trinken',
imageUrl: 'assets/images/Essen.png',
iconUrl:'assets/images/Icons/Icon_Essen.png',
color: const Color.fromARGB(255,253, 73,73), //FD4949//Essen
category: 'ef83c4d3-228a-44e1-8a5d-8b47d2dfc351',
textheight: 58,
amount:0,
),
Category(
id: '7',
title: 'Soziales',
imageUrl: 'assets/images/Soziales.png',
iconUrl: 'assets/images/Icons/Icon_Soziales.png',
color: const Color.fromARGB(255, 255, 0, 199), //FF00C7//Essen
category: '53a1782b-e07b-491d-b778-d99ef9cf57e2',
textheight: 86,
amount: 0,
),
id: '7',
title: 'Soziales',
imageUrl: 'assets/images/Soziales.png',
iconUrl:'assets/images/Icons/Icon_Soziales.png',
color: const Color.fromARGB(255,255,0,199), //FF00C7//Essen
category: '53a1782b-e07b-491d-b778-d99ef9cf57e2',
textheight: 86,
amount:0,
),
Category(
id: '8',
title: 'Familie',
imageUrl: 'assets/images/Familie.png',
iconUrl: 'assets/images/Icons/Icon_Familie.png',
color: const Color.fromARGB(
255, 66, 255, 0), //42FF00//Essen //HSL 104 100 50 100
category: '30cb3481-c425-4068-9714-adc86df85d3f',
textheight: 86,
amount: 0,
),
id: '8',
title: 'Familie',
imageUrl: 'assets/images/Familie.png',
iconUrl:'assets/images/Icons/Icon_Familie.png',
color: const Color.fromARGB(255,66,255,0), //42FF00//Essen //HSL 104 100 50 100
category: '30cb3481-c425-4068-9714-adc86df85d3f',
textheight: 86,
amount:0,
),
];
void addCategory(Category category) {
category.add(category);
notifyListeners();
@ -121,31 +119,27 @@ class Categories extends ChangeNotifier {
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++) {
//TODO: man müsste sicherstellen, dass die Main Category bei allen Events existent ist. Und dass in den jeweilige Subcategorien nicht die MainCatgeorie vorkommt. Erst dann kann das möglich sein.
//müsste man auch in der Admin Page ermöglichen.
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) {
}}
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;
}
return;
}
// Method to get all items
// Method to get all items
List<Category> get categories => List.unmodifiable(_categories);
// Method to clear all items
@ -157,12 +151,18 @@ class Categories extends ChangeNotifier {
int get itemCount => _categories.length;
}
class SupabaseDataService {
Future<List<Map<String, dynamic>>> fetchEvents(String category) async {
try {
final today = DateTime.now().toUtc().toString().split(' ')[0];
final response = await supabase
.from("events")
.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);
@ -177,11 +177,14 @@ class SupabaseDataService {
}
}
Future<Map<String, dynamic>> fetchSingleRecord(
String tableName, String id) async {
Future<Map<String, dynamic>> fetchSingleRecord(String tableName, String id) async {
try {
final response =
await supabase.from(tableName).select().eq('id', id).single();
final response = await supabase
.from(tableName)
.select()
.eq('id', id)
.single();
return response;
} catch (e) {
@ -353,4 +356,4 @@ class _NetworkException implements Exception {
},
),
);
} */
} */