maestro improvise

This commit is contained in:
2026-03-09 22:10:40 +05:30
parent 91cedf54c9
commit 52bb1d1af4
53 changed files with 903 additions and 452 deletions

View File

@@ -104,11 +104,15 @@ class ClientGetStartedPage extends StatelessWidget {
const SizedBox(height: UiConstants.space8),
// Sign In Button
UiButton.primary(
text: t.client_authentication.get_started_page
.sign_in_button,
onPressed: () => Modular.to.toClientSignIn(),
fullWidth: true,
Semantics(
identifier: 'client_landing_sign_in',
child: UiButton.primary(
text: t.client_authentication
.get_started_page.sign_in_button,
onPressed: () =>
Modular.to.toClientSignIn(),
fullWidth: true,
),
),
const SizedBox(height: UiConstants.space3),

View File

@@ -5,46 +5,25 @@ import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
/// A custom bottom navigation bar for the Client app.
///
/// This widget provides a glassmorphic bottom navigation bar with blur effect
/// and follows the KROW Design System guidelines. It displays five tabs:
/// Coverage, Billing, Home, Orders, and Reports.
///
/// The widget uses:
/// - [UiColors] for all color values
/// - [UiTypography] for text styling
/// - [UiIcons] for icon assets
/// - [UiConstants] for spacing and sizing
class ClientMainBottomBar extends StatelessWidget {
/// Creates a [ClientMainBottomBar].
///
/// The [currentIndex] indicates which tab is currently selected.
/// The [onTap] callback is invoked when a tab is tapped.
const ClientMainBottomBar({
required this.currentIndex,
required this.onTap,
super.key,
});
/// The index of the currently selected tab.
final int currentIndex;
/// Callback invoked when a tab is tapped.
///
/// The callback receives the index of the tapped tab.
final ValueChanged<int> onTap;
@override
Widget build(BuildContext context) {
final Translations t = Translations.of(context);
// Client App colors from design system
const Color activeColor = UiColors.textPrimary;
const Color inactiveColor = UiColors.textInactive;
return Stack(
clipBehavior: Clip.none,
children: <Widget>[
// Glassmorphic background with blur effect
Positioned.fill(
child: ClipRect(
child: BackdropFilter(
@@ -62,7 +41,6 @@ class ClientMainBottomBar extends StatelessWidget {
),
),
),
// Navigation items
Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom + UiConstants.space2,
@@ -74,6 +52,7 @@ class ClientMainBottomBar extends StatelessWidget {
children: <Widget>[
_buildNavItem(
index: 0,
id: 'client_nav_coverage',
icon: UiIcons.calendar,
label: t.client_main.tabs.coverage,
activeColor: activeColor,
@@ -81,6 +60,7 @@ class ClientMainBottomBar extends StatelessWidget {
),
_buildNavItem(
index: 1,
id: 'client_nav_billing',
icon: UiIcons.dollar,
label: t.client_main.tabs.billing,
activeColor: activeColor,
@@ -88,6 +68,7 @@ class ClientMainBottomBar extends StatelessWidget {
),
_buildNavItem(
index: 2,
id: 'client_nav_home',
icon: UiIcons.building,
label: t.client_main.tabs.home,
activeColor: activeColor,
@@ -95,6 +76,7 @@ class ClientMainBottomBar extends StatelessWidget {
),
_buildNavItem(
index: 3,
id: 'client_nav_orders',
icon: UiIcons.file,
label: t.client_main.tabs.orders,
activeColor: activeColor,
@@ -102,6 +84,7 @@ class ClientMainBottomBar extends StatelessWidget {
),
_buildNavItem(
index: 4,
id: 'client_nav_reports',
icon: UiIcons.chart,
label: t.client_main.tabs.reports,
activeColor: activeColor,
@@ -114,15 +97,9 @@ class ClientMainBottomBar extends StatelessWidget {
);
}
/// Builds a single navigation item.
///
/// Uses design system tokens for all styling:
/// - Icon size uses a standard value (24px is acceptable for navigation icons)
/// - Spacing uses [UiConstants.space1]
/// - Typography uses [UiTypography.footnote2m]
/// - Colors are passed as parameters from design system
Widget _buildNavItem({
required int index,
required String id,
required IconData icon,
required String label,
required Color activeColor,
@@ -130,26 +107,30 @@ class ClientMainBottomBar extends StatelessWidget {
}) {
final bool isSelected = currentIndex == index;
return Expanded(
child: GestureDetector(
onTap: () => onTap(index),
behavior: HitTestBehavior.opaque,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(
icon,
color: isSelected ? activeColor : inactiveColor,
size: 24, // Standard navigation icon size
),
const SizedBox(height: UiConstants.space1),
Text(
label,
style: UiTypography.footnote2m.copyWith(
child: Semantics(
identifier: id,
label: label,
child: GestureDetector(
onTap: () => onTap(index),
behavior: HitTestBehavior.opaque,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(
icon,
color: isSelected ? activeColor : inactiveColor,
size: 24,
),
),
],
const SizedBox(height: UiConstants.space1),
Text(
label,
style: UiTypography.footnote2m.copyWith(
color: isSelected ? activeColor : inactiveColor,
),
),
],
),
),
),
);

View File

@@ -86,16 +86,22 @@ class ClientHomeHeader extends StatelessWidget {
Row(
spacing: UiConstants.space2,
children: <Widget>[
HeaderIconButton(
icon: UiIcons.edit,
isActive: state.isEditMode,
onTap: () => BlocProvider.of<ClientHomeBloc>(
context,
).add(ClientHomeEditModeToggled()),
Semantics(
identifier: 'client_home_edit_mode',
child: HeaderIconButton(
icon: UiIcons.edit,
isActive: state.isEditMode,
onTap: () => BlocProvider.of<ClientHomeBloc>(
context,
).add(ClientHomeEditModeToggled()),
),
),
HeaderIconButton(
icon: UiIcons.settings,
onTap: () => Modular.to.toClientSettings(),
Semantics(
identifier: 'client_home_settings',
child: HeaderIconButton(
icon: UiIcons.settings,
onTap: () => Modular.to.toClientSettings(),
),
),
],
),