-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SCRUM-3] Implement login page ui (#1)
* Implemented basic UI and functionality for login page. Login page appears on start up of application. * Refactoring and modularizing aspects of the application such as theme styling, page routing, and login page. Login page rewritten for readability.
- Loading branch information
1 parent
251f3ac
commit a430d8c
Showing
5 changed files
with
226 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import 'package:go_router/go_router.dart'; | ||
import 'package:utm_marketplace/views/login.dart'; | ||
|
||
// TODO: These are temporary imports for testing purposes, remove when no longer needed | ||
import 'package:utm_marketplace/views/model_view.dart'; | ||
import 'package:utm_marketplace/models/model.dart'; | ||
|
||
// Define the router as a top-level global variable | ||
final GoRouter router = GoRouter( | ||
initialLocation: '/login', | ||
routes: [ | ||
GoRoute( | ||
path: '/login', | ||
builder: (context, state) => const Login(), | ||
), | ||
GoRoute( | ||
path: '/temp_view', | ||
builder: (context, state) => ModelView(model: Model(attribute1: 'Attribute 1', attribute2: 2)), | ||
), | ||
], | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
final appTheme = ThemeData( | ||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlue), | ||
useMaterial3: true, | ||
scaffoldBackgroundColor: Colors.white, | ||
); | ||
|
||
// This class is for storing text styles that are used throughout the app | ||
// The label style is used for smaller text, such as form labels | ||
// The header style is used for larger text, such as titles | ||
class ThemeText { | ||
static const TextStyle header = TextStyle( | ||
fontSize: 40.0, | ||
fontWeight: FontWeight.w900, | ||
letterSpacing: 2, | ||
); | ||
|
||
static const TextStyle label = TextStyle( | ||
fontSize: 16.0, | ||
fontWeight: FontWeight.w700, | ||
); | ||
} | ||
|
||
// This class is a custom text widget that uses the theme text style provided above | ||
// This simplifies the process of creating text widgets with consistent styling | ||
// To use, simply provide the text, style, and optional text alignment | ||
// Will most likely be modified as we continue to develop the app | ||
class StyleText extends StatelessWidget { | ||
final String text; | ||
final TextStyle style; | ||
final TextAlign? textAlign; | ||
|
||
const StyleText({ | ||
super.key, | ||
required this.text, | ||
required this.style, | ||
this.textAlign, | ||
}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Text( | ||
text, | ||
style: style, | ||
textAlign: textAlign, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,24 @@ | ||
import 'package:flutter/material.dart'; | ||
// import 'package:go_router/go_router.dart'; | ||
// import 'package:provider/provider.dart'; | ||
|
||
import 'package:utm_marketplace/common/theme.dart'; | ||
import 'package:utm_marketplace/common/router.dart'; | ||
|
||
void main() { | ||
runApp(const MyApp()); | ||
} | ||
|
||
// The main app widget, which initializes the app with the router and theme | ||
// Router and theme are defined in the common/router.dart and common/theme.dart files | ||
class MyApp extends StatelessWidget { | ||
const MyApp({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return MaterialApp( | ||
title: 'Flutter Demo', | ||
theme: ThemeData( | ||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), | ||
useMaterial3: true, | ||
), | ||
home: const MyHomePage(title: 'Flutter Demo Home Page'), | ||
); | ||
} | ||
} | ||
|
||
class MyHomePage extends StatefulWidget { | ||
const MyHomePage({super.key, required this.title}); | ||
final String title; | ||
|
||
@override | ||
State<MyHomePage> createState() => _MyHomePageState(); | ||
} | ||
|
||
class _MyHomePageState extends State<MyHomePage> { | ||
int _counter = 0; | ||
|
||
void _incrementCounter() { | ||
setState(() { | ||
_counter++; | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
backgroundColor: Theme.of(context).colorScheme.inversePrimary, | ||
title: Text(widget.title), | ||
), | ||
body: Center( | ||
child: Column( | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: <Widget>[ | ||
const Text( | ||
'You have pushed the button this many times:', | ||
), | ||
Text( | ||
'$_counter', | ||
style: Theme.of(context).textTheme.headlineMedium, | ||
), | ||
], | ||
), | ||
), | ||
floatingActionButton: FloatingActionButton( | ||
onPressed: _incrementCounter, | ||
tooltip: 'Increment', | ||
child: const Icon(Icons.add), | ||
), | ||
return MaterialApp.router( | ||
title: 'UTM Marketplace', | ||
theme: appTheme, | ||
routerConfig: router, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:go_router/go_router.dart'; | ||
import 'package:utm_marketplace/common/theme.dart'; | ||
|
||
// Note: There's a small issue regarding the flex Spacer widget, it's not too important | ||
// but would be nice to find a way that makes it so the UI elements | ||
// don't shift when a validator fails. | ||
|
||
class Login extends StatefulWidget { | ||
const Login({super.key}); | ||
|
||
@override | ||
LoginState createState() => LoginState(); | ||
} | ||
|
||
class LoginState extends State<Login> { | ||
final _formKey = GlobalKey<FormState>(); | ||
bool _obscureText = true; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final logoText = StyleText( | ||
text: 'UTMarketplace', | ||
style: ThemeText.header.copyWith( | ||
color: Theme.of(context).colorScheme.primary, | ||
), | ||
); | ||
|
||
final emailField = TextFormField( | ||
decoration: InputDecoration( | ||
border: OutlineInputBorder(), | ||
labelText: 'Enter your UofT email', | ||
), | ||
// TODO: REGEX for valid UofT domain email, uncomment when ready | ||
// validator: (value) { | ||
// if (value == null || value.isEmpty) { | ||
// return 'Please a valid UofT email address'; | ||
// } | ||
// return null; | ||
// }, | ||
); | ||
|
||
final passwordField = TextFormField( | ||
obscureText: _obscureText, | ||
decoration: InputDecoration( | ||
border: OutlineInputBorder(), | ||
labelText: 'Enter your password', | ||
suffixIcon: IconButton( | ||
icon: Icon( | ||
_obscureText ? Icons.visibility_off : Icons.visibility, | ||
), | ||
onPressed: () { | ||
setState(() { | ||
_obscureText = !_obscureText; | ||
}); | ||
}, | ||
), | ||
), | ||
// TODO: Implement email validation and password validation (backend), uncomment when ready | ||
// validator: (value) { | ||
// if (value == null || value.isEmpty) { | ||
// return 'Password or email is incorrect'; | ||
// } | ||
// return null; | ||
// }, | ||
); | ||
|
||
final loginButton = ElevatedButton( | ||
onPressed: () { | ||
if (_formKey.currentState!.validate()) { | ||
// TODO: Implement login functionality (backend) | ||
// If this condition passed, a redirect call to the home | ||
// page should be made | ||
context.go('/temp_view'); | ||
} | ||
}, | ||
style: ElevatedButton.styleFrom( | ||
minimumSize: Size(double.infinity, 50), | ||
), | ||
child: Text('Log In'), | ||
); | ||
|
||
final signUpRow = Row( | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: <Widget>[ | ||
Text('Don\'t have an account?'), | ||
TextButton( | ||
onPressed: () { | ||
// TODO: Implement redirect to sign up page | ||
}, | ||
child: Text('Sign Up'), | ||
), | ||
], | ||
); | ||
|
||
final forgotPasswordButton = TextButton( | ||
onPressed: () { | ||
// TODO: Implement forgot password functionality | ||
}, | ||
child: Text('Forgot Password?'), | ||
); | ||
|
||
return SafeArea( | ||
child: Scaffold( | ||
resizeToAvoidBottomInset: false, | ||
body: Container( | ||
padding: EdgeInsets.all(16.0), | ||
child: Form( | ||
key: _formKey, | ||
child: Column( | ||
crossAxisAlignment: CrossAxisAlignment.center, | ||
mainAxisAlignment: MainAxisAlignment.center, | ||
children: <Widget>[ | ||
Spacer(flex: 1), | ||
logoText, | ||
Spacer(flex: 1), | ||
Align( | ||
alignment: Alignment.centerLeft, | ||
child: StyleText( | ||
text: 'UofT Email Address', | ||
style: ThemeText.label, | ||
), | ||
), | ||
emailField, | ||
SizedBox(height: 16.0), | ||
Align( | ||
alignment: Alignment.centerLeft, | ||
child: StyleText( | ||
text: 'Password', | ||
style: ThemeText.label, | ||
), | ||
), | ||
passwordField, | ||
SizedBox(height: 16.0), | ||
loginButton, | ||
signUpRow, | ||
forgotPasswordButton, | ||
Spacer(flex: 1), | ||
], | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} |