chore: fix 273+ analysis issues and repair corrupted core files

This commit is contained in:
2026-03-20 21:05:23 +05:30
parent d3159bc2ae
commit 39263a4af5
59 changed files with 265 additions and 3268 deletions

View File

@@ -53,7 +53,7 @@ class AttireGrid extends StatelessWidget {
return Container(
decoration: BoxDecoration(
color: isSelected
? UiColors.primary.withOpacity(0.1)
? UiColors.primary.withValues(alpha: 0.1)
: Colors.transparent,
borderRadius: UiConstants.radiusSm,
border: Border.all(
@@ -141,7 +141,7 @@ class AttireGrid extends StatelessWidget {
),
decoration: BoxDecoration(
color: hasPhoto
? UiColors.primary.withOpacity(0.05)
? UiColors.primary.withValues(alpha: 0.05)
: UiColors.white,
border: Border.all(
color: hasPhoto ? UiColors.primary : UiColors.border,

View File

@@ -1,26 +1,16 @@
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
import 'package:core_localization/core_localization.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:google_places_flutter/model/prediction.dart';
import 'package:krow_core/core.dart';
import '../blocs/personal_info_bloc.dart';
import '../blocs/personal_info_event.dart';
import '../blocs/personal_info_state.dart';
import '../widgets/preferred_locations_page/places_search_field.dart';
import '../widgets/preferred_locations_page/locations_list.dart';
import '../widgets/preferred_locations_page/empty_locations_state.dart';
import 'package:staff_profile_info/src/presentation/blocs/personal_info_bloc.dart';
import 'package:staff_profile_info/src/presentation/blocs/personal_info_state.dart';
import 'package:staff_profile_info/src/presentation/blocs/personal_info_event.dart';
/// The maximum number of preferred locations a staff member can add.
const int _kMaxLocations = 5;
/// Uber-style Preferred Locations editing page.
/// Page for staff members to manage their preferred work locations.
///
/// Allows staff to search for US locations using the Google Places API,
/// add them as chips (max 5), and save back to their profile.
/// Allows searching for and adding multiple locations to the profile.
class PreferredLocationsPage extends StatefulWidget {
/// Creates a [PreferredLocationsPage].
const PreferredLocationsPage({super.key});
@@ -30,211 +20,112 @@ class PreferredLocationsPage extends StatefulWidget {
}
class _PreferredLocationsPageState extends State<PreferredLocationsPage> {
late final TextEditingController _searchController;
late final FocusNode _searchFocusNode;
@override
void initState() {
super.initState();
_searchController = TextEditingController();
_searchFocusNode = FocusNode();
}
final TextEditingController _searchController = TextEditingController();
@override
void dispose() {
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
void _onLocationSelected(Prediction prediction, PersonalInfoBloc bloc) {
final String description = prediction.description ?? '';
if (description.isEmpty) return;
bloc.add(PersonalInfoLocationAdded(location: description));
// Clear search field after selection
void _onAddLocation(String location, PersonalInfoBloc bloc) {
if (location.trim().isEmpty) return;
bloc.add(PersonalInfoLocationAdded(location: location));
_searchController.clear();
_searchFocusNode.unfocus();
}
void _removeLocation(String location, PersonalInfoBloc bloc) {
void _onRemoveLocation(String location, PersonalInfoBloc bloc) {
bloc.add(PersonalInfoLocationRemoved(location: location));
}
void _save(BuildContext context, PersonalInfoBloc bloc, PersonalInfoState state) {
bloc.add(const PersonalInfoFormSubmitted());
}
@override
Widget build(BuildContext context) {
final TranslationsStaffOnboardingPersonalInfoEn i18n = t.staff.onboarding.personal_info;
// Access the same PersonalInfoBloc singleton managed by the module.
final PersonalInfoBloc bloc = Modular.get<PersonalInfoBloc>();
return BlocProvider<PersonalInfoBloc>.value(
value: bloc,
child: BlocConsumer<PersonalInfoBloc, PersonalInfoState>(
listener: (BuildContext context, PersonalInfoState state) {
if (state.status == PersonalInfoStatus.saved) {
UiSnackbar.show(
context,
message: i18n.preferred_locations.save_success,
type: UiSnackbarType.success,
);
} else if (state.status == PersonalInfoStatus.error) {
UiSnackbar.show(
context,
message: state.errorMessage != null
? translateErrorKey(state.errorMessage!)
: 'An error occurred',
type: UiSnackbarType.error,
);
}
},
builder: (BuildContext context, PersonalInfoState state) {
final List<String> locations = _currentLocations(state);
final bool atMax = locations.length >= _kMaxLocations;
final bool isSaving = state.status == PersonalInfoStatus.saving;
return Scaffold(
backgroundColor: UiColors.background,
appBar: UiAppBar(
title: i18n.preferred_locations.title,
showBackButton: true,
),
body: Stack(
children: [
SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// ” Description
Padding(
padding: const EdgeInsets.fromLTRB(
UiConstants.space5,
UiConstants.space5,
UiConstants.space5,
UiConstants.space3,
),
child: Text(
i18n.preferred_locations.description,
style: UiTypography.body2r.textSecondary,
),
),
// ” Search autocomplete field
Padding(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space5,
),
child: PlacesSearchField(
controller: _searchController,
focusNode: _searchFocusNode,
hint: i18n.preferred_locations.search_hint,
enabled: !atMax && !isSaving,
onSelected: (Prediction p) => _onLocationSelected(p, bloc),
),
),
// ” "Max reached" banner
if (atMax)
Padding(
padding: const EdgeInsets.fromLTRB(
UiConstants.space5,
UiConstants.space2,
UiConstants.space5,
0,
),
child: Row(
children: <Widget>[
const Icon(
UiIcons.info,
size: 14,
color: UiColors.textWarning,
),
const SizedBox(width: UiConstants.space1),
Text(
i18n.preferred_locations.max_reached,
style: UiTypography.footnote1r.textWarning,
),
],
),
),
const SizedBox(height: UiConstants.space5),
// ” Section label
Padding(
padding: const EdgeInsets.symmetric(
horizontal: UiConstants.space5,
),
child: Text(
i18n.preferred_locations.added_label,
style: UiTypography.titleUppercase3m.textSecondary,
),
),
const SizedBox(height: UiConstants.space3),
// Locations list / empty state
Expanded(
child: locations.isEmpty
? EmptyLocationsState(message: i18n.preferred_locations.empty_state)
: LocationsList(
locations: locations,
isSaving: isSaving,
removeTooltip: i18n.preferred_locations.remove_tooltip,
onRemove: (String loc) => _removeLocation(loc, bloc),
),
),
// Save button
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: UiButton.primary(
text: isSaving ? null : i18n.preferred_locations.save_button,
fullWidth: true,
onPressed: isSaving ? null : () => _save(context, bloc, state),
child: isSaving
? const SizedBox(
height: UiConstants.iconMd,
width: UiConstants.iconMd,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
UiColors.white,
),
),
)
: null,
),
),
],
),
),
if (isSaving)
Container(
color: UiColors.black.withValues(alpha: 0.3),
child: const Center(
child: CircularProgressIndicator(
color: UiColors.primary,
),
),
),
],
),
);
},
),
);
}
List<String> _currentLocations(PersonalInfoState state) {
final dynamic raw = state.formValues['preferredLocations'];
final dynamic raw = state.personalInfo?.preferredLocations;
if (raw is List<String>) return raw;
if (raw is List) return raw.map((dynamic e) => e.toString()).toList();
return <String>[];
}
}
@override
Widget build(BuildContext context) {
final TranslationsStaffOnboardingPersonalInfoEn i18n =
Translations.of(context).staff.onboarding.personal_info;
return BlocProvider<PersonalInfoBloc>.value(
value: Modular.get<PersonalInfoBloc>(),
child: BlocBuilder<PersonalInfoBloc, PersonalInfoState>(
builder: (BuildContext context, PersonalInfoState state) {
final PersonalInfoBloc bloc = BlocProvider.of<PersonalInfoBloc>(context);
final List<String> locations = _currentLocations(state);
return Scaffold(
appBar: UiAppBar(
title: i18n.preferred_locations.title,
showBackButton: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
i18n.preferred_locations.description,
style: UiTypography.body2r.textSecondary,
),
const SizedBox(height: UiConstants.space5),
// Search field (Mock autocomplete)
TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: i18n.preferred_locations.search_hint,
suffixIcon: IconButton(
icon: const Icon(UiIcons.add),
onPressed: () => _onAddLocation(_searchController.text, bloc),
),
),
onSubmitted: (String val) => _onAddLocation(val, bloc),
),
],
),
),
Expanded(
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space5),
itemCount: locations.length,
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemBuilder: (BuildContext context, int index) {
final String loc = locations[index];
return ListTile(
contentPadding: EdgeInsets.zero,
leading: const Icon(UiIcons.mapPin, color: UiColors.primary),
title: Text(loc, style: UiTypography.body2m.textPrimary),
trailing: IconButton(
icon: const Icon(UiIcons.close, size: 20),
onPressed: () => _onRemoveLocation(loc, bloc),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(UiConstants.space5),
child: UiButton.primary(
text: i18n.save_button,
onPressed: state.status == PersonalInfoStatus.loading
? null
: () => bloc.add(const PersonalInfoFormSubmitted()),
),
),
],
),
);
},
),
);
}
}