app bar & chip

pull/1/head
aamir-csol 2 months ago
parent 255d189ce1
commit 4d76b34608

@ -37,3 +37,5 @@ enum SelectionType { dropdown, calendar }
enum GenderType { male, female }
enum MaritalStatusType { single, married, divorced, widowed }
enum ChipType { success, error, alert, info, warning }

@ -1,3 +1,4 @@
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
@ -189,3 +190,37 @@ Widget widthSpacer3per() => SizedBox(height: 3.w);
Widget widthSpacer4per() => SizedBox(height: 4.w);
Widget widthSpacer5per() => SizedBox(height: 5.w);
extension ChipTypeExtension on ChipType {
Color get color {
switch (this) {
case ChipType.success:
return AppColors.successColor; // Replace with your actual color
case ChipType.error:
return AppColors.errorColor; // Replace with your actual color
case ChipType.alert:
return AppColors.alertColor; // Replace with your actual color
case ChipType.info:
return AppColors.infoColor; // Replace with your actual color
case ChipType.warning:
return AppColors.warningColor; // Replace with your actual color
}
}
Color get backgroundColor {
switch (this) {
case ChipType.success:
return AppColors.successLightColor; // Replace with your actual color
case ChipType.error:
return AppColors.errorLightColor; // Replace with your actual color
case ChipType.alert:
return AppColors.alertLightColor; // Replace with your actual color
case ChipType.info:
return AppColors.infoLightColor; // Replace with your actual color
case ChipType.warning:
return AppColors.warningLightColor; // Replace with your actual color
}
}
}

@ -12,6 +12,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/app_bar_widget.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/input_widget.dart';
import 'package:hmg_patient_app_new/widgets/language_switcher.dart';
import 'package:sizer/sizer.dart'; // Import sizer
class LoginScreen extends StatefulWidget {
@override
@ -31,59 +32,42 @@ class _LoginScreen extends State<LoginScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
onBackPressed: () {
Navigator.of(context).pop();
},
onLanguageChanged: (String value) {
print(value);
context.setLocale(value == 'en' ? Locale('ar', 'SA') : Locale('en', 'US'));
},
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus(); // Dismiss the keyboard when tapping outside
},
child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith(overscroll: false, physics: const ClampingScrollPhysics()),
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (notification) {
notification.disallowIndicator();
return true;
},
child: SingleChildScrollView(
physics: ClampingScrollPhysics(), // Remove NeverScrollableScrollPhysics()
padding: EdgeInsets.only(
left: 24,
right: 24,
),
return Sizer(// Wrap with Sizer
builder: (context, orientation, deviceType) {
return Scaffold(
appBar: CustomAppBar(
onBackPressed: () {
// Navigator.of(context).pop();
},
onLanguageChanged: (String value) {
print(value);
context.setLocale(value == 'en' ? Locale('ar', 'SA') : Locale('en', 'US'));
},
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus(); // Dismiss the keyboard when tapping outside
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 6.w, right: 6.w),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.showLottie(
context: context,
assetPath: AppAnimations.login,
width: MediaQuery.of(context).size.width * 0.45,
height: MediaQuery.of(context).size.height * 0.22,
repeat: true,
fit: BoxFit.cover),
Flexible(
fit: FlexFit.loose,
child: Container(height: MediaQuery.of(context).size.height * 0.18),
),
Utils.showLottie(context: context, assetPath: AppAnimations.login, width: 45.w, height: 22.h, repeat: true, fit: BoxFit.cover),
SizedBox(height: 19.h), // Adjusted to sizer unit
Text(
LocaleKeys.welcomeToDrSulaiman.tr(),
style: context.dynamicTextStyle(
fontSize: 28,
fontSize: 22.sp,
fontWeight: FontWeight.w600,
color: Color(0xff2B353E),
color: AppColors.textColor,
letterSpacing: -0.4,
height: 40 / 28,
),
),
SizedBox(height: 32),
SizedBox(height: 4.h), // Adjusted to sizer unit (approx 32px)
TextInputWidget(
labelText: "${LocaleKeys.nationalId.tr()} / ${LocaleKeys.fileNo.tr()}",
hintText: "xxxxxxxxx",
@ -94,25 +78,27 @@ class _LoginScreen extends State<LoginScreen> {
autoFocus: true,
isBorderAllowed: false,
isAllowLeadingIcon: true,
padding: EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8),
padding: EdgeInsets.symmetric(vertical: 1.h, horizontal: 2.w),
leadingIcon: AppAssets.student_card,
errorMessage: "Please enter a valid national ID or file number",
hasError: true,
),
SizedBox(height: 16),
SizedBox(height: 2.h), // Adjusted to sizer unit (approx 16px)
CustomButton(
text: LocaleKeys.login.tr(),
icon: AppAssets.login1,
iconColor: Colors.white,
onPressed: () {},
),
SizedBox(height: 14),
SizedBox(height: 1.8.h), // Adjusted to sizer unit (approx 14px)
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: context.dynamicTextStyle(
color: Colors.black,
fontSize: 16,
height: 26 / 16,
fontSize: 14.sp, // Adjusted to sizer unit
height: 26 / 16, // This height is a ratio, may need re-evaluation
fontWeight: FontWeight.w500,
),
children: <TextSpan>[
@ -121,23 +107,23 @@ class _LoginScreen extends State<LoginScreen> {
TextSpan(
text: LocaleKeys.registernow.tr(),
style: context.dynamicTextStyle(
color: AppColors.bgRedColor,
fontSize: 16,
height: 26 / 16,
color: AppColors.primaryRedColor,
fontSize: 14.sp, // Adjusted to sizer unit
height: 26 / 16, // Ratio
fontWeight: FontWeight.w500,
),
recognizer: TapGestureRecognizer()..onTap = () {},
),
],
),
).withVerticalPadding(16),
).withVerticalPadding(2.h), // Adjusted to sizer unit
),
],
),
),
),
),
),
);
);
});
}
}

