feat: user pin setup uncompletely yet

This commit is contained in:
pahmiudahgede 2025-05-03 16:14:51 +07:00
parent f620157de8
commit da4191408d
7 changed files with 164 additions and 172 deletions

View File

@ -27,7 +27,7 @@ final router = GoRouter(
return VerifotpScreen(phone: phone!); return VerifotpScreen(phone: phone!);
}, },
), ),
GoRoute(path: '/setpin', builder: (context, state) => UserPinScreen()), GoRoute(path: '/setpin', builder: (context, state) => SetPinScreen()),
GoRoute(path: '/verifpin', builder: (context, state) => VerifPinScreen()), GoRoute(path: '/verifpin', builder: (context, state) => VerifPinScreen()),
GoRoute( GoRoute(
path: '/navigasi', path: '/navigasi',

View File

@ -1,34 +1,31 @@
import 'package:rijig_mobile/core/api_services.dart'; import 'package:rijig_mobile/core/api_services.dart';
import 'package:rijig_mobile/model/response_model.dart';
class PinModel { class PinModel {
final ApiService _apiService = ApiService(); final ApiService _apiService = ApiService();
Future<bool> checkPinStatus() async { Future<ResponseModel?> checkPinStatus(String userId) async {
try { try {
var response = await _apiService.get('/cek-pin-status'); var response = await _apiService.get('/cek-pin-status');
if (response['meta']['status'] == 200) { return ResponseModel.fromJson(response);
return true;
} else {
return false;
}
} catch (e) { } catch (e) {
rethrow; rethrow;
} }
} }
Future<bool> setPin(String userPin) async { Future<ResponseModel?> setPin(String pin) async {
try { try {
var response = await _apiService.post('/set-pin', {'userpin': userPin}); var response = await _apiService.post('/set-pin', {'userpin': pin});
return response['meta']['status'] == 201; return ResponseModel.fromJson(response);
} catch (e) { } catch (e) {
rethrow; rethrow;
} }
} }
Future<bool> verifyPin(String userPin) async { Future<ResponseModel?> verifyPin(String pin) async {
try { try {
var response = await _apiService.post('/verif-pin', {'userpin': userPin}); var response = await _apiService.post('/verif-pin', {'userpin': pin});
return response['meta']['status'] == 200; return ResponseModel.fromJson(response);
} catch (e) { } catch (e) {
rethrow; rethrow;
} }

View File

@ -1,87 +1,54 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rijig_mobile/core/guide.dart';
import 'package:rijig_mobile/core/router.dart'; import 'package:rijig_mobile/core/router.dart';
import 'package:rijig_mobile/viewmodel/userpin_vmod.dart'; import 'package:rijig_mobile/viewmodel/userpin_vmod.dart';
class UserPinScreen extends StatefulWidget { class SetPinScreen extends StatefulWidget {
const UserPinScreen({super.key}); const SetPinScreen({super.key});
@override @override
State<UserPinScreen> createState() => _UserPinScreenState(); SetPinScreenState createState() => SetPinScreenState();
} }
class _UserPinScreenState extends State<UserPinScreen> { class SetPinScreenState extends State<SetPinScreen> {
final TextEditingController _pinController = TextEditingController(); final _pinController = TextEditingController();
final _formKey = GlobalKey<FormState>();
String errorMessage = '';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final pinViewModel = Provider.of<PinViewModel>(context); final pinViewModel = Provider.of<PinViewModel>(context);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text("Buat PIN Pengguna")), appBar: AppBar(title: Text("Buat PIN Baru")),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Form( child: Column(
key: _formKey, crossAxisAlignment: CrossAxisAlignment.start,
child: Column( children: [
mainAxisAlignment: MainAxisAlignment.center, Text("Buat PIN Anda (6 digit)", style: TextStyle(fontSize: 18)),
children: [ SizedBox(height: 20),
TextFormField( TextField(
controller: _pinController, controller: _pinController,
decoration: const InputDecoration(labelText: 'Masukkan PIN'), decoration: InputDecoration(labelText: "PIN"),
obscureText: true, keyboardType: TextInputType.number,
maxLength: 6, obscureText: true,
keyboardType: TextInputType.number, ),
validator: (value) { SizedBox(height: 20),
if (value == null || value.isEmpty) { ElevatedButton(
return 'PIN harus diisi'; onPressed: () async {
} else if (value.length != 6) { String pin = _pinController.text;
return 'PIN harus 6 digit';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
final pin = _pinController.text;
bool pinCreated = await pinViewModel.checkPinStatus(); await pinViewModel.createPin(pin);
if (pinViewModel.pinExists == true) {
if (!pinCreated) { router.go('/navigasi');
bool pinSet = await pinViewModel.setPin(pin); } else {
if (pinSet) { ScaffoldMessenger.of(
router.go('/navigasi'); context,
} else { ).showSnackBar(SnackBar(content: Text('Gagal membuat PIN')));
setState(() { }
errorMessage = 'Gagal membuat PIN'; },
}); child: Text("Buat PIN"),
} ),
} else { ],
bool pinVerified = await pinViewModel.verifyPin(pin);
if (pinVerified) {
router.go('/navigasi');
} else {
setState(() {
errorMessage = 'PIN yang anda masukkan salah';
});
}
}
}
},
child: const Text('Kirim'),
),
if (errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(errorMessage, style: TextStyle(color: redColor)),
),
],
),
), ),
), ),
); );

View File

@ -3,6 +3,7 @@ import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:rijig_mobile/core/router.dart'; import 'package:rijig_mobile/core/router.dart';
import 'package:rijig_mobile/viewmodel/auth_vmod.dart'; import 'package:rijig_mobile/viewmodel/auth_vmod.dart';
import 'package:rijig_mobile/viewmodel/userpin_vmod.dart';
import 'package:rijig_mobile/widget/buttoncard.dart'; import 'package:rijig_mobile/widget/buttoncard.dart';
class VerifotpScreen extends StatefulWidget { class VerifotpScreen extends StatefulWidget {
@ -19,7 +20,9 @@ class _VerifotpScreenState extends State<VerifotpScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final viewModel = Provider.of<AuthViewModel>(context);
final authViewModel = Provider.of<AuthViewModel>(context);
final pinViewModel = Provider.of<PinViewModel>(context);
return Scaffold( return Scaffold(
body: SafeArea( body: SafeArea(
child: Padding( child: Padding(
@ -58,34 +61,42 @@ class _VerifotpScreenState extends State<VerifotpScreen> {
horizontal: double.infinity, horizontal: double.infinity,
vertical: 50, vertical: 50,
onTap: () { onTap: () {
// if (_otpController.text.isNotEmpty) {
// viewModel.verifyOtp(widget.phone, _otpController.text).then(
// (_) {
// if (viewModel.errorMessage == null) {
// router.go('/navigasi');
// } else {
// debugPrint(viewModel.errorMessage ?? '');
// }
// },
// );
// }
if (_otpController.text.isNotEmpty) { authViewModel.verifyOtp(widget.phone, _otpController.text).then((
viewModel.verifyOtp(widget.phone, _otpController.text).then( _,
(_) { ) {
if (viewModel.errorMessage == null) {
if (viewModel.pinExists == false) { pinViewModel
.checkPinStatus(
authViewModel.authModel?.data?['user_id'],
)
.then((_) {
if (pinViewModel.pinExists == false) {
router.go('/setpin'); router.go('/setpin');
} else { } else if (pinViewModel.pinExists == true) {
router.go('/verifpin'); router.go('/verifpin');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gagal memverifikasi status PIN'),
),
);
} }
} else { });
debugPrint(viewModel.errorMessage ?? ''); });
}
},
);
}
}, },
loadingTrue: viewModel.isLoading, loadingTrue: authViewModel.isLoading,
usingRow: false, usingRow: false,
), ),
], ],

View File

@ -7,72 +7,52 @@ class VerifPinScreen extends StatefulWidget {
const VerifPinScreen({super.key}); const VerifPinScreen({super.key});
@override @override
State<VerifPinScreen> createState() => _VerifPinScreenState(); VerifPinScreenState createState() => VerifPinScreenState();
} }
class _VerifPinScreenState extends State<VerifPinScreen> { class VerifPinScreenState extends State<VerifPinScreen> {
final TextEditingController _pinController = TextEditingController(); final _pinController = TextEditingController();
final _formKey = GlobalKey<FormState>();
String errorMessage = '';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final pinViewModel = Provider.of<PinViewModel>(context); final pinViewModel = Provider.of<PinViewModel>(context);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text("Verifikasi PIN")), appBar: AppBar(title: Text("Verifikasi PIN")),
body: SafeArea( body: Padding(
child: Padding( padding: const EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16.0), child: Column(
child: Form( crossAxisAlignment: CrossAxisAlignment.start,
key: _formKey, children: [
child: Column( Text(
mainAxisAlignment: MainAxisAlignment.center, "Masukkan PIN yang sudah dibuat",
children: [ style: TextStyle(fontSize: 18),
TextFormField(
controller: _pinController,
decoration: const InputDecoration(labelText: 'Masukkan PIN'),
obscureText: true,
maxLength: 6,
keyboardType: TextInputType.number,
validator: (value) {
if (value == null || value.isEmpty) {
return 'PIN harus diisi';
} else if (value.length != 6) {
return 'PIN harus 6 digit';
}
return null;
},
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.validate() ?? false) {
final pin = _pinController.text;
bool pinVerified = await pinViewModel.verifyPin(pin);
if (pinVerified) {
router.go('/navigasi');
} else {
setState(() {
errorMessage = 'PIN yang Anda masukkan salah';
});
}
}
},
child: const Text('Kirim'),
),
if (errorMessage.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(
errorMessage,
style: const TextStyle(color: Colors.red),
),
),
],
), ),
), SizedBox(height: 20),
TextField(
controller: _pinController,
decoration: InputDecoration(labelText: "PIN"),
keyboardType: TextInputType.number,
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// String userId = 'user_id_here';
String pin = _pinController.text;
await pinViewModel.verifyPin(pin);
if (pinViewModel.pinExists == true) {
router.go('/navigasi');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('PIN yang anda masukkan salah')),
);
}
},
child: Text("Verifikasi PIN"),
),
],
), ),
), ),
); );

