Files
GroundedHelper/frontend/lib/Grounded/designs/GoalPicker.dart
alvocool d3431ca5de Switch to Inter, round the corners softly and make the nav switch tabs
Inter replaces General Sans (Inter Display for titles and big numbers).
Corners come back from before the squaring commit, scaled to a soft set
(16 cards, 14 buttons, 12 rows, 8 chips) and applied to the screens built
since. The nav is now a cluster of round frosted buttons that switches
Today, Routines, Goals, Groups and Progress in place inside Home: no
pushed pages, no back arrows, and Android back returns to Today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KhQh614DMeYoQEH9SoMRUw
2026-11-09 07:08:46 +03:00

128 lines
4.0 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../about/external/data/Goal.dart';
import '../about/internal/application/TextType.dart';
import '../utils/Colors.dart';
import '../utils/CommonUtils.dart';
import 'text/Text.dart';
/// The goal chooser, shared by the task form and the routine builder. Opened
/// only once the goals have been loaded — `selectField` loads on tap.
///
/// Resolves to the chosen goal, to a bare `Goal()` (no id) for "no goal", or
/// to null when dismissed without a choice.
Future<Goal?> showGoalPicker(
BuildContext context,
List<Goal> goals, {
String? selectedId,
}) {
return showModalBottomSheet<Goal>(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
barrierColor: colorBlack.withValues(alpha: 0.55),
builder: (BuildContext sheetContext) {
final List<Goal> active = goals.where((goal) => !goal.archived).toList();
return Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(sheetContext).size.height * 0.75,
),
decoration: const BoxDecoration(
color: colorSheetBackground,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: ListView(
shrinkWrap: true,
padding: const EdgeInsets.fromLTRB(24, 24, 24, 32),
children: [
text("BELONGS TO", 9, TextType.Bold,
color: colorGrey2, letterSpacing: 1.2),
const SizedBox(height: 8),
text("Which goal is this for?", 24, TextType.Light,
color: colorPrimaryDark),
const SizedBox(height: 18),
_goalOption(
sheetContext,
Goal(),
"No goal",
"Stands on its own",
colorGrey,
selectedId == null,
),
...active.map((goal) => _goalOption(
sheetContext,
goal,
goal.title,
goal.targetDate == null
? "${goal.remainingTasks} open"
: "${goal.remainingTasks} open · ${targetLabel(goal.targetDate)}",
goalColor(goal.colourHex),
goal.id == selectedId,
)),
if (active.isEmpty) ...[
const SizedBox(height: 8),
text("No goals yet. Create one from the Goals screen.", 12,
TextType.Regular,
color: colorGrey2),
],
],
),
);
},
);
}
Widget _goalOption(
BuildContext sheetContext,
Goal goal,
String title,
String caption,
Color accent,
bool selected,
) {
return GestureDetector(
onTap: () => Navigator.pop(sheetContext, goal),
behavior: HitTestBehavior.opaque,
child: Container(
margin: const EdgeInsets.only(bottom: 8),
padding: const EdgeInsets.fromLTRB(14, 13, 14, 13),
decoration: BoxDecoration(
color: colorWhite,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: selected ? accent.withValues(alpha: 0.5) : colorBorder,
width: selected ? 1.5 : 1,
),
),
child: Row(
children: [
Container(
width: 12,
height: 12,
decoration: BoxDecoration(color: accent, shape: BoxShape.circle),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
text(title, 14, TextType.Medium, color: colorPrimaryDark),
const SizedBox(height: 3),
text(caption, 11, TextType.Regular, color: colorGrey2),
],
),
),
if (selected)
Icon(CupertinoIcons.checkmark_alt, size: 17, color: accent),
],
),
),
);
}