[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: