diff --git a/kifi-app/flutter_launcher_icons.yaml b/kifi-app/flutter_launcher_icons.yaml index 242e426..b70fb34 100644 --- a/kifi-app/flutter_launcher_icons.yaml +++ b/kifi-app/flutter_launcher_icons.yaml @@ -1,4 +1,7 @@ flutter_icons: android: true ios: true + web: + generate: true + image_path: "assets/icon.png" image_path: "assets/icon.png" diff --git a/kifi-app/lib/core/widgets/desktop_sidebar.dart b/kifi-app/lib/core/widgets/desktop_sidebar.dart index db8ca1d..1da9908 100644 --- a/kifi-app/lib/core/widgets/desktop_sidebar.dart +++ b/kifi-app/lib/core/widgets/desktop_sidebar.dart @@ -26,6 +26,8 @@ class DesktopSidebar extends ConsumerWidget { final isDark = theme.brightness == Brightness.dark; final isBusinessMode = ref.watch(businessModeProvider); final businessProfile = ref.watch(businessProfileProvider).asData?.value; + final nature = (businessProfile?.natureOfBusiness ?? businessProfile?.industry ?? 'JEWELLERY').toUpperCase(); + final isJewellery = nature == 'JEWELLERY'; final ratesAsync = ref.watch(commodityRatesProvider); return Container( @@ -51,22 +53,23 @@ class DesktopSidebar extends ConsumerWidget { width: 40, height: 40, decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [Color(0xFFD4AF37), Color(0xFFAA771C)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( - color: const Color(0xFFD4AF37).withValues(alpha: 0.3), - blurRadius: 10, - offset: const Offset(0, 4), + color: Colors.black.withValues(alpha: 0.08), + blurRadius: 8, + offset: const Offset(0, 2), ), ], ), - child: const Center( - child: Icon(LucideIcons.gem, color: Colors.white, size: 22), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Image.asset( + 'assets/icon.png', + width: 40, + height: 40, + fit: BoxFit.cover, + ), ), ), const SizedBox(width: 12), @@ -276,8 +279,9 @@ class DesktopSidebar extends ConsumerWidget { ), ), - // 4. Live Metal Rate Widget in Sidebar - ratesAsync.when( + // 4. Live Metal Rate Widget in Sidebar (Jewellery only) + if (isJewellery) + ratesAsync.when( data: (rates) { if (rates.isEmpty) return const SizedBox.shrink(); final goldRate = rates.firstWhere( diff --git a/kifi-app/lib/features/auth/presentation/auth_screen.dart b/kifi-app/lib/features/auth/presentation/auth_screen.dart index 3507ad6..98c3c37 100644 --- a/kifi-app/lib/features/auth/presentation/auth_screen.dart +++ b/kifi-app/lib/features/auth/presentation/auth_screen.dart @@ -131,19 +131,28 @@ class _AuthScreenState extends ConsumerState mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Container( - width: 80, - height: 80, - decoration: const BoxDecoration( - color: Colors.transparent, - shape: BoxShape.circle, - ), - child: Center( - child: Image.asset( - 'assets/logo.png', - width: 80, - height: 80, - fit: BoxFit.contain, + Center( + child: Container( + width: 80, + height: 80, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.08), + blurRadius: 16, + offset: const Offset(0, 4), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Image.asset( + 'assets/icon.png', + width: 80, + height: 80, + fit: BoxFit.cover, + ), ), ), ), diff --git a/kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart b/kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart index 3613a89..baa2afa 100644 --- a/kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart +++ b/kifi-app/lib/features/auth/presentation/setup_wizard_screen.dart @@ -12,8 +12,7 @@ class SetupWizardScreen extends StatefulWidget { State createState() => _SetupWizardScreenState(); } -class _SetupWizardScreenState extends State - with SingleTickerProviderStateMixin { +class _SetupWizardScreenState extends State { bool _isLoading = false; int _currentStep = 0; String _accountType = 'INDIVIDUAL'; @@ -40,6 +39,19 @@ class _SetupWizardScreenState extends State int get _totalSteps => _accountType == 'BUSINESS' ? 4 : 3; + @override + void dispose() { + _nameController.dispose(); + _usernameController.dispose(); + _businessNameController.dispose(); + _addressController.dispose(); + _emailController.dispose(); + _gstController.dispose(); + _panController.dispose(); + _msmeController.dispose(); + super.dispose(); + } + Future _checkUsername(String username) async { if (username.length < 3) return; setState(() => _checkingUsername = true); @@ -111,6 +123,7 @@ class _SetupWizardScreenState extends State } void _nextStep() { + FocusScope.of(context).unfocus(); if (_currentStep == 1) { if (_nameController.text.trim().isEmpty) { ScaffoldMessenger.of(context).showSnackBar( @@ -150,6 +163,7 @@ class _SetupWizardScreenState extends State } void _prevStep() { + FocusScope.of(context).unfocus(); if (_currentStep > 0) { setState(() => _currentStep--); } @@ -209,7 +223,6 @@ class _SetupWizardScreenState extends State Widget _buildStep0AccountType() { return Column( - key: const ValueKey(0), crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( @@ -324,7 +337,6 @@ class _SetupWizardScreenState extends State Widget _buildStep1Personal() { return Column( - key: const ValueKey(1), crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( @@ -354,6 +366,7 @@ class _SetupWizardScreenState extends State duration: const Duration(milliseconds: 200), child: _checkingUsername ? const SizedBox( + key: ValueKey('user_check_spinner'), width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), @@ -362,7 +375,7 @@ class _SetupWizardScreenState extends State _isUsernameAvailable ? LucideIcons.checkCircle2 : LucideIcons.xCircle, - key: ValueKey(_isUsernameAvailable), + key: ValueKey('user_avail_${_isUsernameAvailable}'), color: _usernameController.text.isEmpty ? Colors.transparent : (_isUsernameAvailable @@ -388,7 +401,6 @@ class _SetupWizardScreenState extends State Widget _buildStep2Business() { return Column( - key: const ValueKey(2), crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( @@ -410,6 +422,10 @@ class _SetupWizardScreenState extends State value: 'JEWELLERY', child: Text('Jewellery', style: TextStyle(color: Colors.black87)), ), + DropdownMenuItem( + value: 'ECOMMERCE', + child: Text('E-Commerce Seller', style: TextStyle(color: Colors.black87)), + ), DropdownMenuItem( value: 'PROJECT_MANAGEMENT', child: Text( @@ -474,7 +490,6 @@ class _SetupWizardScreenState extends State Widget _buildStep3Consent() { return Column( - key: const ValueKey(3), crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text( @@ -556,12 +571,11 @@ class _SetupWizardScreenState extends State ); } - Widget _buildCurrentStep() { - if (_currentStep == 0) return _buildStep0AccountType(); - if (_currentStep == 1) return _buildStep1Personal(); - if (_accountType == 'BUSINESS' && _currentStep == 2) - return _buildStep2Business(); - return _buildStep3Consent(); // Step 2 (Individual) or Step 3 (Business) + int get _stackIndex { + if (_accountType == 'INDIVIDUAL' && _currentStep == 2) { + return 3; + } + return _currentStep; } @override @@ -587,28 +601,38 @@ class _SetupWizardScreenState extends State child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 600), - child: AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - switchInCurve: Curves.easeOutCubic, - switchOutCurve: Curves.easeInCubic, - transitionBuilder: (child, animation) { - return SlideTransition( - position: Tween( - begin: const Offset(0.05, 0), - end: Offset.zero, - ).animate(animation), - child: FadeTransition(opacity: animation, child: child), - ); - }, - child: SingleChildScrollView( - key: ValueKey(_currentStep), - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.symmetric( - horizontal: 24.0, - vertical: 16.0, + child: IndexedStack( + index: _stackIndex, + children: [ + SingleChildScrollView( + padding: const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 16.0, + ), + child: _buildStep0AccountType(), ), - child: _buildCurrentStep(), - ), + SingleChildScrollView( + padding: const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 16.0, + ), + child: _buildStep1Personal(), + ), + SingleChildScrollView( + padding: const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 16.0, + ), + child: _buildStep2Business(), + ), + SingleChildScrollView( + padding: const EdgeInsets.symmetric( + horizontal: 24.0, + vertical: 16.0, + ), + child: _buildStep3Consent(), + ), + ], ), ), ), diff --git a/kifi-app/lib/features/business/domain/business_profile.dart b/kifi-app/lib/features/business/domain/business_profile.dart index a8ceaaf..b436ab0 100644 --- a/kifi-app/lib/features/business/domain/business_profile.dart +++ b/kifi-app/lib/features/business/domain/business_profile.dart @@ -13,6 +13,8 @@ class BusinessProfile { final String? emailId; final String? panNumber; final String? gstin; + final String? natureOfBusiness; + final String? msmeNumber; BusinessProfile({ this.id, @@ -29,13 +31,15 @@ class BusinessProfile { this.emailId, this.panNumber, this.gstin, + this.natureOfBusiness, + this.msmeNumber, }); factory BusinessProfile.fromJson(Map json) { return BusinessProfile( id: json['id'], userId: json['userId'], - businessName: json['businessName'], + businessName: json['businessName'] ?? '', industry: json['industry'], taxNumber: json['taxNumber'], currency: json['currency'], @@ -47,6 +51,8 @@ class BusinessProfile { emailId: json['emailId'], panNumber: json['panNumber'], gstin: json['gstin'], + natureOfBusiness: json['natureOfBusiness'] ?? json['industry'], + msmeNumber: json['msmeNumber'], ); } @@ -66,6 +72,8 @@ class BusinessProfile { 'emailId': emailId, 'panNumber': panNumber, 'gstin': gstin, + 'natureOfBusiness': natureOfBusiness, + 'msmeNumber': msmeNumber, }; } @@ -82,6 +90,8 @@ class BusinessProfile { String? emailId, String? panNumber, String? gstin, + String? natureOfBusiness, + String? msmeNumber, }) { return BusinessProfile( id: id, @@ -98,6 +108,8 @@ class BusinessProfile { emailId: emailId ?? this.emailId, panNumber: panNumber ?? this.panNumber, gstin: gstin ?? this.gstin, + natureOfBusiness: natureOfBusiness ?? this.natureOfBusiness, + msmeNumber: msmeNumber ?? this.msmeNumber, ); } } diff --git a/kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart b/kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart index 60db8cb..08720d5 100644 --- a/kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart +++ b/kifi-app/lib/features/business/presentation/hub/business_hub_screen.dart @@ -34,6 +34,8 @@ class BusinessHubScreen extends ConsumerWidget { final bool showInventory = featureState?.inventoryManagement ?? false; final bool showSales = featureState?.salesManagement ?? false; final bool showPurchase = featureState?.purchaseManagement ?? false; + final nature = (profile?.natureOfBusiness ?? profile?.industry ?? 'JEWELLERY').toUpperCase(); + final bool isJewellery = nature == 'JEWELLERY'; return RefreshIndicator( onRefresh: () async { @@ -200,7 +202,7 @@ class BusinessHubScreen extends ConsumerWidget { ), isDesktop: isDesktop, ), - if (showInventory) + if (showInventory && isJewellery) _buildActionCard( context, 'Daily Rates', diff --git a/kifi-app/lib/features/inventory/presentation/category_management_screen.dart b/kifi-app/lib/features/inventory/presentation/category_management_screen.dart index c19d20c..3a458b9 100644 --- a/kifi-app/lib/features/inventory/presentation/category_management_screen.dart +++ b/kifi-app/lib/features/inventory/presentation/category_management_screen.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/product_categories_provider.dart'; import '../../../core/theme/nature_colors.dart'; import '../../business/providers/business_mode_provider.dart'; +import '../../business/providers/business_provider.dart'; import '../../../core/theme/app_theme.dart'; import 'package:lucide_icons_flutter/lucide_icons.dart'; import 'dart:ui'; @@ -99,6 +100,18 @@ class _CategoryManagementScreenState extends ConsumerState c.parentCategoryId == category.id).toList(); final isLeaf = children.isEmpty && !category.hasChild; + final hasCommodity = category.commodityCode != null && category.commodityCode != 'NONE' && category.commodityCode!.isNotEmpty; + final hasHsn = category.defaultHsn != null && category.defaultHsn!.isNotEmpty; + + String? subtitleText; + if (hasCommodity && hasHsn) { + subtitleText = '${category.commodityCode} • HSN: ${category.defaultHsn}'; + } else if (hasCommodity) { + subtitleText = category.commodityCode; + } else if (hasHsn) { + subtitleText = 'HSN: ${category.defaultHsn}'; + } + // A nice frosted glass card return Container( margin: EdgeInsets.only(left: depth * 16.0, bottom: 8), @@ -136,8 +149,8 @@ class _CategoryManagementScreenState extends ConsumerState( - icon: const Icon(LucideIcons.moreVertical, color: Colors.grey), - onSelected: (value) { - if (value == 'edit') { + icon: const Icon(LucideIcons.ellipsisVertical, size: 18, color: Colors.grey), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + onSelected: (val) { + if (val == 'edit') { _showAddCategorySheet(context, category, ref, isEdit: true); - } else if (value == 'add_sub') { + } else if (val == 'addSub') { _showAddCategorySheet(context, category, ref, isEdit: false); - } else if (value == 'delete') { - if (category.id != null) { - ref.read(productCategoriesProvider.notifier).deleteCategory(category.id!); - } + } else if (val == 'delete') { + _confirmDelete(category); } }, itemBuilder: (context) => [ - const PopupMenuItem( - value: 'edit', - child: Row(children: [Icon(LucideIcons.edit, size: 18), SizedBox(width: 8), Text('Edit')]), - ), if (!isLeaf) const PopupMenuItem( - value: 'add_sub', - child: Row(children: [Icon(LucideIcons.plus, size: 18), SizedBox(width: 8), Text('Add Subcategory')]), + value: 'addSub', + child: Row( + children: [ + Icon(LucideIcons.folderPlus, size: 18, color: Colors.blue), + SizedBox(width: 12), + Text('Add Subcategory'), + ], + ), ), + const PopupMenuItem( + value: 'edit', + child: Row( + children: [ + Icon(LucideIcons.pencil, size: 18, color: Colors.orange), + SizedBox(width: 12), + Text('Edit Details'), + ], + ), + ), const PopupMenuItem( value: 'delete', - child: Row(children: [Icon(LucideIcons.trash2, size: 18, color: Colors.red), SizedBox(width: 8), Text('Delete', style: TextStyle(color: Colors.red))]), + child: Row( + children: [ + Icon(LucideIcons.trash2, size: 18, color: Colors.red), + SizedBox(width: 12), + Text('Delete Category', style: TextStyle(color: Colors.red)), + ], + ), ), ], ); } + + void _confirmDelete(ProductCategory category) { + showDialog( + context: context, + builder: (context) => AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + title: const Text('Delete Category?'), + content: Text('Are you sure you want to delete "${category.name}"? If it has subcategories or products, they will also be affected.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: Colors.red, foregroundColor: Colors.white), + onPressed: () { + ref.read(productCategoriesProvider.notifier).deleteCategory(category.id!); + Navigator.pop(context); + }, + child: const Text('Delete'), + ), + ], + ), + ); + } } void _showAddCategorySheet(BuildContext context, ProductCategory? parentOrCategory, WidgetRef ref, {bool isEdit = false}) { @@ -251,7 +306,7 @@ class _CategoryFormSheetState extends ConsumerState { bool _huidRequired = false; String _commodityCode = 'XAU'; String _makingChargeType = 'PER_GRAM'; - String _baseUnit = 'g'; + String _baseUnit = 'pcs'; final List> _commodities = [ {'code': 'XAU', 'label': 'XAU - Gold'}, @@ -264,6 +319,13 @@ class _CategoryFormSheetState extends ConsumerState { @override void initState() { super.initState(); + final profile = ref.read(businessProfileProvider).value; + final nature = (profile?.natureOfBusiness ?? profile?.industry ?? 'JEWELLERY').toUpperCase(); + final isJewellery = nature == 'JEWELLERY'; + + _baseUnit = isJewellery ? 'g' : 'pcs'; + _commodityCode = isJewellery ? 'XAU' : 'NONE'; + if (widget.categoryToEdit != null) { final c = widget.categoryToEdit!; _selectedParentId = c.parentCategoryId; @@ -275,14 +337,13 @@ class _CategoryFormSheetState extends ConsumerState { _makingChargeController.text = c.defaultMakingCharge?.toString() ?? ''; _purityFactorController.text = formatPurity(c.purityFactor); _huidRequired = c.huidRequired; - _commodityCode = c.commodityCode ?? 'XAU'; + _commodityCode = c.commodityCode ?? (isJewellery ? 'XAU' : 'NONE'); // Handle legacy or varying enum string values _makingChargeType = c.makingChargeType ?? 'PER_GRAM'; if (_makingChargeType == 'PER_GM') _makingChargeType = 'PER_GRAM'; - - _baseUnit = c.baseUnit ?? 'g'; + _baseUnit = c.baseUnit ?? (isJewellery ? 'g' : 'pcs'); if (_baseUnit == 'gm') _baseUnit = 'g'; } } else if (widget.parent != null) { @@ -302,18 +363,22 @@ class _CategoryFormSheetState extends ConsumerState { void _submit() { if (_formKey.currentState!.validate()) { + final profile = ref.read(businessProfileProvider).value; + final nature = (profile?.natureOfBusiness ?? profile?.industry ?? 'JEWELLERY').toUpperCase(); + final isJewellery = nature == 'JEWELLERY'; + final newCategory = ProductCategory( id: widget.categoryToEdit?.id, name: _nameController.text.trim(), parentCategoryId: _selectedParentId, hasChild: !_isLeaf, - commodityCode: _isLeaf ? _commodityCode : null, - purityFactor: _isLeaf ? normalizePurity(double.tryParse(_purityFactorController.text)) : 1.0, + commodityCode: _isLeaf ? (isJewellery ? _commodityCode : 'NONE') : null, + purityFactor: _isLeaf ? (isJewellery ? normalizePurity(double.tryParse(_purityFactorController.text)) : 1.0) : 1.0, defaultHsn: _isLeaf ? _hsnController.text.trim() : null, defaultGst: _isLeaf ? double.tryParse(_gstController.text) : null, - huidRequired: _isLeaf ? _huidRequired : false, - defaultMakingCharge: _isLeaf ? double.tryParse(_makingChargeController.text) : null, - makingChargeType: _isLeaf ? _makingChargeType : null, + huidRequired: _isLeaf ? (isJewellery ? _huidRequired : false) : false, + defaultMakingCharge: _isLeaf && isJewellery ? double.tryParse(_makingChargeController.text) : null, + makingChargeType: _isLeaf && isJewellery ? _makingChargeType : null, baseUnit: _isLeaf ? _baseUnit : 'pcs', ); @@ -330,6 +395,9 @@ class _CategoryFormSheetState extends ConsumerState { Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final isBusinessMode = ref.watch(businessModeProvider); + final businessProfile = ref.watch(businessProfileProvider).value; + final nature = (businessProfile?.natureOfBusiness ?? businessProfile?.industry ?? 'JEWELLERY').toUpperCase(); + final isJewellery = nature == 'JEWELLERY'; return Container( height: MediaQuery.of(context).size.height * 0.85, @@ -461,7 +529,7 @@ class _CategoryFormSheetState extends ConsumerState { const Text('Product Defaults', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 16), - if (isBusinessMode) ...[ + if (isJewellery && isBusinessMode) ...[ Row( children: [ Expanded( @@ -516,51 +584,66 @@ class _CategoryFormSheetState extends ConsumerState { ), const SizedBox(height: 16), - SwitchListTile( - title: const Text('HUID Required'), - subtitle: const Text('Is Hallmark Unique Identification mandatory?'), - value: _huidRequired, - onChanged: (val) => setState(() => _huidRequired = val), - contentPadding: EdgeInsets.zero, - ), - const SizedBox(height: 16), - - Row( - children: [ - Expanded( - child: DropdownButtonFormField( - value: _makingChargeType, - decoration: InputDecoration( - labelText: 'Making Charge Type', + if (isJewellery) ...[ + SwitchListTile( + title: const Text('HUID Required'), + subtitle: const Text('Is Hallmark Unique Identification mandatory?'), + value: _huidRequired, + onChanged: (val) => setState(() => _huidRequired = val), + contentPadding: EdgeInsets.zero, + ), + const SizedBox(height: 16), + + Row( + children: [ + Expanded( + child: DropdownButtonFormField( + value: _makingChargeType, + decoration: const InputDecoration( + labelText: 'Making Charge Type', + ), + items: const [ + DropdownMenuItem(value: 'PER_GRAM', child: Text('Per Gram')), + DropdownMenuItem(value: 'PER_PIECE', child: Text('Per Piece')), + DropdownMenuItem(value: 'PERCENTAGE', child: Text('Percentage')), + ], + onChanged: (val) => setState(() => _makingChargeType = val!), ), - items: const [ - DropdownMenuItem(value: 'PER_GRAM', child: Text('Per Gram')), - DropdownMenuItem(value: 'PER_PIECE', child: Text('Per Piece')), - DropdownMenuItem(value: 'PERCENTAGE', child: Text('Percentage')), - ], - onChanged: (val) => setState(() => _makingChargeType = val!), ), - ), - const SizedBox(width: 16), - Expanded( - child: _buildTextField( - controller: _makingChargeController, - label: 'Default Charge', - keyboardType: const TextInputType.numberWithOptions(decimal: true), + const SizedBox(width: 16), + Expanded( + child: _buildTextField( + controller: _makingChargeController, + label: 'Default Charge', + keyboardType: const TextInputType.numberWithOptions(decimal: true), + ), ), - ), - ], - ), - const SizedBox(height: 16), + ], + ), + const SizedBox(height: 16), + ], + DropdownButtonFormField( value: _baseUnit, - decoration: InputDecoration( + decoration: const InputDecoration( labelText: 'Base Unit', ), - items: const [ - DropdownMenuItem(value: 'g', child: Text('Grams (g)')), - DropdownMenuItem(value: 'kg', child: Text('Kilograms (kg)')), - DropdownMenuItem(value: 'pcs', child: Text('Pieces (pcs)')), + items: [ + if (isJewellery) ...const [ + DropdownMenuItem(value: 'g', child: Text('Grams (g)')), + DropdownMenuItem(value: 'kg', child: Text('Kilograms (kg)')), + DropdownMenuItem(value: 'pcs', child: Text('Pieces (pcs)')), + ] else ...const [ + DropdownMenuItem(value: 'pcs', child: Text('Pieces (pcs)')), + DropdownMenuItem(value: 'unit', child: Text('Units (unit)')), + DropdownMenuItem(value: 'box', child: Text('Boxes (box)')), + DropdownMenuItem(value: 'set', child: Text('Sets (set)')), + DropdownMenuItem(value: 'pair', child: Text('Pairs (pair)')), + DropdownMenuItem(value: 'g', child: Text('Grams (g)')), + DropdownMenuItem(value: 'kg', child: Text('Kilograms (kg)')), + DropdownMenuItem(value: 'm', child: Text('Meters (m)')), + DropdownMenuItem(value: 'l', child: Text('Liters (l)')), + ], ], onChanged: (val) => setState(() => _baseUnit = val!), ), diff --git a/kifi-app/web/favicon.png b/kifi-app/web/favicon.png index 8aaa46a..2a2f05a 100644 Binary files a/kifi-app/web/favicon.png and b/kifi-app/web/favicon.png differ diff --git a/kifi-app/web/icons/Icon-192.png b/kifi-app/web/icons/Icon-192.png index b749bfe..e446c0d 100644 Binary files a/kifi-app/web/icons/Icon-192.png and b/kifi-app/web/icons/Icon-192.png differ diff --git a/kifi-app/web/icons/Icon-512.png b/kifi-app/web/icons/Icon-512.png index 88cfd48..3cce864 100644 Binary files a/kifi-app/web/icons/Icon-512.png and b/kifi-app/web/icons/Icon-512.png differ diff --git a/kifi-app/web/icons/Icon-maskable-192.png b/kifi-app/web/icons/Icon-maskable-192.png index eb9b4d7..e446c0d 100644 Binary files a/kifi-app/web/icons/Icon-maskable-192.png and b/kifi-app/web/icons/Icon-maskable-192.png differ diff --git a/kifi-app/web/icons/Icon-maskable-512.png b/kifi-app/web/icons/Icon-maskable-512.png index d69c566..3cce864 100644 Binary files a/kifi-app/web/icons/Icon-maskable-512.png and b/kifi-app/web/icons/Icon-maskable-512.png differ diff --git a/kifi-app/web/index.html b/kifi-app/web/index.html index 5fe0b9c..477e9cd 100644 --- a/kifi-app/web/index.html +++ b/kifi-app/web/index.html @@ -5,7 +5,7 @@ - + @@ -16,7 +16,7 @@ - KIFI - Financial Ledger & Jewellery ERP + KIFI - Financial Ledger & Business ERP