background-activity #1

Open
Mr.Jebelli wants to merge 6 commits from background-activity into main
2 changed files with 285 additions and 144 deletions
Showing only changes of commit 60c91e8fbb - Show all commits

View File

@ -1,3 +1,5 @@
// lib/presentation/notification_preferences/bloc/notification_preferences_bloc.dart
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
@ -26,12 +28,12 @@ class NotificationPreferencesBloc
LoadCategories event, Emitter<NotificationPreferencesState> emit) { LoadCategories event, Emitter<NotificationPreferencesState> emit) {
final categories = [ final categories = [
CategoryEntity(id: "e33dd7f9-5b20-4273-8eea-59da6ca5f206", name: 'لوازم دیجیتال', icon: Assets.icons.digital), CategoryEntity(id: "e33dd7f9-5b20-4273-8eea-59da6ca5f206", name: 'لوازم دیجیتال', icon: Assets.icons.digital),
CategoryEntity(id: "b73a868a-a2d2-4d96-8fd4-615327ed9629", name: 'کافیشاپ', icon: Assets.icons.coffeeshop), CategoryEntity(id: "b73a868a-a2d2-4d96-8fd4-615327ed9629", name: 'کافی شاپ', icon: Assets.icons.coffeeshop), // Change Here
CategoryEntity(id: "b5881239-bfd5-4c27-967a-187316a7e0b7", name: 'رستوران', icon: Assets.icons.resturan), CategoryEntity(id: "b5881239-bfd5-4c27-967a-187316a7e0b7", name: 'رستوران', icon: Assets.icons.resturan),
CategoryEntity(id: "6803b940-3e19-48cd-9190-28d9f25421ff", name: 'فستفود', icon: Assets.icons.fastfood), CategoryEntity(id: "6803b940-3e19-48cd-9190-28d9f25421ff", name: 'فست فود', icon: Assets.icons.fastfood), // Change Here
CategoryEntity(id: "71e371f8-a47a-4a58-aee6-4ed0f26bf29b", name: 'پوشاک', icon: Assets.icons.pooshak), CategoryEntity(id: "71e371f8-a47a-4a58-aee6-4ed0f26bf29b", name: 'پوشاک', icon: Assets.icons.pooshak),
CategoryEntity(id: "42acff41-1165-4e62-89b9-58db7329ec3a", name: 'تریا', icon: Assets.icons.teria), CategoryEntity(id: "42acff41-1165-4e62-89b9-58db7329ec3a", name: 'تریا', icon: Assets.icons.teria),
CategoryEntity(id: "2f38918c-5566-4aec-a0a9-2c7c48b1e878", name: 'کیف‌وکفش', icon: Assets.icons.kafsh), CategoryEntity(id: "2f38918c-5566-4aec-a0a9-2c7c48b1e878", name: 'کیف و کفش', icon: Assets.icons.kafsh), // Change Here
CategoryEntity(id: "52c51010-3a63-4264-a350-e011c889f3dd", name: 'سینما', icon: Assets.icons.cinama), CategoryEntity(id: "52c51010-3a63-4264-a350-e011c889f3dd", name: 'سینما', icon: Assets.icons.cinama),
CategoryEntity(id: "34185954-f79f-4b9e-8eb2-1702679c40a0", name: 'لوازم آرایشی', icon: Assets.icons.arayesh), CategoryEntity(id: "34185954-f79f-4b9e-8eb2-1702679c40a0", name: 'لوازم آرایشی', icon: Assets.icons.arayesh),
CategoryEntity(id: "e4517b0c-aacf-4758-94bd-85f45062980f", name: 'طلا و زیورآلات', icon: Assets.icons.tala), CategoryEntity(id: "e4517b0c-aacf-4758-94bd-85f45062980f", name: 'طلا و زیورآلات', icon: Assets.icons.tala),
@ -127,5 +129,3 @@ class NotificationPreferencesBloc
emit(state.copyWith(submissionSuccess: false)); emit(state.copyWith(submissionSuccess: false));
} }
} }

View File

