Add explicit types and improve type safety across codebase
This commit adds explicit type annotations to variables, function parameters, and return types throughout the codebase, particularly in widget trees, Bloc logic, and repository implementations. The changes improve code readability, maintainability, and type safety, and align with Dart best practices. No business logic was changed.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
import 'package:firebase_data_connect/src/core/ref.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||
import '../../domain/repositories/auth_repository_interface.dart';
|
||||
@@ -19,7 +20,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
|
||||
@override
|
||||
Stream<domain.User?> get currentUser => _firebaseAuth
|
||||
.authStateChanges()
|
||||
.map((firebaseUser) {
|
||||
.map((firebase.User? firebaseUser) {
|
||||
if (firebaseUser == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -35,24 +36,24 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
|
||||
/// Signs in with a phone number and returns a verification ID.
|
||||
@override
|
||||
Future<String?> signInWithPhone({required String phoneNumber}) async {
|
||||
final completer = Completer<String?>();
|
||||
final Completer<String?> completer = Completer<String?>();
|
||||
|
||||
await _firebaseAuth.verifyPhoneNumber(
|
||||
phoneNumber: phoneNumber,
|
||||
verificationCompleted: (_) {},
|
||||
verificationFailed: (e) {
|
||||
verificationFailed: (firebase.FirebaseAuthException e) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.completeError(
|
||||
Exception(e.message ?? 'Phone verification failed.'),
|
||||
);
|
||||
}
|
||||
},
|
||||
codeSent: (verificationId, _) {
|
||||
codeSent: (String verificationId, _) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(verificationId);
|
||||
}
|
||||
},
|
||||
codeAutoRetrievalTimeout: (verificationId) {
|
||||
codeAutoRetrievalTimeout: (String verificationId) {
|
||||
if (!completer.isCompleted) {
|
||||
completer.complete(verificationId);
|
||||
}
|
||||
@@ -74,20 +75,20 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
|
||||
required String verificationId,
|
||||
required String smsCode,
|
||||
}) async {
|
||||
final credential = firebase.PhoneAuthProvider.credential(
|
||||
final firebase.PhoneAuthCredential credential = firebase.PhoneAuthProvider.credential(
|
||||
verificationId: verificationId,
|
||||
smsCode: smsCode,
|
||||
);
|
||||
final userCredential = await _firebaseAuth.signInWithCredential(credential);
|
||||
final firebaseUser = userCredential.user;
|
||||
final firebase.UserCredential userCredential = await _firebaseAuth.signInWithCredential(credential);
|
||||
final firebase.User? firebaseUser = userCredential.user;
|
||||
if (firebaseUser == null) {
|
||||
throw Exception('Phone verification failed, no Firebase user received.');
|
||||
}
|
||||
|
||||
final response = await _dataConnect.getUserById(
|
||||
final QueryResult<dc.GetUserByIdData, dc.GetUserByIdVariables> response = await _dataConnect.getUserById(
|
||||
id: firebaseUser.uid,
|
||||
).execute();
|
||||
final user = response.data?.user;
|
||||
final dc.GetUserByIdUser? user = response.data?.user;
|
||||
if (user == null) {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('Authenticated user profile not found in database.');
|
||||
@@ -97,7 +98,7 @@ class AuthRepositoryImpl implements AuthRepositoryInterface {
|
||||
throw Exception('User is not authorized for this app.');
|
||||
}
|
||||
|
||||
final email = user.email ?? '';
|
||||
final String email = user.email ?? '';
|
||||
if (email.isEmpty) {
|
||||
await _firebaseAuth.signOut();
|
||||
throw Exception('User email is missing in profile data.');
|
||||
|
||||
@@ -13,5 +13,5 @@ class SignInWithPhoneArguments extends UseCaseArgument {
|
||||
const SignInWithPhoneArguments({required this.phoneNumber});
|
||||
|
||||
@override
|
||||
List<Object> get props => [phoneNumber];
|
||||
List<Object> get props => <Object>[phoneNumber];
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@ class VerifyOtpArguments extends UseCaseArgument {
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object> get props => [verificationId, smsCode];
|
||||
List<Object> get props => <Object>[verificationId, smsCode];
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:staff_authentication/src/domain/ui_entities/auth_mode.dart';
|
||||
abstract class AuthEvent extends Equatable {
|
||||
const AuthEvent();
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
List<Object> get props => <Object>[];
|
||||
}
|
||||
|
||||
/// Event for requesting a sign-in with a phone number.
|
||||
@@ -19,7 +19,7 @@ class AuthSignInRequested extends AuthEvent {
|
||||
const AuthSignInRequested({this.phoneNumber, required this.mode});
|
||||
|
||||
@override
|
||||
List<Object> get props => [mode];
|
||||
List<Object> get props => <Object>[mode];
|
||||
}
|
||||
|
||||
/// Event for submitting an OTP (One-Time Password) for verification.
|
||||
@@ -36,7 +36,7 @@ class AuthOtpSubmitted extends AuthEvent {
|
||||
const AuthOtpSubmitted({required this.verificationId, required this.smsCode});
|
||||
|
||||
@override
|
||||
List<Object> get props => [verificationId, smsCode];
|
||||
List<Object> get props => <Object>[verificationId, smsCode];
|
||||
}
|
||||
|
||||
/// Event for clearing any authentication error in the state.
|
||||
@@ -50,7 +50,7 @@ class AuthOtpUpdated extends AuthEvent {
|
||||
const AuthOtpUpdated(this.otp);
|
||||
|
||||
@override
|
||||
List<Object> get props => [otp];
|
||||
List<Object> get props => <Object>[otp];
|
||||
}
|
||||
|
||||
/// Event for updating the current draft phone number in the state.
|
||||
@@ -61,5 +61,5 @@ class AuthPhoneUpdated extends AuthEvent {
|
||||
const AuthPhoneUpdated(this.phoneNumber);
|
||||
|
||||
@override
|
||||
List<Object> get props => [phoneNumber];
|
||||
List<Object> get props => <Object>[phoneNumber];
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class AuthState extends Equatable {
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
List<Object?> get props => <Object?>[
|
||||
status,
|
||||
verificationId,
|
||||
mode,
|
||||
|
||||
@@ -5,7 +5,7 @@ abstract class ProfileSetupEvent extends Equatable {
|
||||
const ProfileSetupEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
List<Object?> get props => <Object?>[];
|
||||
}
|
||||
|
||||
/// Event triggered when the full name changes.
|
||||
@@ -17,7 +17,7 @@ class ProfileSetupFullNameChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupFullNameChanged(this.fullName);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [fullName];
|
||||
List<Object?> get props => <Object?>[fullName];
|
||||
}
|
||||
|
||||
/// Event triggered when the bio changes.
|
||||
@@ -29,7 +29,7 @@ class ProfileSetupBioChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupBioChanged(this.bio);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [bio];
|
||||
List<Object?> get props => <Object?>[bio];
|
||||
}
|
||||
|
||||
/// Event triggered when the preferred locations change.
|
||||
@@ -41,7 +41,7 @@ class ProfileSetupLocationsChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupLocationsChanged(this.locations);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [locations];
|
||||
List<Object?> get props => <Object?>[locations];
|
||||
}
|
||||
|
||||
/// Event triggered when the max distance changes.
|
||||
@@ -53,7 +53,7 @@ class ProfileSetupDistanceChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupDistanceChanged(this.distance);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [distance];
|
||||
List<Object?> get props => <Object?>[distance];
|
||||
}
|
||||
|
||||
/// Event triggered when the skills change.
|
||||
@@ -65,7 +65,7 @@ class ProfileSetupSkillsChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupSkillsChanged(this.skills);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [skills];
|
||||
List<Object?> get props => <Object?>[skills];
|
||||
}
|
||||
|
||||
/// Event triggered when the industries change.
|
||||
@@ -77,7 +77,7 @@ class ProfileSetupIndustriesChanged extends ProfileSetupEvent {
|
||||
const ProfileSetupIndustriesChanged(this.industries);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [industries];
|
||||
List<Object?> get props => <Object?>[industries];
|
||||
}
|
||||
|
||||
/// Event triggered when the profile submission is requested.
|
||||
|
||||
@@ -33,10 +33,10 @@ class ProfileSetupState extends Equatable {
|
||||
const ProfileSetupState({
|
||||
this.fullName = '',
|
||||
this.bio = '',
|
||||
this.preferredLocations = const [],
|
||||
this.preferredLocations = const <String>[],
|
||||
this.maxDistanceMiles = 25,
|
||||
this.skills = const [],
|
||||
this.industries = const [],
|
||||
this.skills = const <String>[],
|
||||
this.industries = const <String>[],
|
||||
this.status = ProfileSetupStatus.initial,
|
||||
this.errorMessage,
|
||||
});
|
||||
@@ -65,7 +65,7 @@ class ProfileSetupState extends Equatable {
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
List<Object?> get props => <Object?>[
|
||||
fullName,
|
||||
bio,
|
||||
preferredLocations,
|
||||
|
||||
@@ -6,7 +6,7 @@ import '../../domain/ui_entities/auth_mode.dart';
|
||||
extension AuthNavigator on IModularNavigator {
|
||||
/// Navigates to the phone verification page.
|
||||
void pushPhoneVerification(AuthMode mode) {
|
||||
pushNamed('./phone-verification', arguments: {'mode': mode.name});
|
||||
pushNamed('./phone-verification', arguments: <String, String>{'mode': mode.name});
|
||||
}
|
||||
|
||||
/// Navigates to the profile setup page, replacing the current route.
|
||||
|
||||
@@ -30,7 +30,7 @@ class GetStartedPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Background
|
||||
const Expanded(child: GetStartedBackground()),
|
||||
|
||||
@@ -40,7 +40,7 @@ class GetStartedPage extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Main text and actions
|
||||
const GetStartedHeader(),
|
||||
|
||||
|
||||
@@ -61,11 +61,11 @@ class PhoneVerificationPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<AuthBloc>(
|
||||
create: (context) => Modular.get<AuthBloc>(),
|
||||
create: (BuildContext context) => Modular.get<AuthBloc>(),
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
builder: (BuildContext context) {
|
||||
return BlocListener<AuthBloc, AuthState>(
|
||||
listener: (context, state) {
|
||||
listener: (BuildContext context, AuthState state) {
|
||||
if (state.status == AuthStatus.authenticated) {
|
||||
if (state.mode == AuthMode.signup) {
|
||||
Modular.to.pushReplacementProfileSetup();
|
||||
@@ -75,7 +75,7 @@ class PhoneVerificationPage extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
child: BlocBuilder<AuthBloc, AuthState>(
|
||||
builder: (context, state) {
|
||||
builder: (BuildContext context, AuthState state) {
|
||||
// Check if we are in the OTP step
|
||||
final bool isOtpStep =
|
||||
state.status == AuthStatus.codeSent ||
|
||||
@@ -93,7 +93,7 @@ class PhoneVerificationPage extends StatelessWidget {
|
||||
child: isOtpStep
|
||||
? OtpVerification(
|
||||
state: state,
|
||||
onOtpSubmitted: (otp) => _onOtpSubmitted(
|
||||
onOtpSubmitted: (String otp) => _onOtpSubmitted(
|
||||
context: context,
|
||||
otp: otp,
|
||||
verificationId: state.verificationId ?? '',
|
||||
|
||||
@@ -24,18 +24,18 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
int _currentStep = 0;
|
||||
|
||||
/// List of steps in the profile setup process.
|
||||
List<Map<String, dynamic>> get _steps => [
|
||||
{
|
||||
List<Map<String, dynamic>> get _steps => <Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
'id': 'basic',
|
||||
'title': t.staff_authentication.profile_setup_page.steps.basic,
|
||||
'icon': UiIcons.user,
|
||||
},
|
||||
{
|
||||
<String, dynamic>{
|
||||
'id': 'location',
|
||||
'title': t.staff_authentication.profile_setup_page.steps.location,
|
||||
'icon': UiIcons.mapPin,
|
||||
},
|
||||
{
|
||||
<String, dynamic>{
|
||||
'id': 'experience',
|
||||
'title': t.staff_authentication.profile_setup_page.steps.experience,
|
||||
'icon': UiIcons.briefcase,
|
||||
@@ -83,15 +83,15 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
@override
|
||||
/// Builds the profile setup page UI.
|
||||
Widget build(BuildContext context) {
|
||||
final steps = _steps;
|
||||
final List<Map<String, dynamic>> steps = _steps;
|
||||
|
||||
// Calculate progress
|
||||
final double progress = (_currentStep + 1) / steps.length;
|
||||
|
||||
return BlocProvider<ProfileSetupBloc>(
|
||||
create: (context) => Modular.get<ProfileSetupBloc>(),
|
||||
create: (BuildContext context) => Modular.get<ProfileSetupBloc>(),
|
||||
child: BlocConsumer<ProfileSetupBloc, ProfileSetupState>(
|
||||
listener: (context, state) {
|
||||
listener: (BuildContext context, ProfileSetupState state) {
|
||||
if (state.status == ProfileSetupStatus.success) {
|
||||
Modular.to.pushWorkerHome();
|
||||
} else if (state.status == ProfileSetupStatus.failure) {
|
||||
@@ -105,13 +105,13 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final isCreatingProfile = state.status == ProfileSetupStatus.loading;
|
||||
builder: (BuildContext context, ProfileSetupState state) {
|
||||
final bool isCreatingProfile = state.status == ProfileSetupStatus.loading;
|
||||
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Progress Bar
|
||||
LinearProgressIndicator(value: progress),
|
||||
|
||||
@@ -125,7 +125,7 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
// Step Indicators
|
||||
UiStepIndicator(
|
||||
stepIcons: steps
|
||||
.map((step) => step['icon'] as IconData)
|
||||
.map((Map<String, dynamic> step) => step['icon'] as IconData)
|
||||
.toList(),
|
||||
currentStep: _currentStep,
|
||||
),
|
||||
@@ -200,10 +200,10 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
return ProfileSetupBasicInfo(
|
||||
fullName: state.fullName,
|
||||
bio: state.bio,
|
||||
onFullNameChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onFullNameChanged: (String val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupFullNameChanged(val)),
|
||||
onBioChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onBioChanged: (String val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupBioChanged(val)),
|
||||
);
|
||||
@@ -211,10 +211,10 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
return ProfileSetupLocation(
|
||||
preferredLocations: state.preferredLocations,
|
||||
maxDistanceMiles: state.maxDistanceMiles,
|
||||
onLocationsChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onLocationsChanged: (List<String> val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupLocationsChanged(val)),
|
||||
onDistanceChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onDistanceChanged: (double val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupDistanceChanged(val)),
|
||||
);
|
||||
@@ -222,10 +222,10 @@ class _ProfileSetupPageState extends State<ProfileSetupPage> {
|
||||
return ProfileSetupExperience(
|
||||
skills: state.skills,
|
||||
industries: state.industries,
|
||||
onSkillsChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onSkillsChanged: (List<String> val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupSkillsChanged(val)),
|
||||
onIndustriesChanged: (val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
onIndustriesChanged: (List<String> val) => BlocProvider.of<ProfileSetupBloc>(
|
||||
context,
|
||||
).add(ProfileSetupIndustriesChanged(val)),
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ class AuthTroubleLink extends StatelessWidget {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: UiConstants.space1,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_authentication.common.trouble_question,
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
|
||||
@@ -20,7 +20,7 @@ class SectionTitleSubtitle extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: UiConstants.space1,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Title
|
||||
Text(title, style: UiTypography.headline1m),
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class GetStartedActions extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Sign Up Button
|
||||
UiButton.primary(
|
||||
text: t.staff_authentication.get_started_page.sign_up_button,
|
||||
|
||||
@@ -11,14 +11,14 @@ class GetStartedBackground extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 24.0),
|
||||
child: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Logo
|
||||
Image.asset(UiImageAssets.logoBlue, height: 40),
|
||||
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
// Hero Image
|
||||
Container(
|
||||
width: 288,
|
||||
|
||||
@@ -11,12 +11,12 @@ class GetStartedHeader extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: UiTypography.displayM,
|
||||
children: [
|
||||
children: <InlineSpan>[
|
||||
TextSpan(
|
||||
text: t.staff_authentication.get_started_page.title_part1,
|
||||
),
|
||||
|
||||
@@ -32,7 +32,7 @@ class OtpVerification extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@@ -41,7 +41,7 @@ class OtpVerification extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
OtpVerificationHeader(phoneNumber: state.phoneNumber),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
OtpInputField(
|
||||
|
||||
@@ -36,17 +36,17 @@ class _OtpInputFieldState extends State<OtpInputField> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final controller in _controllers) {
|
||||
for (final TextEditingController controller in _controllers) {
|
||||
controller.dispose();
|
||||
}
|
||||
for (final node in _focusNodes) {
|
||||
for (final FocusNode node in _focusNodes) {
|
||||
node.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// Helper getter to compute the current OTP code from all controllers.
|
||||
String get _otpCode => _controllers.map((c) => c.text).join();
|
||||
String get _otpCode => _controllers.map((TextEditingController c) => c.text).join();
|
||||
|
||||
/// Handles changes to the OTP input fields.
|
||||
void _onChanged({
|
||||
@@ -69,10 +69,10 @@ class _OtpInputFieldState extends State<OtpInputField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: List.generate(6, (index) {
|
||||
children: List.generate(6, (int index) {
|
||||
return SizedBox(
|
||||
width: 56,
|
||||
height: 56,
|
||||
@@ -80,7 +80,7 @@ class _OtpInputFieldState extends State<OtpInputField> {
|
||||
controller: _controllers[index],
|
||||
focusNode: _focusNodes[index],
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
|
||||
textAlign: TextAlign.center,
|
||||
maxLength: 1,
|
||||
style: UiTypography.headline3m,
|
||||
@@ -108,7 +108,7 @@ class _OtpInputFieldState extends State<OtpInputField> {
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (value) =>
|
||||
onChanged: (String value) =>
|
||||
_onChanged(context: context, index: index, value: value),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ class _OtpResendSectionState extends State<OtpResendSection> {
|
||||
return Center(
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
children: <InlineSpan>[
|
||||
TextSpan(
|
||||
text: widget.hasError
|
||||
? ''
|
||||
|
||||
@@ -33,7 +33,7 @@ class OtpVerificationActions extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
isLoading
|
||||
? ElevatedButton(
|
||||
onPressed: null,
|
||||
|
||||
@@ -14,7 +14,7 @@ class OtpVerificationHeader extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_authentication.phone_verification_page.enter_code_title,
|
||||
style: UiTypography.headline1m,
|
||||
@@ -27,7 +27,7 @@ class OtpVerificationHeader extends StatelessWidget {
|
||||
.phone_verification_page
|
||||
.code_sent_message,
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
children: [
|
||||
children: <InlineSpan>[
|
||||
TextSpan(text: '+1 $phoneNumber', style: UiTypography.body2b),
|
||||
TextSpan(
|
||||
text: t
|
||||
|
||||
@@ -22,7 +22,7 @@ class PhoneInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@@ -31,13 +31,13 @@ class PhoneInput extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
const PhoneInputHeader(),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
PhoneInputFormField(
|
||||
initialValue: state.phoneNumber,
|
||||
error: state.errorMessage ?? '',
|
||||
onChanged: (value) {
|
||||
onChanged: (String value) {
|
||||
BlocProvider.of<AuthBloc>(
|
||||
context,
|
||||
).add(AuthPhoneUpdated(value));
|
||||
|
||||
@@ -27,7 +27,7 @@ class PhoneInputActions extends StatelessWidget {
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
isLoading
|
||||
? UiButton.secondary(
|
||||
onPressed: null,
|
||||
|
||||
@@ -47,21 +47,21 @@ class _PhoneInputFormFieldState extends State<PhoneInputFormField> {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_authentication.phone_input.label,
|
||||
style: UiTypography.footnote1m.textSecondary,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 100,
|
||||
height: 48,
|
||||
alignment: Alignment.center,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text('🇺🇸', style: UiTypography.headline2m),
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text('+1', style: UiTypography.body1m),
|
||||
@@ -73,7 +73,7 @@ class _PhoneInputFormFieldState extends State<PhoneInputFormField> {
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
keyboardType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
LengthLimitingTextInputFormatter(10),
|
||||
],
|
||||
|
||||
@@ -11,7 +11,7 @@ class PhoneInputHeader extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_authentication.phone_input.title,
|
||||
style: UiTypography.headline1m,
|
||||
|
||||
@@ -31,7 +31,7 @@ class ProfileSetupBasicInfo extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
SectionTitleSubtitle(
|
||||
title: t.staff_authentication.profile_setup_page.basic_info.title,
|
||||
subtitle:
|
||||
@@ -42,7 +42,7 @@ class ProfileSetupBasicInfo extends StatelessWidget {
|
||||
// Photo Upload
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 120,
|
||||
height: 120,
|
||||
|
||||
@@ -17,7 +17,7 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
/// Callback for when industries change.
|
||||
final ValueChanged<List<String>> onIndustriesChanged;
|
||||
|
||||
static const List<String> _allSkillKeys = [
|
||||
static const List<String> _allSkillKeys = <String>[
|
||||
'food_service',
|
||||
'bartending',
|
||||
'warehouse',
|
||||
@@ -30,7 +30,7 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
'cooking',
|
||||
];
|
||||
|
||||
static const List<String> _allIndustryKeys = [
|
||||
static const List<String> _allIndustryKeys = <String>[
|
||||
'hospitality',
|
||||
'food_service',
|
||||
'warehouse',
|
||||
@@ -50,7 +50,7 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
|
||||
/// Toggles a skill.
|
||||
void _toggleSkill({required String skill}) {
|
||||
final updatedList = List<String>.from(skills);
|
||||
final List<String> updatedList = List<String>.from(skills);
|
||||
if (updatedList.contains(skill)) {
|
||||
updatedList.remove(skill);
|
||||
} else {
|
||||
@@ -61,7 +61,7 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
|
||||
/// Toggles an industry.
|
||||
void _toggleIndustry({required String industry}) {
|
||||
final updatedList = List<String>.from(industries);
|
||||
final List<String> updatedList = List<String>.from(industries);
|
||||
if (updatedList.contains(industry)) {
|
||||
updatedList.remove(industry);
|
||||
} else {
|
||||
@@ -75,7 +75,7 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
SectionTitleSubtitle(
|
||||
title: t.staff_authentication.profile_setup_page.experience.title,
|
||||
subtitle:
|
||||
@@ -92,10 +92,10 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
children: _allSkillKeys.map((key) {
|
||||
final isSelected = skills.contains(key);
|
||||
children: _allSkillKeys.map((String key) {
|
||||
final bool isSelected = skills.contains(key);
|
||||
// Dynamic translation access
|
||||
final label = _getSkillLabel(key);
|
||||
final String label = _getSkillLabel(key);
|
||||
|
||||
return UiChip(
|
||||
label: label,
|
||||
@@ -118,9 +118,9 @@ class ProfileSetupExperience extends StatelessWidget {
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
children: _allIndustryKeys.map((key) {
|
||||
final isSelected = industries.contains(key);
|
||||
final label = _getIndustryLabel(key);
|
||||
children: _allIndustryKeys.map((String key) {
|
||||
final bool isSelected = industries.contains(key);
|
||||
final String label = _getIndustryLabel(key);
|
||||
|
||||
return UiChip(
|
||||
label: label,
|
||||
|
||||
@@ -31,7 +31,7 @@ class ProfileSetupHeader extends StatelessWidget {
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
if (currentStep > 0 && onBackTap != null)
|
||||
GestureDetector(
|
||||
onTap: onBackTap,
|
||||
|
||||
@@ -41,9 +41,9 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
|
||||
/// Adds the current text from the controller as a location.
|
||||
void _addLocation() {
|
||||
final loc = _locationController.text.trim();
|
||||
final String loc = _locationController.text.trim();
|
||||
if (loc.isNotEmpty && !widget.preferredLocations.contains(loc)) {
|
||||
final updatedList = List<String>.from(widget.preferredLocations)
|
||||
final List<String> updatedList = List<String>.from(widget.preferredLocations)
|
||||
..add(loc);
|
||||
widget.onLocationsChanged(updatedList);
|
||||
_locationController.clear();
|
||||
@@ -55,7 +55,7 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
SectionTitleSubtitle(
|
||||
title: t.staff_authentication.profile_setup_page.location.title,
|
||||
subtitle: t.staff_authentication.profile_setup_page.location.subtitle,
|
||||
@@ -66,7 +66,7 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
spacing: UiConstants.space2,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: UiTextField(
|
||||
label: t
|
||||
@@ -102,7 +102,7 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
children: widget.preferredLocations.map((loc) {
|
||||
children: widget.preferredLocations.map((String loc) {
|
||||
return UiChip(
|
||||
label: loc,
|
||||
leadingIcon: UiIcons.mapPin,
|
||||
@@ -132,7 +132,7 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t
|
||||
.staff_authentication
|
||||
@@ -158,7 +158,7 @@ class _ProfileSetupLocationState extends State<ProfileSetupLocation> {
|
||||
|
||||
/// Removes the specified [location] from the list.
|
||||
void _removeLocation({required String location}) {
|
||||
final updatedList = List<String>.from(widget.preferredLocations)
|
||||
final List<String> updatedList = List<String>.from(widget.preferredLocations)
|
||||
..remove(location);
|
||||
widget.onLocationsChanged(updatedList);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
library staff_authentication;
|
||||
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||
@@ -23,7 +24,7 @@ export 'package:core_localization/core_localization.dart';
|
||||
/// A [Module] for the staff authentication feature.
|
||||
class StaffAuthenticationModule extends Module {
|
||||
@override
|
||||
List<Module> get imports => [DataConnectModule()];
|
||||
List<Module> get imports => <Module>[DataConnectModule()];
|
||||
|
||||
@override
|
||||
void binds(Injector i) {
|
||||
@@ -50,15 +51,15 @@ class StaffAuthenticationModule extends Module {
|
||||
}
|
||||
|
||||
@override
|
||||
void routes(r) {
|
||||
void routes(RouteManager r) {
|
||||
r.child('/', child: (_) => const GetStartedPage());
|
||||
r.child(
|
||||
'/phone-verification',
|
||||
child: (context) {
|
||||
child: (BuildContext context) {
|
||||
final Map<String, dynamic>? data = r.args.data;
|
||||
final String? modeName = data?['mode'];
|
||||
final AuthMode mode = AuthMode.values.firstWhere(
|
||||
(e) => e.name == modeName,
|
||||
(AuthMode e) => e.name == modeName,
|
||||
orElse: () => AuthMode.login,
|
||||
);
|
||||
return PhoneVerificationPage(mode: mode);
|
||||
|
||||
Reference in New Issue
Block a user