fix(UI-02): guards rôle sur pages organisations — FAB, édition, suppression SUPER_ADMIN only
- OrgTypesPage: FAB création, tap/édition/suppression type visibles uniquement SUPER_ADMIN - OrganizationDetailPage: bouton édition visible orgAdmin+superAdmin, suppression SUPER_ADMIN only, section Actions cachée si non autorisé
This commit is contained in:
@@ -5,6 +5,8 @@ import '../../../../shared/widgets/core_card.dart';
|
||||
import '../../../../core/di/injection.dart';
|
||||
import '../../bloc/org_types_bloc.dart';
|
||||
import '../../domain/entities/type_reference_entity.dart';
|
||||
import '../../../../features/authentication/presentation/bloc/auth_bloc.dart';
|
||||
import '../../../../features/authentication/data/models/user_role.dart';
|
||||
|
||||
class OrgTypesPage extends StatelessWidget {
|
||||
const OrgTypesPage({super.key});
|
||||
@@ -77,11 +79,17 @@ class _OrgTypesViewState extends State<_OrgTypesView> {
|
||||
);
|
||||
},
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.small(
|
||||
onPressed: () => _showTypeForm(context, null),
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
child: const Icon(Icons.add, color: Colors.white),
|
||||
),
|
||||
floatingActionButton: Builder(builder: (ctx) {
|
||||
final authState = ctx.read<AuthBloc>().state;
|
||||
final isSuperAdmin = authState is AuthAuthenticated &&
|
||||
authState.effectiveRole == UserRole.superAdmin;
|
||||
if (!isSuperAdmin) return const SizedBox.shrink();
|
||||
return FloatingActionButton.small(
|
||||
onPressed: () => _showTypeForm(context, null),
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
child: const Icon(Icons.add, color: Colors.white),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,12 +104,15 @@ class _OrgTypesViewState extends State<_OrgTypesView> {
|
||||
Widget _buildTypeCard(BuildContext context, TypeReferenceEntity type, OrgTypesState state) {
|
||||
final isOperating = state is OrgTypeOperating;
|
||||
final color = _parseColor(type.couleur) ?? AppColors.primaryGreen;
|
||||
final authState = context.read<AuthBloc>().state;
|
||||
final isSuperAdmin = authState is AuthAuthenticated &&
|
||||
authState.effectiveRole == UserRole.superAdmin;
|
||||
|
||||
return Opacity(
|
||||
opacity: isOperating ? 0.6 : 1.0,
|
||||
child: CoreCard(
|
||||
margin: EdgeInsets.zero,
|
||||
onTap: (!type.estSysteme && !isOperating) ? () => _showTypeForm(context, type) : null,
|
||||
onTap: (isSuperAdmin && !type.estSysteme && !isOperating) ? () => _showTypeForm(context, type) : null,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(left: BorderSide(color: color, width: 3)),
|
||||
@@ -163,7 +174,7 @@ class _OrgTypesViewState extends State<_OrgTypesView> {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!type.estSysteme && !isOperating) ...[
|
||||
if (isSuperAdmin && !type.estSysteme && !isOperating) ...[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit_outlined, size: 16),
|
||||
color: AppColors.textSecondaryLight,
|
||||
@@ -187,6 +198,10 @@ class _OrgTypesViewState extends State<_OrgTypesView> {
|
||||
}
|
||||
|
||||
Widget _buildEmptyState(BuildContext context) {
|
||||
final authState = context.read<AuthBloc>().state;
|
||||
final isSuperAdmin = authState is AuthAuthenticated &&
|
||||
authState.effectiveRole == UserRole.superAdmin;
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
@@ -201,22 +216,26 @@ class _OrgTypesViewState extends State<_OrgTypesView> {
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'Créez votre premier type d\'organisation',
|
||||
isSuperAdmin
|
||||
? 'Créez votre premier type d\'organisation'
|
||||
: 'Aucun type d\'organisation disponible',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey[500]),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _showTypeForm(context, null),
|
||||
icon: const Icon(Icons.add, size: 16),
|
||||
label: const Text('Créer un type'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
if (isSuperAdmin) ...[
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _showTypeForm(context, null),
|
||||
icon: const Icon(Icons.add, size: 16),
|
||||
label: const Text('Créer un type'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryGreen,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -51,7 +51,14 @@ class _OrganizationDetailPageState extends State<OrganizationDetailPage> {
|
||||
title: const Text('Détail Organisation'),
|
||||
elevation: 0,
|
||||
actions: [
|
||||
IconButton(onPressed: _showEditPage, icon: const Icon(Icons.edit), tooltip: 'Modifier'),
|
||||
Builder(builder: (ctx) {
|
||||
final authState = ctx.read<AuthBloc>().state;
|
||||
final canEdit = authState is AuthAuthenticated &&
|
||||
(authState.effectiveRole == UserRole.superAdmin ||
|
||||
authState.effectiveRole == UserRole.orgAdmin);
|
||||
if (!canEdit) return const SizedBox.shrink();
|
||||
return IconButton(onPressed: _showEditPage, icon: const Icon(Icons.edit), tooltip: 'Modifier');
|
||||
}),
|
||||
Builder(builder: (ctx) {
|
||||
final authState = ctx.read<AuthBloc>().state;
|
||||
final isSuperAdmin = authState is AuthAuthenticated &&
|
||||
@@ -314,6 +321,16 @@ class _OrganizationDetailPageState extends State<OrganizationDetailPage> {
|
||||
// ── Actions ─────────────────────────────────────────────────────────────────
|
||||
|
||||
Widget _buildActionsCard(OrganizationModel org) {
|
||||
final authState = context.read<AuthBloc>().state;
|
||||
final isSuperAdmin = authState is AuthAuthenticated &&
|
||||
authState.effectiveRole == UserRole.superAdmin;
|
||||
final canEdit = authState is AuthAuthenticated &&
|
||||
(authState.effectiveRole == UserRole.superAdmin ||
|
||||
authState.effectiveRole == UserRole.orgAdmin);
|
||||
|
||||
// Aucune action autorisée → ne pas afficher la section
|
||||
if (!canEdit) return const SizedBox.shrink();
|
||||
|
||||
return _buildCard('Actions', Icons.bolt, [
|
||||
Row(children: [
|
||||
Expanded(child: ElevatedButton.icon(
|
||||
@@ -322,13 +339,15 @@ class _OrganizationDetailPageState extends State<OrganizationDetailPage> {
|
||||
label: const Text('Modifier'),
|
||||
style: ElevatedButton.styleFrom(backgroundColor: AppColors.primaryGreen, foregroundColor: Colors.white),
|
||||
)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: OutlinedButton.icon(
|
||||
onPressed: () => _showDeleteConfirmation(org),
|
||||
icon: const Icon(Icons.delete),
|
||||
label: const Text('Supprimer'),
|
||||
style: OutlinedButton.styleFrom(foregroundColor: Colors.red, side: const BorderSide(color: Colors.red)),
|
||||
)),
|
||||
if (isSuperAdmin) ...[
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: OutlinedButton.icon(
|
||||
onPressed: () => _showDeleteConfirmation(org),
|
||||
icon: const Icon(Icons.delete),
|
||||
label: const Text('Supprimer'),
|
||||
style: OutlinedButton.styleFrom(foregroundColor: Colors.red, side: const BorderSide(color: Colors.red)),
|
||||
)),
|
||||
],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user