refactor(#93): uniformiser la ligne utilisateur et afficher Modifier au survol
Met le rendu des lignes sur une seule ligne (icone, nom, infos) et n’affiche l’action Modifier qu’au hover pour alléger visuellement les listes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
5da2ab9005
commit
aec1990ec9
@ -89,13 +89,6 @@ class _AdminManagementWidgetState extends State<AdminManagementWidget> {
|
|||||||
// TODO: Modifier admin
|
// TODO: Modifier admin
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete),
|
|
||||||
tooltip: 'Supprimer',
|
|
||||||
onPressed: () {
|
|
||||||
// TODO: Supprimer admin
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AdminUserCard extends StatelessWidget {
|
class AdminUserCard extends StatefulWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final List<String> subtitleLines;
|
final List<String> subtitleLines;
|
||||||
final String? avatarUrl;
|
final String? avatarUrl;
|
||||||
@ -16,75 +16,117 @@ class AdminUserCard extends StatelessWidget {
|
|||||||
this.actions = const [],
|
this.actions = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AdminUserCard> createState() => _AdminUserCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AdminUserCardState extends State<AdminUserCard> {
|
||||||
|
bool _isHovered = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
final infoLine =
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
widget.subtitleLines.where((e) => e.trim().isNotEmpty).join(' ');
|
||||||
elevation: 0,
|
final actionsWidth =
|
||||||
shape: RoundedRectangleBorder(
|
widget.actions.isNotEmpty ? widget.actions.length * 30.0 : 0.0;
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
side: BorderSide(color: Colors.grey.shade300),
|
return MouseRegion(
|
||||||
),
|
onEnter: (_) => setState(() => _isHovered = true),
|
||||||
child: Padding(
|
onExit: (_) => setState(() => _isHovered = false),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
child: Material(
|
||||||
child: Row(
|
color: Colors.transparent,
|
||||||
children: [
|
borderRadius: BorderRadius.circular(10),
|
||||||
CircleAvatar(
|
child: InkWell(
|
||||||
radius: 14,
|
onTap: () {},
|
||||||
backgroundColor: const Color(0xFFEDE5FA),
|
borderRadius: BorderRadius.circular(10),
|
||||||
backgroundImage:
|
hoverColor: const Color(0x149CC5C0),
|
||||||
avatarUrl != null ? NetworkImage(avatarUrl!) : null,
|
child: Card(
|
||||||
child: avatarUrl == null
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
? Icon(
|
elevation: 0,
|
||||||
fallbackIcon,
|
shape: RoundedRectangleBorder(
|
||||||
size: 16,
|
borderRadius: BorderRadius.circular(10),
|
||||||
color: const Color(0xFF6B3FA0),
|
side: BorderSide(color: Colors.grey.shade300),
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
child: Padding(
|
||||||
Expanded(
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9),
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
CircleAvatar(
|
||||||
title.isNotEmpty ? title : 'Sans nom',
|
radius: 14,
|
||||||
style: const TextStyle(
|
backgroundColor: const Color(0xFFEDE5FA),
|
||||||
fontWeight: FontWeight.w600,
|
backgroundImage: widget.avatarUrl != null
|
||||||
fontSize: 14,
|
? NetworkImage(widget.avatarUrl!)
|
||||||
|
: null,
|
||||||
|
child: widget.avatarUrl == null
|
||||||
|
? Icon(
|
||||||
|
widget.fallbackIcon,
|
||||||
|
size: 16,
|
||||||
|
color: const Color(0xFF6B3FA0),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.loose,
|
||||||
|
child: Text(
|
||||||
|
widget.title.isNotEmpty ? widget.title : 'Sans nom',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
infoLine,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.black54,
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
if (widget.actions.isNotEmpty)
|
||||||
...subtitleLines.map(
|
SizedBox(
|
||||||
(line) => Text(
|
width: actionsWidth,
|
||||||
line,
|
child: AnimatedOpacity(
|
||||||
style: const TextStyle(
|
duration: const Duration(milliseconds: 120),
|
||||||
color: Colors.black54,
|
opacity: _isHovered ? 1 : 0,
|
||||||
fontSize: 12,
|
child: IgnorePointer(
|
||||||
|
ignoring: !_isHovered,
|
||||||
|
child: IconTheme(
|
||||||
|
data: const IconThemeData(size: 17),
|
||||||
|
child: IconButtonTheme(
|
||||||
|
data: IconButtonThemeData(
|
||||||
|
style: IconButton.styleFrom(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
minimumSize: const Size(28, 28),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: widget.actions,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (actions.isNotEmpty)
|
),
|
||||||
IconTheme(
|
|
||||||
data: const IconThemeData(size: 18),
|
|
||||||
child: IconButtonTheme(
|
|
||||||
data: IconButtonThemeData(
|
|
||||||
style: IconButton.styleFrom(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
minimumSize: const Size(28, 28),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: actions,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user