Merge branch 'fix/responsive' into 'master'
refactor: adjust spacing and improve layout across multiple screens See merge request profile-image/kedaireka/polinema-adapative-learning/mobile-adaptive-learning!29
This commit is contained in:
commit
dfeb41cf79
|
|
@ -21,6 +21,9 @@ class CustomButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenWidth = mediaQuery.size.width;
|
||||
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
|
|
@ -46,7 +49,7 @@ class CustomButton extends StatelessWidget {
|
|||
text,
|
||||
style: textStyle ??
|
||||
AppTextStyles.blackButtonTextStyle.copyWith(
|
||||
fontSize: 14,
|
||||
fontSize: screenWidth * 0.036,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -50,20 +50,23 @@ class CustomFieldWidget extends StatefulWidget {
|
|||
|
||||
class _CustomFieldWidgetState extends State<CustomFieldWidget> {
|
||||
late TextEditingController _controller;
|
||||
late ValidatorProvider _validatorProvider;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = widget.controller ?? TextEditingController();
|
||||
|
||||
context
|
||||
.read<ValidatorProvider>()
|
||||
.setController(widget.fieldName, _controller);
|
||||
// Simpan referensi provider di initState
|
||||
_validatorProvider = context.read<ValidatorProvider>();
|
||||
_validatorProvider.setController(widget.fieldName, _controller);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
context.read<ValidatorProvider>().removeController(widget.fieldName);
|
||||
// Gunakan referensi yang disimpan sebelumnya
|
||||
_validatorProvider.removeController(widget.fieldName);
|
||||
|
||||
if (widget.controller == null) {
|
||||
_controller.dispose();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.1)
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -19,8 +19,9 @@ class SigninScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _SigninScreenState extends State<SigninScreen> {
|
||||
final TextEditingController _loginController = TextEditingController();
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
late TextEditingController _loginController = TextEditingController();
|
||||
late TextEditingController _passwordController = TextEditingController();
|
||||
late ValidatorProvider _validatorProvider;
|
||||
final FocusNode _loginFocus = FocusNode();
|
||||
final FocusNode _passwordFocus = FocusNode();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
|
@ -28,16 +29,22 @@ class _SigninScreenState extends State<SigninScreen> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
context.read<ValidatorProvider>().setController('login', _loginController);
|
||||
context
|
||||
.read<ValidatorProvider>()
|
||||
.setController('password', _passwordController);
|
||||
_loginController = TextEditingController();
|
||||
_passwordController = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_validatorProvider = context.read<ValidatorProvider>();
|
||||
_validatorProvider.setController('login', _loginController);
|
||||
_validatorProvider.setController('password', _passwordController);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
context.read<ValidatorProvider>().removeController('login');
|
||||
context.read<ValidatorProvider>().removeController('password');
|
||||
_validatorProvider.removeController('login');
|
||||
_validatorProvider.removeController('password');
|
||||
|
||||
_loginController.dispose();
|
||||
_passwordController.dispose();
|
||||
|
|
@ -346,7 +353,7 @@ class _SigninScreenState extends State<SigninScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.02),
|
||||
SizedBox(height: screenHeight * 0.1),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ class LoginEmailField extends StatefulWidget {
|
|||
const LoginEmailField({super.key});
|
||||
|
||||
@override
|
||||
_LoginEmailFieldState createState() => _LoginEmailFieldState();
|
||||
LoginEmailFieldState createState() => LoginEmailFieldState();
|
||||
}
|
||||
|
||||
class _LoginEmailFieldState extends State<LoginEmailField> {
|
||||
class LoginEmailFieldState extends State<LoginEmailField> {
|
||||
late FocusNode _focusNode;
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -316,6 +316,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
|||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.1)
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -67,14 +67,18 @@ class HistoryProvider with ChangeNotifier {
|
|||
Future<void> fetchLearningHistory(String token) async {
|
||||
if (_sectionProvider.sections.isEmpty) {
|
||||
_error = 'No sections available';
|
||||
notifyListeners();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
notifyListeners();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
String sectionId = _sectionProvider.sections[_selectedPageIndex].id;
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
notifyListeners();
|
||||
});
|
||||
|
||||
try {
|
||||
final history = await _repository.getLearningHistory(sectionId, token);
|
||||
|
|
@ -85,7 +89,9 @@ class HistoryProvider with ChangeNotifier {
|
|||
_historyModel = [];
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -361,6 +361,9 @@ class _HomeContentState extends State<HomeContent> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenHeight = mediaQuery.size.height;
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: _initializeData,
|
||||
child: Consumer2<UserProvider, CompletedTopicsProvider>(
|
||||
|
|
@ -486,7 +489,7 @@ class _HomeContentState extends State<HomeContent> {
|
|||
return WelcomeCard(cardModel: cardData.cardData[index]);
|
||||
},
|
||||
options: CarouselOptions(
|
||||
height: 168,
|
||||
height: screenHeight * 0.19,
|
||||
viewportFraction: 0.9,
|
||||
enlargeCenterPage: true,
|
||||
autoPlay: true,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class IncompleteSubmission extends StatelessWidget {
|
|||
children: [
|
||||
Expanded(
|
||||
child: GlobalButton(
|
||||
text: 'Check Again',
|
||||
text: 'Check',
|
||||
textColor: AppColors.blueColor,
|
||||
borderColor: AppColors.blueColor,
|
||||
backgroundColor: Colors.transparent,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:english_learning/core/services/repositories/level_repository.dart';
|
||||
import 'package:english_learning/features/learning/modules/level/models/level_model.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class LevelProvider with ChangeNotifier {
|
||||
final LevelRepository _levelRepository = LevelRepository();
|
||||
|
|
@ -21,8 +21,9 @@ class LevelProvider with ChangeNotifier {
|
|||
Future<void> fetchLevels(String topicId, String token) async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
notifyListeners();
|
||||
});
|
||||
try {
|
||||
final result = await _levelRepository.getLevels(topicId, token);
|
||||
_levels = result['levels'];
|
||||
|
|
@ -37,7 +38,9 @@ class LevelProvider with ChangeNotifier {
|
|||
_error = 'Error fetching levels: ${e.toString()}';
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,18 @@ class LevelCard extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenHeight = mediaQuery.size.height;
|
||||
|
||||
return Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
elevation: 0,
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).size.height * 0.6,
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: screenHeight * 0.7,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
gradient: isAllowed
|
||||
|
|
@ -107,20 +112,20 @@ class LevelCard extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
// Score Display
|
||||
Text(
|
||||
// 'Score ${level.score}/100',
|
||||
'Score $score/100',
|
||||
style: AppTextStyles.whiteTextStyle.copyWith(
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const Spacer(), // Learn Now Button
|
||||
const Spacer(),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
),
|
||||
child: CustomButton(
|
||||
text: isAllowed ? 'Learn Now' : 'Locked',
|
||||
textStyle:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ class PretestCard extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenHeight = mediaQuery.size.height;
|
||||
|
||||
return Consumer<LevelProvider>(builder: (context, levelProvider, _) {
|
||||
final isFinished = levelProvider.isPretestFinished(pretest.idLevel);
|
||||
final score = levelProvider.getPretestScore(pretest.idLevel);
|
||||
|
|
@ -80,7 +83,9 @@ class PretestCard extends StatelessWidget {
|
|||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4, horizontal: 8),
|
||||
vertical: 4,
|
||||
horizontal: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color:
|
||||
|
|
@ -125,7 +130,7 @@ class PretestCard extends StatelessWidget {
|
|||
Flexible(
|
||||
child: Image.asset(
|
||||
'lib/features/learning/modules/level/assets/images/pretest_level_illustration.png',
|
||||
height: 95,
|
||||
height: screenHeight * 0.13,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,22 +5,42 @@ import 'package:flutter/foundation.dart';
|
|||
class SectionProvider extends ChangeNotifier {
|
||||
final SectionRepository _repository = SectionRepository();
|
||||
List<Section> _sections = [];
|
||||
final bool _isLoading = false;
|
||||
bool _isLoading = false;
|
||||
dynamic _error;
|
||||
|
||||
List<Section> get sections => _sections;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
|
||||
Future<List<Section>> fetchSections(String token) async {
|
||||
void resetData() {
|
||||
_sections = [];
|
||||
_error = null;
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> fetchSections(String token) async {
|
||||
try {
|
||||
// Set loading state
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
// Fetch sections
|
||||
_sections = await _repository.getSections(token);
|
||||
|
||||
// Reset loading state
|
||||
_isLoading = false;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
return _sections;
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
// Handle error
|
||||
_isLoading = false;
|
||||
_error = e;
|
||||
notifyListeners();
|
||||
return [];
|
||||
|
||||
// Rethrow the error to be handled by the caller
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ class _LearningScreenState extends State<LearningScreen>
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeSections();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_initializeSections();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _initializeSections() async {
|
||||
|
|
@ -32,45 +34,91 @@ class _LearningScreenState extends State<LearningScreen>
|
|||
final sectionProvider =
|
||||
Provider.of<SectionProvider>(context, listen: false);
|
||||
|
||||
// Cek apakah sections sudah ada
|
||||
if (sectionProvider.sections.isEmpty) {
|
||||
try {
|
||||
final token = await userProvider.getValidToken();
|
||||
if (token != null) {
|
||||
await sectionProvider.fetchSections(token);
|
||||
}
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
} finally {
|
||||
setState(() {
|
||||
_isInitialLoading = false;
|
||||
});
|
||||
try {
|
||||
// Reset data sebelum fetch
|
||||
sectionProvider.resetData(); // Tambahkan method ini di SectionProvider
|
||||
|
||||
final token = await userProvider.getValidToken();
|
||||
if (token != null) {
|
||||
await sectionProvider.fetchSections(token);
|
||||
}
|
||||
} else {
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to load data: ${e.toString()}'),
|
||||
action: SnackBarAction(
|
||||
label: 'Retry',
|
||||
onPressed: _initializeSections,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
setState(() {
|
||||
_isInitialLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refreshSections() async {
|
||||
final userProvider = Provider.of<UserProvider>(context, listen: false);
|
||||
final sectionProvider =
|
||||
Provider.of<SectionProvider>(context, listen: false);
|
||||
// Future<void> _refreshSections() async {
|
||||
// final userProvider = Provider.of<UserProvider>(context, listen: false);
|
||||
// final sectionProvider =
|
||||
// Provider.of<SectionProvider>(context, listen: false);
|
||||
|
||||
try {
|
||||
final token = await userProvider.getValidToken();
|
||||
if (token != null) {
|
||||
await sectionProvider.fetchSections(token);
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to refresh sections: $e'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
// try {
|
||||
// final token = await userProvider.getValidToken();
|
||||
// if (token != null) {
|
||||
// await sectionProvider.fetchSections(token);
|
||||
// }
|
||||
// } catch (e) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text('Failed to refresh sections: $e'),
|
||||
// backgroundColor: Colors.red,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
Widget _buildErrorWidget(String error) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error_outline,
|
||||
size: 48,
|
||||
color: Colors.red[300],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Oops! Something went wrong',
|
||||
style: AppTextStyles.blackTextStyle.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
error,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppTextStyles.disableTextStyle.copyWith(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: _initializeSections,
|
||||
icon: const Icon(Icons.refresh),
|
||||
label: const Text('Retry'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -115,35 +163,13 @@ class _LearningScreenState extends State<LearningScreen>
|
|||
|
||||
// Tampilkan error jika ada
|
||||
if (sectionProvider.error != null) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: _refreshSections,
|
||||
child: ListView(
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Error: ${sectionProvider.error}',
|
||||
style: AppTextStyles.greyTextStyle,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _refreshSections,
|
||||
child: const Text('Retry'),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return _buildErrorWidget(sectionProvider.error!);
|
||||
}
|
||||
|
||||
// Tampilkan sections atau pesan jika kosong
|
||||
if (sectionProvider.sections.isEmpty) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: _refreshSections,
|
||||
onRefresh: _initializeSections,
|
||||
child: ListView(
|
||||
children: [
|
||||
Center(
|
||||
|
|
@ -165,7 +191,7 @@ class _LearningScreenState extends State<LearningScreen>
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: _refreshSections,
|
||||
onPressed: _initializeSections,
|
||||
child: const Text('Refresh'),
|
||||
)
|
||||
],
|
||||
|
|
@ -178,7 +204,7 @@ class _LearningScreenState extends State<LearningScreen>
|
|||
|
||||
// Tampilkan daftar sections
|
||||
return RefreshIndicator(
|
||||
onRefresh: _refreshSections,
|
||||
onRefresh: _initializeSections,
|
||||
child: ListView.builder(
|
||||
itemCount: sectionProvider.sections.length,
|
||||
itemBuilder: (context, index) {
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
|||
currentPage: _currentPage,
|
||||
itemCount: controller.onBoardingData.length,
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.2),
|
||||
SizedBox(height: screenHeight * 0.08),
|
||||
if (_currentPage == controller.onBoardingData.length - 1)
|
||||
Column(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -51,92 +51,92 @@ class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
|
|||
),
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
child: Consumer<ValidatorProvider>(
|
||||
builder: (context, validatorProvider, child) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 22.0,
|
||||
body: SingleChildScrollView(child: Consumer<ValidatorProvider>(
|
||||
builder: (
|
||||
context,
|
||||
validatorProvider,
|
||||
child,
|
||||
) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 22.0,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'Old Password',
|
||||
hintText: 'Enter your old password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'Old Password',
|
||||
obscureText: true,
|
||||
controller: _oldPasswordController,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'Old Password',
|
||||
hintText: 'Enter your old password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'Old Password',
|
||||
obscureText: true,
|
||||
controller: _oldPasswordController,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'New Password',
|
||||
hintText: 'Enter your new password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'new password',
|
||||
obscureText: true,
|
||||
controller: _newPasswordController,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'Confirm New Password',
|
||||
hintText: 'Retype your new password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'confirm new password',
|
||||
obscureText: true,
|
||||
controller: _confirmPasswordController,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
GlobalButton(
|
||||
text: 'Update Now',
|
||||
onPressed: () async {
|
||||
final userProvider =
|
||||
Provider.of<UserProvider>(context, listen: false);
|
||||
bool success = await userProvider.updatePassword(
|
||||
oldPassword: _oldPasswordController.text,
|
||||
newPassword: _newPasswordController.text,
|
||||
confirmPassword: _confirmPasswordController.text,
|
||||
);
|
||||
const SizedBox(height: 12),
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'New Password',
|
||||
hintText: 'Enter your new password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'new password',
|
||||
obscureText: true,
|
||||
controller: _newPasswordController,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
CustomFieldWidget(
|
||||
isRequired: true,
|
||||
labelText: 'Confirm New Password',
|
||||
hintText: 'Retype your new password',
|
||||
textInputAction: TextInputAction.next,
|
||||
fieldName: 'confirm new password',
|
||||
obscureText: true,
|
||||
controller: _confirmPasswordController,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
GlobalButton(
|
||||
text: 'Update Now',
|
||||
onPressed: () async {
|
||||
final userProvider =
|
||||
Provider.of<UserProvider>(context, listen: false);
|
||||
bool success = await userProvider.updatePassword(
|
||||
oldPassword: _oldPasswordController.text,
|
||||
newPassword: _newPasswordController.text,
|
||||
confirmPassword: _confirmPasswordController.text,
|
||||
);
|
||||
|
||||
if (success) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return ChangePasswordDialog(
|
||||
onSubmit: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const SigninScreen()),
|
||||
(route) => false,
|
||||
);
|
||||
},
|
||||
if (success) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return ChangePasswordDialog(
|
||||
onSubmit: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SigninScreen()),
|
||||
(route) => false,
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
CustomSnackBar.show(
|
||||
context,
|
||||
message:
|
||||
'Failed to update password. Please try again.',
|
||||
isError: true,
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
CustomSnackBar.show(
|
||||
context,
|
||||
message: 'Failed to update password. Please try again.',
|
||||
isError: true,
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenHeight = mediaQuery.size.height;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -196,6 +199,7 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
|||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.05),
|
||||
],
|
||||
));
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class LogoutConfirmation extends StatelessWidget {
|
|||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: GlobalButton(
|
||||
text: 'Yes, logout!',
|
||||
text: 'Yes',
|
||||
onPressed: onSubmit,
|
||||
textColor: AppColors.whiteColor,
|
||||
backgroundColor: AppColors.redColor,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ class SettingsScreen extends StatefulWidget {
|
|||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final screenHeight = mediaQuery.size.height;
|
||||
final screenWidth = mediaQuery.size.width;
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.bgSoftColor,
|
||||
body: Consumer<UserProvider>(builder: (context, userProvider, child) {
|
||||
|
|
@ -35,7 +38,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 210,
|
||||
height: screenHeight * 0.33,
|
||||
decoration: BoxDecoration(
|
||||
gradient: AppColors.gradientTheme,
|
||||
borderRadius: const BorderRadius.only(
|
||||
|
|
@ -44,8 +47,12 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 71.0, left: 26, right: 16.0, bottom: 19.0),
|
||||
padding: EdgeInsets.only(
|
||||
top: screenHeight * 0.1,
|
||||
left: screenWidth * 0.07,
|
||||
right: screenWidth * 0.04,
|
||||
bottom: screenHeight * 0.03,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
|
|
@ -54,7 +61,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
Row(
|
||||
children: [
|
||||
UserAvatar(
|
||||
radius: 60,
|
||||
radius: screenWidth * 0.15,
|
||||
pictureUrl: userProvider.userData?['PICTURE'],
|
||||
baseUrl: '${mediaUrl}avatar/',
|
||||
onImageSelected: (File image) {
|
||||
|
|
@ -63,7 +70,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
selectedImage: userProvider.selectedImage,
|
||||
isLoading: userProvider.isLoading,
|
||||
),
|
||||
const SizedBox(width: 28),
|
||||
const SizedBox(width: 16),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -72,7 +79,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
'Loading...',
|
||||
style:
|
||||
AppTextStyles.whiteTextStyle.copyWith(
|
||||
fontSize: 18,
|
||||
fontSize: screenWidth * 0.05,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
|
|
@ -82,9 +89,11 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||
'Loading...',
|
||||
style:
|
||||
AppTextStyles.whiteTextStyle.copyWith(
|
||||
fontSize: 14,
|
||||
fontSize: screenWidth * 0.036,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class WelcomeScreen extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: screenHeight * 0.1),
|
||||
SizedBox(height: screenHeight * 0.05),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user