feat: Refactor ExperiencePage and ExperienceCustomInput to use design system components and remove deprecated ExperienceBadge

This commit is contained in:
Achintha Isuru
2026-01-24 21:08:55 -05:00
parent f81e1949d1
commit d6cceaceec
4 changed files with 24 additions and 133 deletions

View File

@@ -18,7 +18,7 @@ extension ProfileNavigator on IModularNavigator {
/// Navigates to the experience page. /// Navigates to the experience page.
void pushExperience() { void pushExperience() {
pushNamed('/profile/experience'); pushNamed('./experience');
} }
/// Navigates to the attire page. /// Navigates to the attire page.

View File

@@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart'; import 'package:flutter_modular/flutter_modular.dart';
import '../blocs/experience_bloc.dart'; import '../blocs/experience_bloc.dart';
import '../widgets/experience_badge.dart';
import '../widgets/experience_custom_input.dart'; import '../widgets/experience_custom_input.dart';
import '../widgets/experience_section_title.dart'; import '../widgets/experience_section_title.dart';
@@ -63,21 +62,9 @@ class _ExperienceView extends StatelessWidget {
return Scaffold( return Scaffold(
backgroundColor: UiColors.background, backgroundColor: UiColors.background,
appBar: AppBar( appBar: UiAppBar(
backgroundColor: UiColors.bgPopup, title: i18n.title,
elevation: 0, onLeadingPressed: () => Modular.to.pop(),
leading: IconButton(
icon: Icon(UiIcons.chevronLeft, color: UiColors.textSecondary),
onPressed: () => Modular.to.pop(),
),
title: Text(
i18n.title,
style: UiTypography.title1m.copyWith(color: UiColors.textPrimary),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(1.0),
child: Container(color: UiColors.border, height: 1.0),
),
), ),
body: BlocConsumer<ExperienceBloc, ExperienceState>( body: BlocConsumer<ExperienceBloc, ExperienceState>(
listener: (context, state) { listener: (context, state) {
@@ -105,12 +92,14 @@ class _ExperienceView extends StatelessWidget {
runSpacing: UiConstants.space2, runSpacing: UiConstants.space2,
children: state.availableIndustries children: state.availableIndustries
.map( .map(
(i) => ExperienceBadge( (i) => UiChip(
label: _getIndustryLabel(i18n.industries, i), label: _getIndustryLabel(i18n.industries, i),
isSelected: state.selectedIndustries.contains(i), isSelected: state.selectedIndustries.contains(i),
onTap: () => BlocProvider.of<ExperienceBloc>(context) onTap: () => BlocProvider.of<ExperienceBloc>(context)
.add(ExperienceIndustryToggled(i)), .add(ExperienceIndustryToggled(i)),
isIndustry: true, variant: state.selectedIndustries.contains(i)
? UiChipVariant.primary
: UiChipVariant.secondary,
), ),
) )
.toList(), .toList(),
@@ -127,11 +116,14 @@ class _ExperienceView extends StatelessWidget {
runSpacing: UiConstants.space2, runSpacing: UiConstants.space2,
children: state.availableSkills children: state.availableSkills
.map( .map(
(s) => ExperienceBadge( (s) => UiChip(
label: _getSkillLabel(i18n.skills, s), label: _getSkillLabel(i18n.skills, s),
isSelected: state.selectedSkills.contains(s), isSelected: state.selectedSkills.contains(s),
onTap: () => BlocProvider.of<ExperienceBloc>(context) onTap: () => BlocProvider.of<ExperienceBloc>(context)
.add(ExperienceSkillToggled(s)), .add(ExperienceSkillToggled(s)),
variant: state.selectedSkills.contains(s)
? UiChipVariant.primary
: UiChipVariant.secondary,
), ),
) )
.toList(), .toList(),
@@ -171,24 +163,9 @@ class _ExperienceView extends StatelessWidget {
spacing: UiConstants.space2, spacing: UiConstants.space2,
runSpacing: UiConstants.space2, runSpacing: UiConstants.space2,
children: customSkills.map((skill) { children: customSkills.map((skill) {
return Container( return UiChip(
padding: EdgeInsets.symmetric( label: skill,
horizontal: UiConstants.space3, variant: UiChipVariant.accent,
vertical: UiConstants.space2,
),
decoration: BoxDecoration(
color: UiColors.accent,
borderRadius: UiConstants.radiusFull,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
skill,
style: UiTypography.body2m.copyWith(color: UiColors.textPrimary),
),
],
),
); );
}).toList(), }).toList(),
), ),
@@ -206,32 +183,22 @@ class _ExperienceView extends StatelessWidget {
child: SafeArea( child: SafeArea(
child: SizedBox( child: SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: UiButton.primary(
onPressed: state.status == ExperienceStatus.loading onPressed: state.status == ExperienceStatus.loading
? null ? null
: () => BlocProvider.of<ExperienceBloc>(context).add(ExperienceSubmitted()), : () => BlocProvider.of<ExperienceBloc>(context).add(ExperienceSubmitted()),
style: ElevatedButton.styleFrom( fullWidth: true,
backgroundColor: UiColors.primary, text: state.status == ExperienceStatus.loading ? null : i18n.save_button,
foregroundColor: UiColors.primaryForeground,
padding: EdgeInsets.symmetric(vertical: UiConstants.space4),
shape: RoundedRectangleBorder(
borderRadius: UiConstants.radiusFull,
),
elevation: 0,
),
child: state.status == ExperienceStatus.loading child: state.status == ExperienceStatus.loading
? SizedBox( ? SizedBox(
height: 20.0, height: 20.0,
width: 20.0, width: 20.0,
child: CircularProgressIndicator( child: CircularProgressIndicator(
strokeWidth: 2, strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(UiColors.primaryForeground), valueColor: AlwaysStoppedAnimation<Color>(UiColors.white), // UiColors.primaryForeground is white mostly
), ),
) )
: Text( : null,
i18n.save_button,
style: UiTypography.title2b,
),
), ),
), ),
), ),

View File

@@ -1,43 +0,0 @@
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
class ExperienceBadge extends StatelessWidget {
final String label;
final bool isSelected;
final VoidCallback onTap;
final bool isIndustry;
const ExperienceBadge({
super.key,
required this.label,
required this.isSelected,
required this.onTap,
this.isIndustry = false,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.symmetric(
horizontal: UiConstants.space3,
vertical: UiConstants.space2,
),
decoration: BoxDecoration(
color: isSelected ? UiColors.primary : Colors.transparent,
borderRadius: UiConstants.radiusFull,
border: Border.all(
color: isSelected ? UiColors.primary : UiColors.border,
),
),
child: Text(
label,
style: UiTypography.body2m.copyWith(
color: isSelected ? UiColors.primaryForeground : UiColors.textSecondary,
),
),
),
);
}
}

View File

@@ -33,49 +33,16 @@ class _ExperienceCustomInputState extends State<ExperienceCustomInput> {
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: TextField( child: UiTextField(
controller: _controller, controller: _controller,
onSubmitted: (_) => _addSkill(), onSubmitted: (_) => _addSkill(),
style: UiTypography.body1r.copyWith(color: UiColors.textPrimary), hintText: t.staff.onboarding.experience.custom_skill_hint,
decoration: InputDecoration(
hintText: t.staff.onboarding.experience.custom_skill_hint,
hintStyle: UiTypography.body1r.copyWith(color: UiColors.textPlaceholder),
contentPadding: EdgeInsets.symmetric(
horizontal: UiConstants.space3,
vertical: UiConstants.space3,
),
border: OutlineInputBorder(
borderRadius: UiConstants.radiusMd,
borderSide: BorderSide(color: UiColors.border),
),
enabledBorder: OutlineInputBorder(
borderRadius: UiConstants.radiusMd,
borderSide: BorderSide(color: UiColors.border),
),
focusedBorder: OutlineInputBorder(
borderRadius: UiConstants.radiusMd,
borderSide: BorderSide(color: UiColors.primary),
),
),
fillColor: UiColors.bgPopup,
filled: true,
),
), ),
), ),
SizedBox(width: UiConstants.space2), SizedBox(width: UiConstants.space2),
InkWell( UiIconButton.primary(
icon: UiIcons.add,
onTap: _addSkill, onTap: _addSkill,
child: Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: UiColors.primary,
borderRadius: BorderRadius.circular(UiConstants.radiusMd),
),
child: Center(
child: Icon(UiIcons.add, color: UiColors.primaryForeground),
),
),
), ),
], ],
); );