UI Phase 2: cosmetic leftovers — compact Profile photo card, fit Users table
- Profile Photo card: replace the tall centered avatar+buttons stack with a compact horizontal row (avatar left, caption + Upload/Camera buttons right), roughly halving the card height and reclaiming the dead vertical space. - TasQColumn gains an optional `minWidth`; the adaptive table now sums per-column minimums instead of a flat 200 px each. User Management sets narrow widths on its short columns (Role/Offices/Status/Last active) so all six columns fit at desktop width without the horizontal scroll that was clipping the Status column. Other tables keep the 200 px default (unchanged). Verified: flutter analyze lib clean; flutter build web green; visual QA (Profile, User Management) in dark. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -280,54 +280,69 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
children: [
|
||||
const AppSectionHeader('Profile Photo', padding: EdgeInsets.zero),
|
||||
const SizedBox(height: 16),
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'profile-avatar',
|
||||
child: CircleAvatar(
|
||||
radius: 56,
|
||||
backgroundColor: colors.surfaceContainerHighest,
|
||||
backgroundImage: avatarUrl != null
|
||||
? NetworkImage(avatarUrl)
|
||||
: null,
|
||||
child: avatarUrl == null
|
||||
? Icon(
|
||||
Icons.person,
|
||||
size: 48,
|
||||
color: colors.onSurfaceVariant,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (_uploadingAvatar)
|
||||
const Positioned.fill(
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: _uploadingAvatar
|
||||
? null
|
||||
: () => _pickAvatar(ImageSource.gallery),
|
||||
icon: const Icon(Icons.photo_library),
|
||||
label: const Text('Upload'),
|
||||
Stack(
|
||||
children: [
|
||||
Hero(
|
||||
tag: 'profile-avatar',
|
||||
child: CircleAvatar(
|
||||
radius: 44,
|
||||
backgroundColor: colors.surfaceContainerHighest,
|
||||
backgroundImage: avatarUrl != null
|
||||
? NetworkImage(avatarUrl)
|
||||
: null,
|
||||
child: avatarUrl == null
|
||||
? Icon(
|
||||
Icons.person,
|
||||
size: 40,
|
||||
color: colors.onSurfaceVariant,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (_uploadingAvatar)
|
||||
const Positioned.fill(
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (!kIsWeb) ...[
|
||||
const SizedBox(width: 12),
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: _uploadingAvatar
|
||||
? null
|
||||
: () => _pickAvatar(ImageSource.camera),
|
||||
icon: const Icon(Icons.camera_alt),
|
||||
label: const Text('Camera'),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'A clear headshot helps teammates recognize you.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colors.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Wrap(
|
||||
spacing: 12,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: _uploadingAvatar
|
||||
? null
|
||||
: () => _pickAvatar(ImageSource.gallery),
|
||||
icon: const Icon(Icons.photo_library),
|
||||
label: const Text('Upload'),
|
||||
),
|
||||
if (!kIsWeb)
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: _uploadingAvatar
|
||||
? null
|
||||
: () => _pickAvatar(ImageSource.camera),
|
||||
icon: const Icon(Icons.camera_alt),
|
||||
label: const Text('Camera'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user