[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(
|
||||
labelText: 'Password',
|
||||
),
|
||||
FTextInput(
|
||||
labelText: 'Password',
|
||||
controller: passwordController,
|
||||
onFieldSubmitted: (_) => _login(),
|
||||
autofillHints: const [AutofillHints.password],
|
||||
obscureText: true,
|
||||
),
|
||||
FButton(
|
||||
labelText: 'Sign In',
|
||||
onPressed: _login,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: FilledButton(
|
||||
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!,
|
||||
apiClient: widget.apiClient,
|
||||
refreshParent: _asyncInitState),
|
||||
);
|
||||
title = Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: Text(
|
||||
"🅵🅾🅾🅳🅴🆁",
|
||||
style: logoStyle(context),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
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,
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
} 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(
|
||||
labelText: 'Password',
|
||||
),
|
||||
FTextInput(
|
||||
labelText: 'Password',
|
||||
controller: passwordController,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
obscureText: true,
|
||||
),
|
||||
FTextInput(
|
||||
labelText: 'Confirm password',
|
||||
controller: passwordConfirmController,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
onFieldSubmitted: (_) => _register(),
|
||||
obscureText: true,
|
||||
),
|
||||
FButton(
|
||||
labelText: 'Register account',
|
||||
onPressed: _register,
|
||||
),
|
||||
TextFormField(
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Confirm password',
|
||||
),
|
||||
controller: passwordConfirmController,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
onFieldSubmitted: (_) => _register()),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: FilledButton(
|
||||
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