From da7b10f0d0ab4b727600104b8b8d334569528d91 Mon Sep 17 00:00:00 2001 From: amirrezaghabeli Date: Wed, 6 Aug 2025 14:14:07 +0330 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8implement=20light=20and=20dark=20theme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/config/dependencies.dart | 6 +- lib/core/constants/colors.dart | 51 -------- lib/core/routes/app_shell_screen.dart | 7 +- lib/core/theme/colors.dart | 117 ++++++++++++++++++ lib/core/theme/theme_provider.dart | 82 ++++++++++++ lib/main.dart | 29 ++++- lib/views/detail/detail_screen.dart | 2 +- lib/views/home/home_screen.dart | 10 +- lib/views/home/progress_bar_column.dart | 13 +- lib/views/home/tenders_list_item.dart | 25 ++-- lib/views/login/widgets/login_button.dart | 8 +- lib/views/login/widgets/login_textfield.dart | 4 +- lib/views/profile/profile_screen.dart | 19 ++- lib/views/shared/main_tab_bar.dart | 2 +- lib/views/shared/tab_item.dart | 2 +- lib/views/tenders/tenders_screen.dart | 47 +++++-- .../tenders/widgets/main_tenders_slider.dart | 4 +- .../widgets/tender_action_buttons.dart | 2 +- lib/views/tenders/widgets/tender_app_bar.dart | 2 +- lib/views/tenders/widgets/tender_card.dart | 23 ++-- .../your_tenders/widgets/tender_card.dart | 4 +- .../widgets/tenders_submitted.dart | 4 +- .../your_tenders/your_tenders_screen.dart | 2 +- lib/widgets/theme_toggle.dart | 60 +++++++++ 24 files changed, 407 insertions(+), 118 deletions(-) delete mode 100644 lib/core/constants/colors.dart create mode 100644 lib/core/theme/colors.dart create mode 100644 lib/core/theme/theme_provider.dart create mode 100644 lib/widgets/theme_toggle.dart diff --git a/lib/core/config/dependencies.dart b/lib/core/config/dependencies.dart index 97fb698..47949cb 100644 --- a/lib/core/config/dependencies.dart +++ b/lib/core/config/dependencies.dart @@ -1,5 +1,6 @@ import 'package:provider/provider.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/services/auth_service.dart'; @@ -11,7 +12,10 @@ List get providersRemote { } List get cores { - return [Provider(create: (context) => NetworkManager())]; + return [ + Provider(create: (context) => NetworkManager()), + ChangeNotifierProvider(create: (context) => ThemeProvider()), + ]; } List get apiClients { diff --git a/lib/core/constants/colors.dart b/lib/core/constants/colors.dart deleted file mode 100644 index 5b1c8bf..0000000 --- a/lib/core/constants/colors.dart +++ /dev/null @@ -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); -} diff --git a/lib/core/routes/app_shell_screen.dart b/lib/core/routes/app_shell_screen.dart index 4fb772f..62f6b60 100644 --- a/lib/core/routes/app_shell_screen.dart +++ b/lib/core/routes/app_shell_screen.dart @@ -4,6 +4,7 @@ import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import '../constants/assets.dart'; +import '../theme/colors.dart'; import '../utils/size_config.dart'; class AppShellScreen extends StatelessWidget { @@ -26,10 +27,8 @@ class AppShellScreen extends StatelessWidget { bottomNavigationBar: Container( height: 72.0.h(), decoration: BoxDecoration( - color: const Color(0xFFE3E3E3), - border: Border.fromBorderSide( - BorderSide(color: const Color(0xFFE3E3E3)), - ), + color: AppColors.grey10, + border: Border.fromBorderSide(BorderSide(color: AppColors.grey30)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, diff --git a/lib/core/theme/colors.dart b/lib/core/theme/colors.dart new file mode 100644 index 0000000..e99fe91 --- /dev/null +++ b/lib/core/theme/colors.dart @@ -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); +} diff --git a/lib/core/theme/theme_provider.dart b/lib/core/theme/theme_provider.dart new file mode 100644 index 0000000..eae8662 --- /dev/null +++ b/lib/core/theme/theme_provider.dart @@ -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 _loadThemeFromPrefs() async { + final prefs = await SharedPreferences.getInstance(); + _isDarkMode = prefs.getBool(_themeKey) ?? false; + + // Update AppColors + AppColors.setDarkMode(_isDarkMode); + + // Notify listeners after loading + notifyListeners(); + } + + Future 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 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(); + } +} diff --git a/lib/main.dart b/lib/main.dart index 7cb3e7c..149c1d4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,10 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.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/theme/colors.dart'; import 'core/utils/logger.dart'; void main() { @@ -17,15 +19,38 @@ void main() { runApp(MultiProvider(providers: [...providersRemote], child: const MyApp())); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { const MyApp({super.key}); + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + @override + void didChangeDependencies() { + super.didChangeDependencies(); + // Set the context for ThemeProvider to enable forced rebuilds + ThemeProvider.setContext(context); + } + @override Widget build(BuildContext context) { + // Listen to theme changes + final themeProvider = context.watch(); + return MaterialApp.router( title: 'Flutter Demo', 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, ); diff --git a/lib/views/detail/detail_screen.dart b/lib/views/detail/detail_screen.dart index 33002d4..05ed36f 100644 --- a/lib/views/detail/detail_screen.dart +++ b/lib/views/detail/detail_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.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/views/login/widgets/login_button.dart'; diff --git a/lib/views/home/home_screen.dart b/lib/views/home/home_screen.dart index b42ced2..24782d9 100644 --- a/lib/views/home/home_screen.dart +++ b/lib/views/home/home_screen.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:tm_app/core/routes/app_routes.dart'; import '../../../core/constants/strings.dart'; -import '../../core/constants/colors.dart'; +import '../../core/theme/colors.dart'; import '../../core/utils/size_config.dart'; import 'widgets.dart'; @@ -14,7 +14,7 @@ class HomeScreen extends StatelessWidget { SizeConfig.init(context); return SafeArea( child: Scaffold( - backgroundColor: Colors.white, + backgroundColor: AppColors.backgroundColor, body: _body(context), appBar: _appbar(), ), @@ -68,7 +68,7 @@ class HomeScreen extends StatelessWidget { style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, - color: Color(0xFF222222), + color: AppColors.grey70, ), ), Image.asset( @@ -111,7 +111,7 @@ class HomeScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ StatisticsCard( - backgroundColor: Color(0xFFE5EFFF), + backgroundColor: AppColors.primary20, iconPath: 'assets/icons/arrows.svg', title: AppStrings.tenderSubmitting, amount: '12', @@ -168,7 +168,7 @@ class HomeScreen extends StatelessWidget { style: TextStyle( fontSize: 20.0.sp(), fontWeight: FontWeight.w600, - color: Color(0xFF777777), + color: AppColors.grey60, ), ); } diff --git a/lib/views/home/progress_bar_column.dart b/lib/views/home/progress_bar_column.dart index 46265e3..453ae8b 100644 --- a/lib/views/home/progress_bar_column.dart +++ b/lib/views/home/progress_bar_column.dart @@ -1,13 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:tm_app/core/theme/colors.dart'; import '../../core/utils/size_config.dart'; class ProgressBarColumn extends StatefulWidget { const ProgressBarColumn({ - super.key, required this.text, required this.value, required this.amount, + super.key, }); final String text; @@ -74,7 +75,7 @@ class _ProgressBarColumnState extends State backgroundColor: Color(0xFFE1E1E1), strokeCap: StrokeCap.round, strokeWidth: 8.0, - valueColor: AlwaysStoppedAnimation(Color(0xFF34BCCB)), + valueColor: AlwaysStoppedAnimation(AppColors.jellyBean), value: _animation.value, ), ), @@ -85,7 +86,11 @@ class _ProgressBarColumnState extends State return Center( child: Text( 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, ), ); @@ -97,7 +102,7 @@ class _ProgressBarColumnState extends State style: TextStyle( fontSize: 16.0.sp(), fontWeight: FontWeight.bold, - color: Color(0xFF222222), + color: AppColors.titleColor, ), ); } diff --git a/lib/views/home/tenders_list_item.dart b/lib/views/home/tenders_list_item.dart index 52a1203..93e4dde 100644 --- a/lib/views/home/tenders_list_item.dart +++ b/lib/views/home/tenders_list_item.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import '../../core/theme/colors.dart'; import '../../core/utils/size_config.dart'; class TendersListItem extends StatelessWidget { @@ -8,7 +9,12 @@ class TendersListItem extends StatelessWidget { @override 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(), height: 309.0.h(), child: Padding( @@ -23,14 +29,14 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 12.0.sp(), fontWeight: FontWeight.w400, - color: Color(0xFF777777), + color: AppColors.grey60, ), ), Container( width: 91.0.w(), height: 24.0.h(), decoration: BoxDecoration( - color: Color(0xFFDAF8D6), + color: AppColors.green20, borderRadius: BorderRadius.circular(8), ), alignment: Alignment.center, @@ -39,7 +45,7 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 12.0.sp(), fontWeight: FontWeight.w500, - color: Color(0xFF289744), + color: AppColors.green30, ), ), ), @@ -51,7 +57,7 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 16.0.sp(), fontWeight: FontWeight.w600, - color: Color(0xFF222222), + color: AppColors.grey80, ), ), SizedBox(height: 8.0.h()), @@ -60,7 +66,7 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 14.0.sp(), fontWeight: FontWeight.w400, - color: Color(0xFF222222), + color: AppColors.grey70, ), ), SizedBox(height: 24.0.h()), @@ -73,7 +79,7 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 12.0.sp(), fontWeight: FontWeight.w400, - color: Color(0xFF777777), + color: AppColors.grey80, ), ), SizedBox(width: 8.0.w()), @@ -87,9 +93,8 @@ class TendersListItem extends StatelessWidget { width: 96.0.w(), height: 24.0.h(), decoration: BoxDecoration( - color: Color(0xFFE4E4E4), + color: AppColors.grey30, borderRadius: BorderRadius.circular(88), - border: Border.all(color: Color(0xFFDADADA)), ), alignment: Alignment.center, child: Text( @@ -97,7 +102,7 @@ class TendersListItem extends StatelessWidget { style: TextStyle( fontSize: 12.0.sp(), fontWeight: FontWeight.w500, - color: Color(0xFF777777), + color: AppColors.grey60, ), ), ), diff --git a/lib/views/login/widgets/login_button.dart b/lib/views/login/widgets/login_button.dart index 52d64d1..10c58de 100644 --- a/lib/views/login/widgets/login_button.dart +++ b/lib/views/login/widgets/login_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import '../../../core/constants/colors.dart'; + import '../../../core/constants/strings.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; class BaseButton extends StatelessWidget { @@ -35,7 +36,8 @@ class BaseButton extends StatelessWidget { child: ElevatedButton( onPressed: isEnabled ? onPressed : null, style: ElevatedButton.styleFrom( - backgroundColor: backgroundColor ?? + backgroundColor: + backgroundColor ?? (isEnabled ? AppColors.mainBlue : Colors.grey[300]), foregroundColor: textColor ?? Colors.white, elevation: elevation ?? 0, @@ -58,4 +60,4 @@ class BaseButton extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/views/login/widgets/login_textfield.dart b/lib/views/login/widgets/login_textfield.dart index 4bc6f04..a1ce398 100644 --- a/lib/views/login/widgets/login_textfield.dart +++ b/lib/views/login/widgets/login_textfield.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import '../../../core/constants/assets.dart'; -import '../../../core/constants/colors.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; class LoginTextField extends StatelessWidget { @@ -15,11 +15,11 @@ class LoginTextField extends StatelessWidget { final VoidCallback? onToggleVisibility; const LoginTextField({ - super.key, required this.controller, required this.focusNode, required this.label, required this.iconPath, + super.key, this.isPassword = false, this.obscureText = false, this.onToggleVisibility, diff --git a/lib/views/profile/profile_screen.dart b/lib/views/profile/profile_screen.dart index f623cbe..14a53b9 100644 --- a/lib/views/profile/profile_screen.dart +++ b/lib/views/profile/profile_screen.dart @@ -2,7 +2,8 @@ import 'package:flutter/material.dart'; import 'package:tm_app/core/constants/strings.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 { const ProfileScreen({super.key}); @@ -27,7 +28,7 @@ class ProfileScreen extends StatelessWidget { style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, - color: Color(0xFF222222), + color: AppColors.primaryTextColor, ), ), Image.asset( @@ -65,6 +66,20 @@ class ProfileScreen extends StatelessWidget { description: 'Telecommunications', ), 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(), + ), ], ), ), diff --git a/lib/views/shared/main_tab_bar.dart b/lib/views/shared/main_tab_bar.dart index 1ab5a87..567bfd7 100644 --- a/lib/views/shared/main_tab_bar.dart +++ b/lib/views/shared/main_tab_bar.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../core/constants/colors.dart'; +import '../../core/theme/colors.dart'; import '../../core/utils/size_config.dart'; class MainTabBar extends StatefulWidget { diff --git a/lib/views/shared/tab_item.dart b/lib/views/shared/tab_item.dart index 2604be8..7cf06da 100644 --- a/lib/views/shared/tab_item.dart +++ b/lib/views/shared/tab_item.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import '../../core/constants/colors.dart'; +import '../../core/theme/colors.dart'; import '../../core/utils/size_config.dart'; class TabItem extends StatelessWidget { diff --git a/lib/views/tenders/tenders_screen.dart b/lib/views/tenders/tenders_screen.dart index 8e4c58e..492e695 100644 --- a/lib/views/tenders/tenders_screen.dart +++ b/lib/views/tenders/tenders_screen.dart @@ -1,9 +1,9 @@ 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 'widgets/main_tenders_slider.dart'; -import 'widgets/widgets.dart'; class TendersScreen extends StatefulWidget { const TendersScreen({super.key}); @@ -34,18 +34,16 @@ class _TendersScreenState extends State @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.backgroundColor, - body: SafeArea( - child: SingleChildScrollView( + return SafeArea( + child: Scaffold( + backgroundColor: AppColors.backgroundColor, + appBar: _appbar(), + body: SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric(vertical: 24.0.h()), child: Column( children: [ - TenderAppBar(), - SizedBox(height: 24.0.h()), // MainTabBar(controller: controller), - SizedBox(height: 24.0.h()), MainTendersSlider(), ], ), @@ -54,4 +52,35 @@ class _TendersScreenState extends State ), ); } + + 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, + ), + ], + ), + ), + ); + } } diff --git a/lib/views/tenders/widgets/main_tenders_slider.dart b/lib/views/tenders/widgets/main_tenders_slider.dart index b020e4c..bbd4918 100644 --- a/lib/views/tenders/widgets/main_tenders_slider.dart +++ b/lib/views/tenders/widgets/main_tenders_slider.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.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/theme/colors.dart'; import '../../../core/constants/assets.dart'; import '../../../core/utils/size_config.dart'; @@ -86,7 +86,7 @@ class _MainTendersSliderState extends State { children: [ SizedBox( width: double.infinity, - height: 693.0.h(), + height: 694.0.h(), child: PageView.builder( controller: pageController, scrollDirection: Axis.horizontal, diff --git a/lib/views/tenders/widgets/tender_action_buttons.dart b/lib/views/tenders/widgets/tender_action_buttons.dart index fe18af8..03b84b4 100644 --- a/lib/views/tenders/widgets/tender_action_buttons.dart +++ b/lib/views/tenders/widgets/tender_action_buttons.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import '../../../core/constants/assets.dart'; -import '../../../core/constants/colors.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; class TenderActionButtons extends StatelessWidget { diff --git a/lib/views/tenders/widgets/tender_app_bar.dart b/lib/views/tenders/widgets/tender_app_bar.dart index a86769d..2d6cfdc 100644 --- a/lib/views/tenders/widgets/tender_app_bar.dart +++ b/lib/views/tenders/widgets/tender_app_bar.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import '../../../core/constants/assets.dart'; -import '../../../core/constants/colors.dart'; import '../../../core/constants/strings.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; class TenderAppBar extends StatelessWidget { diff --git a/lib/views/tenders/widgets/tender_card.dart b/lib/views/tenders/widgets/tender_card.dart index 514cd6c..21f8549 100644 --- a/lib/views/tenders/widgets/tender_card.dart +++ b/lib/views/tenders/widgets/tender_card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import '../../../core/constants/assets.dart'; -import '../../../core/constants/colors.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; import 'tender_action_buttons.dart'; @@ -50,7 +50,7 @@ class TenderCard extends StatelessWidget { decoration: BoxDecoration( color: AppColors.grey0, borderRadius: BorderRadius.circular(12), - border: Border.all(color: AppColors.borderColor), + border: Border.all(color: AppColors.grey30), ), child: Column( children: [ @@ -75,10 +75,7 @@ class TenderCard extends StatelessWidget { Container( width: double.infinity, height: 24.0.h(), - padding: EdgeInsets.symmetric( - horizontal: 8.0.w(), - vertical: 4.0.h(), - ), + padding: EdgeInsets.symmetric(horizontal: 8.0.w()), decoration: BoxDecoration( color: AppColors.primary2, borderRadius: BorderRadius.circular(4), @@ -89,7 +86,7 @@ class TenderCard extends StatelessWidget { Text( 'Deadline:', style: TextStyle( - color: AppColors.mainBlue, + color: AppColors.textBlue, fontSize: 14.0.sp(), fontWeight: FontWeight.w500, ), @@ -134,7 +131,7 @@ class TenderCard extends StatelessWidget { Text( tenderId, style: TextStyle( - color: AppColors.grey60, + color: AppColors.grey, fontSize: 14.0.sp(), fontWeight: FontWeight.w400, ), @@ -155,7 +152,7 @@ class TenderCard extends StatelessWidget { Text( 'Match with your profile', style: TextStyle( - color: AppColors.primaryTextColor, + color: AppColors.grey80, fontSize: 14.0.sp(), fontWeight: FontWeight.w500, ), @@ -163,7 +160,7 @@ class TenderCard extends StatelessWidget { Text( '${matchPercentage.toInt()}%', style: TextStyle( - color: const Color(0xFF2484A8), + color: AppColors.secondaryTextColor, fontSize: 16.0.sp(), fontWeight: FontWeight.w600, ), @@ -177,7 +174,7 @@ class TenderCard extends StatelessWidget { width: double.infinity, height: 4.0.h(), decoration: BoxDecoration( - color: AppColors.grey10, + color: AppColors.grey20, borderRadius: BorderRadius.circular(2), ), child: FractionallySizedBox( @@ -185,7 +182,7 @@ class TenderCard extends StatelessWidget { widthFactor: matchPercentage / 100, child: Container( decoration: BoxDecoration( - color: const Color(0xFF34BC9B), + color: AppColors.secondary50, borderRadius: BorderRadius.circular(2), ), ), @@ -205,7 +202,7 @@ class TenderCard extends StatelessWidget { Text( location, style: TextStyle( - color: AppColors.primaryTextColor, + color: AppColors.grey80, fontSize: 14.0.sp(), fontWeight: FontWeight.w500, ), diff --git a/lib/views/your_tenders/widgets/tender_card.dart b/lib/views/your_tenders/widgets/tender_card.dart index 4a9cb63..0abe667 100644 --- a/lib/views/your_tenders/widgets/tender_card.dart +++ b/lib/views/your_tenders/widgets/tender_card.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import '../../../core/constants/assets.dart'; -import '../../../core/constants/colors.dart'; +import '../../../core/theme/colors.dart'; import '../../../core/utils/size_config.dart'; class TenderCard extends StatelessWidget { @@ -74,7 +74,7 @@ class TenderCard extends StatelessWidget { vertical: 4.0.h(), ), decoration: BoxDecoration( - color: statusCardColor ?? AppColors.gren20, + color: statusCardColor ?? AppColors.green20, borderRadius: BorderRadius.circular(8), ), child: Row( diff --git a/lib/views/your_tenders/widgets/tenders_submitted.dart b/lib/views/your_tenders/widgets/tenders_submitted.dart index 48ae07f..b8a44bb 100644 --- a/lib/views/your_tenders/widgets/tenders_submitted.dart +++ b/lib/views/your_tenders/widgets/tenders_submitted.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.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/views/your_tenders/model/tender_model.dart'; import 'package:tm_app/views/your_tenders/widgets/tender_card.dart'; @@ -35,7 +35,7 @@ class TendersSubmitted extends StatelessWidget { ? AssetsManager.tickCircle : AssetsManager.closeCircle, statusCardColor: - tender.status == 'Won' ? AppColors.gren20 : AppColors.red0, + tender.status == 'Won' ? AppColors.green20 : AppColors.red0, statusTextColor: tender.status == 'Won' ? AppColors.gren30 : AppColors.red10, ); diff --git a/lib/views/your_tenders/your_tenders_screen.dart b/lib/views/your_tenders/your_tenders_screen.dart index 61937d1..ec294ce 100644 --- a/lib/views/your_tenders/your_tenders_screen.dart +++ b/lib/views/your_tenders/your_tenders_screen.dart @@ -1,6 +1,6 @@ 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/theme/colors.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/tenders_submitted.dart'; diff --git a/lib/widgets/theme_toggle.dart b/lib/widgets/theme_toggle.dart new file mode 100644 index 0000000..53fdabb --- /dev/null +++ b/lib/widgets/theme_toggle.dart @@ -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(); + + 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(); + + 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', + ); + } +}