diff --git a/lib/core/blocs/session/session_cubit.dart b/lib/core/blocs/session/session_cubit.dart index 1dafd01..b21d693 100644 --- a/lib/core/blocs/session/session_cubit.dart +++ b/lib/core/blocs/session/session_cubit.dart @@ -40,9 +40,26 @@ class SessionCubit extends Cubit { try { // 1. CHI È QUESTO UTENTE? (Vediamo se ha un profilo staff, che sia Invitato o Admin) - final staff = await _repository.getStaffMemberByUserId(user.id); - // 1. Controllo Azienda + StaffMemberModel? staff = await _repository.getStaffMemberByUserId( + user.id, + ); CompanyModel? company; + if (staff != null) { + // --- LA MAGIA DEL SENSORE --- + if (staff.hasJoined == false) { + // È la primissima volta che entra! Aggiorniamo il DB. + await _repository.updateStaffMember(staff.id!, {'has_joined': true}); + // Aggiorniamo anche il nostro modello in memoria per questa sessione + staff = staff.copyWith(hasJoined: true); + } + + company = await _repository.getCompanyById(staff.companyId); + } else { + // È l'Admin in onboarding + company = await _repository.getCompanyByOwnerId(user.id); + } + // 1. Controllo Azienda + if (staff != null) { // L'utente esiste già nel sistema! Carichiamo l'azienda per cui lavora company = await _repository.getCompanyById(staff.companyId); diff --git a/lib/core/data/constants.dart b/lib/core/data/constants.dart new file mode 100644 index 0000000..316b798 --- /dev/null +++ b/lib/core/data/constants.dart @@ -0,0 +1,2 @@ +const String resetPasswordUrl = + 'https://flux-web-invite.marco-6ba.workers.dev/'; diff --git a/lib/core/data/core_repository.dart b/lib/core/data/core_repository.dart index 4b6d148..192e412 100644 --- a/lib/core/data/core_repository.dart +++ b/lib/core/data/core_repository.dart @@ -131,4 +131,11 @@ class CoreRepository { 'store_id': storeId, }); } + + Future updateStaffMember( + String staffId, + Map data, + ) async { + await _supabase.from('staff_member').update(data).eq('id', staffId); + } } diff --git a/lib/features/auth/bloc/auth_cubit.dart b/lib/features/auth/bloc/auth_cubit.dart index 6f062fe..53411e0 100644 --- a/lib/features/auth/bloc/auth_cubit.dart +++ b/lib/features/auth/bloc/auth_cubit.dart @@ -1,6 +1,7 @@ import 'package:equatable/equatable.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; +import 'package:flux/core/data/constants.dart'; import 'package:get_it/get_it.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; part 'auth_state.dart'; @@ -64,6 +65,28 @@ class AuthCubit extends Cubit { } } + Future requestPasswordReset(String email) async { + if (email.isEmpty) { + emit( + state.copyWith( + status: AuthStatus.failure, + errorMessage: 'Devi inserire l\'indirizzo email', + ), + ); + return; + } + await _supabase.auth.resetPasswordForEmail( + email, + redirectTo: resetPasswordUrl, + ); + emit( + state.copyWith( + status: AuthStatus.pwResetSent, + infoMessage: "Email per reset password inviata a $email!", + ), + ); + } + Future requestLogout() async { await _supabase.auth.signOut(); emit(state.copyWith(status: AuthStatus.initial)); diff --git a/lib/features/auth/bloc/auth_state.dart b/lib/features/auth/bloc/auth_state.dart index e491094..f3c237e 100644 --- a/lib/features/auth/bloc/auth_state.dart +++ b/lib/features/auth/bloc/auth_state.dart @@ -1,6 +1,6 @@ part of 'auth_cubit.dart'; -enum AuthStatus { initial, loading, failure } +enum AuthStatus { initial, pwResetSent, loading, failure } class AuthState extends Equatable { final AuthStatus status; diff --git a/lib/features/auth/ui/auth_screen.dart b/lib/features/auth/ui/auth_screen.dart index 00543d9..f6327d8 100644 --- a/lib/features/auth/ui/auth_screen.dart +++ b/lib/features/auth/ui/auth_screen.dart @@ -162,6 +162,21 @@ class _AuthScreenState extends State { ), ), ), + if (state.isLoginMode) ...[ + const SizedBox(height: 24), + TextButton( + onPressed: () => context + .read() + .requestPasswordReset(_emailController.text.trim()), + child: Text( + 'Pw dimenticata/Invito scaduto?', + style: TextStyle( + color: context.accent, + fontWeight: FontWeight.bold, + ), + ), + ), + ], ], ), ), diff --git a/lib/features/master_data/staff/models/staff_member_model.dart b/lib/features/master_data/staff/models/staff_member_model.dart index 1368716..ac3b3d3 100644 --- a/lib/features/master_data/staff/models/staff_member_model.dart +++ b/lib/features/master_data/staff/models/staff_member_model.dart @@ -25,6 +25,7 @@ class StaffMemberModel extends Equatable { final String? jobTitle; final SystemRole systemRole; final bool isActive; + final bool hasJoined; const StaffMemberModel({ this.id, @@ -36,6 +37,7 @@ class StaffMemberModel extends Equatable { this.jobTitle, this.systemRole = SystemRole.user, this.isActive = true, + this.hasJoined = false, }); StaffMemberModel copyWith({ @@ -49,6 +51,7 @@ class StaffMemberModel extends Equatable { String? jobTitle, SystemRole? systemRole, bool? isActive, + bool? hasJoined, }) { return StaffMemberModel( id: id ?? this.id, @@ -60,6 +63,7 @@ class StaffMemberModel extends Equatable { jobTitle: jobTitle ?? this.jobTitle, systemRole: systemRole ?? this.systemRole, isActive: isActive ?? this.isActive, + hasJoined: hasJoined ?? this.hasJoined, ); } @@ -71,8 +75,6 @@ class StaffMemberModel extends Equatable { email: '', phoneNumber: '', jobTitle: '', - systemRole: SystemRole.user, - isActive: true, ); } @@ -87,6 +89,7 @@ class StaffMemberModel extends Equatable { jobTitle: map['job_title'] as String?, systemRole: SystemRole.fromString(map['system_role']), isActive: map['is_active'] ?? true, + hasJoined: map['has_joined'] ?? false, ); } @@ -101,6 +104,7 @@ class StaffMemberModel extends Equatable { if (jobTitle != null) 'job_title': jobTitle, 'system_role': systemRole.name, // Trasforma SystemRole.admin in 'admin' 'is_active': isActive, + 'has_joined': hasJoined, }; } @@ -115,5 +119,6 @@ class StaffMemberModel extends Equatable { jobTitle, systemRole, isActive, + hasJoined, ]; } diff --git a/lib/features/services/ui/service_form_screen/attachment_section.dart b/lib/features/services/ui/service_form_screen/attachment_section.dart index cb81224..6883f65 100644 --- a/lib/features/services/ui/service_form_screen/attachment_section.dart +++ b/lib/features/services/ui/service_form_screen/attachment_section.dart @@ -174,7 +174,6 @@ class AttachmentsSection extends StatelessWidget { ); }, ), - // --- PANNELLO AZIONI CONTESTUALI (LA MAGIA) --- // Appare SOLO se c'è almeno un file selezionato if (state.selectedFiles.isNotEmpty)