kasy-cli 1.10.0 → 1.13.0

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.
Files changed (141) hide show
  1. package/bin/kasy.js +25 -4
  2. package/lib/commands/check.js +40 -50
  3. package/lib/commands/deploy.js +25 -25
  4. package/lib/commands/splash.js +220 -0
  5. package/lib/scaffold/CHANGELOG.json +9 -0
  6. package/lib/scaffold/backends/api/patch/lib/main.dart +29 -10
  7. package/lib/scaffold/backends/supabase/patch/lib/main.dart +29 -10
  8. package/lib/scaffold/features/README.md +15 -139
  9. package/lib/scaffold/shared/generator-utils.js +16 -15
  10. package/lib/utils/i18n.js +292 -43
  11. package/package.json +2 -2
  12. package/templates/firebase/android/app/src/main/res/drawable-hdpi/android12splash.png +0 -0
  13. package/templates/firebase/android/app/src/main/res/drawable-hdpi/splash.png +0 -0
  14. package/templates/firebase/android/app/src/main/res/drawable-mdpi/android12splash.png +0 -0
  15. package/templates/firebase/android/app/src/main/res/drawable-mdpi/splash.png +0 -0
  16. package/templates/firebase/android/app/src/main/res/drawable-night/background.png +0 -0
  17. package/templates/firebase/android/app/src/main/res/drawable-night/launch_background.xml +9 -0
  18. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/android12splash.png +0 -0
  19. package/templates/firebase/android/app/src/main/res/drawable-night-hdpi/splash.png +0 -0
  20. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/android12splash.png +0 -0
  21. package/templates/firebase/android/app/src/main/res/drawable-night-mdpi/splash.png +0 -0
  22. package/templates/firebase/android/app/src/main/res/drawable-night-v21/background.png +0 -0
  23. package/templates/firebase/android/app/src/main/res/drawable-night-v21/launch_background.xml +9 -0
  24. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/android12splash.png +0 -0
  25. package/templates/firebase/android/app/src/main/res/drawable-night-xhdpi/splash.png +0 -0
  26. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png +0 -0
  27. package/templates/firebase/android/app/src/main/res/drawable-night-xxhdpi/splash.png +0 -0
  28. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png +0 -0
  29. package/templates/firebase/android/app/src/main/res/drawable-night-xxxhdpi/splash.png +0 -0
  30. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/android12splash.png +0 -0
  31. package/templates/firebase/android/app/src/main/res/drawable-xhdpi/splash.png +0 -0
  32. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/android12splash.png +0 -0
  33. package/templates/firebase/android/app/src/main/res/drawable-xxhdpi/splash.png +0 -0
  34. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/android12splash.png +0 -0
  35. package/templates/firebase/android/app/src/main/res/drawable-xxxhdpi/splash.png +0 -0
  36. package/templates/firebase/android/app/src/main/res/values-night-v31/styles.xml +2 -1
  37. package/templates/firebase/android/app/src/main/res/values-v31/styles.xml +1 -0
  38. package/templates/firebase/assets/images/splash_logo_dark.png +0 -0
  39. package/templates/firebase/assets/images/splash_logo_light.png +0 -0
  40. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json +9 -8
  41. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchBackground.imageset/darkbackground.png +0 -0
  42. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +33 -0
  43. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png +0 -0
  44. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png +0 -0
  45. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png +0 -0
  46. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark.png +0 -0
  47. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@2x.png +0 -0
  48. package/templates/firebase/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImageDark@3x.png +0 -0
  49. package/templates/firebase/ios/Runner/Base.lproj/LaunchScreen.storyboard +1 -1
  50. package/templates/firebase/lib/core/initializer/onstart_widget.dart +7 -1
  51. package/templates/firebase/lib/core/theme/providers/theme_provider.dart +48 -24
  52. package/templates/firebase/lib/features/onboarding/ui/components/onboarding_features.dart +4 -0
  53. package/templates/firebase/lib/features/onboarding/ui/onboarding_page.dart +1 -0
  54. package/templates/firebase/lib/features/onboarding/ui/widgets/onboarding_feature.dart +13 -0
  55. package/templates/firebase/lib/features/settings/settings_page.dart +158 -18
  56. package/templates/firebase/lib/i18n/en.i18n.json +6 -2
  57. package/templates/firebase/lib/i18n/es.i18n.json +6 -2
  58. package/templates/firebase/lib/i18n/pt.i18n.json +6 -2
  59. package/templates/firebase/lib/main.dart +29 -10
  60. package/templates/firebase/pubspec.yaml +4 -5
  61. package/templates/firebase/test/core/data/repositories/user_repository_test.dart +1 -1
  62. package/templates/firebase/web/index.html +47 -39
  63. package/templates/firebase/web/splash/img/dark-1x.png +0 -0
  64. package/templates/firebase/web/splash/img/dark-2x.png +0 -0
  65. package/templates/firebase/web/splash/img/dark-3x.png +0 -0
  66. package/templates/firebase/web/splash/img/dark-4x.png +0 -0
  67. package/templates/firebase/web/splash/img/light-1x.png +0 -0
  68. package/templates/firebase/web/splash/img/light-2x.png +0 -0
  69. package/templates/firebase/web/splash/img/light-3x.png +0 -0
  70. package/templates/firebase/web/splash/img/light-4x.png +0 -0
  71. package/lib/scaffold/features/analytics/lib/core/data/api/analytics_api.dart +0 -124
  72. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.es.md +0 -35
  73. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.md +0 -35
  74. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/BUG.pt.md +0 -35
  75. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.es.md +0 -12
  76. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.md +0 -12
  77. package/lib/scaffold/features/ci/.github/ISSUE_TEMPLATE/feature_request.pt.md +0 -12
  78. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.es.md +0 -17
  79. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  80. package/lib/scaffold/features/ci/.github/PULL_REQUEST_TEMPLATE.pt.md +0 -17
  81. package/lib/scaffold/features/ci/.github/dependabot.yml +0 -16
  82. package/lib/scaffold/features/ci/.github/workflows/app.yml +0 -20
  83. package/lib/scaffold/features/ci/.gitlab/templates/deploy.yaml +0 -14
  84. package/lib/scaffold/features/ci/.gitlab/templates/dropbox.yaml +0 -19
  85. package/lib/scaffold/features/ci/.gitlab/templates/flutter.yaml +0 -163
  86. package/lib/scaffold/features/ci/.gitlab/templates/mailgun.yaml +0 -28
  87. package/lib/scaffold/features/ci/.gitlab-ci.yml +0 -37
  88. package/lib/scaffold/features/ci/codemagic.yaml +0 -157
  89. package/lib/scaffold/features/facebook/lib/core/data/api/tracking_api.dart +0 -111
  90. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_request_entity.dart +0 -27
  91. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/entities/feature_vote_entity.dart +0 -27
  92. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_request_api.dart +0 -50
  93. package/lib/scaffold/features/feedback/lib/features/feedbacks/api/feature_vote_api.dart +0 -79
  94. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feature_requests.dart +0 -48
  95. package/lib/scaffold/features/feedback/lib/features/feedbacks/models/feedback_state.dart +0 -42
  96. package/lib/scaffold/features/feedback/lib/features/feedbacks/providers/feedback_page_notifier.dart +0 -147
  97. package/lib/scaffold/features/feedback/lib/features/feedbacks/repositories/feature_request_repository.dart +0 -95
  98. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/component/add_feature_form.dart +0 -199
  99. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/feedback_page.dart +0 -175
  100. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/add_feature_button.dart +0 -76
  101. package/lib/scaffold/features/feedback/lib/features/feedbacks/ui/widgets/feature_card.dart +0 -279
  102. package/lib/scaffold/features/ios-release/.kasy/apple.env.example +0 -8
  103. package/lib/scaffold/features/ios-release/.kasy/codemagic.env.example +0 -7
  104. package/lib/scaffold/features/ios-release/docs/codemagic-release.en.md +0 -50
  105. package/lib/scaffold/features/ios-release/docs/codemagic-release.es.md +0 -50
  106. package/lib/scaffold/features/ios-release/docs/codemagic-release.pt.md +0 -50
  107. package/lib/scaffold/features/ios-release/docs/ios-release.en.md +0 -41
  108. package/lib/scaffold/features/ios-release/docs/ios-release.es.md +0 -41
  109. package/lib/scaffold/features/ios-release/docs/ios-release.pt.md +0 -41
  110. package/lib/scaffold/features/ios-release/scripts/bump-ios-version.js +0 -38
  111. package/lib/scaffold/features/ios-release/scripts/release-ios.sh +0 -137
  112. package/lib/scaffold/features/llm_chat/lib/features/llm_chat/llm_chat_page.dart +0 -301
  113. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/providers/reminder_notifier.dart +0 -81
  114. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/repositories/reminder_preferences.dart +0 -76
  115. package/lib/scaffold/features/local_notifications/lib/features/local_reminder/ui/reminder_page.dart +0 -282
  116. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/entities/user_info_entity.dart +0 -24
  117. package/lib/scaffold/features/onboarding/lib/features/onboarding/api/user_infos_api.dart +0 -71
  118. package/lib/scaffold/features/onboarding/lib/features/onboarding/models/user_info.dart +0 -92
  119. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_model.dart +0 -15
  120. package/lib/scaffold/features/onboarding/lib/features/onboarding/providers/onboarding_provider.dart +0 -78
  121. package/lib/scaffold/features/onboarding/lib/features/onboarding/repositories/user_infos_repository.dart +0 -29
  122. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/animations/page_transitions.dart +0 -30
  123. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_att_setup.dart +0 -66
  124. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_features.dart +0 -72
  125. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_loader.dart +0 -92
  126. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_notifications_setup.dart +0 -73
  127. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/components/onboarding_questions.dart +0 -89
  128. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/onboarding_page.dart +0 -94
  129. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_background.dart +0 -80
  130. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_feature.dart +0 -139
  131. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart +0 -110
  132. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_progress.dart +0 -84
  133. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_radio_question.dart +0 -173
  134. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_reassurance.dart +0 -45
  135. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/onboarding_sticky_footer.dart +0 -77
  136. package/lib/scaffold/features/onboarding/lib/features/onboarding/ui/widgets/selectable_row_tile.dart +0 -392
  137. package/lib/scaffold/features/revenuecat/lib/core/data/api/tracking_api.dart +0 -116
  138. package/lib/scaffold/features/revenuecat/lib/core/data/models/subscription.dart +0 -322
  139. package/lib/scaffold/features/revenuecat/lib/core/home_widgets/home_widget_background_task.dart +0 -41
  140. package/lib/scaffold/features/revenuecat/lib/core/states/user_state_notifier.dart +0 -305
  141. package/templates/firebase/assets/images/splashscreen.png +0 -0
