Skip to content

Commit 99510a5

Browse files
committed
add UI of authentication
1 parent 2421912 commit 99510a5

File tree

5 files changed

+259
-9
lines changed

5 files changed

+259
-9
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import 'package:flutter/material.dart';
2+
3+
import 'widgets/inverted_color_button.dart';
4+
import 'widgets/label_text_field.dart';
5+
6+
class AuthenticationScreen extends StatefulWidget {
7+
const AuthenticationScreen({Key? key}) : super(key: key);
8+
9+
@override
10+
_AuthenticationScreenState createState() => _AuthenticationScreenState();
11+
}
12+
13+
class _AuthenticationScreenState extends State<AuthenticationScreen> {
14+
bool isLogin = true, enableButton = false;
15+
16+
late final TextEditingController _nameController = TextEditingController();
17+
late final TextEditingController _emailController = TextEditingController();
18+
late final TextEditingController _passwordController =
19+
TextEditingController();
20+
21+
@override
22+
Widget build(BuildContext context) {
23+
return Scaffold(
24+
body: Padding(
25+
padding: const EdgeInsets.only(left: 100),
26+
child: Column(
27+
mainAxisAlignment: MainAxisAlignment.center,
28+
crossAxisAlignment: CrossAxisAlignment.start,
29+
children: <Widget>[
30+
Text(
31+
isLogin ? "Login" : "Sign Up",
32+
style: Theme.of(context).textTheme.headline2,
33+
),
34+
const SizedBox(height: 20),
35+
Row(
36+
children: [
37+
Text(
38+
isLogin
39+
? "Don't have an account ? "
40+
: "Already have an account ? ",
41+
style: const TextStyle(
42+
fontWeight: FontWeight.w600,
43+
fontSize: 16,
44+
),
45+
),
46+
InkWell(
47+
onTap: () {
48+
setState(() {
49+
isLogin = !isLogin;
50+
});
51+
},
52+
child: Text(
53+
isLogin ? "Sign up" : "Login",
54+
style: const TextStyle(
55+
decoration: TextDecoration.underline,
56+
fontSize: 16,
57+
fontWeight: FontWeight.w600,
58+
),
59+
),
60+
)
61+
],
62+
),
63+
const SizedBox(height: 25),
64+
SizedBox(
65+
width: 500,
66+
child: Column(
67+
children: [
68+
if (!isLogin)
69+
LabelTextField(
70+
key: const ValueKey("name"),
71+
label: "Name",
72+
controller: _nameController,
73+
onChanged: (_) {
74+
setState(() {
75+
enableButton = isAllBoxFilled;
76+
});
77+
},
78+
),
79+
LabelTextField(
80+
key: const ValueKey("email"),
81+
label: "Email",
82+
controller: _emailController,
83+
onChanged: (_) {
84+
setState(() {
85+
enableButton = isAllBoxFilled;
86+
});
87+
},
88+
),
89+
LabelTextField(
90+
key: const ValueKey("password"),
91+
label: "Password",
92+
controller: _passwordController,
93+
isPassword: true,
94+
onChanged: (_) {
95+
setState(() {
96+
enableButton = isAllBoxFilled;
97+
});
98+
},
99+
),
100+
],
101+
),
102+
),
103+
const SizedBox(height: 25),
104+
InvertedColorButton(
105+
text: isLogin ? "Login" : "Sign Up",
106+
onPressed: enableButton ? () {} : null,
107+
)
108+
],
109+
),
110+
),
111+
);
112+
}
113+
114+
bool get isAllBoxFilled =>
115+
(isLogin || _nameController.text.isNotEmpty) &&
116+
_emailController.text.isNotEmpty &&
117+
_passwordController.text.isNotEmpty;
118+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import 'package:flutter/material.dart';
2+
3+
class InvertedColorButton extends StatelessWidget {
4+
const InvertedColorButton({
5+
Key? key,
6+
required this.onPressed,
7+
required this.text,
8+
}) : super(key: key);
9+
10+
final VoidCallback? onPressed;
11+
final String text;
12+
13+
@override
14+
Widget build(BuildContext context) {
15+
return OutlinedButton(
16+
style: ButtonStyle(
17+
backgroundColor: MaterialStateProperty.resolveWith<Color?>(
18+
(states) {
19+
if (states.contains(MaterialState.hovered))
20+
return Colors.white;
21+
else if (states.contains(MaterialState.disabled))
22+
return const Color(0xFF888C93);
23+
return Colors.black;
24+
},
25+
),
26+
side: MaterialStateProperty.resolveWith((states) {
27+
if (states.contains(MaterialState.hovered))
28+
return const BorderSide();
29+
else if (states.contains(MaterialState.disabled))
30+
return const BorderSide(color: Color(0xFF888C93));
31+
return const BorderSide(color: Colors.white);
32+
}),
33+
padding: MaterialStateProperty.all(
34+
const EdgeInsets.symmetric(horizontal: 60, vertical: 22),
35+
),
36+
foregroundColor: MaterialStateProperty.resolveWith<Color?>(
37+
(states) {
38+
if (states.contains(MaterialState.hovered))
39+
return Colors.black;
40+
else if (states.contains(MaterialState.disabled))
41+
return Colors.white54;
42+
return Colors.white;
43+
},
44+
),
45+
textStyle: MaterialStateProperty.all<TextStyle?>(const TextStyle(
46+
fontSize: 18,
47+
fontWeight: FontWeight.bold,
48+
)),
49+
),
50+
onPressed: onPressed,
51+
child: Text(text),
52+
);
53+
}
54+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import 'package:flutter/material.dart';
2+
3+
class LabelTextField extends StatefulWidget {
4+
const LabelTextField({
5+
Key? key,
6+
required this.label,
7+
this.isPassword = false,
8+
this.onChanged,
9+
required this.controller,
10+
}) : super(key: key);
11+
12+
final String label;
13+
final bool isPassword;
14+
final Function(String)? onChanged;
15+
final TextEditingController controller;
16+
17+
@override
18+
_LabelTextFieldState createState() => _LabelTextFieldState();
19+
}
20+
21+
class _LabelTextFieldState extends State<LabelTextField> {
22+
late bool obscureText;
23+
bool showIcon = false;
24+
25+
@override
26+
void initState() {
27+
super.initState();
28+
obscureText = widget.isPassword;
29+
}
30+
31+
@override
32+
Widget build(BuildContext context) {
33+
return Column(
34+
crossAxisAlignment: CrossAxisAlignment.start,
35+
children: <Widget>[
36+
Text(
37+
widget.label,
38+
style: const TextStyle(fontSize: 18),
39+
),
40+
Padding(
41+
padding: const EdgeInsets.symmetric(vertical: 15.0),
42+
child: TextField(
43+
cursorColor: Colors.black,
44+
controller: widget.controller,
45+
obscureText: obscureText,
46+
style: const TextStyle(fontSize: 18),
47+
onChanged: (value) {
48+
if (widget.isPassword) showIcon = value.isNotEmpty;
49+
widget.onChanged?.call(value);
50+
},
51+
decoration: InputDecoration(
52+
suffixIcon: widget.isPassword && showIcon
53+
? IconButton(
54+
onPressed: () {
55+
setState(() {
56+
obscureText = !obscureText;
57+
});
58+
},
59+
icon: Icon(
60+
obscureText
61+
? Icons.visibility_outlined
62+
: Icons.visibility_off_outlined,
63+
color: Colors.black,
64+
),
65+
)
66+
: null,
67+
contentPadding: const EdgeInsets.only(left: 10),
68+
focusedBorder: const UnderlineInputBorder(),
69+
),
70+
),
71+
),
72+
],
73+
);
74+
}
75+
}

lib/landing/landing_screen.dart

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class LandingScreen extends StatelessWidget {
1010
return Scaffold(
1111
body: Column(
1212
children: <Widget>[
13-
Spacer(),
13+
const Spacer(),
1414
FittedBox(
1515
child: Text(
1616
"Introducing",
@@ -34,14 +34,14 @@ class LandingScreen extends StatelessWidget {
3434
child: Row(
3535
mainAxisAlignment: MainAxisAlignment.center,
3636
children: <Widget>[
37-
Text("A simple to-do app built with "),
37+
const Text("A simple to-do app built with "),
3838
Image.asset(
3939
"assets/logos/appwrite.png",
4040
width: 30,
4141
),
42-
Text(" Appwrite and "),
43-
FlutterLogo(size: 30),
44-
Text(" Flutter"),
42+
const Text(" Appwrite and "),
43+
const FlutterLogo(size: 30),
44+
const Text(" Flutter"),
4545
],
4646
),
4747
),
@@ -50,9 +50,9 @@ class LandingScreen extends StatelessWidget {
5050
padding: const EdgeInsets.all(50.0),
5151
child: OutlinedButton(
5252
onPressed: () {
53-
Routemaster.of(context).push("/todos");
53+
Routemaster.of(context).push("/login");
5454
},
55-
child: Text("Get Started"),
55+
child: const Text("Get Started"),
5656
),
5757
),
5858
),

lib/utils/routing.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
33
import 'package:routemaster/routemaster.dart';
4+
import 'package:todo_appwrite/authentication/authentication_screen.dart';
45
import 'package:todo_appwrite/landing/landing_screen.dart';
56
import 'package:todo_appwrite/todo_list/todo_list_screen.dart';
67

@@ -11,14 +12,16 @@ final routeProvider = StateNotifierProvider<RouteProvider, RouteMap>((ref) {
1112
class RouteProvider extends StateNotifier<RouteMap> {
1213
RouteProvider() : super(_initialRoute());
1314

14-
static const bool _loggedIn = true;
15+
static const bool _loggedIn = false;
1516

1617
static RouteMap _initialRoute() {
1718
return RouteMap(
1819
routes: {
1920
"/": (_) => const MaterialPage(child: LandingScreen()),
2021
if (_loggedIn)
21-
"/todos": (_) => const MaterialPage(child: TodoListScreen()),
22+
"/todos": (_) => const MaterialPage(child: TodoListScreen())
23+
else
24+
"/login": (_) => const MaterialPage(child: AuthenticationScreen())
2225
},
2326
onUnknownRoute: (_) => const Redirect("/"),
2427
);

0 commit comments

Comments
 (0)