diff options
| author | Rishi-k-s <rishikrishna.sr@gmail.com> | 2024-11-15 17:28:20 +0530 |
|---|---|---|
| committer | Rishi-k-s <rishikrishna.sr@gmail.com> | 2024-11-15 17:28:20 +0530 |
| commit | 136758f36719e43e14d6f5234562c58b332b57e1 (patch) | |
| tree | 50280d4985313a54665fb43a87d6e8215530fec0 | |
| parent | a6c0e7d7e2fb8badc4b4ade48438b2d025025366 (diff) | |
doine nedobrulaist stuffui-feature-branch
| -rw-r--r-- | lib/userpage/Scoreboardpage.dart | 170 | ||||
| -rw-r--r-- | lib/userpage/loginpage.dart | 221 | ||||
| -rw-r--r-- | lib/userpage/quizpage.dart | 193 | ||||
| -rw-r--r-- | lib/userpage/userverificationpage.dart | 172 | ||||
| -rw-r--r-- | test_page.dart | 240 |
5 files changed, 813 insertions, 183 deletions
diff --git a/lib/userpage/Scoreboardpage.dart b/lib/userpage/Scoreboardpage.dart index c72a04f..ee79dc0 100644 --- a/lib/userpage/Scoreboardpage.dart +++ b/lib/userpage/Scoreboardpage.dart @@ -10,7 +10,7 @@ class ScoreboardPage extends StatefulWidget { class _ScoreboardPageState extends State<ScoreboardPage> { final DatabaseReference database = FirebaseDatabase.instance.ref(); - List<Map<String, dynamic>> users = []; // To store user data + List<Map<String, dynamic>> users = []; bool isLoading = true; @override @@ -19,20 +19,18 @@ class _ScoreboardPageState extends State<ScoreboardPage> { _loadUsers(); } - // Load users from Firebase and sort them by score Future<void> _loadUsers() async { final snapshot = await database.child("users").get(); if (snapshot.exists) { final data = snapshot.value as Map; users = data.entries.map((e) { return { - 'name': e.value['fullName'], // Get the name field - 'semester': e.value['semester'], // Get the semester field - 'score': e.value['score'], // Get the score field + 'name': e.value['fullName'], + 'semester': e.value['semester'], + 'score': e.value['score'], }; }).toList(); - // Sort users by score in descending order users.sort((a, b) => b['score'].compareTo(a['score'])); setState(() { @@ -41,27 +39,153 @@ class _ScoreboardPageState extends State<ScoreboardPage> { } } + Color _getMedalColor(int index) { + switch (index) { + case 0: + return const Color(0xFFFFD700); // Gold + case 1: + return const Color(0xFFC0C0C0); // Silver + case 2: + return const Color(0xFFCD7F32); // Bronze + default: + return Colors.transparent; + } + } + + Widget _buildUserCard(Map<String, dynamic> user, int index) { + final bool isTopThree = index < 3; + final medalColor = _getMedalColor(index); + + return Container( + margin: const EdgeInsets.only(bottom: 16), + decoration: BoxDecoration( + color: isTopThree ? medalColor.withOpacity(0.1) : Colors.white, + border: Border.all( + color: isTopThree ? medalColor : const Color(0xFF3A78C2), + width: isTopThree ? 3 : 2, + ), + borderRadius: BorderRadius.circular(8), + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: isTopThree ? medalColor : const Color(0xFF4D9FFF), + shape: BoxShape.circle, + border: Border.all( + color: isTopThree ? medalColor.withOpacity(0.7) : const Color(0xFF3A78C2), + width: 2, + ), + ), + child: Center( + child: Text( + '${index + 1}', + style: TextStyle( + color: isTopThree ? Colors.black : Colors.white, + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + user['name'] ?? "Unknown", + style: TextStyle( + fontSize: isTopThree ? 20 : 18, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 4), + Text( + "Semester: ${user['semester'] ?? 'N/A'}", + style: TextStyle( + fontSize: 16, + color: Colors.grey[600], + ), + ), + ], + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: isTopThree ? medalColor.withOpacity(0.2) : const Color(0xFF4D9FFF).withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: isTopThree ? medalColor : const Color(0xFF3A78C2), + width: 2, + ), + ), + child: Text( + "${user['score']}", + style: TextStyle( + fontSize: isTopThree ? 20 : 18, + fontWeight: FontWeight.bold, + color: isTopThree ? Colors.black : const Color(0xFF3A78C2), + ), + ), + ), + ], + ), + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("Scoreboard")), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: isLoading - ? const Center(child: CircularProgressIndicator()) - : users.isEmpty - ? const Center(child: Text("No users found")) - : ListView.builder( - itemCount: users.length, - itemBuilder: (context, index) { - return ListTile( - title: Text(users[index]['name'] ?? "Unknown"), - subtitle: Text("Semester: ${users[index]['semester'] ?? "N/A"}"), - trailing: Text("Score: ${users[index]['score']}"), - ); - }, + body: Container( + color: const Color(0xFFFDF6E3), + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Scoreboard", + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: Colors.black, ), + ), + const SizedBox(height: 24), + Expanded( + child: isLoading + ? const Center(child: CircularProgressIndicator()) + : users.isEmpty + ? const Center( + child: Text( + "No users found", + style: TextStyle( + fontSize: 18, + color: Color(0xFF3A78C2), + ), + ), + ) + : ListView.builder( + itemCount: users.length, + itemBuilder: (context, index) { + return _buildUserCard(users[index], index); + }, + ), + ), + ], + ), + ), + ), ), ); } -} +}
\ No newline at end of file diff --git a/lib/userpage/loginpage.dart b/lib/userpage/loginpage.dart index 0fdda98..66298bc 100644 --- a/lib/userpage/loginpage.dart +++ b/lib/userpage/loginpage.dart @@ -1,5 +1,6 @@ import 'package:firebase_database/firebase_database.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @@ -10,8 +11,6 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State<LoginPage> { final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); - - // Controllers for each field final TextEditingController emailController = TextEditingController(); final TextEditingController fullNameController = TextEditingController(); final TextEditingController semesterController = TextEditingController(); @@ -26,7 +25,7 @@ class _LoginPageState extends State<LoginPage> { bool _isLoading = false; bool _iswaiting = false; - Future<void> _submitData() async { + Future<void> _submitData() async { String question; if (_formKey.currentState!.validate()) { question = @@ -92,82 +91,164 @@ class _LoginPageState extends State<LoginPage> { } } - @override - Widget build(BuildContext context) { - return Scaffold( - body: _iswaiting - ? const Text( - "Waiting page.....", - style: TextStyle(color: Colors.red, fontSize: 30), - ) - : SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Form( - key: _formKey, - child: Column( - children: [ - CustomTextField( - labelText: 'Email', controller: emailController), - CustomTextField( - labelText: 'Full Name', - controller: fullNameController), - CustomTextField( - labelText: 'Semester', - controller: semesterController), - CustomTextField( - labelText: 'Question', - controller: questionController), - CustomTextField( - labelText: 'Answer', controller: answerController), - CustomTextField( - labelText: 'Option 1', controller: option1Controller), - CustomTextField( - labelText: 'Option 2', controller: option2Controller), - CustomTextField( - labelText: 'Option 3', controller: option3Controller), - const SizedBox(height: 20), - _isLoading - ? const CircularProgressIndicator() // Show loader if loading - : ElevatedButton( - onPressed: - _submitData, // Call _submitData function - child: const Text('Submit'), - ), - ], - ), - ), + // Previous methods remain the same (_submitData)... + + Widget _buildStyledTextField(String labelText, TextEditingController controller, {bool isNumeric = false}) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + labelText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Color(0xFF3A78C2), + ), + ), + const SizedBox(height: 8), + TextFormField( + controller: controller, + keyboardType: isNumeric ? TextInputType.number : TextInputType.text, + inputFormatters: isNumeric ? [FilteringTextInputFormatter.digitsOnly] : null, + decoration: InputDecoration( + filled: true, + fillColor: Colors.white, + hintText: 'Enter $labelText', + hintStyle: TextStyle(color: Colors.grey.shade400), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide( + color: Color(0xFF3A78C2), + width: 2, ), ), - ); - } + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide( + color: Color(0xFF4D9FFF), + width: 2, + ), + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide( + color: Colors.red, + width: 2, + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide( + color: Colors.red, + width: 2, + ), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter $labelText'; + } + return null; + }, + ), + ], + ), + ); } -class CustomTextField extends StatelessWidget { - final String labelText; - final TextEditingController controller; - const CustomTextField({super.key, required this.labelText, required this.controller}); + Widget _buildSubmitButton() { + return Container( + width: double.infinity, + height: 56, + decoration: BoxDecoration( + color: const Color(0xFF4D9FFF), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: const Color(0xFF3A78C2), + width: 3, + ), + ), + child: ElevatedButton( + onPressed: _isLoading ? null : _submitData, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: _isLoading + ? const CircularProgressIndicator(color: Colors.white) + : const Text( + 'Submit', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ), + ); + } @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: TextFormField( - controller: controller, - decoration: InputDecoration( - labelText: labelText, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8.0), - ), + return Scaffold( + body: Container( + color: const Color(0xFFFDF6E3), + child: SafeArea( + child: _iswaiting + ? const Center( + child: Text( + "Waiting page.....", + style: TextStyle( + color: Color(0xFF3A78C2), + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + ) + : SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Create Quiz", + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 24), + Form( + key: _formKey, + child: Column( + children: [ + _buildStyledTextField('Email', emailController), + _buildStyledTextField('Full Name', fullNameController), + _buildStyledTextField('Semester', semesterController, isNumeric: true), + _buildStyledTextField('Question', questionController), + _buildStyledTextField('Answer', answerController), + _buildStyledTextField('Option 1', option1Controller), + _buildStyledTextField('Option 2', option2Controller), + _buildStyledTextField('Option 3', option3Controller), + const SizedBox(height: 24), + _buildSubmitButton(), + ], + ), + ), + ], + ), + ), + ), ), - validator: (value) { - if (value == null || value.isEmpty) { - return 'Please enter $labelText'; - } - return null; - }, ), ); } -} +}
\ No newline at end of file diff --git a/lib/userpage/quizpage.dart b/lib/userpage/quizpage.dart index 62ac74d..56094e4 100644 --- a/lib/userpage/quizpage.dart +++ b/lib/userpage/quizpage.dart @@ -1,11 +1,10 @@ import 'dart:async'; - import 'package:firebase_database/firebase_database.dart'; import 'package:flutter/material.dart'; class QuizPage extends StatefulWidget { final String email; - final String userId; // Pass user ID along with email + final String userId; const QuizPage({super.key, required this.email, required this.userId}); @@ -16,11 +15,11 @@ class QuizPage extends StatefulWidget { class _QuizPageState extends State<QuizPage> { final DatabaseReference database = FirebaseDatabase.instance.ref(); late StreamController<Map> _questionController; - int score = 0; // The initial score will be fetched from Firebase + int score = 0; bool isLoading = true; List<Map> questions = []; int currentQuestionIndex = 0; - Set<String> answeredQuestions = <String>{}; // Track answered questions + Set<String> answeredQuestions = <String>{}; @override void initState() { @@ -29,7 +28,6 @@ class _QuizPageState extends State<QuizPage> { _loadData(); } - // Load both the questions and user's score from the database Future<void> _loadData() async { try { // Fetch the user's data from the database @@ -108,6 +106,12 @@ class _QuizPageState extends State<QuizPage> { // Check the answer, update score, and load the next random question Future<void> _checkAnswer(String selectedAnswer, Map question) async { + // Get the current gameState from the database + final gameStateSnapshot = await database.child("gameState").get(); + final gameState = gameStateSnapshot.value; + + // Proceed only if the gameState is "start" + if (gameState == "start") { if (selectedAnswer == question['answer']) { score += 4; } else { @@ -122,7 +126,13 @@ class _QuizPageState extends State<QuizPage> { // Move to the next question (loop through the shuffled list) _showNextQuestion(); + } else { + // Notify the user that the game is not in progress + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Game is not active currently')), + ); } +} // Method to update score in Firebase Future<void> _updateScoreInDatabase() async { @@ -136,64 +146,133 @@ class _QuizPageState extends State<QuizPage> { } } - @override - void dispose() { - super.dispose(); - _questionController.close(); // Close the StreamController + Widget _buildOptionButton(String option, int index, Map question) { + final List<Color> buttonColors = [ + const Color(0xFFFF69B4), // Pink + const Color(0xFF90EE90), // Green + const Color(0xFFFFD700), // Gold + const Color(0xFF4D9FFF), // Blue + ]; + + final List<Color> borderColors = [ + const Color(0xFFD4527A), // Darker Pink + const Color(0xFF6CB76C), // Darker Green + const Color(0xFFD4B400), // Darker Gold + const Color(0xFF3A78C2), // Darker Blue + ]; + + return Padding( + padding: const EdgeInsets.only(bottom: 16.0), + child: InkWell( + onTap: () => _checkAnswer(option, question), + child: Container( + width: double.infinity, + padding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 24, + ), + decoration: BoxDecoration( + color: buttonColors[index], + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: borderColors[index], + width: 3, + ), + ), + child: Text( + "${String.fromCharCode(65 + index)}) $option", + style: const TextStyle( + fontSize: 18, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ); } @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("Quiz")), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: StreamBuilder<Map>( - stream: _questionController.stream, - builder: (context, snapshot) { - if (isLoading) { - return const Center(child: CircularProgressIndicator()); - } - - // Handle loading state - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: CircularProgressIndicator()); - } - - // Handle the case when no more questions are available - if (snapshot.hasData && - snapshot.data!['no_more_questions'] == true) { - return const Center(child: Text("No more questions available.")); - } - - // Handle the state when data is available (quiz ongoing) - if (snapshot.hasData) { - final question = snapshot.data!; - - return Column( - children: [ - Text( - question['question'], - style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 20), - ...question['options'].map<Widget>((option) { - return ListTile( - title: Text(option), - onTap: () => _checkAnswer(option, question), - ); - }).toList(), - const SizedBox(height: 20), - Text("Score: $score"), - ], - ); - } - - // Default case (shouldn't hit unless there's an issue) - return const Center(child: Text("An error occurred.")); - }, + body: Container( + color: const Color(0xFFFDF6E3), // Cream background color + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: StreamBuilder<Map>( + stream: _questionController.stream, + builder: (context, snapshot) { + if (isLoading) { + return const Center(child: CircularProgressIndicator()); + } + + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } + + if (snapshot.hasData && snapshot.data!['no_more_questions'] == true) { + return const Center(child: Text("No more questions available.")); + } + + if (snapshot.hasData) { + final question = snapshot.data!; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "Quiz", + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 40), + Text( + question['question'], + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + const SizedBox(height: 40), + ...List.generate( + question['options'].length, + (index) => _buildOptionButton( + question['options'][index], + index, + question, + ), + ), + const SizedBox(height: 20), + Center( + child: Text( + "Score: $score", + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ); + } + + return const Center(child: Text("An error occurred.")); + }, + ), + ), ), ), ); } -} + + @override + void dispose() { + _questionController.close(); + super.dispose(); + } +}
\ No newline at end of file diff --git a/lib/userpage/userverificationpage.dart b/lib/userpage/userverificationpage.dart index 3c163ed..2f1676f 100644 --- a/lib/userpage/userverificationpage.dart +++ b/lib/userpage/userverificationpage.dart @@ -12,10 +12,8 @@ class UserVerificationPage extends StatefulWidget { class _UserVerificationPageState extends State<UserVerificationPage> { final TextEditingController nameController = TextEditingController(); final TextEditingController emailController = TextEditingController(); - final DatabaseReference database = FirebaseDatabase.instance.ref(); - // Corrected method to find userId by email Future<String?> _findUserIdByEmail(String email) async { try { final snapshot = await database @@ -25,15 +23,10 @@ class _UserVerificationPageState extends State<UserVerificationPage> { .once(); if (snapshot.snapshot.exists) { - // If user exists, retrieve the userId (which is the key of the user) final data = snapshot.snapshot.value as Map<dynamic, dynamic>; - - // Getting the first key (which is the userId) final userId = data.keys.first; - return userId; } else { - // User does not exist print("User not found"); return null; } @@ -43,15 +36,11 @@ class _UserVerificationPageState extends State<UserVerificationPage> { } } - // Handle button press and navigate to the quiz page void _verifyUser() async { final email = emailController.text.trim(); - - // Call _findUserIdByEmail to find the userId final userId = await _findUserIdByEmail(email); if (userId != null) { - // If userId is found, navigate to the QuizPage Navigator.push( context, MaterialPageRoute( @@ -59,9 +48,15 @@ class _UserVerificationPageState extends State<UserVerificationPage> { ), ); } else { - // If userId is not found, show an error ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("User not found. Please register.")), + SnackBar( + content: const Text("User not found. Please register."), + backgroundColor: const Color(0xFFFF6B6B), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), ); } } @@ -69,28 +64,139 @@ class _UserVerificationPageState extends State<UserVerificationPage> { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("User Verification")), - backgroundColor: Colors.white, - body: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - TextField( - controller: nameController, - decoration: const InputDecoration(labelText: "Name"), - ), - TextField( - controller: emailController, - decoration: const InputDecoration(labelText: "Email"), + backgroundColor: const Color(0xFFFFF3E0), // Warm background color + // appBar: AppBar( + // title: const Text( + // "LOGIN", + // style: TextStyle( + // fontWeight: FontWeight.bold, + // letterSpacing: 2, + // ), + // ), + // backgroundColor: const Color(0xFF4ECDC4), // Bright teal + // elevation: 8, + // shadowColor: Colors.black, + // ), + body: Center( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Logo or Image placeholder + Container( + width: 120, + height: 120, + decoration: BoxDecoration( + color: const Color(0xFFFF6B6B), // Coral + borderRadius: BorderRadius.circular(20), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: const Icon( + Icons.person, + size: 60, + color: Colors.white, + ), + ), + const SizedBox(height: 40), + // Name TextField + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.black, width: 3), + borderRadius: BorderRadius.circular(15), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: TextField( + controller: nameController, + decoration: const InputDecoration( + labelText: "NAME", + labelStyle: TextStyle( + color: Color(0xFF2C3E50), + fontWeight: FontWeight.bold, + ), + border: InputBorder.none, + contentPadding: EdgeInsets.all(16), + ), + ), + ), + const SizedBox(height: 20), + // Email TextField + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.black, width: 3), + borderRadius: BorderRadius.circular(15), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: TextField( + controller: emailController, + decoration: const InputDecoration( + labelText: "EMAIL", + labelStyle: TextStyle( + color: Color(0xFF2C3E50), + fontWeight: FontWeight.bold, + ), + border: InputBorder.none, + contentPadding: EdgeInsets.all(16), + ), + ), + ), + const SizedBox(height: 40), + // Login Button + GestureDetector( + onTap: _verifyUser, + child: Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(vertical: 16), + decoration: BoxDecoration( + color: const Color(0xFFFFBE0B), // Bright yellow + border: Border.all(color: Colors.black, width: 3), + borderRadius: BorderRadius.circular(15), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: const Text( + "CONTINUE →", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black, + letterSpacing: 1, + ), + ), + ), + ), + ], ), - const SizedBox(height: 20), - ElevatedButton( - onPressed: _verifyUser, // Call _verifyUser on button press - child: const Text("Continue..."), - ), - ], + ), ), ), ); } -} +}
\ No newline at end of file diff --git a/test_page.dart b/test_page.dart new file mode 100644 index 0000000..d2ea27e --- /dev/null +++ b/test_page.dart @@ -0,0 +1,240 @@ +import 'package:firebase_database/firebase_database.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class RegistrationPage extends StatefulWidget { + const RegistrationPage({super.key}); + + @override + State<RegistrationPage> createState() => _RegistrationPageState(); +} + +class _RegistrationPageState extends State<RegistrationPage> { + final GlobalKey<FormState> _formKey = GlobalKey<FormState>(); + final TextEditingController emailController = TextEditingController(); + final TextEditingController passwordController = TextEditingController(); + final TextEditingController confirmPasswordController = TextEditingController(); + final TextEditingController usernameController = TextEditingController(); + + final DatabaseReference database = FirebaseDatabase.instance.ref(); + bool _isLoading = false; + + // Neo-brutalist colors + static const Color primaryColor = Color(0xFFFF6B6B); + static const Color secondaryColor = Color(0xFF4ECDC4); + static const Color backgroundColor = Color(0xFFFFF9DB); + static const Color textColor = Color(0xFF2C3E50); + + Future<void> _register() async { + if (_formKey.currentState!.validate()) { + if (passwordController.text != confirmPasswordController.text) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Passwords do not match!')), + ); + return; + } + + setState(() { + _isLoading = true; + }); + + try { + // Create User data + final userData = { + "email": emailController.text, + "username": usernameController.text, + // Note: In a real app, you should hash the password + "password": passwordController.text, + }; + + // Save data to Firebase + await database.child("users").push().set(userData); + + // Clear form fields + emailController.clear(); + passwordController.clear(); + confirmPasswordController.clear(); + usernameController.clear(); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Registration successful!'), + backgroundColor: primaryColor, + ), + ); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Registration failed: $e')), + ); + } finally { + setState(() { + _isLoading = false; + }); + } + } + } + + Widget _buildNeoBrutalistTextField( + String labelText, TextEditingController controller, + {bool isPassword = false}) { + return Container( + margin: const EdgeInsets.symmetric(vertical: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + labelText.toUpperCase(), + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: textColor, + letterSpacing: 1.5, + ), + ), + const SizedBox(height: 8), + Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: textColor, width: 3), + borderRadius: BorderRadius.circular(8), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: TextFormField( + controller: controller, + obscureText: isPassword, + decoration: InputDecoration( + hintText: 'Enter $labelText', + hintStyle: TextStyle(color: Colors.grey.shade400), + contentPadding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 16, + ), + border: InputBorder.none, + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter $labelText'; + } + if (labelText.contains('Email') && + !value.contains('@')) { + return 'Please enter a valid email'; + } + if (labelText.contains('Password') && value.length < 6) { + return 'Password must be at least 6 characters'; + } + return null; + }, + ), + ), + ], + ), + ); + } + + Widget _buildNeoBrutalistButton() { + return Container( + width: double.infinity, + height: 60, + margin: const EdgeInsets.symmetric(vertical: 20), + decoration: BoxDecoration( + color: primaryColor, + border: Border.all(color: Colors.black, width: 3), + borderRadius: BorderRadius.circular(8), + boxShadow: const [ + BoxShadow( + color: Colors.black, + offset: Offset(4, 4), + blurRadius: 0, + ), + ], + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: _isLoading ? null : _register, + child: Center( + child: _isLoading + ? const CircularProgressIndicator(color: Colors.white) + : const Text( + 'REGISTER', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.white, + letterSpacing: 2, + ), + ), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: backgroundColor, + body: SafeArea( + child: SingleChildScrollView( + padding: const EdgeInsets.all(24.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only(bottom: 40), + child: const Text( + "REGISTER", + style: TextStyle( + fontSize: 48, + fontWeight: FontWeight.bold, + color: textColor, + letterSpacing: 2, + ), + ), + ), + Form( + key: _formKey, + child: Column( + children: [ + _buildNeoBrutalistTextField('Username', usernameController), + _buildNeoBrutalistTextField('Email', emailController), + _buildNeoBrutalistTextField( + 'Password', + passwordController, + isPassword: true, + ), + _buildNeoBrutalistTextField( + 'Confirm Password', + confirmPasswordController, + isPassword: true, + ), + _buildNeoBrutalistButton(), + TextButton( + onPressed: () { + // Add navigation to login page + }, + child: const Text( + 'Already have an account? Login', + style: TextStyle( + color: secondaryColor, + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } +}
\ No newline at end of file |
