import 'package:change_case/change_case.dart';
import 'utils.dart';
Future<void> main(List<String> args) async {
// create files
if (args.isEmpty) throw Exception("Missing args");
if (args.length > 1) throw Exception("Too many arguments");
final featureName = args[0];
final className = featureName.toPascalCase();
final snakeCase = featureName.toSnakeCase();
final blocFile = await createFile(
"lib/presentation/screens/$featureName/bloc/${featureName}_cubit.dart");
final stateFile = await createFile(
"lib/presentation/screens/$featureName/bloc/${featureName}_state.dart");
final screenFile = await createFile(
"lib/presentation/screens/$featureName/${featureName}_screen.dart");
final routeFile = await createFile(
"lib/presentation/screens/$featureName/${featureName}_route.dart");
// write files
await writeToFile(screenFile, screenTemplate(snakeCase, className));
await writeToFile(stateFile, stateTemplate(snakeCase, className));
await writeToFile(blocFile, blocTemplate(snakeCase, className));
await writeToFile(routeFile, routeTemplate(snakeCase, className));
print("$featureName created successfully");
}
String screenTemplate(String snakeCase, String className) {
final cubitName = "${className}Cubit";
final screenName = "${className}Screen";
final stateName = "${className}State";
return """
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:concierge/presentation/screens/$snakeCase/bloc/${snakeCase}_cubit.dart';
import 'package:concierge/presentation/screens/$snakeCase/bloc/${snakeCase}_state.dart';
class $screenName extends StatelessWidget {
const $screenName({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<$cubitName, $stateName>(
builder: (context, state) {
final cubit = context.read<$cubitName>();
return MultiBlocListener(
listeners: [
BlocListener<$cubitName, $stateName>(
listenWhen: (prev, curr) =>
prev.isLoading && curr.error.isError,
listener: (context, state) {
},
)
],
child: Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
children: [
Text("$className"),
],
),
),
),
);
},
);
}
}
"""
.trim();
}
String stateTemplate(String snakeCase, String className) {
final stateName = "${className}State";
return """
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:concierge/domain/models/app_error.dart';
part '../../../../_generated/presentation/screens/$snakeCase/bloc/${snakeCase}_state.freezed.dart';
@freezed
abstract class $stateName with _\$$stateName {
const factory $stateName({
@Default(false) bool isLoading,
@Default(AppError.none) AppError error,
}) = _$stateName;
}
"""
.trim();
}
String blocTemplate(String snakeCase, String className) {
final cubitName = "${className}Cubit";
final stateName = "${className}State";
return """
import 'package:concierge/presentation/base/base_cubit.dart';
import 'package:concierge/presentation/screens/$snakeCase/bloc/${snakeCase}_state.dart';
class $cubitName extends BaseCubit<$stateName> {
$cubitName() : super(const $stateName()) {
init();
}
Future<void> init() async {
}
}
"""
.trim();
}
String routeTemplate(String snakeCase, String className) {
final routeName = "${className}Route";
final pathName = "static const ${className.toCamelCase()} = \"/${className.toKebabCase()}\";";
final cubitName = "${className}Cubit";
final screenName = "${className}Screen";
return """
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:concierge/presentation/navigation/app_routes.dart';
import 'package:go_router/go_router.dart';
import 'package:concierge/presentation/navigation/transitions/slide_up_transition.dart';
import 'package:concierge/presentation/screens/$snakeCase/bloc/${snakeCase}_cubit.dart';
import 'package:concierge/presentation/screens/$snakeCase/${snakeCase}_screen.dart';
part '../../../_generated/presentation/screens/$snakeCase/${snakeCase}_route.g.dart';
@TypedGoRoute<$routeName>(
path: "/${className.toKebabCase()}", // add me to AppRoutes: $pathName
)
class $routeName extends GoRouteData with \$$routeName {
@override
Page<void> buildPage(BuildContext context, GoRouterState state) {
return slideUpTransition(
state: state,
child: BlocProvider(
create: (context) => $cubitName(),
child: $screenName(),
),
);
}
}"""
.trim();
}