@ -74,7 +74,7 @@ class _SplashScreenState extends State<SplashPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xffF8F8F8),
backgroundColor: AppColors.whiteColor,
body: Stack(
alignment: Alignment.center,
children: [
@ -89,7 +89,7 @@ class _SplashScreenState extends State<SplashPage> {
children: [
Text(
"Powered by",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.powerdBy, letterSpacing: -0.56, height: 16 / 14),
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: AppColors.textColor, letterSpacing: -0.56, height: 16 / 14),
),
SizedBox(
height: 5,

@ -1,30 +1,46 @@
import 'package:flutter/material.dart';
class AppColors {
static const mainPurple = Color(0xFF7954F7);
static const purpleBg = Color(0xFFAEA4FC);
static const deepPurple = Color(0xFF7C65E7);
static const logoColor = Color(0xFF7C65E7);
static const buttonColor = Color(0xFF6A46F5);
static const splashBgColor = Color(0xFF3C355D);
static const whiteColor = Color(0xFFffffff);
static const blackColor = Color(0xFF000000);
static const lightGray = Color(0xFFF4F5F7);
static const lightPurple = Color(0xFFB7A3E6);
static const scaffoldBgColor = Color(0xFFF8F8F8);
static const lightGreyEFColor = Color(0xffeaeaff);
static const greyF7Color = Color(0xffF7F7F7);
static const lightGrayColor = Color(0xff808080);
static const buttonGrayColor = Color(0xffF1F1F1);
static const lightPurpleAlpha = Color(0x5AB7A3E6);
static const mainPurple = Color(0xFF7954F7);
static const purpleBg = Color(0xFFAEA4FC);
static const deepPurple = Color(0xFF7C65E7);
static const logoColor = Color(0xFF7C65E7);
static const buttonColor = Color(0xFF6A46F5);
static const splashBgColor = Color(0xFF3C355D);
static const blackColor = Color(0xFF000000);
static const lightGray = Color(0xFFF4F5F7);
static const lightPurple = Color(0xFFB7A3E6);
static const scaffoldBgColor = Color(0xFFF8F8F8);
static const lightGreyEFColor = Color(0xffeaeaff);
static const greyF7Color = Color(0xffF7F7F7);
static const lightGrayColor = Color(0xff808080);
static const buttonGrayColor = Color(0xffF1F1F1);
static const lightPurpleAlpha = Color(0x5AB7A3E6);
// New UI Colors
static const Color bgRedColor = Color(0xFFED1C2B);
static const Color bgRedBorderColor = Color(0xFFED1C2B);
static const whiteColor = Color(0xFFffffff);
static const Color primaryRedColor = Color(0xFFED1C2B);
static const Color primaryRedBorderColor = Color(0xFFED1C2B);
static const Color secondaryLightRedColor = Color(0xFFFEE9EA);
static const Color secondaryLightRedBorderColor = Color(0xFFFEE9EA);
static const Color bgRedLightColor = Color(0xFFFEE9EA);
static const Color bgGreenColor = Color(0xFF18C273);
static const Color powerdBy = Color(0xFF333C45);
}
static const Color textColor = Color(0xFF2E3039);
static const Color borderOnlyColor = Color(0xFF2E3039);
//Chips
static const Color successColor = Color(0xff18C273);
static const Color errorColor = Color(0xFFED1C2B);
static const Color alertColor = Color(0xFFD48D05);
static const Color infoColor = Color(0xFF0B85F7);
static const Color warningColor = Color(0xFFFFCC00);
static const Color greyColor = Color(0xFFEFEFF0);
static const Color successLightColor = Color(0xFF18C27326);
static const Color errorLightColor = Color(0xFFED1C2B1A);
static const Color alertLightColor = Color(0xFFD48D0526);
static const Color infoLightColor = Color(0xFF0B85F726);
static const Color warningLightColor = Color(0xFFFFCC0026);
static const Color greyLightColor = Color(0xFFEFEFF026);
}

@ -28,12 +28,17 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Arrow Back with click handler
GestureDetector(
onTap: onBackPressed,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
width: 32,
height: 32,
Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: GestureDetector(
onTap: onBackPressed,
child: Utils.buildSvgWithAssets(
icon: AppAssets.arrow_back,
width: 32,
height: 32,
),
),
),
),
@ -43,14 +48,19 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
),
// Language Selector
LanguageSelector(
currentLanguage: context.locale.languageCode,
showOnlyIcon: false,
onLanguageChanged: onLanguageChanged,
languages: [
{'code': 'ar', 'name': LocaleKeys.arabic.tr()},
{'code': 'en', 'name': LocaleKeys.english.tr()}
],
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: LanguageSelector(
currentLanguage: context.locale.languageCode,
showOnlyIcon: false,
onLanguageChanged: onLanguageChanged,
languages: [
{'code': 'ar', 'name': LocaleKeys.arabic.tr()},
{'code': 'en', 'name': LocaleKeys.english.tr()}
],
),
),
),
],
),

