coregen-cli 3.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coregen.py +1585 -0
- coregen_cli-3.1.6.dist-info/METADATA +1211 -0
- coregen_cli-3.1.6.dist-info/RECORD +172 -0
- coregen_cli-3.1.6.dist-info/WHEEL +5 -0
- coregen_cli-3.1.6.dist-info/entry_points.txt +2 -0
- coregen_cli-3.1.6.dist-info/top_level.txt +2 -0
- generators/__init__.py +1 -0
- generators/assets/__init__.py +1 -0
- generators/assets/assets.py +30 -0
- generators/assets/main.py +4 -0
- generators/config/__init__.py +1 -0
- generators/config/analisy_options.py +42 -0
- generators/config/main.py +11 -0
- generators/config/pubspec.py +139 -0
- generators/cursor/__init__.py +3 -0
- generators/cursor/setup.py +87 -0
- generators/helpers/__init__.py +56 -0
- generators/helpers/component.py +1030 -0
- generators/helpers/config.py +255 -0
- generators/helpers/data_source.py +180 -0
- generators/helpers/domain.py +469 -0
- generators/helpers/feature.py +654 -0
- generators/helpers/navigation.py +274 -0
- generators/helpers/page.py +63 -0
- generators/helpers/project.py +33 -0
- generators/helpers/utils.py +338 -0
- generators/helpers/validation.py +364 -0
- generators/initializator.py +68 -0
- generators/main.py +81 -0
- generators/static/assets/logo.png +0 -0
- generators/static/assets/mock/auth_user.json +5 -0
- generators/static/assets/svgs/apple.svg +4 -0
- generators/static/assets/svgs/google.svg +2 -0
- generators/static/cursor/AGENTS.md.jinja +37 -0
- generators/static/cursor/agents/doc-writer.md +20 -0
- generators/static/cursor/agents/epic-orchestrator.md +28 -0
- generators/static/cursor/agents/feature-implementer.md +29 -0
- generators/static/cursor/agents/integration-wiring.md +30 -0
- generators/static/cursor/agents/layer-application.md +21 -0
- generators/static/cursor/agents/layer-guardian.md +21 -0
- generators/static/cursor/agents/layer-infrastructure.md +31 -0
- generators/static/cursor/agents/layer-model.md +24 -0
- generators/static/cursor/agents/layer-presentation.md +33 -0
- generators/static/cursor/docs/architecture/APIS_AND_INTEGRATION.md.jinja +42 -0
- generators/static/cursor/docs/architecture/CARAVAGGIO_COMPONENTS.md.jinja +317 -0
- generators/static/cursor/docs/architecture/DDD_LAYERS.md.jinja +32 -0
- generators/static/cursor/docs/architecture/FILE_TEMPLATES.md.jinja +76 -0
- generators/static/cursor/docs/architecture/MOCK_AND_REMOTE_DATA.md.jinja +87 -0
- generators/static/cursor/docs/architecture/REFERENCE_IMPLEMENTATIONS.md.jinja +48 -0
- generators/static/cursor/docs/architecture/WIDGETS_AND_CARAVAGGIO.md.jinja +76 -0
- generators/static/cursor/docs/epics/README.md +17 -0
- generators/static/cursor/lib/domain/AGENTS.md +23 -0
- generators/static/cursor/lib/features/AGENTS.md +23 -0
- generators/static/cursor/lib/widgets/AGENTS.md +21 -0
- generators/static/cursor/rules/apis-layer.mdc.jinja +21 -0
- generators/static/cursor/rules/application-layer.mdc.jinja +12 -0
- generators/static/cursor/rules/architecture-core.mdc.jinja +43 -0
- generators/static/cursor/rules/dart-conventions.mdc.jinja +14 -0
- generators/static/cursor/rules/domain-layer.mdc.jinja +24 -0
- generators/static/cursor/rules/login-context.mdc.jinja +16 -0
- generators/static/cursor/rules/presentation-layer.mdc.jinja +15 -0
- generators/static/cursor/rules/quality-gate.mdc.jinja +14 -0
- generators/static/cursor/rules/ui-caravaggio.mdc.jinja +22 -0
- generators/static/cursor/skills/caravaggio-ui/SKILL.md +138 -0
- generators/static/cursor/skills/epic-delivery/SKILL.md +74 -0
- generators/static/cursor/skills/epic-delivery/templates/epic-status.md +14 -0
- generators/static/cursor/skills/epic-delivery/templates/epic.md +36 -0
- generators/static/templates/apis/common/constants_template.jinja +48 -0
- generators/static/templates/apis/common/data_source_config_template.jinja +47 -0
- generators/static/templates/apis/core/api_injectable_module_template.jinja +14 -0
- generators/static/templates/apis/interceptors/api_logger_template.jinja +135 -0
- generators/static/templates/apis/interceptors/auth_interceptor_template.jinja +207 -0
- generators/static/templates/auth/application/auth_bloc_template.jinja +36 -0
- generators/static/templates/auth/application/auth_event_template.jinja +7 -0
- generators/static/templates/auth/application/auth_state_template.jinja +8 -0
- generators/static/templates/auth/infrastructure/auth_facade_module_template.jinja +16 -0
- generators/static/templates/auth/infrastructure/auth_facade_template.jinja +288 -0
- generators/static/templates/auth/infrastructure/mock_auth_facade_template.jinja +106 -0
- generators/static/templates/auth/model/auth_failure_template.jinja +11 -0
- generators/static/templates/auth/model/i_auth_facade_template.jinja +24 -0
- generators/static/templates/auth/model/user_template.jinja +34 -0
- generators/static/templates/auth/model/value_objects_template.jinja +54 -0
- generators/static/templates/auth/presentation/login_screen_template.jinja +24 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_bloc_template.jinja +139 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_event_template.jinja +15 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_state_template.jinja +26 -0
- generators/static/templates/auth/sign_in_form/presentation/apple_form_template.jinja +16 -0
- generators/static/templates/auth/sign_in_form/presentation/email_password_form_template_INACTIVE.jinja +94 -0
- generators/static/templates/auth/sign_in_form/presentation/google_form_template.jinja +15 -0
- generators/static/templates/auth/sign_in_form/presentation/sign_in_form_template.jinja +381 -0
- generators/static/templates/component/component_bloc_template.jinja +49 -0
- generators/static/templates/component/component_event_template.jinja +7 -0
- generators/static/templates/component/component_form_bloc_template.jinja +56 -0
- generators/static/templates/component/component_form_event_template.jinja +7 -0
- generators/static/templates/component/component_form_state_template.jinja +18 -0
- generators/static/templates/component/component_form_widget_template.jinja +130 -0
- generators/static/templates/component/component_list_widget_template.jinja +95 -0
- generators/static/templates/component/component_state_template.jinja +9 -0
- generators/static/templates/component/component_widget_template.jinja +113 -0
- generators/static/templates/core/bloc/base_form_bloc_template.jinja +32 -0
- generators/static/templates/core/errors/error_localizer_template.jinja +61 -0
- generators/static/templates/core/infrastructure/base_mapper_template.jinja +21 -0
- generators/static/templates/core/infrastructure/base_repository_mixin_template.jinja +78 -0
- generators/static/templates/core/infrastructure/firebase_injectable_module_template.jinja +11 -0
- generators/static/templates/core/infrastructure/firestore_helpers_template.jinja +22 -0
- generators/static/templates/core/infrastructure/repository_error_handler_template.jinja +44 -0
- generators/static/templates/core/model/common_interfaces_template.jinja +3 -0
- generators/static/templates/core/model/entity_template.jinja +5 -0
- generators/static/templates/core/model/errors_template.jinja +15 -0
- generators/static/templates/core/model/failures_template.jinja +97 -0
- generators/static/templates/core/model/value_objects_template.jinja +135 -0
- generators/static/templates/core/model/value_validators_template.jinja +105 -0
- generators/static/templates/core/presentation/app_drawer_template.jinja +52 -0
- generators/static/templates/core/presentation/app_widget_template.jinja +41 -0
- generators/static/templates/core/presentation/bottom_nav_bar_template.jinja +32 -0
- generators/static/templates/domain/domain_mapper_template.jinja +39 -0
- generators/static/templates/domain/domain_remote_service_template.jinja +46 -0
- generators/static/templates/domain/domain_repository_template.jinja +90 -0
- generators/static/templates/domain/domain_service_module_template.jinja +23 -0
- generators/static/templates/domain/enum_template.jinja +3 -0
- generators/static/templates/domain/i_domain_service_template.jinja +18 -0
- generators/static/templates/domain/mock_domain_service_template.jinja +73 -0
- generators/static/templates/feature/feature_bloc_template.jinja +104 -0
- generators/static/templates/feature/feature_dto_template.jinja +26 -0
- generators/static/templates/feature/feature_entity_template.jinja +23 -0
- generators/static/templates/feature/feature_event_template.jinja +20 -0
- generators/static/templates/feature/feature_extensions_template.jinja +25 -0
- generators/static/templates/feature/feature_failure_template.jinja +11 -0
- generators/static/templates/feature/feature_page_template.jinja +113 -0
- generators/static/templates/feature/feature_repository_template.jinja +112 -0
- generators/static/templates/feature/feature_state_template.jinja +20 -0
- generators/static/templates/feature/i_feature_repository_template.jinja +21 -0
- generators/static/templates/feature/value_object_field_template.jinja +0 -0
- generators/static/templates/feature/value_object_template.jinja +0 -0
- generators/static/templates/feature/value_validators_template.jinja +57 -0
- generators/static/templates/home/home_screen_template.jinja +68 -0
- generators/static/templates/home/presentation/home_screen_template.jinja +52 -0
- generators/static/templates/home/screen_template.jinja +12 -0
- generators/static/templates/injection_template.jinja +8 -0
- generators/static/templates/logging/analytics_logging_template.jinja +42 -0
- generators/static/templates/logging/console_template.jinja +50 -0
- generators/static/templates/logging/logger_injectable_module_template.jinja +24 -0
- generators/static/templates/logging/logger_template.jinja +118 -0
- generators/static/templates/main_template.jinja +43 -0
- generators/static/templates/page_template.jinja +29 -0
- generators/static/templates/router_template.jinja +26 -0
- generators/static/templates/splash/presentation/splash_screen_auth_template.jinja +97 -0
- generators/static/templates/splash/presentation/splash_screen_template.jinja +51 -0
- generators/static/templates/storage/storage_repository_template.jinja +80 -0
- generators/static/templates/user_profile/infrastructure/user_profile_dto_template.jinja +27 -0
- generators/static/templates/user_profile/infrastructure/user_profile_mapper_template.jinja +43 -0
- generators/static/templates/user_profile/infrastructure/user_profile_repository_template.jinja +82 -0
- generators/static/templates/user_profile/infrastructure/user_profile_service_template.jinja +27 -0
- generators/static/templates/user_profile/model/i_user_profile_repository_template.jinja +34 -0
- generators/static/templates/user_profile/model/user_profile_failure_template.jinja +11 -0
- generators/static/templates/user_profile/model/user_profile_template.jinja +31 -0
- generators/static/templates/widgets/common/custom_scaffold_template.jinja +52 -0
- generators/static/templates/widgets/common/error_widget_template.jinja +22 -0
- generators/static/templates/widgets/common/loading_widget_template.jinja +14 -0
- generators/static/templates/widgets/common/unknown_state_widget_template.jinja +23 -0
- generators/templates/__init__.py +1 -0
- generators/templates/_core/core_generator.py +121 -0
- generators/templates/apis/apis_generator.py +50 -0
- generators/templates/auth/auth_generator.py +40 -0
- generators/templates/auth/sign_in_form_generator.py +22 -0
- generators/templates/copier.py +51 -0
- generators/templates/home/home_generator.py +26 -0
- generators/templates/lib/lib_generator.py +40 -0
- generators/templates/logging/logging_generator.py +28 -0
- generators/templates/main.py +75 -0
- generators/templates/splash/splash_generator.py +20 -0
- generators/templates/storage/storage_generator.py +5 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* BLoC (Business Logic Component) template for feature management
|
|
3
|
+
* Generates a fully functional BLoC with CRUD operations:
|
|
4
|
+
* - Load: Fetch all items from repository
|
|
5
|
+
* - Create: Add new item
|
|
6
|
+
* - Update: Modify existing item
|
|
7
|
+
* - Delete: Remove item
|
|
8
|
+
*
|
|
9
|
+
* Uses:
|
|
10
|
+
* - Freezed for immutable state/events
|
|
11
|
+
* - Repository pattern for data access
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import 'package:bloc/bloc.dart';
|
|
15
|
+
import 'package:dartz/dartz.dart';
|
|
16
|
+
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
17
|
+
import 'package:[[feature_import_prefix]]/model/[[feature_name]].dart';
|
|
18
|
+
import 'package:[[feature_import_prefix]]/model/[[feature_name]]_failure.dart';
|
|
19
|
+
import 'package:[[feature_import_prefix]]/model/i_[[feature_name]]_repository.dart';
|
|
20
|
+
|
|
21
|
+
part '[[feature_name]]_event.dart';
|
|
22
|
+
part '[[feature_name]]_state.dart';
|
|
23
|
+
|
|
24
|
+
part '[[feature_name]]_bloc.freezed.dart';
|
|
25
|
+
|
|
26
|
+
class [[feature_name.capitalize()]]Bloc extends Bloc<[[feature_name.capitalize()]]Event, [[feature_name.capitalize()]]State> {
|
|
27
|
+
final I[[feature_name.capitalize()]]Repository _repository;
|
|
28
|
+
|
|
29
|
+
[[feature_name.capitalize()]]Bloc(this._repository) : super(const [[feature_name.capitalize()]]State.initial()) {
|
|
30
|
+
on<LoadRequested>(_onLoadRequested);
|
|
31
|
+
on<CreateRequested>(_onCreateRequested);
|
|
32
|
+
on<UpdateRequested>(_onUpdateRequested);
|
|
33
|
+
on<DeleteRequested>(_onDeleteRequested);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Future<void> _onLoadRequested(LoadRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
|
|
37
|
+
emit(const [[feature_name.capitalize()]]State.loading());
|
|
38
|
+
final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> result =
|
|
39
|
+
await _repository.getAll();
|
|
40
|
+
result.fold(
|
|
41
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
42
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
43
|
+
(List<[[feature_name.capitalize()]]> items) =>
|
|
44
|
+
emit([[feature_name.capitalize()]]State.loaded(items)),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Future<void> _onCreateRequested(CreateRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
|
|
49
|
+
emit(const [[feature_name.capitalize()]]State.loading());
|
|
50
|
+
final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.create(event.item);
|
|
51
|
+
result.fold(
|
|
52
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
53
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
54
|
+
(Unit _) async {
|
|
55
|
+
final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
|
|
56
|
+
await _repository.getAll();
|
|
57
|
+
itemsResult.fold(
|
|
58
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
59
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
60
|
+
(List<[[feature_name.capitalize()]]> items) =>
|
|
61
|
+
emit([[feature_name.capitalize()]]State.loaded(items)),
|
|
62
|
+
);
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Future<void> _onUpdateRequested(UpdateRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
|
|
68
|
+
emit(const [[feature_name.capitalize()]]State.loading());
|
|
69
|
+
final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.update(event.item);
|
|
70
|
+
result.fold(
|
|
71
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
72
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
73
|
+
(Unit _) async {
|
|
74
|
+
final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
|
|
75
|
+
await _repository.getAll();
|
|
76
|
+
itemsResult.fold(
|
|
77
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
78
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
79
|
+
(List<[[feature_name.capitalize()]]> items) =>
|
|
80
|
+
emit([[feature_name.capitalize()]]State.loaded(items)),
|
|
81
|
+
);
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Future<void> _onDeleteRequested(DeleteRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
|
|
87
|
+
emit(const [[feature_name.capitalize()]]State.loading());
|
|
88
|
+
final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.delete(event.id);
|
|
89
|
+
result.fold(
|
|
90
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
91
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
92
|
+
(Unit _) async {
|
|
93
|
+
final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
|
|
94
|
+
await _repository.getAll();
|
|
95
|
+
itemsResult.fold(
|
|
96
|
+
([[feature_name.capitalize()]]Failure failure) =>
|
|
97
|
+
emit([[feature_name.capitalize()]]State.error(failure.toString())),
|
|
98
|
+
(List<[[feature_name.capitalize()]]> items) =>
|
|
99
|
+
emit([[feature_name.capitalize()]]State.loaded(items)),
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Data Transfer Object (DTO) template for API communication
|
|
3
|
+
* Generates a serializable class for network data transfer with:
|
|
4
|
+
* - JSON serialization/deserialization
|
|
5
|
+
* - Freezed for immutability and code generation
|
|
6
|
+
* - Automatic fromJson/toJson methods
|
|
7
|
+
*
|
|
8
|
+
* DTOs represent the data structure expected by the API
|
|
9
|
+
* and are mapped to/from domain entities in repositories
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
13
|
+
[[dto_imports]]
|
|
14
|
+
|
|
15
|
+
part '[[file_name]]_dto.freezed.dart';
|
|
16
|
+
part '[[file_name]]_dto.g.dart';
|
|
17
|
+
|
|
18
|
+
@freezed
|
|
19
|
+
abstract class [[feature_name]]Dto with _$[[feature_name]]Dto {
|
|
20
|
+
const factory [[feature_name]]Dto({
|
|
21
|
+
[[fields]]
|
|
22
|
+
}) = _[[feature_name]]Dto;
|
|
23
|
+
|
|
24
|
+
factory [[feature_name]]Dto.fromJson(Map<String, dynamic> json) =>
|
|
25
|
+
_$[[feature_name]]DtoFromJson(json);
|
|
26
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Entity/Model template for domain objects
|
|
3
|
+
* Generates an immutable data class using Freezed package
|
|
4
|
+
* Represents core business objects with:
|
|
5
|
+
* - Value object integration for type safety
|
|
6
|
+
* - Immutable properties
|
|
7
|
+
* - Auto-generated equality and copyWith methods
|
|
8
|
+
*
|
|
9
|
+
* This is the domain layer model that represents business entities
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
13
|
+
import 'package:[[project_name]]/core/model/value_objects.dart';
|
|
14
|
+
[[entity_import]]
|
|
15
|
+
|
|
16
|
+
part '[[file_name]].freezed.dart';
|
|
17
|
+
|
|
18
|
+
@freezed
|
|
19
|
+
abstract class [[feature_name]] with _$[[feature_name]] {
|
|
20
|
+
const factory [[feature_name]]({
|
|
21
|
+
[[fields]]
|
|
22
|
+
}) = _[[feature_name]];
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* BLoC events template for feature operations
|
|
3
|
+
* Defines immutable events using Freezed that trigger BLoC actions:
|
|
4
|
+
* - LoadRequested: Fetch all items
|
|
5
|
+
* - CreateRequested: Create new item
|
|
6
|
+
* - UpdateRequested: Update existing item
|
|
7
|
+
* - DeleteRequested: Remove item by ID
|
|
8
|
+
*
|
|
9
|
+
* Events represent user intentions and trigger state changes
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
part of '[[feature_name]]_bloc.dart';
|
|
13
|
+
|
|
14
|
+
@freezed
|
|
15
|
+
abstract class [[feature_name.capitalize()]]Event with _$[[feature_name.capitalize()]]Event {
|
|
16
|
+
const factory [[feature_name.capitalize()]]Event.loadRequested() = LoadRequested;
|
|
17
|
+
const factory [[feature_name.capitalize()]]Event.createRequested([[feature_name.capitalize()]] item) = CreateRequested;
|
|
18
|
+
const factory [[feature_name.capitalize()]]Event.updateRequested([[feature_name.capitalize()]] item) = UpdateRequested;
|
|
19
|
+
const factory [[feature_name.capitalize()]]Event.deleteRequested(String id) = DeleteRequested;
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Extension methods template for data mapping
|
|
3
|
+
* Generates conversion methods between domain and infrastructure layers:
|
|
4
|
+
* - DTO to Domain: Convert API data to business objects
|
|
5
|
+
* - Domain to DTO: Convert business objects for API calls
|
|
6
|
+
*
|
|
7
|
+
* These extensions provide clean separation between:
|
|
8
|
+
* - Domain layer (business logic)
|
|
9
|
+
* - Infrastructure layer (API communication)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import 'package:[[project_name]]/[[feature_name]]/model/[[feature_name]].dart';
|
|
13
|
+
import 'package:[[project_name]]/[[feature_name]]/infrastructure/[[feature_name]]_dto.dart';
|
|
14
|
+
|
|
15
|
+
extension [[feature_name.capitalize()]]DtoX on [[feature_name.capitalize()]]Dto {
|
|
16
|
+
[[feature_name.capitalize()]] toDomain() => [[feature_name.capitalize()]](
|
|
17
|
+
[[dto_to_domain_fields]]
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
extension [[feature_name.capitalize()]]X on [[feature_name.capitalize()]] {
|
|
22
|
+
[[feature_name.capitalize()]]Dto toDto() => [[feature_name.capitalize()]]Dto(
|
|
23
|
+
[[domain_to_dto_fields]]
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '[[file_name]]_failure.freezed.dart';
|
|
4
|
+
|
|
5
|
+
@freezed
|
|
6
|
+
abstract class [[feature_name]]Failure with _$[[feature_name]]Failure {
|
|
7
|
+
const factory [[feature_name]]Failure.unexpected() = Unexpected;
|
|
8
|
+
const factory [[feature_name]]Failure.insufficientPermission() = InsufficientPermission;
|
|
9
|
+
const factory [[feature_name]]Failure.unableToUpdate() = UnableToUpdate;
|
|
10
|
+
const factory [[feature_name]]Failure.notFound() = NotFound;
|
|
11
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Feature page template with full CRUD UI
|
|
3
|
+
* Generates a complete page with:
|
|
4
|
+
* - BLoC integration for state management
|
|
5
|
+
* - List view showing all items
|
|
6
|
+
* - Add, edit, delete action buttons
|
|
7
|
+
* - Loading and error state handling
|
|
8
|
+
* - Navigation ready structure
|
|
9
|
+
*
|
|
10
|
+
* This provides a complete feature page with all basic operations
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import 'package:caravaggio_ui/caravaggio_ui.dart';
|
|
14
|
+
import 'package:flutter/material.dart';
|
|
15
|
+
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
16
|
+
import 'package:[[project_name]]/injection.dart';
|
|
17
|
+
import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
|
|
18
|
+
import 'package:[[project_name]]/widgets/common/loading_widget.dart';
|
|
19
|
+
import 'package:[[model_import_prefix]]/model/[[model_file_stem]].dart';
|
|
20
|
+
import '../application/[[feature_name]]_bloc.dart';
|
|
21
|
+
|
|
22
|
+
class [[feature_name.capitalize()]]Page extends StatelessWidget {
|
|
23
|
+
static const String routeName = '/[[feature_name]]';
|
|
24
|
+
|
|
25
|
+
const [[feature_name.capitalize()]]Page({super.key});
|
|
26
|
+
|
|
27
|
+
@override
|
|
28
|
+
Widget build(BuildContext context) {
|
|
29
|
+
return BlocProvider(
|
|
30
|
+
create: (BuildContext context) => getIt.get<[[feature_name.capitalize()]]Bloc>(),
|
|
31
|
+
child: Builder(
|
|
32
|
+
builder: (BuildContext context) {
|
|
33
|
+
return CustomScaffold(
|
|
34
|
+
title: CText.title('[[feature_name.replace("_", " ").capitalize()]]', size: TextSize.small),
|
|
35
|
+
showBackButton: true,
|
|
36
|
+
action: Row(
|
|
37
|
+
mainAxisSize: MainAxisSize.min,
|
|
38
|
+
children: <Widget>[
|
|
39
|
+
IconButton(
|
|
40
|
+
icon: const Icon(Icons.add),
|
|
41
|
+
onPressed: () {
|
|
42
|
+
// TODO: Navigate to create form
|
|
43
|
+
},
|
|
44
|
+
),
|
|
45
|
+
IconButton(
|
|
46
|
+
icon: const Icon(Icons.refresh),
|
|
47
|
+
onPressed: () {
|
|
48
|
+
context.read<[[feature_name.capitalize()]]Bloc>().add(
|
|
49
|
+
const [[feature_name.capitalize()]]Event.loadRequested(),
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
),
|
|
53
|
+
],
|
|
54
|
+
),
|
|
55
|
+
bodyBuilder: (BuildContext context, double topPadding) {
|
|
56
|
+
return BlocBuilder<[[feature_name.capitalize()]]Bloc, [[feature_name.capitalize()]]State>(
|
|
57
|
+
builder: (BuildContext context, [[feature_name.capitalize()]]State state) {
|
|
58
|
+
return switch (state) {
|
|
59
|
+
Initial() => Padding(
|
|
60
|
+
padding: EdgeInsets.only(top: topPadding),
|
|
61
|
+
child: const Center(child: Text('Welcome')),
|
|
62
|
+
),
|
|
63
|
+
Loading() => Padding(
|
|
64
|
+
padding: EdgeInsets.only(top: topPadding),
|
|
65
|
+
child: const LoadingWidget(),
|
|
66
|
+
),
|
|
67
|
+
Loaded(:final items) => ListView.builder(
|
|
68
|
+
padding: EdgeInsets.only(top: topPadding, left: 16, right: 16),
|
|
69
|
+
itemCount: items.length,
|
|
70
|
+
itemBuilder: (BuildContext context, int index) {
|
|
71
|
+
final [[model_class_pascal]] item = items[index];
|
|
72
|
+
return CTile.simple(
|
|
73
|
+
title: item.toString(),
|
|
74
|
+
trailing: Row(
|
|
75
|
+
mainAxisSize: MainAxisSize.min,
|
|
76
|
+
children: <Widget>[
|
|
77
|
+
IconButton(
|
|
78
|
+
icon: const Icon(Icons.edit),
|
|
79
|
+
onPressed: () {
|
|
80
|
+
// TODO: Navigate to edit form
|
|
81
|
+
},
|
|
82
|
+
),
|
|
83
|
+
IconButton(
|
|
84
|
+
icon: const Icon(Icons.delete),
|
|
85
|
+
onPressed: () {
|
|
86
|
+
context.read<[[feature_name.capitalize()]]Bloc>().add(
|
|
87
|
+
[[feature_name.capitalize()]]Event.deleteRequested(item.id.getOrCrash()),
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
),
|
|
91
|
+
],
|
|
92
|
+
),
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
),
|
|
96
|
+
Error(:final message) => Padding(
|
|
97
|
+
padding: EdgeInsets.only(top: topPadding),
|
|
98
|
+
child: Center(child: CText.body('Errore: $message')),
|
|
99
|
+
),
|
|
100
|
+
_ => Padding(
|
|
101
|
+
padding: EdgeInsets.only(top: topPadding),
|
|
102
|
+
child: const Center(child: Text('Stato sconosciuto')),
|
|
103
|
+
),
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Repository implementation template with REST API integration
|
|
3
|
+
* Provides concrete implementation of repository interface with:
|
|
4
|
+
* - Retrofit for API calls
|
|
5
|
+
* - Dio HTTP client integration
|
|
6
|
+
* - DTO to Entity mapping
|
|
7
|
+
* - Error handling with Either types
|
|
8
|
+
* - Injectable dependency registration
|
|
9
|
+
*
|
|
10
|
+
* Includes both remote service definition and repository implementation
|
|
11
|
+
* with proper separation between API layer and domain layer
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import 'package:dartz/dartz.dart';
|
|
15
|
+
import 'package:dio/dio.dart';
|
|
16
|
+
import 'package:injectable/injectable.dart';
|
|
17
|
+
import 'package:retrofit/retrofit.dart';
|
|
18
|
+
[[repo_import]]
|
|
19
|
+
import 'package:[[project_name]]/apis/common/constants.dart';
|
|
20
|
+
|
|
21
|
+
part '[[feature_name]]_repository.g.dart';
|
|
22
|
+
|
|
23
|
+
@module
|
|
24
|
+
abstract class [[feature_name.capitalize()]]RemoteModule {
|
|
25
|
+
@preResolve
|
|
26
|
+
@LazySingleton()
|
|
27
|
+
Future<[[feature_name.capitalize()]]RemoteService> [[feature_name]]RemoteService(Dio dio) async {
|
|
28
|
+
return [[feature_name.capitalize()]]RemoteService(dio, baseUrl: Constants.apiUrl);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@RestApi()
|
|
33
|
+
abstract class [[feature_name.capitalize()]]RemoteService {
|
|
34
|
+
@factoryMethod
|
|
35
|
+
factory [[feature_name.capitalize()]]RemoteService(Dio dio, {String baseUrl}) = _[[feature_name.capitalize()]]RemoteService;
|
|
36
|
+
|
|
37
|
+
@GET('/[[feature_name]]s')
|
|
38
|
+
Future<List<[[feature_name.capitalize()]]Dto>> getAllDto();
|
|
39
|
+
|
|
40
|
+
@GET('/[[feature_name]]s/{id}')
|
|
41
|
+
Future<[[feature_name.capitalize()]]Dto> getByIdDto(@Path('id') String id);
|
|
42
|
+
|
|
43
|
+
@POST('/[[feature_name]]s')
|
|
44
|
+
Future<void> createDto(@Body() [[feature_name.capitalize()]]Dto [[feature_name]]Dto);
|
|
45
|
+
|
|
46
|
+
@PUT('/[[feature_name]]s/{id}')
|
|
47
|
+
Future<void> updateDto(@Path('id') String id, @Body() [[feature_name.capitalize()]]Dto [[feature_name]]Dto);
|
|
48
|
+
|
|
49
|
+
@DELETE('/[[feature_name]]s/{id}')
|
|
50
|
+
Future<void> deleteDto(@Path('id') String id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Injectable(as: I[[feature_name.capitalize()]]Repository)
|
|
54
|
+
class [[feature_name.capitalize()]]Repository implements I[[feature_name.capitalize()]]Repository {
|
|
55
|
+
final [[feature_name.capitalize()]]RemoteService _remoteService;
|
|
56
|
+
|
|
57
|
+
[[feature_name.capitalize()]]Repository(this._remoteService);
|
|
58
|
+
|
|
59
|
+
@override
|
|
60
|
+
Future<Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>>> getAll() async {
|
|
61
|
+
try {
|
|
62
|
+
final List<[[feature_name.capitalize()]]Dto> dtos = await _remoteService.getAllDto();
|
|
63
|
+
final List<[[feature_name.capitalize()]]> domain = dtos
|
|
64
|
+
.map(([[feature_name.capitalize()]]Dto dto) => dto.toDomain())
|
|
65
|
+
.toList();
|
|
66
|
+
return right(domain);
|
|
67
|
+
} on Object catch (_) {
|
|
68
|
+
return left(const [[feature_name.capitalize()]]Failure.unexpected());
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@override
|
|
73
|
+
Future<Either<[[feature_name.capitalize()]]Failure, [[feature_name.capitalize()]]>> getById(String id) async {
|
|
74
|
+
try {
|
|
75
|
+
final [[feature_name.capitalize()]]Dto dto = await _remoteService.getByIdDto(id);
|
|
76
|
+
final [[feature_name.capitalize()]] domain = dto.toDomain();
|
|
77
|
+
return right(domain);
|
|
78
|
+
} on Object catch (_) {
|
|
79
|
+
return left(const [[feature_name.capitalize()]]Failure.unexpected());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@override
|
|
84
|
+
Future<Either<[[feature_name.capitalize()]]Failure, Unit>> create([[feature_name.capitalize()]] item) async {
|
|
85
|
+
try {
|
|
86
|
+
await _remoteService.createDto(item.toDto());
|
|
87
|
+
return right(unit);
|
|
88
|
+
} on Object catch (_) {
|
|
89
|
+
return left(const [[feature_name.capitalize()]]Failure.unexpected());
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@override
|
|
94
|
+
Future<Either<[[feature_name.capitalize()]]Failure, Unit>> update([[feature_name.capitalize()]] item) async {
|
|
95
|
+
try {
|
|
96
|
+
await _remoteService.updateDto(item.id.getOrCrash(), item.toDto());
|
|
97
|
+
return right(unit);
|
|
98
|
+
} on Object catch (_) {
|
|
99
|
+
return left(const [[feature_name.capitalize()]]Failure.unexpected());
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@override
|
|
104
|
+
Future<Either<[[feature_name.capitalize()]]Failure, Unit>> delete(String id) async {
|
|
105
|
+
try {
|
|
106
|
+
await _remoteService.deleteDto(id);
|
|
107
|
+
return right(unit);
|
|
108
|
+
} on Object catch (_) {
|
|
109
|
+
return left(const [[feature_name.capitalize()]]Failure.unexpected());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* BLoC states template for feature UI representation
|
|
3
|
+
* Defines immutable states using Freezed for different UI states:
|
|
4
|
+
* - Initial: App just started, no data loaded
|
|
5
|
+
* - Loading: Data is being fetched/processed
|
|
6
|
+
* - Loaded: Data successfully retrieved with items list
|
|
7
|
+
* - Error: Something went wrong with error message
|
|
8
|
+
*
|
|
9
|
+
* States represent the current condition of the feature
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
part of '[[feature_name]]_bloc.dart';
|
|
13
|
+
|
|
14
|
+
@freezed
|
|
15
|
+
abstract class [[feature_name.capitalize()]]State with _$[[feature_name.capitalize()]]State {
|
|
16
|
+
const factory [[feature_name.capitalize()]]State.initial() = Initial;
|
|
17
|
+
const factory [[feature_name.capitalize()]]State.loading() = Loading;
|
|
18
|
+
const factory [[feature_name.capitalize()]]State.loaded(List<[[feature_name.capitalize()]]> items) = Loaded;
|
|
19
|
+
const factory [[feature_name.capitalize()]]State.error(String message) = Error;
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Repository interface template for data access abstraction
|
|
3
|
+
* Defines the contract for data operations using:
|
|
4
|
+
* - Either type for error handling (Left = failure, Right = success)
|
|
5
|
+
* - CRUD operations (Create, Read, Update, Delete)
|
|
6
|
+
* - Async operations returning Futures
|
|
7
|
+
*
|
|
8
|
+
* This interface allows different implementations (API, local storage, etc.)
|
|
9
|
+
* while keeping the business logic independent of data source
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import 'package:dartz/dartz.dart';
|
|
13
|
+
[[i_repo_import]]
|
|
14
|
+
|
|
15
|
+
abstract class I[[feature_name]]Repository {
|
|
16
|
+
Future<Either<[[feature_name]]Failure, List<[[feature_name]]>>> getAll();
|
|
17
|
+
Future<Either<[[feature_name]]Failure, [[feature_name]]>> getById(String id);
|
|
18
|
+
Future<Either<[[feature_name]]Failure, Unit>> create([[feature_name]] item);
|
|
19
|
+
Future<Either<[[feature_name]]Failure, Unit>> update([[feature_name]] item);
|
|
20
|
+
Future<Either<[[feature_name]]Failure, Unit>> delete(String id);
|
|
21
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Value validators template for input validation
|
|
3
|
+
* Generates validation functions for different data types:
|
|
4
|
+
* - String validation (empty check and custom rules)
|
|
5
|
+
* - Numeric validation (int, double)
|
|
6
|
+
* - Boolean validation
|
|
7
|
+
* - DateTime validation
|
|
8
|
+
*
|
|
9
|
+
* Uses Either types for functional error handling
|
|
10
|
+
* Returns validation failures or valid values
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import 'package:dartz/dartz.dart';
|
|
14
|
+
import 'package:[[project_name]]/core/model/failures.dart';
|
|
15
|
+
|
|
16
|
+
{% for field in field_list %}
|
|
17
|
+
{% if field.name != 'id' %}
|
|
18
|
+
{% if field.type == 'String' %}
|
|
19
|
+
Either<ValueFailure<String>, String> validate[[field.pascal_name]](String input) {
|
|
20
|
+
if (input.isEmpty) {
|
|
21
|
+
return left(ValueFailure.empty(failedValue: input));
|
|
22
|
+
}
|
|
23
|
+
// Additional string validations can be added here
|
|
24
|
+
return right(input);
|
|
25
|
+
}
|
|
26
|
+
{% elif field.type == 'int' %}
|
|
27
|
+
Either<ValueFailure<int>, int> validate[[field.pascal_name]](int input) {
|
|
28
|
+
// Additional int validations can be added here
|
|
29
|
+
return right(input);
|
|
30
|
+
}
|
|
31
|
+
{% elif field.type == 'double' %}
|
|
32
|
+
Either<ValueFailure<double>, double> validate[[field.pascal_name]](double input) {
|
|
33
|
+
// Additional double validations can be added here
|
|
34
|
+
return right(input);
|
|
35
|
+
}
|
|
36
|
+
{% elif field.type == 'bool' %}
|
|
37
|
+
Either<ValueFailure<bool>, bool> validate[[field.pascal_name]](bool input) {
|
|
38
|
+
// Boolean validation - always valid
|
|
39
|
+
// Additional boolean validations can be added here
|
|
40
|
+
return right(input);
|
|
41
|
+
}
|
|
42
|
+
{% elif field.type == 'DateTime' %}
|
|
43
|
+
Either<ValueFailure<DateTime>, DateTime> validate[[field.pascal_name]](DateTime input) {
|
|
44
|
+
// Additional datetime validations can be added here
|
|
45
|
+
return right(input);
|
|
46
|
+
}
|
|
47
|
+
{% else %}
|
|
48
|
+
Either<ValueFailure<String>, String> validate[[field.pascal_name]](String input) {
|
|
49
|
+
if (input.isEmpty) {
|
|
50
|
+
return left(ValueFailure.empty(failedValue: input));
|
|
51
|
+
}
|
|
52
|
+
// Additional string validations can be added here
|
|
53
|
+
return right(input);
|
|
54
|
+
}
|
|
55
|
+
{% endif %}
|
|
56
|
+
{% endif %}
|
|
57
|
+
{% endfor %}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Home screen template with navigation structure
|
|
3
|
+
* Generates the main application screen with:
|
|
4
|
+
* - Bottom navigation bar integration
|
|
5
|
+
* - Multiple tab screens based on configuration
|
|
6
|
+
* - Optional drawer support
|
|
7
|
+
* - StatefulWidget for navigation state management
|
|
8
|
+
*
|
|
9
|
+
* This serves as the main navigation hub for the application
|
|
10
|
+
* with configurable navigation items and screens
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import 'package:caravaggio_ui/caravaggio_ui.dart';
|
|
14
|
+
import 'package:flutter/material.dart';
|
|
15
|
+
import 'package:[[project_name]]/core/presentation/bottom_nav_bar.dart';
|
|
16
|
+
import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
|
|
17
|
+
{% for nav_item in nav_items %}
|
|
18
|
+
import 'package:[[project_name]]/features/home/[[nav_item.name]]_screen.dart';
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% if has_drawer %}
|
|
21
|
+
import 'package:[[project_name]]/core/presentation/app_drawer.dart';
|
|
22
|
+
{% endif %}
|
|
23
|
+
|
|
24
|
+
class HomePage extends StatefulWidget {
|
|
25
|
+
static const String routeName = '/home';
|
|
26
|
+
|
|
27
|
+
const HomePage({super.key});
|
|
28
|
+
|
|
29
|
+
@override
|
|
30
|
+
State<HomePage> createState() => _HomePageState();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class _HomePageState extends State<HomePage> {
|
|
34
|
+
int _selectedIndex = 0;
|
|
35
|
+
|
|
36
|
+
final List<Widget> _pages = [
|
|
37
|
+
const Center(child: Text('Home Content')),
|
|
38
|
+
{% for nav_item in nav_items %}
|
|
39
|
+
const [[nav_item.name|title]]Screen(),
|
|
40
|
+
{% endfor %}
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
void _onItemTapped(int index) {
|
|
44
|
+
setState(() {
|
|
45
|
+
_selectedIndex = index;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@override
|
|
50
|
+
Widget build(BuildContext context) {
|
|
51
|
+
return CustomScaffold(
|
|
52
|
+
title: CText.title('Home', size: TextSize.medium).bold,
|
|
53
|
+
showBackButton: false,
|
|
54
|
+
{% if has_drawer %}
|
|
55
|
+
drawer: const AppDrawer(),
|
|
56
|
+
{% endif %}
|
|
57
|
+
body: Column(
|
|
58
|
+
children: <Widget>[
|
|
59
|
+
Expanded(child: _pages[_selectedIndex]),
|
|
60
|
+
BottomNavBar(
|
|
61
|
+
currentIndex: _selectedIndex,
|
|
62
|
+
onTap: _onItemTapped,
|
|
63
|
+
),
|
|
64
|
+
],
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import 'package:caravaggio_ui/caravaggio_ui.dart';
|
|
2
|
+
import 'package:flutter/material.dart';
|
|
3
|
+
{% if has_login %}
|
|
4
|
+
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
5
|
+
import 'package:go_router/go_router.dart';
|
|
6
|
+
import 'package:[[project_name]]/features/auth/application/auth_bloc.dart';
|
|
7
|
+
import 'package:[[project_name]]/features/auth/presentation/login_page.dart';
|
|
8
|
+
{% endif %}
|
|
9
|
+
import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
|
|
10
|
+
|
|
11
|
+
class HomePage extends StatefulWidget {
|
|
12
|
+
static const String routeName = '/home';
|
|
13
|
+
|
|
14
|
+
const HomePage({super.key});
|
|
15
|
+
|
|
16
|
+
@override
|
|
17
|
+
State<HomePage> createState() => _HomePageState();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class _HomePageState extends State<HomePage> {
|
|
21
|
+
@override
|
|
22
|
+
Widget build(BuildContext context) {
|
|
23
|
+
{% if has_login %}
|
|
24
|
+
return BlocListener<AuthBloc, AuthState>(
|
|
25
|
+
listener: (BuildContext context, AuthState state) => switch (state) {
|
|
26
|
+
Unauthenticated() => context.go(LoginPage.routeName),
|
|
27
|
+
_ => null,
|
|
28
|
+
},
|
|
29
|
+
child: CustomScaffold(
|
|
30
|
+
title: CText.title('Home', size: TextSize.medium).bold,
|
|
31
|
+
showBackButton: false,
|
|
32
|
+
action: CButton.icon(
|
|
33
|
+
icon: Icons.logout,
|
|
34
|
+
tooltip: 'Logout',
|
|
35
|
+
onPressed: () => context.read<AuthBloc>().add(const AuthEvent.signedOut()),
|
|
36
|
+
),
|
|
37
|
+
body: const Center(
|
|
38
|
+
child: Text('Home Screen'),
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
{% else %}
|
|
43
|
+
return CustomScaffold(
|
|
44
|
+
title: CText.title('Home', size: TextSize.medium).bold,
|
|
45
|
+
showBackButton: false,
|
|
46
|
+
body: const Center(
|
|
47
|
+
child: Text('Home Screen'),
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
{% endif %}
|
|
51
|
+
}
|
|
52
|
+
}
|