mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-03-03 10:36:47 +00:00
261 lines
8.1 KiB
Dart
261 lines
8.1 KiB
Dart
// ignore_for_file: avoid_dynamic_calls
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:twonly/src/utils/keyvalue.dart';
|
|
import 'package:twonly/src/utils/misc.dart';
|
|
import 'package:twonly/src/utils/storage.dart';
|
|
import 'package:twonly/src/views/user_study/user_study_data_collection.dart';
|
|
|
|
class UserStudyQuestionnaireView extends StatefulWidget {
|
|
const UserStudyQuestionnaireView({super.key});
|
|
|
|
@override
|
|
State<UserStudyQuestionnaireView> createState() =>
|
|
_UserStudyQuestionnaireViewState();
|
|
}
|
|
|
|
class _UserStudyQuestionnaireViewState
|
|
extends State<UserStudyQuestionnaireView> {
|
|
final Map<String, dynamic> _responses = {
|
|
'age': null,
|
|
'education': null,
|
|
'education_free': '',
|
|
'vocational': null,
|
|
'vocational_free': '',
|
|
'enrolled': null,
|
|
'study_program': '',
|
|
'working': null,
|
|
'work_field': '',
|
|
'smartphone_2years': null,
|
|
'comp_knowledge': null,
|
|
'security_knowledge': null,
|
|
'messengers': [],
|
|
'is_release_mode': kReleaseMode,
|
|
};
|
|
|
|
final List<String> _messengerOptions = [
|
|
'WhatsApp',
|
|
'Signal',
|
|
'Telegram',
|
|
'Facebook Messenger',
|
|
'iMessage',
|
|
'Teams',
|
|
'Viber',
|
|
'Element',
|
|
'Andere',
|
|
];
|
|
|
|
Future<void> _submitData() async {
|
|
await KeyValueStore.put(userStudySurveyKey, _responses);
|
|
|
|
await updateUserdata((u) {
|
|
// generate a random participants id to identify data send later while keeping the user anonym
|
|
u
|
|
..userStudyParticipantsToken = getRandomString(25)
|
|
..askedForUserStudyPermission = true;
|
|
return u;
|
|
});
|
|
|
|
await handleUserStudyUpload();
|
|
|
|
if (!mounted) return;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('Vielen Dank für deine Teilnahme!')),
|
|
);
|
|
|
|
context.pop();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('Befragung')),
|
|
body: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_sectionTitle('Demografische Daten'),
|
|
_questionText('Wie alt bist du?'),
|
|
_buildRadioList(
|
|
[
|
|
'18-22',
|
|
'23-27',
|
|
'28-32',
|
|
'33-37',
|
|
'38-42',
|
|
'43-47',
|
|
'48-52',
|
|
'53-57',
|
|
'58-62',
|
|
'63-67',
|
|
'68-72',
|
|
'73-77',
|
|
'77 oder älter',
|
|
'Keine Angabe',
|
|
],
|
|
'age',
|
|
),
|
|
_questionText('Was ist dein höchster Schulabschluss?'),
|
|
_buildRadioList(
|
|
[
|
|
'Noch in der Schule',
|
|
'Hauptschulabschluss',
|
|
'POS (Polytechnische Oberschule)',
|
|
'Realschulabschluss',
|
|
'Abitur / Hochschulreife',
|
|
'Kein Abschluss',
|
|
'Keine Angabe',
|
|
],
|
|
'education',
|
|
),
|
|
_buildTextField(
|
|
'Freitext (optional)',
|
|
(val) => _responses['education_free'] = val,
|
|
),
|
|
_questionText('Was ist dein höchster beruflicher Abschluss?'),
|
|
_buildRadioList(
|
|
[
|
|
'Berufsausbildung / Duales System',
|
|
'Fachschulabschluss',
|
|
'Fachschulabschluss (ehem. DDR)',
|
|
'Bachelor',
|
|
'Master',
|
|
'Diplom',
|
|
'Promotion (PhD)',
|
|
'Kein beruflicher Abschluss',
|
|
'Keine Angabe',
|
|
],
|
|
'vocational',
|
|
),
|
|
_buildTextField(
|
|
'Freitext (optional)',
|
|
(val) => _responses['vocational_free'] = val,
|
|
),
|
|
_questionText(
|
|
'Bist du derzeit in einem Studiengang eingeschrieben? (Bachelor, Master, Diplom, Staatsexamen, Magister)',
|
|
),
|
|
_buildRadioList(['Ja', 'Nein', 'Keine Angabe'], 'enrolled'),
|
|
_questionText('Wenn ja, welcher Studiengang?'),
|
|
_buildTextField(
|
|
'Studiengang eingeben',
|
|
(val) => _responses['study_program'] = val,
|
|
),
|
|
_questionText('Bist du derzeit berufstätig?'),
|
|
_buildRadioList(['Ja', 'Nein', 'Keine Angabe'], 'working'),
|
|
_questionText('Wenn ja, in welchem Bereich arbeiten Sie?'),
|
|
_buildTextField(
|
|
'Arbeitsbereich eingeben',
|
|
(val) => _responses['work_field'] = val,
|
|
),
|
|
const SizedBox(height: 30),
|
|
// const Divider(),
|
|
_sectionTitle('Technisches Wissen'),
|
|
_questionText(
|
|
'Nutzt du seit mehr als zwei Jahren ein Smartphone?',
|
|
),
|
|
_buildRadioList(['Ja', 'Nein'], 'smartphone_2years'),
|
|
_questionText(
|
|
'Wie schätzt du deine allgemeinen Computerkenntnisse ein?',
|
|
),
|
|
_buildRadioList(
|
|
['Anfänger', 'Mittel', 'Fortgeschritten'],
|
|
'comp_knowledge',
|
|
),
|
|
_questionText(
|
|
'Wie schätzt du dein Wissen im Bereich IT-Sicherheit ein?',
|
|
),
|
|
_buildRadioList(
|
|
['Anfänger', 'Mittel', 'Fortgeschritten'],
|
|
'security_knowledge',
|
|
),
|
|
_questionText(
|
|
'Welche der folgenden Messenger hast du schon einmal benutzt?',
|
|
),
|
|
..._messengerOptions.map(
|
|
(m) => CheckboxListTile(
|
|
title: Text(m),
|
|
visualDensity: const VisualDensity(vertical: -4),
|
|
value: (_responses['messengers'] as List<dynamic>).contains(m),
|
|
onChanged: (value) {
|
|
setState(() {
|
|
value!
|
|
? _responses['messengers'].add(m)
|
|
: _responses['messengers'].remove(m);
|
|
});
|
|
},
|
|
),
|
|
),
|
|
const SizedBox(height: 30),
|
|
Center(
|
|
child: FilledButton(
|
|
onPressed: _submitData,
|
|
child: const Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
|
|
child:
|
|
Text('Jetzt teilnehmen', style: TextStyle(fontSize: 18)),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 50),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Hilfsmethoden für das UI
|
|
Widget _sectionTitle(String title) => Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
child: Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
);
|
|
|
|
Widget _questionText(String text) => Padding(
|
|
padding: const EdgeInsets.only(top: 20, bottom: 5),
|
|
child: Text(
|
|
text,
|
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
|
),
|
|
);
|
|
|
|
Widget _buildRadioList(List<String> options, String key) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: DropdownButtonFormField<String>(
|
|
decoration: const InputDecoration(
|
|
border: OutlineInputBorder(),
|
|
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
labelText: 'Bitte wählen...',
|
|
),
|
|
initialValue: _responses[key] as String?,
|
|
items: options.map((value) {
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(value),
|
|
);
|
|
}).toList(),
|
|
onChanged: (val) {
|
|
setState(() {
|
|
_responses[key] = val;
|
|
});
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTextField(String hint, void Function(String) onChanged) {
|
|
return TextField(
|
|
decoration:
|
|
InputDecoration(hintText: hint, border: const OutlineInputBorder()),
|
|
onChanged: onChanged,
|
|
);
|
|
}
|
|
}
|