@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/enums.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
class CustomChipWidget extends StatelessWidget {
final ChipType chipType;
final String chipText;
final String? iconAsset;
final VoidCallback? onTap;
final bool isSelected;
final double borderRadius;
final EdgeInsetsGeometry padding;
const CustomChipWidget({
Key? key,
required this.chipType,
required this.chipText,
this.iconAsset,
this.onTap,
this.isSelected = false,
this.borderRadius = 12,
this.padding = const EdgeInsets.all(8),
}) : super(key: key);
@override
Widget build(BuildContext context) {
final hasIcon = iconAsset != null;
final hasOnTap = onTap != null || hasIcon;
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
color: isSelected ? chipType.color : chipType.backgroundColor,
border: Border.all(
color: chipType.color,
width: isSelected ? 0 : 1,
),
),
child: InkWell(
onTap: hasOnTap ? onTap : null,
borderRadius: BorderRadius.circular(borderRadius),
child: Container(
padding: padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (iconAsset != null) ...[
Utils.buildSvgWithAssets(icon: iconAsset!),
const SizedBox(width: 6),
],
Text(
chipText.toUpperCase(),
style: context.dynamicTextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
color: isSelected ? Colors.white : chipType.color,
letterSpacing: 0.1,
isLanguageSwitcher: true,
),
),
],
),
),
),
);
}
}

@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
// TODO: Import AppColors if bgRedColor is defined there
// import 'package:hmg_patient_app_new/core/ui_utils/app_colors.dart';
class TextInputWidget extends StatelessWidget {
final String labelText;
final String hintText;
@ -19,6 +22,8 @@ class TextInputWidget extends StatelessWidget {
final bool isAllowLeadingIcon;
final String? leadingIcon;
final bool isCountryDropDown;
final bool hasError;
final String? errorMessage;
// final List<Country> countryList;
// final Function(Country)? onCountryChange;
@ -41,36 +46,58 @@ class TextInputWidget extends StatelessWidget {
this.isAllowLeadingIcon = false,
this.leadingIcon,
this.isCountryDropDown = false,
this.hasError = false,
this.errorMessage,
// this.countryList = const [],
// this.onCountryChange,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: padding,
alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
borderRadius: isAllowRadius ? 15 : null,
side: isBorderAllowed ? BorderSide(color: const Color(0xffefefef), width: 1) : null,
),
child: Row(
textDirection: Directionality.of(context),
children: [
if (isAllowLeadingIcon && leadingIcon != null) _buildLeadingIcon(context),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildLabelText(),
_buildTextField(context),
],
// Assuming AppColors.bgRedColor exists, otherwise using Colors.red
final errorColor = Colors.red; // Replace with AppColors.bgRedColor if available
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: padding,
alignment: Alignment.center,
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
color: Colors.white,
borderRadius: isAllowRadius ? 15 : null,
side: isBorderAllowed ? BorderSide(color: hasError ? errorColor : const Color(0xffefefef), width: 1) : null,
),
child: Row(
textDirection: Directionality.of(context),
children: [
if (isAllowLeadingIcon && leadingIcon != null) _buildLeadingIcon(context),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildLabelText(),
_buildTextField(context),
],
),
),
],
),
),
if (hasError && errorMessage != null)
Padding(
padding: const EdgeInsets.only(top: 4.0, left: 12.0), // Adjust padding as needed
child: Text(
errorMessage!,
style: TextStyle(
color: errorColor,
fontSize: 12,
),
),
),
],
),
],
);
}

@ -43,19 +43,16 @@ class _LanguageSelectorState extends State<LanguageSelector> {
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Color(0xFFFEE9EA),
color: AppColors.secondaryLightRedColor,
),
child: InkWell(
onTap: () {
final newLanguage = widget.currentLanguage == 'ar' ? 'en' : 'ar';
print(newLanguage);
widget.onLanguageChanged(newLanguage);
},
child: Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(12)),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
@ -66,7 +63,7 @@ class _LanguageSelectorState extends State<LanguageSelector> {
style: context.dynamicTextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
color: AppColors.bgRedColor,
color: AppColors.primaryRedColor,
letterSpacing: 0.1,
isLanguageSwitcher: true,
),

Loading…
Cancel
Save