@ -10,6 +10,7 @@ import 'package:proxibuy/presentation/comment/bloc/comment_bloc.dart';
import 'package:proxibuy/presentation/comment/bloc/comment_event.dart'; import 'package:proxibuy/presentation/comment/bloc/comment_event.dart';
import 'package:proxibuy/presentation/comment/bloc/comment_state.dart'; import 'package:proxibuy/presentation/comment/bloc/comment_state.dart';
import 'package:proxibuy/presentation/pages/offers_page.dart'; import 'package:proxibuy/presentation/pages/offers_page.dart';
import 'package:flutter_animate/flutter_animate.dart';
class CommentPage extends StatefulWidget { class CommentPage extends StatefulWidget {
final String discountId; final String discountId;
@ -39,7 +40,10 @@ class _CommentPageState extends State<CommentPage> {
); );
return; return;
} }
final pickedFile = await _picker.pickImage(source: source, imageQuality: 80); final pickedFile = await _picker.pickImage(
source: source,
imageQuality: 80,
);
if (pickedFile != null) { if (pickedFile != null) {
setState(() { setState(() {
_images.add(File(pickedFile.path)); _images.add(File(pickedFile.path));
@ -47,6 +51,12 @@ class _CommentPageState extends State<CommentPage> {
} }
} }
void _removeImage(int index) {
setState(() {
_images.removeAt(index);
});
}
void _showImageSourceActionSheet() { void _showImageSourceActionSheet() {
showModalBottomSheet( showModalBottomSheet(
context: context, context: context,
@ -58,7 +68,10 @@ class _CommentPageState extends State<CommentPage> {
child: Wrap( child: Wrap(
children: <Widget>[ children: <Widget>[
ListTile( ListTile(
leading: const Icon(Icons.photo_library, color: AppColors.primary), leading: const Icon(
Icons.photo_library,
color: AppColors.primary,
),
title: const Text('انتخاب از گالری'), title: const Text('انتخاب از گالری'),
onTap: () { onTap: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -85,64 +98,137 @@ class _CommentPageState extends State<CommentPage> {
return BlocProvider( return BlocProvider(
create: (context) => CommentBloc(), create: (context) => CommentBloc(),
child: Scaffold( child: Scaffold(
body: Stack( backgroundColor: Colors.grey[50],
children: [ appBar: _buildCustomAppBar(),
Positioned.fill( body: SingleChildScrollView(
child: Image.asset(Assets.images.userinfo.path, fit: BoxFit.cover),
),
DraggableScrollableSheet(
initialChildSize: 0.65,
minChildSize: 0.65,
maxChildSize: 0.65,
builder: (context, scrollController) {
return Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(32)),
),
child: SingleChildScrollView(
controller: scrollController,
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Center( _buildHeader(),
child: Container(
width: 50,
height: 5,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
borderRadius: BorderRadius.circular(12),
),
),
),
const SizedBox(height: 24), const SizedBox(height: 24),
Center(child: _buildRatingCard()),
const SizedBox(height: 16),
_buildCommentCard(),
const SizedBox(height: 16),
_buildImagePickerSection(),
const SizedBox(height: 32),
_buildActionButtons(),
]
.animate(interval: 100.ms)
.fadeIn(duration: 400.ms)
.slideY(begin: 0.2, curve: Curves.easeOut),
),
),
),
);
}
PreferredSizeWidget _buildCustomAppBar() {
return PreferredSize(
preferredSize: const Size.fromHeight(70.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: const BorderRadius.vertical(
bottom: Radius.circular(15),
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Text(
'ثبت نظر',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.normal,
fontSize: 18,
),
),
IconButton(
icon: SvgPicture.asset(Assets.icons.arrowLeft.path),
onPressed: () => Navigator.of(context).pop(),
),
],
),
),
),
),
);
}
Widget _buildHeader() {
return Center(
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColors.confirm.withOpacity(0.1),
),
child: Icon(
Icons.check_circle_outline,
color: AppColors.confirm,
size: 50,
),
),
const SizedBox(height: 16),
const Text( const Text(
'خریدت با موفقیت انجام شد. منتظر دیدار دوباره‌ات هستیم. لطفا نظرت رو در مورد این تخفیف بهمون بگو.', 'خریدت با موفقیت انجام شد. منتظر دیدار دوباره‌ات هستیم. لطفا نظرت رو در مورد این تخفیف بهمون بگو.',
style: TextStyle( style: TextStyle(fontSize: 16, color: Colors.black, height: 1.5),
fontSize: 16,
fontWeight: FontWeight.normal,
height: 1.5,
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 24), ],
Center( ),
child: RatingBar.builder( );
}
Widget _buildRatingCard() {
return Card(
elevation: 1,
shadowColor: Colors.black12,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Text(
"امتیاز شما چقدره؟",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
RatingBar.builder(
initialRating: 0, initialRating: 0,
minRating: 1, minRating: 1,
direction: Axis.horizontal, direction: Axis.horizontal,
itemCount: 5, itemCount: 5,
itemPadding: const EdgeInsets.symmetric(horizontal: 15.0), itemPadding: const EdgeInsets.symmetric(horizontal: 7.0),
itemBuilder: (context, _) => Icon( itemBuilder:
Icons.star, (context, _) =>
color: Colors.amber.shade700, Icon(Icons.star, color: Colors.amber.shade700),
),
onRatingUpdate: (rating) => setState(() => _rating = rating), onRatingUpdate: (rating) => setState(() => _rating = rating),
), ),
],
), ),
const SizedBox(height: 24), ),
TextField( );
}
Widget _buildCommentCard() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _commentController, controller: _commentController,
maxLines: 4, maxLines: 4,
textAlign: TextAlign.right, textAlign: TextAlign.right,
@ -150,29 +236,37 @@ class _CommentPageState extends State<CommentPage> {
labelText: "گوشمون به شماست", labelText: "گوشمون به شماست",
hintText: "نظراتت رو بگو...", hintText: "نظراتت رو بگو...",
alignLabelWithHint: true, alignLabelWithHint: true,
suffixIcon: Padding( suffixIcon: Padding(padding: const EdgeInsets.all(12.0)),
padding: const EdgeInsets.all(12.0),
child: IconButton(
icon: SvgPicture.asset(
Assets.icons.galleryAdd.path,
color: _images.length >= 2 ? Colors.grey : AppColors.primary,
),
onPressed: _images.length >= 2 ? null : _showImageSourceActionSheet,
), ),
), ),
);
}
Widget _buildImagePickerSection() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"افزودن عکس (اختیاری)",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 8),
const Text(
"می‌تونی عکس تجربه خریدت رو باهامون به اشتراک بذاری!",
style: TextStyle(fontSize: 14, color: AppColors.hint),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
if (_images.isNotEmpty) SingleChildScrollView(
SizedBox(
height: 80,
child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: _images.length, child: Row(
itemBuilder: (context, index) { children: [
...List.generate(_images.length, (index) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: ClipRRect( child: Stack(
clipBehavior: Clip.none,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
child: Image.file( child: Image.file(
_images[index], _images[index],
@ -181,21 +275,55 @@ class _CommentPageState extends State<CommentPage> {
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),
); Positioned(
}, top: -8,
right: -8,
child: GestureDetector(
onTap: () => _removeImage(index),
child: Container(
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
),
child: const Icon(
Icons.close,
color: Colors.white,
size: 16,
),
),
), ),
), ),
const SizedBox(height: 24),
_buildActionButtons(),
], ],
), ),
),
); );
}, }),
if (_images.length < 2)
GestureDetector(
onTap: _showImageSourceActionSheet,
child: Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: Colors.grey.shade200,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.grey.shade400,
width: 1.5,
style: BorderStyle.solid,
),
),
child: const Icon(
Icons.add_a_photo_outlined,
color: Colors.grey,
size: 30,
),
),
), ),
], ],
), ),
), ),
],
); );
} }
@ -207,6 +335,7 @@ class _CommentPageState extends State<CommentPage> {
const SnackBar( const SnackBar(
content: Text('نظر شما با موفقیت ثبت شد. ممنونیم!'), content: Text('نظر شما با موفقیت ثبت شد. ممنونیم!'),
backgroundColor: Colors.green, backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
), ),
); );
Navigator.of(context).pushAndRemoveUntil( Navigator.of(context).pushAndRemoveUntil(
@ -215,7 +344,11 @@ class _CommentPageState extends State<CommentPage> {
); );
} else if (state is CommentSubmissionFailure) { } else if (state is CommentSubmissionFailure) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(state.error), backgroundColor: Colors.red), SnackBar(
content: Text(state.error),
backgroundColor: Colors.red,
behavior: SnackBarBehavior.floating,
),
); );
} }
}, },
@ -226,7 +359,8 @@ class _CommentPageState extends State<CommentPage> {
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: ElevatedButton(
onPressed: isLoading onPressed:
isLoading
? null ? null
: () { : () {
context.read<CommentBloc>().add( context.read<CommentBloc>().add(
@ -242,9 +376,12 @@ class _CommentPageState extends State<CommentPage> {
backgroundColor: AppColors.confirm, backgroundColor: AppColors.confirm,
foregroundColor: Colors.white, foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16), padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)), shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
), ),
child: isLoading ),
child:
isLoading
? const SizedBox( ? const SizedBox(
width: 24, width: 24,
height: 24, height: 24,
@ -255,7 +392,8 @@ class _CommentPageState extends State<CommentPage> {
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
TextButton( TextButton(
onPressed: isLoading onPressed:
isLoading
? null ? null
: () { : () {
Navigator.of(context).pushAndRemoveUntil( Navigator.of(context).pushAndRemoveUntil(
@ -263,7 +401,10 @@ class _CommentPageState extends State<CommentPage> {
(route) => false, (route) => false,
); );
}, },
child: const Text('رد شدن', style: TextStyle(color: Colors.black)), child: const Text(
'رد شدن',
style: TextStyle(color: Colors.black),
),
), ),
], ],
); );