Skip to content

Commit

Permalink
Implemented basic UI and functionality for login page. Login page app…
Browse files Browse the repository at this point in the history
…ears on start up of application.
  • Loading branch information
ziadzananiri committed Jan 30, 2025
1 parent 320163e commit 6a118cc
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ migrate_working_dir/
.pub/
/build/
/frontend/build/
devtools_options.yaml

# Symbolication related
app.*.symbols
Expand Down
7 changes: 7 additions & 0 deletions frontend/lib/common/theme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import 'package:flutter/material.dart';

final appTheme = ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlue),
useMaterial3: true,
scaffoldBackgroundColor: Colors.white,
);
81 changes: 27 additions & 54 deletions frontend/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,70 +1,43 @@
import 'package:flutter/material.dart';
// import 'package:go_router/go_router.dart';
import 'package:go_router/go_router.dart';
// import 'package:provider/provider.dart';

import 'package:utm_marketplace/common/theme.dart';
import 'package:utm_marketplace/views/login.dart';

// TODO: These are just for testing, remove when done/replace with actual views
import 'package:utm_marketplace/views/model_view.dart';
import 'package:utm_marketplace/models/model.dart';

void main() {
runApp(const MyApp());
}

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,
GoRouter router() {
return GoRouter(
initialLocation: '/login',
routes: [
GoRoute(
path: '/login',
builder: (context, state) => const Login(),
),
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();
GoRoute(
path: '/temp_view',
builder: (context, state) => ModelView(model: Model(attribute1: 'Attribute 1', attribute2: 2)),
),
],
);
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
_counter++;
});
}
class MyApp extends StatelessWidget {
const MyApp({super.key});

@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(),
);
}
}
149 changes: 149 additions & 0 deletions frontend/lib/views/login.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@

import 'package:flutter/material.dart';
import 'package:go_router/go_router.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) {
return 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),
Text(
'UTMarketplace',
style: TextStyle(
fontSize: 40.0,
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.w900,
letterSpacing: 2,
),
),
Spacer(flex: 1),
Align(
alignment: Alignment.centerLeft,
child: Text(
'UofT Email Address',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w700,
),
),
),
TextFormField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter your UofT email',
errorMaxLines: 1,
errorStyle: TextStyle(
height: 0.0,
),
),
// 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;
// },
),
SizedBox(height: 16.0),
Align(
alignment: Alignment.centerLeft,
child: Text(
'Password',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w700,
),
),
),
TextFormField(
obscureText: _obscureText,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Enter your password',
errorMaxLines: 1,
errorStyle: TextStyle(
height: 0.0,
),
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;
// },
),
SizedBox(height: 16.0),
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'),
),
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'),
),
],
),
TextButton(
onPressed: () {
// TODO: Implement forgot password functionality
},
child: Text('Forgot Password?'),
),
Spacer(flex: 1),
],
),
),
),
);
}
}

0 comments on commit 6a118cc

Please sign in to comment.