From ae210a5990b4e8d5f4d229387dc614f98c4007f5 Mon Sep 17 00:00:00 2001 From: moon <56061215+MgKyawLay@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:22:41 +0630 Subject: [PATCH] profile added --- android/app/src/main/AndroidManifest.xml | 6 +- .../example/cb_prestige_qr/MainActivity.kt | 10 +- ios/Runner/Info.plist | 8 +- lib/core/storage/local_storage_service.dart | 16 +- .../manager/analysis_chart_metric.dart | 2 +- .../auth/data/fingerprint_repository.dart | 16 -- .../auth/data/user_profile_repository.dart | 63 ++++++++ .../auth/domain/fingerprint_state.dart | 9 -- lib/features/auth/domain/user_profile.dart | 25 +++ .../auth/presentation/pages/login_page.dart | 58 +++---- .../providers/fingerprint_provider.dart | 33 ---- .../settings_local_data_source.dart | 30 ++-- .../settings_repository_impl.dart | 11 +- .../domain/entities/settings_content.dart | 6 +- .../repositories/settings_repository.dart | 1 - .../domain/use_cases/set_finger_enabled.dart | 9 -- .../manager/settings_ui_state.dart | 10 +- .../manager/settings_view_model.dart | 19 +-- .../presentation/pages/settings_page.dart | 147 ++++++++++++++++-- pubspec.yaml | 3 +- 20 files changed, 309 insertions(+), 173 deletions(-) delete mode 100644 lib/features/auth/data/fingerprint_repository.dart create mode 100644 lib/features/auth/data/user_profile_repository.dart delete mode 100644 lib/features/auth/domain/fingerprint_state.dart create mode 100644 lib/features/auth/domain/user_profile.dart delete mode 100644 lib/features/auth/presentation/providers/fingerprint_provider.dart delete mode 100644 lib/features/settings/domain/use_cases/set_finger_enabled.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 150f200..78e5482 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ - - + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 - CFBundleName - cb_prestige_qr - CFBundlePackageType - APPL + CFBundleName + cb_prestige_qr + CFBundlePackageType + APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) CFBundleSignature diff --git a/lib/core/storage/local_storage_service.dart b/lib/core/storage/local_storage_service.dart index c14fce1..91c52ba 100644 --- a/lib/core/storage/local_storage_service.dart +++ b/lib/core/storage/local_storage_service.dart @@ -1,13 +1,23 @@ import 'package:shared_preferences/shared_preferences.dart'; class LocalStorageService { - Future setBool(String key, bool value) async{ + Future setBool(String key, bool value) async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(key, value); } - + Future getBool(String key) async { final prefs = await SharedPreferences.getInstance(); return prefs.getBool(key); } -} \ No newline at end of file + + Future setString(String key, String value) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString(key, value); + } + + Future getString(String key) async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString(key); + } +} diff --git a/lib/features/analysis/presentation/manager/analysis_chart_metric.dart b/lib/features/analysis/presentation/manager/analysis_chart_metric.dart index d335a6c..e0a1bb1 100644 --- a/lib/features/analysis/presentation/manager/analysis_chart_metric.dart +++ b/lib/features/analysis/presentation/manager/analysis_chart_metric.dart @@ -3,6 +3,6 @@ enum AnalysisChartMetric { scans, pointsUsed } extension AnalysisChartMetricX on AnalysisChartMetric { String get label => switch (this) { AnalysisChartMetric.scans => 'Member scans', - AnalysisChartMetric.pointsUsed => 'Coins redeemed', + AnalysisChartMetric.pointsUsed => 'Points redeemed', }; } diff --git a/lib/features/auth/data/fingerprint_repository.dart b/lib/features/auth/data/fingerprint_repository.dart deleted file mode 100644 index 4b37e39..0000000 --- a/lib/features/auth/data/fingerprint_repository.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:cb_prestige_qr/core/storage/local_storage_service.dart'; - -class FingerprintRepository { - final LocalStorageService storage; - FingerprintRepository(this.storage); - - static const key = "fingerprint_enabled"; - - Future load() async { - return await storage.getBool(key) ?? false; - } - - Future save(bool value) async { - await storage.setBool(key, value); - } -} \ No newline at end of file diff --git a/lib/features/auth/data/user_profile_repository.dart b/lib/features/auth/data/user_profile_repository.dart new file mode 100644 index 0000000..524c144 --- /dev/null +++ b/lib/features/auth/data/user_profile_repository.dart @@ -0,0 +1,63 @@ +import 'package:cb_prestige_qr/core/storage/local_storage_service.dart'; +import 'package:cb_prestige_qr/features/auth/domain/user_profile.dart'; + +class UserProfileRepository { + UserProfileRepository(this._storage); + + final LocalStorageService _storage; + + static const _usernameKey = 'logged_in_username'; + static const _displayNameKey = 'logged_in_display_name'; + static const _roleKey = 'logged_in_role'; + static const _branchKey = 'logged_in_branch'; + + Future load() async { + final username = await _storage.getString(_usernameKey) ?? 'cashier'; + final displayName = + await _storage.getString(_displayNameKey) ?? + _displayNameFromUsername(username); + final roleLabel = await _storage.getString(_roleKey) ?? 'Cashier'; + final branchLabel = + await _storage.getString(_branchKey) ?? 'Prestige Counter'; + + return UserProfile( + username: username, + displayName: displayName, + roleLabel: roleLabel, + branchLabel: branchLabel, + ); + } + + Future saveFromUsername(String username) async { + final normalizedUsername = username.trim(); + final safeUsername = normalizedUsername.isEmpty + ? 'cashier' + : normalizedUsername; + + await _storage.setString(_usernameKey, safeUsername); + await _storage.setString( + _displayNameKey, + _displayNameFromUsername(safeUsername), + ); + await _storage.setString(_roleKey, 'Cashier'); + await _storage.setString(_branchKey, 'Prestige Counter'); + } + + static String _displayNameFromUsername(String username) { + final words = username + .replaceAll(RegExp(r'[._-]+'), ' ') + .trim() + .split(RegExp(r'\s+')) + .where((word) => word.isNotEmpty) + .toList(growable: false); + if (words.isEmpty) return 'Cashier'; + + return words.map(_capitalize).join(' '); + } + + static String _capitalize(String value) { + if (value.isEmpty) return value; + if (value.length == 1) return value.toUpperCase(); + return '${value.substring(0, 1).toUpperCase()}${value.substring(1)}'; + } +} diff --git a/lib/features/auth/domain/fingerprint_state.dart b/lib/features/auth/domain/fingerprint_state.dart deleted file mode 100644 index 573f548..0000000 --- a/lib/features/auth/domain/fingerprint_state.dart +++ /dev/null @@ -1,9 +0,0 @@ -class FingerprintState { - final bool enabled; - - FingerprintState(this.enabled); - - FingerprintState copyWith({bool? enabled}){ - return FingerprintState(enabled ?? this.enabled); - } -} \ No newline at end of file diff --git a/lib/features/auth/domain/user_profile.dart b/lib/features/auth/domain/user_profile.dart new file mode 100644 index 0000000..5a2b525 --- /dev/null +++ b/lib/features/auth/domain/user_profile.dart @@ -0,0 +1,25 @@ +class UserProfile { + const UserProfile({ + required this.username, + required this.displayName, + required this.roleLabel, + required this.branchLabel, + }); + + final String username; + final String displayName; + final String roleLabel; + final String branchLabel; + + String get initials { + final parts = displayName + .trim() + .split(RegExp(r'\s+')) + .where((part) => part.isNotEmpty) + .toList(growable: false); + if (parts.isEmpty) return 'U'; + if (parts.length == 1) return parts.first.substring(0, 1).toUpperCase(); + return '${parts.first.substring(0, 1)}${parts.last.substring(0, 1)}' + .toUpperCase(); + } +} diff --git a/lib/features/auth/presentation/pages/login_page.dart b/lib/features/auth/presentation/pages/login_page.dart index fcf815a..6b39c3d 100644 --- a/lib/features/auth/presentation/pages/login_page.dart +++ b/lib/features/auth/presentation/pages/login_page.dart @@ -1,6 +1,7 @@ +import 'package:cb_prestige_qr/core/storage/local_storage_service.dart'; import 'package:cb_prestige_qr/core/utils/MainShell.dart'; +import 'package:cb_prestige_qr/features/auth/data/user_profile_repository.dart'; import 'package:flutter/material.dart'; -import 'package:local_auth/local_auth.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @@ -9,33 +10,16 @@ class LoginPage extends StatefulWidget { State createState() => _LoginPageState(); } -enum _SupportState { unknown, supported, unsupported } - class _LoginPageState extends State { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); - final LocalAuthentication auth = LocalAuthentication(); - bool? _canCheckBiometric; - List? _availableBiometrics; - String _authorized = "Not Authorized"; - bool _isAuthenticating = false; + final UserProfileRepository _userProfileRepository = UserProfileRepository( + LocalStorageService(), + ); bool _isSigningIn = false; - _SupportState _supportState = _SupportState.unknown; var _obscurePassword = true; - - @override - void initState(){ - super.initState(); - auth.isDeviceSupported().then( - (bool isSupported) => setState( - () => _supportState = isSupported - ? _SupportState.supported - : _SupportState.unsupported, - ), - ); - } @override void dispose() { @@ -56,9 +40,15 @@ class _LoginPageState extends State { if (!mounted) return; - Navigator.of(context).pushReplacement( - MaterialPageRoute(builder: (_) => const MainShell()), + await _userProfileRepository.saveFromUsername( + _usernameController.text.trim(), ); + + if (!mounted) return; + + Navigator.of( + context, + ).pushReplacement(MaterialPageRoute(builder: (_) => const MainShell())); } @override @@ -72,11 +62,7 @@ class _LoginPageState extends State { gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [ - Color(0xff17181c), - Color(0xff25262b), - Color(0xff2c2d33), - ], + colors: [Color(0xff17181c), Color(0xff25262b), Color(0xff2c2d33)], ), ), child: SafeArea( @@ -88,12 +74,14 @@ class _LoginPageState extends State { child: Container( padding: const EdgeInsets.all(24), decoration: BoxDecoration( - color: const Color(0xff1d1e23).withOpacity(0.92), + color: const Color(0xff1d1e23).withValues(alpha: 0.92), borderRadius: BorderRadius.circular(28), - border: Border.all(color: Colors.white.withOpacity(0.08)), + border: Border.all( + color: Colors.white.withValues(alpha: 0.08), + ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.28), + color: Colors.black.withValues(alpha: 0.28), blurRadius: 28, offset: const Offset(0, 18), ), @@ -111,7 +99,9 @@ class _LoginPageState extends State { height: 56, width: 56, decoration: BoxDecoration( - color: colorScheme.primary.withOpacity(0.16), + color: colorScheme.primary.withValues( + alpha: 0.16, + ), borderRadius: BorderRadius.circular(18), ), child: const Icon( @@ -151,10 +141,10 @@ class _LoginPageState extends State { width: double.infinity, padding: const EdgeInsets.all(18), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.04), + color: Colors.white.withValues(alpha: 0.04), borderRadius: BorderRadius.circular(20), border: Border.all( - color: Colors.white.withOpacity(0.06), + color: Colors.white.withValues(alpha: 0.06), ), ), child: Row( diff --git a/lib/features/auth/presentation/providers/fingerprint_provider.dart b/lib/features/auth/presentation/providers/fingerprint_provider.dart deleted file mode 100644 index f386518..0000000 --- a/lib/features/auth/presentation/providers/fingerprint_provider.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:cb_prestige_qr/core/storage/local_storage_service.dart'; -import 'package:cb_prestige_qr/features/auth/data/fingerprint_repository.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:hooks_riverpod/legacy.dart'; - - -final storageProvider = Provider((ref) => LocalStorageService()); - -final fingerprintRepoProvider = Provider((ref) { - return FingerprintRepository(ref.read(storageProvider)); -}); - -final fingerprintProvider = -StateNotifierProvider((ref) { - return FingerprintNotifier(ref.read(fingerprintRepoProvider)); -}); - -class FingerprintNotifier extends StateNotifier { - final FingerprintRepository repo; - - FingerprintNotifier(this.repo) : super(false) { - _init(); - } - - Future _init() async { - state = await repo.load(); - } - - Future toggle(bool value) async { - state = value; - await repo.save(value); - } -} \ No newline at end of file diff --git a/lib/features/settings/data/data_sources/settings_local_data_source.dart b/lib/features/settings/data/data_sources/settings_local_data_source.dart index fbc35fd..461aa6e 100644 --- a/lib/features/settings/data/data_sources/settings_local_data_source.dart +++ b/lib/features/settings/data/data_sources/settings_local_data_source.dart @@ -1,41 +1,41 @@ +import 'package:cb_prestige_qr/core/storage/local_storage_service.dart'; +import 'package:cb_prestige_qr/features/auth/data/user_profile_repository.dart'; + import '../../domain/entities/settings_content.dart'; abstract class SettingsLocalDataSource { - SettingsContent getSettings(); - void setNotificationsEnabled(bool value); - void setHapticsEnabled(bool value); - void setFingerEnabled(bool value); + Future getSettings(); + Future setNotificationsEnabled(bool value); + Future setHapticsEnabled(bool value); } class SettingsLocalDataSourceImpl implements SettingsLocalDataSource { - SettingsLocalDataSourceImpl(); + SettingsLocalDataSourceImpl(this._storage); + + final LocalStorageService _storage; bool _notificationsEnabled = true; bool _hapticsEnabled = true; - bool _fingerEnabled = true; @override - SettingsContent getSettings() { + Future getSettings() async { + final userProfile = await UserProfileRepository(_storage).load(); + return SettingsContent( notificationsEnabled: _notificationsEnabled, hapticsEnabled: _hapticsEnabled, - fingerEnabled: _fingerEnabled, appVersionLabel: 'v1.0.0', + userProfile: userProfile, ); } @override - void setNotificationsEnabled(bool value) { + Future setNotificationsEnabled(bool value) async { _notificationsEnabled = value; } @override - void setHapticsEnabled(bool value) { + Future setHapticsEnabled(bool value) async { _hapticsEnabled = value; } - - @override - void setFingerEnabled(bool value) { - _fingerEnabled = value; - } } diff --git a/lib/features/settings/data/repositories/settings_repository_impl.dart b/lib/features/settings/data/repositories/settings_repository_impl.dart index 77242d1..3825821 100644 --- a/lib/features/settings/data/repositories/settings_repository_impl.dart +++ b/lib/features/settings/data/repositories/settings_repository_impl.dart @@ -8,20 +8,15 @@ class SettingsRepositoryImpl implements SettingsRepository { final SettingsLocalDataSource _localDataSource; @override - Future getSettings() async => _localDataSource.getSettings(); + Future getSettings() => _localDataSource.getSettings(); @override Future setNotificationsEnabled(bool value) async { - _localDataSource.setNotificationsEnabled(value); + await _localDataSource.setNotificationsEnabled(value); } @override Future setHapticsEnabled(bool value) async { - _localDataSource.setHapticsEnabled(value); - } - - @override - Future setFingerEnabled(bool value) async { - _localDataSource.setFingerEnabled(value); + await _localDataSource.setHapticsEnabled(value); } } diff --git a/lib/features/settings/domain/entities/settings_content.dart b/lib/features/settings/domain/entities/settings_content.dart index 1c20146..b54e09a 100644 --- a/lib/features/settings/domain/entities/settings_content.dart +++ b/lib/features/settings/domain/entities/settings_content.dart @@ -1,13 +1,15 @@ +import 'package:cb_prestige_qr/features/auth/domain/user_profile.dart'; + class SettingsContent { const SettingsContent({ required this.notificationsEnabled, required this.hapticsEnabled, - required this.fingerEnabled, required this.appVersionLabel, + required this.userProfile, }); final bool notificationsEnabled; final bool hapticsEnabled; - final bool fingerEnabled; final String appVersionLabel; + final UserProfile userProfile; } diff --git a/lib/features/settings/domain/repositories/settings_repository.dart b/lib/features/settings/domain/repositories/settings_repository.dart index 99173c8..e08579e 100644 --- a/lib/features/settings/domain/repositories/settings_repository.dart +++ b/lib/features/settings/domain/repositories/settings_repository.dart @@ -4,5 +4,4 @@ abstract class SettingsRepository { Future getSettings(); Future setNotificationsEnabled(bool value); Future setHapticsEnabled(bool value); - Future setFingerEnabled(bool value); } diff --git a/lib/features/settings/domain/use_cases/set_finger_enabled.dart b/lib/features/settings/domain/use_cases/set_finger_enabled.dart deleted file mode 100644 index cf64fbf..0000000 --- a/lib/features/settings/domain/use_cases/set_finger_enabled.dart +++ /dev/null @@ -1,9 +0,0 @@ -import '../repositories/settings_repository.dart'; - -class SetFingerEnabled { - const SetFingerEnabled(this._repository); - - final SettingsRepository _repository; - - Future call(bool value) => _repository.setFingerEnabled(value); -} diff --git a/lib/features/settings/presentation/manager/settings_ui_state.dart b/lib/features/settings/presentation/manager/settings_ui_state.dart index 2fa4a7f..e933b39 100644 --- a/lib/features/settings/presentation/manager/settings_ui_state.dart +++ b/lib/features/settings/presentation/manager/settings_ui_state.dart @@ -1,30 +1,32 @@ import 'package:flutter/foundation.dart'; +import '../../../auth/domain/user_profile.dart'; + @immutable class SettingsUiState { const SettingsUiState({ required this.notificationsEnabled, required this.hapticsEnabled, - required this.fingerEnabled, required this.appVersionLabel, + required this.userProfile, }); final bool notificationsEnabled; final bool hapticsEnabled; - final bool fingerEnabled; final String appVersionLabel; + final UserProfile userProfile; SettingsUiState copyWith({ bool? notificationsEnabled, bool? hapticsEnabled, - bool? fingerEnabled, String? appVersionLabel, + UserProfile? userProfile, }) { return SettingsUiState( notificationsEnabled: notificationsEnabled ?? this.notificationsEnabled, hapticsEnabled: hapticsEnabled ?? this.hapticsEnabled, - fingerEnabled: fingerEnabled ?? this.fingerEnabled, appVersionLabel: appVersionLabel ?? this.appVersionLabel, + userProfile: userProfile ?? this.userProfile, ); } } diff --git a/lib/features/settings/presentation/manager/settings_view_model.dart b/lib/features/settings/presentation/manager/settings_view_model.dart index 7a2e309..873306c 100644 --- a/lib/features/settings/presentation/manager/settings_view_model.dart +++ b/lib/features/settings/presentation/manager/settings_view_model.dart @@ -1,17 +1,21 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import '../../../../core/storage/local_storage_service.dart'; import '../../data/data_sources/settings_local_data_source.dart'; import '../../data/repositories/settings_repository_impl.dart'; import '../../domain/entities/settings_content.dart'; import '../../domain/repositories/settings_repository.dart'; import '../../domain/use_cases/get_settings.dart'; -import '../../domain/use_cases/set_finger_enabled.dart'; import '../../domain/use_cases/set_haptics_enabled.dart'; import '../../domain/use_cases/set_notifications_enabled.dart'; import 'settings_ui_state.dart'; +final _localStorageServiceProvider = Provider( + (ref) => LocalStorageService(), +); + final _settingsLocalDataSourceProvider = Provider( - (ref) => SettingsLocalDataSourceImpl(), + (ref) => SettingsLocalDataSourceImpl(ref.watch(_localStorageServiceProvider)), ); final _settingsRepositoryProvider = Provider( @@ -30,10 +34,6 @@ final _setHapticsEnabledProvider = Provider( (ref) => SetHapticsEnabled(ref.watch(_settingsRepositoryProvider)), ); -final _setFingerEnabledProvider = Provider( - (ref) => SetFingerEnabled(ref.watch(_settingsRepositoryProvider)), -); - final settingsViewModelProvider = AsyncNotifierProvider( SettingsViewModel.new, @@ -50,8 +50,8 @@ class SettingsViewModel extends AsyncNotifier { return SettingsUiState( notificationsEnabled: content.notificationsEnabled, hapticsEnabled: content.hapticsEnabled, - fingerEnabled: content.fingerEnabled, appVersionLabel: content.appVersionLabel, + userProfile: content.userProfile, ); } @@ -64,9 +64,4 @@ class SettingsViewModel extends AsyncNotifier { await ref.watch(_setHapticsEnabledProvider)(value); state = state.whenData((s) => s.copyWith(hapticsEnabled: value)); } - - Future toggleFinger(bool value) async { - await ref.watch(_setFingerEnabledProvider)(value); - state = state.whenData((s) => s.copyWith(fingerEnabled: value)); - } } diff --git a/lib/features/settings/presentation/pages/settings_page.dart b/lib/features/settings/presentation/pages/settings_page.dart index 4e66a4c..3453bf4 100644 --- a/lib/features/settings/presentation/pages/settings_page.dart +++ b/lib/features/settings/presentation/pages/settings_page.dart @@ -3,6 +3,7 @@ import 'package:cb_prestige_qr/features/auth/presentation/pages/login_page.dart' import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import '../../../auth/domain/user_profile.dart'; import '../manager/settings_ui_state.dart'; import '../manager/settings_view_model.dart'; @@ -29,7 +30,6 @@ class SettingsPage extends ConsumerWidget { state: state, onNotificationsChanged: viewModel.toggleNotifications, onHapticsChanged: viewModel.toggleHaptics, - onFingerChanged: viewModel.toggleFinger, onLogout: () { ref.read(navIndexNotifierProvider.notifier).setIndex(0); Navigator.of(context).pushAndRemoveUntil( @@ -55,14 +55,12 @@ class _SettingsBody extends StatelessWidget { required this.state, required this.onNotificationsChanged, required this.onHapticsChanged, - required this.onFingerChanged, required this.onLogout, }); final SettingsUiState state; final ValueChanged onNotificationsChanged; final ValueChanged onHapticsChanged; - final ValueChanged onFingerChanged; final VoidCallback onLogout; @override @@ -70,6 +68,8 @@ class _SettingsBody extends StatelessWidget { return ListView( padding: const EdgeInsets.fromLTRB(16, 12, 16, 24), children: [ + _ProfileCard(profile: state.userProfile), + const SizedBox(height: 12), _SectionCard( title: 'Preferences', children: [ @@ -86,13 +86,6 @@ class _SettingsBody extends StatelessWidget { title: const Text('Haptics'), subtitle: const Text('Vibration feedback'), ), - const Divider(height: 1), - SwitchListTile.adaptive( - value: state.fingerEnabled, - onChanged: onFingerChanged, - title: const Text('Fingerprint'), - subtitle: const Text('Enable fingerprint authentication'), - ), ], ), const SizedBox(height: 12), @@ -112,6 +105,134 @@ class _SettingsBody extends StatelessWidget { } } +class _ProfileCard extends StatelessWidget { + const _ProfileCard({required this.profile}); + + final UserProfile profile; + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + + return Container( + decoration: BoxDecoration( + color: colorScheme.surface, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: colorScheme.outlineVariant.withValues(alpha: 0.5), + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.06), + blurRadius: 14, + offset: const Offset(0, 6), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Container( + width: 54, + height: 54, + decoration: BoxDecoration( + color: colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(18), + ), + alignment: Alignment.center, + child: Text( + profile.initials, + style: textTheme.titleLarge?.copyWith( + color: colorScheme.onPrimaryContainer, + fontWeight: FontWeight.w900, + ), + ), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + profile.displayName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.w800, + ), + ), + const SizedBox(height: 3), + Text( + '@${profile.username}', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: textTheme.bodySmall?.copyWith( + color: colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: [ + _ProfileChip( + icon: Icons.badge_rounded, + label: profile.roleLabel, + ), + _ProfileChip( + icon: Icons.store_rounded, + label: profile.branchLabel, + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _ProfileChip extends StatelessWidget { + const _ProfileChip({required this.icon, required this.label}); + + final IconData icon; + final String label; + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + final textTheme = Theme.of(context).textTheme; + + return Container( + padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 6), + decoration: BoxDecoration( + color: colorScheme.surfaceContainerHighest.withValues(alpha: 0.55), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 15, color: colorScheme.onSurfaceVariant), + const SizedBox(width: 5), + Text( + label, + style: textTheme.labelMedium?.copyWith( + color: colorScheme.onSurfaceVariant, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ); + } +} + class _LogoutButton extends StatelessWidget { const _LogoutButton({required this.onPressed}); @@ -157,10 +278,12 @@ class _SectionCard extends StatelessWidget { decoration: BoxDecoration( color: colorScheme.surface, borderRadius: BorderRadius.circular(16), - border: Border.all(color: colorScheme.outlineVariant.withOpacity(0.5)), + border: Border.all( + color: colorScheme.outlineVariant.withValues(alpha: 0.5), + ), boxShadow: [ BoxShadow( - color: Colors.black.withOpacity(0.06), + color: Colors.black.withValues(alpha: 0.06), blurRadius: 14, offset: const Offset(0, 6), ), diff --git a/pubspec.yaml b/pubspec.yaml index a6c4450..0d48d33 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,8 +40,7 @@ dependencies: riverpod_annotation: ^4.0.2 carousel_slider: ^5.1.2 mobile_scanner: ^7.2.0 - local_auth: ^3.0.1 - shared_preferences: ^2.5.5 + shared_preferences: ^2.5.5 dev_dependencies: flutter_test: