feat: Enhance officer and profile models with place of birth and date of birth fields; update step indicators for improved layout and styling

This commit is contained in:
vergiLgood1 2025-05-19 21:20:14 +07:00
parent ce7d448b2f
commit ce7d5f5cf4
6 changed files with 334 additions and 346 deletions

View File

@ -12,6 +12,8 @@ class OfficerModel {
final String? phone; final String? phone;
final String? email; final String? email;
final String? avatar; final String? avatar;
final String? placeOfBirth;
final DateTime? dateOfBirth;
final DateTime? validUntil; final DateTime? validUntil;
final String? qrCode; final String? qrCode;
final DateTime? createdAt; final DateTime? createdAt;
@ -30,6 +32,8 @@ class OfficerModel {
this.phone, this.phone,
this.email, this.email,
this.avatar, this.avatar,
this.placeOfBirth,
this.dateOfBirth,
this.validUntil, this.validUntil,
this.qrCode, this.qrCode,
this.createdAt, this.createdAt,
@ -51,6 +55,11 @@ class OfficerModel {
phone: json['phone'] as String?, phone: json['phone'] as String?,
email: json['email'] as String?, email: json['email'] as String?,
avatar: json['avatar'] as String?, avatar: json['avatar'] as String?,
placeOfBirth: json['place_of_birth'] as String?,
dateOfBirth:
json['date_of_birth'] != null
? DateTime.parse(json['date_of_birth'] as String)
: null,
validUntil: validUntil:
json['valid_until'] != null json['valid_until'] != null
? DateTime.parse(json['valid_until'] as String) ? DateTime.parse(json['valid_until'] as String)
@ -85,6 +94,8 @@ class OfficerModel {
'phone': phone, 'phone': phone,
'email': email, 'email': email,
'avatar': avatar, 'avatar': avatar,
'place_of_birth': placeOfBirth,
'date_of_birth': dateOfBirth?.toIso8601String(),
'valid_until': validUntil?.toIso8601String(), 'valid_until': validUntil?.toIso8601String(),
'qr_code': qrCode, 'qr_code': qrCode,
'created_at': createdAt?.toIso8601String(), 'created_at': createdAt?.toIso8601String(),
@ -106,6 +117,8 @@ class OfficerModel {
String? phone, String? phone,
String? email, String? email,
String? avatar, String? avatar,
String? placeOfBirth,
DateTime? dateOfBirth,
DateTime? validUntil, DateTime? validUntil,
String? qrCode, String? qrCode,
DateTime? createdAt, DateTime? createdAt,
@ -124,6 +137,8 @@ class OfficerModel {
phone: phone ?? this.phone, phone: phone ?? this.phone,
email: email ?? this.email, email: email ?? this.email,
avatar: avatar ?? this.avatar, avatar: avatar ?? this.avatar,
placeOfBirth: placeOfBirth ?? this.placeOfBirth,
dateOfBirth: dateOfBirth ?? this.dateOfBirth,
validUntil: validUntil ?? this.validUntil, validUntil: validUntil ?? this.validUntil,
qrCode: qrCode ?? this.qrCode, qrCode: qrCode ?? this.qrCode,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
@ -149,6 +164,17 @@ class OfficerModel {
position: officerData['position'], position: officerData['position'],
phone: officerData['phone'], phone: officerData['phone'],
email: metadata['email'], email: metadata['email'],
avatar: officerData['avatar'],
placeOfBirth: officerData['place_of_birth'],
dateOfBirth:
officerData['date_of_birth'] != null
? DateTime.parse(officerData['date_of_birth'])
: null,
validUntil:
officerData['valid_until'] != null
? DateTime.parse(officerData['valid_until'])
: null,
qrCode: officerData['qr_code'],
); );
} }

View File

@ -108,7 +108,7 @@ class OnboardingController extends GetxController
TFullScreenLoader.stopLoading(); TFullScreenLoader.stopLoading();
if (!isLocationValid) { if (isLocationValid) {
// If location is valid, proceed to role selection // If location is valid, proceed to role selection
Get.offAllNamed(AppRoutes.roleSelection); Get.offAllNamed(AppRoutes.roleSelection);

View File

@ -8,7 +8,9 @@ class ProfileModel {
final String? lastName; final String? lastName;
final String? bio; final String? bio;
final Map<String, dynamic>? address; final Map<String, dynamic>? address;
final String? placeOfBirth;
final DateTime? birthDate; final DateTime? birthDate;
ProfileModel({ ProfileModel({
required this.id, required this.id,
@ -20,6 +22,7 @@ class ProfileModel {
this.lastName, this.lastName,
this.bio, this.bio,
this.address, this.address,
this.placeOfBirth,
this.birthDate, this.birthDate,
}); });
@ -38,6 +41,7 @@ class ProfileModel {
json['address'] != null json['address'] != null
? Map<String, dynamic>.from(json['address'] as Map) ? Map<String, dynamic>.from(json['address'] as Map)
: null, : null,
placeOfBirth: json['place_of_birth'] as String?,
birthDate: birthDate:
json['birth_date'] != null json['birth_date'] != null
? DateTime.parse(json['birth_date'] as String) ? DateTime.parse(json['birth_date'] as String)
@ -57,6 +61,7 @@ class ProfileModel {
'last_name': lastName, 'last_name': lastName,
'bio': bio, 'bio': bio,
'address': address, 'address': address,
'place_of_birth': placeOfBirth,
'birth_date': birthDate?.toIso8601String(), 'birth_date': birthDate?.toIso8601String(),
}; };
} }
@ -72,6 +77,7 @@ class ProfileModel {
String? lastName, String? lastName,
String? bio, String? bio,
Map<String, dynamic>? address, Map<String, dynamic>? address,
String? placeOfBirth,
DateTime? birthDate, DateTime? birthDate,
}) { }) {
return ProfileModel( return ProfileModel(
@ -84,6 +90,7 @@ class ProfileModel {
lastName: lastName ?? this.lastName, lastName: lastName ?? this.lastName,
bio: bio ?? this.bio, bio: bio ?? this.bio,
address: address ?? this.address, address: address ?? this.address,
placeOfBirth: placeOfBirth ?? this.placeOfBirth,
birthDate: birthDate ?? this.birthDate, birthDate: birthDate ?? this.birthDate,
); );
} }

View File

@ -32,14 +32,17 @@ class NumberedStepIndicator extends StatelessWidget {
} }
Widget _buildTwoStepIndicator(BuildContext context) { Widget _buildTwoStepIndicator(BuildContext context) {
const boxSize = TSizes.xl + TSizes.xs;
final double padding = TSizes.xs;
return Column( return Column(
children: [ children: [
// Step indicators with connector line
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: TSizes.md / 2), padding: EdgeInsets.symmetric(horizontal: padding),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// First step // First step box
_buildStepBox(0), _buildStepBox(0),
// Connector line // Connector line
@ -61,110 +64,99 @@ class NumberedStepIndicator extends StatelessWidget {
), ),
), ),
// Second step // Second step box
_buildStepBox(1), _buildStepBox(1),
], ],
), ),
), ),
SizedBox(height: TSizes.sm),
// Step titles const SizedBox(height: TSizes.sm),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // Step titles with fixed widths aligned with boxes
children: List.generate(totalSteps, (index) { Padding(
return Text( padding: EdgeInsets.symmetric(horizontal: padding),
stepTitles[index], child: Row(
style: theme.textTheme.labelMedium?.copyWith( children: [
fontWeight: // First step title
index == currentStep ? FontWeight.bold : FontWeight.normal, SizedBox(
color: width: boxSize,
index == currentStep child: Text(
? theme.primaryColor stepTitles[0],
: isDark textAlign: TextAlign.center,
? Colors.white70 style: _getTitleStyle(0),
: TColors.textSecondary, overflow: TextOverflow.ellipsis,
maxLines: 2,
),
), ),
);
}), // Empty space matching the connector
Expanded(child: Container()),
// Second step title
SizedBox(
width: boxSize,
child: Text(
stepTitles[1],
textAlign: TextAlign.center,
style: _getTitleStyle(1),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
),
],
),
), ),
], ],
); );
} }
Widget _buildMultiStepIndicator(BuildContext context) { Widget _buildMultiStepIndicator(BuildContext context) {
const boxSize = TSizes.xl + TSizes.xs;
final availableWidth =
MediaQuery.of(context).size.width - (TSizes.defaultSpace * 2);
final double spacing =
(availableWidth - (boxSize * totalSteps)) / (totalSteps - 1);
return Column( return Column(
children: [ children: [
// Step indicators with connector lines
Row( Row(
children: List.generate(totalSteps, (index) { mainAxisAlignment: MainAxisAlignment.spaceBetween,
final isLast = index == totalSteps - 1; children: List.generate(2 * totalSteps - 1, (index) {
// Even indexes are step boxes, odd indexes are connectors
return Expanded( if (index.isEven) {
child: Row( final stepIndex = index ~/ 2;
children: [ return _buildStepBox(stepIndex);
// Step number } else {
_buildStepBox(index), final prevStepIndex = index ~/ 2;
return Container(
// Connector line width: spacing,
if (!isLast) height: TSizes.dividerHeight,
Expanded( color:
child: Stack( prevStepIndex < currentStep
alignment: Alignment.center, ? theme.primaryColor
children: [ : isDark
Container( ? TColors.darkerGrey
height: TSizes.dividerHeight, : TColors.borderPrimary,
color: );
isDark }
? TColors.darkerGrey
: TColors.borderPrimary,
),
Container(
height: TSizes.dividerHeight,
width:
index < currentStep
? MediaQuery.of(context).size.width
: 0,
color: theme.primaryColor,
),
],
),
),
],
),
);
}), }),
), ),
SizedBox(height: TSizes.sm),
// Step titles const SizedBox(height: TSizes.md),
// Step titles with fixed positions matching boxes
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(totalSteps, (index) { children: List.generate(totalSteps, (index) {
return Expanded( return SizedBox(
child: Padding( width: boxSize,
padding: EdgeInsets.only( child: Text(
left: index == 0 ? 0 : TSizes.xs, stepTitles[index],
right: index == totalSteps - 1 ? 0 : TSizes.xs, textAlign: TextAlign.center,
), style: _getTitleStyle(index),
child: Text( maxLines: 2,
stepTitles[index], overflow: TextOverflow.ellipsis,
textAlign:
index == 0
? TextAlign.start
: index == totalSteps - 1
? TextAlign.end
: TextAlign.center,
style: theme.textTheme.labelMedium?.copyWith(
fontWeight:
index == currentStep
? FontWeight.bold
: FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
),
),
), ),
); );
}), }),
@ -176,13 +168,14 @@ class NumberedStepIndicator extends StatelessWidget {
Widget _buildStepBox(int index) { Widget _buildStepBox(int index) {
final isActive = index <= currentStep; final isActive = index <= currentStep;
final isCompleted = index < currentStep; final isCompleted = index < currentStep;
const boxSize = TSizes.xl + TSizes.xs;
return GestureDetector( return GestureDetector(
onTap: () => onStepTapped(index), onTap: () => onStepTapped(index),
child: AnimatedContainer( child: AnimatedContainer(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
width: TSizes.xl + TSizes.xs, width: boxSize,
height: TSizes.xl + TSizes.xs, height: boxSize,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color:
isCompleted isCompleted
@ -218,4 +211,16 @@ class NumberedStepIndicator extends StatelessWidget {
), ),
); );
} }
TextStyle? _getTitleStyle(int index) {
return theme.textTheme.labelMedium?.copyWith(
fontWeight: index == currentStep ? FontWeight.bold : FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
);
}
} }

View File

@ -32,12 +32,14 @@ class RoundedStepIndicator extends StatelessWidget {
} }
Widget _buildTwoStepIndicator(BuildContext context) { Widget _buildTwoStepIndicator(BuildContext context) {
final circleWidth = TSizes.xl;
final double padding = TSizes.xs;
return Column( return Column(
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: TSizes.md / 2), padding: EdgeInsets.symmetric(horizontal: padding),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// First step // First step
_buildStepCircle(0), _buildStepCircle(0),
@ -66,106 +68,96 @@ class RoundedStepIndicator extends StatelessWidget {
], ],
), ),
), ),
SizedBox(height: TSizes.sm),
const SizedBox(height: TSizes.sm),
// Step titles // Step titles with fixed widths aligned with circles
Row( Padding(
mainAxisAlignment: MainAxisAlignment.spaceBetween, padding: EdgeInsets.symmetric(horizontal: padding),
children: List.generate(totalSteps, (index) { child: Row(
return SizedBox( children: [
width: TSizes.xl, // First step title
child: Text( SizedBox(
stepTitles[index], width: circleWidth,
textAlign: TextAlign.center, child: Text(
overflow: TextOverflow.ellipsis, stepTitles[0],
style: theme.textTheme.labelMedium?.copyWith( textAlign: TextAlign.center,
fontWeight: style: _getTitleStyle(0),
index == currentStep overflow: TextOverflow.ellipsis,
? FontWeight.bold maxLines: 2,
: FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
), ),
), ),
);
}), // Empty space matching the connector
Expanded(child: Container()),
// Second step title
SizedBox(
width: circleWidth,
child: Text(
stepTitles[1],
textAlign: TextAlign.center,
style: _getTitleStyle(1),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
),
],
),
), ),
], ],
); );
} }
Widget _buildMultiStepIndicator(BuildContext context) { Widget _buildMultiStepIndicator(BuildContext context) {
final circleWidth = TSizes.xl;
final availableWidth =
MediaQuery.of(context).size.width - (TSizes.defaultSpace * 2);
final double spacing =
(availableWidth - (circleWidth * totalSteps)) / (totalSteps - 1);
return Column( return Column(
children: [ children: [
SizedBox( // Step indicators with connector lines
height: TSizes.xl + TSizes.xs, Row(
child: Stack( mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: List.generate(2 * totalSteps - 1, (index) {
// Connector lines first (in the background) // Even indexes are step circles, odd indexes are connectors
Positioned.fill( if (index.isEven) {
top: TSizes.xl / 2 - TSizes.dividerHeight / 2, final stepIndex = index ~/ 2;
child: Row( return _buildStepCircle(stepIndex);
children: List.generate(totalSteps - 1, (index) { } else {
final isActive = index < currentStep; return Container(
return Expanded( width: spacing,
child: Container( height: TSizes.dividerHeight,
height: TSizes.dividerHeight, decoration: BoxDecoration(
margin: EdgeInsets.symmetric(horizontal: TSizes.xs), color:
decoration: BoxDecoration( (index ~/ 2) < currentStep
color: ? theme.primaryColor
isActive : isDark
? theme.primaryColor ? TColors.darkerGrey
: isDark : TColors.borderPrimary,
? TColors.darkerGrey borderRadius: BorderRadius.circular(TSizes.dividerHeight / 2),
: TColors.borderPrimary,
borderRadius: BorderRadius.circular(
TSizes.dividerHeight / 2,
),
),
),
);
}),
), ),
), );
}
// Step circles on top }),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(totalSteps, (index) {
return _buildStepCircle(index);
}),
),
],
),
), ),
SizedBox(height: TSizes.sm),
const SizedBox(height: TSizes.sm),
// Step titles // Step titles with fixed positions matching circles
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(totalSteps, (index) { children: List.generate(totalSteps, (index) {
return SizedBox( return SizedBox(
width: TSizes.xl, width: circleWidth,
child: Text( child: Text(
stepTitles[index], stepTitles[index],
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: _getTitleStyle(index),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: theme.textTheme.labelMedium?.copyWith( maxLines: 2,
fontWeight:
index == currentStep
? FontWeight.bold
: FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
),
), ),
); );
}), }),
@ -227,4 +219,16 @@ class RoundedStepIndicator extends StatelessWidget {
), ),
); );
} }
TextStyle? _getTitleStyle(int index) {
return theme.textTheme.labelMedium?.copyWith(
fontWeight: index == currentStep ? FontWeight.bold : FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
);
}
} }

View File

@ -33,44 +33,17 @@ class StandardStepIndicator extends StatelessWidget {
Widget _buildTwoStepIndicator(BuildContext context) { Widget _buildTwoStepIndicator(BuildContext context) {
final circleWidth = TSizes.xl; final circleWidth = TSizes.xl;
final double padding = TSizes.xs;
return Column( return Column(
children: [ children: [
// Step indicators with connector line
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: TSizes.md / 2), padding: EdgeInsets.symmetric(horizontal: padding),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// First step // First step
Container( _buildStepCircle(0, circleWidth),
width: circleWidth,
height: circleWidth,
decoration: BoxDecoration(
color: theme.primaryColor,
shape: BoxShape.circle,
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => onStepTapped(0),
borderRadius: BorderRadius.circular(circleWidth),
child: Center(
child:
0 < currentStep
? Icon(
Icons.check,
color: Colors.white,
size: TSizes.iconSm,
)
: Icon(
Icons.circle,
color: Colors.white,
size: TSizes.iconXs,
),
),
),
),
),
// Connector line that spans the entire space between circles // Connector line that spans the entire space between circles
Expanded( Expanded(
@ -86,173 +59,97 @@ class StandardStepIndicator extends StatelessWidget {
), ),
// Second step // Second step
Container( _buildStepCircle(1, circleWidth),
],
),
),
const SizedBox(height: TSizes.sm),
// Step titles with fixed widths aligned with circles
Padding(
padding: EdgeInsets.symmetric(horizontal: padding),
child: Row(
children: [
SizedBox(
width: circleWidth, width: circleWidth,
height: circleWidth, child: Text(
decoration: BoxDecoration( stepTitles[0],
color: textAlign: TextAlign.center,
currentStep >= 1 style: _getTitleStyle(0),
? theme.primaryColor overflow: TextOverflow.ellipsis,
: isDark maxLines: 2,
? TColors.darkerGrey
: TColors.secondary,
shape: BoxShape.circle,
), ),
child: Material( ),
color: Colors.transparent,
child: InkWell( // Empty space matching the connector
onTap: () => onStepTapped(1), Expanded(child: Container()),
borderRadius: BorderRadius.circular(circleWidth),
child: Center( // Second step title
child: SizedBox(
currentStep >= 1 width: circleWidth,
? Icon( child: Text(
currentStep > 1 ? Icons.check : Icons.circle, stepTitles[1],
color: Colors.white, textAlign: TextAlign.center,
size: style: _getTitleStyle(1),
currentStep > 1 overflow: TextOverflow.ellipsis,
? TSizes.iconSm maxLines: 2,
: TSizes.iconXs,
)
: Text(
'2',
style: theme.textTheme.bodySmall?.copyWith(
color:
isDark
? Colors.white
: TColors.textSecondary,
fontWeight: FontWeight.bold,
),
),
),
),
), ),
), ),
], ],
), ),
), ),
SizedBox(height: TSizes.sm),
// Step titles
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(totalSteps, (index) {
return Text(
stepTitles[index],
style: theme.textTheme.labelMedium?.copyWith(
fontWeight:
index == currentStep ? FontWeight.bold : FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
),
);
}),
),
], ],
); );
} }
Widget _buildMultiStepIndicator(BuildContext context) { Widget _buildMultiStepIndicator(BuildContext context) {
const circleWidth = TSizes.xl;
final availableWidth =
MediaQuery.of(context).size.width - (TSizes.defaultSpace * 2);
final double spacing =
(availableWidth - (circleWidth * totalSteps)) / (totalSteps - 1);
return Column( return Column(
children: [ children: [
// Step indicators with connector lines
Row( Row(
children: List.generate(totalSteps, (index) { mainAxisAlignment: MainAxisAlignment.spaceBetween,
final isActive = index <= currentStep; children: List.generate(2 * totalSteps - 1, (index) {
final isLast = index == totalSteps - 1; // Even indexes (0, 2, 4...) are step circles, odd indexes (1, 3, 5...) are connectors
if (index.isEven) {
return Expanded( final stepIndex = index ~/ 2;
child: Row( return _buildStepCircle(stepIndex, circleWidth);
children: [ } else {
// Step circle final prevStepIndex = index ~/ 2;
GestureDetector( return Container(
onTap: () => onStepTapped(index), width: spacing,
child: Container( height: TSizes.dividerHeight,
width: TSizes.xl, color:
height: TSizes.xl, prevStepIndex < currentStep
decoration: BoxDecoration( ? theme.primaryColor
color: : isDark
isActive ? TColors.darkerGrey
? theme.primaryColor : TColors.borderPrimary,
: isDark );
? TColors.darkerGrey }
: TColors.secondary,
shape: BoxShape.circle,
),
child: Center(
child:
isActive
? Icon(
index < currentStep
? Icons.check
: Icons.circle,
color: Colors.white,
size:
index < currentStep
? TSizes.iconSm
: TSizes.iconXs,
)
: Text(
'${index + 1}',
style: theme.textTheme.bodySmall?.copyWith(
color:
isDark
? Colors.white
: TColors.textSecondary,
fontWeight: FontWeight.bold,
),
),
),
),
),
// Connector line
if (!isLast)
Expanded(
child: Container(
height: TSizes.dividerHeight,
color:
index < currentStep
? theme.primaryColor
: isDark
? TColors.darkerGrey
: TColors.borderPrimary,
),
),
],
),
);
}), }),
), ),
SizedBox(height: TSizes.sm),
const SizedBox(height: TSizes.sm),
// Step titles // Step titles with fixed positions matching circles
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(totalSteps, (index) { children: List.generate(totalSteps, (index) {
return Expanded( return SizedBox(
width: circleWidth,
child: Text( child: Text(
stepTitles[index], stepTitles[index],
textAlign: textAlign: TextAlign.center,
index == 0 style: _getTitleStyle(index),
? TextAlign.start maxLines: 2,
: index == totalSteps - 1 overflow: TextOverflow.ellipsis,
? TextAlign.end
: TextAlign.center,
style: theme.textTheme.labelMedium?.copyWith(
fontWeight:
index == currentStep
? FontWeight.bold
: FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
),
), ),
); );
}), }),
@ -260,4 +157,53 @@ class StandardStepIndicator extends StatelessWidget {
], ],
); );
} }
Widget _buildStepCircle(int index, double circleWidth) {
final isActive = index <= currentStep;
return GestureDetector(
onTap: () => onStepTapped(index),
child: Container(
width: circleWidth,
height: circleWidth,
decoration: BoxDecoration(
color:
isActive
? theme.primaryColor
: isDark
? TColors.darkerGrey
: TColors.secondary,
shape: BoxShape.circle,
),
child: Center(
child:
isActive
? Icon(
index < currentStep ? Icons.check : Icons.circle,
color: Colors.white,
size: index < currentStep ? TSizes.iconSm : TSizes.iconXs,
)
: Text(
'${index + 1}',
style: theme.textTheme.bodySmall?.copyWith(
color: isDark ? Colors.white : TColors.textSecondary,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
TextStyle? _getTitleStyle(int index) {
return theme.textTheme.labelMedium?.copyWith(
fontWeight: index == currentStep ? FontWeight.bold : FontWeight.normal,
color:
index == currentStep
? theme.primaryColor
: isDark
? Colors.white70
: TColors.textSecondary,
);
}
} }