diff --git a/lib/core/constants/storage_constants.dart b/lib/core/constants/storage_constants.dart index d98d2d4..d1fcf03 100644 --- a/lib/core/constants/storage_constants.dart +++ b/lib/core/constants/storage_constants.dart @@ -27,6 +27,9 @@ class HiveBoxNames { /// Construction projects static const String projectBox = 'project_box'; + /// Quote requests and quotations + static const String quotes = 'quotes_box'; + /// Loyalty program transactions and points history static const String loyaltyBox = 'loyalty_box'; @@ -61,6 +64,7 @@ class HiveBoxNames { cartBox, orderBox, projectBox, + quotes, loyaltyBox, rewardsBox, settingsBox, diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart index 86c4430..1ab4d87 100644 --- a/lib/core/router/app_router.dart +++ b/lib/core/router/app_router.dart @@ -17,6 +17,7 @@ import 'package:worker/features/orders/presentation/pages/payments_page.dart'; import 'package:worker/features/products/presentation/pages/product_detail_page.dart'; import 'package:worker/features/products/presentation/pages/products_page.dart'; import 'package:worker/features/promotions/presentation/pages/promotion_detail_page.dart'; +import 'package:worker/features/quotes/presentation/pages/quotes_page.dart'; /// App Router /// @@ -156,6 +157,16 @@ class AppRouter { }, ), + // Quotes Route + GoRoute( + path: RouteNames.quotes, + name: RouteNames.quotes, + pageBuilder: (context, state) => MaterialPage( + key: state.pageKey, + child: const QuotesPage(), + ), + ), + // TODO: Add more routes as features are implemented ], diff --git a/lib/features/home/presentation/pages/home_page.dart b/lib/features/home/presentation/pages/home_page.dart index 924ebe5..bc7bcdc 100644 --- a/lib/features/home/presentation/pages/home_page.dart +++ b/lib/features/home/presentation/pages/home_page.dart @@ -182,8 +182,7 @@ class HomePage extends ConsumerWidget { QuickAction( icon: Icons.description, label: 'Yêu cầu báo giá', - onTap: () => - _showComingSoon(context, 'Yêu cầu báo giá', l10n), + onTap: () => context.push(RouteNames.quotes), ), QuickAction( icon: Icons.inventory_2, diff --git a/lib/features/orders/presentation/providers/invoices_provider.g.dart b/lib/features/orders/presentation/providers/invoices_provider.g.dart index 3c89ee6..1edc5a4 100644 --- a/lib/features/orders/presentation/providers/invoices_provider.g.dart +++ b/lib/features/orders/presentation/providers/invoices_provider.g.dart @@ -340,7 +340,7 @@ final class TotalInvoicesAmountProvider } String _$totalInvoicesAmountHash() => - r'7800e2be935dfe91d382957539b151bbf4f936fe'; + r'f311abe063d4f9c2e25a13acac6202b1cce72754'; /// Total Unpaid Amount Provider /// @@ -384,4 +384,4 @@ final class TotalUnpaidAmountProvider } } -String _$totalUnpaidAmountHash() => r'9a81800149d8809e1c3be065bc3c5357792c4aee'; +String _$totalUnpaidAmountHash() => r'8cde697cbede5d799208fe5eca0cc0822ca608a4'; diff --git a/lib/features/quotes/data/datasources/quotes_local_datasource.dart b/lib/features/quotes/data/datasources/quotes_local_datasource.dart new file mode 100644 index 0000000..1f6c98c --- /dev/null +++ b/lib/features/quotes/data/datasources/quotes_local_datasource.dart @@ -0,0 +1,170 @@ +/// Data Source: Quotes Local Data Source +/// +/// Handles local storage operations for quotes using Hive. +library; + +import 'package:hive_ce/hive.dart'; +import 'package:worker/core/constants/storage_constants.dart'; +import 'package:worker/core/database/models/enums.dart'; +import 'package:worker/features/quotes/data/models/quote_model.dart'; + +/// Quotes Local Data Source +/// +/// Provides methods to interact with locally stored quote data. +class QuotesLocalDataSource { + Box? _quotesBox; + + /// Get Hive box for quotes + Future> get quotesBox async { + _quotesBox ??= await Hive.openBox(HiveBoxNames.quotes); + return _quotesBox!; + } + + /// Get all quotes + Future> getAllQuotes() async { + final box = await quotesBox; + return box.values.toList(); + } + + /// Get quote by ID + Future getQuoteById(String quoteId) async { + final box = await quotesBox; + return box.values.firstWhere( + (quote) => quote.quoteId == quoteId, + orElse: () => throw Exception('Quote not found'), + ); + } + + /// Save quote + Future saveQuote(QuoteModel quote) async { + final box = await quotesBox; + await box.put(quote.quoteId, quote); + } + + /// Save multiple quotes + Future saveQuotes(List quotes) async { + final box = await quotesBox; + final Map quotesMap = { + for (var quote in quotes) quote.quoteId: quote, + }; + await box.putAll(quotesMap); + } + + /// Delete quote + Future deleteQuote(String quoteId) async { + final box = await quotesBox; + await box.delete(quoteId); + } + + /// Clear all quotes + Future clearQuotes() async { + final box = await quotesBox; + await box.clear(); + } + + /// Get quotes by status + Future> getQuotesByStatus(QuoteStatus status) async { + final quotes = await getAllQuotes(); + return quotes.where((quote) => quote.status == status).toList(); + } + + /// Search quotes + Future> searchQuotes(String query) async { + final quotes = await getAllQuotes(); + final lowerQuery = query.toLowerCase(); + + return quotes.where((quote) { + final matchesNumber = quote.quoteNumber.toLowerCase().contains(lowerQuery); + final matchesProject = + quote.projectName?.toLowerCase().contains(lowerQuery) ?? false; + return matchesNumber || matchesProject; + }).toList(); + } + + /// Seed mock data for development + Future seedMockQuotes() async { + final mockQuotes = [ + QuoteModel( + quoteId: 'quote_001', + quoteNumber: 'YC001234', + userId: 'user_001', + status: QuoteStatus.viewed, + totalAmount: 45000000, + discountAmount: 2250000, + finalAmount: 42750000, + projectName: 'Villa Thủ Đức - Giai đoạn 2', + notes: 'Khách hàng yêu cầu giảm giá 5%', + validUntil: DateTime.now().add(const Duration(days: 30)), + createdAt: DateTime(2023, 8, 5), + ), + QuoteModel( + quoteId: 'quote_002', + quoteNumber: 'YC001233', + userId: 'user_001', + status: QuoteStatus.accepted, + totalAmount: 125500000, + discountAmount: 0, + finalAmount: 125500000, + projectName: 'Chung cư Landmark Center', + notes: 'Tổng giá trị: 125.500.000 VND', + validUntil: DateTime.now().add(const Duration(days: 45)), + createdAt: DateTime(2023, 8, 3), + ), + QuoteModel( + quoteId: 'quote_003', + quoteNumber: 'YC001232', + userId: 'user_001', + status: QuoteStatus.converted, + totalAmount: 32500000, + discountAmount: 500000, + finalAmount: 32000000, + projectName: 'Nhà phố Bình Thạnh', + notes: 'Mã đơn hàng: #DH005432', + convertedOrderId: 'order_005432', + validUntil: DateTime.now().subtract(const Duration(days: 5)), + createdAt: DateTime(2023, 8, 1), + ), + QuoteModel( + quoteId: 'quote_004', + quoteNumber: 'YC001231', + userId: 'user_001', + status: QuoteStatus.sent, + totalAmount: 78000000, + discountAmount: 3000000, + finalAmount: 75000000, + projectName: 'Văn phòng Quận 7', + notes: 'Chờ khách hàng phản hồi', + validUntil: DateTime.now().add(const Duration(days: 20)), + createdAt: DateTime(2023, 7, 31), + ), + QuoteModel( + quoteId: 'quote_005', + quoteNumber: 'YC001230', + userId: 'user_001', + status: QuoteStatus.draft, + totalAmount: 185000000, + discountAmount: 5000000, + finalAmount: 180000000, + projectName: 'Resort Vũng Tàu', + notes: 'Yêu cầu báo giá cho khu vực pool và spa', + validUntil: DateTime.now().add(const Duration(days: 60)), + createdAt: DateTime(2023, 7, 29), + ), + QuoteModel( + quoteId: 'quote_006', + quoteNumber: 'YC001229', + userId: 'user_001', + status: QuoteStatus.cancelled, + totalAmount: 56000000, + discountAmount: 1000000, + finalAmount: 55000000, + projectName: 'Showroom Quận 1', + notes: 'Khách hàng hủy dự án', + validUntil: DateTime.now().subtract(const Duration(days: 10)), + createdAt: DateTime(2023, 7, 25), + ), + ]; + + await saveQuotes(mockQuotes); + } +} diff --git a/lib/features/quotes/presentation/pages/quotes_page.dart b/lib/features/quotes/presentation/pages/quotes_page.dart new file mode 100644 index 0000000..3055e0a --- /dev/null +++ b/lib/features/quotes/presentation/pages/quotes_page.dart @@ -0,0 +1,513 @@ +/// Page: Quotes Page +/// +/// Displays list of quote requests with search and filter functionality. +library; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; +import 'package:worker/core/constants/ui_constants.dart'; +import 'package:worker/core/database/models/enums.dart'; +import 'package:worker/core/theme/colors.dart'; +import 'package:worker/features/quotes/data/models/quote_model.dart'; +import 'package:worker/features/quotes/presentation/providers/quotes_provider.dart'; + +/// Quotes Page +/// +/// Features: +/// - Search bar for quote numbers and project names +/// - Filter section +/// - List of quote request cards with status indicators +/// - Pull-to-refresh +class QuotesPage extends ConsumerStatefulWidget { + const QuotesPage({super.key}); + + @override + ConsumerState createState() => _QuotesPageState(); +} + +class _QuotesPageState extends ConsumerState { + final TextEditingController _searchController = TextEditingController(); + + @override + void initState() { + super.initState(); + _searchController.addListener(_onSearchChanged); + } + + @override + void dispose() { + _searchController..removeListener(_onSearchChanged) + ..dispose(); + super.dispose(); + } + + void _onSearchChanged() { + ref.read(quoteSearchQueryProvider.notifier).updateQuery( + _searchController.text, + ); + } + + @override + Widget build(BuildContext context) { + final filteredQuotesAsync = ref.watch(filteredQuotesProvider); + + return Scaffold( + backgroundColor: const Color(0xFFF4F6F8), + appBar: AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.black), + onPressed: () => context.pop(), + ), + title: const Text( + 'Yêu cầu báo giá', + style: TextStyle(color: Colors.black), + ), + actions: [ + IconButton( + icon: const Icon(Icons.add, color: Colors.black), + onPressed: () { + // TODO: Navigate to quote create page + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Tạo yêu cầu báo giá mới')), + ); + }, + ), + ], + elevation: AppBarSpecs.elevation, + backgroundColor: AppColors.white, + foregroundColor: AppColors.grey900, + centerTitle: false, + ), + body: RefreshIndicator( + onRefresh: () async { + await ref.read(quotesProvider.notifier).refresh(); + }, + child: CustomScrollView( + slivers: [ + // Search Bar and Filter Button + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.all(16), + child: _buildSearchAndFilterRow(), + ), + ), + + // Quotes List + SliverPadding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 24), + sliver: filteredQuotesAsync.when( + data: (quotes) { + if (quotes.isEmpty) { + return _buildEmptyState(); + } + + return SliverList( + delegate: SliverChildBuilderDelegate( + (context, index) { + final quote = quotes[index]; + return _buildQuoteCard(quote); + }, + childCount: quotes.length, + ), + ); + }, + loading: () => _buildLoadingState(), + error: (error, stack) => _buildErrorState(error), + ), + ), + ], + ), + ), + ); + } + + /// Build search bar and filter button row + Widget _buildSearchAndFilterRow() { + return Row( + children: [ + // Search Bar + Expanded( + child: Container( + decoration: BoxDecoration( + color: AppColors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: TextField( + controller: _searchController, + decoration: InputDecoration( + hintText: 'Tìm theo mã yêu cầu hoặc tên dự án', + hintStyle: const TextStyle( + color: AppColors.grey500, + fontSize: 14, + ), + prefixIcon: const Icon( + Icons.search, + color: AppColors.grey500, + ), + suffixIcon: _searchController.text.isNotEmpty + ? IconButton( + icon: const Icon(Icons.clear, color: AppColors.grey500), + onPressed: () { + _searchController.clear(); + }, + ) + : null, + border: InputBorder.none, + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + ), + ), + ), + ), + + const SizedBox(width: 12), + + // Filter Button + Container( + decoration: BoxDecoration( + color: AppColors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: IconButton( + onPressed: () { + _showFilterDialog(); + }, + icon: Icon( + Icons.filter_list, + color: AppColors.primaryBlue, + ), + iconSize: 24, + padding: const EdgeInsets.all(12), + constraints: const BoxConstraints( + minWidth: 48, + minHeight: 48, + ), + ), + ), + ], + ); + } + + /// Build quote card + Widget _buildQuoteCard(QuoteModel quote) { + final dateFormatter = DateFormat('dd/MM/yyyy'); + + return Card( + margin: const EdgeInsets.only(bottom: 12), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + clipBehavior: Clip.antiAlias, + child: InkWell( + onTap: () { + // TODO: Navigate to quote detail + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Chi tiết báo giá ${quote.quoteNumber}')), + ); + }, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Quote ID and Date + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '#${quote.quoteNumber}', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + color: AppColors.grey900, + ), + ), + Text( + dateFormatter.format(quote.createdAt), + style: const TextStyle( + fontSize: 12, + color: AppColors.grey500, + ), + ), + ], + ), + + const SizedBox(height: 8), + + // Project Name + if (quote.projectName != null) + Text( + 'Dự án: ${quote.projectName}', + style: const TextStyle( + fontSize: 14, + color: AppColors.grey900, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + + const SizedBox(height: 4), + + // Additional Info (placeholder for now) + const Text( + '5 sản phẩm - Diện tích: 200m²', + style: TextStyle( + fontSize: 13, + color: AppColors.grey500, + ), + ), + + const SizedBox(height: 8), + + // Status Badge + _buildStatusBadge(quote.status), + + const SizedBox(height: 8), + + // Notes + if (quote.notes != null && quote.notes!.isNotEmpty) + Text( + quote.notes!, + style: const TextStyle( + fontSize: 13, + color: AppColors.grey500, + fontStyle: FontStyle.italic, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ), + ); + } + + /// Build status badge + Widget _buildStatusBadge(QuoteStatus status) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: _getStatusColor(status).withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: _getStatusColor(status).withValues(alpha: 0.3), + width: 1, + ), + ), + child: Text( + _getStatusText(status), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: _getStatusColor(status), + ), + ), + ); + } + + /// Get status color + Color _getStatusColor(QuoteStatus status) { + switch (status) { + case QuoteStatus.draft: + return AppColors.warning; + case QuoteStatus.sent: + return AppColors.info; + case QuoteStatus.viewed: + return const Color(0xFFF59E0B); // yellow/orange + case QuoteStatus.accepted: + return AppColors.primaryBlue; + case QuoteStatus.rejected: + return AppColors.danger; + case QuoteStatus.expired: + return AppColors.grey500; + case QuoteStatus.converted: + return AppColors.success; + case QuoteStatus.cancelled: + return AppColors.grey500; + } + } + + /// Get status text + String _getStatusText(QuoteStatus status) { + switch (status) { + case QuoteStatus.draft: + return 'Chờ duyệt'; + case QuoteStatus.sent: + return 'Đã gửi'; + case QuoteStatus.viewed: + return 'Đang đàm phán'; + case QuoteStatus.accepted: + return 'Đã chốt'; + case QuoteStatus.rejected: + return 'Từ chối'; + case QuoteStatus.expired: + return 'Hết hạn'; + case QuoteStatus.converted: + return 'Đã thành đơn hàng'; + case QuoteStatus.cancelled: + return 'Đã hủy'; + } + } + + /// Show filter dialog + void _showFilterDialog() { + showDialog( + context: context, + builder: (context) { + final selectedStatus = ref.read(selectedQuoteStatusProvider); + + return AlertDialog( + title: const Text('Lọc theo trạng thái'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildFilterOption( + context, + 'Tất cả', + null, + selectedStatus == null, + ), + ...QuoteStatus.values.map((status) { + return _buildFilterOption( + context, + _getStatusText(status), + status, + selectedStatus == status, + ); + }), + ], + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('Đóng'), + ), + ], + ); + }, + ); + } + + /// Build filter option + Widget _buildFilterOption( + BuildContext context, + String label, + QuoteStatus? status, + bool isSelected, + ) { + return RadioListTile( + title: Text(label), + value: status, + groupValue: ref.watch(selectedQuoteStatusProvider), + onChanged: (value) { + ref.read(selectedQuoteStatusProvider.notifier).selectStatus(value); + Navigator.of(context).pop(); + }, + activeColor: AppColors.primaryBlue, + ); + } + + /// Build empty state + Widget _buildEmptyState() { + return SliverFillRemaining( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.receipt_long_outlined, + size: 80, + color: AppColors.grey500.withValues(alpha: 0.5), + ), + const SizedBox(height: 16), + const Text( + 'Không có yêu cầu báo giá nào', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: AppColors.grey500, + ), + ), + const SizedBox(height: 8), + const Text( + 'Kéo xuống để làm mới', + style: TextStyle( + fontSize: 14, + color: AppColors.grey500, + ), + ), + ], + ), + ), + ); + } + + /// Build loading state + Widget _buildLoadingState() { + return const SliverFillRemaining( + child: Center( + child: CircularProgressIndicator(), + ), + ); + } + + /// Build error state + Widget _buildErrorState(Object error) { + return SliverFillRemaining( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.error_outline, + size: 80, + color: AppColors.danger.withValues(alpha: 0.7), + ), + const SizedBox(height: 16), + const Text( + 'Có lỗi xảy ra', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: AppColors.grey900, + ), + ), + const SizedBox(height: 8), + Text( + error.toString(), + style: const TextStyle( + fontSize: 14, + color: AppColors.grey500, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/quotes/presentation/providers/quotes_provider.dart b/lib/features/quotes/presentation/providers/quotes_provider.dart new file mode 100644 index 0000000..9e98222 --- /dev/null +++ b/lib/features/quotes/presentation/providers/quotes_provider.dart @@ -0,0 +1,138 @@ +/// Providers: Quotes +/// +/// Riverpod providers for managing quotes state. +library; + +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:worker/core/database/models/enums.dart'; +import 'package:worker/features/quotes/data/datasources/quotes_local_datasource.dart'; +import 'package:worker/features/quotes/data/models/quote_model.dart'; + +part 'quotes_provider.g.dart'; + +/// Quotes Local Data Source Provider +@riverpod +QuotesLocalDataSource quotesLocalDataSource(Ref ref) { + return QuotesLocalDataSource(); +} + +/// Quotes Provider +/// +/// Provides list of all quotes from local data source. +@riverpod +class Quotes extends _$Quotes { + @override + Future> build() async { + final datasource = ref.read(quotesLocalDataSourceProvider); + + // Seed mock data on first load + final quotes = await datasource.getAllQuotes(); + if (quotes.isEmpty) { + await datasource.seedMockQuotes(); + return await datasource.getAllQuotes(); + } + + return quotes; + } + + /// Refresh quotes + Future refresh() async { + state = const AsyncValue.loading(); + state = await AsyncValue.guard(() async { + return await ref.read(quotesLocalDataSourceProvider).getAllQuotes(); + }); + } +} + +/// Quote Search Query Provider +@riverpod +class QuoteSearchQuery extends _$QuoteSearchQuery { + @override + String build() { + return ''; + } + + void updateQuery(String query) { + state = query; + } + + void clearQuery() { + state = ''; + } +} + +/// Selected Quote Status Filter Provider +@riverpod +class SelectedQuoteStatus extends _$SelectedQuoteStatus { + @override + QuoteStatus? build() { + return null; // null means show all statuses + } + + void selectStatus(QuoteStatus? status) { + state = status; + } + + void clearFilter() { + state = null; + } +} + +/// Filtered Quotes Provider +/// +/// Filters quotes by search query and status. +@riverpod +Future> filteredQuotes(Ref ref) async { + final quotesAsync = ref.watch(quotesProvider); + final searchQuery = ref.watch(quoteSearchQueryProvider); + final selectedStatus = ref.watch(selectedQuoteStatusProvider); + + return quotesAsync.when( + data: (quotes) { + var filtered = quotes; + + // Filter by search query + if (searchQuery.isNotEmpty) { + final lowerQuery = searchQuery.toLowerCase(); + filtered = filtered.where((quote) { + final matchesNumber = quote.quoteNumber.toLowerCase().contains(lowerQuery); + final matchesProject = + quote.projectName?.toLowerCase().contains(lowerQuery) ?? false; + return matchesNumber || matchesProject; + }).toList(); + } + + // Filter by status + if (selectedStatus != null) { + filtered = filtered.where((quote) => quote.status == selectedStatus).toList(); + } + + // Sort by creation date (newest first) + filtered.sort((a, b) => b.createdAt.compareTo(a.createdAt)); + + return filtered; + }, + loading: () => [], + error: (error, stack) => [], + ); +} + +/// Quotes Count by Status Provider +@riverpod +Future> quotesCountByStatus(Ref ref) async { + final quotesAsync = ref.watch(quotesProvider); + + return quotesAsync.when( + data: (quotes) { + final counts = {}; + + for (final status in QuoteStatus.values) { + counts[status] = quotes.where((quote) => quote.status == status).length; + } + + return counts; + }, + loading: () => {}, + error: (error, stack) => {}, + ); +} diff --git a/lib/features/quotes/presentation/providers/quotes_provider.g.dart b/lib/features/quotes/presentation/providers/quotes_provider.g.dart new file mode 100644 index 0000000..8c060d2 --- /dev/null +++ b/lib/features/quotes/presentation/providers/quotes_provider.g.dart @@ -0,0 +1,338 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'quotes_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint, type=warning +/// Quotes Local Data Source Provider + +@ProviderFor(quotesLocalDataSource) +const quotesLocalDataSourceProvider = QuotesLocalDataSourceProvider._(); + +/// Quotes Local Data Source Provider + +final class QuotesLocalDataSourceProvider + extends + $FunctionalProvider< + QuotesLocalDataSource, + QuotesLocalDataSource, + QuotesLocalDataSource + > + with $Provider { + /// Quotes Local Data Source Provider + const QuotesLocalDataSourceProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'quotesLocalDataSourceProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$quotesLocalDataSourceHash(); + + @$internal + @override + $ProviderElement $createElement( + $ProviderPointer pointer, + ) => $ProviderElement(pointer); + + @override + QuotesLocalDataSource create(Ref ref) { + return quotesLocalDataSource(ref); + } + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(QuotesLocalDataSource value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$quotesLocalDataSourceHash() => + r'02a822db926d8d80460bcc27a08ea494dff6c441'; + +/// Quotes Provider +/// +/// Provides list of all quotes from local data source. + +@ProviderFor(Quotes) +const quotesProvider = QuotesProvider._(); + +/// Quotes Provider +/// +/// Provides list of all quotes from local data source. +final class QuotesProvider + extends $AsyncNotifierProvider> { + /// Quotes Provider + /// + /// Provides list of all quotes from local data source. + const QuotesProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'quotesProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$quotesHash(); + + @$internal + @override + Quotes create() => Quotes(); +} + +String _$quotesHash() => r'f5011c354218f10da95af16269c956416fca3303'; + +/// Quotes Provider +/// +/// Provides list of all quotes from local data source. + +abstract class _$Quotes extends $AsyncNotifier> { + FutureOr> build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = + this.ref as $Ref>, List>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier>, List>, + AsyncValue>, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} + +/// Quote Search Query Provider + +@ProviderFor(QuoteSearchQuery) +const quoteSearchQueryProvider = QuoteSearchQueryProvider._(); + +/// Quote Search Query Provider +final class QuoteSearchQueryProvider + extends $NotifierProvider { + /// Quote Search Query Provider + const QuoteSearchQueryProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'quoteSearchQueryProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$quoteSearchQueryHash(); + + @$internal + @override + QuoteSearchQuery create() => QuoteSearchQuery(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(String value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$quoteSearchQueryHash() => r'cc889177beb9905a80b223cba14612bb0c419103'; + +/// Quote Search Query Provider + +abstract class _$QuoteSearchQuery extends $Notifier { + String build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + String, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} + +/// Selected Quote Status Filter Provider + +@ProviderFor(SelectedQuoteStatus) +const selectedQuoteStatusProvider = SelectedQuoteStatusProvider._(); + +/// Selected Quote Status Filter Provider +final class SelectedQuoteStatusProvider + extends $NotifierProvider { + /// Selected Quote Status Filter Provider + const SelectedQuoteStatusProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'selectedQuoteStatusProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$selectedQuoteStatusHash(); + + @$internal + @override + SelectedQuoteStatus create() => SelectedQuoteStatus(); + + /// {@macro riverpod.override_with_value} + Override overrideWithValue(QuoteStatus? value) { + return $ProviderOverride( + origin: this, + providerOverride: $SyncValueProvider(value), + ); + } +} + +String _$selectedQuoteStatusHash() => + r'5c1ecf114bbb85a00174dad255c939288722658b'; + +/// Selected Quote Status Filter Provider + +abstract class _$SelectedQuoteStatus extends $Notifier { + QuoteStatus? build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier, + QuoteStatus?, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} + +/// Filtered Quotes Provider +/// +/// Filters quotes by search query and status. + +@ProviderFor(filteredQuotes) +const filteredQuotesProvider = FilteredQuotesProvider._(); + +/// Filtered Quotes Provider +/// +/// Filters quotes by search query and status. + +final class FilteredQuotesProvider + extends + $FunctionalProvider< + AsyncValue>, + List, + FutureOr> + > + with $FutureModifier>, $FutureProvider> { + /// Filtered Quotes Provider + /// + /// Filters quotes by search query and status. + const FilteredQuotesProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'filteredQuotesProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$filteredQuotesHash(); + + @$internal + @override + $FutureProviderElement> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + return filteredQuotes(ref); + } +} + +String _$filteredQuotesHash() => r'77076cfa483cb81cc56972bca6a3c1e97861165c'; + +/// Quotes Count by Status Provider + +@ProviderFor(quotesCountByStatus) +const quotesCountByStatusProvider = QuotesCountByStatusProvider._(); + +/// Quotes Count by Status Provider + +final class QuotesCountByStatusProvider + extends + $FunctionalProvider< + AsyncValue>, + Map, + FutureOr> + > + with + $FutureModifier>, + $FutureProvider> { + /// Quotes Count by Status Provider + const QuotesCountByStatusProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'quotesCountByStatusProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$quotesCountByStatusHash(); + + @$internal + @override + $FutureProviderElement> $createElement( + $ProviderPointer pointer, + ) => $FutureProviderElement(pointer); + + @override + FutureOr> create(Ref ref) { + return quotesCountByStatus(ref); + } +} + +String _$quotesCountByStatusHash() => + r'474b62ad0ccf890df1c33c64a17f9a0f428f676e';