Flutter Init, App, Home and Login Modules

Mohamad's interest is in Programming (Mobile, Web, Database and Machine Learning). He is studying at the Center For Artificial Intelligence Technology (CAIT), Universiti Kebangsaan Malaysia (UKM).
[1] Dependencies configuration
file -> pubspec.yaml
name: workgroup_app
description: A flutter workgroup app.
publish_to: 'none'
version: 0.1.0
environment:
sdk: '>=2.18.2 <3.0.0'
dependencies:
flutter:
sdk: flutter
hive: ^2.2.3
hive_flutter: ^1.1.0
http: 0.13.0
intl: ^0.17.0 # DateFormat
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
[2] Project folder/file structure
lib/
├── main.dart
└── modules/
├── app.dart
├── home.dart
├── init.dart
└── login.dart
[3] Main module
file-> lib/main.dart
import 'package:flutter/material.dart';
import 'modules/init.dart';
import 'modules/app.dart';
void main() async {
await initializeApp();
runApp(const App());
}
[4] Sub Modules
[4.1] Init
file-> lib/modules/init.dart
import 'package:hive_flutter/hive_flutter.dart';
Future<void> initializeApp() async {
await _initHive();
// Add any other initialization logic here
}
Future<void> _initHive() async {
// Hive initialization logic
await Hive.initFlutter(); //
await Hive.openBox("user");
}
[4.2] App
file-> lib/modules/app.dart
import 'package:flutter/material.dart';
import 'home.dart';
import 'workgroups.dart';
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Workgroup App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
initialRoute: '/',
routes: {
'/': (context) => const HomeScreen(),
'/home': (context) => const HomeScreen(),
'/workgroups': (context) => const WorkgroupsScreen(),
},
);
}
}
[4.3] Home
file-> lib/modules/home.dart
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'login.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomeScreen> {
bool _isLoggedIn = false;
final Box _boxUser = Hive.box("user");
@override
void initState() {
super.initState();
_checkUserToken();
}
Future<void> _checkUserToken() async {
final userToken = await _boxUser.get('user_token');
if (userToken == null) {
// Redirect to login page
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => LoginScreen()),
);
} else {
setState(() {
_isLoggedIn = true;
});
}
}
Future<void> _logout() async {
await _boxUser.delete('user_token');
setState(() {
_isLoggedIn = false;
});
// Redirect to login page
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => LoginScreen()),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
if (_isLoggedIn)
ElevatedButton(
onPressed: _logout,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
padding:
const EdgeInsets.all(8.0),
),
child: const Icon(Icons.logout),
),
],
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/workgroups');
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), // Increase the button padding
textStyle: const TextStyle(
fontSize: 18, // Increase the font size
),
),
child: const Text('Workgroups'),
),
),
);
}
}
Output (Screen) for App/Home:

[4.4] Login
file-> lib/modules/login.dart
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:hive/hive.dart';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final Box _boxUser = Hive.box("user");
Future<void> _login() async {
final url = Uri.parse('https://demo.razzi.my/spotnet/public/api/login');
final request = http.MultipartRequest('POST', url);
request.fields['email'] = _emailController.text;
request.fields['password'] = _passwordController.text;
final response = await request.send();
final responseBody = await response.stream.bytesToString();
if (response.statusCode == 200) {
final data = jsonDecode(responseBody);
final email = data['email'];
final userToken = data['user_token'];
// Update the 'boxUser' box
await _boxUser.put('email', email);
await _boxUser.put('user_token', userToken);
// Handle the successful login response
print(data);
// Navigate to the home page
Navigator.pushReplacementNamed(context, '/home');
} else {
// Handle the login error
print('Login failed: $responseBody');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(
labelText: 'Email',
),
),
SizedBox(height: 16.0),
TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(
labelText: 'Password',
),
),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
],
),
),
);
}
}
Output (Screen) for Login:
