eksplicit mapping af envs
This commit is contained in:
201
app/lib/screens/profile_screen.dart
Normal file
201
app/lib/screens/profile_screen.dart
Normal file
@@ -0,0 +1,201 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:sighej/services/session_store.dart';
|
||||
|
||||
const List<String> kAvailableInterests = [
|
||||
'Tech',
|
||||
'Musik',
|
||||
'Filosofi',
|
||||
'Design',
|
||||
'DevOps',
|
||||
'Bøger',
|
||||
'Gaming',
|
||||
'Fitness',
|
||||
'Kunst',
|
||||
'Mad',
|
||||
'Rejser',
|
||||
'Videnskab',
|
||||
'Iværksætteri',
|
||||
'Film',
|
||||
'Natur',
|
||||
'Kodning',
|
||||
'Podcast',
|
||||
'Arkitektur',
|
||||
'Klima',
|
||||
'Sport',
|
||||
];
|
||||
|
||||
class ProfileScreen extends StatefulWidget {
|
||||
/// If [isSetup] is true, the screen is shown as first-run onboarding.
|
||||
/// If false, it's opened from the home screen as "rediger profil".
|
||||
final bool isSetup;
|
||||
|
||||
const ProfileScreen({super.key, this.isSetup = false});
|
||||
|
||||
@override
|
||||
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||
}
|
||||
|
||||
class _ProfileScreenState extends State<ProfileScreen> {
|
||||
late final TextEditingController _nameCtrl;
|
||||
late final TextEditingController _taglineCtrl;
|
||||
late final Set<String> _selected;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final store = context.read<SessionStore>();
|
||||
_nameCtrl = TextEditingController(text: store.name);
|
||||
_taglineCtrl = TextEditingController(text: store.tagline);
|
||||
_selected = Set<String>.from(store.interests);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_nameCtrl.dispose();
|
||||
_taglineCtrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
await context.read<SessionStore>().saveProfile(
|
||||
name: _nameCtrl.text.trim(),
|
||||
tagline: _taglineCtrl.text.trim(),
|
||||
interests: _selected.toList(),
|
||||
);
|
||||
if (mounted) Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isSetup = widget.isSetup;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(isSetup ? 'Hvem er du?' : 'Din profil'),
|
||||
automaticallyImplyLeading: !isSetup,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (isSetup) ...[
|
||||
Text(
|
||||
'SigHej sender en diskret notifikation, når nogen i nærheden deler dine interesser. '
|
||||
'Ingen profiler at swipe — bare et lille vink om at starte en samtale.',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 28),
|
||||
],
|
||||
_SectionLabel('Kaldenavn', hint: 'Valgfrit — hvad vil du kaldes?'),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _nameCtrl,
|
||||
maxLength: 40,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'F.eks. "Henrik" eller "Tech-nerd"',
|
||||
border: OutlineInputBorder(),
|
||||
counterText: '',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_SectionLabel(
|
||||
'Hvad er du op til i dag?',
|
||||
hint: 'Valgfrit — sæt tonen',
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: _taglineCtrl,
|
||||
maxLength: 80,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'F.eks. "Åben for en kaffesnak" eller "Op til at netværke"',
|
||||
border: OutlineInputBorder(),
|
||||
counterText: '',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_SectionLabel(
|
||||
'Hvad interesserer dig?',
|
||||
hint: 'Vi finder folk med fælles interesser i nærheden',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: kAvailableInterests.map((interest) {
|
||||
final selected = _selected.contains(interest);
|
||||
return FilterChip(
|
||||
label: Text(interest),
|
||||
selected: selected,
|
||||
onSelected: (val) => setState(
|
||||
() => val
|
||||
? _selected.add(interest)
|
||||
: _selected.remove(interest),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
if (_selected.isEmpty)
|
||||
Text(
|
||||
'Vælg mindst ét emne for at bruge SigHej.',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 8, 24, 24),
|
||||
child: FilledButton(
|
||||
onPressed: _selected.isEmpty ? null : _save,
|
||||
style: FilledButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(52),
|
||||
),
|
||||
child: Text(isSetup ? 'Kom i gang' : 'Gem'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SectionLabel extends StatelessWidget {
|
||||
final String label;
|
||||
final String? hint;
|
||||
|
||||
const _SectionLabel(this.label, {this.hint});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: Theme.of(context).textTheme.titleSmall),
|
||||
if (hint != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
hint!,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user