proxibuy_bussiness/lib/presentation/pages/discount_manegment_page.dart

273 lines
9.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// lib/presentation/pages/discount_manegment_page.dart
import 'dart:async';
import 'package:business_panel/core/config/app_colors.dart';
import 'package:business_panel/domain/entities/discount_entity.dart';
import 'package:business_panel/presentation/discount_management/bloc/discount_management_bloc.dart';
import 'package:business_panel/presentation/widgets/analytics_discount_card.dart';
import 'package:business_panel/presentation/widgets/custom_app_bar_single.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:business_panel/gen/assets.gen.dart';
class DiscountManegmentPage extends StatelessWidget {
const DiscountManegmentPage({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => DiscountManagementBloc(),
child: const _DiscountManegmentView(),
);
}
}
class _DiscountManegmentView extends StatefulWidget {
const _DiscountManegmentView();
@override
State<_DiscountManegmentView> createState() => _DiscountManegmentPageState();
}
class _DiscountManegmentPageState extends State<_DiscountManegmentView> {
final TextEditingController _searchController = TextEditingController();
Timer? _debounce;
int _selectedStatus = 1; // 1 for active, 0 for inactive
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
context
.read<DiscountManagementBloc>()
.add(FetchManagedDiscounts(status: _selectedStatus));
}
});
}
@override
void dispose() {
_searchController.dispose();
_debounce?.cancel();
super.dispose();
}
void _onSearchChanged(String query) {
if (_debounce?.isActive ?? false) _debounce!.cancel();
_debounce = Timer(const Duration(milliseconds: 500), () {
if (mounted) {
context.read<DiscountManagementBloc>().add(
SearchManagedDiscounts(query: query, status: _selectedStatus));
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBarSingle(
page: "تخفیف ها",
),
body: BlocListener<DiscountManagementBloc, DiscountManagementState>(
listener: (context, state) {
if (state is DiscountDeleteSuccess) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text(state.message),
backgroundColor: Colors.green),
);
context
.read<DiscountManagementBloc>()
.add(FetchManagedDiscounts(status: _selectedStatus));
} else if (state is DiscountDeleteFailure) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(
SnackBar(
content: Text(state.error), backgroundColor: Colors.red),
);
}
},
child: Column(
children: [
_buildSearchBar(),
_buildStatusFilters(),
_buildDiscountList(),
],
),
),
);
}
Widget _buildSearchBar() {
return Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _searchController,
decoration: InputDecoration(
hintText: 'دنبال چی می‌گردی؟',
hintStyle:
const TextStyle(color: Color.fromARGB(255, 157, 157, 157)),
prefixIcon: Padding(
padding: const EdgeInsets.all(12.0),
child: SvgPicture.asset(Assets.icons.riSearch2Line),
),
fillColor: const Color.fromARGB(255, 244, 244, 244),
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: BorderSide.none,
),
contentPadding: const EdgeInsets.symmetric(vertical: 0),
),
onChanged: _onSearchChanged,
),
);
}
Widget _buildStatusFilters() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: Row(
children: [
_buildStatusSelector(context, text: "تخفیف‌های فعال", status: 1),
const SizedBox(width: 16),
_buildStatusSelector(context,
text: "تخفیف‌های غیر فعال", status: 0),
],
),
);
}
Widget _buildStatusSelector(BuildContext context,
{required String text, required int status}) {
final bool isSelected = _selectedStatus == status;
return Expanded(
child: InkWell(
onTap: () {
setState(() => _selectedStatus = status);
context
.read<DiscountManagementBloc>()
.add(FetchManagedDiscounts(status: _selectedStatus));
_searchController.clear();
},
borderRadius: BorderRadius.circular(50),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 22,
height: 22,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected ? Colors.white : Colors.transparent,
border: Border.all(
color:
isSelected ? AppColors.active : Colors.grey.shade400,
width: 2,
),
),
child: isSelected
? Center(
child: Container(
width: 12,
height: 12,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColors.active,
),
),
)
: null,
),
const SizedBox(width: 10),
Text(
text,
style: const TextStyle(
color: AppColors.hint,
fontWeight: FontWeight.bold,
fontSize: 15),
),
],
),
),
),
);
}
Widget _buildDiscountList() {
return Expanded(
child: BlocBuilder<DiscountManagementBloc, DiscountManagementState>(
builder: (context, state) {
if (state is DiscountManagementLoading) {
return const Center(child: CircularProgressIndicator());
}
if (state is DiscountManagementError) {
return Center(child: Text('خطا: ${state.message}'));
}
if (state is DiscountManagementLoaded) {
if (state.discounts.isEmpty) {
return const Center(
child: Text("هیچ تخفیفی با این مشخصات یافت نشد."));
}
// Group discounts
final Map<String, List<DiscountEntity>> groupedDiscounts = {};
for (var discount in state.discounts) {
if (groupedDiscounts.containsKey(discount.type)) {
groupedDiscounts[discount.type]!.add(discount);
} else {
groupedDiscounts[discount.type] = [discount];
}
}
final groupKeys = groupedDiscounts.keys.toList();
return RefreshIndicator(
onRefresh: () async {
context
.read<DiscountManagementBloc>()
.add(FetchManagedDiscounts(status: _selectedStatus));
_searchController.clear();
},
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: groupKeys.length,
itemBuilder: (context, index) {
final type = groupKeys[index];
final discountsOfType = groupedDiscounts[type]!;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(0, 24, 0, 8),
child: Text(
"تخفیف $type",
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
...discountsOfType.map((discount) {
return BlocProvider.value(
value: context.read<DiscountManagementBloc>(),
child: AnalyticsDiscountCard(discount: discount),
);
}).toList(),
],
);
},
),
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}