@@ -1,139 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_animate/flutter_animate.dart';
3
- import 'package:kasy_kit/components/components.dart';
4
- import 'package:kasy_kit/core/theme/theme.dart';
5
- import 'package:kasy_kit/core/widgets/responsive_layout.dart';
6
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
7
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_illustration_scaffold.dart';
8
-
9
- /// A generic onboarding step widget with text and image.
10
- class OnboardingStep extends StatelessWidget {
11
- final String? title;
12
- final Widget? titleWidget;
13
- final String imgPath;
14
- final String description;
15
- final String btnText;
16
- final String nextRoute;
17
- final VoidCallback? onNext;
18
- final double progress;
19
- final Widget? image;
20
- final bool withBg;
21
-
22
- const OnboardingStep({
23
- super.key,
24
- this.title,
25
- this.titleWidget,
26
- required this.imgPath,
27
- required this.description,
28
- required this.btnText,
29
- required this.nextRoute,
30
- required this.progress,
31
- this.onNext,
32
- this.withBg = false,
33
- this.image,
34
- });
35
-
36
- @override
37
- Widget build(BuildContext context) {
38
- final Widget? illustration = image ??
39
- (imgPath.isNotEmpty
40
- ? Animate(
41
- effects: const [
42
- FadeEffect(
43
- delay: Duration(milliseconds: 100),
44
- duration: Duration(milliseconds: 200),
45
- curve: Curves.easeIn,
46
- ),
47
- MoveEffect(
48
- delay: Duration(milliseconds: 100),
49
- duration: Duration(milliseconds: 450),
50
- curve: Curves.easeOut,
51
- begin: Offset(0, 50),
52
- end: Offset.zero,
53
- ),
54
- ],
55
- child: Image.asset(imgPath, fit: BoxFit.contain),
56
- )
57
- : null);
58
-
59
- final scaffold = OnboardingIllustrationScaffold(
60
- progress: progress,
61
- title: title ?? '',
62
- titleWidget: title != null
63
- ? Animate(
64
- effects: const [
65
- FadeEffect(
66
- delay: Duration(milliseconds: 200),
67
- duration: Duration(milliseconds: 200),
68
- curve: Curves.easeIn,
69
- ),
70
- MoveEffect(
71
- delay: Duration(milliseconds: 200),
72
- duration: Duration(milliseconds: 450),
73
- curve: Curves.easeOut,
74
- begin: Offset(0, 50),
75
- end: Offset.zero,
76
- ),
77
- ],
78
- child: Text(
79
- title!,
80
- textAlign: TextAlign.center,
81
- style: context.textTheme.headlineMedium?.copyWith(
82
- color: context.colors.onBackground,
83
- fontWeight: FontWeight.w600,
84
- ),
85
- ),
86
- )
87
- : titleWidget,
88
- description: description,
89
- descriptionWidget: Animate(
90
- effects: const [
91
- FadeEffect(
92
- delay: Duration(milliseconds: 300),
93
- duration: Duration(milliseconds: 200),
94
- curve: Curves.easeIn,
95
- ),
96
- MoveEffect(
97
- delay: Duration(milliseconds: 300),
98
- duration: Duration(milliseconds: 450),
99
- curve: Curves.easeOut,
100
- begin: Offset(0, 50),
101
- end: Offset.zero,
102
- ),
103
- ],
104
- child: Text(
105
- description,
106
- textAlign: TextAlign.center,
107
- style: context.textTheme.bodyLarge?.copyWith(
108
- color: context.colors.onBackground.withValues(alpha: 0.6),
109
- ),
110
- ),
111
- ),
112
- image: illustration,
113
- footerActions: [
114
- KasyButton(
115
- label: btnText,
116
- expand: true,
117
- onPressed: () {
118
- if (onNext != null) {
119
- onNext!.call();
120
- } else {
121
- Navigator.of(context).pushReplacementNamed(nextRoute);
122
- }
123
- },
124
- ),
125
- ],
126
- );
127
-
128
- final content = ResponsiveLayout(
129
- small: withBg
130
- ? OnboardingBackground(child: scaffold)
131
- : ColoredBox(
132
- color: context.colors.background,
133
- child: scaffold,
134
- ),
135
- );
136
-
137
- return content;
138
- }
139
- }
@@ -1,110 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/core/theme/theme.dart';
3
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_progress.dart';
4
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_sticky_footer.dart';
5
-
6
- /// Layout compartilhado para passos de onboarding com ilustração e ações no rodapé.
7
- ///
8
- /// Evita buracos grandes de [Expanded] + [Spacer] com imagens [BoxFit.contain].
9
- class OnboardingIllustrationScaffold extends StatelessWidget {
10
- const OnboardingIllustrationScaffold({
11
- super.key,
12
- required this.progress,
13
- required this.title,
14
- required this.description,
15
- required this.footerActions,
16
- this.imageAsset,
17
- this.image,
18
- this.imageMaxHeight = 280,
19
- this.titleWidget,
20
- this.descriptionWidget,
21
- this.footerAnimationDelayMs = 400,
22
- this.animateFooter = true,
23
- });
24
-
25
- final double progress;
26
- final String title;
27
- final String description;
28
- final String? imageAsset;
29
- final Widget? image;
30
- final List<Widget> footerActions;
31
- final double imageMaxHeight;
32
- final Widget? titleWidget;
33
- final Widget? descriptionWidget;
34
- final int footerAnimationDelayMs;
35
- final bool animateFooter;
36
-
37
- @override
38
- Widget build(BuildContext context) {
39
- final Widget? illustration = image ??
40
- (imageAsset != null && imageAsset!.isNotEmpty
41
- ? Image.asset(imageAsset!, fit: BoxFit.contain)
42
- : null);
43
-
44
- return Column(
45
- crossAxisAlignment: CrossAxisAlignment.stretch,
46
- children: [
47
- Expanded(
48
- child: SafeArea(
49
- bottom: false,
50
- child: Column(
51
- crossAxisAlignment: CrossAxisAlignment.stretch,
52
- children: [
53
- OnboardingProgress(value: progress),
54
- Expanded(
55
- child: SingleChildScrollView(
56
- padding: const EdgeInsets.fromLTRB(
57
- KasySpacing.xl,
58
- KasySpacing.lg,
59
- KasySpacing.xl,
60
- KasySpacing.md,
61
- ),
62
- child: Column(
63
- children: [
64
- titleWidget ??
65
- Text(
66
- title,
67
- textAlign: TextAlign.center,
68
- style:
69
- context.textTheme.headlineMedium?.copyWith(
70
- color: context.colors.onBackground,
71
- fontWeight: FontWeight.w600,
72
- ),
73
- ),
74
- const SizedBox(height: KasySpacing.smd),
75
- descriptionWidget ??
76
- Text(
77
- description,
78
- textAlign: TextAlign.center,
79
- style: context.textTheme.bodyLarge?.copyWith(
80
- color: context.colors.onBackground.withValues(
81
- alpha: 0.6,
82
- ),
83
- ),
84
- ),
85
- if (illustration != null) ...[
86
- const SizedBox(height: KasySpacing.xl),
87
- ConstrainedBox(
88
- constraints:
89
- BoxConstraints(maxHeight: imageMaxHeight),
90
- child: illustration,
91
- ),
92
- ],
93
- ],
94
- ),
95
- ),
96
- ),
97
- ],
98
- ),
99
- ),
100
- ),
101
- OnboardingStickyFooter(
102
- animate: animateFooter,
103
- animationDelayMs: footerAnimationDelayMs,
104
- horizontalPadding: KasySpacing.xl,
105
- children: footerActions,
106
- ),
107
- ],
108
- );
109
- }
110
- }
@@ -1,84 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:kasy_kit/core/theme/theme.dart';
3
-
4
- class OnboardingProgress extends StatefulWidget {
5
- final double value;
6
-
7
- const OnboardingProgress({super.key, required this.value});
8
-
9
- @override
10
- State<OnboardingProgress> createState() => _OnboardingProgressState();
11
- }
12
-
13
- class _OnboardingProgressState extends State<OnboardingProgress>
14
- with SingleTickerProviderStateMixin {
15
- late final AnimationController animationController;
16
-
17
- late Animation<double> _progressAnimation;
18
-
19
- @override
20
- void initState() {
21
- super.initState();
22
-
23
- animationController = AnimationController(
24
- vsync: this,
25
- duration: const Duration(milliseconds: 1500),
26
- );
27
- _setProgressValueAndStart();
28
- }
29
-
30
- @override
31
- void didUpdateWidget(OnboardingProgress oldWidget) {
32
- super.didUpdateWidget(oldWidget);
33
- if (oldWidget.value != widget.value) {
34
- _setProgressValueAndStart();
35
- }
36
- }
37
-
38
- @override
39
- void dispose() {
40
- animationController.dispose();
41
- super.dispose();
42
- }
43
-
44
- void _setProgressValueAndStart() {
45
- var start = 0.0;
46
- if (widget.value > 0) {
47
- start = widget.value - 0.1;
48
- }
49
- _progressAnimation = Tween<double>(
50
- begin: start,
51
- end: widget.value,
52
- ).animate(
53
- CurvedAnimation(
54
- parent: animationController,
55
- curve: Curves.ease,
56
- ),
57
- );
58
- animationController.forward(from: 0);
59
- }
60
-
61
- @override
62
- Widget build(BuildContext context) {
63
- return AnimatedBuilder(
64
- animation: _progressAnimation,
65
- builder: (context, child) {
66
- return Padding(
67
- // Intentionally narrow (80px lateral) — visual design choice for progress bar
68
- padding: const EdgeInsets.fromLTRB(80, KasySpacing.md, 80, 0),
69
- child: ClipRRect(
70
- borderRadius: KasyRadius.fullBorderRadius,
71
- child: LinearProgressIndicator(
72
- value: _progressAnimation.value,
73
- minHeight: 16,
74
- valueColor: AlwaysStoppedAnimation<Color>(
75
- context.colors.primary,
76
- ),
77
- backgroundColor: context.colors.primary.withValues(alpha: 0.1),
78
- ),
79
- ),
80
- );
81
- },
82
- );
83
- }
84
- }
@@ -1,173 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_animate/flutter_animate.dart';
3
- import 'package:flutter_riverpod/flutter_riverpod.dart';
4
- import 'package:kasy_kit/components/components.dart';
5
- import 'package:kasy_kit/core/animations/movefade_anim.dart';
6
- import 'package:kasy_kit/core/theme/theme.dart';
7
- import 'package:kasy_kit/core/widgets/responsive_layout.dart';
8
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_background.dart';
9
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_progress.dart';
10
- import 'package:kasy_kit/features/onboarding/ui/widgets/onboarding_sticky_footer.dart';
11
- import 'package:kasy_kit/features/onboarding/ui/widgets/selectable_row_tile.dart';
12
-
13
- typedef OptionBuilder = Widget Function(String key, bool selected);
14
-
15
- typedef ReassuranceBuilder = Widget? Function(String key);
16
-
17
- typedef OnOptionIdSelected = void Function(String id);
18
-
19
- typedef OnValidate = void Function(String? key);
20
-
21
- /// Single choice question with radio buttons
22
- class OnboardingRadioQuestion extends ConsumerStatefulWidget {
23
- final double? progress;
24
- final String title;
25
- final String description;
26
- final String btnText;
27
- final List<String> optionIds;
28
- final OptionBuilder optionBuilder;
29
- final ReassuranceBuilder? reassuranceBuilder;
30
- final OnOptionIdSelected? onOptionIdSelected;
31
- final OnValidate? onValidate;
32
-
33
- const OnboardingRadioQuestion({
34
- super.key,
35
- required this.title,
36
- required this.description,
37
- required this.btnText,
38
- required this.optionIds,
39
- required this.optionBuilder,
40
- this.progress,
41
- this.onOptionIdSelected,
42
- this.onValidate,
43
- this.reassuranceBuilder,
44
- });
45
-
46
- @override
47
- ConsumerState<OnboardingRadioQuestion> createState() =>
48
- _OnboardingRadioQuestionState();
49
- }
50
-
51
- class _OnboardingRadioQuestionState
52
- extends ConsumerState<OnboardingRadioQuestion> {
53
- String? selectedChoiceId;
54
-
55
- @override
56
- Widget build(BuildContext context) {
57
- final scrollBody = Column(
58
- crossAxisAlignment: CrossAxisAlignment.stretch,
59
- children: [
60
- if (widget.progress != null)
61
- OnboardingProgress(value: widget.progress!),
62
- Padding(
63
- padding: const EdgeInsets.fromLTRB(
64
- KasySpacing.md,
65
- KasySpacing.xl,
66
- KasySpacing.md,
67
- 0,
68
- ),
69
- child: MoveFadeAnim(
70
- delayInMs: 100,
71
- child: Text(
72
- widget.title,
73
- textAlign: TextAlign.center,
74
- style: context.textTheme.headlineLarge?.copyWith(
75
- color: context.colors.onBackground,
76
- ),
77
- ),
78
- ),
79
- ),
80
- Padding(
81
- padding: const EdgeInsets.fromLTRB(
82
- KasySpacing.lg,
83
- KasySpacing.md,
84
- KasySpacing.lg,
85
- KasySpacing.xl,
86
- ),
87
- child: MoveFadeAnim(
88
- delayInMs: 200,
89
- child: Text(
90
- widget.description,
91
- textAlign: TextAlign.center,
92
- style: context.textTheme.bodyLarge?.copyWith(
93
- color: context.colors.onBackground.withValues(alpha: 0.6),
94
- ),
95
- ),
96
- ),
97
- ),
98
- Padding(
99
- padding: const EdgeInsets.symmetric(horizontal: KasySpacing.md),
100
- child: OnboardingSelectableRowGroup(
101
- physics: const NeverScrollableScrollPhysics(),
102
- options: widget.optionIds
103
- .map(
104
- (e) {
105
- final index = widget.optionIds.indexOf(e);
106
- return Animate(
107
- effects: [
108
- FadeEffect(
109
- delay: Duration(milliseconds: 300 + index * 100),
110
- duration: const Duration(milliseconds: 550),
111
- curve: Curves.easeInOut,
112
- ),
113
- ],
114
- child: widget.optionBuilder(e, e == selectedChoiceId),
115
- );
116
- },
117
- ).toList(),
118
- onSelect: (index, selected) {
119
- widget.onOptionIdSelected?.call(widget.optionIds[index]);
120
- setState(() {
121
- selectedChoiceId = widget.optionIds[index];
122
- });
123
- },
124
- onSelectInfoWidget: widget.optionIds
125
- .map((el) => widget.reassuranceBuilder?.call(el))
126
- .toList(),
127
- ),
128
- ),
129
- const SizedBox(height: KasySpacing.xl),
130
- ],
131
- );
132
-
133
- return OnboardingBackground(
134
- child: Column(
135
- crossAxisAlignment: CrossAxisAlignment.stretch,
136
- children: [
137
- Expanded(
138
- child: SafeArea(
139
- bottom: false,
140
- child: SingleChildScrollView(
141
- padding: const EdgeInsets.only(bottom: KasySpacing.md),
142
- child: ResponsiveBuilder(
143
- small: scrollBody,
144
- medium: Center(
145
- child: ConstrainedBox(
146
- constraints: const BoxConstraints(maxWidth: 600),
147
- child: scrollBody,
148
- ),
149
- ),
150
- ),
151
- ),
152
- ),
153
- ),
154
- DeviceSizeBuilder(
155
- builder: (device) => OnboardingStickyFooter(
156
- maxContentWidth:
157
- device == DeviceType.small ? null : 600,
158
- children: [
159
- KasyButton(
160
- label: widget.btnText,
161
- expand: true,
162
- onPressed: selectedChoiceId == null
163
- ? null
164
- : () => widget.onValidate?.call(selectedChoiceId),
165
- ),
166
- ],
167
- ),
168
- ),
169
- ],
170
- ),
171
- );
172
- }
173
- }
@@ -1,45 +0,0 @@
1
- import 'package:flutter/material.dart';
2
- import 'package:flutter_animate/flutter_animate.dart';
3
- import 'package:kasy_kit/core/theme/theme.dart';
4
-
5
- class CheckedReassurance extends StatelessWidget {
6
- final String text;
7
-
8
- const CheckedReassurance({super.key, required this.text});
9
-
10
- @override
11
- Widget build(BuildContext context) {
12
- return Animate(
13
- effects: const [
14
- FadeEffect(
15
- duration: Duration(milliseconds: 300),
16
- curve: Curves.easeInOut,
17
- ),
18
- MoveEffect(
19
- duration: Duration(milliseconds: 250),
20
- curve: Curves.easeInOut,
21
- begin: Offset(0, -20),
22
- end: Offset.zero,
23
- ),
24
- ],
25
- child: Container(
26
- padding: const EdgeInsets.all(KasySpacing.lg),
27
- decoration: BoxDecoration(
28
- color: context.colors.success.withValues(alpha: 0.05),
29
- borderRadius: KasyRadius.smBorderRadius,
30
- border: Border.all(
31
- color: context.colors.muted,
32
- ),
33
- ),
34
- child: Text(
35
- text,
36
- textAlign: TextAlign.left,
37
- style: context.textTheme.bodyLarge?.copyWith(
38
- color: context.colors.muted,
39
- fontWeight: FontWeight.w900,
40
- ),
41
- ),
42
- ),
43
- );
44
- }
45
- }
@@ -1,77 +0,0 @@
1
- import 'package:flutter/foundation.dart';
2
- import 'package:flutter/material.dart';
3
- import 'package:kasy_kit/core/animations/movefade_anim.dart';
4
- import 'package:kasy_kit/core/theme/theme.dart';
5
-
6
- /// Rodapé fixo do onboarding: fundo até a borda inferior + animação de entrada.
7
- class OnboardingStickyFooter extends StatelessWidget {
8
- const OnboardingStickyFooter({
9
- super.key,
10
- required this.children,
11
- this.animate = true,
12
- this.animationDelayMs = 400,
13
- this.horizontalPadding = KasySpacing.lg,
14
- this.maxContentWidth,
15
- });
16
-
17
- final List<Widget> children;
18
- final bool animate;
19
- final int animationDelayMs;
20
- final double horizontalPadding;
21
-
22
- /// Largura máxima do conteúdo (ex.: 600 em telas médias).
23
- final double? maxContentWidth;
24
-
25
- @override
26
- Widget build(BuildContext context) {
27
- final bottomInset = MediaQuery.viewPaddingOf(context).bottom;
28
-
29
- Widget content = Column(
30
- crossAxisAlignment: CrossAxisAlignment.stretch,
31
- children: children,
32
- );
33
-
34
- if (maxContentWidth != null) {
35
- content = Center(
36
- child: ConstrainedBox(
37
- constraints: BoxConstraints(maxWidth: maxContentWidth!),
38
- child: content,
39
- ),
40
- );
41
- }
42
-
43
- Widget footer = Container(
44
- width: double.infinity,
45
- decoration: BoxDecoration(
46
- color: context.colors.background,
47
- boxShadow: [
48
- BoxShadow(
49
- color: context.colors.onBackground.withValues(alpha: 0.06),
50
- blurRadius: 16,
51
- offset: const Offset(0, -4),
52
- ),
53
- ],
54
- ),
55
- padding: EdgeInsets.fromLTRB(
56
- horizontalPadding,
57
- KasySpacing.md,
58
- horizontalPadding,
59
- KasySpacing.md +
60
- bottomInset +
61
- (defaultTargetPlatform == TargetPlatform.android
62
- ? KasySpacing.sm
63
- : 0),
64
- ),
65
- child: content,
66
- );
67
-
68
- if (animate) {
69
- footer = MoveFadeAnim(
70
- delayInMs: animationDelayMs,
71
- child: footer,
72
- );
73
- }
74
-
75
- return footer;
76
- }
77
- }