Compare commits
No commits in common. "72e42a1f47b16d2d7690cd3d83d4037997121a6c" and "aec64cefc31342375c109c72a1c521dbae5aa7a1" have entirely different histories.
72e42a1f47
...
aec64cefc3
|
|
@ -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>
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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: '',
|
||||
);
|
||||
}
|
||||
|
|
@ -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 {
|
|||
},
|
||||
),
|
||||
);
|
||||
} */
|
||||
} */
|
||||
Loading…
Reference in New Issue