bible-tracker/lib/screens/create_tracker_screen.dart

136 lines
4 KiB
Dart
Raw Permalink Normal View History

2026-04-20 18:39:49 +00:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/tracker.dart';
import '../services/tracker_service.dart';
import '../widgets/theme.dart';
class CreateTrackerScreen extends ConsumerStatefulWidget {
const CreateTrackerScreen({super.key, this.existing});
final Tracker? existing;
@override
ConsumerState<CreateTrackerScreen> createState() =>
_CreateTrackerScreenState();
}
class _CreateTrackerScreenState extends ConsumerState<CreateTrackerScreen> {
late final TextEditingController _nameController;
late Color _color;
bool _saving = false;
@override
void initState() {
super.initState();
_nameController = TextEditingController(text: widget.existing?.name ?? '');
_color = widget.existing != null
? Color(widget.existing!.colorValue)
: AppTokens.trackerPalette.first;
}
@override
void dispose() {
_nameController.dispose();
super.dispose();
}
Future<void> _save() async {
final String name = _nameController.text.trim();
if (name.isEmpty) return;
setState(() => _saving = true);
final TrackerService service = ref.read(trackerServiceProvider.notifier);
if (widget.existing == null) {
await service.create(name: name, color: _color);
} else {
await service.updateMeta(widget.existing!.id, name: name, color: _color);
}
if (!mounted) return;
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
final bool isEditing = widget.existing != null;
return Scaffold(
appBar: AppBar(title: Text(isEditing ? 'Edit Tracker' : 'New Tracker')),
body: SingleChildScrollView(
padding: const EdgeInsets.all(AppTokens.spaceL),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Name',
hintText: 'e.g. My First Read-Through',
border: OutlineInputBorder(),
),
textInputAction: TextInputAction.done,
autofocus: !isEditing,
),
const SizedBox(height: AppTokens.spaceXL),
Text('Color', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: AppTokens.spaceM),
Wrap(
spacing: AppTokens.spaceM,
runSpacing: AppTokens.spaceM,
children: <Widget>[
for (final Color option in AppTokens.trackerPalette)
_ColorSwatch(
color: option,
selected: option.toARGB32() == _color.toARGB32(),
onTap: () => setState(() => _color = option),
),
],
),
const SizedBox(height: AppTokens.spaceXXL),
FilledButton(
onPressed: _saving ? null : _save,
style: FilledButton.styleFrom(backgroundColor: _color),
child: Text(isEditing ? 'Save Changes' : 'Create Tracker'),
),
],
),
),
);
}
}
class _ColorSwatch extends StatelessWidget {
const _ColorSwatch({
required this.color,
required this.selected,
required this.onTap,
});
final Color color;
final bool selected;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return InkResponse(
onTap: onTap,
radius: 32,
child: Container(
width: 44,
height: 44,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
border: Border.all(
color: selected
? Theme.of(context).colorScheme.onSurface
: Colors.transparent,
width: 3,
),
),
child: selected
? const Icon(Icons.check, color: Colors.white, size: 20)
: null,
),
);
}
}