View File

@ -64,7 +64,16 @@ class AuthViewModel extends ChangeNotifier {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLoggedIn', true); await prefs.setBool('isLoggedIn', true);
pinExists = await _pinModel.checkPinStatus();
var pinStatusResponse = await _pinModel.checkPinStatus(
response.data?['user_id'],
);
if (pinStatusResponse?.status == 200) {
pinExists = true;
} else {
pinExists = false;
}
authModel = response; authModel = response;
notifyListeners(); notifyListeners();

View File

@ -2,29 +2,57 @@ import 'package:flutter/material.dart';
import 'package:rijig_mobile/model/userpin_model.dart'; import 'package:rijig_mobile/model/userpin_model.dart';
class PinViewModel extends ChangeNotifier { class PinViewModel extends ChangeNotifier {
final PinModel _pinService = PinModel(); final PinModel _pinModel = PinModel();
bool? pinExists;
Future<bool> checkPinStatus() async { Future<void> checkPinStatus(String userId) async {
try { try {
return await _pinService.checkPinStatus(); var response = await _pinModel.checkPinStatus(userId);
if (response?.status == 200) {
pinExists = true;
} else {
pinExists = false;
}
notifyListeners();
} catch (e) { } catch (e) {
throw Exception('Error checking PIN status: $e'); debugPrint('Error checking pin status: $e');
pinExists = false;
notifyListeners();
} }
} }
Future<bool> setPin(String userPin) async { Future<void> createPin(String pin) async {
try { try {
return await _pinService.setPin(userPin); var response = await _pinModel.setPin(pin);
if (response?.status == 201) {
pinExists = true;
} else {
pinExists = false;
}
notifyListeners();
} catch (e) { } catch (e) {
throw Exception('Error setting PIN: $e'); debugPrint('Error creating pin: $e');
pinExists = false;
notifyListeners();
} }
} }
Future<bool> verifyPin(String userPin) async { Future<void> verifyPin(String pin) async {
try { try {
return await _pinService.verifyPin(userPin); var response = await _pinModel.verifyPin(pin);
if (response?.status == 200) {
pinExists = true;
} else {
pinExists = false;
}
notifyListeners();
} catch (e) { } catch (e) {
throw Exception('Error verifying PIN: $e'); debugPrint('Error verifying pin: $e');
pinExists = false;
notifyListeners();
} }
} }
} }