247 lines
7.3 KiB
Dart
247 lines
7.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:laserscouter/core/api.dart';
|
|
import 'notespage.dart';
|
|
import 'teamadder.dart';
|
|
import 'package:to_csv/to_csv.dart' as csv_export;
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
|
|
class TeamPicker extends StatefulWidget {
|
|
final String eventCode;
|
|
final String eventName;
|
|
final bool isCustomOnly;
|
|
|
|
const TeamPicker({super.key, required this.eventCode, required this.eventName,this.isCustomOnly = false});
|
|
|
|
@override
|
|
State<TeamPicker> createState() => _TeamPickerState();
|
|
}
|
|
|
|
class _TeamPickerState extends State<TeamPicker> {
|
|
List<String> teamNames = [];
|
|
List<String> teamCodes = [];
|
|
bool isLoading = true;
|
|
String? errorMessage;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_fetchTeams();
|
|
}
|
|
|
|
Future<void> _exportData() async {
|
|
List<String> header = [];
|
|
header.add('Team Number');
|
|
header.add('Bot Position');
|
|
header.add('Gen. Observations');
|
|
header.add('Auton Rundown');
|
|
header.add('Intake Position');
|
|
header.add('Can Drive Over Bump');
|
|
header.add('Can Go Under Trench');
|
|
header.add('Can Give Fuel to HP');
|
|
header.add('Climb Level');
|
|
header.add('Fuel Capacity');
|
|
header.add('Fuel per Cycle');
|
|
header.add("Cycle Time");
|
|
|
|
List<List<String>> data = [];
|
|
for (int i = 0; i < teamCodes.length; i++) {
|
|
String generateKey(String field) {
|
|
return '${teamCodes[i]}_${widget.eventCode}_$field';
|
|
}
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
String? botPosition = prefs.getString(generateKey('botPosition'));
|
|
String? generalObservations = prefs.getString(generateKey('generalObservations'));
|
|
String? autonRundown = prefs.getString(generateKey('autonRundown'));
|
|
String? intakePosition = prefs.getString(generateKey('intakePosition'));
|
|
String? canDriveOverBump = prefs.getBool(generateKey('canDriveOverBump')).toString();
|
|
String? canDriveUnderTrench = prefs.getBool(generateKey('canDriveUnderTrench')).toString();
|
|
String? canGiveToHumanPlayer = prefs.getBool(generateKey('canGiveToHumanPlayer')).toString();
|
|
String? climbLevel = prefs.getDouble(generateKey('climbLevel')).toString();
|
|
String? fuelCapacity = prefs.getDouble(generateKey('fuelCapacity')).toString();
|
|
String? fuelPerCycle = prefs.getDouble(generateKey('fuelPerCycle')).toString();
|
|
String? cycleTime = prefs.getDouble(generateKey('cycleTime')).toString();
|
|
|
|
if (canDriveOverBump == 'null') {
|
|
canDriveOverBump = '';
|
|
}
|
|
if (canDriveUnderTrench == 'null') {
|
|
canDriveUnderTrench = '';
|
|
}
|
|
if (canGiveToHumanPlayer == 'null') {
|
|
canGiveToHumanPlayer = '';
|
|
}
|
|
if (climbLevel == 'null') {
|
|
climbLevel = '';
|
|
}
|
|
if (fuelCapacity == 'null') {
|
|
fuelCapacity = '';
|
|
}
|
|
if (fuelPerCycle == 'null') {
|
|
fuelPerCycle = '';
|
|
}
|
|
if (cycleTime == 'null') {
|
|
cycleTime = '';
|
|
}
|
|
|
|
|
|
List<String> teamData = [];
|
|
teamData.add(teamCodes[i]);
|
|
teamData.add(botPosition ?? '');
|
|
teamData.add(generalObservations ?? '');
|
|
teamData.add(autonRundown ?? '');
|
|
teamData.add(intakePosition ?? '');
|
|
teamData.add(canDriveOverBump);
|
|
teamData.add(canDriveUnderTrench);
|
|
teamData.add(canGiveToHumanPlayer);
|
|
teamData.add(climbLevel);
|
|
teamData.add(fuelCapacity);
|
|
teamData.add(fuelPerCycle);
|
|
teamData.add(cycleTime);
|
|
data.add(teamData);
|
|
}
|
|
csv_export.myCSV(header, data, setHeadersInFirstRow: true, fileName: 'laserscouter_${widget.eventCode}.csv');
|
|
}
|
|
|
|
Future<void> _fetchTeams() async {
|
|
try {
|
|
List<String> apiTeamNames = [];
|
|
List<String> apiTeamCodes = [];
|
|
|
|
if (!widget.isCustomOnly) {
|
|
final EventSearchResult apiResult = await eventSearch(widget.eventCode);
|
|
apiTeamNames = apiResult.teamNames;
|
|
apiTeamCodes = apiResult.teamCodes;
|
|
}
|
|
|
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
final List<String> customTeamNames = prefs.getStringList('custom_team_names_${widget.eventName}') ?? [];
|
|
final List<String> customTeamCodes = prefs.getStringList('custom_team_numbers_${widget.eventCode}') ?? [];
|
|
|
|
List<String> combinedNames = [];
|
|
List<String> combinedCodes = [];
|
|
for (int i = 0; i < apiTeamCodes.length; i++) {
|
|
if (!combinedCodes.contains(apiTeamCodes[i])) {
|
|
combinedCodes.add(apiTeamCodes[i]);
|
|
if (i < apiTeamNames.length) {
|
|
combinedNames.add(apiTeamNames[i]);
|
|
} else {
|
|
combinedNames.add('');
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < customTeamCodes.length; i++) {
|
|
if (!combinedCodes.contains(customTeamCodes[i])) {
|
|
combinedCodes.add(customTeamCodes[i]);
|
|
if (i < customTeamNames.length) {
|
|
combinedNames.add(customTeamNames[i]);
|
|
} else {
|
|
combinedNames.add('');
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mounted) {
|
|
setState(() {
|
|
teamNames = combinedNames.toList();
|
|
teamCodes = combinedCodes.toList();
|
|
isLoading = false;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
if (mounted) {
|
|
setState(() {
|
|
errorMessage = widget.isCustomOnly
|
|
? "Could not load custom teams."
|
|
: "Failed to load teams. Please try again.";
|
|
isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> _refreshTeams() async {
|
|
setState(() {
|
|
isLoading = true;
|
|
});
|
|
await _fetchTeams();
|
|
}
|
|
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Teams'),
|
|
actions: [
|
|
IconButton(
|
|
onPressed: () async {
|
|
await Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => TeamAdder(eventCode: widget.eventCode,),
|
|
),
|
|
);
|
|
_refreshTeams();
|
|
},
|
|
icon: Icon(Icons.add),
|
|
)
|
|
]
|
|
),
|
|
body: _buildBody(),
|
|
floatingActionButton: FloatingActionButton(
|
|
onPressed: _exportData,
|
|
child: const Icon(Icons.share),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildBody() {
|
|
if (isLoading) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
if (errorMessage != null) {
|
|
return Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Text(
|
|
errorMessage!,
|
|
textAlign: TextAlign.center,
|
|
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
|
color: Colors.red,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (teamCodes.isEmpty) {
|
|
return const Center(
|
|
child: Text('No teams found for this event.'),
|
|
);
|
|
}
|
|
|
|
return ListView.builder(
|
|
itemCount: teamCodes.length,
|
|
itemBuilder: (context, index) {
|
|
return ListTile(
|
|
title: Text('${teamCodes[index]} - ${teamNames[index]}'),
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => NotesPage(
|
|
teamName: teamNames[index],
|
|
eventCode: widget.eventCode,
|
|
teamCode: teamCodes[index],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|