[UI craze] begin implementing new UI
This commit is contained in:
		
							parent
							
								
									34786d5de3
								
							
						
					
					
						commit
						90fad4a0ac
					
				
					 13 changed files with 474 additions and 153 deletions
				
			
		
							
								
								
									
										22
									
								
								lib/components/appBar.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lib/components/appBar.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class FAppBar extends StatelessWidget implements PreferredSizeWidget {
 | 
			
		||||
  const FAppBar({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: EdgeInsets.symmetric(horizontal: 8),
 | 
			
		||||
      child: AppBar(
 | 
			
		||||
        backgroundColor: Colors.transparent,
 | 
			
		||||
        elevation: 0,
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Size get preferredSize => Size.fromHeight(56);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								lib/components/button.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								lib/components/button.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class FButton extends StatelessWidget {
 | 
			
		||||
  final String labelText;
 | 
			
		||||
  final double padding;
 | 
			
		||||
  final double insidePadding;
 | 
			
		||||
  final double fontSize;
 | 
			
		||||
  final Function()? onPressed;
 | 
			
		||||
 | 
			
		||||
  const FButton({super.key, required this.labelText, this.padding = 8, this.insidePadding = 24, this.fontSize = 20, this.onPressed});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: onPressed,
 | 
			
		||||
      child: Padding(
 | 
			
		||||
        padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
 | 
			
		||||
        child: Container(
 | 
			
		||||
          padding: EdgeInsets.symmetric(vertical: insidePadding),
 | 
			
		||||
          decoration: BoxDecoration(
 | 
			
		||||
            color: colorScheme.primary,
 | 
			
		||||
            borderRadius: BorderRadius.circular(4),
 | 
			
		||||
          ),
 | 
			
		||||
          child: Center(
 | 
			
		||||
            child: Text(
 | 
			
		||||
              labelText,
 | 
			
		||||
              style: theme.textTheme.button!.copyWith(
 | 
			
		||||
                fontWeight: FontWeight.bold,
 | 
			
		||||
                fontSize: fontSize,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										135
									
								
								lib/components/datePicker.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								lib/components/datePicker.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,135 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FDateItemWidget extends StatelessWidget {
 | 
			
		||||
  final DateTime date;
 | 
			
		||||
  final bool picked;
 | 
			
		||||
  final Function(DateTime) onDatePicked;
 | 
			
		||||
 | 
			
		||||
  const FDateItemWidget({super.key, required this.date, required this.onDatePicked, this.picked = false});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    var dayOfTheWeekMap = {
 | 
			
		||||
      1: 'Mon',
 | 
			
		||||
      2: 'Tue',
 | 
			
		||||
      3: 'Wed',
 | 
			
		||||
      4: 'Thu',
 | 
			
		||||
      5: 'Fri',
 | 
			
		||||
      6: 'Sat',
 | 
			
		||||
      7: 'Sun',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return GestureDetector(
 | 
			
		||||
      onTap: () {
 | 
			
		||||
        onDatePicked(date);
 | 
			
		||||
      },
 | 
			
		||||
      child: Container(
 | 
			
		||||
        width: 100,
 | 
			
		||||
        decoration: BoxDecoration(
 | 
			
		||||
          borderRadius: BorderRadius.circular(50),
 | 
			
		||||
          border: Border.all(
 | 
			
		||||
            color: colorScheme.onPrimary,
 | 
			
		||||
            width: 2,
 | 
			
		||||
          ),
 | 
			
		||||
          color: picked ? colorScheme.onPrimary.withOpacity(0.25) : Colors.transparent,
 | 
			
		||||
        ),
 | 
			
		||||
        child: Column(
 | 
			
		||||
          mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
          children: <Widget>[
 | 
			
		||||
            Text(
 | 
			
		||||
              dayOfTheWeekMap[date.weekday]!,
 | 
			
		||||
              style: TextStyle(
 | 
			
		||||
                color: colorScheme.onPrimary,
 | 
			
		||||
                fontSize: 24,
 | 
			
		||||
                fontWeight: FontWeight.bold,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
            Text(
 | 
			
		||||
              '${date.day}.${date.month}',
 | 
			
		||||
              style: TextStyle(
 | 
			
		||||
                color: colorScheme.onPrimary,
 | 
			
		||||
                fontSize: 24,
 | 
			
		||||
                fontWeight: FontWeight.bold,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FDatePickerWidget extends StatefulWidget {
 | 
			
		||||
  final DateTime date;
 | 
			
		||||
  final Function(DateTime) onDatePicked;
 | 
			
		||||
 | 
			
		||||
  const FDatePickerWidget({super.key, required this.date, required this.onDatePicked});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  State<FDatePickerWidget> createState() => _FDatePickerWidgetState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _FDatePickerWidgetState extends State<FDatePickerWidget> {
 | 
			
		||||
  DateTime date = DateTime.now();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    super.initState();
 | 
			
		||||
    setState(() {
 | 
			
		||||
      date = widget.date;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<void> onDatePicked(DateTime date) async {
 | 
			
		||||
    setState(() {
 | 
			
		||||
      this.date = date;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    await widget.onDatePicked(date);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return SizedBox(
 | 
			
		||||
      height: 100,
 | 
			
		||||
      child: Center(
 | 
			
		||||
        child: ListView(
 | 
			
		||||
          scrollDirection: Axis.horizontal,
 | 
			
		||||
          shrinkWrap: true,
 | 
			
		||||
          children: <Widget>[
 | 
			
		||||
            SizedBox(width: 25),
 | 
			
		||||
            FDateItemWidget(date: date.add(Duration(days: -2)), onDatePicked: onDatePicked),
 | 
			
		||||
            SizedBox(width: 25),
 | 
			
		||||
            FDateItemWidget(date: date.add(Duration(days: -1)), onDatePicked: onDatePicked),
 | 
			
		||||
            SizedBox(width: 25),
 | 
			
		||||
            FDateItemWidget(date: date, onDatePicked: onDatePicked, picked: true),
 | 
			
		||||
            SizedBox(width: 25),
 | 
			
		||||
            FDateItemWidget(date: date.add(Duration(days: 1)), onDatePicked: onDatePicked),
 | 
			
		||||
            SizedBox(width: 25),
 | 
			
		||||
            FDateItemWidget(date: date.add(Duration(days: 2)), onDatePicked: onDatePicked),
 | 
			
		||||
            Container(
 | 
			
		||||
              width: 100,
 | 
			
		||||
              child: IconButton(
 | 
			
		||||
                icon: Icon(
 | 
			
		||||
                  Icons.calendar_month,
 | 
			
		||||
                  color: colorScheme.onPrimary,
 | 
			
		||||
                  size: 40,
 | 
			
		||||
                ),
 | 
			
		||||
                onPressed: () {
 | 
			
		||||
                  onDatePicked(date.add(Duration(days: 1)));
 | 
			
		||||
                },
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										99
									
								
								lib/components/sliver.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								lib/components/sliver.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,99 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class BackgroundWave extends StatelessWidget {
 | 
			
		||||
  final double height;
 | 
			
		||||
 | 
			
		||||
  const BackgroundWave({Key? key, required this.height}) : super(key: key);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return SizedBox(
 | 
			
		||||
      height: height,
 | 
			
		||||
      child: ClipPath(
 | 
			
		||||
          clipper: BackgroundWaveClipper(),
 | 
			
		||||
          child: Container(
 | 
			
		||||
            width: MediaQuery.of(context).size.width,
 | 
			
		||||
            height: height,
 | 
			
		||||
            decoration: BoxDecoration(
 | 
			
		||||
                gradient: LinearGradient(
 | 
			
		||||
              colors: [colorScheme.primary, colorScheme.secondary],
 | 
			
		||||
            )),
 | 
			
		||||
          )),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BackgroundWaveClipper extends CustomClipper<Path> {
 | 
			
		||||
  @override
 | 
			
		||||
  Path getClip(Size size) {
 | 
			
		||||
    var path = Path();
 | 
			
		||||
    path.lineTo(0.0, size.height);
 | 
			
		||||
 | 
			
		||||
    var firstCurve = Offset(0, size.height - 20);
 | 
			
		||||
    var lastCurve = Offset(30, size.height - 20);
 | 
			
		||||
 | 
			
		||||
    path.quadraticBezierTo(
 | 
			
		||||
        firstCurve.dx, firstCurve.dy, lastCurve.dx, lastCurve.dy,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    firstCurve = Offset(0, size.height - 20);
 | 
			
		||||
    lastCurve = Offset(size.width - 30, size.height - 20);
 | 
			
		||||
 | 
			
		||||
    path.quadraticBezierTo(
 | 
			
		||||
        firstCurve.dx, firstCurve.dy, lastCurve.dx, lastCurve.dy,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    firstCurve = Offset(size.width, size.height - 20);
 | 
			
		||||
    lastCurve = Offset(size.width, size.height);
 | 
			
		||||
 | 
			
		||||
    path.quadraticBezierTo(
 | 
			
		||||
        firstCurve.dx, firstCurve.dy, lastCurve.dx, lastCurve.dy,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    path.lineTo(size.width, 0.0);
 | 
			
		||||
    path.close();
 | 
			
		||||
 | 
			
		||||
    return path;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool shouldReclip(BackgroundWaveClipper oldClipper) => oldClipper != this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FSliverAppBar extends SliverPersistentHeaderDelegate {
 | 
			
		||||
  final Widget child;
 | 
			
		||||
  const FSliverAppBar({required this.child});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
 | 
			
		||||
    var adjustedShrinkOffset = shrinkOffset > minExtent ? minExtent : shrinkOffset;
 | 
			
		||||
    double offset = (minExtent - adjustedShrinkOffset);
 | 
			
		||||
 | 
			
		||||
    return Stack(
 | 
			
		||||
      children: [
 | 
			
		||||
        const BackgroundWave(
 | 
			
		||||
          height: 280,
 | 
			
		||||
        ),
 | 
			
		||||
        Positioned(
 | 
			
		||||
          top: offset + 8,
 | 
			
		||||
          child: child,
 | 
			
		||||
          left: 16,
 | 
			
		||||
          right: 16,
 | 
			
		||||
        )
 | 
			
		||||
      ],
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  double get maxExtent => 280;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  double get minExtent => 140;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) =>
 | 
			
		||||
      oldDelegate.maxExtent != maxExtent || oldDelegate.minExtent != minExtent;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								lib/components/text.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								lib/components/text.dart
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
class FTextInput extends StatelessWidget {
 | 
			
		||||
  final String labelText;
 | 
			
		||||
  final double padding;
 | 
			
		||||
  final TextEditingController controller;
 | 
			
		||||
  final List<String>? autofillHints;
 | 
			
		||||
  final bool autofocus;
 | 
			
		||||
  final bool obscureText;
 | 
			
		||||
  final Function(String)? onFieldSubmitted;
 | 
			
		||||
 | 
			
		||||
  const FTextInput({super.key, required this.labelText, this.padding = 8, required this.controller, this.autofillHints, this.autofocus = false, this.onFieldSubmitted, this.obscureText = false});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return Padding(
 | 
			
		||||
      padding: EdgeInsets.symmetric(vertical: padding, horizontal: padding),
 | 
			
		||||
      child: TextFormField(
 | 
			
		||||
        obscureText: obscureText,
 | 
			
		||||
        decoration: InputDecoration(
 | 
			
		||||
          labelText: labelText,
 | 
			
		||||
          enabledBorder: OutlineInputBorder(
 | 
			
		||||
            borderSide: BorderSide(color: colorScheme.primary),
 | 
			
		||||
          ),
 | 
			
		||||
          focusedBorder: OutlineInputBorder(
 | 
			
		||||
            borderSide: BorderSide(color: colorScheme.onPrimary),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        controller: controller,
 | 
			
		||||
        autofillHints: autofillHints,
 | 
			
		||||
        autofocus: autofocus,
 | 
			
		||||
        onFieldSubmitted: onFieldSubmitted,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:fooder/screens/login.dart';
 | 
			
		||||
import 'package:fooder/client.dart';
 | 
			
		||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
 | 
			
		||||
 | 
			
		||||
class MyApp extends StatelessWidget {
 | 
			
		||||
  const MyApp({super.key});
 | 
			
		||||
| 
						 | 
				
			
			@ -9,13 +10,10 @@ class MyApp extends StatelessWidget {
 | 
			
		|||
  Widget build(BuildContext context) {
 | 
			
		||||
    return MaterialApp(
 | 
			
		||||
      title: 'FOODER',
 | 
			
		||||
      theme: ThemeData(
 | 
			
		||||
        colorScheme: ColorScheme.fromSeed(
 | 
			
		||||
          seedColor: Colors.blueGrey,
 | 
			
		||||
          brightness: Brightness.dark,
 | 
			
		||||
        ),
 | 
			
		||||
        useMaterial3: true,
 | 
			
		||||
      ),
 | 
			
		||||
      theme: FlexThemeData.light(scheme: FlexScheme.brandBlue),
 | 
			
		||||
      darkTheme: FlexThemeData.dark(scheme: FlexScheme.brandBlue),
 | 
			
		||||
      themeMode: ThemeMode.system,
 | 
			
		||||
      debugShowCheckedModeBanner: false,
 | 
			
		||||
      home: LoginScreen(
 | 
			
		||||
        apiClient: ApiClient(
 | 
			
		||||
          baseUrl: 'https://fooderapi.domandoman.xyz/api',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ import 'package:fooder/models/meal.dart';
 | 
			
		|||
import 'package:fooder/widgets/product.dart';
 | 
			
		||||
import 'package:fooder/screens/add_product.dart';
 | 
			
		||||
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
 | 
			
		||||
import 'package:fooder/components/appBar.dart';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AddEntryScreen extends BasedScreen {
 | 
			
		||||
  final Diary diary;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,10 +128,8 @@ class _AddEntryScreen extends State<AddEntryScreen> {
 | 
			
		|||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
			
		||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
			
		||||
      ),
 | 
			
		||||
      extendBodyBehindAppBar: true,
 | 
			
		||||
      appBar: FAppBar(),
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: Container(
 | 
			
		||||
            constraints: const BoxConstraints(maxWidth: 720),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,5 +11,36 @@ abstract class BasedScreen extends StatefulWidget {
 | 
			
		|||
  final ApiClient apiClient;
 | 
			
		||||
 | 
			
		||||
  const BasedScreen({super.key, required this.apiClient});
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
abstract class BasedState<T extends BasedScreen> extends State<T> {
 | 
			
		||||
  void showError(String message) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(
 | 
			
		||||
          message,
 | 
			
		||||
          textAlign: TextAlign.center,
 | 
			
		||||
          style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
			
		||||
            fontWeight: FontWeight.bold,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showText(String text) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(
 | 
			
		||||
          text,
 | 
			
		||||
          textAlign: TextAlign.center,
 | 
			
		||||
          style: Theme.of(context).textTheme.bodyLarge!.copyWith(
 | 
			
		||||
            fontWeight: FontWeight.bold,
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.primary,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ import 'package:flutter/services.dart';
 | 
			
		|||
import 'package:fooder/screens/based.dart';
 | 
			
		||||
import 'package:fooder/screens/main.dart';
 | 
			
		||||
import 'package:fooder/screens/register.dart';
 | 
			
		||||
import 'package:fooder/components/text.dart';
 | 
			
		||||
import 'package:fooder/components/button.dart';
 | 
			
		||||
 | 
			
		||||
class LoginScreen extends BasedScreen {
 | 
			
		||||
  const LoginScreen({super.key, required super.apiClient});
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +13,7 @@ class LoginScreen extends BasedScreen {
 | 
			
		|||
  State<LoginScreen> createState() => _LoginScreen();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _LoginScreen extends State<LoginScreen> {
 | 
			
		||||
class _LoginScreen extends BasedState<LoginScreen> {
 | 
			
		||||
  final usernameController = TextEditingController();
 | 
			
		||||
  final passwordController = TextEditingController();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -22,24 +24,6 @@ class _LoginScreen extends State<LoginScreen> {
 | 
			
		|||
    super.dispose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showError(String message) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(message, textAlign: TextAlign.center),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showText(String text) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(text, textAlign: TextAlign.center),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.primary,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void popMeDaddy() {
 | 
			
		||||
    Navigator.pushReplacement(
 | 
			
		||||
      context,
 | 
			
		||||
| 
						 | 
				
			
			@ -95,11 +79,10 @@ class _LoginScreen extends State<LoginScreen> {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
			
		||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
			
		||||
      ),
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: Container(
 | 
			
		||||
          constraints: const BoxConstraints(maxWidth: 600),
 | 
			
		||||
| 
						 | 
				
			
			@ -108,32 +91,30 @@ class _LoginScreen extends State<LoginScreen> {
 | 
			
		|||
            child: Column(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
              children: <Widget>[
 | 
			
		||||
                TextFormField(
 | 
			
		||||
                  decoration: const InputDecoration(
 | 
			
		||||
                    labelText: 'Username',
 | 
			
		||||
                Icon(
 | 
			
		||||
                  Icons.lock,
 | 
			
		||||
                  size: 100,
 | 
			
		||||
                  color: colorScheme.primary,
 | 
			
		||||
                ),
 | 
			
		||||
                FTextInput(
 | 
			
		||||
                  labelText: 'Username',
 | 
			
		||||
                  controller: usernameController,
 | 
			
		||||
                  autofillHints: const [AutofillHints.username],
 | 
			
		||||
                  autofocus: true,
 | 
			
		||||
                ),
 | 
			
		||||
                TextFormField(
 | 
			
		||||
                  obscureText: true,
 | 
			
		||||
                  decoration: const InputDecoration(
 | 
			
		||||
                FTextInput(
 | 
			
		||||
                  labelText: 'Password',
 | 
			
		||||
                  ),
 | 
			
		||||
                  controller: passwordController,
 | 
			
		||||
                  onFieldSubmitted: (_) => _login(),
 | 
			
		||||
                  autofillHints: const [AutofillHints.password],
 | 
			
		||||
                  obscureText: true,
 | 
			
		||||
                ),
 | 
			
		||||
                Padding(
 | 
			
		||||
                  padding: const EdgeInsets.symmetric(vertical: 10),
 | 
			
		||||
                  child: FilledButton(
 | 
			
		||||
                FButton(
 | 
			
		||||
                  labelText: 'Sign In',
 | 
			
		||||
                  onPressed: _login,
 | 
			
		||||
                    child: const Text('Login'),
 | 
			
		||||
                  ),
 | 
			
		||||
                ),
 | 
			
		||||
                Padding(
 | 
			
		||||
                  padding: const EdgeInsets.symmetric(vertical: 10),
 | 
			
		||||
                  padding: const EdgeInsets.symmetric(vertical: 8),
 | 
			
		||||
                  child: TextButton(
 | 
			
		||||
                    onPressed: () {
 | 
			
		||||
                      Navigator.push(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,10 @@ import 'package:fooder/screens/login.dart';
 | 
			
		|||
import 'package:fooder/screens/add_entry.dart';
 | 
			
		||||
import 'package:fooder/models/diary.dart';
 | 
			
		||||
import 'package:fooder/widgets/diary.dart';
 | 
			
		||||
import 'package:fooder/widgets/meal.dart';
 | 
			
		||||
import 'package:fooder/components/appBar.dart';
 | 
			
		||||
import 'package:fooder/components/sliver.dart';
 | 
			
		||||
import 'package:fooder/components/datePicker.dart';
 | 
			
		||||
 | 
			
		||||
class MainScreen extends BasedScreen {
 | 
			
		||||
  const MainScreen({super.key, required super.apiClient});
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +16,7 @@ class MainScreen extends BasedScreen {
 | 
			
		|||
  State<MainScreen> createState() => _MainScreen();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _MainScreen extends State<MainScreen> {
 | 
			
		||||
class _MainScreen extends BasedState<MainScreen> {
 | 
			
		||||
  Diary? diary;
 | 
			
		||||
  DateTime date = DateTime.now();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,19 +28,18 @@ class _MainScreen extends State<MainScreen> {
 | 
			
		|||
 | 
			
		||||
  Future<void> _asyncInitState() async {
 | 
			
		||||
    var diaryMap = await widget.apiClient.getDiary(date: date);
 | 
			
		||||
 | 
			
		||||
    setState(() {
 | 
			
		||||
      diary = Diary.fromJson(diaryMap);
 | 
			
		||||
      date = date;
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<void> _pickDate() async {
 | 
			
		||||
    date = (await showDatePicker(
 | 
			
		||||
      context: context,
 | 
			
		||||
      initialDate: date,
 | 
			
		||||
      firstDate: DateTime(2020),
 | 
			
		||||
      lastDate: DateTime(DateTime.now().year + 1),
 | 
			
		||||
    ))!;
 | 
			
		||||
  Future<void> _pickDate(DateTime date) async {
 | 
			
		||||
    setState(() {
 | 
			
		||||
      this.date = date;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    await _asyncInitState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -66,60 +69,34 @@ class _MainScreen extends State<MainScreen> {
 | 
			
		|||
    Widget title;
 | 
			
		||||
 | 
			
		||||
    if (diary != null) {
 | 
			
		||||
      content = Container(
 | 
			
		||||
        constraints: const BoxConstraints(maxWidth: 720),
 | 
			
		||||
        padding: const EdgeInsets.all(10),
 | 
			
		||||
        child: DiaryWidget(
 | 
			
		||||
            diary: diary!,
 | 
			
		||||
      content = CustomScrollView(
 | 
			
		||||
        slivers: <Widget>[
 | 
			
		||||
          SliverPersistentHeader(
 | 
			
		||||
            delegate: FSliverAppBar(child: FDatePickerWidget(date: date, onDatePicked: _pickDate)),
 | 
			
		||||
            pinned: true,
 | 
			
		||||
          ),
 | 
			
		||||
          SliverList(
 | 
			
		||||
            delegate: SliverChildListDelegate(
 | 
			
		||||
              [
 | 
			
		||||
                for (var meal in diary!.meals)
 | 
			
		||||
                  MealWidget(
 | 
			
		||||
                    meal: meal,
 | 
			
		||||
                    apiClient: widget.apiClient,
 | 
			
		||||
            refreshParent: _asyncInitState),
 | 
			
		||||
      );
 | 
			
		||||
      title = Row(
 | 
			
		||||
        mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          TextButton(
 | 
			
		||||
            child: Text(
 | 
			
		||||
              "🅵🅾🅾🅳🅴🆁",
 | 
			
		||||
              style: logoStyle(context),
 | 
			
		||||
            ),
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              Navigator.pushReplacement(
 | 
			
		||||
                context,
 | 
			
		||||
                MaterialPageRoute(
 | 
			
		||||
                    builder: (context) =>
 | 
			
		||||
                        MainScreen(apiClient: widget.apiClient)),
 | 
			
		||||
              ).then((_) => _asyncInitState());
 | 
			
		||||
            },
 | 
			
		||||
          ),
 | 
			
		||||
          const Spacer(),
 | 
			
		||||
          Text(
 | 
			
		||||
            "${date.year}-${date.month}-${date.day}",
 | 
			
		||||
            style: const TextStyle(fontSize: 20),
 | 
			
		||||
          ),
 | 
			
		||||
          IconButton(
 | 
			
		||||
            icon: const Icon(Icons.calendar_month),
 | 
			
		||||
            onPressed: _pickDate,
 | 
			
		||||
          ),
 | 
			
		||||
          const Spacer(),
 | 
			
		||||
          IconButton(
 | 
			
		||||
            icon: const Icon(Icons.logout),
 | 
			
		||||
            onPressed: _logout,
 | 
			
		||||
                    refreshParent: _asyncInitState,
 | 
			
		||||
                  ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ]
 | 
			
		||||
      );
 | 
			
		||||
    } else {
 | 
			
		||||
      content = const CircularProgressIndicator();
 | 
			
		||||
      title = Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context));
 | 
			
		||||
      content = const Center(child: const CircularProgressIndicator());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
			
		||||
        title: title,
 | 
			
		||||
      ),
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: content,
 | 
			
		||||
      ),
 | 
			
		||||
      body: content,
 | 
			
		||||
      extendBodyBehindAppBar: true,
 | 
			
		||||
      appBar: FAppBar(),
 | 
			
		||||
      floatingActionButton: FloatingActionButton(
 | 
			
		||||
        onPressed: _addEntry,
 | 
			
		||||
        child: const Icon(Icons.add),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:fooder/screens/based.dart';
 | 
			
		||||
import 'package:fooder/components/text.dart';
 | 
			
		||||
import 'package:fooder/components/button.dart';
 | 
			
		||||
 | 
			
		||||
class RegisterScreen extends BasedScreen {
 | 
			
		||||
  const RegisterScreen({super.key, required super.apiClient});
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +11,7 @@ class RegisterScreen extends BasedScreen {
 | 
			
		|||
  State<RegisterScreen> createState() => _RegisterScreen();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _RegisterScreen extends State<RegisterScreen> {
 | 
			
		||||
class _RegisterScreen extends BasedState<RegisterScreen> {
 | 
			
		||||
  final usernameController = TextEditingController();
 | 
			
		||||
  final passwordController = TextEditingController();
 | 
			
		||||
  final passwordConfirmController = TextEditingController();
 | 
			
		||||
| 
						 | 
				
			
			@ -35,24 +37,6 @@ class _RegisterScreen extends State<RegisterScreen> {
 | 
			
		|||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showError(String message) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(message, textAlign: TextAlign.center),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.error,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void showText(String text) {
 | 
			
		||||
    ScaffoldMessenger.of(context).showSnackBar(
 | 
			
		||||
      SnackBar(
 | 
			
		||||
        content: Text(text, textAlign: TextAlign.center),
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.primary,
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void popMeDaddy() {
 | 
			
		||||
    Navigator.pop(context);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -78,11 +62,10 @@ class _RegisterScreen extends State<RegisterScreen> {
 | 
			
		|||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var theme = Theme.of(context);
 | 
			
		||||
    var colorScheme = theme.colorScheme;
 | 
			
		||||
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
 | 
			
		||||
        title: Text("🅵🅾🅾🅳🅴🆁", style: logoStyle(context)),
 | 
			
		||||
      ),
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: Container(
 | 
			
		||||
          constraints: const BoxConstraints(maxWidth: 600),
 | 
			
		||||
| 
						 | 
				
			
			@ -91,35 +74,34 @@ class _RegisterScreen extends State<RegisterScreen> {
 | 
			
		|||
            child: Column(
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
              children: <Widget>[
 | 
			
		||||
                TextFormField(
 | 
			
		||||
                  decoration: const InputDecoration(
 | 
			
		||||
                    labelText: 'Username',
 | 
			
		||||
                Icon(
 | 
			
		||||
                  Icons.group_add,
 | 
			
		||||
                  size: 100,
 | 
			
		||||
                  color: colorScheme.primary,
 | 
			
		||||
                ),
 | 
			
		||||
                FTextInput(
 | 
			
		||||
                  labelText: 'Username',
 | 
			
		||||
                  controller: usernameController,
 | 
			
		||||
                  autofillHints: const [AutofillHints.username],
 | 
			
		||||
                  autofocus: true,
 | 
			
		||||
                ),
 | 
			
		||||
                TextFormField(
 | 
			
		||||
                  obscureText: true,
 | 
			
		||||
                  decoration: const InputDecoration(
 | 
			
		||||
                FTextInput(
 | 
			
		||||
                  labelText: 'Password',
 | 
			
		||||
                  ),
 | 
			
		||||
                  controller: passwordController,
 | 
			
		||||
                  autofillHints: const [AutofillHints.password],
 | 
			
		||||
                ),
 | 
			
		||||
                TextFormField(
 | 
			
		||||
                  obscureText: true,
 | 
			
		||||
                    decoration: const InputDecoration(
 | 
			
		||||
                      labelText: 'Confirm password',
 | 
			
		||||
                ),
 | 
			
		||||
                FTextInput(
 | 
			
		||||
                  labelText: 'Confirm password',
 | 
			
		||||
                  controller: passwordConfirmController,
 | 
			
		||||
                  autofillHints: const [AutofillHints.password],
 | 
			
		||||
                    onFieldSubmitted: (_) => _register()),
 | 
			
		||||
                Padding(
 | 
			
		||||
                    padding: const EdgeInsets.symmetric(vertical: 10),
 | 
			
		||||
                    child: FilledButton(
 | 
			
		||||
                  onFieldSubmitted: (_) => _register(),
 | 
			
		||||
                  obscureText: true,
 | 
			
		||||
                ),
 | 
			
		||||
                FButton(
 | 
			
		||||
                  labelText: 'Register account',
 | 
			
		||||
                  onPressed: _register,
 | 
			
		||||
                      child: const Text('Register'),
 | 
			
		||||
                    )),
 | 
			
		||||
                ),
 | 
			
		||||
              ],
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								pubspec.lock
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -65,6 +65,22 @@ packages:
 | 
			
		|||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.2"
 | 
			
		||||
  flex_color_scheme:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_color_scheme
 | 
			
		||||
      sha256: "32914024a4f404d90ff449f58d279191675b28e7c08824046baf06826e99d984"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.3.1"
 | 
			
		||||
  flex_seed_scheme:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_seed_scheme
 | 
			
		||||
      sha256: "29c12aba221eb8a368a119685371381f8035011d18de5ba277ad11d7dfb8657f"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.4.0"
 | 
			
		||||
  flutter:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description: flutter
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,6 +39,7 @@ dependencies:
 | 
			
		|||
  intl: ^0.19.0
 | 
			
		||||
  flutter_secure_storage: ^9.0.0
 | 
			
		||||
  simple_barcode_scanner: ^0.1.1
 | 
			
		||||
  flex_color_scheme: ^7.3.1
 | 
			
		||||
 | 
			
		||||
dev_dependencies:
 | 
			
		||||
  flutter_test:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue