implement light and dark theme

This commit is contained in:
amirrezaghabeli
2025-08-06 14:14:07 +03:30
parent 337fcdbcbc
commit da7b10f0d0
24 changed files with 407 additions and 118 deletions
+5 -1
View File
@@ -1,5 +1,6 @@
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart'; import 'package:provider/single_child_widget.dart';
import 'package:tm_app/core/theme/theme_provider.dart';
import '../../data/repositories/auth_repository.dart'; import '../../data/repositories/auth_repository.dart';
import '../../data/services/auth_service.dart'; import '../../data/services/auth_service.dart';
@@ -11,7 +12,10 @@ List<SingleChildWidget> get providersRemote {
} }
List<SingleChildWidget> get cores { List<SingleChildWidget> get cores {
return [Provider(create: (context) => NetworkManager())]; return [
Provider(create: (context) => NetworkManager()),
ChangeNotifierProvider(create: (context) => ThemeProvider()),
];
} }
List<SingleChildWidget> get apiClients { List<SingleChildWidget> get apiClients {
-51
View File
@@ -1,51 +0,0 @@
import 'package:flutter/material.dart';
class AppColors {
static const Color mainBlue = Color(0xff0164FF);
static const Color borderBlue = Color(0xffA1C6FF);
// Primary Colors
static const Color primaryColor = Color(0xFF007BFF);
static const Color accentColor = Color(0xFFE83E8C);
// Backgrounds
static const Color lightBackgroundColor = Color(0xFFFFFFFF);
static const Color darkBackgroundColor = Color(0xFF222222);
// Text Colors
static const Color primaryTextColor = Color(0xFF212529);
static const Color secondaryTextColor = Color(0xFF6C757D);
static const Color linkTextColor = primaryColor;
// Status Colors
static const Color successColor = Color(0xFF28A745);
static const Color errorColor = Color(0xFFDC3545);
static const Color warningColor = Color(0xFFFFC107);
static const Color jellyBean = Color(0xFF34BCCB);
static const Color grey = Color(0xFF555555);
static const Color grey20 = Color(0xFFE4E4E4);
static const Color grey40 = Color(0xFFDADADA);
static const Color grey50 = Color(0xFF9E9E9E);
static const Color grey60 = Color(0xFF777777);
static const Color grey70 = Color(0xFF444444);
static const Color grey80 = Color(0xFF222222);
static const Color grey10 = Color(0xFFF4F4F4);
// static const Color grey20 = Color(0xFFE3E3E3);
static const Color grey0 = Color(0xFFFCFCFC);
static const Color backgroundColor = Color(0xFFFFFFFF);
static const Color borderColor = Color(0xFFE1E1E1);
static const Color primary2 = Color(0xFFE5EFFF);
static const Color dividerColor = Color(0xFFE1E1E1);
static const Color gren0 = Color(0xFFF9FCF8);
static const Color green10 = Color(0xFFE0F0DC);
static const Color gren20 = Color(0xFFDAF8D6);
static const Color gren30 = Color(0xFF289744);
static const Color red0 = Color(0xFFF8D6D6);
static const Color red10 = Color(0xFFC02525);
static const Color paleOrange = Color(0xFFfff7ee);
// static const Color red10 = Color(0xFFC02525);
static const Color lightBlue = Color(0xFFe8ecfc);
static const Color cyanAqua = Color(0xFFd6f4f8);
static const Color cyanTeal = Color(0xFF24A6B4);
}
+3 -4
View File
@@ -4,6 +4,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import '../constants/assets.dart'; import '../constants/assets.dart';
import '../theme/colors.dart';
import '../utils/size_config.dart'; import '../utils/size_config.dart';
class AppShellScreen extends StatelessWidget { class AppShellScreen extends StatelessWidget {
@@ -26,10 +27,8 @@ class AppShellScreen extends StatelessWidget {
bottomNavigationBar: Container( bottomNavigationBar: Container(
height: 72.0.h(), height: 72.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFFE3E3E3), color: AppColors.grey10,
border: Border.fromBorderSide( border: Border.fromBorderSide(BorderSide(color: AppColors.grey30)),
BorderSide(color: const Color(0xFFE3E3E3)),
),
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
+117
View File
@@ -0,0 +1,117 @@
import 'package:flutter/material.dart';
class AppColors {
// Theme mode tracking
static bool _isDarkMode = false;
static void setDarkMode(bool isDark) {
_isDarkMode = isDark;
}
static bool get isDarkMode => _isDarkMode;
// Theme-aware colors
static Color get primaryTextColor =>
_isDarkMode ? const Color(0xFFFFFFFF) : const Color(0xFF212529);
static Color get secondaryTextColor =>
_isDarkMode ? const Color(0xFFFFFFFF) : const Color(0xFF24848E);
static Color get backgroundColor =>
_isDarkMode ? const Color(0xFF222222) : const Color(0xFFFFFFFF);
static Color get surfaceColor =>
_isDarkMode ? const Color(0xFF2C2C2C) : const Color(0xFFFFFFFF);
static Color get cardBackground =>
_isDarkMode ? const Color(0xFF2B2B2B) : const Color(0xFFFFFFFF);
static Color get borderColor =>
_isDarkMode ? const Color(0xFF3C3C3C) : const Color(0xFFE1E1E1);
static Color get dividerColor =>
_isDarkMode ? const Color(0xFF3C3C3C) : const Color(0xFFE1E1E1);
static Color get inputFillColor =>
_isDarkMode ? const Color(0xFF2C2C2C) : const Color(0xFFF5F5F5);
// Static colors that don't change with theme
static const Color mainBlue = Color(0xff0164FF);
static const Color borderBlue = Color(0xffA1C6FF);
static const Color primaryColor = Color(0xFF007BFF);
static const Color accentColor = Color(0xFFE83E8C);
// Link color
static const Color linkTextColor = primaryColor;
// Status Colors (usually don't change with theme)
static const Color successColor = Color(0xFF28A745);
static const Color errorColor = Color(0xFFDC3545);
static const Color warningColor = Color(0xFFFFC107);
static const Color jellyBean = Color(0xFF34BCCB);
static const Color grey = Color(0xFF555555);
// Grey scale with theme awareness
static Color get grey10 =>
_isDarkMode ? const Color(0xFF292929) : const Color(0xFFF4F4F4);
static Color get grey20 =>
_isDarkMode ? const Color(0xFF333333) : const Color(0xFFE3E3E3);
static Color get grey30 =>
_isDarkMode ? const Color(0xFF494949) : const Color(0xFFE1E1E1);
static Color get grey40 =>
_isDarkMode ? const Color(0xFF484848) : const Color(0xFFDADADA);
static Color get grey50 =>
_isDarkMode ? const Color(0xFF707070) : const Color(0xFF9E9E9E);
static Color get grey60 =>
_isDarkMode ? const Color(0xFF777777) : const Color(0xFF777777);
static Color get grey70 =>
_isDarkMode ? const Color(0xFF9E9E9E) : const Color(0xFF444444);
static Color get grey80 =>
_isDarkMode ? const Color(0xFFFFFFFF) : const Color(0xFF222222);
static Color get grey0 =>
_isDarkMode ? const Color(0xFF262626) : const Color(0xFFFCFCFC);
static Color get titleColor =>
_isDarkMode ? const Color(0xFFFCFCFC) : const Color(0xFF222222);
static Color get green20 =>
_isDarkMode ? const Color(0xFF4E5D4C) : const Color(0xFFDAF8D6);
static Color get green30 =>
_isDarkMode ? const Color(0xFF80C491) : const Color(0xFF289744);
static Color get textBlue =>
_isDarkMode ? const Color(0xFF3A87FF) : const Color(0xFF0164FF);
static Color get primary20 =>
_isDarkMode
? const Color(0x7386a533).withValues(alpha: 0.2)
: const Color(0xFFE5EFFF);
// Primary color variations
static const Color primary2 = Color(0xFFE5EFFF);
static const Color secondary50 = Color(0xFF34BCCB);
// Green variations (status colors)
static const Color gren0 = Color(0xFFF9FCF8);
static const Color green10 = Color(0xFFE0F0DC);
static const Color gren30 = Color(0xFF289744);
// Red variations (status colors)
static const Color red0 = Color(0xFFF8D6D6);
static const Color red10 = Color(0xFFC02525);
// Other colors
static const Color paleOrange = Color(0xFFfff7ee);
static const Color lightBlue = Color(0xFFe8ecfc);
static const Color cyanAqua = Color(0xFFd6f4f8);
static const Color cyanTeal = Color(0xFF24A6B4);
}
+82
View File
@@ -0,0 +1,82 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'colors.dart';
class ThemeProvider extends ChangeNotifier {
static const String _themeKey = 'theme_mode';
static BuildContext? _context;
bool _isDarkMode = false;
bool get isDarkMode => _isDarkMode;
// Set the app context for rebuilding
static void setContext(BuildContext context) {
_context = context;
}
ThemeProvider() {
_loadThemeFromPrefs();
}
static void _rebuildAllChildren() {
void rebuild(Element el) {
el.markNeedsBuild();
el.visitChildren(rebuild);
}
if (_context != null) {
(_context as Element).visitChildren(rebuild);
}
}
Future<void> _loadThemeFromPrefs() async {
final prefs = await SharedPreferences.getInstance();
_isDarkMode = prefs.getBool(_themeKey) ?? false;
// Update AppColors
AppColors.setDarkMode(_isDarkMode);
// Notify listeners after loading
notifyListeners();
}
Future<void> toggleTheme() async {
_isDarkMode = !_isDarkMode;
// Update AppColors
AppColors.setDarkMode(_isDarkMode);
// Save to preferences
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_themeKey, _isDarkMode);
// Notify all listeners to rebuild
notifyListeners();
// Force rebuild all children for immediate theme update
_rebuildAllChildren();
}
Future<void> setDarkMode(bool isDark) async {
if (_isDarkMode == isDark) {
return;
}
_isDarkMode = isDark;
// Update AppColors
AppColors.setDarkMode(_isDarkMode);
// Save to preferences
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_themeKey, _isDarkMode);
// Notify all listeners to rebuild
notifyListeners();
// Force rebuild all children for immediate theme update
_rebuildAllChildren();
}
}
+27 -2
View File
@@ -2,8 +2,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tm_app/core/config/dependencies.dart'; import 'package:tm_app/core/config/dependencies.dart';
import 'package:tm_app/core/theme/theme_provider.dart';
import 'core/routes/app_routes.dart'; import 'core/routes/app_routes.dart';
import 'core/theme/colors.dart';
import 'core/utils/logger.dart'; import 'core/utils/logger.dart';
void main() { void main() {
@@ -17,15 +19,38 @@ void main() {
runApp(MultiProvider(providers: [...providersRemote], child: const MyApp())); runApp(MultiProvider(providers: [...providersRemote], child: const MyApp()));
} }
class MyApp extends StatelessWidget { class MyApp extends StatefulWidget {
const MyApp({super.key}); const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Set the context for ThemeProvider to enable forced rebuilds
ThemeProvider.setContext(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Listen to theme changes
final themeProvider = context.watch<ThemeProvider>();
return MaterialApp.router( return MaterialApp.router(
title: 'Flutter Demo', title: 'Flutter Demo',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), brightness:
themeProvider.isDarkMode ? Brightness.dark : Brightness.light,
primaryColor: AppColors.primaryColor,
scaffoldBackgroundColor: AppColors.backgroundColor,
colorScheme: ColorScheme.fromSeed(
seedColor: AppColors.primaryColor,
brightness:
themeProvider.isDarkMode ? Brightness.dark : Brightness.light,
),
), ),
routerConfig: appRouter, routerConfig: appRouter,
); );
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/constants/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/views/login/widgets/login_button.dart'; import 'package:tm_app/views/login/widgets/login_button.dart';
+5 -5
View File
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:tm_app/core/routes/app_routes.dart'; import 'package:tm_app/core/routes/app_routes.dart';
import '../../../core/constants/strings.dart'; import '../../../core/constants/strings.dart';
import '../../core/constants/colors.dart'; import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
import 'widgets.dart'; import 'widgets.dart';
@@ -14,7 +14,7 @@ class HomeScreen extends StatelessWidget {
SizeConfig.init(context); SizeConfig.init(context);
return SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
backgroundColor: Colors.white, backgroundColor: AppColors.backgroundColor,
body: _body(context), body: _body(context),
appBar: _appbar(), appBar: _appbar(),
), ),
@@ -68,7 +68,7 @@ class HomeScreen extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF222222), color: AppColors.grey70,
), ),
), ),
Image.asset( Image.asset(
@@ -111,7 +111,7 @@ class HomeScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
StatisticsCard( StatisticsCard(
backgroundColor: Color(0xFFE5EFFF), backgroundColor: AppColors.primary20,
iconPath: 'assets/icons/arrows.svg', iconPath: 'assets/icons/arrows.svg',
title: AppStrings.tenderSubmitting, title: AppStrings.tenderSubmitting,
amount: '12', amount: '12',
@@ -168,7 +168,7 @@ class HomeScreen extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 20.0.sp(), fontSize: 20.0.sp(),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF777777), color: AppColors.grey60,
), ),
); );
} }
+9 -4
View File
@@ -1,13 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tm_app/core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
class ProgressBarColumn extends StatefulWidget { class ProgressBarColumn extends StatefulWidget {
const ProgressBarColumn({ const ProgressBarColumn({
super.key,
required this.text, required this.text,
required this.value, required this.value,
required this.amount, required this.amount,
super.key,
}); });
final String text; final String text;
@@ -74,7 +75,7 @@ class _ProgressBarColumnState extends State<ProgressBarColumn>
backgroundColor: Color(0xFFE1E1E1), backgroundColor: Color(0xFFE1E1E1),
strokeCap: StrokeCap.round, strokeCap: StrokeCap.round,
strokeWidth: 8.0, strokeWidth: 8.0,
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF34BCCB)), valueColor: AlwaysStoppedAnimation<Color>(AppColors.jellyBean),
value: _animation.value, value: _animation.value,
), ),
), ),
@@ -85,7 +86,11 @@ class _ProgressBarColumnState extends State<ProgressBarColumn>
return Center( return Center(
child: Text( child: Text(
widget.amount, widget.amount,
style: TextStyle(fontSize: 24.0.sp(), fontWeight: FontWeight.bold), style: TextStyle(
fontSize: 24.0.sp(),
fontWeight: FontWeight.bold,
color: AppColors.titleColor,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
); );
@@ -97,7 +102,7 @@ class _ProgressBarColumnState extends State<ProgressBarColumn>
style: TextStyle( style: TextStyle(
fontSize: 16.0.sp(), fontSize: 16.0.sp(),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF222222), color: AppColors.titleColor,
), ),
); );
} }
+15 -10
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
class TendersListItem extends StatelessWidget { class TendersListItem extends StatelessWidget {
@@ -8,7 +9,12 @@ class TendersListItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SizedBox( return Container(
decoration: BoxDecoration(
color: AppColors.cardBackground,
borderRadius: BorderRadius.circular(4),
),
margin: EdgeInsetsDirectional.only(end: 16.0.w()),
width: 327.0.w(), width: 327.0.w(),
height: 309.0.h(), height: 309.0.h(),
child: Padding( child: Padding(
@@ -23,14 +29,14 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Color(0xFF777777), color: AppColors.grey60,
), ),
), ),
Container( Container(
width: 91.0.w(), width: 91.0.w(),
height: 24.0.h(), height: 24.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xFFDAF8D6), color: AppColors.green20,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
alignment: Alignment.center, alignment: Alignment.center,
@@ -39,7 +45,7 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Color(0xFF289744), color: AppColors.green30,
), ),
), ),
), ),
@@ -51,7 +57,7 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 16.0.sp(), fontSize: 16.0.sp(),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Color(0xFF222222), color: AppColors.grey80,
), ),
), ),
SizedBox(height: 8.0.h()), SizedBox(height: 8.0.h()),
@@ -60,7 +66,7 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 14.0.sp(), fontSize: 14.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Color(0xFF222222), color: AppColors.grey70,
), ),
), ),
SizedBox(height: 24.0.h()), SizedBox(height: 24.0.h()),
@@ -73,7 +79,7 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
color: Color(0xFF777777), color: AppColors.grey80,
), ),
), ),
SizedBox(width: 8.0.w()), SizedBox(width: 8.0.w()),
@@ -87,9 +93,8 @@ class TendersListItem extends StatelessWidget {
width: 96.0.w(), width: 96.0.w(),
height: 24.0.h(), height: 24.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0xFFE4E4E4), color: AppColors.grey30,
borderRadius: BorderRadius.circular(88), borderRadius: BorderRadius.circular(88),
border: Border.all(color: Color(0xFFDADADA)),
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: Text( child: Text(
@@ -97,7 +102,7 @@ class TendersListItem extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 12.0.sp(), fontSize: 12.0.sp(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Color(0xFF777777), color: AppColors.grey60,
), ),
), ),
), ),
+5 -3
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../core/constants/colors.dart';
import '../../../core/constants/strings.dart'; import '../../../core/constants/strings.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
class BaseButton extends StatelessWidget { class BaseButton extends StatelessWidget {
@@ -35,7 +36,8 @@ class BaseButton extends StatelessWidget {
child: ElevatedButton( child: ElevatedButton(
onPressed: isEnabled ? onPressed : null, onPressed: isEnabled ? onPressed : null,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor ?? backgroundColor:
backgroundColor ??
(isEnabled ? AppColors.mainBlue : Colors.grey[300]), (isEnabled ? AppColors.mainBlue : Colors.grey[300]),
foregroundColor: textColor ?? Colors.white, foregroundColor: textColor ?? Colors.white,
elevation: elevation ?? 0, elevation: elevation ?? 0,
@@ -58,4 +60,4 @@ class BaseButton extends StatelessWidget {
), ),
); );
} }
} }
+2 -2
View File
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/constants/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
class LoginTextField extends StatelessWidget { class LoginTextField extends StatelessWidget {
@@ -15,11 +15,11 @@ class LoginTextField extends StatelessWidget {
final VoidCallback? onToggleVisibility; final VoidCallback? onToggleVisibility;
const LoginTextField({ const LoginTextField({
super.key,
required this.controller, required this.controller,
required this.focusNode, required this.focusNode,
required this.label, required this.label,
required this.iconPath, required this.iconPath,
super.key,
this.isPassword = false, this.isPassword = false,
this.obscureText = false, this.obscureText = false,
this.onToggleVisibility, this.onToggleVisibility,
+17 -2
View File
@@ -2,7 +2,8 @@ import 'package:flutter/material.dart';
import 'package:tm_app/core/constants/strings.dart'; import 'package:tm_app/core/constants/strings.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import '../../core/constants/colors.dart'; import '../../core/theme/colors.dart';
import '../../widgets/theme_toggle.dart';
class ProfileScreen extends StatelessWidget { class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key}); const ProfileScreen({super.key});
@@ -27,7 +28,7 @@ class ProfileScreen extends StatelessWidget {
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Color(0xFF222222), color: AppColors.primaryTextColor,
), ),
), ),
Image.asset( Image.asset(
@@ -65,6 +66,20 @@ class ProfileScreen extends StatelessWidget {
description: 'Telecommunications', description: 'Telecommunications',
), ),
TitleDescription(title: 'Founded', description: '2010'), TitleDescription(title: 'Founded', description: '2010'),
SizedBox(height: 24.0.h()),
// Theme Toggle
Container(
padding: EdgeInsets.symmetric(
horizontal: 16.0.w(),
vertical: 12.0.h(),
),
decoration: BoxDecoration(
color: AppColors.surfaceColor,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColors.borderColor),
),
child: const ThemeToggle(),
),
], ],
), ),
), ),
+1 -1
View File
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../core/constants/colors.dart'; import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
class MainTabBar extends StatefulWidget { class MainTabBar extends StatefulWidget {
+1 -1
View File
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../core/constants/colors.dart'; import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
class TabItem extends StatelessWidget { class TabItem extends StatelessWidget {
+38 -9
View File
@@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tm_app/core/constants/strings.dart';
import '../../core/constants/colors.dart'; import '../../core/theme/colors.dart';
import '../../core/utils/size_config.dart'; import '../../core/utils/size_config.dart';
import 'widgets/main_tenders_slider.dart'; import 'widgets/main_tenders_slider.dart';
import 'widgets/widgets.dart';
class TendersScreen extends StatefulWidget { class TendersScreen extends StatefulWidget {
const TendersScreen({super.key}); const TendersScreen({super.key});
@@ -34,18 +34,16 @@ class _TendersScreenState extends State<TendersScreen>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return SafeArea(
backgroundColor: AppColors.backgroundColor, child: Scaffold(
body: SafeArea( backgroundColor: AppColors.backgroundColor,
child: SingleChildScrollView( appBar: _appbar(),
body: SingleChildScrollView(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(vertical: 24.0.h()), padding: EdgeInsets.symmetric(vertical: 24.0.h()),
child: Column( child: Column(
children: [ children: [
TenderAppBar(),
SizedBox(height: 24.0.h()),
// MainTabBar(controller: controller), // MainTabBar(controller: controller),
SizedBox(height: 24.0.h()),
MainTendersSlider(), MainTendersSlider(),
], ],
), ),
@@ -54,4 +52,35 @@ class _TendersScreenState extends State<TendersScreen>
), ),
); );
} }
PreferredSize _appbar() {
return PreferredSize(
preferredSize: Size.fromHeight(56.0.h()),
child: Container(
color: AppColors.backgroundColor,
padding: EdgeInsets.symmetric(horizontal: 24.0.w()),
height: 56.0.h(),
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
AppStrings.tendersTitle,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: AppColors.grey70,
),
),
Image.asset(
'assets/icons/tenderLogo.png',
width: 59.0.w(),
height: 28.0.h(),
fit: BoxFit.cover,
),
],
),
),
);
}
} }
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:tm_app/core/constants/colors.dart';
import 'package:tm_app/core/routes/app_routes.dart'; import 'package:tm_app/core/routes/app_routes.dart';
import 'package:tm_app/core/theme/colors.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
@@ -86,7 +86,7 @@ class _MainTendersSliderState extends State<MainTendersSlider> {
children: [ children: [
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 693.0.h(), height: 694.0.h(),
child: PageView.builder( child: PageView.builder(
controller: pageController, controller: pageController,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/constants/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
class TenderActionButtons extends StatelessWidget { class TenderActionButtons extends StatelessWidget {
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/constants/colors.dart';
import '../../../core/constants/strings.dart'; import '../../../core/constants/strings.dart';
import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
class TenderAppBar extends StatelessWidget { class TenderAppBar extends StatelessWidget {
+10 -13
View File
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/constants/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
import 'tender_action_buttons.dart'; import 'tender_action_buttons.dart';
@@ -50,7 +50,7 @@ class TenderCard extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.grey0, color: AppColors.grey0,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.borderColor), border: Border.all(color: AppColors.grey30),
), ),
child: Column( child: Column(
children: [ children: [
@@ -75,10 +75,7 @@ class TenderCard extends StatelessWidget {
Container( Container(
width: double.infinity, width: double.infinity,
height: 24.0.h(), height: 24.0.h(),
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(horizontal: 8.0.w()),
horizontal: 8.0.w(),
vertical: 4.0.h(),
),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.primary2, color: AppColors.primary2,
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
@@ -89,7 +86,7 @@ class TenderCard extends StatelessWidget {
Text( Text(
'Deadline:', 'Deadline:',
style: TextStyle( style: TextStyle(
color: AppColors.mainBlue, color: AppColors.textBlue,
fontSize: 14.0.sp(), fontSize: 14.0.sp(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -134,7 +131,7 @@ class TenderCard extends StatelessWidget {
Text( Text(
tenderId, tenderId,
style: TextStyle( style: TextStyle(
color: AppColors.grey60, color: AppColors.grey,
fontSize: 14.0.sp(), fontSize: 14.0.sp(),
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
), ),
@@ -155,7 +152,7 @@ class TenderCard extends StatelessWidget {
Text( Text(
'Match with your profile', 'Match with your profile',
style: TextStyle( style: TextStyle(
color: AppColors.primaryTextColor, color: AppColors.grey80,
fontSize: 14.0.sp(), fontSize: 14.0.sp(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -163,7 +160,7 @@ class TenderCard extends StatelessWidget {
Text( Text(
'${matchPercentage.toInt()}%', '${matchPercentage.toInt()}%',
style: TextStyle( style: TextStyle(
color: const Color(0xFF2484A8), color: AppColors.secondaryTextColor,
fontSize: 16.0.sp(), fontSize: 16.0.sp(),
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@@ -177,7 +174,7 @@ class TenderCard extends StatelessWidget {
width: double.infinity, width: double.infinity,
height: 4.0.h(), height: 4.0.h(),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppColors.grey10, color: AppColors.grey20,
borderRadius: BorderRadius.circular(2), borderRadius: BorderRadius.circular(2),
), ),
child: FractionallySizedBox( child: FractionallySizedBox(
@@ -185,7 +182,7 @@ class TenderCard extends StatelessWidget {
widthFactor: matchPercentage / 100, widthFactor: matchPercentage / 100,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF34BC9B), color: AppColors.secondary50,
borderRadius: BorderRadius.circular(2), borderRadius: BorderRadius.circular(2),
), ),
), ),
@@ -205,7 +202,7 @@ class TenderCard extends StatelessWidget {
Text( Text(
location, location,
style: TextStyle( style: TextStyle(
color: AppColors.primaryTextColor, color: AppColors.grey80,
fontSize: 14.0.sp(), fontSize: 14.0.sp(),
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../../core/constants/assets.dart'; import '../../../core/constants/assets.dart';
import '../../../core/constants/colors.dart'; import '../../../core/theme/colors.dart';
import '../../../core/utils/size_config.dart'; import '../../../core/utils/size_config.dart';
class TenderCard extends StatelessWidget { class TenderCard extends StatelessWidget {
@@ -74,7 +74,7 @@ class TenderCard extends StatelessWidget {
vertical: 4.0.h(), vertical: 4.0.h(),
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: statusCardColor ?? AppColors.gren20, color: statusCardColor ?? AppColors.green20,
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
child: Row( child: Row(
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tm_app/core/constants/assets.dart'; import 'package:tm_app/core/constants/assets.dart';
import 'package:tm_app/core/constants/colors.dart'; import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/views/your_tenders/model/tender_model.dart'; import 'package:tm_app/views/your_tenders/model/tender_model.dart';
import 'package:tm_app/views/your_tenders/widgets/tender_card.dart'; import 'package:tm_app/views/your_tenders/widgets/tender_card.dart';
@@ -35,7 +35,7 @@ class TendersSubmitted extends StatelessWidget {
? AssetsManager.tickCircle ? AssetsManager.tickCircle
: AssetsManager.closeCircle, : AssetsManager.closeCircle,
statusCardColor: statusCardColor:
tender.status == 'Won' ? AppColors.gren20 : AppColors.red0, tender.status == 'Won' ? AppColors.green20 : AppColors.red0,
statusTextColor: statusTextColor:
tender.status == 'Won' ? AppColors.gren30 : AppColors.red10, tender.status == 'Won' ? AppColors.gren30 : AppColors.red10,
); );
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tm_app/core/constants/colors.dart';
import 'package:tm_app/core/constants/strings.dart'; import 'package:tm_app/core/constants/strings.dart';
import 'package:tm_app/core/theme/colors.dart';
import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/core/utils/size_config.dart';
import 'package:tm_app/views/your_tenders/widgets/approved_tenders.dart'; import 'package:tm_app/views/your_tenders/widgets/approved_tenders.dart';
import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart'; import 'package:tm_app/views/your_tenders/widgets/tenders_submitted.dart';
+60
View File
@@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../core/theme/colors.dart';
import '../core/theme/theme_provider.dart';
class ThemeToggle extends StatelessWidget {
const ThemeToggle({super.key});
@override
Widget build(BuildContext context) {
final themeProvider = context.watch<ThemeProvider>();
return Row(
children: [
Icon(
themeProvider.isDarkMode ? Icons.dark_mode : Icons.light_mode,
color: AppColors.primaryTextColor,
),
const SizedBox(width: 8),
Text(
themeProvider.isDarkMode ? 'Dark Mode' : 'Light Mode',
style: TextStyle(color: AppColors.primaryTextColor, fontSize: 16),
),
const Spacer(),
Switch(
value: themeProvider.isDarkMode,
onChanged: (value) {
themeProvider.toggleTheme();
},
activeColor: AppColors.primaryColor,
),
],
);
}
}
// Simple icon button version
class ThemeToggleButton extends StatelessWidget {
const ThemeToggleButton({super.key});
@override
Widget build(BuildContext context) {
final themeProvider = context.watch<ThemeProvider>();
return IconButton(
icon: Icon(
themeProvider.isDarkMode ? Icons.light_mode : Icons.dark_mode,
color: AppColors.primaryTextColor,
),
onPressed: () {
themeProvider.toggleTheme();
},
tooltip:
themeProvider.isDarkMode
? 'Switch to Light Mode'
: 'Switch to Dark Mode',
);
}
}