✨implement light and dark theme
This commit is contained in:
@@ -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<SingleChildWidget> get providersRemote {
|
||||
}
|
||||
|
||||
List<SingleChildWidget> get cores {
|
||||
return [Provider(create: (context) => NetworkManager())];
|
||||
return [
|
||||
Provider(create: (context) => NetworkManager()),
|
||||
ChangeNotifierProvider(create: (context) => ThemeProvider()),
|
||||
];
|
||||
}
|
||||
|
||||
List<SingleChildWidget> get apiClients {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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<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
|
||||
Widget build(BuildContext context) {
|
||||
// Listen to theme changes
|
||||
final themeProvider = context.watch<ThemeProvider>();
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<ProgressBarColumn>
|
||||
backgroundColor: Color(0xFFE1E1E1),
|
||||
strokeCap: StrokeCap.round,
|
||||
strokeWidth: 8.0,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF34BCCB)),
|
||||
valueColor: AlwaysStoppedAnimation<Color>(AppColors.jellyBean),
|
||||
value: _animation.value,
|
||||
),
|
||||
),
|
||||
@@ -85,7 +86,11 @@ class _ProgressBarColumnState extends State<ProgressBarColumn>
|
||||
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<ProgressBarColumn>
|
||||
style: TextStyle(
|
||||
fontSize: 16.0.sp(),
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF222222),
|
||||
color: AppColors.titleColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<TendersScreen>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: AppColors.backgroundColor,
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
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<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_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<MainTendersSlider> {
|
||||
children: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 693.0.h(),
|
||||
height: 694.0.h(),
|
||||
child: PageView.builder(
|
||||
controller: pageController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user