feat-invite_staff #9
@@ -40,9 +40,26 @@ class SessionCubit extends Cubit<SessionState> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. CHI È QUESTO UTENTE? (Vediamo se ha un profilo staff, che sia Invitato o Admin)
|
// 1. CHI È QUESTO UTENTE? (Vediamo se ha un profilo staff, che sia Invitato o Admin)
|
||||||
final staff = await _repository.getStaffMemberByUserId(user.id);
|
StaffMemberModel? staff = await _repository.getStaffMemberByUserId(
|
||||||
// 1. Controllo Azienda
|
user.id,
|
||||||
|
);
|
||||||
CompanyModel? company;
|
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) {
|
if (staff != null) {
|
||||||
// L'utente esiste già nel sistema! Carichiamo l'azienda per cui lavora
|
// L'utente esiste già nel sistema! Carichiamo l'azienda per cui lavora
|
||||||
company = await _repository.getCompanyById(staff.companyId);
|
company = await _repository.getCompanyById(staff.companyId);
|
||||||
|
|||||||
2
lib/core/data/constants.dart
Normal file
2
lib/core/data/constants.dart
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
const String resetPasswordUrl =
|
||||||
|
'https://flux-web-invite.marco-6ba.workers.dev/';
|
||||||
@@ -131,4 +131,11 @@ class CoreRepository {
|
|||||||
'store_id': storeId,
|
'store_id': storeId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> updateStaffMember(
|
||||||
|
String staffId,
|
||||||
|
Map<String, dynamic> data,
|
||||||
|
) async {
|
||||||
|
await _supabase.from('staff_member').update(data).eq('id', staffId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flux/core/blocs/session/session_cubit.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:get_it/get_it.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
part 'auth_state.dart';
|
part 'auth_state.dart';
|
||||||
@@ -64,6 +65,28 @@ class AuthCubit extends Cubit<AuthState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> 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<void> requestLogout() async {
|
Future<void> requestLogout() async {
|
||||||
await _supabase.auth.signOut();
|
await _supabase.auth.signOut();
|
||||||
emit(state.copyWith(status: AuthStatus.initial));
|
emit(state.copyWith(status: AuthStatus.initial));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
part of 'auth_cubit.dart';
|
part of 'auth_cubit.dart';
|
||||||
|
|
||||||
enum AuthStatus { initial, loading, failure }
|
enum AuthStatus { initial, pwResetSent, loading, failure }
|
||||||
|
|
||||||
class AuthState extends Equatable {
|
class AuthState extends Equatable {
|
||||||
final AuthStatus status;
|
final AuthStatus status;
|
||||||
|
|||||||
@@ -162,6 +162,21 @@ class _AuthScreenState extends State<AuthScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (state.isLoginMode) ...[
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => context
|
||||||
|
.read<AuthCubit>()
|
||||||
|
.requestPasswordReset(_emailController.text.trim()),
|
||||||
|
child: Text(
|
||||||
|
'Pw dimenticata/Invito scaduto?',
|
||||||
|
style: TextStyle(
|
||||||
|
color: context.accent,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
final String? jobTitle;
|
final String? jobTitle;
|
||||||
final SystemRole systemRole;
|
final SystemRole systemRole;
|
||||||
final bool isActive;
|
final bool isActive;
|
||||||
|
final bool hasJoined;
|
||||||
|
|
||||||
const StaffMemberModel({
|
const StaffMemberModel({
|
||||||
this.id,
|
this.id,
|
||||||
@@ -36,6 +37,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
this.jobTitle,
|
this.jobTitle,
|
||||||
this.systemRole = SystemRole.user,
|
this.systemRole = SystemRole.user,
|
||||||
this.isActive = true,
|
this.isActive = true,
|
||||||
|
this.hasJoined = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
StaffMemberModel copyWith({
|
StaffMemberModel copyWith({
|
||||||
@@ -49,6 +51,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
String? jobTitle,
|
String? jobTitle,
|
||||||
SystemRole? systemRole,
|
SystemRole? systemRole,
|
||||||
bool? isActive,
|
bool? isActive,
|
||||||
|
bool? hasJoined,
|
||||||
}) {
|
}) {
|
||||||
return StaffMemberModel(
|
return StaffMemberModel(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
@@ -60,6 +63,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
jobTitle: jobTitle ?? this.jobTitle,
|
jobTitle: jobTitle ?? this.jobTitle,
|
||||||
systemRole: systemRole ?? this.systemRole,
|
systemRole: systemRole ?? this.systemRole,
|
||||||
isActive: isActive ?? this.isActive,
|
isActive: isActive ?? this.isActive,
|
||||||
|
hasJoined: hasJoined ?? this.hasJoined,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +75,6 @@ class StaffMemberModel extends Equatable {
|
|||||||
email: '',
|
email: '',
|
||||||
phoneNumber: '',
|
phoneNumber: '',
|
||||||
jobTitle: '',
|
jobTitle: '',
|
||||||
systemRole: SystemRole.user,
|
|
||||||
isActive: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +89,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
jobTitle: map['job_title'] as String?,
|
jobTitle: map['job_title'] as String?,
|
||||||
systemRole: SystemRole.fromString(map['system_role']),
|
systemRole: SystemRole.fromString(map['system_role']),
|
||||||
isActive: map['is_active'] ?? true,
|
isActive: map['is_active'] ?? true,
|
||||||
|
hasJoined: map['has_joined'] ?? false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +104,7 @@ class StaffMemberModel extends Equatable {
|
|||||||
if (jobTitle != null) 'job_title': jobTitle,
|
if (jobTitle != null) 'job_title': jobTitle,
|
||||||
'system_role': systemRole.name, // Trasforma SystemRole.admin in 'admin'
|
'system_role': systemRole.name, // Trasforma SystemRole.admin in 'admin'
|
||||||
'is_active': isActive,
|
'is_active': isActive,
|
||||||
|
'has_joined': hasJoined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,5 +119,6 @@ class StaffMemberModel extends Equatable {
|
|||||||
jobTitle,
|
jobTitle,
|
||||||
systemRole,
|
systemRole,
|
||||||
isActive,
|
isActive,
|
||||||
|
hasJoined,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,7 +174,6 @@ class AttachmentsSection extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
// --- PANNELLO AZIONI CONTESTUALI (LA MAGIA) ---
|
// --- PANNELLO AZIONI CONTESTUALI (LA MAGIA) ---
|
||||||
// Appare SOLO se c'è almeno un file selezionato
|
// Appare SOLO se c'è almeno un file selezionato
|
||||||
if (state.selectedFiles.isNotEmpty)
|
if (state.selectedFiles.isNotEmpty)
|
||||||
|
|||||||
Reference in New Issue
Block a user