Created
May 14, 2024 23:20
-
-
Save aceeedev/54cecd2e6ba603b88d726e392b2dcba5 to your computer and use it in GitHub Desktop.
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
import 'package:flutter/material.dart'; | |
import 'package:google_fonts/google_fonts.dart'; | |
/* | |
* Styling | |
* | |
* Try to play around with different values! | |
*/ | |
class Styles { | |
// Colors: | |
static const primaryColor = Color(0xFFAD57B4); | |
static const secondaryColor = Color(0xFF2F2831); | |
static const backgroundColor = Color(0xFF363841); | |
static const lightColor = Color(0xFFC8CBD7); | |
// Text: | |
static final defaultTextStyle = GoogleFonts.roboto( | |
textStyle: const TextStyle( | |
fontSize: 16, color: lightColor, fontWeight: FontWeight.w300)); | |
static final header1TextStyle = GoogleFonts.roboto( | |
textStyle: const TextStyle( | |
fontSize: 48, color: lightColor, fontWeight: FontWeight.w200)); | |
static final header2TextStyle = GoogleFonts.roboto( | |
textStyle: const TextStyle( | |
fontSize: 24, color: lightColor, fontWeight: FontWeight.w200)); | |
static final textInputTextStyle = GoogleFonts.roboto( | |
textStyle: const TextStyle( | |
fontSize: 16, color: Colors.black, fontWeight: FontWeight.w300)); | |
// Buttons | |
static final submitButtonStyle = TextButton.styleFrom( | |
backgroundColor: primaryColor, | |
shape: const StadiumBorder(), | |
padding: const EdgeInsets.all(20.0), | |
); | |
static final deleteButtonStyle = TextButton.styleFrom( | |
backgroundColor: secondaryColor, | |
shape: RoundedRectangleBorder( | |
borderRadius: BorderRadius.circular(20), | |
), | |
); | |
// TextFields: | |
static final textInputDecoration = InputDecoration( | |
border: OutlineInputBorder(borderRadius: BorderRadius.circular(50)), | |
filled: true, | |
fillColor: lightColor, | |
hoverColor: lightColor, | |
); | |
// Cards: | |
static final accountCardDecoration = BoxDecoration( | |
color: backgroundColor, | |
borderRadius: BorderRadius.circular(10.0), | |
border: Border.all( | |
color: primaryColor, | |
width: 2.0, | |
), | |
); | |
} | |
/* | |
* Main function | |
*/ | |
void main() { | |
runApp(const App()); | |
} | |
/* | |
* Main App widget | |
*/ | |
class App extends StatelessWidget { | |
const App({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'ACM Fullstack Workshop', | |
theme: ThemeData( | |
useMaterial3: true, | |
scaffoldBackgroundColor: Styles.backgroundColor, | |
), | |
debugShowCheckedModeBanner: false, | |
home: const HomePage(), | |
); | |
} | |
} | |
/* | |
* Home page widget | |
*/ | |
class HomePage extends StatefulWidget { | |
const HomePage({super.key}); | |
@override | |
State<HomePage> createState() => _HomePageState(); | |
} | |
class _HomePageState extends State<HomePage> { | |
final _formKey = GlobalKey<FormState>(); | |
final nameTextController = TextEditingController(); | |
final emailTextController = TextEditingController(); | |
final List<Account> accountEntries = []; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
Text( | |
'Add your name and email', | |
style: Styles.header1TextStyle, | |
), | |
const Padding( | |
padding: EdgeInsets.only(top: 16, bottom: 16), | |
child: SizedBox( | |
height: 1, | |
width: 400, | |
child: DecoratedBox( | |
decoration: BoxDecoration(color: Styles.primaryColor), | |
), | |
), | |
), | |
Padding( | |
padding: const EdgeInsets.only(left: 50, right: 50), | |
child: Form( | |
key: _formKey, | |
child: Column( | |
children: [ | |
TextInput( | |
title: 'name:', textController: nameTextController), | |
TextInput( | |
title: 'email:', textController: emailTextController), | |
ElevatedButton( | |
style: Styles.submitButtonStyle, | |
onPressed: () { | |
final String name = nameTextController.text; | |
final String email = emailTextController.text; | |
final Account accountToAdd = | |
Account(name: name, email: email); | |
setState(() { | |
accountEntries.add(accountToAdd); | |
}); | |
}, | |
child: Text( | |
'Submit', | |
style: Styles.defaultTextStyle, | |
)) | |
], | |
)), | |
), | |
Padding( | |
padding: const EdgeInsets.only(top: 50, bottom: 16), | |
child: Text( | |
'List of Names and Emails:', | |
style: Styles.header2TextStyle, | |
), | |
), | |
Expanded( | |
child: Padding( | |
padding: const EdgeInsets.only(left: 75, right: 75), | |
child: ListView.builder( | |
itemCount: accountEntries.length, | |
itemBuilder: (context, index) { | |
return Padding( | |
padding: const EdgeInsets.only(top: 8.0, bottom: 8.0), | |
child: AccountCard( | |
account: accountEntries[index], | |
removeAccount: removeAccount, | |
accountIndex: index, | |
), | |
); | |
}), | |
), | |
), | |
], | |
), | |
); | |
} | |
void removeAccount(int index) { | |
setState(() { | |
accountEntries.removeAt(index); | |
}); | |
} | |
} | |
/* | |
* Custom Widgets | |
*/ | |
class TextInput extends StatelessWidget { | |
const TextInput( | |
{super.key, required this.title, required this.textController}); | |
final String title; | |
final TextEditingController textController; | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.only(bottom: 16.0), | |
child: Column( | |
children: [ | |
Text( | |
title, | |
style: Styles.defaultTextStyle, | |
), | |
TextFormField( | |
decoration: Styles.textInputDecoration, | |
style: Styles.textInputTextStyle, | |
cursorColor: Styles.primaryColor, | |
controller: textController, | |
) | |
], | |
), | |
); | |
} | |
} | |
class AccountCard extends StatelessWidget { | |
const AccountCard( | |
{super.key, | |
required this.account, | |
required this.removeAccount, | |
required this.accountIndex}); | |
final Account account; | |
final int accountIndex; | |
final Function removeAccount; | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
decoration: Styles.accountCardDecoration, | |
padding: const EdgeInsets.all(10.0), | |
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ | |
Expanded( | |
child: Text( | |
'${account.name} - ${account.email}', | |
style: Styles.defaultTextStyle, | |
), | |
), | |
ElevatedButton( | |
onPressed: () { | |
removeAccount(accountIndex); | |
}, | |
style: Styles.deleteButtonStyle, | |
child: Text('Delete', style: Styles.defaultTextStyle), | |
) | |
])); | |
} | |
} | |
/* | |
* Models | |
*/ | |
class Account { | |
String name; | |
String email; | |
Account({required this.name, required this.email}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment