proxibuy/lib/presentation/pages/notification_preferences_pa...

256 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:proxibuy/core/config/app_colors.dart';
import 'package:proxibuy/core/gen/assets.gen.dart';
import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_bloc.dart';
import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_event.dart';
import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_state.dart';
import 'package:proxibuy/presentation/pages/offers_page.dart';
import 'package:proxibuy/presentation/pages/reserved_list_page.dart';
import 'package:proxibuy/presentation/reservation/cubit/reservation_cubit.dart';
import 'package:proxibuy/presentation/widgets/category_selection_card.dart';
import 'package:shared_preferences/shared_preferences.dart';
class NotificationPreferencesPage extends StatelessWidget {
const NotificationPreferencesPage({super.key});
static Route<void> route() {
return MaterialPageRoute<void>(
builder: (_) => BlocProvider(
create: (context) => NotificationPreferencesBloc(),
child: const NotificationPreferencesPage(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
title: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.0),
child: Assets.icons.logoWithName.svg(height: 40, width: 200),
),
actions: [
IconButton(onPressed: () {}, icon: Assets.icons.notification.svg()),
BlocBuilder<ReservationCubit, ReservationState>(
builder: (context, state) {
final reservedCount = state.reservedProductIds.length;
return Stack(
alignment: Alignment.center,
children: [
IconButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const ReservedListPage(),
),
);
},
icon: Assets.icons.scanBarcode.svg(),
),
if (reservedCount > 0)
Positioned(
top: 0,
right: 2,
child: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const ReservedListPage(),
),
);
},
child: Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 1.5),
),
constraints: const BoxConstraints(
minWidth: 18,
minHeight: 18,
),
child: Padding(
padding: const EdgeInsets.fromLTRB(2, 4, 2, 2),
child: Text(
'$reservedCount',
style: const TextStyle(
color: Colors.white,
fontSize: 11,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
),
),
),
],
);
},
),
const SizedBox(width: 8),
],
),
body: BlocListener<NotificationPreferencesBloc, NotificationPreferencesState>(
listener: (context, state) {
if (state.submissionSuccess) {
if (Navigator.canPop(context)) {
Navigator.of(context).pop(true);
} else {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const OffersPage(showDialogsOnLoad: true),
),
);
}
}
if (state.errorMessage != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage!),
backgroundColor: Colors.red,
),
);
}
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'دریافت اعلان',
style: TextStyle(
fontFamily: 'Dana',
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
const Divider(),
RichText(
text: TextSpan(
style: TextStyle(
fontFamily: 'Dana',
fontSize: 14,
color: AppColors.hint,
height: 1.5,
),
children: const <TextSpan>[
TextSpan(
text:
'ترجیح می‌دی از کدام دسته‌بندی‌ها اعلان تخفیف دریافت کنی؟ ',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
TextSpan(text: '(حداقل یک مورد رو انتخاب کن).'),
],
),
),
const SizedBox(height: 24),
Expanded(
child: BlocBuilder<NotificationPreferencesBloc, NotificationPreferencesState>(
builder: (context, state) {
if (state.categories.isEmpty && state.isLoading) {
return const Center(child: CircularProgressIndicator());
}
final double horizontalPadding = 24.0;
final double crossAxisSpacing = 16.0;
final int crossAxisCount = 3;
final screenWidth = MediaQuery.of(context).size.width;
final itemWidth = (screenWidth - (horizontalPadding * 2) - (crossAxisSpacing * (crossAxisCount - 1))) / crossAxisCount;
final itemHeight = itemWidth / 0.9;
return SingleChildScrollView(
child: Wrap(
spacing: crossAxisSpacing,
runSpacing: 24.0,
alignment: WrapAlignment.center,
children: state.categories.map((category) {
final isSelected =
state.selectedCategoryIds.contains(category.id);
return SizedBox(
width: itemWidth,
height: itemHeight,
child: CategorySelectionCard(
name: category.name,
icon: category.icon,
isSelected: isSelected,
showSelectableIndicator: state.selectedCategoryIds.isNotEmpty,
onTap: () {
context
.read<NotificationPreferencesBloc>()
.add(ToggleCategorySelection(category.id));
},
),
);
}).toList(),
),
);
},
),
),
BlocBuilder<NotificationPreferencesBloc, NotificationPreferencesState>(
builder: (context, state) {
final areCategoriesSelected = state.selectedCategoryIds.isNotEmpty;
if (areCategoriesSelected) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: !state.isLoading
? () async {
final bloc = context.read<NotificationPreferencesBloc>();
final selectedCategoryNames = bloc.state.categories
.where((cat) => bloc.state.selectedCategoryIds.contains(cat.id))
.map((cat) => cat.name)
.toList();
final prefs = await SharedPreferences.getInstance();
await prefs.setStringList('user_selected_categories', selectedCategoryNames);
bloc.add(SubmitPreferences());
}
: null,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.confirm,
foregroundColor: Colors.white,
disabledBackgroundColor: Colors.grey,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
child: state.isLoading
? const CircularProgressIndicator(color: Colors.white)
: const Text(
'اعمال',
style: TextStyle(
fontFamily: 'Dana',
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
);
} else {
return const SizedBox.shrink();
}
},
),
const SizedBox(height: 20),
],
),
),
),
);
}
}