184 lines
7.1 KiB
Dart
184 lines
7.1 KiB
Dart
/// Rank-order the Most Important nominees into a personal hierarchy.
|
|
library;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../providers/values_sort_provider.dart';
|
|
import '../widgets/practice_chrome.dart';
|
|
|
|
class RankOrderScreen extends StatelessWidget {
|
|
const RankOrderScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final sort = context.watch<ValuesSortController>();
|
|
final ranked = sort.rankedCards;
|
|
final text = Theme.of(context).textTheme;
|
|
final colors = Theme.of(context).colorScheme;
|
|
|
|
return PracticeScaffold(
|
|
header: Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 4, 12, 0),
|
|
child: Row(
|
|
children: [
|
|
IconButton(
|
|
onPressed: sort.goToHub,
|
|
icon: const Icon(Icons.arrow_back),
|
|
),
|
|
Expanded(
|
|
child: Text(
|
|
'Stage 3 · Prioritization',
|
|
style: text.labelMedium,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
footer: PrimaryPillButton(
|
|
label: 'Reflect on top values',
|
|
icon: Icons.spa_outlined,
|
|
onPressed: ranked.isEmpty ? null : sort.goToReflection,
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Order Your Core Values', style: text.displaySmall),
|
|
const SizedBox(height: 6),
|
|
Text(
|
|
'Drag or reorder your finalists. Let #1 represent your non-negotiable value.',
|
|
style: text.bodyMedium,
|
|
),
|
|
const SizedBox(height: 12),
|
|
if (ranked.isEmpty)
|
|
Expanded(
|
|
child: Center(
|
|
child: Text(
|
|
'Promote a few values into Most Important first.',
|
|
style: text.bodyLarge?.copyWith(color: colors.onSurfaceVariant),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
)
|
|
else
|
|
Expanded(
|
|
child: ReorderableListView.builder(
|
|
itemCount: ranked.length,
|
|
onReorderItem: sort.reorderRanked,
|
|
proxyDecorator: (child, index, animation) {
|
|
return Material(
|
|
elevation: 6,
|
|
color: Colors.transparent,
|
|
shadowColor: const Color(0x332C2825),
|
|
child: child,
|
|
);
|
|
},
|
|
itemBuilder: (context, index) {
|
|
final card = ranked[index];
|
|
final isPrimary = index == 0;
|
|
return Container(
|
|
key: ValueKey(card.id),
|
|
margin: const EdgeInsets.only(bottom: 10),
|
|
padding: const EdgeInsets.fromLTRB(12, 12, 4, 12),
|
|
decoration: BoxDecoration(
|
|
color: isPrimary
|
|
? colors.surfaceContainerLowest
|
|
: colors.surfaceContainerLow,
|
|
borderRadius: BorderRadius.circular(20),
|
|
border: Border.all(
|
|
color: isPrimary
|
|
? colors.secondary.withValues(alpha: 0.5)
|
|
: colors.outlineVariant,
|
|
),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(
|
|
width: 36,
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
'${index + 1}',
|
|
style: text.titleLarge?.copyWith(
|
|
color: isPrimary
|
|
? colors.secondary
|
|
: colors.primary,
|
|
),
|
|
),
|
|
if (isPrimary)
|
|
Icon(
|
|
Icons.star,
|
|
size: 14,
|
|
color: colors.secondary,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
card.title,
|
|
style: text.titleLarge?.copyWith(
|
|
color: colors.onSurface,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
card.description,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: text.bodyMedium?.copyWith(
|
|
color: colors.onSurfaceVariant,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
IconButton(
|
|
visualDensity: VisualDensity.compact,
|
|
padding: EdgeInsets.zero,
|
|
constraints: const BoxConstraints(
|
|
minWidth: 32,
|
|
minHeight: 28,
|
|
),
|
|
onPressed: () => sort.moveRank(index, up: true),
|
|
icon: const Icon(Icons.keyboard_arrow_up, size: 22),
|
|
),
|
|
ReorderableDragStartListener(
|
|
index: index,
|
|
child: const Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 2),
|
|
child: Icon(Icons.drag_indicator, size: 22),
|
|
),
|
|
),
|
|
IconButton(
|
|
visualDensity: VisualDensity.compact,
|
|
padding: EdgeInsets.zero,
|
|
constraints: const BoxConstraints(
|
|
minWidth: 32,
|
|
minHeight: 28,
|
|
),
|
|
onPressed: () => sort.moveRank(index, up: false),
|
|
icon: const Icon(Icons.keyboard_arrow_down, size: 22),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|