marco.pms.mobileapp/lib/helpers/theme/theme_editor_widget.dart
Vaibhav Surve 04da062f4f Refactor UI components to use contentTheme colors
- Updated various screens to replace hardcoded color values with contentTheme.buttonColor for consistency.
- Changed icons in NotesView, UserDocumentsPage, EmployeeDetailPage, EmployeesScreen, ExpenseDetailScreen, and others to use updated icon styles.
- Refactored OfflineScreen and TenantSelectionScreen to utilize new wave background widget.
- Introduced ThemeEditorWidget in UserProfileBar for dynamic theme adjustments.
- Enhanced logout confirmation dialog styling to align with new theme colors.
2025-10-28 17:38:19 +05:30

217 lines
8.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/wave_background.dart';
import 'package:marco/helpers/theme/admin_theme.dart';
class ThemeOption {
final String label;
final Color primary;
final Color button;
final Color brand;
ThemeOption(this.label, this.primary, this.button, this.brand);
}
// Define your themes
final List<ThemeOption> themeOptions = [
ThemeOption("Theme 1", Colors.red, Colors.red, Colors.red),
ThemeOption("Theme 2", const Color(0xFF49BF3C), const Color(0xFF49BF3C), const Color(0xFF49BF3C)),
ThemeOption("Theme 3", const Color(0xFF3F51B5), const Color(0xFF3F51B5), const Color(0xFF3F51B5)),
ThemeOption("Theme 4", const Color(0xFF40B7FF), const Color(0xFF40B7FF), const Color(0xFF40B7FF)),
];
// Reactive controller
class ThemeController extends GetxController {
RxInt selectedIndex = 0.obs;
RxBool showApplied = false.obs;
void init() {
final currentPrimary = AdminTheme.theme.contentTheme.primary;
int index = themeOptions.indexWhere((opt) => opt.primary.value == currentPrimary.value);
selectedIndex.value = index == -1 ? 0 : index;
}
void applyTheme(int index) async {
selectedIndex.value = index;
showApplied.value = true;
// Update AdminTheme
AdminTheme.updateThemeColors(
primary: themeOptions[index].primary,
buttonColor: themeOptions[index].button,
brandColor: themeOptions[index].brand,
);
await Future.delayed(const Duration(milliseconds: 600));
showApplied.value = false;
}
}
// Theme Editor Widget
class ThemeEditorWidget extends StatelessWidget {
final VoidCallback onClose;
ThemeEditorWidget({Key? key, required this.onClose}) : super(key: key);
final ThemeController themeController = Get.put(ThemeController());
@override
Widget build(BuildContext context) {
themeController.init();
return Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MyText.bodyLarge("Theme Customization", fontWeight: 600),
IconButton(
icon: const Icon(Icons.close),
onPressed: onClose,
tooltip: "Back",
iconSize: 20,
),
],
),
const SizedBox(height: 12),
// Theme Cards
Center(
child: Obx(() => Wrap(
spacing: 12,
runSpacing: 12,
alignment: WrapAlignment.center,
children: List.generate(themeOptions.length, (i) {
final theme = themeOptions[i];
final isSelected = themeController.selectedIndex.value == i;
return SizedBox(
width: 80,
child: GestureDetector(
onTap: () => themeController.applyTheme(i),
child: AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isSelected ? theme.brand : Colors.transparent,
width: 2,
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 80,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Stack(
fit: StackFit.expand,
children: [
CustomPaint(
painter: RedWavePainter(theme.brand, 0.15),
),
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Hello, User!",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.w600,
color: theme.primary,
fontSize: 12,
),
),
const SizedBox(height: 4),
SizedBox(
height: 18,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: theme.button,
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
elevation: 1,
textStyle: const TextStyle(fontSize: 10),
),
onPressed: () {},
child: const Text("Welcome"),
),
),
],
),
),
],
),
),
),
const SizedBox(height: 6),
Text(
theme.label,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 12,
color: Colors.grey[700],
),
),
],
),
),
),
);
}),
)),
),
const SizedBox(height: 12),
// Applied Indicator
Obx(() => themeController.showApplied.value
? Padding(
padding: const EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.check_circle,
color: themeOptions[themeController.selectedIndex.value].brand, size: 20),
const SizedBox(width: 6),
Text(
"Theme Applied!",
style: TextStyle(
color: themeOptions[themeController.selectedIndex.value].brand,
fontWeight: FontWeight.w700,
),
),
],
),
)
: const SizedBox()),
const SizedBox(height: 16),
const Text(
"Preview and select a theme. You can change this anytime.",
style: TextStyle(fontSize: 13, color: Colors.black54),
),
],
),
);
}
}