Fix calendar navigation, task deletion, and language defaults
- Add date parameter support to DailyAgendaPage for calendar navigation - Add popup menu to task tile with delete and reschedule options - Set default locale to English when none is saved - Update API base URL comment for desktop vs Android
This commit is contained in:
parent
820b35f5e6
commit
864560ef2e
@ -27,11 +27,7 @@ class SettingsPage extends StatelessWidget {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.language),
|
||||
title: Text(l10n.language),
|
||||
subtitle: Text(
|
||||
settingsVm.locale != null
|
||||
? settingsVm.getLanguageName(settingsVm.locale!)
|
||||
: l10n.systemDefault,
|
||||
),
|
||||
subtitle: Text(settingsVm.getLanguageName(settingsVm.locale!)),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
onTap: () => _showLanguageDialog(context, settingsVm, l10n),
|
||||
),
|
||||
@ -107,12 +103,12 @@ class _LanguageDialog extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LanguageDialogState extends State<_LanguageDialog> {
|
||||
late Locale? _selectedLocale;
|
||||
late String _selectedLanguage;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedLocale = widget.vm.locale;
|
||||
_selectedLanguage = widget.vm.locale!.languageCode;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -121,27 +117,27 @@ class _LanguageDialogState extends State<_LanguageDialog> {
|
||||
title: Text(widget.l10n.language),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: SettingsViewModel.supportedLocales.map((locale) {
|
||||
return ListTile(
|
||||
title: Text(widget.vm.getLanguageName(locale)),
|
||||
leading: Radio<Locale>(
|
||||
value: locale,
|
||||
groupValue: _selectedLocale,
|
||||
onChanged: (value) {
|
||||
setState(() => _selectedLocale = value);
|
||||
if (value != null) {
|
||||
widget.vm.setLocale(value);
|
||||
children: [
|
||||
...SettingsViewModel.supportedLocales.map((locale) {
|
||||
return ListTile(
|
||||
title: Text(widget.vm.getLanguageName(locale)),
|
||||
leading: Radio<String>(
|
||||
value: locale.languageCode,
|
||||
groupValue: _selectedLanguage,
|
||||
onChanged: (value) {
|
||||
setState(() => _selectedLanguage = value!);
|
||||
widget.vm.setLocale(locale);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
setState(() => _selectedLanguage = locale.languageCode);
|
||||
widget.vm.setLocale(locale);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
setState(() => _selectedLocale = locale);
|
||||
widget.vm.setLocale(locale);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
|
||||
@ -26,7 +26,7 @@ class SettingsViewModel extends ChangeNotifier {
|
||||
];
|
||||
|
||||
void _loadSettings() {
|
||||
_locale = dataSource.getLocale();
|
||||
_locale = dataSource.getLocale() ?? const Locale('en');
|
||||
_themeMode = dataSource.getThemeMode();
|
||||
logger.info('Settings loaded: locale=$_locale, themeMode=$_themeMode');
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@ class TaskRemoteDataSourceImpl implements TaskRemoteDataSource {
|
||||
final AppLogger logger;
|
||||
final http.Client _client;
|
||||
|
||||
static const String _baseUrl = 'http://10.0.2.2:8000';
|
||||
// Use 10.0.2.2 for Android emulator, localhost for desktop/web
|
||||
static const String _baseUrl = 'http://localhost:8000';
|
||||
|
||||
TaskRemoteDataSourceImpl({
|
||||
required this.logger,
|
||||
|
||||
@ -10,12 +10,25 @@ import '../widgets/task_tile.dart';
|
||||
import '../widgets/filter_chips.dart';
|
||||
|
||||
class DailyAgendaPage extends StatelessWidget {
|
||||
const DailyAgendaPage({super.key});
|
||||
final String? initialDate;
|
||||
|
||||
const DailyAgendaPage({super.key, this.initialDate});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider(
|
||||
create: (_) => getIt<DailyTasksViewModel>()..loadTasks(),
|
||||
create: (_) {
|
||||
final vm = getIt<DailyTasksViewModel>();
|
||||
if (initialDate != null) {
|
||||
final date = DateTime.tryParse(initialDate!);
|
||||
if (date != null) {
|
||||
vm.setSelectedDate(date);
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
vm.loadTasks();
|
||||
return vm;
|
||||
},
|
||||
child: const _DailyAgendaView(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -118,10 +118,55 @@ class TaskTile extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.schedule),
|
||||
onPressed: onReschedule,
|
||||
tooltip: l10n.rescheduleToTomorrow,
|
||||
PopupMenuButton<String>(
|
||||
onSelected: (value) async {
|
||||
if (value == 'reschedule') {
|
||||
onReschedule();
|
||||
} else if (value == 'delete') {
|
||||
final confirm = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(l10n.deleteTask),
|
||||
content: Text(l10n.deleteTaskConfirm),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: Text(l10n.delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (confirm == true) {
|
||||
onDelete();
|
||||
}
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'reschedule',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.schedule),
|
||||
const SizedBox(width: 8),
|
||||
Text(l10n.rescheduleToTomorrow),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.delete, color: Theme.of(context).colorScheme.error),
|
||||
const SizedBox(width: 8),
|
||||
Text(l10n.delete, style: TextStyle(color: Theme.of(context).colorScheme.error)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@ -12,7 +12,10 @@ class AppRouter {
|
||||
GoRoute(
|
||||
path: '/',
|
||||
name: 'daily',
|
||||
builder: (context, state) => const DailyAgendaPage(),
|
||||
builder: (context, state) {
|
||||
final dateStr = state.uri.queryParameters['date'];
|
||||
return DailyAgendaPage(initialDate: dateStr);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/calendar',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user