generatePage function
Emits compilable stubs for a form page.
Implementation
List<GeneratedFile> generatePage(PageGenRequest req) {
final feature = req.feature;
final name = req.name;
final featurePascal = _pascal(feature);
final namePascal = _pascal(name);
final mixinName = '$featurePascal${namePascal}Data';
final pageName = '$namePascal${featurePascal}Page';
final edit = req.editModel;
final files = <GeneratedFile>[
GeneratedFile(
relativePath:
'lib/features/$feature/controllers/${feature}_${name}_data.dart',
contents: '''
import 'package:flutter/widgets.dart';
import 'package:flutter_page_kit/flutter_page_kit.dart';
mixin $mixinName<T extends StatefulWidget> on State<T>, PageData<T> {
${edit == null ? '' : ' $edit? get editing;\n'}
late final title = text();
@override
List<Validatable> get validated => [title];
List<PageAction> get actions => [
PageAction(
id: 'save',
label: 'Save',
busyKey: 'save',
isPrimary: true,
onPressed: submit,
),
];
Future<void> submit() => run(
key: 'save',
action: () async {
if (!await validateForm()) return;
// TODO: call repository
},
);
}
''',
),
GeneratedFile(
relativePath: 'lib/features/$feature/pages/${name}_${feature}_page.dart',
contents: '''
import 'package:flutter/material.dart';
import 'package:flutter_page_kit/flutter_page_kit.dart';
import '../controllers/${feature}_${name}_data.dart';
import '../widgets/${feature}_${name}_body.dart';
class $pageName extends StatefulWidget {
const $pageName({super.key});
@override
State<$pageName> createState() => _${pageName}State();
}
class _${pageName}State extends State<$pageName>
with PageData<$pageName>, $mixinName<$pageName> {
@override
Widget build(BuildContext context) {
return PageScope(
data: this,
child: FormPage(
title: '$namePascal $featurePascal',
actions: actions,
failure: failure,
child: const $featurePascal${namePascal}Body(),
),
);
}
}
''',
),
];
for (var i = 1; i <= req.steps; i++) {
files.add(
GeneratedFile(
relativePath:
'lib/features/$feature/widgets/${feature}_${name}_step_$i.dart',
contents: '''
import 'package:flutter/material.dart';
class $featurePascal${namePascal}Step$i extends StatelessWidget {
const $featurePascal${namePascal}Step$i({super.key});
@override
Widget build(BuildContext context) {
return const Center(child: Text('Step $i'));
}
}
''',
),
);
}
files.add(
GeneratedFile(
relativePath: 'lib/features/$feature/widgets/${feature}_${name}_body.dart',
contents: '''
import 'package:flutter/material.dart';
${[
for (var i = 1; i <= req.steps; i++)
"import '${feature}_${name}_step_$i.dart';",
].join('\n')}
class $featurePascal${namePascal}Body extends StatelessWidget {
const $featurePascal${namePascal}Body({super.key});
@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
${[
for (var i = 1; i <= req.steps; i++)
' const $featurePascal${namePascal}Step$i(),',
].join('\n')}
],
);
}
}
''',
),
);
files.add(
GeneratedFile(
relativePath: 'test/${feature}_${name}_harness_test.dart',
contents: '''
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('${_camel(feature)} ${_camel(name)} harness mounts', (tester) async {
// TODO: mount generated page with PageHarness
expect(true, isTrue);
});
}
''',
),
);
return files;
}