Added UserDataPage (first draft)

master
Rafael 2024-05-05 01:02:09 +02:00
parent 952a8673f0
commit 25f456a193
4 changed files with 257 additions and 0 deletions

View File

@ -1,3 +1,4 @@
import 'package:cofounderella/pages/user_data_page.dart';
import 'package:cofounderella/services/auth/auth_service.dart';
import 'package:cofounderella/pages/settings_page.dart';
import 'package:flutter/material.dart';
@ -85,6 +86,26 @@ class MyDrawer extends StatelessWidget {
),
),
// TODO TESTING - user data tile
Padding(
padding: const EdgeInsets.only(left: 25),
child: ListTile(
title: const Text("User Data"),
leading: const Icon(Icons.supervised_user_circle),
onTap: () {
// pop the drawer
Navigator.pop(context);
//navigate to settings page
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserDataPage(),
));
},
),
),
// horizontal line
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),

View File

@ -0,0 +1,23 @@
class Language {
final String code;
final String name;
final String nativeName;
final String iconFile;
Language({
required this.code,
required this.name,
required this.nativeName,
required this.iconFile,
});
// convert to a map
Map<String, dynamic> toMap() {
return {
'code': code,
'name': name,
'nativeName': nativeName,
'iconFile': iconFile,
};
}
}

View File

@ -0,0 +1,11 @@
import 'language.dart';
class LanguageSetting {
Language language;
bool isSelected;
LanguageSetting({
required this.language,
this.isSelected = false,
});
}

View File

@ -0,0 +1,202 @@
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cofounderella/components/my_button.dart';
import 'package:cofounderella/components/my_textfield.dart';
import 'package:cofounderella/models/language.dart';
import 'package:cofounderella/models/language_setting.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:cofounderella/services/auth/auth_service.dart';
class UserDataPage extends StatefulWidget {
const UserDataPage({super.key});
@override
State<UserDataPage> createState() => _UserDataPageState();
}
class _UserDataPageState extends State<UserDataPage> {
final TextEditingController _locationController = TextEditingController();
final TextEditingController _birthdayController = TextEditingController();
final TextEditingController _genderController = TextEditingController();
List<LanguageSetting> languagesList = [];
final List<Language> _selectedLanguages = [];
// get instance of firestore and auth
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final AuthService _authService = AuthService();
@override
void initState() {
super.initState();
// Load data from JSON file when the widget initializes
loadLanguagesFromJson();
}
void saveUserData(BuildContext context) async {
// get userID from auth service
String currentUserID = _authService.getCurrentUser()!.uid;
// Get reference to the Firebase collection
CollectionReference languagesRef = _firestore
.collection('Users')
.doc(currentUserID)
.collection('languages');
// Loop through each Language object and save it to the collection
for (int i = 0; i < _selectedLanguages.length; i++) {
// Convert Language object to a map and add the map to the collection,
// using .doc(myID).set() instead of .add() to avoid duplicates.
await languagesRef
.doc(_selectedLanguages[i].code)
.set(_selectedLanguages[i].toMap());
}
// List to store language codes from the provided list
List<String> languageCodes =
_selectedLanguages.map((language) => language.code).toList();
// Clean up languages that were not part of the provided list
await deleteUnusedDocuments(languagesRef, languageCodes);
}
/// Deletes documents from collection that are not part of the provided list
Future<void> deleteUnusedDocuments(
CollectionReference refCollection, List<String> idsToKeep) async {
// Fetch the existing documents from the database
QuerySnapshot snapshot = await refCollection.get();
// Loop through each document in the collection
for (QueryDocumentSnapshot doc in snapshot.docs) {
String documentId = doc.id;
// If the language code is not in the provided list, delete the document
if (!idsToKeep.contains(documentId)) {
await doc.reference.delete();
}
}
}
Future<void> loadLanguagesFromJson() async {
// Load JSON data from assets
String jsonData = await rootBundle.loadString('lib/assets/languages.json');
// Parse JSON into a list of objects
List<dynamic> jsonList = await json.decode(jsonData);
// Create LanguageSetting objects from JSON data
languagesList = jsonList.map((item) {
Language language = Language(
code: item['code'],
name: item['name'],
nativeName: item['nativeName'],
iconFile: item['iconFile'],
);
// TODO Werte aus DB laden
return LanguageSetting(language: language);
}).toList();
// Update the UI after loading data
setState(() {
// TODO ?
});
}
@override
Widget build(BuildContext context) {
if (languagesList.isEmpty) {
return const Center(child: CircularProgressIndicator());
} else {
return Scaffold(
appBar: AppBar(
title: const Text("User Data"),
centerTitle: true,
),
body: ListView(
children: [
const Text(
'Location',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
MyTextField(
hintText: "Location",
obscureText: false,
controller: _locationController,
),
const Text(
'Birthday',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
MyTextField(
hintText: "Birthday",
obscureText: false,
controller: _birthdayController,
),
const Text(
'Gender',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
MyTextField(
hintText: "Gender",
obscureText: false,
controller: _genderController,
),
const Divider(),
Text(
'Language: (${_selectedLanguages.length} selected)',
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
...languagesList.map(buildSingleCheckbox), // ... spread operator
const Divider(),
Padding(
padding: const EdgeInsets.all(8.0),
child: MyButton(text: "Save", onTap: () => saveUserData(context)),
)
],
),
);
}
}
Widget buildSingleCheckbox(LanguageSetting languageSetting) => buildCheckbox(
languageSetting: languageSetting,
onClicked: () {
setState(() {
final newValue = !languageSetting.isSelected;
languageSetting.isSelected = newValue;
if (languageSetting.isSelected &&
!_selectedLanguages.contains(languageSetting.language)) {
_selectedLanguages.add(languageSetting.language);
} else if (languageSetting.isSelected == false) {
_selectedLanguages.removeWhere(
(element) => element.code == languageSetting.language.code);
}
});
},
);
Widget buildCheckbox({
required LanguageSetting languageSetting,
required VoidCallback onClicked,
}) =>
ListTile(
tileColor: Colors.greenAccent,
onTap: onClicked,
leading: SizedBox(
width: 48,
height: 32,
child: SvgPicture.asset(
languageSetting.language.iconFile,
),
),
title: Text(
languageSetting.language.nativeName,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
subtitle: Text(languageSetting.language.name),
trailing: Checkbox(
value: languageSetting.isSelected,
onChanged: (value) => onClicked(),
),
);
}