Team Color, image compression for attendance verification, improved wherebouts
This commit is contained in:
@@ -277,6 +277,9 @@ class _TeamsScreenState extends ConsumerState<TeamsScreen> {
|
||||
final itStaff = profiles.where((p) => p.role == 'it_staff').toList();
|
||||
final nameController = TextEditingController(text: team?.name ?? '');
|
||||
String? leaderId = team?.leaderId;
|
||||
Color? teamColor = team?.color != null
|
||||
? Color(int.parse(team!.color!, radix: 16) | 0xFF000000)
|
||||
: null;
|
||||
List<String> selectedOffices = List<String>.from(team?.officeIds ?? []);
|
||||
List<String> selectedMembers = [];
|
||||
final isEdit = team != null;
|
||||
@@ -305,6 +308,11 @@ class _TeamsScreenState extends ConsumerState<TeamsScreen> {
|
||||
decoration: const InputDecoration(labelText: 'Team Name'),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_TeamColorPicker(
|
||||
selectedColor: teamColor,
|
||||
onColorChanged: (c) => setState(() => teamColor = c),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
DropdownButtonFormField<String>(
|
||||
initialValue: leaderId,
|
||||
items: [
|
||||
@@ -408,6 +416,11 @@ class _TeamsScreenState extends ConsumerState<TeamsScreen> {
|
||||
'name': name,
|
||||
'leader_id': leaderId,
|
||||
'office_ids': selectedOffices,
|
||||
'color': teamColor != null
|
||||
? (teamColor!.toARGB32() & 0xFFFFFF)
|
||||
.toRadixString(16)
|
||||
.padLeft(6, '0')
|
||||
: null,
|
||||
})
|
||||
.eq('id', team.id);
|
||||
final upErr = extractSupabaseError(upRes);
|
||||
@@ -454,6 +467,11 @@ class _TeamsScreenState extends ConsumerState<TeamsScreen> {
|
||||
'name': name,
|
||||
'leader_id': leaderId,
|
||||
'office_ids': selectedOffices,
|
||||
'color': teamColor != null
|
||||
? (teamColor!.toARGB32() & 0xFFFFFF)
|
||||
.toRadixString(16)
|
||||
.padLeft(6, '0')
|
||||
: null,
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
@@ -657,3 +675,90 @@ class _TeamsScreenState extends ConsumerState<TeamsScreen> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Inline color picker for team color selection.
|
||||
class _TeamColorPicker extends StatelessWidget {
|
||||
const _TeamColorPicker({
|
||||
required this.selectedColor,
|
||||
required this.onColorChanged,
|
||||
});
|
||||
|
||||
final Color? selectedColor;
|
||||
final ValueChanged<Color?> onColorChanged;
|
||||
|
||||
static const List<Color> _presetColors = [
|
||||
Color(0xFFE53935), // Red
|
||||
Color(0xFFD81B60), // Pink
|
||||
Color(0xFF8E24AA), // Purple
|
||||
Color(0xFF5E35B1), // Deep Purple
|
||||
Color(0xFF3949AB), // Indigo
|
||||
Color(0xFF1E88E5), // Blue
|
||||
Color(0xFF039BE5), // Light Blue
|
||||
Color(0xFF00ACC1), // Cyan
|
||||
Color(0xFF00897B), // Teal
|
||||
Color(0xFF43A047), // Green
|
||||
Color(0xFF7CB342), // Light Green
|
||||
Color(0xFFFDD835), // Yellow
|
||||
Color(0xFFFFB300), // Amber
|
||||
Color(0xFFFB8C00), // Orange
|
||||
Color(0xFFF4511E), // Deep Orange
|
||||
Color(0xFF6D4C41), // Brown
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text('Team Color', style: Theme.of(context).textTheme.bodyMedium),
|
||||
if (selectedColor != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () => onColorChanged(null),
|
||||
child: Text(
|
||||
'Clear',
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: _presetColors.map((color) {
|
||||
final isSelected =
|
||||
selectedColor != null &&
|
||||
(selectedColor!.toARGB32() & 0xFFFFFF) ==
|
||||
(color.toARGB32() & 0xFFFFFF);
|
||||
return GestureDetector(
|
||||
onTap: () => onColorChanged(color),
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
border: isSelected
|
||||
? Border.all(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
width: 3,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: isSelected
|
||||
? Icon(Icons.check, color: Colors.white, size: 18)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user