add quotes

This commit is contained in:
Phuoc Nguyen
2025-10-27 15:30:31 +07:00
parent 7ce4239772
commit 3020c4e626
8 changed files with 1177 additions and 4 deletions

View File

@@ -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,

View File

@@ -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';

View File

@@ -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<QuoteModel>? _quotesBox;
/// Get Hive box for quotes
Future<Box<QuoteModel>> get quotesBox async {
_quotesBox ??= await Hive.openBox<QuoteModel>(HiveBoxNames.quotes);
return _quotesBox!;
}
/// Get all quotes
Future<List<QuoteModel>> getAllQuotes() async {
final box = await quotesBox;
return box.values.toList();
}
/// Get quote by ID
Future<QuoteModel?> 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<void> saveQuote(QuoteModel quote) async {
final box = await quotesBox;
await box.put(quote.quoteId, quote);
}
/// Save multiple quotes
Future<void> saveQuotes(List<QuoteModel> quotes) async {
final box = await quotesBox;
final Map<String, QuoteModel> quotesMap = {
for (var quote in quotes) quote.quoteId: quote,
};
await box.putAll(quotesMap);
}
/// Delete quote
Future<void> deleteQuote(String quoteId) async {
final box = await quotesBox;
await box.delete(quoteId);
}
/// Clear all quotes
Future<void> clearQuotes() async {
final box = await quotesBox;
await box.clear();
}
/// Get quotes by status
Future<List<QuoteModel>> getQuotesByStatus(QuoteStatus status) async {
final quotes = await getAllQuotes();
return quotes.where((quote) => quote.status == status).toList();
}
/// Search quotes
Future<List<QuoteModel>> 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<void> 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);
}
}

View File

@@ -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<QuotesPage> createState() => _QuotesPageState();
}
class _QuotesPageState extends ConsumerState<QuotesPage> {
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<QuoteStatus?>(
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,
),
],
),
),
);
}
}

View File

@@ -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<List<QuoteModel>> 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<void> 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<List<QuoteModel>> 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<Map<QuoteStatus, int>> quotesCountByStatus(Ref ref) async {
final quotesAsync = ref.watch(quotesProvider);
return quotesAsync.when(
data: (quotes) {
final counts = <QuoteStatus, int>{};
for (final status in QuoteStatus.values) {
counts[status] = quotes.where((quote) => quote.status == status).length;
}
return counts;
},
loading: () => {},
error: (error, stack) => {},
);
}

View File

@@ -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<QuotesLocalDataSource> {
/// 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<QuotesLocalDataSource> $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<QuotesLocalDataSource>(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, List<QuoteModel>> {
/// 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<List<QuoteModel>> {
FutureOr<List<QuoteModel>> build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref =
this.ref as $Ref<AsyncValue<List<QuoteModel>>, List<QuoteModel>>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<AsyncValue<List<QuoteModel>>, List<QuoteModel>>,
AsyncValue<List<QuoteModel>>,
Object?,
Object?
>;
element.handleValue(ref, created);
}
}
/// Quote Search Query Provider
@ProviderFor(QuoteSearchQuery)
const quoteSearchQueryProvider = QuoteSearchQueryProvider._();
/// Quote Search Query Provider
final class QuoteSearchQueryProvider
extends $NotifierProvider<QuoteSearchQuery, String> {
/// 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<String>(value),
);
}
}
String _$quoteSearchQueryHash() => r'cc889177beb9905a80b223cba14612bb0c419103';
/// Quote Search Query Provider
abstract class _$QuoteSearchQuery extends $Notifier<String> {
String build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<String, String>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<String, String>,
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<SelectedQuoteStatus, QuoteStatus?> {
/// 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<QuoteStatus?>(value),
);
}
}
String _$selectedQuoteStatusHash() =>
r'5c1ecf114bbb85a00174dad255c939288722658b';
/// Selected Quote Status Filter Provider
abstract class _$SelectedQuoteStatus extends $Notifier<QuoteStatus?> {
QuoteStatus? build();
@$mustCallSuper
@override
void runBuild() {
final created = build();
final ref = this.ref as $Ref<QuoteStatus?, QuoteStatus?>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<QuoteStatus?, QuoteStatus?>,
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<QuoteModel>>,
List<QuoteModel>,
FutureOr<List<QuoteModel>>
>
with $FutureModifier<List<QuoteModel>>, $FutureProvider<List<QuoteModel>> {
/// 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<List<QuoteModel>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<List<QuoteModel>> 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<QuoteStatus, int>>,
Map<QuoteStatus, int>,
FutureOr<Map<QuoteStatus, int>>
>
with
$FutureModifier<Map<QuoteStatus, int>>,
$FutureProvider<Map<QuoteStatus, int>> {
/// 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<Map<QuoteStatus, int>> $createElement(
$ProviderPointer pointer,
) => $FutureProviderElement(pointer);
@override
FutureOr<Map<QuoteStatus, int>> create(Ref ref) {
return quotesCountByStatus(ref);
}
}
String _$quotesCountByStatusHash() =>
r'474b62ad0ccf890df1c33c64a17f9a0f428f676e';