|
|
|
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_cupertino.dart';
|
|
|
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_fluent.dart';
|
|
|
|
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions_material.dart';
|
|
|
|
import 'package:info_tren/models.dart';
|
|
|
|
import 'package:info_tren/providers.dart';
|
|
|
|
import 'package:info_tren/utils/default_ui_design.dart';
|
|
|
|
|
|
|
|
class SelectTrainSuggestions extends ConsumerWidget {
|
|
|
|
final List<TrainsResult> choices;
|
|
|
|
final String? currentInput;
|
|
|
|
final void Function(String trainNumber) onTrainSelected;
|
|
|
|
|
|
|
|
const SelectTrainSuggestions({required this.choices, this.currentInput, required this.onTrainSelected, super.key, });
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
|
|
final uiDesign = ref.watch(uiDesignProvider);
|
|
|
|
|
|
|
|
switch(uiDesign) {
|
|
|
|
case UiDesign.MATERIAL:
|
|
|
|
return SelectTrainSuggestionsMaterial(
|
|
|
|
choices: choices,
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
currentInput: currentInput,
|
|
|
|
);
|
|
|
|
case UiDesign.CUPERTINO:
|
|
|
|
return SelectTrainSuggestionsCupertino(
|
|
|
|
choices: choices,
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
currentInput: currentInput,
|
|
|
|
);
|
|
|
|
case UiDesign.FLUENT:
|
|
|
|
return SelectTrainSuggestionsFluent(
|
|
|
|
choices: choices,
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
currentInput: currentInput,
|
|
|
|
);
|
|
|
|
default:
|
|
|
|
throw UnmatchedUiDesignException(uiDesign);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class SelectTrainSuggestionsShared extends StatelessWidget {
|
|
|
|
String getUseCurrentInputWidgetText(String currentInput) => 'Caută trenul cu numărul $currentInput';
|
|
|
|
Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected);
|
|
|
|
|
|
|
|
final List<TrainsResult> choices;
|
|
|
|
final String? currentInput;
|
|
|
|
final void Function(String trainNumber) onTrainSelected;
|
|
|
|
|
|
|
|
const SelectTrainSuggestionsShared({
|
|
|
|
required this.choices,
|
|
|
|
this.currentInput,
|
|
|
|
required this.onTrainSelected,
|
|
|
|
super.key,
|
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
var slivers = choices.map((c) => c.company).toSet().map((operator) => OperatorAutocompleteSliver(
|
|
|
|
operatorName: operator,
|
|
|
|
trains: choices.where((c) => c.company == operator).toList(),
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
)).toList();
|
|
|
|
|
|
|
|
return CustomScrollView(
|
|
|
|
slivers: <Widget>[
|
|
|
|
...slivers,
|
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: currentInput != null && int.tryParse(currentInput!) != null ? getUseCurrentInputWidget(currentInput!, onTrainSelected) : Container(),
|
|
|
|
),
|
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: Container(
|
|
|
|
height: MediaQuery.of(context).viewPadding.bottom,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class OperatorAutocompleteSliver extends ConsumerWidget {
|
|
|
|
final String operatorName;
|
|
|
|
final List<TrainsResult> trains;
|
|
|
|
final void Function(String) onTrainSelected;
|
|
|
|
|
|
|
|
const OperatorAutocompleteSliver({
|
|
|
|
super.key,
|
|
|
|
required this.operatorName,
|
|
|
|
required this.trains,
|
|
|
|
required this.onTrainSelected,
|
|
|
|
});
|
|
|
|
|
|
|
|
Widget mapTrainToItem(TrainsResult train, UiDesign uiDesign) {
|
|
|
|
switch (uiDesign) {
|
|
|
|
case UiDesign.MATERIAL:
|
|
|
|
return OperatorAutocompleteTileMaterial(
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
operatorName: operatorName,
|
|
|
|
train: train,
|
|
|
|
);
|
|
|
|
case UiDesign.CUPERTINO:
|
|
|
|
return OperatorAutocompleteTileCupertino(
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
operatorName: operatorName,
|
|
|
|
train: train,
|
|
|
|
);
|
|
|
|
case UiDesign.FLUENT:
|
|
|
|
return OperatorAutocompleteTileFluent(
|
|
|
|
onTrainSelected: onTrainSelected,
|
|
|
|
operatorName: operatorName,
|
|
|
|
train: train,
|
|
|
|
);
|
|
|
|
default:
|
|
|
|
throw UnmatchedUiDesignException(uiDesign);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
|
|
final uiDesign = ref.watch(uiDesignProvider);
|
|
|
|
if (trains.isEmpty) {
|
|
|
|
return SliverToBoxAdapter(child: Container(),);
|
|
|
|
}
|
|
|
|
|
|
|
|
return SliverPrototypeExtentList(
|
|
|
|
prototypeItem: Column(
|
|
|
|
children: <Widget>[
|
|
|
|
mapTrainToItem(const TrainsResult(company: 'Company', number: '123', rank: 'R'), uiDesign),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
delegate: SliverChildBuilderDelegate(
|
|
|
|
(context, index) {
|
|
|
|
return Column(
|
|
|
|
children: <Widget>[
|
|
|
|
mapTrainToItem(trains[index], uiDesign),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
},
|
|
|
|
childCount: trains.length,
|
|
|
|
addSemanticIndexes: true,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class OperatorAutocompleteTile extends StatelessWidget {
|
|
|
|
final String operatorName;
|
|
|
|
final TrainsResult train;
|
|
|
|
final void Function(String) onTrainSelected;
|
|
|
|
|
|
|
|
const OperatorAutocompleteTile({ Key? key, required this.onTrainSelected, required this.operatorName, required this.train }) : super(key: key);
|
|
|
|
}
|