TimeZone support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'package:blind_master/BlindMasterResources/error_snackbar.dart';
|
||||
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
||||
import 'package:blind_master/BlindMasterResources/timezone_picker.dart';
|
||||
import 'package:blind_master/BlindMasterScreens/accountManagement/change_password_screen.dart';
|
||||
import 'package:blind_master/BlindMasterScreens/accountManagement/change_email_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -17,6 +18,7 @@ class _AccountScreenState extends State<AccountScreen> {
|
||||
String? name;
|
||||
String? email;
|
||||
String? createdAt;
|
||||
String? timezone;
|
||||
bool isLoading = true;
|
||||
|
||||
@override
|
||||
@@ -38,7 +40,8 @@ class _AccountScreenState extends State<AccountScreen> {
|
||||
setState(() {
|
||||
name = body['name'] ?? 'N/A';
|
||||
email = body['email'] ?? 'N/A';
|
||||
|
||||
timezone = body['timezone'] as String?;
|
||||
|
||||
// Parse and format the created_at timestamp
|
||||
if (body['created_at'] != null) {
|
||||
try {
|
||||
@@ -67,6 +70,64 @@ class _AccountScreenState extends State<AccountScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
String _tzAbbrev(String? ianaKey) {
|
||||
if (ianaKey == null) return 'None (UTC)';
|
||||
final match = kTimezones.firstWhere(
|
||||
(tz) => tz['tz'] == ianaKey,
|
||||
orElse: () => {'display': ianaKey, 'tz': ianaKey},
|
||||
);
|
||||
final display = match['display']!;
|
||||
final parenMatch = RegExp(r'\(([^)]+)\)').firstMatch(display);
|
||||
return parenMatch?.group(1) ?? display;
|
||||
}
|
||||
|
||||
Future<void> _handleChangeTimezone() async {
|
||||
String? selected = timezone;
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (dialogContext) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setDialogState) {
|
||||
return AlertDialog(
|
||||
title: const Text('Account Timezone'),
|
||||
content: TimezonePicker(
|
||||
value: selected,
|
||||
label: 'Default Timezone',
|
||||
onChanged: (tz) => setDialogState(() => selected = tz),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(false),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).primaryColorLight,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
onPressed: () => Navigator.of(dialogContext).pop(true),
|
||||
child: const Text('Save'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (confirmed == true && selected != null && mounted) {
|
||||
try {
|
||||
final response = await securePost({'timezone': selected}, 'update_user_timezone');
|
||||
if (response == null) throw Exception('No response');
|
||||
if (response.statusCode != 200) throw Exception('Failed to update timezone');
|
||||
setState(() => timezone = selected);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleDeleteAccount() async {
|
||||
final primaryColor = Theme.of(context).primaryColorLight;
|
||||
|
||||
@@ -268,6 +329,13 @@ class _AccountScreenState extends State<AccountScreen> {
|
||||
);
|
||||
},
|
||||
),
|
||||
Divider(height: 1),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.access_time),
|
||||
title: Text('Timezone: ${_tzAbbrev(timezone)}'),
|
||||
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||
onTap: _handleChangeTimezone,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user