feat: logout behavior
This commit is contained in:
parent
801698262b
commit
438c95746f
|
@ -1,9 +1,12 @@
|
|||
import 'package:get_it/get_it.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/login_vmod.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/logout_vmod.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/otp_vmod.dart';
|
||||
import 'package:rijig_mobile/features/auth/repositories/login_repository.dart';
|
||||
import 'package:rijig_mobile/features/auth/repositories/logout_repository.dart';
|
||||
import 'package:rijig_mobile/features/auth/repositories/otp_repository.dart';
|
||||
import 'package:rijig_mobile/features/auth/service/login_service.dart';
|
||||
import 'package:rijig_mobile/features/auth/service/logout_service.dart';
|
||||
import 'package:rijig_mobile/features/auth/service/otp_service.dart';
|
||||
|
||||
final sl = GetIt.instance;
|
||||
|
@ -11,4 +14,5 @@ final sl = GetIt.instance;
|
|||
void init() {
|
||||
sl.registerFactory(() => LoginViewModel(LoginService(LoginRepository())));
|
||||
sl.registerFactory(() => OtpViewModel(OtpService(OtpRepository())));
|
||||
sl.registerFactory(() => LogoutViewModel(LogoutService(LogoutRepository())));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'package:google_fonts/google_fonts.dart';
|
|||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
// =====================color schema=====================
|
||||
Color whiteColor = Color(0xffF0F1EA);
|
||||
Color whiteColor = Color(0xffFBFBFB);
|
||||
Color blackNavyColor = Color(0xff101010);
|
||||
Color primaryColor = Color(0xff018558);
|
||||
Color secondaryColor = Color(0xffBDE902);
|
||||
|
|
|
@ -75,7 +75,7 @@ class _NavigationPageState extends State<NavigationPage> {
|
|||
padding: PaddingCustom().paddingHorizontal(2),
|
||||
elevation: 0,
|
||||
height: 67,
|
||||
color: Colors.white,
|
||||
color: primaryColor,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
notchMargin: 3.0,
|
||||
child: BottomNavigationBar(
|
||||
|
@ -84,33 +84,33 @@ class _NavigationPageState extends State<NavigationPage> {
|
|||
elevation: 0,
|
||||
showSelectedLabels: true,
|
||||
showUnselectedLabels: true,
|
||||
selectedItemColor: Colors.blue,
|
||||
unselectedItemColor: Colors.grey,
|
||||
selectedItemColor: secondaryColor,
|
||||
unselectedItemColor: whiteColor,
|
||||
currentIndex: _selectedIndex,
|
||||
onTap: _onItemTapped,
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Iconsax.home_1, color: Colors.grey),
|
||||
activeIcon: Icon(Iconsax.home_1, color: Colors.blue),
|
||||
icon: Icon(Iconsax.home_2),
|
||||
activeIcon: Icon(Iconsax.home_2, size: 28),
|
||||
label: 'Beranda',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Iconsax.home, color: Colors.grey),
|
||||
activeIcon: Icon(Iconsax.home, color: Colors.blue),
|
||||
label: 'Pesan',
|
||||
icon: Icon(Iconsax.note_favorite),
|
||||
activeIcon: Icon(Iconsax.note_favorite, size: 28),
|
||||
label: 'Aktivitas',
|
||||
),
|
||||
const BottomNavigationBarItem(
|
||||
icon: SizedBox.shrink(),
|
||||
label: '',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Iconsax.document, color: Colors.grey),
|
||||
activeIcon: Icon(Iconsax.document, color: Colors.blue),
|
||||
label: 'Tutorial',
|
||||
icon: Icon(Iconsax.shopping_cart),
|
||||
activeIcon: Icon(Iconsax.shopping_cart, size: 28),
|
||||
label: 'Keranjang',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Iconsax.home, color: Colors.grey),
|
||||
activeIcon: Icon(Iconsax.home, color: Colors.blue),
|
||||
icon: Icon(Iconsax.user),
|
||||
activeIcon: Icon(Iconsax.user, size: 28),
|
||||
label: 'Profil',
|
||||
),
|
||||
],
|
||||
|
@ -129,7 +129,7 @@ class _NavigationPageState extends State<NavigationPage> {
|
|||
onPressed: () {
|
||||
router.push("/requestpickup");
|
||||
},
|
||||
backgroundColor: Colors.white,
|
||||
backgroundColor: primaryColor,
|
||||
shape: const CircleBorder(
|
||||
side: BorderSide(color: Colors.white, width: 4),
|
||||
),
|
||||
|
@ -142,8 +142,8 @@ class _NavigationPageState extends State<NavigationPage> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(Iconsax.home, color: primaryColor, size: 30),
|
||||
Text("data", style: TextStyle(color: blackNavyColor)),
|
||||
Icon(Iconsax.archive_2, color: whiteColor, size: 30),
|
||||
Text("mulai", style: TextStyle(color: whiteColor)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class LogoutResponse {
|
||||
final String message;
|
||||
|
||||
LogoutResponse({required this.message});
|
||||
|
||||
factory LogoutResponse.fromJson(Map<String, dynamic> json) {
|
||||
return LogoutResponse(message: json['meta']['message']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:rijig_mobile/features/auth/service/logout_service.dart';
|
||||
|
||||
class LogoutViewModel extends ChangeNotifier {
|
||||
final LogoutService _logoutService;
|
||||
|
||||
LogoutViewModel(this._logoutService);
|
||||
|
||||
bool isLoading = false;
|
||||
String? errorMessage;
|
||||
|
||||
Future<void> logout() async {
|
||||
isLoading = true;
|
||||
errorMessage = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
await _logoutService.logout();
|
||||
} catch (e) {
|
||||
errorMessage = "Error: ${e.toString()}";
|
||||
}
|
||||
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import 'package:rijig_mobile/core/api/api_services.dart';
|
||||
import 'package:rijig_mobile/features/auth/model/logout_model.dart';
|
||||
|
||||
class LogoutRepository {
|
||||
final Https _https = Https();
|
||||
|
||||
Future<LogoutResponse> logout() async {
|
||||
final response = await _https.post('/authmasyarakat/logout');
|
||||
return LogoutResponse.fromJson(response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:rijig_mobile/core/storage/secure_storage.dart';
|
||||
import 'package:rijig_mobile/features/auth/repositories/logout_repository.dart';
|
||||
|
||||
class LogoutService {
|
||||
final LogoutRepository _logoutRepository;
|
||||
final _storage = SecureStorage();
|
||||
|
||||
LogoutService(this._logoutRepository);
|
||||
|
||||
Future<void> clearSession() async {
|
||||
await _storage.deleteSecureData('token');
|
||||
await _storage.deleteSecureData('user_id');
|
||||
await _storage.deleteSecureData('user_role');
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
await _logoutRepository.logout();
|
||||
await clearSession();
|
||||
} catch (e) {
|
||||
throw Exception('Logout failed: $e');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:iconsax_flutter/iconsax_flutter.dart';
|
||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||
|
||||
class HomeHeader extends StatelessWidget {
|
||||
const HomeHeader({super.key});
|
||||
|
@ -12,33 +13,23 @@ class HomeHeader extends StatelessWidget {
|
|||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("Rijig", style: TextStyle(fontSize: 24)),
|
||||
Text("Rijig", style: Tulisan.heading(color: primaryColor)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Icon(Iconsax.notification),
|
||||
Gap(10),
|
||||
Icon(Iconsax.message),
|
||||
Icon(Iconsax.message_2),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
// IconBtnWithCounter(
|
||||
// svgSrc: "assets/icons/Cart Icon.svg",
|
||||
// press: () => Navigator.pushNamed(context, CartScreen.routeName),
|
||||
// ),
|
||||
// const SizedBox(width: 8),
|
||||
// IconBtnWithCounter(
|
||||
// svgSrc: "assets/icons/Bell.svg",
|
||||
// numOfitem: 3,
|
||||
// press: () {},
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:rijig_mobile/core/utils/guide.dart';
|
||||
import 'package:rijig_mobile/features/home/components/categories.dart';
|
||||
import 'package:rijig_mobile/features/home/components/discount_banner.dart';
|
||||
import 'package:rijig_mobile/features/home/components/home_header.dart';
|
||||
|
@ -15,7 +16,8 @@ class HomeScreen extends StatefulWidget {
|
|||
class _HomeScreenState extends State<HomeScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Scaffold(
|
||||
return Scaffold(
|
||||
backgroundColor: whiteColor,
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:rijig_mobile/core/router.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/logout_vmod.dart';
|
||||
import 'package:rijig_mobile/widget/buttoncard.dart';
|
||||
|
||||
class ProfilScreen extends StatefulWidget {
|
||||
const ProfilScreen({super.key});
|
||||
|
@ -14,21 +16,45 @@ class _ProfilScreenState extends State<ProfilScreen> {
|
|||
Widget build(BuildContext context) {
|
||||
final titleofscreen = "Profil";
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text("ini adalah halaman $titleofscreen"),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('isLoggedIn');
|
||||
router.go('/login');
|
||||
},
|
||||
child: Text("keluar"),
|
||||
body: Consumer<LogoutViewModel>(
|
||||
builder: (context, viewModel, child) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text("Are you sure you want to logout?"),
|
||||
SizedBox(height: 20),
|
||||
CardButtonOne(
|
||||
textButton: viewModel.isLoading ? 'Logging out...' : 'Logout',
|
||||
fontSized: 16,
|
||||
colorText: Colors.white,
|
||||
borderRadius: 10,
|
||||
horizontal: double.infinity,
|
||||
vertical: 50,
|
||||
onTap: () async {
|
||||
await viewModel.logout();
|
||||
|
||||
if (viewModel.errorMessage == null) {
|
||||
router.go("/login");
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(viewModel.errorMessage!)),
|
||||
);
|
||||
}
|
||||
},
|
||||
loadingTrue: viewModel.isLoading,
|
||||
usingRow: false,
|
||||
),
|
||||
if (viewModel.errorMessage != null)
|
||||
Text(
|
||||
viewModel.errorMessage!,
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:provider/provider.dart';
|
|||
import 'package:rijig_mobile/core/container/injection_container.dart';
|
||||
import 'package:rijig_mobile/core/router.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/login_vmod.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/logout_vmod.dart';
|
||||
import 'package:rijig_mobile/features/auth/presentation/viewmodel/otp_vmod.dart';
|
||||
|
||||
void main() async {
|
||||
|
@ -29,6 +30,7 @@ class MyApp extends StatelessWidget {
|
|||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => sl<LoginViewModel>()),
|
||||
ChangeNotifierProvider(create: (_) => sl<OtpViewModel>()),
|
||||
ChangeNotifierProvider(create: (_) => sl<LogoutViewModel>()),
|
||||
],
|
||||
child: ScreenUtilInit(
|
||||
designSize: const Size(375, 812),
|
||||
|
|
|
@ -19,7 +19,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
onPressed: () {
|
||||
router.pop();
|
||||
},
|
||||
icon: Icon(Iconsax.arrow_left_3_copy, color: whiteColor, size: 26),
|
||||
icon: Icon(Iconsax.arrow_circle_left, color: whiteColor, size: 26),
|
||||
),
|
||||
backgroundColor: primaryColor,
|
||||
elevation: 0,
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class InformationCard extends StatelessWidget {
|
||||
const InformationCard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 120,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF1F1F1F),
|
||||
borderRadius: BorderRadius.circular(12.0),
|
||||
),
|
||||
child: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Membership',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'594',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 27.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'US\$496',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 27.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Total members',
|
||||
style: TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Per month',
|
||||
style: TextStyle(color: Colors.white70, fontSize: 17.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -41,3 +41,4 @@ flutter:
|
|||
assets:
|
||||
- server/.env.dev
|
||||
- assets/image/
|
||||
- assets/icon/
|
||||
|
|
Loading…
Reference in New Issue