Add Fluent UI for Win, Linux
Also add split screen train view for landscape
This commit is contained in:
		
							parent
							
								
									da983871e2
								
							
						
					
					
						commit
						0e484bdc16
					
				
					 30 changed files with 3062 additions and 612 deletions
				
			
		| 
						 | 
					@ -1,3 +1,9 @@
 | 
				
			||||||
 | 
					v2.7.9
 | 
				
			||||||
 | 
					Add Fluent UI for Windows and Linux.
 | 
				
			||||||
 | 
					Add split view in landscape when viewing a train.
 | 
				
			||||||
 | 
					Add error handling and auto refresh when viewing a station's arrivals/departures.
 | 
				
			||||||
 | 
					General code fixes and migration (freezed, riverpod).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
v2.7.8
 | 
					v2.7.8
 | 
				
			||||||
Added cancelled trains in departures/arrivals board.
 | 
					Added cancelled trains in departures/arrivals board.
 | 
				
			||||||
Selecting train in departures/arrivels board chooses appropriate departure date.
 | 
					Selecting train in departures/arrivels board chooses appropriate departure date.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										59
									
								
								lib/components/badge/badge.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								lib/components/badge/badge.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,59 @@
 | 
				
			||||||
 | 
					import 'package:flutter/cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/badge/badge_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/badge/badge_fluent.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/badge/badge_material.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Badge extends ConsumerWidget {
 | 
				
			||||||
 | 
					  final String text;
 | 
				
			||||||
 | 
					  final String caption;
 | 
				
			||||||
 | 
					  final bool isNotScheduled;
 | 
				
			||||||
 | 
					  final bool isOnTime;
 | 
				
			||||||
 | 
					  final bool isDelayed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Badge({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.text,
 | 
				
			||||||
 | 
					    required this.caption,
 | 
				
			||||||
 | 
					    this.isNotScheduled = false,
 | 
				
			||||||
 | 
					    this.isOnTime = false,
 | 
				
			||||||
 | 
					    this.isDelayed = false,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final uiDesign = ref.watch(uiDesignProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (uiDesign) {
 | 
				
			||||||
 | 
					      case UiDesign.MATERIAL:
 | 
				
			||||||
 | 
					        return MaterialBadge(
 | 
				
			||||||
 | 
					          text: text,
 | 
				
			||||||
 | 
					          caption: caption,
 | 
				
			||||||
 | 
					          isNotScheduled: isNotScheduled,
 | 
				
			||||||
 | 
					          isOnTime: isOnTime,
 | 
				
			||||||
 | 
					          isDelayed: isDelayed,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
 | 
					        return CupertinoBadge(
 | 
				
			||||||
 | 
					          text: text,
 | 
				
			||||||
 | 
					          caption: caption,
 | 
				
			||||||
 | 
					          isNotScheduled: isNotScheduled,
 | 
				
			||||||
 | 
					          isOnTime: isOnTime,
 | 
				
			||||||
 | 
					          isDelayed: isDelayed,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return FluentBadge(
 | 
				
			||||||
 | 
					          text: text,
 | 
				
			||||||
 | 
					          caption: caption,
 | 
				
			||||||
 | 
					          isNotScheduled: isNotScheduled,
 | 
				
			||||||
 | 
					          isOnTime: isOnTime,
 | 
				
			||||||
 | 
					          isDelayed: isDelayed,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,84 +1,5 @@
 | 
				
			||||||
import 'package:flutter/cupertino.dart';
 | 
					import 'package:flutter/cupertino.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
 | 
					import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MaterialBadge extends StatelessWidget {
 | 
					 | 
				
			||||||
  final String text;
 | 
					 | 
				
			||||||
  final String caption;
 | 
					 | 
				
			||||||
  final bool isNotScheduled;
 | 
					 | 
				
			||||||
  final bool isOnTime;
 | 
					 | 
				
			||||||
  final bool isDelayed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const MaterialBadge({
 | 
					 | 
				
			||||||
    required this.text,
 | 
					 | 
				
			||||||
    required this.caption,
 | 
					 | 
				
			||||||
    this.isNotScheduled = false,
 | 
					 | 
				
			||||||
    this.isOnTime = false,
 | 
					 | 
				
			||||||
    this.isDelayed = false,
 | 
					 | 
				
			||||||
    super.key,
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    Color foregroundColor = Colors.white70;
 | 
					 | 
				
			||||||
    Color? backgroundColor;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (isNotScheduled) {
 | 
					 | 
				
			||||||
      foregroundColor = Colors.orange.shade300;
 | 
					 | 
				
			||||||
      backgroundColor = Colors.orange.shade900.withOpacity(0.3);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (isOnTime) {
 | 
					 | 
				
			||||||
      foregroundColor = Colors.green.shade300;
 | 
					 | 
				
			||||||
      backgroundColor = Colors.green.shade900.withOpacity(0.3);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else if (isDelayed) {
 | 
					 | 
				
			||||||
      foregroundColor = Colors.red.shade300;
 | 
					 | 
				
			||||||
      backgroundColor = Colors.red.shade900.withOpacity(0.3);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Padding(
 | 
					 | 
				
			||||||
      padding: const EdgeInsets.all(8),
 | 
					 | 
				
			||||||
      child: Container(
 | 
					 | 
				
			||||||
        decoration: BoxDecoration(
 | 
					 | 
				
			||||||
          borderRadius: BorderRadius.circular(10),
 | 
					 | 
				
			||||||
          border: Border.all(
 | 
					 | 
				
			||||||
            width: 2,
 | 
					 | 
				
			||||||
            color: foregroundColor,
 | 
					 | 
				
			||||||
          ),
 | 
					 | 
				
			||||||
          color: backgroundColor,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        width: isSmallScreen(context) ? 42 : 48,
 | 
					 | 
				
			||||||
        height: isSmallScreen(context) ? 42 : 48,
 | 
					 | 
				
			||||||
        child: Column(
 | 
					 | 
				
			||||||
          mainAxisSize: MainAxisSize.min,
 | 
					 | 
				
			||||||
          children: <Widget>[
 | 
					 | 
				
			||||||
            Expanded(
 | 
					 | 
				
			||||||
              child: Center(
 | 
					 | 
				
			||||||
                child: Text(
 | 
					 | 
				
			||||||
                  text,
 | 
					 | 
				
			||||||
                  style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
					 | 
				
			||||||
                    fontSize: isSmallScreen(context) ? 16 : 20,
 | 
					 | 
				
			||||||
                    fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
 | 
					 | 
				
			||||||
                    color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            Text(
 | 
					 | 
				
			||||||
              caption,
 | 
					 | 
				
			||||||
              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
					 | 
				
			||||||
                fontSize: 10,
 | 
					 | 
				
			||||||
                color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CupertinoBadge extends StatelessWidget {
 | 
					class CupertinoBadge extends StatelessWidget {
 | 
				
			||||||
  final String text;
 | 
					  final String text;
 | 
				
			||||||
							
								
								
									
										80
									
								
								lib/components/badge/badge_fluent.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								lib/components/badge/badge_fluent.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FluentBadge extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String text;
 | 
				
			||||||
 | 
					  final String caption;
 | 
				
			||||||
 | 
					  final bool isNotScheduled;
 | 
				
			||||||
 | 
					  final bool isOnTime;
 | 
				
			||||||
 | 
					  final bool isDelayed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const FluentBadge({
 | 
				
			||||||
 | 
					    required this.text,
 | 
				
			||||||
 | 
					    required this.caption,
 | 
				
			||||||
 | 
					    this.isNotScheduled = false,
 | 
				
			||||||
 | 
					    this.isOnTime = false,
 | 
				
			||||||
 | 
					    this.isDelayed = false,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    Color foregroundColor = FluentTheme.of(context).activeColor;
 | 
				
			||||||
 | 
					    Color? backgroundColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isNotScheduled) {
 | 
				
			||||||
 | 
					      foregroundColor = const Color.fromRGBO(225, 175, 30, 1);
 | 
				
			||||||
 | 
					      backgroundColor = const Color.fromRGBO(80, 40, 10, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (isOnTime) {
 | 
				
			||||||
 | 
					      foregroundColor = const Color.fromRGBO(130, 175, 65, 1);
 | 
				
			||||||
 | 
					      backgroundColor = const Color.fromRGBO(40, 80, 10, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (isDelayed) {
 | 
				
			||||||
 | 
					      foregroundColor = const Color.fromRGBO(225, 75, 30, 1);
 | 
				
			||||||
 | 
					      backgroundColor = const Color.fromRGBO(80, 20, 10, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					      child: Container(
 | 
				
			||||||
 | 
					        decoration: BoxDecoration(
 | 
				
			||||||
 | 
					          borderRadius: BorderRadius.circular(10),
 | 
				
			||||||
 | 
					          border: Border.all(
 | 
				
			||||||
 | 
					            width: 2,
 | 
				
			||||||
 | 
					            color: foregroundColor,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          color: backgroundColor,
 | 
				
			||||||
 | 
					          // color: CupertinoColors.activeOrange,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        width: 48,
 | 
				
			||||||
 | 
					        height: 48,
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: Center(
 | 
				
			||||||
 | 
					                child:  Text(
 | 
				
			||||||
 | 
					                  text,
 | 
				
			||||||
 | 
					                  style: FluentTheme.of(context).typography.bodyLarge?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: 20,
 | 
				
			||||||
 | 
					                    fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
 | 
				
			||||||
 | 
					                    color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              caption,
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                fontSize: 12,
 | 
				
			||||||
 | 
					                color: MediaQuery.of(context).boldText ? Colors.white : foregroundColor,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								lib/components/badge/badge_material.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								lib/components/badge/badge_material.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,79 @@
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MaterialBadge extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String text;
 | 
				
			||||||
 | 
					  final String caption;
 | 
				
			||||||
 | 
					  final bool isNotScheduled;
 | 
				
			||||||
 | 
					  final bool isOnTime;
 | 
				
			||||||
 | 
					  final bool isDelayed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MaterialBadge({
 | 
				
			||||||
 | 
					    required this.text,
 | 
				
			||||||
 | 
					    required this.caption,
 | 
				
			||||||
 | 
					    this.isNotScheduled = false,
 | 
				
			||||||
 | 
					    this.isOnTime = false,
 | 
				
			||||||
 | 
					    this.isDelayed = false,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    Color foregroundColor = Colors.white70;
 | 
				
			||||||
 | 
					    Color? backgroundColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isNotScheduled) {
 | 
				
			||||||
 | 
					      foregroundColor = Colors.orange.shade300;
 | 
				
			||||||
 | 
					      backgroundColor = Colors.orange.shade900.withOpacity(0.3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (isOnTime) {
 | 
				
			||||||
 | 
					      foregroundColor = Colors.green.shade300;
 | 
				
			||||||
 | 
					      backgroundColor = Colors.green.shade900.withOpacity(0.3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (isDelayed) {
 | 
				
			||||||
 | 
					      foregroundColor = Colors.red.shade300;
 | 
				
			||||||
 | 
					      backgroundColor = Colors.red.shade900.withOpacity(0.3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					      child: Container(
 | 
				
			||||||
 | 
					        decoration: BoxDecoration(
 | 
				
			||||||
 | 
					          borderRadius: BorderRadius.circular(10),
 | 
				
			||||||
 | 
					          border: Border.all(
 | 
				
			||||||
 | 
					            width: 2,
 | 
				
			||||||
 | 
					            color: foregroundColor,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          color: backgroundColor,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        width: isSmallScreen(context) ? 42 : 48,
 | 
				
			||||||
 | 
					        height: isSmallScreen(context) ? 42 : 48,
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: Center(
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  text,
 | 
				
			||||||
 | 
					                  style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: isSmallScreen(context) ? 16 : 20,
 | 
				
			||||||
 | 
					                    fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
 | 
				
			||||||
 | 
					                    color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              caption,
 | 
				
			||||||
 | 
					              style: Theme.of(context).textTheme.bodyMedium?.copyWith(
 | 
				
			||||||
 | 
					                fontSize: 10,
 | 
				
			||||||
 | 
					                color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
import 'package:flutter/widgets.dart';
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/components/loading/loading_cupertino.dart';
 | 
					import 'package:info_tren/components/loading/loading_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/loading/loading_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/components/loading/loading_material.dart';
 | 
					import 'package:info_tren/components/loading/loading_material.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
| 
						 | 
					@ -19,6 +20,8 @@ class Loading extends ConsumerWidget {
 | 
				
			||||||
        return LoadingMaterial(text: text ?? defaultText,);
 | 
					        return LoadingMaterial(text: text ?? defaultText,);
 | 
				
			||||||
      case UiDesign.CUPERTINO:
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
        return LoadingCupertino(text: text ?? defaultText,);
 | 
					        return LoadingCupertino(text: text ?? defaultText,);
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return LoadingFluent(text: text ?? defaultText,);
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										26
									
								
								lib/components/loading/loading_fluent.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								lib/components/loading/loading_fluent.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,26 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/loading/loading.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LoadingFluent extends LoadingCommon {
 | 
				
			||||||
 | 
					  const LoadingFluent({required super.text, super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Center(
 | 
				
			||||||
 | 
					      child: Column(
 | 
				
			||||||
 | 
					        crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          const Padding(
 | 
				
			||||||
 | 
					            padding: EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					            child: ProgressRing(),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					            child: Text(text),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
import 'package:flutter/widgets.dart';
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.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_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/components/select_train_suggestions/select_train_suggestions_material.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,12 @@ class SelectTrainSuggestions extends ConsumerWidget {
 | 
				
			||||||
          onTrainSelected: onTrainSelected,
 | 
					          onTrainSelected: onTrainSelected,
 | 
				
			||||||
          currentInput: currentInput,
 | 
					          currentInput: currentInput,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return SelectTrainSuggestionsFluent(
 | 
				
			||||||
 | 
					          choices: choices,
 | 
				
			||||||
 | 
					          onTrainSelected: onTrainSelected,
 | 
				
			||||||
 | 
					          currentInput: currentInput,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -102,6 +109,12 @@ class OperatorAutocompleteSliver extends ConsumerWidget {
 | 
				
			||||||
          operatorName: operatorName,
 | 
					          operatorName: operatorName,
 | 
				
			||||||
          train: train,
 | 
					          train: train,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return OperatorAutocompleteTileFluent(
 | 
				
			||||||
 | 
					          onTrainSelected: onTrainSelected,
 | 
				
			||||||
 | 
					          operatorName: operatorName,
 | 
				
			||||||
 | 
					          train: train,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,84 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SelectTrainSuggestionsFluent extends SelectTrainSuggestionsShared {
 | 
				
			||||||
 | 
					  const SelectTrainSuggestionsFluent({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required super.choices,
 | 
				
			||||||
 | 
					    required super.onTrainSelected,
 | 
				
			||||||
 | 
					    super.currentInput,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget getUseCurrentInputWidget(String currentInput, void Function(String) onTrainSelected) {
 | 
				
			||||||
 | 
					    return Column(
 | 
				
			||||||
 | 
					      mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.all(0),
 | 
				
			||||||
 | 
					            child: Column(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					              children: <Widget>[
 | 
				
			||||||
 | 
					                Button(
 | 
				
			||||||
 | 
					                  child: Text(getUseCurrentInputWidgetText(currentInput)),
 | 
				
			||||||
 | 
					                  onPressed: () => onTrainSelected(currentInput),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        const Divider(),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class OperatorAutocompleteTileFluent extends OperatorAutocompleteTile {
 | 
				
			||||||
 | 
					  const OperatorAutocompleteTileFluent({
 | 
				
			||||||
 | 
					    Key? key,
 | 
				
			||||||
 | 
					    required String operatorName,
 | 
				
			||||||
 | 
					    required void Function(String) onTrainSelected,
 | 
				
			||||||
 | 
					    required TrainsResult train
 | 
				
			||||||
 | 
					  }): super(
 | 
				
			||||||
 | 
					    onTrainSelected: onTrainSelected,
 | 
				
			||||||
 | 
					    operatorName: operatorName,
 | 
				
			||||||
 | 
					    train: train,
 | 
				
			||||||
 | 
					    key: key,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Column(
 | 
				
			||||||
 | 
					      mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					      children: [
 | 
				
			||||||
 | 
					        GestureDetector(
 | 
				
			||||||
 | 
					          onTap: () {
 | 
				
			||||||
 | 
					            onTrainSelected(train.number);
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          child: Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.fromLTRB(16, 4, 16, 4),
 | 
				
			||||||
 | 
					            child: SizedBox(
 | 
				
			||||||
 | 
					              width: double.infinity,
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
				
			||||||
 | 
					                children: <Widget>[
 | 
				
			||||||
 | 
					                  Text(
 | 
				
			||||||
 | 
					                    operatorName,
 | 
				
			||||||
 | 
					                    style: FluentTheme.of(context).typography.body?.copyWith(fontSize: 10, fontWeight: FontWeight.w200),
 | 
				
			||||||
 | 
					                    textAlign: TextAlign.left,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Text(
 | 
				
			||||||
 | 
					                    "${train.rank} ${train.number}",
 | 
				
			||||||
 | 
					                    textAlign: TextAlign.left,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        const Divider(),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,10 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:fluent_ui/fluent_ui.dart' as f;
 | 
				
			||||||
 | 
					import 'package:flutter/cupertino.dart' as c;
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart' as m;
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/about/about_page.dart';
 | 
					import 'package:info_tren/pages/about/about_page.dart';
 | 
				
			||||||
import 'package:info_tren/pages/main/main_page.dart';
 | 
					import 'package:info_tren/pages/main/main_page.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
				
			||||||
| 
						 | 
					@ -54,48 +59,59 @@ Map<String, WidgetBuilder> get routes => {
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class StartPoint extends StatelessWidget {
 | 
					class StartPoint extends ConsumerWidget {
 | 
				
			||||||
  final String appTitle = 'Info Tren';
 | 
					  final String appTitle = 'Info Tren';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const StartPoint({super.key});
 | 
					  const StartPoint({super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
    // if (Platform.isIOS || Platform.isMacOS) {
 | 
					    final uiDesign = ref.watch(uiDesignProvider);
 | 
				
			||||||
    //   return AnnotatedRegion(
 | 
					    if (uiDesign == UiDesign.CUPERTINO) {
 | 
				
			||||||
    //     value: const SystemUiOverlayStyle(
 | 
					      return AnnotatedRegion(
 | 
				
			||||||
    //       statusBarBrightness: Brightness.dark,
 | 
					        value: const SystemUiOverlayStyle(
 | 
				
			||||||
    //     ),
 | 
					          statusBarBrightness: c.Brightness.dark,
 | 
				
			||||||
    //     child: CupertinoApp(
 | 
					        ),
 | 
				
			||||||
    //       title: appTitle,
 | 
					        child: c.CupertinoApp(
 | 
				
			||||||
    //       theme: CupertinoThemeData(
 | 
					          title: appTitle,
 | 
				
			||||||
    //         primaryColor: Colors.blue.shade600,
 | 
					          theme: c.CupertinoThemeData(
 | 
				
			||||||
    //         brightness: Brightness.dark,
 | 
					            primaryColor: m.Colors.blue.shade600,
 | 
				
			||||||
    //         // textTheme: CupertinoTextThemeData(
 | 
					            brightness: c.Brightness.dark,
 | 
				
			||||||
    //         //   textStyle: TextStyle(
 | 
					            // textTheme: CupertinoTextThemeData(
 | 
				
			||||||
    //         //     fontFamily: 'Atkinson Hyperlegible',
 | 
					            //   textStyle: TextStyle(
 | 
				
			||||||
    //         //   ),
 | 
					            //     fontFamily: 'Atkinson Hyperlegible',
 | 
				
			||||||
    //         // ),
 | 
					            //   ),
 | 
				
			||||||
    //       ),
 | 
					            // ),
 | 
				
			||||||
    //       routes: routesByUiDesign(UiDesign.CUPERTINO),
 | 
					          ),
 | 
				
			||||||
    //     ),
 | 
					          routes: routes,
 | 
				
			||||||
    //   );
 | 
					        ),
 | 
				
			||||||
    // }
 | 
					      );
 | 
				
			||||||
    // else {
 | 
					    }
 | 
				
			||||||
      return MaterialApp(
 | 
					    else if (uiDesign == UiDesign.FLUENT) {
 | 
				
			||||||
 | 
					      return f.FluentApp(
 | 
				
			||||||
        title: appTitle,
 | 
					        title: appTitle,
 | 
				
			||||||
        theme: ThemeData(
 | 
					        theme: f.ThemeData(
 | 
				
			||||||
          primarySwatch: Colors.blue,
 | 
					          brightness: f.Brightness.dark,
 | 
				
			||||||
          colorScheme: ColorScheme.fromSwatch(
 | 
					          accentColor: f.Colors.blue,
 | 
				
			||||||
            brightness: Brightness.dark,
 | 
					        ),
 | 
				
			||||||
            primarySwatch: Colors.blue,
 | 
					        routes: routes,
 | 
				
			||||||
            accentColor: Colors.blue.shade700,
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return m.MaterialApp(
 | 
				
			||||||
 | 
					        title: appTitle,
 | 
				
			||||||
 | 
					        theme: m.ThemeData(
 | 
				
			||||||
 | 
					          primarySwatch: m.Colors.blue,
 | 
				
			||||||
 | 
					          colorScheme: m.ColorScheme.fromSwatch(
 | 
				
			||||||
 | 
					            brightness: m.Brightness.dark,
 | 
				
			||||||
 | 
					            primarySwatch: m.Colors.blue,
 | 
				
			||||||
 | 
					            accentColor: m.Colors.blue.shade700,
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          useMaterial3: true,
 | 
					          useMaterial3: true,
 | 
				
			||||||
          // fontFamily: 'Atkinson Hyperlegible',
 | 
					          // fontFamily: 'Atkinson Hyperlegible',
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        routes: routes,
 | 
					        routes: routes,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    // }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
enum UiDesign {
 | 
					enum UiDesign {
 | 
				
			||||||
  MATERIAL,
 | 
					  MATERIAL,
 | 
				
			||||||
  CUPERTINO
 | 
					  CUPERTINO,
 | 
				
			||||||
 | 
					  FLUENT,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class UnmatchedUiDesignException implements Exception {
 | 
					class UnmatchedUiDesignException implements Exception {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/about/about_page.dart';
 | 
					import 'package:info_tren/pages/about/about_page.dart';
 | 
				
			||||||
import 'package:info_tren/pages/main/main_page_cupertino.dart';
 | 
					import 'package:info_tren/pages/main/main_page_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/main/main_page_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/pages/main/main_page_material.dart';
 | 
					import 'package:info_tren/pages/main/main_page_material.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
 | 
					import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,8 @@ class MainPage extends ConsumerWidget {
 | 
				
			||||||
        return const MainPageMaterial();
 | 
					        return const MainPageMaterial();
 | 
				
			||||||
      case UiDesign.CUPERTINO:
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
        return const MainPageCupertino();
 | 
					        return const MainPageCupertino();
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return const MainPageFluent();
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										73
									
								
								lib/pages/main/main_page_fluent.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								lib/pages/main/main_page_fluent.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,73 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/main/main_page.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MainPageFluent extends MainPageShared {
 | 
				
			||||||
 | 
					  const MainPageFluent({super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					        automaticallyImplyLeading: false,
 | 
				
			||||||
 | 
					        title: Text(pageTitle),
 | 
				
			||||||
 | 
					        // centerTitle: true,
 | 
				
			||||||
 | 
					        // actions: [
 | 
				
			||||||
 | 
					        //   PopupMenuButton<int>(
 | 
				
			||||||
 | 
					        //     icon: const Icon(Icons.more_vert),
 | 
				
			||||||
 | 
					        //     tooltip: moreOptionsText,
 | 
				
			||||||
 | 
					        //     itemBuilder: (_) => popupMenu.asMap().entries.map((e) => PopupMenuItem(
 | 
				
			||||||
 | 
					        //       value: e.key,
 | 
				
			||||||
 | 
					        //       child: Text(e.value.name),
 | 
				
			||||||
 | 
					        //     )).toList(),
 | 
				
			||||||
 | 
					        //     onSelected: (index) {
 | 
				
			||||||
 | 
					        //       popupMenu[index].action?.call(context);
 | 
				
			||||||
 | 
					        //     },
 | 
				
			||||||
 | 
					        //   ),
 | 
				
			||||||
 | 
					        // ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: SafeArea(
 | 
				
			||||||
 | 
					        child: Center(
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: options.map((option) => HoverButton(
 | 
				
			||||||
 | 
					              onPressed: option.action != null ? () => option.action!(context) : null,
 | 
				
			||||||
 | 
					              builder: (context, states) {
 | 
				
			||||||
 | 
					                return Card(
 | 
				
			||||||
 | 
					                  backgroundColor: option.action != null ? (states.isHovering ? FluentTheme.of(context).accentColor.dark : FluentTheme.of(context).accentColor) : null,
 | 
				
			||||||
 | 
					                  child: Column(
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      Padding(
 | 
				
			||||||
 | 
					                        padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                        child: Text(
 | 
				
			||||||
 | 
					                          option.name,
 | 
				
			||||||
 | 
					                          style: FluentTheme.of(context)
 | 
				
			||||||
 | 
					                            .typography
 | 
				
			||||||
 | 
					                            .bodyLarge
 | 
				
			||||||
 | 
					                            ?.copyWith(
 | 
				
			||||||
 | 
					                              color:
 | 
				
			||||||
 | 
					                                  FluentTheme.of(context).activeColor,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      Padding(
 | 
				
			||||||
 | 
					                        padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                        child: Text(option.description!),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            )).map((w) => Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
 | 
				
			||||||
 | 
					              child: SizedBox(
 | 
				
			||||||
 | 
					                width: double.infinity,
 | 
				
			||||||
 | 
					                child: w,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            )).toList(),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_cupertino.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_material.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station_material.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,8 @@ class SelectStationPage extends ConsumerWidget {
 | 
				
			||||||
        return const SelectStationPageMaterial();
 | 
					        return const SelectStationPageMaterial();
 | 
				
			||||||
      case UiDesign.CUPERTINO:
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
        return const SelectStationPageCupertino();
 | 
					        return const SelectStationPageCupertino();
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return const SelectStationPageFluent();
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,59 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/station_arrdep_page/select_station/select_station.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SelectStationPageFluent extends SelectStationPageShared {
 | 
				
			||||||
 | 
					  const SelectStationPageFluent({super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<StatefulWidget> createState() => SelectStationPageStateFluent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SelectStationPageStateFluent extends SelectStationPageState {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: const NavigationAppBar(
 | 
				
			||||||
 | 
					        title: Text(SelectStationPageState.pageTitle),
 | 
				
			||||||
 | 
					        // centerTitle: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: SafeArea(
 | 
				
			||||||
 | 
					        bottom: false,
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					              child: TextBox(
 | 
				
			||||||
 | 
					                controller: textEditingController,
 | 
				
			||||||
 | 
					                autofocus: true,
 | 
				
			||||||
 | 
					                placeholder: SelectStationPageState.textFieldLabel,
 | 
				
			||||||
 | 
					                textInputAction: TextInputAction.search,
 | 
				
			||||||
 | 
					                onChanged: onTextChanged,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: ListView.builder(
 | 
				
			||||||
 | 
					                itemBuilder: (context, index) {
 | 
				
			||||||
 | 
					                  return Column(
 | 
				
			||||||
 | 
					                    mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      ListTile(
 | 
				
			||||||
 | 
					                        // dense: true,
 | 
				
			||||||
 | 
					                        title: Text(filteredStations[index]),
 | 
				
			||||||
 | 
					                        onPressed: () => onSuggestionSelected(filteredStations[index]),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      const Divider(
 | 
				
			||||||
 | 
					                        size: 1,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                itemCount: filteredStations.length,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/components/refresh_future_builder.dart';
 | 
					import 'package:info_tren/components/refresh_future_builder.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_cupertino.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_material.dart';
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station_material.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
| 
						 | 
					@ -31,6 +32,11 @@ class ViewStationPage extends HookConsumerWidget {
 | 
				
			||||||
          tab: tab.value,
 | 
					          tab: tab.value,
 | 
				
			||||||
          setTab: (newTab) => tab.value = newTab,
 | 
					          setTab: (newTab) => tab.value = newTab,
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return ViewStationPageFluent(
 | 
				
			||||||
 | 
					          tab: tab.value,
 | 
				
			||||||
 | 
					          setTab: (newTab) => tab.value = newTab,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,267 @@
 | 
				
			||||||
 | 
					import 'dart:math';
 | 
				
			||||||
 | 
					import 'dart:ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/badge/badge.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/loading/loading.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/refresh_future_builder.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ViewStationPageFluent extends ViewStationPageShared {
 | 
				
			||||||
 | 
					  const ViewStationPageFluent({super.key, required super.tab, required super.setTab});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget buildContent(BuildContext context, Future Function() refresh, Future Function(Future<StationData> Function()) _, RefreshFutureBuilderSnapshot<StationData> snapshot) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					        title: Consumer(
 | 
				
			||||||
 | 
					          builder: (context, ref, _) {
 | 
				
			||||||
 | 
					            final stationName = ref.watch(viewStationArgumentsProvider.select((value) => value.stationName));
 | 
				
			||||||
 | 
					            return Text(snapshot.hasData ? snapshot.data!.stationName : stationName);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: snapshot.state == RefreshFutureBuilderState.waiting || snapshot.state == RefreshFutureBuilderState.refreshError
 | 
				
			||||||
 | 
					          ? const Loading(text: ViewStationPageShared.loadingText,)
 | 
				
			||||||
 | 
					          : snapshot.state == RefreshFutureBuilderState.error
 | 
				
			||||||
 | 
					          ? Padding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					            child: Center(
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  Icon(
 | 
				
			||||||
 | 
					                    FluentIcons.error,
 | 
				
			||||||
 | 
					                    size: 32,
 | 
				
			||||||
 | 
					                    color: Colors.red.normal,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  const Text(
 | 
				
			||||||
 | 
					                    ViewStationPageShared.errorText,
 | 
				
			||||||
 | 
					                    style: TextStyle(
 | 
				
			||||||
 | 
					                      inherit: true,
 | 
				
			||||||
 | 
					                      fontSize: 32,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Text(
 | 
				
			||||||
 | 
					                    snapshot.error.toString(),
 | 
				
			||||||
 | 
					                    style: FluentTheme.of(context).typography.subtitle,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Padding(
 | 
				
			||||||
 | 
					                    padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                    child: Button(
 | 
				
			||||||
 | 
					                      onPressed: () {
 | 
				
			||||||
 | 
					                        refresh();
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                      child: const Text(ViewStationPageShared.retryText),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					          : null,
 | 
				
			||||||
 | 
					      pane: snapshot.hasData ? NavigationPane(
 | 
				
			||||||
 | 
					        onChanged: onTabChange,
 | 
				
			||||||
 | 
					        selected: tab.index,
 | 
				
			||||||
 | 
					        items: [
 | 
				
			||||||
 | 
					          PaneItem(
 | 
				
			||||||
 | 
					            body: CustomScrollView(
 | 
				
			||||||
 | 
					              slivers: [
 | 
				
			||||||
 | 
					                SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
 | 
				
			||||||
 | 
					                SliverList(
 | 
				
			||||||
 | 
					                  delegate: SliverChildBuilderDelegate(
 | 
				
			||||||
 | 
					                        (context, index) {
 | 
				
			||||||
 | 
					                      return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            title: const Text(ViewStationPageShared.arrivals),
 | 
				
			||||||
 | 
					            icon: const Icon(FluentIcons.arrow_down_right8),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          PaneItem(
 | 
				
			||||||
 | 
					            body: CustomScrollView(
 | 
				
			||||||
 | 
					              slivers: [
 | 
				
			||||||
 | 
					                SliverToBoxAdapter(child: SafeArea(left: false, bottom: false, right: false,child: Container(),),),
 | 
				
			||||||
 | 
					                SliverList(
 | 
				
			||||||
 | 
					                  delegate: SliverChildBuilderDelegate(
 | 
				
			||||||
 | 
					                        (context, index) {
 | 
				
			||||||
 | 
					                      return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            title: const Text(ViewStationPageShared.departures),
 | 
				
			||||||
 | 
					            icon: const Icon(FluentIcons.arrow_up_right8),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ) : null,
 | 
				
			||||||
 | 
					      // bottomNavigationBar: snapshot.hasData ? BottomNavigationBar(
 | 
				
			||||||
 | 
					      //   items: const [
 | 
				
			||||||
 | 
					      //     BottomNavigationBarItem(
 | 
				
			||||||
 | 
					      //       icon: Icon(Icons.arrow_downward),
 | 
				
			||||||
 | 
					      //       label: ViewStationPageShared.arrivals,
 | 
				
			||||||
 | 
					      //     ),
 | 
				
			||||||
 | 
					      //     BottomNavigationBarItem(
 | 
				
			||||||
 | 
					      //       icon: Icon(Icons.arrow_upward),
 | 
				
			||||||
 | 
					      //       label: ViewStationPageShared.departures,
 | 
				
			||||||
 | 
					      //     ),
 | 
				
			||||||
 | 
					      //   ],
 | 
				
			||||||
 | 
					      //   currentIndex: tab.index,
 | 
				
			||||||
 | 
					      //   onTap: onTabChange,
 | 
				
			||||||
 | 
					      // ) : null,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget buildStationItem(BuildContext context, StationArrDep item, {required bool arrival}) {
 | 
				
			||||||
 | 
					    return HoverButton(
 | 
				
			||||||
 | 
					      onPressed: () => onTrainTapped(context, item.train),
 | 
				
			||||||
 | 
					      builder: (context, states) {
 | 
				
			||||||
 | 
					        return Container(
 | 
				
			||||||
 | 
					          color: item.status.cancelled
 | 
				
			||||||
 | 
					              ? Colors.red.withAlpha(100)
 | 
				
			||||||
 | 
					              : states.isPressing
 | 
				
			||||||
 | 
					              ? FluentTheme.of(context).scaffoldBackgroundColor
 | 
				
			||||||
 | 
					              : states.isHovering
 | 
				
			||||||
 | 
					              ? FluentTheme.of(context).inactiveBackgroundColor
 | 
				
			||||||
 | 
					              : null,
 | 
				
			||||||
 | 
					          child: Row(
 | 
				
			||||||
 | 
					            crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              Padding(
 | 
				
			||||||
 | 
					                padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					                child: Column(
 | 
				
			||||||
 | 
					                  mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                  crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					                  children: [
 | 
				
			||||||
 | 
					                    Text(
 | 
				
			||||||
 | 
					                      '${item.time.toLocal().hour.toString().padLeft(2, '0')}:${item.time.toLocal().minute.toString().padLeft(2, '0')}',
 | 
				
			||||||
 | 
					                      style: TextStyle(
 | 
				
			||||||
 | 
					                        inherit: true,
 | 
				
			||||||
 | 
					                        fontFeatures: const [
 | 
				
			||||||
 | 
					                          FontFeature.tabularFigures(),
 | 
				
			||||||
 | 
					                        ],
 | 
				
			||||||
 | 
					                        decoration: item.status.cancelled || item.status.delay != 0 ? TextDecoration.lineThrough : null,
 | 
				
			||||||
 | 
					                        fontSize: item.status.delay != 0 ? 12 : null,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    if (item.status.delay != 0) Builder(
 | 
				
			||||||
 | 
					                      builder: (context) {
 | 
				
			||||||
 | 
					                        final newTime = item.time.add(Duration(minutes: item.status.delay));
 | 
				
			||||||
 | 
					                        final delay = item.status.delay > 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return Text(
 | 
				
			||||||
 | 
					                          '${newTime.toLocal().hour.toString().padLeft(2, '0')}:${newTime.toLocal().minute.toString().padLeft(2, '0')}',
 | 
				
			||||||
 | 
					                          style: TextStyle(
 | 
				
			||||||
 | 
					                            inherit: true,
 | 
				
			||||||
 | 
					                            fontFeatures: const [
 | 
				
			||||||
 | 
					                              FontFeature.tabularFigures(),
 | 
				
			||||||
 | 
					                            ],
 | 
				
			||||||
 | 
					                            color: delay ? Colors.red : Colors.green,
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Expanded(
 | 
				
			||||||
 | 
					                child: IgnorePointer(
 | 
				
			||||||
 | 
					                  child: ListTile(
 | 
				
			||||||
 | 
					                    // isThreeLine: item.status.delay != 0,
 | 
				
			||||||
 | 
					                    title: Text.rich(
 | 
				
			||||||
 | 
					                      TextSpan(
 | 
				
			||||||
 | 
					                        children: [
 | 
				
			||||||
 | 
					                          TextSpan(
 | 
				
			||||||
 | 
					                            text: item.train.rank,
 | 
				
			||||||
 | 
					                            style: TextStyle(
 | 
				
			||||||
 | 
					                              color: item.train.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                          const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					                          TextSpan(text: item.train.number,),
 | 
				
			||||||
 | 
					                        ],
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    subtitle: Text.rich(
 | 
				
			||||||
 | 
					                      TextSpan(
 | 
				
			||||||
 | 
					                        children: [
 | 
				
			||||||
 | 
					                          TextSpan(
 | 
				
			||||||
 | 
					                              text: item.status.cancelled
 | 
				
			||||||
 | 
					                                  ? (arrival ? ViewStationPageShared.cancelledArrival : ViewStationPageShared.cancelledDeparture)
 | 
				
			||||||
 | 
					                                  : item.time.add(Duration(minutes: max(0, item.status.delay))).compareTo(DateTime.now()) < 0
 | 
				
			||||||
 | 
					                                  ? (arrival ? ViewStationPageShared.arrivedFrom : ViewStationPageShared.departedTo)
 | 
				
			||||||
 | 
					                                  : (arrival ? ViewStationPageShared.arrivesFrom : ViewStationPageShared.departsTo)
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                          const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					                          TextSpan(text: item.train.terminus),
 | 
				
			||||||
 | 
					                          if (item.status.delay != 0) ...[
 | 
				
			||||||
 | 
					                            const TextSpan(text: '\n'),
 | 
				
			||||||
 | 
					                            if (item.status.delay.abs() >= 60) ...[
 | 
				
			||||||
 | 
					                              TextSpan(text: (item.status.delay.abs() ~/ 60).toString()),
 | 
				
			||||||
 | 
					                              TextSpan(text: item.status.delay.abs() >= 120 ? ' ore' : ' oră'),
 | 
				
			||||||
 | 
					                              if (item.status.delay.abs() % 60 != 0)
 | 
				
			||||||
 | 
					                                const TextSpan(text: ' și '),
 | 
				
			||||||
 | 
					                            ],
 | 
				
			||||||
 | 
					                            TextSpan(text: (item.status.delay.abs() % 60).toString()),
 | 
				
			||||||
 | 
					                            TextSpan(text: item.status.delay.abs() > 1 ? ' minute' : ' minut'),
 | 
				
			||||||
 | 
					                            const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					                            if (item.status.delay > 0)
 | 
				
			||||||
 | 
					                              TextSpan(
 | 
				
			||||||
 | 
					                                text: 'întârziere',
 | 
				
			||||||
 | 
					                                style: TextStyle(
 | 
				
			||||||
 | 
					                                  inherit: true,
 | 
				
			||||||
 | 
					                                  color: Colors.red,
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              )
 | 
				
			||||||
 | 
					                            else
 | 
				
			||||||
 | 
					                              TextSpan(
 | 
				
			||||||
 | 
					                                text: 'mai devreme',
 | 
				
			||||||
 | 
					                                style: TextStyle(
 | 
				
			||||||
 | 
					                                  inherit: true,
 | 
				
			||||||
 | 
					                                  color: Colors.green,
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ],
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              if (item.status.platform != null)
 | 
				
			||||||
 | 
					                IntrinsicHeight(
 | 
				
			||||||
 | 
					                  child: AspectRatio(
 | 
				
			||||||
 | 
					                    aspectRatio: 1,
 | 
				
			||||||
 | 
					                    child: Badge(
 | 
				
			||||||
 | 
					                      text: item.status.platform!,
 | 
				
			||||||
 | 
					                      caption: 'Linia',
 | 
				
			||||||
 | 
					                      isOnTime: item.status.real && item.status.delay <= 0,
 | 
				
			||||||
 | 
					                      isDelayed: item.status.real && item.status.delay > 0,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget buildStationArrivalItem(BuildContext context, StationArrDep item) {
 | 
				
			||||||
 | 
					    return buildStationItem(context, item, arrival: true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget buildStationDepartureItem(BuildContext context, StationArrDep item) {
 | 
				
			||||||
 | 
					    return buildStationItem(context, item, arrival: false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ import 'dart:math';
 | 
				
			||||||
import 'dart:ui';
 | 
					import 'dart:ui';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/components/badge.dart';
 | 
					import 'package:info_tren/components/badge/badge.dart';
 | 
				
			||||||
import 'package:info_tren/components/loading/loading.dart';
 | 
					import 'package:info_tren/components/loading/loading.dart';
 | 
				
			||||||
import 'package:info_tren/components/refresh_future_builder.dart';
 | 
					import 'package:info_tren/components/refresh_future_builder.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
| 
						 | 
					@ -205,7 +205,7 @@ class ViewStationPageMaterial extends ViewStationPageShared {
 | 
				
			||||||
              IntrinsicHeight(
 | 
					              IntrinsicHeight(
 | 
				
			||||||
                child: AspectRatio(
 | 
					                child: AspectRatio(
 | 
				
			||||||
                  aspectRatio: 1,
 | 
					                  aspectRatio: 1,
 | 
				
			||||||
                  child: MaterialBadge(
 | 
					                  child: Badge(
 | 
				
			||||||
                    text: item.status.platform!,
 | 
					                    text: item.status.platform!,
 | 
				
			||||||
                    caption: 'Linia',
 | 
					                    caption: 'Linia',
 | 
				
			||||||
                    isOnTime: item.status.real && item.status.delay <= 0,
 | 
					                    isOnTime: item.status.real && item.status.delay <= 0,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
 | 
					import 'package:info_tren/components/select_train_suggestions/select_train_suggestions.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train_cupertino.dart';
 | 
					import 'package:info_tren/pages/train_info_page/select_train/select_train_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/select_train/select_train_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/select_train/select_train_material.dart';
 | 
					import 'package:info_tren/pages/train_info_page/select_train/select_train_material.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
| 
						 | 
					@ -26,6 +27,8 @@ class SelectTrainPage extends ConsumerWidget {
 | 
				
			||||||
        return const SelectTrainPageMaterial();
 | 
					        return const SelectTrainPageMaterial();
 | 
				
			||||||
      case UiDesign.CUPERTINO:
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
        return const SelectTrainPageCupertino();
 | 
					        return const SelectTrainPageCupertino();
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return const SelectTrainPageFluent();
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        throw UnmatchedUiDesignException(uiDesign);
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -70,7 +73,11 @@ abstract class SelectTrainPageState extends State<SelectTrainPageShared> {
 | 
				
			||||||
        return posInNum1.compareTo(posInNum2);
 | 
					        return posInNum1.compareTo(posInNum2);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return t1.number.length.compareTo(t2.number.length);
 | 
					      if (t1.number.length != t2.number.length) {
 | 
				
			||||||
 | 
					        return t1.number.length.compareTo(t2.number.length);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return t1.number.compareTo(t2.number);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return filtered;
 | 
					    return filtered;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/select_train/select_train.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SelectTrainPageFluent extends SelectTrainPageShared {
 | 
				
			||||||
 | 
					  const SelectTrainPageFluent({super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  State<SelectTrainPageShared> createState() => SelectTrainPageStateFluent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SelectTrainPageStateFluent extends SelectTrainPageState {
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					        title: Text(pageTitle),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: SafeArea(
 | 
				
			||||||
 | 
					        bottom: false,
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					              child: TextBox(
 | 
				
			||||||
 | 
					                controller: trainNoController,
 | 
				
			||||||
 | 
					                autofocus: true,
 | 
				
			||||||
 | 
					                placeholder: textFieldLabel,
 | 
				
			||||||
 | 
					                textInputAction: TextInputAction.search,
 | 
				
			||||||
 | 
					                keyboardType: TextInputType.number,
 | 
				
			||||||
 | 
					                onChanged: (_) => onTextChanged(),
 | 
				
			||||||
 | 
					                inputFormatters: [
 | 
				
			||||||
 | 
					                  FilteringTextInputFormatter.digitsOnly,
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: suggestionsList,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,11 @@
 | 
				
			||||||
 | 
					import 'package:flutter/widgets.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:flutter/cupertino.dart';
 | 
					 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:info_tren/api/train_data.dart';
 | 
					import 'package:info_tren/api/train_data.dart';
 | 
				
			||||||
import 'package:info_tren/components/loading/loading.dart';
 | 
					import 'package:info_tren/components/loading/loading.dart';
 | 
				
			||||||
import 'package:info_tren/components/refresh_future_builder.dart';
 | 
					import 'package:info_tren/components/refresh_future_builder.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
				
			||||||
import 'package:info_tren/providers.dart';
 | 
					import 'package:info_tren/providers.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,34 +29,35 @@ class TrainInfo extends ConsumerWidget {
 | 
				
			||||||
          replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1))));
 | 
					          replaceFutureBuilder(() => getTrain(trainNumber, date: DateTime.now().subtract(const Duration(days: 1))));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
 | 
				
			||||||
 | 
					          return TrainInfoLoading(title: trainNumber.toString(), loadingText: "Se încarcă...",);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (snapshot.state == RefreshFutureBuilderState.error) {
 | 
				
			||||||
 | 
					          return TrainInfoError(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (uiDesign) {
 | 
					        switch (uiDesign) {
 | 
				
			||||||
          case UiDesign.MATERIAL:
 | 
					          case UiDesign.MATERIAL:
 | 
				
			||||||
            if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
 | 
					 | 
				
			||||||
              return TrainInfoLoadingMaterial(title: trainNumber.toString(), loadingText: "Se încarcă...",);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (snapshot.state == RefreshFutureBuilderState.error) {
 | 
					 | 
				
			||||||
              return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return TrainInfoMaterial(
 | 
					            return TrainInfoMaterial(
 | 
				
			||||||
              trainData: snapshot.data!, 
 | 
					              trainData: snapshot.data!, 
 | 
				
			||||||
              refresh: refresh,
 | 
					              refresh: refresh,
 | 
				
			||||||
 | 
					              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
				
			||||||
              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
					              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          case UiDesign.CUPERTINO:
 | 
					          case UiDesign.CUPERTINO:
 | 
				
			||||||
            if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
 | 
					 | 
				
			||||||
              return TrainInfoLoadingCupertino(title: trainNumber.toString(), loadingText: "Se încarcă...",);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (snapshot.state == RefreshFutureBuilderState.error) {
 | 
					 | 
				
			||||||
              return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return TrainInfoCupertino(
 | 
					            return TrainInfoCupertino(
 | 
				
			||||||
              trainData: snapshot.data!, 
 | 
					              trainData: snapshot.data!, 
 | 
				
			||||||
              refresh: refresh, 
 | 
					              refresh: refresh, 
 | 
				
			||||||
              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
					              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
				
			||||||
              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
					              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					          case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					            return TrainInfoFluent(
 | 
				
			||||||
 | 
					              trainData: snapshot.data!,
 | 
				
			||||||
 | 
					              refresh: refresh,
 | 
				
			||||||
 | 
					              isRefreshing: snapshot.state == RefreshFutureBuilderState.refreshing,
 | 
				
			||||||
 | 
					              onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
          default:
 | 
					          default:
 | 
				
			||||||
            throw UnmatchedUiDesignException(uiDesign);
 | 
					            throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -73,23 +73,176 @@ class TrainInfoArguments {
 | 
				
			||||||
  TrainInfoArguments({required this.trainNumber, this.date});
 | 
					  TrainInfoArguments({required this.trainNumber, this.date});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class TrainInfoLoading extends StatelessWidget {
 | 
					abstract class TrainInfoShared extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					  final Future Function()? refresh;
 | 
				
			||||||
 | 
					  final void Function()? onViewYesterdayTrain;
 | 
				
			||||||
 | 
					  final bool? isRefreshing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const TrainInfoShared({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.trainData,
 | 
				
			||||||
 | 
					    this.refresh,
 | 
				
			||||||
 | 
					    this.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    this.isRefreshing,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoLoading extends ConsumerWidget {
 | 
				
			||||||
 | 
					  final String title;
 | 
				
			||||||
 | 
					  final String? loadingText;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const TrainInfoLoading({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.title,
 | 
				
			||||||
 | 
					    this.loadingText,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final uiDesign = ref.watch(uiDesignProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (uiDesign) {
 | 
				
			||||||
 | 
					      case UiDesign.MATERIAL:
 | 
				
			||||||
 | 
					        return TrainInfoLoadingMaterial(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          loadingText: loadingText,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
 | 
					        return TrainInfoLoadingCupertino(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          loadingText: loadingText,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return TrainInfoLoadingFluent(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          loadingText: loadingText,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TrainInfoLoadingShared extends StatelessWidget {
 | 
				
			||||||
  final String title;
 | 
					  final String title;
 | 
				
			||||||
  final Widget loadingWidget;
 | 
					  final Widget loadingWidget;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  TrainInfoLoading({
 | 
					  TrainInfoLoadingShared({
 | 
				
			||||||
    required this.title, 
 | 
					    required this.title, 
 | 
				
			||||||
    String? loadingText, 
 | 
					    String? loadingText, 
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
  }) : loadingWidget = Loading(text: loadingText,);
 | 
					  }) : loadingWidget = Loading(text: loadingText,);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class TrainInfoError extends StatelessWidget {
 | 
					class TrainInfoError extends ConsumerWidget {
 | 
				
			||||||
  final String title;
 | 
					  final String title;
 | 
				
			||||||
  final Object error;
 | 
					  final Object error;
 | 
				
			||||||
  final Future Function()? refresh;
 | 
					  final Future Function()? refresh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const TrainInfoError({required this.title, required this.error, this.refresh, super.key,});
 | 
					  const TrainInfoError({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.title,
 | 
				
			||||||
 | 
					    required this.error,
 | 
				
			||||||
 | 
					    this.refresh,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final uiDesign = ref.watch(uiDesignProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (uiDesign) {
 | 
				
			||||||
 | 
					      case UiDesign.MATERIAL:
 | 
				
			||||||
 | 
					        return TrainInfoErrorMaterial(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          error: error,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
 | 
					        return TrainInfoErrorCupertino(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          error: error,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return TrainInfoErrorFluent(
 | 
				
			||||||
 | 
					          title: title,
 | 
				
			||||||
 | 
					          error: error,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TrainInfoErrorShared extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String title;
 | 
				
			||||||
 | 
					  final Object error;
 | 
				
			||||||
 | 
					  final Future Function()? refresh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const TrainInfoErrorShared({required this.title, required this.error, this.refresh, super.key,});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoBody extends ConsumerWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					  final void Function()? onViewYesterdayTrain;
 | 
				
			||||||
 | 
					  final Future Function()? refresh;
 | 
				
			||||||
 | 
					  final bool? isRefreshing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const TrainInfoBody({
 | 
				
			||||||
 | 
					    required this.trainData,
 | 
				
			||||||
 | 
					    this.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    this.refresh,
 | 
				
			||||||
 | 
					    this.isRefreshing,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
 | 
					    final uiDesign = ref.watch(uiDesignProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (uiDesign) {
 | 
				
			||||||
 | 
					      case UiDesign.MATERIAL:
 | 
				
			||||||
 | 
					        return TrainInfoBodyMaterial(
 | 
				
			||||||
 | 
					          trainData: trainData,
 | 
				
			||||||
 | 
					          onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					          isRefreshing: isRefreshing,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.CUPERTINO:
 | 
				
			||||||
 | 
					        return TrainInfoBodyCupertino(
 | 
				
			||||||
 | 
					          trainData: trainData,
 | 
				
			||||||
 | 
					          onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					          isRefreshing: isRefreshing,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      case UiDesign.FLUENT:
 | 
				
			||||||
 | 
					        return TrainInfoBodyFluent(
 | 
				
			||||||
 | 
					          trainData: trainData,
 | 
				
			||||||
 | 
					          onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
 | 
					          refresh: refresh,
 | 
				
			||||||
 | 
					          isRefreshing: isRefreshing,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw UnmatchedUiDesignException(uiDesign);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class TrainInfoBodyShared extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					  final void Function()? onViewYesterdayTrain;
 | 
				
			||||||
 | 
					  final Future Function()? refresh;
 | 
				
			||||||
 | 
					  final bool? isRefreshing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const TrainInfoBodyShared({
 | 
				
			||||||
 | 
					    required this.trainData,
 | 
				
			||||||
 | 
					    this.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    this.refresh,
 | 
				
			||||||
 | 
					    this.isRefreshing,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget {
 | 
					abstract class DisplayTrainYesterdayWarningCommon extends StatelessWidget {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_cupertino_DisplayTrainStation.dart';
 | 
				
			||||||
import 'package:info_tren/utils/state_to_string.dart';
 | 
					import 'package:info_tren/utils/state_to_string.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoLoadingCupertino extends TrainInfoLoading {
 | 
					class TrainInfoLoadingCupertino extends TrainInfoLoadingShared {
 | 
				
			||||||
  TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,});
 | 
					  TrainInfoLoadingCupertino({required super.title, super.loadingText, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
| 
						 | 
					@ -26,17 +26,13 @@ class TrainInfoLoadingCupertino extends TrainInfoLoading {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoErrorCupertino extends TrainInfoError {
 | 
					class TrainInfoErrorCupertino extends TrainInfoErrorShared {
 | 
				
			||||||
  const TrainInfoErrorCupertino({
 | 
					  const TrainInfoErrorCupertino({
 | 
				
			||||||
    required Object error,
 | 
					    required super.error,
 | 
				
			||||||
    required String title,
 | 
					    required super.title,
 | 
				
			||||||
    Future Function()? refresh,
 | 
					    super.refresh,
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
  }) : super(
 | 
					  });
 | 
				
			||||||
          error: error,
 | 
					 | 
				
			||||||
          title: title,
 | 
					 | 
				
			||||||
          refresh: refresh,
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
| 
						 | 
					@ -64,17 +60,12 @@ class TrainInfoErrorCupertino extends TrainInfoError {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoCupertino extends StatelessWidget {
 | 
					class TrainInfoCupertino extends TrainInfoShared {
 | 
				
			||||||
  final TrainData trainData;
 | 
					 | 
				
			||||||
  final Future Function()? refresh;
 | 
					 | 
				
			||||||
  final bool? isRefreshing;
 | 
					 | 
				
			||||||
  final void Function()? onViewYesterdayTrain;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const TrainInfoCupertino({
 | 
					  const TrainInfoCupertino({
 | 
				
			||||||
    required this.trainData,
 | 
					    required super.trainData,
 | 
				
			||||||
    this.refresh,
 | 
					    super.refresh,
 | 
				
			||||||
    this.isRefreshing,
 | 
					    super.isRefreshing,
 | 
				
			||||||
    this.onViewYesterdayTrain,
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,195 +84,10 @@ class TrainInfoCupertino extends StatelessWidget {
 | 
				
			||||||
      child: SafeArea(
 | 
					      child: SafeArea(
 | 
				
			||||||
        top: false,
 | 
					        top: false,
 | 
				
			||||||
        bottom: false,
 | 
					        bottom: false,
 | 
				
			||||||
        child: Builder(builder: (context) {
 | 
					        child: TrainInfoBody(
 | 
				
			||||||
          final topPadding = MediaQuery.of(context).padding.top;
 | 
					          trainData: trainData,
 | 
				
			||||||
 | 
					          onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
          return NestedScrollView(
 | 
					        ),
 | 
				
			||||||
            headerSliverBuilder: (context, innerBoxIsScrolled) {
 | 
					 | 
				
			||||||
              return [
 | 
					 | 
				
			||||||
                // SliverPadding(
 | 
					 | 
				
			||||||
                //   padding: EdgeInsets.only(
 | 
					 | 
				
			||||||
                //     top: topPadding,
 | 
					 | 
				
			||||||
                //   ),
 | 
					 | 
				
			||||||
                // ),
 | 
					 | 
				
			||||||
                SliverPersistentHeaderPadding(
 | 
					 | 
				
			||||||
                  maxHeight: topPadding,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
              ];
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            body: Builder(builder: (context) {
 | 
					 | 
				
			||||||
              return CustomScrollView(
 | 
					 | 
				
			||||||
                slivers: <Widget>[
 | 
					 | 
				
			||||||
                  if (refresh != null)
 | 
					 | 
				
			||||||
                    CupertinoSliverRefreshControl(
 | 
					 | 
				
			||||||
                      builder: (context, mode, pulledExtent,
 | 
					 | 
				
			||||||
                          refreshTriggerPullDistance, refreshIndicatorExtent) {
 | 
					 | 
				
			||||||
                        return Column(
 | 
					 | 
				
			||||||
                          mainAxisSize: MainAxisSize.min,
 | 
					 | 
				
			||||||
                          children: [
 | 
					 | 
				
			||||||
                            SizedBox(
 | 
					 | 
				
			||||||
                              height: pulledExtent,
 | 
					 | 
				
			||||||
                              child: Column(
 | 
					 | 
				
			||||||
                                children: [
 | 
					 | 
				
			||||||
                                  SizedBox(
 | 
					 | 
				
			||||||
                                    height: min(
 | 
					 | 
				
			||||||
                                        refreshIndicatorExtent, pulledExtent),
 | 
					 | 
				
			||||||
                                    child: Center(
 | 
					 | 
				
			||||||
                                      child: Builder(
 | 
					 | 
				
			||||||
                                        builder: (context) {
 | 
					 | 
				
			||||||
                                          if (mode ==
 | 
					 | 
				
			||||||
                                              RefreshIndicatorMode.inactive) {
 | 
					 | 
				
			||||||
                                            return Container();
 | 
					 | 
				
			||||||
                                          } else if (mode ==
 | 
					 | 
				
			||||||
                                              RefreshIndicatorMode.done) {
 | 
					 | 
				
			||||||
                                            return const Text('Refreshed!');
 | 
					 | 
				
			||||||
                                          } else if (mode ==
 | 
					 | 
				
			||||||
                                              RefreshIndicatorMode.drag) {
 | 
					 | 
				
			||||||
                                            return Row(
 | 
					 | 
				
			||||||
                                              mainAxisSize: MainAxisSize.min,
 | 
					 | 
				
			||||||
                                              children: const [
 | 
					 | 
				
			||||||
                                                CupertinoActivityIndicator(
 | 
					 | 
				
			||||||
                                                  animating: false,
 | 
					 | 
				
			||||||
                                                ),
 | 
					 | 
				
			||||||
                                                Text('Pull to refresh...'),
 | 
					 | 
				
			||||||
                                              ],
 | 
					 | 
				
			||||||
                                            );
 | 
					 | 
				
			||||||
                                          } else if (mode ==
 | 
					 | 
				
			||||||
                                              RefreshIndicatorMode.armed) {
 | 
					 | 
				
			||||||
                                            return Row(
 | 
					 | 
				
			||||||
                                              mainAxisSize: MainAxisSize.min,
 | 
					 | 
				
			||||||
                                              children: const [
 | 
					 | 
				
			||||||
                                                CupertinoActivityIndicator(
 | 
					 | 
				
			||||||
                                                  animating: false,
 | 
					 | 
				
			||||||
                                                ),
 | 
					 | 
				
			||||||
                                                Text('Release to refresh...'),
 | 
					 | 
				
			||||||
                                              ],
 | 
					 | 
				
			||||||
                                            );
 | 
					 | 
				
			||||||
                                          } else {
 | 
					 | 
				
			||||||
                                            return Row(
 | 
					 | 
				
			||||||
                                              mainAxisSize: MainAxisSize.min,
 | 
					 | 
				
			||||||
                                              children: const [
 | 
					 | 
				
			||||||
                                                CupertinoActivityIndicator(),
 | 
					 | 
				
			||||||
                                                Text('Refreshing'),
 | 
					 | 
				
			||||||
                                              ],
 | 
					 | 
				
			||||||
                                            );
 | 
					 | 
				
			||||||
                                          }
 | 
					 | 
				
			||||||
                                        },
 | 
					 | 
				
			||||||
                                      ),
 | 
					 | 
				
			||||||
                                    ),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                  Expanded(
 | 
					 | 
				
			||||||
                                    child: Container(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ],
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ],
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
                      },
 | 
					 | 
				
			||||||
                      onRefresh: refresh,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  DisplayTrainID(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  DisplayTrainOperator(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  DisplayTrainRoute(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  DisplayTrainDeparture(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  const SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                    child: CupertinoDivider(
 | 
					 | 
				
			||||||
                      color: foregroundWhite,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  DisplayTrainLastInfo(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  const SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                    child: CupertinoDivider(),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                    child: IntrinsicHeight(
 | 
					 | 
				
			||||||
                      child: Row(
 | 
					 | 
				
			||||||
                        children: <Widget>[
 | 
					 | 
				
			||||||
                          // Expanded(
 | 
					 | 
				
			||||||
                          //   child: DisplayTrainNextStop(trainData: trainData,),
 | 
					 | 
				
			||||||
                          // ),
 | 
					 | 
				
			||||||
                          Expanded(
 | 
					 | 
				
			||||||
                            child: DisplayTrainRouteDuration(
 | 
					 | 
				
			||||||
                              trainData: trainData,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          // Expanded(
 | 
					 | 
				
			||||||
                          //   child: DisplayTrainDestination(trainData: trainData,),
 | 
					 | 
				
			||||||
                          // ),
 | 
					 | 
				
			||||||
                          const SizedBox(
 | 
					 | 
				
			||||||
                            height: double.infinity,
 | 
					 | 
				
			||||||
                            child: CupertinoVerticalDivider(),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          Expanded(
 | 
					 | 
				
			||||||
                            child: DisplayTrainRouteDistance(
 | 
					 | 
				
			||||||
                              trainData: trainData,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ],
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  // SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                  //   child: CupertinoDivider(),
 | 
					 | 
				
			||||||
                  // ),
 | 
					 | 
				
			||||||
                  // SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                  //   child: IntrinsicHeight(
 | 
					 | 
				
			||||||
                  //     child: Row(
 | 
					 | 
				
			||||||
                  //       children: <Widget>[
 | 
					 | 
				
			||||||
                  //         // Expanded(
 | 
					 | 
				
			||||||
                  //         //   child: DisplayTrainRouteDuration(trainData: trainData,),
 | 
					 | 
				
			||||||
                  //         // ),
 | 
					 | 
				
			||||||
                  //         Expanded(child: Container(),),
 | 
					 | 
				
			||||||
                  //         SizedBox(
 | 
					 | 
				
			||||||
                  //           height: double.infinity,
 | 
					 | 
				
			||||||
                  //           child: CupertinoVerticalDivider(),
 | 
					 | 
				
			||||||
                  //         ),
 | 
					 | 
				
			||||||
                  //         Expanded(
 | 
					 | 
				
			||||||
                  //           child: DisplayTrainRouteDistance(trainData: trainData,),
 | 
					 | 
				
			||||||
                  //         )
 | 
					 | 
				
			||||||
                  //       ],
 | 
					 | 
				
			||||||
                  //     ),
 | 
					 | 
				
			||||||
                  //   ),
 | 
					 | 
				
			||||||
                  // ),
 | 
					 | 
				
			||||||
                  const SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                    child: CupertinoDivider(
 | 
					 | 
				
			||||||
                      color: foregroundWhite,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
 | 
					 | 
				
			||||||
                    SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                      child: DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                    const SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                      child: CupertinoDivider(
 | 
					 | 
				
			||||||
                        color: foregroundWhite,
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ],
 | 
					 | 
				
			||||||
                  DisplayTrainStations(
 | 
					 | 
				
			||||||
                    trainData: trainData,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                    child: Container(
 | 
					 | 
				
			||||||
                      height: MediaQuery.of(context).viewPadding.bottom,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
              );
 | 
					 | 
				
			||||||
            }),
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        }),
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -390,31 +196,382 @@ class TrainInfoCupertino extends StatelessWidget {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoBodyCupertino extends TrainInfoBodyShared {
 | 
				
			||||||
 | 
					  const TrainInfoBodyCupertino({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required super.trainData,
 | 
				
			||||||
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    super.isRefreshing,
 | 
				
			||||||
 | 
					    super.refresh,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final mq = MediaQuery.of(context);
 | 
				
			||||||
 | 
					    final topPadding = mq.padding.top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
 | 
				
			||||||
 | 
					      return Row(
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          Container(
 | 
				
			||||||
 | 
					            constraints: const BoxConstraints(
 | 
				
			||||||
 | 
					              minWidth: 400,
 | 
				
			||||||
 | 
					              maxWidth: 400,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            child: Column(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                DisplayTrainID(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainOperator(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainRoute(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainDeparture(trainData: trainData),
 | 
				
			||||||
 | 
					                const CupertinoDivider(
 | 
				
			||||||
 | 
					                  color: foregroundWhite,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                DisplayTrainLastInfo(trainData: trainData),
 | 
				
			||||||
 | 
					                const CupertinoDivider(),
 | 
				
			||||||
 | 
					                IntrinsicHeight(
 | 
				
			||||||
 | 
					                  child: Row(
 | 
				
			||||||
 | 
					                    children: <Widget>[
 | 
				
			||||||
 | 
					                      // Expanded(
 | 
				
			||||||
 | 
					                      //   child: DisplayTrainNextStop(trainData: trainData,),
 | 
				
			||||||
 | 
					                      // ),
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                          trainData: trainData,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      // Expanded(
 | 
				
			||||||
 | 
					                      //   child: DisplayTrainDestination(trainData: trainData,),
 | 
				
			||||||
 | 
					                      // ),
 | 
				
			||||||
 | 
					                      const SizedBox(
 | 
				
			||||||
 | 
					                        height: double.infinity,
 | 
				
			||||||
 | 
					                        child: CupertinoVerticalDivider(),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                          trainData: trainData,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                const CupertinoDivider(
 | 
				
			||||||
 | 
					                  color: foregroundWhite,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
 | 
				
			||||||
 | 
					                  DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
 | 
				
			||||||
 | 
					                  const CupertinoDivider(
 | 
				
			||||||
 | 
					                    color: foregroundWhite,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Expanded(
 | 
				
			||||||
 | 
					            child: NestedScrollView(
 | 
				
			||||||
 | 
					              headerSliverBuilder: (context, innerBoxIsScrolled) {
 | 
				
			||||||
 | 
					                return [
 | 
				
			||||||
 | 
					                  // SliverPadding(
 | 
				
			||||||
 | 
					                  //   padding: EdgeInsets.only(
 | 
				
			||||||
 | 
					                  //     top: topPadding,
 | 
				
			||||||
 | 
					                  //   ),
 | 
				
			||||||
 | 
					                  // ),
 | 
				
			||||||
 | 
					                  SliverPersistentHeaderPadding(
 | 
				
			||||||
 | 
					                    maxHeight: topPadding,
 | 
				
			||||||
 | 
					                  )
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              body: CustomScrollView(
 | 
				
			||||||
 | 
					                slivers: [
 | 
				
			||||||
 | 
					                  if (refresh != null)
 | 
				
			||||||
 | 
					                    CupertinoSliverRefreshControl(
 | 
				
			||||||
 | 
					                      builder: (context, mode, pulledExtent,
 | 
				
			||||||
 | 
					                          refreshTriggerPullDistance, refreshIndicatorExtent) {
 | 
				
			||||||
 | 
					                        return Column(
 | 
				
			||||||
 | 
					                          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            SizedBox(
 | 
				
			||||||
 | 
					                              height: pulledExtent,
 | 
				
			||||||
 | 
					                              child: Column(
 | 
				
			||||||
 | 
					                                children: [
 | 
				
			||||||
 | 
					                                  SizedBox(
 | 
				
			||||||
 | 
					                                    height: min(
 | 
				
			||||||
 | 
					                                        refreshIndicatorExtent, pulledExtent),
 | 
				
			||||||
 | 
					                                    child: Center(
 | 
				
			||||||
 | 
					                                      child: Builder(
 | 
				
			||||||
 | 
					                                        builder: (context) {
 | 
				
			||||||
 | 
					                                          if (mode ==
 | 
				
			||||||
 | 
					                                              RefreshIndicatorMode.inactive) {
 | 
				
			||||||
 | 
					                                            return Container();
 | 
				
			||||||
 | 
					                                          } else if (mode ==
 | 
				
			||||||
 | 
					                                              RefreshIndicatorMode.done) {
 | 
				
			||||||
 | 
					                                            return const Text('Refreshed!');
 | 
				
			||||||
 | 
					                                          } else if (mode ==
 | 
				
			||||||
 | 
					                                              RefreshIndicatorMode.drag) {
 | 
				
			||||||
 | 
					                                            return Row(
 | 
				
			||||||
 | 
					                                              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                              children: const [
 | 
				
			||||||
 | 
					                                                CupertinoActivityIndicator(
 | 
				
			||||||
 | 
					                                                  animating: false,
 | 
				
			||||||
 | 
					                                                ),
 | 
				
			||||||
 | 
					                                                Text('Pull to refresh...'),
 | 
				
			||||||
 | 
					                                              ],
 | 
				
			||||||
 | 
					                                            );
 | 
				
			||||||
 | 
					                                          } else if (mode ==
 | 
				
			||||||
 | 
					                                              RefreshIndicatorMode.armed) {
 | 
				
			||||||
 | 
					                                            return Row(
 | 
				
			||||||
 | 
					                                              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                              children: const [
 | 
				
			||||||
 | 
					                                                CupertinoActivityIndicator(
 | 
				
			||||||
 | 
					                                                  animating: false,
 | 
				
			||||||
 | 
					                                                ),
 | 
				
			||||||
 | 
					                                                Text('Release to refresh...'),
 | 
				
			||||||
 | 
					                                              ],
 | 
				
			||||||
 | 
					                                            );
 | 
				
			||||||
 | 
					                                          } else {
 | 
				
			||||||
 | 
					                                            return Row(
 | 
				
			||||||
 | 
					                                              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                              children: const [
 | 
				
			||||||
 | 
					                                                CupertinoActivityIndicator(),
 | 
				
			||||||
 | 
					                                                Text('Refreshing'),
 | 
				
			||||||
 | 
					                                              ],
 | 
				
			||||||
 | 
					                                            );
 | 
				
			||||||
 | 
					                                          }
 | 
				
			||||||
 | 
					                                        },
 | 
				
			||||||
 | 
					                                      ),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                  Expanded(
 | 
				
			||||||
 | 
					                                    child: Container(),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ],
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      },
 | 
				
			||||||
 | 
					                      onRefresh: refresh,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  DisplayTrainStations(
 | 
				
			||||||
 | 
					                    trainData: trainData,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  SliverToBoxAdapter(
 | 
				
			||||||
 | 
					                    child: Container(
 | 
				
			||||||
 | 
					                      height: MediaQuery.of(context).viewPadding.bottom,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return NestedScrollView(
 | 
				
			||||||
 | 
					      headerSliverBuilder: (context, innerBoxIsScrolled) {
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					          // SliverPadding(
 | 
				
			||||||
 | 
					          //   padding: EdgeInsets.only(
 | 
				
			||||||
 | 
					          //     top: topPadding,
 | 
				
			||||||
 | 
					          //   ),
 | 
				
			||||||
 | 
					          // ),
 | 
				
			||||||
 | 
					          SliverPersistentHeaderPadding(
 | 
				
			||||||
 | 
					            maxHeight: topPadding,
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      body: Builder(builder: (context) {
 | 
				
			||||||
 | 
					        return CustomScrollView(
 | 
				
			||||||
 | 
					          slivers: <Widget>[
 | 
				
			||||||
 | 
					            if (refresh != null)
 | 
				
			||||||
 | 
					              CupertinoSliverRefreshControl(
 | 
				
			||||||
 | 
					                builder: (context, mode, pulledExtent,
 | 
				
			||||||
 | 
					                    refreshTriggerPullDistance, refreshIndicatorExtent) {
 | 
				
			||||||
 | 
					                  return Column(
 | 
				
			||||||
 | 
					                    mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      SizedBox(
 | 
				
			||||||
 | 
					                        height: pulledExtent,
 | 
				
			||||||
 | 
					                        child: Column(
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            SizedBox(
 | 
				
			||||||
 | 
					                              height: min(
 | 
				
			||||||
 | 
					                                  refreshIndicatorExtent, pulledExtent),
 | 
				
			||||||
 | 
					                              child: Center(
 | 
				
			||||||
 | 
					                                child: Builder(
 | 
				
			||||||
 | 
					                                  builder: (context) {
 | 
				
			||||||
 | 
					                                    if (mode ==
 | 
				
			||||||
 | 
					                                        RefreshIndicatorMode.inactive) {
 | 
				
			||||||
 | 
					                                      return Container();
 | 
				
			||||||
 | 
					                                    } else if (mode ==
 | 
				
			||||||
 | 
					                                        RefreshIndicatorMode.done) {
 | 
				
			||||||
 | 
					                                      return const Text('Refreshed!');
 | 
				
			||||||
 | 
					                                    } else if (mode ==
 | 
				
			||||||
 | 
					                                        RefreshIndicatorMode.drag) {
 | 
				
			||||||
 | 
					                                      return Row(
 | 
				
			||||||
 | 
					                                        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                        children: const [
 | 
				
			||||||
 | 
					                                          CupertinoActivityIndicator(
 | 
				
			||||||
 | 
					                                            animating: false,
 | 
				
			||||||
 | 
					                                          ),
 | 
				
			||||||
 | 
					                                          Text('Pull to refresh...'),
 | 
				
			||||||
 | 
					                                        ],
 | 
				
			||||||
 | 
					                                      );
 | 
				
			||||||
 | 
					                                    } else if (mode ==
 | 
				
			||||||
 | 
					                                        RefreshIndicatorMode.armed) {
 | 
				
			||||||
 | 
					                                      return Row(
 | 
				
			||||||
 | 
					                                        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                        children: const [
 | 
				
			||||||
 | 
					                                          CupertinoActivityIndicator(
 | 
				
			||||||
 | 
					                                            animating: false,
 | 
				
			||||||
 | 
					                                          ),
 | 
				
			||||||
 | 
					                                          Text('Release to refresh...'),
 | 
				
			||||||
 | 
					                                        ],
 | 
				
			||||||
 | 
					                                      );
 | 
				
			||||||
 | 
					                                    } else {
 | 
				
			||||||
 | 
					                                      return Row(
 | 
				
			||||||
 | 
					                                        mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                                        children: const [
 | 
				
			||||||
 | 
					                                          CupertinoActivityIndicator(),
 | 
				
			||||||
 | 
					                                          Text('Refreshing'),
 | 
				
			||||||
 | 
					                                        ],
 | 
				
			||||||
 | 
					                                      );
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                  },
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: Container(),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                onRefresh: refresh,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ...[
 | 
				
			||||||
 | 
					              DisplayTrainID(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              DisplayTrainOperator(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              DisplayTrainRoute(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              DisplayTrainDeparture(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              const CupertinoDivider(
 | 
				
			||||||
 | 
					                color: foregroundWhite,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              DisplayTrainLastInfo(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              const CupertinoDivider(),
 | 
				
			||||||
 | 
					              IntrinsicHeight(
 | 
				
			||||||
 | 
					                child: Row(
 | 
				
			||||||
 | 
					                  children: <Widget>[
 | 
				
			||||||
 | 
					                    // Expanded(
 | 
				
			||||||
 | 
					                    //   child: DisplayTrainNextStop(trainData: trainData,),
 | 
				
			||||||
 | 
					                    // ),
 | 
				
			||||||
 | 
					                    Expanded(
 | 
				
			||||||
 | 
					                      child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                        trainData: trainData,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    // Expanded(
 | 
				
			||||||
 | 
					                    //   child: DisplayTrainDestination(trainData: trainData,),
 | 
				
			||||||
 | 
					                    // ),
 | 
				
			||||||
 | 
					                    const SizedBox(
 | 
				
			||||||
 | 
					                      height: double.infinity,
 | 
				
			||||||
 | 
					                      child: CupertinoVerticalDivider(),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    Expanded(
 | 
				
			||||||
 | 
					                      child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                        trainData: trainData,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              const CupertinoDivider(
 | 
				
			||||||
 | 
					                color: foregroundWhite,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
 | 
				
			||||||
 | 
					                DisplayTrainYesterdayWarningCupertino(onViewYesterdayTrain!),
 | 
				
			||||||
 | 
					                const CupertinoDivider(
 | 
				
			||||||
 | 
					                  color: foregroundWhite,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ].map((e) => SliverToBoxAdapter(child: e)),
 | 
				
			||||||
 | 
					            // SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            //   child: CupertinoDivider(),
 | 
				
			||||||
 | 
					            // ),
 | 
				
			||||||
 | 
					            // SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            //   child: IntrinsicHeight(
 | 
				
			||||||
 | 
					            //     child: Row(
 | 
				
			||||||
 | 
					            //       children: <Widget>[
 | 
				
			||||||
 | 
					            //         // Expanded(
 | 
				
			||||||
 | 
					            //         //   child: DisplayTrainRouteDuration(trainData: trainData,),
 | 
				
			||||||
 | 
					            //         // ),
 | 
				
			||||||
 | 
					            //         Expanded(child: Container(),),
 | 
				
			||||||
 | 
					            //         SizedBox(
 | 
				
			||||||
 | 
					            //           height: double.infinity,
 | 
				
			||||||
 | 
					            //           child: CupertinoVerticalDivider(),
 | 
				
			||||||
 | 
					            //         ),
 | 
				
			||||||
 | 
					            //         Expanded(
 | 
				
			||||||
 | 
					            //           child: DisplayTrainRouteDistance(trainData: trainData,),
 | 
				
			||||||
 | 
					            //         )
 | 
				
			||||||
 | 
					            //       ],
 | 
				
			||||||
 | 
					            //     ),
 | 
				
			||||||
 | 
					            //   ),
 | 
				
			||||||
 | 
					            // ),
 | 
				
			||||||
 | 
					            DisplayTrainStations(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: Container(
 | 
				
			||||||
 | 
					                height: MediaQuery.of(context).viewPadding.bottom,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DisplayTrainID extends StatelessWidget {
 | 
					class DisplayTrainID extends StatelessWidget {
 | 
				
			||||||
  final TrainData trainData;
 | 
					  final TrainData trainData;
 | 
				
			||||||
  const DisplayTrainID({required this.trainData, super.key,});
 | 
					  const DisplayTrainID({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return SliverToBoxAdapter(
 | 
					    return Center(
 | 
				
			||||||
      child: Center(
 | 
					      child: Padding(
 | 
				
			||||||
        child: Padding(
 | 
					        padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
          padding: const EdgeInsets.all(8.0),
 | 
					        child: Text.rich(
 | 
				
			||||||
          child: Text.rich(
 | 
					        TextSpan(
 | 
				
			||||||
          TextSpan(
 | 
					          children: [
 | 
				
			||||||
            children: [
 | 
					            TextSpan(
 | 
				
			||||||
              TextSpan(
 | 
					              text: trainData.rank,
 | 
				
			||||||
                text: trainData.rank,
 | 
					              style: TextStyle(
 | 
				
			||||||
                style: TextStyle(
 | 
					                color: trainData.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
 | 
				
			||||||
                  color: trainData.rank.startsWith('IR') ? const Color.fromARGB(255, 255, 0, 0) : null,
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              const TextSpan(text: ' '),
 | 
					            ),
 | 
				
			||||||
              TextSpan(text: trainData.number,),
 | 
					            const TextSpan(text: ' '),
 | 
				
			||||||
            ],
 | 
					            TextSpan(text: trainData.number,),
 | 
				
			||||||
          ),
 | 
					          ],
 | 
				
			||||||
            style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
 | 
					        ),
 | 
				
			||||||
          ),
 | 
					          style: CupertinoTheme.of(context).textTheme.navLargeTitleTextStyle,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -428,41 +585,39 @@ class DisplayTrainRoute extends StatelessWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return SliverToBoxAdapter(
 | 
					    return Row(
 | 
				
			||||||
      child: Row(
 | 
					      children: <Widget>[
 | 
				
			||||||
        children: <Widget>[
 | 
					        Expanded(
 | 
				
			||||||
          Expanded(
 | 
					          child: Center(
 | 
				
			||||||
            child: Center(
 | 
					            child: Padding(
 | 
				
			||||||
              child: Padding(
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
                padding: const EdgeInsets.all(4),
 | 
					              child: Text(
 | 
				
			||||||
                child: Text(
 | 
					                trainData.route.from,
 | 
				
			||||||
                  trainData.route.from,
 | 
					                style:
 | 
				
			||||||
                  style:
 | 
					                    CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
                      CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					                          fontSize: 16,
 | 
				
			||||||
                            fontSize: 16,
 | 
					                        ),
 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          const Center(child: Text("-")),
 | 
					        ),
 | 
				
			||||||
          Expanded(
 | 
					        const Center(child: Text("-")),
 | 
				
			||||||
            child: Center(
 | 
					        Expanded(
 | 
				
			||||||
              child: Padding(
 | 
					          child: Center(
 | 
				
			||||||
                padding: const EdgeInsets.all(4),
 | 
					            child: Padding(
 | 
				
			||||||
                child: Text(
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
                  trainData.route.to,
 | 
					              child: Text(
 | 
				
			||||||
                  style:
 | 
					                trainData.route.to,
 | 
				
			||||||
                      CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					                style:
 | 
				
			||||||
                            fontSize: 16,
 | 
					                    CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
                          ),
 | 
					                          fontSize: 16,
 | 
				
			||||||
                  textAlign: TextAlign.right,
 | 
					                        ),
 | 
				
			||||||
                ),
 | 
					                textAlign: TextAlign.right,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ],
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -474,15 +629,13 @@ class DisplayTrainOperator extends StatelessWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return SliverToBoxAdapter(
 | 
					    return Center(
 | 
				
			||||||
      child: Center(
 | 
					      child: Text(
 | 
				
			||||||
        child: Text(
 | 
					        trainData.operator,
 | 
				
			||||||
          trainData.operator,
 | 
					        style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
          style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					              fontSize: 14,
 | 
				
			||||||
                fontSize: 14,
 | 
					              fontStyle: FontStyle.italic,
 | 
				
			||||||
                fontStyle: FontStyle.italic,
 | 
					            ),
 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -495,18 +648,16 @@ class DisplayTrainDeparture extends StatelessWidget {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return SliverToBoxAdapter(
 | 
					    return Padding(
 | 
				
			||||||
      child: Padding(
 | 
					      padding: const EdgeInsets.all(2),
 | 
				
			||||||
        padding: const EdgeInsets.all(2),
 | 
					      child: Text(
 | 
				
			||||||
        child: Text(
 | 
					        // "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
 | 
				
			||||||
          // "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
 | 
					        "Plecare în ${trainData.date}",
 | 
				
			||||||
          "Plecare în ${trainData.date}",
 | 
					        style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
          style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					              fontStyle: FontStyle.italic,
 | 
				
			||||||
                fontStyle: FontStyle.italic,
 | 
					              fontWeight: FontWeight.w200,
 | 
				
			||||||
                fontWeight: FontWeight.w200,
 | 
					            ),
 | 
				
			||||||
              ),
 | 
					        textAlign: TextAlign.center,
 | 
				
			||||||
          textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -520,90 +671,86 @@ class DisplayTrainLastInfo extends StatelessWidget {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    if (trainData.status == null) {
 | 
					    if (trainData.status == null) {
 | 
				
			||||||
      return SliverToBoxAdapter(
 | 
					      return Container();
 | 
				
			||||||
        child: Container(),
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return SliverToBoxAdapter(
 | 
					    return Column(
 | 
				
			||||||
      child: Column(
 | 
					      mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
        mainAxisSize: MainAxisSize.min,
 | 
					      children: <Widget>[
 | 
				
			||||||
        children: <Widget>[
 | 
					        Center(
 | 
				
			||||||
          Center(
 | 
					          child: Padding(
 | 
				
			||||||
            child: Padding(
 | 
					            padding: const EdgeInsets.all(2),
 | 
				
			||||||
              padding: const EdgeInsets.all(2),
 | 
					            child: Text(
 | 
				
			||||||
              child: Text(
 | 
					              "Ultima informație",
 | 
				
			||||||
                "Ultima informație",
 | 
					              style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
                style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					                    fontSize: 20,
 | 
				
			||||||
                      fontSize: 20,
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
                      fontWeight: FontWeight.bold,
 | 
					                  ),
 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          Row(
 | 
					        ),
 | 
				
			||||||
            children: <Widget>[
 | 
					        Row(
 | 
				
			||||||
              Padding(
 | 
					          children: <Widget>[
 | 
				
			||||||
                padding: const EdgeInsets.all(4),
 | 
					            Padding(
 | 
				
			||||||
                child: Text(
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
                  trainData.status!.station,
 | 
					              child: Text(
 | 
				
			||||||
                  style: CupertinoTheme.of(context).textTheme.textStyle,
 | 
					                trainData.status!.station,
 | 
				
			||||||
                  textAlign: TextAlign.left,
 | 
					                style: CupertinoTheme.of(context).textTheme.textStyle,
 | 
				
			||||||
                ),
 | 
					                textAlign: TextAlign.left,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              Expanded(
 | 
					            ),
 | 
				
			||||||
                child: Container(),
 | 
					            Expanded(
 | 
				
			||||||
 | 
					              child: Container(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					              child: Text(
 | 
				
			||||||
 | 
					                stateToString(trainData.status!.state),
 | 
				
			||||||
 | 
					                style: CupertinoTheme.of(context).textTheme.textStyle,
 | 
				
			||||||
 | 
					                textAlign: TextAlign.right,
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              Padding(
 | 
					            ),
 | 
				
			||||||
                padding: const EdgeInsets.all(4),
 | 
					          ],
 | 
				
			||||||
                child: Text(
 | 
					        ),
 | 
				
			||||||
                  stateToString(trainData.status!.state),
 | 
					        // FutureDisplay<DateTime>(
 | 
				
			||||||
                  style: CupertinoTheme.of(context).textTheme.textStyle,
 | 
					        //   future: trainData.lastInfo.dateAndTime,
 | 
				
			||||||
                  textAlign: TextAlign.right,
 | 
					        //   builder: (context, dt) {
 | 
				
			||||||
                ),
 | 
					        //     return Text(
 | 
				
			||||||
              ),
 | 
					        //       "Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
            ],
 | 
					        //       textAlign: TextAlign.center,
 | 
				
			||||||
          ),
 | 
					        //     );
 | 
				
			||||||
          // FutureDisplay<DateTime>(
 | 
					        //   },
 | 
				
			||||||
          //   future: trainData.lastInfo.dateAndTime,
 | 
					        // ),
 | 
				
			||||||
          //   builder: (context, dt) {
 | 
					        Builder(
 | 
				
			||||||
          //     return Text(
 | 
					          builder: (context) {
 | 
				
			||||||
          //       "Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}",
 | 
					            final data = trainData.status!.delay;
 | 
				
			||||||
          //       textAlign: TextAlign.center,
 | 
					 | 
				
			||||||
          //     );
 | 
					 | 
				
			||||||
          //   },
 | 
					 | 
				
			||||||
          // ),
 | 
					 | 
				
			||||||
          Builder(
 | 
					 | 
				
			||||||
            builder: (context) {
 | 
					 | 
				
			||||||
              final data = trainData.status!.delay;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (data == 0) {
 | 
					            if (data == 0) {
 | 
				
			||||||
                return Container();
 | 
					              return Container();
 | 
				
			||||||
              }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (data > 0) {
 | 
					            if (data > 0) {
 | 
				
			||||||
                return Text(
 | 
					              return Text(
 | 
				
			||||||
                  "$data ${data == 1 ? 'minut' : 'minute'} întârziere",
 | 
					                "$data ${data == 1 ? 'minut' : 'minute'} întârziere",
 | 
				
			||||||
                  style:
 | 
					                style:
 | 
				
			||||||
                      CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					                    CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
                            fontSize: 14,
 | 
					                          fontSize: 14,
 | 
				
			||||||
                            color: CupertinoColors.destructiveRed,
 | 
					                          color: CupertinoColors.destructiveRed,
 | 
				
			||||||
                          ),
 | 
					                        ),
 | 
				
			||||||
                );
 | 
					              );
 | 
				
			||||||
              } else {
 | 
					            } else {
 | 
				
			||||||
                return Text(
 | 
					              return Text(
 | 
				
			||||||
                  "${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
 | 
					                "${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
 | 
				
			||||||
                  style:
 | 
					                style:
 | 
				
			||||||
                      CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
					                    CupertinoTheme.of(context).textTheme.textStyle.copyWith(
 | 
				
			||||||
                            fontSize: 12,
 | 
					                          fontSize: 12,
 | 
				
			||||||
                            color: CupertinoColors.systemGreen,
 | 
					                          color: CupertinoColors.systemGreen,
 | 
				
			||||||
                          ),
 | 
					                        ),
 | 
				
			||||||
                );
 | 
					              );
 | 
				
			||||||
              }
 | 
					            }
 | 
				
			||||||
            },
 | 
					          },
 | 
				
			||||||
          )
 | 
					        )
 | 
				
			||||||
        ],
 | 
					      ],
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import 'package:flutter/cupertino.dart';
 | 
					import 'package:flutter/cupertino.dart';
 | 
				
			||||||
import 'package:info_tren/components/badge.dart';
 | 
					import 'package:info_tren/components/badge/badge.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DisplayTrainStation extends StatelessWidget {
 | 
					class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
                    final isOnTime = delay <= 0 && real == true;
 | 
					                    final isOnTime = delay <= 0 && real == true;
 | 
				
			||||||
                    const isNotScheduled = false;
 | 
					                    const isNotScheduled = false;
 | 
				
			||||||
                          
 | 
					                          
 | 
				
			||||||
                    return CupertinoBadge(
 | 
					                    return Badge(
 | 
				
			||||||
                      text: station.km.toString(),
 | 
					                      text: station.km.toString(),
 | 
				
			||||||
                      caption: 'km',
 | 
					                      caption: 'km',
 | 
				
			||||||
                      isNotScheduled: isNotScheduled,
 | 
					                      isNotScheduled: isNotScheduled,
 | 
				
			||||||
| 
						 | 
					@ -65,7 +65,7 @@ class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
              flex: 1,
 | 
					              flex: 1,
 | 
				
			||||||
              child: Align(
 | 
					              child: Align(
 | 
				
			||||||
                alignment: Alignment.centerRight,
 | 
					                alignment: Alignment.centerRight,
 | 
				
			||||||
                child: station.platform == null ? Container() : CupertinoBadge(text: station.platform!, caption: 'linia'),
 | 
					                child: station.platform == null ? Container() : Badge(text: station.platform!, caption: 'linia'),
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										807
									
								
								lib/pages/train_info_page/view_train/train_info_fluent.dart
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										807
									
								
								lib/pages/train_info_page/view_train/train_info_fluent.dart
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,807 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/gestures.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_fluent_DisplayTrainStation.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/utils/state_to_string.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoLoadingFluent extends TrainInfoLoadingShared {
 | 
				
			||||||
 | 
					  TrainInfoLoadingFluent({required super.title, super.loadingText, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					        title: Text(title),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: Center(
 | 
				
			||||||
 | 
					        child: loadingWidget,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoErrorFluent extends TrainInfoErrorShared {
 | 
				
			||||||
 | 
					  const TrainInfoErrorFluent({
 | 
				
			||||||
 | 
					    required super.error,
 | 
				
			||||||
 | 
					    required super.title,
 | 
				
			||||||
 | 
					    super.refresh,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return NavigationView(
 | 
				
			||||||
 | 
					      appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					        title: Text(title),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      content: Center(
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            Text(error.toString()),
 | 
				
			||||||
 | 
					            if (refresh != null)
 | 
				
			||||||
 | 
					              Padding(
 | 
				
			||||||
 | 
					                padding: const EdgeInsets.all(8),
 | 
				
			||||||
 | 
					                child: Button(
 | 
				
			||||||
 | 
					                  child: const Text('Retry'),
 | 
				
			||||||
 | 
					                  onPressed: () => refresh!(),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoFluent extends TrainInfoShared {
 | 
				
			||||||
 | 
					  const TrainInfoFluent({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required super.trainData,
 | 
				
			||||||
 | 
					    super.isRefreshing,
 | 
				
			||||||
 | 
					    super.refresh,
 | 
				
			||||||
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Builder(
 | 
				
			||||||
 | 
					      builder: (context) {
 | 
				
			||||||
 | 
					        return NavigationView(
 | 
				
			||||||
 | 
					          appBar: NavigationAppBar(
 | 
				
			||||||
 | 
					            title: Text(
 | 
				
			||||||
 | 
					              "Informații despre ${trainData.rank} ${trainData.number}",
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            actions: Row(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                if (refresh != null) ...[
 | 
				
			||||||
 | 
					                  Center(
 | 
				
			||||||
 | 
					                    child: SizedBox(
 | 
				
			||||||
 | 
					                      height: 32,
 | 
				
			||||||
 | 
					                      width: 32,
 | 
				
			||||||
 | 
					                      child: IconButton(
 | 
				
			||||||
 | 
					                        icon: isRefreshing == true ? const ProgressRing() : const Icon(
 | 
				
			||||||
 | 
					                          FluentIcons.refresh,
 | 
				
			||||||
 | 
					                          size: 24,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        onPressed: isRefreshing == true ? null : () {
 | 
				
			||||||
 | 
					                          refresh!();
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          content: Column(
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              Expanded(
 | 
				
			||||||
 | 
					                child: SafeArea(
 | 
				
			||||||
 | 
					                  bottom: false,
 | 
				
			||||||
 | 
					                  child: TrainInfoBody(
 | 
				
			||||||
 | 
					                    trainData: trainData,
 | 
				
			||||||
 | 
					                    onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoBodyFluent extends TrainInfoBodyShared {
 | 
				
			||||||
 | 
					  const TrainInfoBodyFluent({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required super.trainData,
 | 
				
			||||||
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    super.refresh,
 | 
				
			||||||
 | 
					    super.isRefreshing,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final mq = MediaQuery.of(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
 | 
				
			||||||
 | 
					      return Row(
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          Container(
 | 
				
			||||||
 | 
					            constraints: const BoxConstraints(
 | 
				
			||||||
 | 
					              minWidth: 400,
 | 
				
			||||||
 | 
					              maxWidth: 400,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            child: Column(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                DisplayTrainID(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainOperator(trainData: trainData),
 | 
				
			||||||
 | 
					                Padding(
 | 
				
			||||||
 | 
					                  padding: const EdgeInsets.symmetric(horizontal: 2.0),
 | 
				
			||||||
 | 
					                  child: DisplayTrainRoute(trainData: trainData),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                DisplayTrainDeparture(trainData: trainData),
 | 
				
			||||||
 | 
					                Padding(
 | 
				
			||||||
 | 
					                  padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                  child: DisplayTrainLastInfo(trainData: trainData),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                IntrinsicHeight(
 | 
				
			||||||
 | 
					                  child: Row(
 | 
				
			||||||
 | 
					                    children: <Widget>[
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: Padding(
 | 
				
			||||||
 | 
					                          padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                          child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                            trainData: trainData,
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: Padding(
 | 
				
			||||||
 | 
					                          padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                          child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                            trainData: trainData,
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                const Divider(),
 | 
				
			||||||
 | 
					                if (onViewYesterdayTrain != null &&
 | 
				
			||||||
 | 
					                    trainData.stations.first.departure!.scheduleTime
 | 
				
			||||||
 | 
					                        .compareTo(DateTime.now()) >
 | 
				
			||||||
 | 
					                        0)
 | 
				
			||||||
 | 
					                  ...[
 | 
				
			||||||
 | 
					                    DisplayTrainYesterdayWarningFluent(
 | 
				
			||||||
 | 
					                      onViewYesterdayTrain!,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    const Divider(),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Expanded(
 | 
				
			||||||
 | 
					            child: CustomScrollView(
 | 
				
			||||||
 | 
					              slivers: [
 | 
				
			||||||
 | 
					                DisplayTrainStations(
 | 
				
			||||||
 | 
					                  trainData: trainData,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                SliverToBoxAdapter(
 | 
				
			||||||
 | 
					                  child: Container(
 | 
				
			||||||
 | 
					                    height: MediaQuery
 | 
				
			||||||
 | 
					                        .of(context)
 | 
				
			||||||
 | 
					                        .viewPadding
 | 
				
			||||||
 | 
					                        .bottom,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return CustomScrollView(
 | 
				
			||||||
 | 
					        slivers: <Widget>[
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainID(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainOperator(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverPadding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.only(left: 2, right: 2),
 | 
				
			||||||
 | 
					            sliver: SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: DisplayTrainRoute(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainDeparture(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainLastInfo(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: IntrinsicHeight(
 | 
				
			||||||
 | 
					              child: Row(
 | 
				
			||||||
 | 
					                children: <Widget>[
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: Padding(
 | 
				
			||||||
 | 
					                      padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                      child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                        trainData: trainData,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: Padding(
 | 
				
			||||||
 | 
					                      padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					                      child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                        trainData: trainData,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          const SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: Divider(),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          if (onViewYesterdayTrain != null &&
 | 
				
			||||||
 | 
					              trainData.stations.first.departure!.scheduleTime
 | 
				
			||||||
 | 
					                  .compareTo(DateTime.now()) >
 | 
				
			||||||
 | 
					                  0) ...[
 | 
				
			||||||
 | 
					            SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: DisplayTrainYesterdayWarningFluent(
 | 
				
			||||||
 | 
					                  onViewYesterdayTrain!),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            const SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: Divider(),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          DisplayTrainStations(
 | 
				
			||||||
 | 
					            trainData: trainData,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: Container(
 | 
				
			||||||
 | 
					              height: MediaQuery
 | 
				
			||||||
 | 
					                  .of(context)
 | 
				
			||||||
 | 
					                  .viewPadding
 | 
				
			||||||
 | 
					                  .bottom,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainID extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainID({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Text.rich(
 | 
				
			||||||
 | 
					      TextSpan(
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          TextSpan(
 | 
				
			||||||
 | 
					            text: trainData.rank,
 | 
				
			||||||
 | 
					            style: TextStyle(
 | 
				
			||||||
 | 
					              color: trainData.rank.startsWith('IR')
 | 
				
			||||||
 | 
					                  ? const Color.fromARGB(255, 255, 0, 0)
 | 
				
			||||||
 | 
					                  : null,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					          TextSpan(
 | 
				
			||||||
 | 
					            text: trainData.number,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      style: FluentTheme.of(context).typography.title?.copyWith(
 | 
				
			||||||
 | 
					        color: FluentTheme.of(context).typography.body?.color,
 | 
				
			||||||
 | 
					        fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainOperator extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainOperator({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Text(
 | 
				
			||||||
 | 
					      trainData.operator,
 | 
				
			||||||
 | 
					      style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					        fontStyle: FontStyle.italic,
 | 
				
			||||||
 | 
					        fontSize: 14,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainRoute extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainRoute({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Row(
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Expanded(
 | 
				
			||||||
 | 
					          child: Center(
 | 
				
			||||||
 | 
					            child: Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					              child: Text(
 | 
				
			||||||
 | 
					                trainData.route.from,
 | 
				
			||||||
 | 
					                style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                  fontSize: 16,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        const Center(child: Text("-")),
 | 
				
			||||||
 | 
					        Expanded(
 | 
				
			||||||
 | 
					          child: Center(
 | 
				
			||||||
 | 
					            child: Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					              child: Text(
 | 
				
			||||||
 | 
					                trainData.route.to,
 | 
				
			||||||
 | 
					                style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                  fontSize: 16,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                textAlign: TextAlign.right,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainDeparture extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainDeparture({required this.trainData, super.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					      child: Text(
 | 
				
			||||||
 | 
					        // "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
 | 
				
			||||||
 | 
					        "Plecare în ${trainData.date}",
 | 
				
			||||||
 | 
					        style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					          fontStyle: FontStyle.italic,
 | 
				
			||||||
 | 
					          fontWeight: FontWeight.w200,
 | 
				
			||||||
 | 
					          fontSize: 16,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainLastInfo extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainLastInfo({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (trainData.status == null) {
 | 
				
			||||||
 | 
					      return Container();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Card(
 | 
				
			||||||
 | 
					      child: Padding(
 | 
				
			||||||
 | 
					        padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					        child: Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Center(
 | 
				
			||||||
 | 
					              child: Padding(
 | 
				
			||||||
 | 
					                padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  "Ultima informație",
 | 
				
			||||||
 | 
					                  style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: 22,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Row(
 | 
				
			||||||
 | 
					              children: <Widget>[
 | 
				
			||||||
 | 
					                Padding(
 | 
				
			||||||
 | 
					                  padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					                  child: Text(
 | 
				
			||||||
 | 
					                    trainData.status!.station,
 | 
				
			||||||
 | 
					                    style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                      fontSize: 18,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    textAlign: TextAlign.left,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Expanded(
 | 
				
			||||||
 | 
					                  child: Container(),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Padding(
 | 
				
			||||||
 | 
					                  padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					                  child: Text(
 | 
				
			||||||
 | 
					                    stateToString(trainData.status!.state),
 | 
				
			||||||
 | 
					                    style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                      fontSize: 18,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    textAlign: TextAlign.right,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Padding(
 | 
				
			||||||
 | 
					              padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					              child: Row(
 | 
				
			||||||
 | 
					                children: <Widget>[
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: Container(),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Builder(
 | 
				
			||||||
 | 
					                    builder: (context) {
 | 
				
			||||||
 | 
					                      final data = trainData.status!.delay;
 | 
				
			||||||
 | 
					                      if (data == 0) {
 | 
				
			||||||
 | 
					                        return Container();
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                      if (data > 0) {
 | 
				
			||||||
 | 
					                        return Text(
 | 
				
			||||||
 | 
					                          "$data ${data == 1 ? 'minut' : 'minute'} întârziere",
 | 
				
			||||||
 | 
					                          style:
 | 
				
			||||||
 | 
					                          FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                            fontSize: 16,
 | 
				
			||||||
 | 
					                            color: Colors.red.lighter,
 | 
				
			||||||
 | 
					                            // color: Colors.red.shade300,
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      } else {
 | 
				
			||||||
 | 
					                        return Text(
 | 
				
			||||||
 | 
					                          "${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
 | 
				
			||||||
 | 
					                          style:
 | 
				
			||||||
 | 
					                          FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                            fontSize: 16,
 | 
				
			||||||
 | 
					                            color: Colors.green.lighter,
 | 
				
			||||||
 | 
					                            // color: Colors.green.shade300,
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        );
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainDestination extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainDestination({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final destination = trainData.stations.last;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Card(
 | 
				
			||||||
 | 
					      child: Center(
 | 
				
			||||||
 | 
					        child: Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              Padding(
 | 
				
			||||||
 | 
					                padding: const EdgeInsets.all(4),
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  "Destinația",
 | 
				
			||||||
 | 
					                  style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: 22,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Padding(
 | 
				
			||||||
 | 
					                padding: const EdgeInsets.fromLTRB(4, 0, 4, 0),
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  destination.name,
 | 
				
			||||||
 | 
					                  style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                    fontSize: 20,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.w500,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Builder(
 | 
				
			||||||
 | 
					                builder: (context) {
 | 
				
			||||||
 | 
					                  final arrival = destination.arrival!.scheduleTime.toLocal();
 | 
				
			||||||
 | 
					                  final delay =
 | 
				
			||||||
 | 
					                      trainData.stations.last.arrival!.status?.delay ?? 0;
 | 
				
			||||||
 | 
					                  final arrivalWithDelay =
 | 
				
			||||||
 | 
					                  arrival.add(Duration(minutes: delay));
 | 
				
			||||||
 | 
					                  final arrivalWithDelayString =
 | 
				
			||||||
 | 
					                      '${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
 | 
				
			||||||
 | 
					                  // const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  return Column(
 | 
				
			||||||
 | 
					                    mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					                    children: <Widget>[
 | 
				
			||||||
 | 
					                      // Text(
 | 
				
			||||||
 | 
					                      //   "în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}",
 | 
				
			||||||
 | 
					                      //   style: Theme.of(context).textTheme.bodyText2?.copyWith(
 | 
				
			||||||
 | 
					                      //     fontSize: isSmallScreen(context) ? 12 : 14,
 | 
				
			||||||
 | 
					                      //   ),
 | 
				
			||||||
 | 
					                      //   textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                      // ),
 | 
				
			||||||
 | 
					                      Text.rich(
 | 
				
			||||||
 | 
					                        TextSpan(
 | 
				
			||||||
 | 
					                          text: 'la',
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					                            TextSpan(
 | 
				
			||||||
 | 
					                              text:
 | 
				
			||||||
 | 
					                              '${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
 | 
				
			||||||
 | 
					                              style: delay == 0
 | 
				
			||||||
 | 
					                                  ? null
 | 
				
			||||||
 | 
					                                  : const TextStyle(
 | 
				
			||||||
 | 
					                                decoration: TextDecoration.lineThrough,
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            if (delay != 0) ...[
 | 
				
			||||||
 | 
					                              const TextSpan(text: ' '),
 | 
				
			||||||
 | 
					                              TextSpan(
 | 
				
			||||||
 | 
					                                text: arrivalWithDelayString,
 | 
				
			||||||
 | 
					                                style: TextStyle(
 | 
				
			||||||
 | 
					                                  color: delay > 0
 | 
				
			||||||
 | 
					                                      ? Colors.red.lighter
 | 
				
			||||||
 | 
					                                      : Colors.green.lighter,
 | 
				
			||||||
 | 
					                                  // color: delay > 0
 | 
				
			||||||
 | 
					                                  //     ? Colors.red.shade300
 | 
				
			||||||
 | 
					                                  //     : Colors.green.shade300,
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ]
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                          fontSize: 16,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainRouteDistance extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainRouteDistance({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Card(
 | 
				
			||||||
 | 
					      child: Center(
 | 
				
			||||||
 | 
					        child: Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              Text(
 | 
				
			||||||
 | 
					                "Distanța rutei",
 | 
				
			||||||
 | 
					                style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                  fontSize: 22,
 | 
				
			||||||
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Text(
 | 
				
			||||||
 | 
					                "${trainData.stations.last.km} km",
 | 
				
			||||||
 | 
					                style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                  fontSize: 20,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainRouteDuration extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainRouteDuration({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Card(
 | 
				
			||||||
 | 
					      child: Center(
 | 
				
			||||||
 | 
					        child: Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					          child: Column(
 | 
				
			||||||
 | 
					            mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					            children: <Widget>[
 | 
				
			||||||
 | 
					              Text(
 | 
				
			||||||
 | 
					                "Durata rutei",
 | 
				
			||||||
 | 
					                style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                  fontSize: 22,
 | 
				
			||||||
 | 
					                  fontWeight: FontWeight.bold,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              Builder(
 | 
				
			||||||
 | 
					                builder: (context) {
 | 
				
			||||||
 | 
					                  var duration = trainData.stations.last.arrival!.scheduleTime
 | 
				
			||||||
 | 
					                      .difference(
 | 
				
			||||||
 | 
					                      trainData.stations.first.departure!.scheduleTime);
 | 
				
			||||||
 | 
					                  var durationString = StringBuffer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  bool firstWritten = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  if (duration.inDays > 0) {
 | 
				
			||||||
 | 
					                    firstWritten = true;
 | 
				
			||||||
 | 
					                    if (duration.inDays == 1) {
 | 
				
			||||||
 | 
					                      durationString.write("1 zi");
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                      durationString.write("${duration.inDays} zile");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    duration -= Duration(days: duration.inDays);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  if (duration.inHours > 0) {
 | 
				
			||||||
 | 
					                    if (firstWritten) {
 | 
				
			||||||
 | 
					                      durationString.write(", ");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    firstWritten = true;
 | 
				
			||||||
 | 
					                    if (duration.inHours == 1) {
 | 
				
			||||||
 | 
					                      durationString.write("1 oră");
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                      durationString.write("${duration.inHours} ore");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    duration -= Duration(hours: duration.inHours);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  if (duration.inMinutes > 0) {
 | 
				
			||||||
 | 
					                    if (firstWritten) {
 | 
				
			||||||
 | 
					                      durationString.write(", ");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    firstWritten = true;
 | 
				
			||||||
 | 
					                    if (duration.inMinutes == 1) {
 | 
				
			||||||
 | 
					                      durationString.write("1 minut");
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                      durationString.write("${duration.inMinutes} minute");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    duration -= Duration(minutes: duration.inMinutes);
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  return Text(
 | 
				
			||||||
 | 
					                    durationString.toString(),
 | 
				
			||||||
 | 
					                    style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                      fontSize: 20,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainYesterdayWarningFluent
 | 
				
			||||||
 | 
					    extends DisplayTrainYesterdayWarningCommon {
 | 
				
			||||||
 | 
					  const DisplayTrainYesterdayWarningFluent(super.onViewYesterdayTrain, {super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Column(
 | 
				
			||||||
 | 
					      mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					      children: [
 | 
				
			||||||
 | 
					        Padding(
 | 
				
			||||||
 | 
					          padding: const EdgeInsets.all(8.0),
 | 
				
			||||||
 | 
					          child: Text.rich(
 | 
				
			||||||
 | 
					            TextSpan(
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                const TextSpan(
 | 
				
			||||||
 | 
					                  text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                const TextSpan(text: '\n'),
 | 
				
			||||||
 | 
					                TextSpan(
 | 
				
			||||||
 | 
					                  text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
 | 
				
			||||||
 | 
					                  style: TextStyle(
 | 
				
			||||||
 | 
					                    color: Colors.blue,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  recognizer: TapGestureRecognizer()
 | 
				
			||||||
 | 
					                    ..onTap = onViewYesterdayTrain,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainStations extends StatelessWidget {
 | 
				
			||||||
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					  const DisplayTrainStations({required this.trainData, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return SliverList(
 | 
				
			||||||
 | 
					      delegate: SliverChildBuilderDelegate(
 | 
				
			||||||
 | 
					            (context, index) {
 | 
				
			||||||
 | 
					          return IndexedSemantics(
 | 
				
			||||||
 | 
					            index: index,
 | 
				
			||||||
 | 
					            child: DisplayTrainStation(
 | 
				
			||||||
 | 
					              station: trainData.stations[index],
 | 
				
			||||||
 | 
					              onTap: () {
 | 
				
			||||||
 | 
					                Navigator.of(context).pushNamed(
 | 
				
			||||||
 | 
					                  ViewStationPage.routeName,
 | 
				
			||||||
 | 
					                  arguments: ViewStationArguments(stationName: trainData.stations[index].name),
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        childCount: trainData.stations.length,
 | 
				
			||||||
 | 
					        addSemanticIndexes: true,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,447 @@
 | 
				
			||||||
 | 
					import 'package:fluent_ui/fluent_ui.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/components/badge/badge.dart';
 | 
				
			||||||
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					  final void Function()? onTap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DisplayTrainStation({required this.station, this.onTap, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					      child: HoverButton(
 | 
				
			||||||
 | 
					        onPressed: onTap,
 | 
				
			||||||
 | 
					        builder: (context, states) {
 | 
				
			||||||
 | 
					          return Card(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.all(2),
 | 
				
			||||||
 | 
					            child: Column(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					              crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					              children: <Widget>[
 | 
				
			||||||
 | 
					                Row(
 | 
				
			||||||
 | 
					                  mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					                  children: <Widget>[
 | 
				
			||||||
 | 
					                    Expanded(
 | 
				
			||||||
 | 
					                      flex: 1,
 | 
				
			||||||
 | 
					                      child: Align(
 | 
				
			||||||
 | 
					                        alignment: Alignment.centerLeft,
 | 
				
			||||||
 | 
					                        child: Builder(
 | 
				
			||||||
 | 
					                            builder: (context) {
 | 
				
			||||||
 | 
					                              final departureStatus = station.departure?.status;
 | 
				
			||||||
 | 
					                              final arrivalStatus = station.arrival?.status;
 | 
				
			||||||
 | 
					                              int delay;
 | 
				
			||||||
 | 
					                              bool real;
 | 
				
			||||||
 | 
					                              if (departureStatus == null) {
 | 
				
			||||||
 | 
					                                delay = arrivalStatus?.delay ?? 0;
 | 
				
			||||||
 | 
					                                real = arrivalStatus?.real ?? false;
 | 
				
			||||||
 | 
					                              }
 | 
				
			||||||
 | 
					                              else if (arrivalStatus == null) {
 | 
				
			||||||
 | 
					                                delay = departureStatus.delay;
 | 
				
			||||||
 | 
					                                real = departureStatus.real;
 | 
				
			||||||
 | 
					                              }
 | 
				
			||||||
 | 
					                              else {
 | 
				
			||||||
 | 
					                                delay = departureStatus.delay;
 | 
				
			||||||
 | 
					                                real = departureStatus.real;
 | 
				
			||||||
 | 
					                                if (!real && arrivalStatus.real) {
 | 
				
			||||||
 | 
					                                  delay = arrivalStatus.delay;
 | 
				
			||||||
 | 
					                                  real = arrivalStatus.real;
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                              final isDelayed = delay > 0 && real == true;
 | 
				
			||||||
 | 
					                              final isOnTime = delay <= 0 && real == true;
 | 
				
			||||||
 | 
					                              const isNotScheduled = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                              return Badge(
 | 
				
			||||||
 | 
					                                text: station.km.toString(),
 | 
				
			||||||
 | 
					                                caption: 'km',
 | 
				
			||||||
 | 
					                                isNotScheduled: isNotScheduled,
 | 
				
			||||||
 | 
					                                isDelayed: isDelayed,
 | 
				
			||||||
 | 
					                                isOnTime: isOnTime,
 | 
				
			||||||
 | 
					                              );
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    Title(
 | 
				
			||||||
 | 
					                      station: station,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    Expanded(
 | 
				
			||||||
 | 
					                      flex: 1,
 | 
				
			||||||
 | 
					                      child: (station.platform == null)
 | 
				
			||||||
 | 
					                          ? Container()
 | 
				
			||||||
 | 
					                          : Align(
 | 
				
			||||||
 | 
					                        alignment: Alignment.centerRight,
 | 
				
			||||||
 | 
					                        child: Badge(text: station.platform!, caption: 'linia',),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Time(
 | 
				
			||||||
 | 
					                  station: station,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Delay(
 | 
				
			||||||
 | 
					                  station: station,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Title extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Title({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return  Text(
 | 
				
			||||||
 | 
					      station.name,
 | 
				
			||||||
 | 
					      style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					        fontSize: 22,
 | 
				
			||||||
 | 
					        fontWeight: MediaQuery.of(context).boldText ? FontWeight.w500 : FontWeight.w300,
 | 
				
			||||||
 | 
					        // fontStyle: items[1] == "ONI" ? FontStyle.italic : FontStyle.normal,
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					      textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Time extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Time({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (station.arrival == null) {
 | 
				
			||||||
 | 
					      // Plecare
 | 
				
			||||||
 | 
					      return DepartureTime(
 | 
				
			||||||
 | 
					        station: station,
 | 
				
			||||||
 | 
					        firstStation: true,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (station.departure == null) {
 | 
				
			||||||
 | 
					      // Sosire
 | 
				
			||||||
 | 
					      return ArrivalTime(
 | 
				
			||||||
 | 
					        station: station,
 | 
				
			||||||
 | 
					        finalStation: true,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Row(
 | 
				
			||||||
 | 
					      crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        Text(
 | 
				
			||||||
 | 
					          "→",
 | 
				
			||||||
 | 
					          style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					            fontSize: 22,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        Container(width: 2,),
 | 
				
			||||||
 | 
					        ArrivalTime(station: station,),
 | 
				
			||||||
 | 
					        Expanded(child: Container(),),
 | 
				
			||||||
 | 
					        StopTime(station: station,),
 | 
				
			||||||
 | 
					        Expanded(child: Container(),),
 | 
				
			||||||
 | 
					        DepartureTime(station: station,),
 | 
				
			||||||
 | 
					        Container(width: 2,),
 | 
				
			||||||
 | 
					        Text(
 | 
				
			||||||
 | 
					          "→",
 | 
				
			||||||
 | 
					          style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					            fontSize: 22,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ArrivalTime extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					  final bool finalStation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ArrivalTime({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    this.finalStation = false,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (station.arrival == null) {
 | 
				
			||||||
 | 
					      return Container();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (finalStation) {
 | 
				
			||||||
 | 
					      return Row(
 | 
				
			||||||
 | 
					        crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          Text(
 | 
				
			||||||
 | 
					            "→",
 | 
				
			||||||
 | 
					            style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					              fontSize: 22,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Container(width: 2,),
 | 
				
			||||||
 | 
					          const Text("sosire la "),
 | 
				
			||||||
 | 
					          ArrivalTime(station: station,),
 | 
				
			||||||
 | 
					          Expanded(child: Container(),),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      final delay = station.arrival!.status?.delay ?? 0;
 | 
				
			||||||
 | 
					      final time = station.arrival!.scheduleTime.toLocal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (delay == 0) {
 | 
				
			||||||
 | 
					        return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else if (delay > 0) {
 | 
				
			||||||
 | 
					        final oldDate = time;
 | 
				
			||||||
 | 
					        final newDate = oldDate.add(Duration(minutes: delay));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                decoration: TextDecoration.lineThrough,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                // color: Colors.red.shade300,
 | 
				
			||||||
 | 
					                color: Colors.red.lighter,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        final oldDate = time;
 | 
				
			||||||
 | 
					        final newDate = oldDate.add(Duration(minutes: delay));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                decoration: TextDecoration.lineThrough,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                // color: Colors.green.shade300,
 | 
				
			||||||
 | 
					                color: Colors.green.lighter,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StopTime extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const StopTime({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Column(
 | 
				
			||||||
 | 
					      mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					      children: <Widget>[
 | 
				
			||||||
 | 
					        const Text(
 | 
				
			||||||
 | 
					          "staționează pentru",
 | 
				
			||||||
 | 
					          textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        Builder(
 | 
				
			||||||
 | 
					          builder: (context) {
 | 
				
			||||||
 | 
					            int stopsForInt = station.stoppingTime!;
 | 
				
			||||||
 | 
					            bool minutes = false;
 | 
				
			||||||
 | 
					            if (stopsForInt >= 60) {
 | 
				
			||||||
 | 
					              stopsForInt ~/= 60;
 | 
				
			||||||
 | 
					              minutes = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (stopsForInt == 1) {
 | 
				
			||||||
 | 
					              return Text(
 | 
				
			||||||
 | 
					                "1 ${minutes ? 'minut' : 'secundă'}",
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (stopsForInt < 20) {
 | 
				
			||||||
 | 
					              return Text(
 | 
				
			||||||
 | 
					                "$stopsForInt ${minutes ? 'minute' : 'secunde'}",
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					              return Text(
 | 
				
			||||||
 | 
					                "$stopsForInt de ${minutes ? 'minute' : 'secunde'}",
 | 
				
			||||||
 | 
					                textAlign: TextAlign.center,
 | 
				
			||||||
 | 
					              );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DepartureTime extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					  final bool firstStation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const DepartureTime({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    this.firstStation = false,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (station.departure == null) {
 | 
				
			||||||
 | 
					      return Container();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (firstStation) {
 | 
				
			||||||
 | 
					      return Row(
 | 
				
			||||||
 | 
					        crossAxisAlignment: CrossAxisAlignment.center,
 | 
				
			||||||
 | 
					        children: <Widget>[
 | 
				
			||||||
 | 
					          Expanded(child: Container(),),
 | 
				
			||||||
 | 
					          const Text("plecare la "),
 | 
				
			||||||
 | 
					          DepartureTime(station: station,),
 | 
				
			||||||
 | 
					          Container(width: 2,),
 | 
				
			||||||
 | 
					          Text(
 | 
				
			||||||
 | 
					            "→",
 | 
				
			||||||
 | 
					            style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					              fontSize: 22,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      final delay = station.departure!.status?.delay ?? 0;
 | 
				
			||||||
 | 
					      final time = station.departure!.scheduleTime.toLocal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (delay == 0) {
 | 
				
			||||||
 | 
					        return Text("${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else if (delay > 0) {
 | 
				
			||||||
 | 
					        final oldDate = time;
 | 
				
			||||||
 | 
					        final newDate = oldDate.add(Duration(minutes: delay));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                decoration: TextDecoration.lineThrough,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                // color: Colors.red.shade300,
 | 
				
			||||||
 | 
					                color: Colors.red.lighter,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      else {
 | 
				
			||||||
 | 
					        final oldDate = time;
 | 
				
			||||||
 | 
					        final newDate = oldDate.add(Duration(minutes: delay));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return Column(
 | 
				
			||||||
 | 
					          mainAxisSize: MainAxisSize.min,
 | 
				
			||||||
 | 
					          children: <Widget>[
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${oldDate.hour.toString().padLeft(2, '0')}:${oldDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                decoration: TextDecoration.lineThrough,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					              "${newDate.hour.toString().padLeft(2, '0')}:${newDate.minute.toString().padLeft(2, '0')}",
 | 
				
			||||||
 | 
					              style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					                // color: Colors.green.shade300,
 | 
				
			||||||
 | 
					                color: Colors.green.lighter,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Delay extends StatelessWidget {
 | 
				
			||||||
 | 
					  final Station station;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const Delay({
 | 
				
			||||||
 | 
					    required this.station,
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (station.arrival?.status == null && station.departure?.status == null) {
 | 
				
			||||||
 | 
					      return Container();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var delay = station.arrival?.status?.delay;
 | 
				
			||||||
 | 
					    if (station.departure?.status?.real == true) {
 | 
				
			||||||
 | 
					      delay = station.departure?.status?.delay;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (delay == 0 || delay == null) {
 | 
				
			||||||
 | 
					      return Container();
 | 
				
			||||||
 | 
					    } else if (delay > 0) {
 | 
				
			||||||
 | 
					      return Text(
 | 
				
			||||||
 | 
					        "$delay ${delay == 1 ? 'minut' : 'minute'} întârziere",
 | 
				
			||||||
 | 
					        style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					          // color: Colors.red.shade300,
 | 
				
			||||||
 | 
					          color: Colors.red.lighter,
 | 
				
			||||||
 | 
					          fontSize: 14,
 | 
				
			||||||
 | 
					          fontStyle: FontStyle.italic,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (delay < 0) {
 | 
				
			||||||
 | 
					      return Text(
 | 
				
			||||||
 | 
					        "${-delay} ${delay == -1 ? 'minut' : 'minute'} mai devreme",
 | 
				
			||||||
 | 
					        style: FluentTheme.of(context).typography.body?.copyWith(
 | 
				
			||||||
 | 
					          // color: Colors.green.shade300,
 | 
				
			||||||
 | 
					          color: Colors.green.lighter,
 | 
				
			||||||
 | 
					          fontSize: 14,
 | 
				
			||||||
 | 
					          fontStyle: FontStyle.italic,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Container();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
 | 
				
			||||||
import 'package:info_tren/utils/state_to_string.dart';
 | 
					import 'package:info_tren/utils/state_to_string.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoLoadingMaterial extends TrainInfoLoading {
 | 
					class TrainInfoLoadingMaterial extends TrainInfoLoadingShared {
 | 
				
			||||||
  TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
 | 
					  TrainInfoLoadingMaterial({required super.title, super.loadingText, super.key,});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ class TrainInfoLoadingMaterial extends TrainInfoLoading {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoErrorMaterial extends TrainInfoError {
 | 
					class TrainInfoErrorMaterial extends TrainInfoErrorShared {
 | 
				
			||||||
  const TrainInfoErrorMaterial({
 | 
					  const TrainInfoErrorMaterial({
 | 
				
			||||||
    required super.error,
 | 
					    required super.error,
 | 
				
			||||||
    required super.title,
 | 
					    required super.title,
 | 
				
			||||||
| 
						 | 
					@ -61,15 +61,12 @@ class TrainInfoErrorMaterial extends TrainInfoError {
 | 
				
			||||||
bool isSmallScreen(BuildContext context) =>
 | 
					bool isSmallScreen(BuildContext context) =>
 | 
				
			||||||
    MediaQuery.of(context).size.height <= 425;
 | 
					    MediaQuery.of(context).size.height <= 425;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TrainInfoMaterial extends StatelessWidget {
 | 
					class TrainInfoMaterial extends TrainInfoShared {
 | 
				
			||||||
  final TrainData trainData;
 | 
					 | 
				
			||||||
  final Future Function()? refresh;
 | 
					 | 
				
			||||||
  final void Function()? onViewYesterdayTrain;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const TrainInfoMaterial({
 | 
					  const TrainInfoMaterial({
 | 
				
			||||||
    required this.trainData,
 | 
					    required super.trainData,
 | 
				
			||||||
    this.refresh,
 | 
					    super.refresh,
 | 
				
			||||||
    this.onViewYesterdayTrain,
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    super.isRefreshing,
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,12 +76,13 @@ class TrainInfoMaterial extends StatelessWidget {
 | 
				
			||||||
      builder: (context) {
 | 
					      builder: (context) {
 | 
				
			||||||
        return Scaffold(
 | 
					        return Scaffold(
 | 
				
			||||||
          appBar: isSmallScreen(context)
 | 
					          appBar: isSmallScreen(context)
 | 
				
			||||||
              ? null
 | 
					            ? null
 | 
				
			||||||
              : AppBar(
 | 
					            : AppBar(
 | 
				
			||||||
                  centerTitle: true,
 | 
					                centerTitle: true,
 | 
				
			||||||
                  title: Text(
 | 
					                title: Text(
 | 
				
			||||||
                      "Informații despre ${trainData.rank} ${trainData.number}"),
 | 
					                  "Informații despre ${trainData.rank} ${trainData.number}",
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
          body: Column(
 | 
					          body: Column(
 | 
				
			||||||
            children: <Widget>[
 | 
					            children: <Widget>[
 | 
				
			||||||
              if (isSmallScreen(context))
 | 
					              if (isSmallScreen(context))
 | 
				
			||||||
| 
						 | 
					@ -93,8 +91,8 @@ class TrainInfoMaterial extends StatelessWidget {
 | 
				
			||||||
                  left: false,
 | 
					                  left: false,
 | 
				
			||||||
                  right: false,
 | 
					                  right: false,
 | 
				
			||||||
                  child: SlimAppBar(
 | 
					                  child: SlimAppBar(
 | 
				
			||||||
                      title:
 | 
					                    title: 'INFO TREN - ${trainData.rank} ${trainData.number}',
 | 
				
			||||||
                          'INFO TREN - ${trainData.rank} ${trainData.number}'),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
              Expanded(
 | 
					              Expanded(
 | 
				
			||||||
                child: SafeArea(
 | 
					                child: SafeArea(
 | 
				
			||||||
| 
						 | 
					@ -102,102 +100,9 @@ class TrainInfoMaterial extends StatelessWidget {
 | 
				
			||||||
                  top: isSmallScreen(context) ? false : true,
 | 
					                  top: isSmallScreen(context) ? false : true,
 | 
				
			||||||
                  child: RefreshIndicator(
 | 
					                  child: RefreshIndicator(
 | 
				
			||||||
                    onRefresh: refresh ?? () async {},
 | 
					                    onRefresh: refresh ?? () async {},
 | 
				
			||||||
                    child: CustomScrollView(
 | 
					                    child: TrainInfoBody(
 | 
				
			||||||
                      slivers: <Widget>[
 | 
					                      trainData: trainData,
 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					                      onViewYesterdayTrain: onViewYesterdayTrain,
 | 
				
			||||||
                          child: DisplayTrainID(
 | 
					 | 
				
			||||||
                            trainData: trainData,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: DisplayTrainOperator(
 | 
					 | 
				
			||||||
                            trainData: trainData,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        SliverPadding(
 | 
					 | 
				
			||||||
                          padding: const EdgeInsets.only(left: 2, right: 2),
 | 
					 | 
				
			||||||
                          sliver: SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                            child: DisplayTrainRoute(
 | 
					 | 
				
			||||||
                              trainData: trainData,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: DisplayTrainDeparture(
 | 
					 | 
				
			||||||
                            trainData: trainData,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        // SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                        //   child: Divider(
 | 
					 | 
				
			||||||
                        //     color: Colors.white70,
 | 
					 | 
				
			||||||
                        //     height: isSmallScreen(context) ? 8 : 16,
 | 
					 | 
				
			||||||
                        //   ),
 | 
					 | 
				
			||||||
                        // ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: DisplayTrainLastInfo(
 | 
					 | 
				
			||||||
                            trainData: trainData,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: IntrinsicHeight(
 | 
					 | 
				
			||||||
                            child: Row(
 | 
					 | 
				
			||||||
                              children: <Widget>[
 | 
					 | 
				
			||||||
                                // Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
 | 
					 | 
				
			||||||
                                // Expanded(child: DisplayTrainDestination(trainData: trainData,)),
 | 
					 | 
				
			||||||
                                Expanded(
 | 
					 | 
				
			||||||
                                    child: DisplayTrainRouteDuration(
 | 
					 | 
				
			||||||
                                  trainData: trainData,
 | 
					 | 
				
			||||||
                                )),
 | 
					 | 
				
			||||||
                                Expanded(
 | 
					 | 
				
			||||||
                                  child: DisplayTrainRouteDistance(
 | 
					 | 
				
			||||||
                                    trainData: trainData,
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ],
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        // SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                        //   child: IntrinsicHeight(
 | 
					 | 
				
			||||||
                        //     child: Row(
 | 
					 | 
				
			||||||
                        //       children: <Widget>[
 | 
					 | 
				
			||||||
                        //         // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
 | 
					 | 
				
			||||||
                        //         Expanded(child: Container(),),
 | 
					 | 
				
			||||||
                        //         Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
 | 
					 | 
				
			||||||
                        //       ],
 | 
					 | 
				
			||||||
                        //     ),
 | 
					 | 
				
			||||||
                        //   ),
 | 
					 | 
				
			||||||
                        // ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: Divider(
 | 
					 | 
				
			||||||
                            color: Colors.white70,
 | 
					 | 
				
			||||||
                            height: isSmallScreen(context) ? 8 : 16,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        if (onViewYesterdayTrain != null &&
 | 
					 | 
				
			||||||
                            trainData.stations.first.departure!.scheduleTime
 | 
					 | 
				
			||||||
                                    .compareTo(DateTime.now()) >
 | 
					 | 
				
			||||||
                                0) ...[
 | 
					 | 
				
			||||||
                          SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                            child: DisplayTrainYesterdayWarningMaterial(
 | 
					 | 
				
			||||||
                                onViewYesterdayTrain!),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                            child: Divider(
 | 
					 | 
				
			||||||
                              color: Colors.white70,
 | 
					 | 
				
			||||||
                              height: isSmallScreen(context) ? 8 : 16,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ],
 | 
					 | 
				
			||||||
                        DisplayTrainStations(
 | 
					 | 
				
			||||||
                          trainData: trainData,
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        SliverToBoxAdapter(
 | 
					 | 
				
			||||||
                          child: Container(
 | 
					 | 
				
			||||||
                            height: MediaQuery.of(context).viewPadding.bottom,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      ],
 | 
					 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
| 
						 | 
					@ -210,6 +115,201 @@ class TrainInfoMaterial extends StatelessWidget {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TrainInfoBodyMaterial extends TrainInfoBodyShared {
 | 
				
			||||||
 | 
					  const TrainInfoBodyMaterial({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required super.trainData,
 | 
				
			||||||
 | 
					    super.onViewYesterdayTrain,
 | 
				
			||||||
 | 
					    super.isRefreshing,
 | 
				
			||||||
 | 
					    super.refresh,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    final mq = MediaQuery.of(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (mq.orientation == Orientation.landscape && mq.size.width >= 1000) {
 | 
				
			||||||
 | 
					      return Row(
 | 
				
			||||||
 | 
					        mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          Container(
 | 
				
			||||||
 | 
					            constraints: const BoxConstraints(
 | 
				
			||||||
 | 
					              minWidth: 400,
 | 
				
			||||||
 | 
					              maxWidth: 400,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            child: Column(
 | 
				
			||||||
 | 
					              mainAxisSize: MainAxisSize.max,
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                DisplayTrainID(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainOperator(trainData: trainData),
 | 
				
			||||||
 | 
					                Padding(
 | 
				
			||||||
 | 
					                  padding: const EdgeInsets.symmetric(horizontal: 2.0),
 | 
				
			||||||
 | 
					                  child: DisplayTrainRoute(trainData: trainData),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                DisplayTrainDeparture(trainData: trainData),
 | 
				
			||||||
 | 
					                DisplayTrainLastInfo(trainData: trainData),
 | 
				
			||||||
 | 
					                IntrinsicHeight(
 | 
				
			||||||
 | 
					                  child: Row(
 | 
				
			||||||
 | 
					                    children: <Widget>[
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                          trainData: trainData,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                      Expanded(
 | 
				
			||||||
 | 
					                        child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                          trainData: trainData,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Divider(
 | 
				
			||||||
 | 
					                  color: Colors.white70,
 | 
				
			||||||
 | 
					                  height: isSmallScreen(context) ? 8 : 16,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                if (onViewYesterdayTrain != null &&
 | 
				
			||||||
 | 
					                    trainData.stations.first.departure!.scheduleTime
 | 
				
			||||||
 | 
					                            .compareTo(DateTime.now()) >
 | 
				
			||||||
 | 
					                        0)
 | 
				
			||||||
 | 
					                  ...[
 | 
				
			||||||
 | 
					                    DisplayTrainYesterdayWarningMaterial(
 | 
				
			||||||
 | 
					                      onViewYesterdayTrain!,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    Divider(
 | 
				
			||||||
 | 
					                      color: Colors.white70,
 | 
				
			||||||
 | 
					                      height: isSmallScreen(context) ? 8 : 16,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Expanded(
 | 
				
			||||||
 | 
					            child: CustomScrollView(
 | 
				
			||||||
 | 
					              slivers: [
 | 
				
			||||||
 | 
					                DisplayTrainStations(
 | 
				
			||||||
 | 
					                  trainData: trainData,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                SliverToBoxAdapter(
 | 
				
			||||||
 | 
					                  child: Container(
 | 
				
			||||||
 | 
					                    height: MediaQuery
 | 
				
			||||||
 | 
					                        .of(context)
 | 
				
			||||||
 | 
					                        .viewPadding
 | 
				
			||||||
 | 
					                        .bottom,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					      return CustomScrollView(
 | 
				
			||||||
 | 
					        slivers: <Widget>[
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainID(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainOperator(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverPadding(
 | 
				
			||||||
 | 
					            padding: const EdgeInsets.only(left: 2, right: 2),
 | 
				
			||||||
 | 
					            sliver: SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: DisplayTrainRoute(
 | 
				
			||||||
 | 
					                trainData: trainData,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainDeparture(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          // SliverToBoxAdapter(
 | 
				
			||||||
 | 
					          //   child: Divider(
 | 
				
			||||||
 | 
					          //     color: Colors.white70,
 | 
				
			||||||
 | 
					          //     height: isSmallScreen(context) ? 8 : 16,
 | 
				
			||||||
 | 
					          //   ),
 | 
				
			||||||
 | 
					          // ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: DisplayTrainLastInfo(
 | 
				
			||||||
 | 
					              trainData: trainData,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: IntrinsicHeight(
 | 
				
			||||||
 | 
					              child: Row(
 | 
				
			||||||
 | 
					                children: <Widget>[
 | 
				
			||||||
 | 
					                  // Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
 | 
				
			||||||
 | 
					                  // Expanded(child: DisplayTrainDestination(trainData: trainData,)),
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: DisplayTrainRouteDuration(
 | 
				
			||||||
 | 
					                      trainData: trainData,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  Expanded(
 | 
				
			||||||
 | 
					                    child: DisplayTrainRouteDistance(
 | 
				
			||||||
 | 
					                      trainData: trainData,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          // SliverToBoxAdapter(
 | 
				
			||||||
 | 
					          //   child: IntrinsicHeight(
 | 
				
			||||||
 | 
					          //     child: Row(
 | 
				
			||||||
 | 
					          //       children: <Widget>[
 | 
				
			||||||
 | 
					          //         // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
 | 
				
			||||||
 | 
					          //         Expanded(child: Container(),),
 | 
				
			||||||
 | 
					          //         Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
 | 
				
			||||||
 | 
					          //       ],
 | 
				
			||||||
 | 
					          //     ),
 | 
				
			||||||
 | 
					          //   ),
 | 
				
			||||||
 | 
					          // ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: Divider(
 | 
				
			||||||
 | 
					              color: Colors.white70,
 | 
				
			||||||
 | 
					              height: isSmallScreen(context) ? 8 : 16,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          if (onViewYesterdayTrain != null &&
 | 
				
			||||||
 | 
					              trainData.stations.first.departure!.scheduleTime
 | 
				
			||||||
 | 
					                  .compareTo(DateTime.now()) >
 | 
				
			||||||
 | 
					                  0) ...[
 | 
				
			||||||
 | 
					            SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: DisplayTrainYesterdayWarningMaterial(
 | 
				
			||||||
 | 
					                  onViewYesterdayTrain!),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            SliverToBoxAdapter(
 | 
				
			||||||
 | 
					              child: Divider(
 | 
				
			||||||
 | 
					                color: Colors.white70,
 | 
				
			||||||
 | 
					                height: isSmallScreen(context) ? 8 : 16,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          DisplayTrainStations(
 | 
				
			||||||
 | 
					            trainData: trainData,
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          SliverToBoxAdapter(
 | 
				
			||||||
 | 
					            child: Container(
 | 
				
			||||||
 | 
					              height: MediaQuery
 | 
				
			||||||
 | 
					                  .of(context)
 | 
				
			||||||
 | 
					                  .viewPadding
 | 
				
			||||||
 | 
					                  .bottom,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DisplayTrainID extends StatelessWidget {
 | 
					class DisplayTrainID extends StatelessWidget {
 | 
				
			||||||
  final TrainData trainData;
 | 
					  final TrainData trainData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -798,7 +898,7 @@ class DisplayTrainStations extends StatelessWidget {
 | 
				
			||||||
              onTap: () {
 | 
					              onTap: () {
 | 
				
			||||||
                Navigator.of(context).pushNamed(
 | 
					                Navigator.of(context).pushNamed(
 | 
				
			||||||
                  ViewStationPage.routeName,
 | 
					                  ViewStationPage.routeName,
 | 
				
			||||||
                  arguments: trainData.stations[index].name,
 | 
					                  arguments: ViewStationArguments(stationName: trainData.stations[index].name),
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:info_tren/models.dart';
 | 
					import 'package:info_tren/models.dart';
 | 
				
			||||||
import 'package:info_tren/components/badge.dart';
 | 
					import 'package:info_tren/components/badge/badge.dart';
 | 
				
			||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
					import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DisplayTrainStation extends StatelessWidget {
 | 
					class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,7 @@ class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
                          final isOnTime = delay <= 0 && real == true;
 | 
					                          final isOnTime = delay <= 0 && real == true;
 | 
				
			||||||
                          const isNotScheduled = false;
 | 
					                          const isNotScheduled = false;
 | 
				
			||||||
                                    
 | 
					                                    
 | 
				
			||||||
                          return MaterialBadge(
 | 
					                          return Badge(
 | 
				
			||||||
                            text: station.km.toString(),
 | 
					                            text: station.km.toString(),
 | 
				
			||||||
                            caption: 'km',
 | 
					                            caption: 'km',
 | 
				
			||||||
                            isNotScheduled: isNotScheduled,
 | 
					                            isNotScheduled: isNotScheduled,
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ class DisplayTrainStation extends StatelessWidget {
 | 
				
			||||||
                      ? Container() 
 | 
					                      ? Container() 
 | 
				
			||||||
                      : Align(
 | 
					                      : Align(
 | 
				
			||||||
                        alignment: Alignment.centerRight,
 | 
					                        alignment: Alignment.centerRight,
 | 
				
			||||||
                        child: MaterialBadge(text: station.platform!, caption: 'linia',),
 | 
					                        child: Badge(text: station.platform!, caption: 'linia',),
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,9 @@ UiDesign get defaultUiDesign {
 | 
				
			||||||
  if (Platform.isIOS) {
 | 
					  if (Platform.isIOS) {
 | 
				
			||||||
    return UiDesign.CUPERTINO;
 | 
					    return UiDesign.CUPERTINO;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  else if (Platform.isLinux || Platform.isWindows) {
 | 
				
			||||||
 | 
					    return UiDesign.FLUENT;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  else {
 | 
					  else {
 | 
				
			||||||
    return UiDesign.MATERIAL;
 | 
					    return UiDesign.MATERIAL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										44
									
								
								pubspec.lock
									
										
									
									
									
								
							
							
						
						
									
										44
									
								
								pubspec.lock
									
										
									
									
									
								
							| 
						 | 
					@ -99,6 +99,13 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.0.1"
 | 
					    version: "2.0.1"
 | 
				
			||||||
 | 
					  clock:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: clock
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "1.1.1"
 | 
				
			||||||
  code_builder:
 | 
					  code_builder:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -162,6 +169,13 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.0.1"
 | 
					    version: "1.0.1"
 | 
				
			||||||
 | 
					  fluent_ui:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: fluent_ui
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "4.0.3+1"
 | 
				
			||||||
  flutter:
 | 
					  flutter:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description: flutter
 | 
					    description: flutter
 | 
				
			||||||
| 
						 | 
					@ -181,6 +195,11 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.0.1"
 | 
					    version: "2.0.1"
 | 
				
			||||||
 | 
					  flutter_localizations:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description: flutter
 | 
				
			||||||
 | 
					    source: sdk
 | 
				
			||||||
 | 
					    version: "0.0.0"
 | 
				
			||||||
  flutter_riverpod:
 | 
					  flutter_riverpod:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -256,6 +275,13 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "4.0.2"
 | 
					    version: "4.0.2"
 | 
				
			||||||
 | 
					  intl:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: intl
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.17.0"
 | 
				
			||||||
  io:
 | 
					  io:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -311,7 +337,7 @@ packages:
 | 
				
			||||||
      name: material_color_utilities
 | 
					      name: material_color_utilities
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "0.2.0"
 | 
					    version: "0.1.5"
 | 
				
			||||||
  meta:
 | 
					  meta:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -424,6 +450,13 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "3.1.0"
 | 
					    version: "3.1.0"
 | 
				
			||||||
 | 
					  recase:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: recase
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "4.1.0"
 | 
				
			||||||
  riverpod:
 | 
					  riverpod:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -431,6 +464,13 @@ packages:
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.0.2"
 | 
					    version: "2.0.2"
 | 
				
			||||||
 | 
					  scroll_pos:
 | 
				
			||||||
 | 
					    dependency: transitive
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: scroll_pos
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "0.3.0"
 | 
				
			||||||
  shared_preferences:
 | 
					  shared_preferences:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					@ -659,7 +699,7 @@ packages:
 | 
				
			||||||
      name: vector_math
 | 
					      name: vector_math
 | 
				
			||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.1.4"
 | 
					    version: "2.1.2"
 | 
				
			||||||
  watcher:
 | 
					  watcher:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
 | 
				
			||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 | 
					# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 | 
				
			||||||
# Read more about iOS versioning at
 | 
					# Read more about iOS versioning at
 | 
				
			||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
					# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
				
			||||||
version: 2.7.8
 | 
					version: 2.7.9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: ">=2.17.0 <3.0.0"
 | 
					  sdk: ">=2.17.0 <3.0.0"
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@ dependencies:
 | 
				
			||||||
  freezed_annotation: ^2.2.0
 | 
					  freezed_annotation: ^2.2.0
 | 
				
			||||||
  json_annotation: ^4.7.0
 | 
					  json_annotation: ^4.7.0
 | 
				
			||||||
  shared_preferences: ^2.0.15
 | 
					  shared_preferences: ^2.0.15
 | 
				
			||||||
 | 
					  fluent_ui: ^4.0.3+1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  # flutter_test:
 | 
					  # flutter_test:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue