Skip to content

Instantly share code, notes, and snippets.

@xster
Created March 20, 2024 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xster/37605c68fbb629e9857bc436bc3fcb03 to your computer and use it in GitHub Desktop.
Save xster/37605c68fbb629e9857bc436bc3fcb03 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
// =====================================
// Top-Level App Structure
// =====================================
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Workflow Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentStep = 0; // 0: Part 1, 1: Part 2
String _selectedPart1Label = ''; // Store the label from Part 1
void _updateStep(int newStep, {String? part1Label}) {
setState(() {
_currentStep = newStep;
if (part1Label != null) {
_selectedPart1Label = part1Label;
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Workflow Demo')),
body: Center(
child: WorkflowListSection(
onClose: () => setState(() { /* Your removal logic here */ }),
currentStep: _currentStep,
selectedPart1Label: _selectedPart1Label,
onUpdateStep: _updateStep,
),
),
);
}
}
// =====================================
// Workflow List Section
// =====================================
class WorkflowListSection extends StatelessWidget {
final int currentStep;
final String selectedPart1Label;
final VoidCallback onClose;
final Function(int, {String?}) onUpdateStep;
WorkflowListSection({
required this.currentStep,
required this.selectedPart1Label,
required this.onClose,
required this.onUpdateStep,
});
@override
Widget build(BuildContext context) {
return Container(
width: 600,
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
ListHeader(onClose: onClose), // Reusable header widget
SizedBox(height: 20),
if (currentStep == 1) WorkflowBreadcrumb(
selectedPart1Label: selectedPart1Label,
onUpdateStep: onUpdateStep,
)
],
),
);
}
}
// =====================================
// Reusable Widgets
// =====================================
class ListHeader extends StatelessWidget {
final VoidCallback onClose;
ListHeader({required this.onClose});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Help us do better", style: TextStyle(fontSize: 16)),
IconButton(
icon: Icon(Icons.close),
onPressed: onClose,
),
],
);
}
}
class Part1Widget extends StatelessWidget {
final Function(int, {String?}) onUpdateStep;
Part1Widget({required this.onUpdateStep});
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("What would make this summary better?"),
SizedBox(height: 16),
..._buildChoiceButtons(),
],
);
}
List<Widget> _buildChoiceButtons() {
final choices = [
{ 'label': "Tone of voice", 'icon': Icons.volume_up},
{ 'label': "Relevant to context", 'icon': Icons.context_menu},
{ 'label': "Better Grammar", 'icon': Icons.edit},
{ 'label': "Something else", 'icon': Icons.more_horiz},
];
return choices.map((choice) => ElevatedButton.icon(
icon: Icon(choice['icon']),
label: Text(choice['label']),
onPressed: () {
onUpdateStep(1, part1Label: choice['label']); // Navigate to Part 2
},
)).toList();
}
}
class WorkflowBreadcrumb extends StatelessWidget {
final String selectedPart1Label;
final Function(int, {String?}) onUpdateStep;
WorkflowBreadcrumb({required this.selectedPart1Label, required this.onUpdateStep});
@override
Widget build(BuildContext context) {
return Row(
children: [
InkWell(
onTap: () => onUpdateStep(0), // Navigate back to Part 1
child: Text(
selectedPart1Label,
style: TextStyle(color: Colors.grey),
),
),
Icon(Icons.arrow_forward_ios, size: 16),
Text("Which of these is better?", style: TextStyle(fontWeight: FontWeight.bold)),
],
);
}
}
class Part2Widget extends StatefulWidget {
@override
_Part2WidgetState createState() => _Part2WidgetState();
}
class _Part2WidgetState extends State<Part2Widget> {
int _selectedCard = -1;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("Which of these is better?"),
SizedBox(height: 16),
..._buildSummaryCards(),
],
);
}
List<Widget> _buildSummaryCards() {
final options = [
"I am the suggested text content for one of the options for summarizing this doc content",
"I am another option for summarizing this doc using a different tone of voice",
];
return options.asMap().entries.map((entry) {
int index = entry.key;
String text = entry.value;
return SelectableCard(
text: text,
optionLabel: 'Option ${String.fromCharCode('A'.codeUnitAt(0) + index)}',
isSelected: index == _selectedCard,
onTap: () {
setState(() {
_selectedCard = index;
});
},
);
}).toList()
..add(SelectableCard(
text: "None of the above",
optionLabel: 'Option ${String.fromCharCode('A'.codeUnitAt(0) + options.length)}',
isSelected: _selectedCard == options.length,
onTap: () {
setState(() {
_selectedCard = options.length;
});
},
));
}
}
class SelectableCard extends StatefulWidget {
final String text;
final String optionLabel;
SelectableCard({required this.text, required this.optionLabel});
@override
_SelectableCardState createState() => _SelectableCardState();
}
class _SelectableCardState extends State<SelectableCard> {
bool _isSelected = false;
@override
void initState() {
super.initState();
_isSelected = widget.isSelected;
}
@override
Widget build(BuildContext context) {
return Card(
elevation: 2.0,
margin: const EdgeInsets.only(bottom: 16.0),
shape: RoundedRectangleBorder(
side: _isSelected ? BorderSide(color: Colors.blue, width: 2) : BorderSide.none,
borderRadius: BorderRadius.circular(8.0),
),
child: InkWell(
onTap: () {
setState(() {
_isSelected = !_isSelected;
});
widget.onTap(); // Notify the parent about the selection change
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(widget.text),
SizedBox(height: 8),
Text(widget.optionLabel, style: TextStyle(color: Colors.grey)),
],
),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment