xworkmate-app/lib/features/mobile/mobile_settings_page_widgets.dart

186 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import '../../models/app_models.dart';
import '../../theme/app_palette.dart';
class MobileSettingsTabSelectorInternal extends StatelessWidget {
const MobileSettingsTabSelectorInternal({
super.key,
required this.currentTab,
required this.availableTabs,
required this.onChanged,
});
final SettingsTab currentTab;
final List<SettingsTab> availableTabs;
final ValueChanged<SettingsTab> onChanged;
@override
Widget build(BuildContext context) {
return SegmentedButton<SettingsTab>(
key: const Key('mobile-settings-tab-selector'),
segments: [
for (final tab in availableTabs)
ButtonSegment<SettingsTab>(
value: tab,
icon: Icon(
tab == SettingsTab.archivedTasks
? Icons.inventory_2_outlined
: Icons.hub_outlined,
),
label: Text(tab.label),
),
],
selected: <SettingsTab>{currentTab},
onSelectionChanged: (selection) {
if (selection.isNotEmpty) {
onChanged(selection.first);
}
},
);
}
}
class MobileSettingsCardInternal extends StatelessWidget {
const MobileSettingsCardInternal({
super.key,
required this.icon,
required this.title,
required this.subtitle,
required this.children,
});
final IconData icon;
final String title;
final String subtitle;
final List<Widget> children;
@override
Widget build(BuildContext context) {
final palette = context.palette;
return DecoratedBox(
decoration: BoxDecoration(
color: palette.surfacePrimary,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: palette.strokeSoft),
),
child: Padding(
padding: const EdgeInsets.all(14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, color: palette.accent, size: 24),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium,
),
if (subtitle.trim().isNotEmpty) ...[
const SizedBox(height: 4),
Text(
subtitle,
style: Theme.of(context).textTheme.bodySmall
?.copyWith(color: palette.textSecondary),
),
],
],
),
),
],
),
if (children.isNotEmpty) ...[
const SizedBox(height: 14),
...children,
],
],
),
),
);
}
}
class MobileSettingsTextFieldInternal extends StatelessWidget {
const MobileSettingsTextFieldInternal({
super.key,
required this.controller,
required this.label,
required this.icon,
this.obscureText = false,
this.keyboardType,
this.textInputAction,
this.autofillHints,
this.onSubmitted,
});
final TextEditingController controller;
final String label;
final IconData icon;
final bool obscureText;
final TextInputType? keyboardType;
final TextInputAction? textInputAction;
final Iterable<String>? autofillHints;
final ValueChanged<String>? onSubmitted;
@override
Widget build(BuildContext context) {
return TextFormField(
controller: controller,
obscureText: obscureText,
keyboardType: keyboardType,
textInputAction: textInputAction,
autofillHints: autofillHints,
autocorrect: false,
enableSuggestions: !obscureText,
decoration: InputDecoration(labelText: label, prefixIcon: Icon(icon)),
onFieldSubmitted: onSubmitted,
);
}
}
class MobileSettingsMetaRowInternal extends StatelessWidget {
const MobileSettingsMetaRowInternal({
super.key,
required this.icon,
required this.label,
required this.value,
});
final IconData icon;
final String label;
final String value;
@override
Widget build(BuildContext context) {
final palette = context.palette;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 18, color: palette.textSecondary),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: Theme.of(
context,
).textTheme.labelMedium?.copyWith(color: palette.textSecondary),
),
const SizedBox(height: 2),
Text(value, style: Theme.of(context).textTheme.bodyMedium),
],
),
),
],
);
}
}