diff --git a/lib/assets/icons/Ravand.svg b/lib/assets/icons/Ravand.svg
new file mode 100644
index 0000000..360fdf7
--- /dev/null
+++ b/lib/assets/icons/Ravand.svg
@@ -0,0 +1,7 @@
+
diff --git a/lib/assets/icons/Risk.svg b/lib/assets/icons/Risk.svg
new file mode 100644
index 0000000..2c5a171
--- /dev/null
+++ b/lib/assets/icons/Risk.svg
@@ -0,0 +1,17 @@
+
diff --git a/lib/assets/icons/Startup.svg b/lib/assets/icons/Startup.svg
new file mode 100644
index 0000000..06c3951
--- /dev/null
+++ b/lib/assets/icons/Startup.svg
@@ -0,0 +1,6 @@
+
diff --git a/lib/assets/icons/Technology.svg b/lib/assets/icons/Technology.svg
new file mode 100644
index 0000000..e6c7ed6
--- /dev/null
+++ b/lib/assets/icons/Technology.svg
@@ -0,0 +1,11 @@
+
diff --git a/lib/assets/icons/document-filter.svg b/lib/assets/icons/document-filter.svg
new file mode 100644
index 0000000..88ed350
--- /dev/null
+++ b/lib/assets/icons/document-filter.svg
@@ -0,0 +1,6 @@
+
diff --git a/lib/constants/app_icons.dart b/lib/constants/app_icons.dart
index f535aef..caa2156 100644
--- a/lib/constants/app_icons.dart
+++ b/lib/constants/app_icons.dart
@@ -571,4 +571,6 @@ class DidvanIcons {
IconData(0xe90e, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData font_size_solid =
IconData(0xe90f, fontFamily: _kFontFam, fontPackage: _kFontPkg);
+ static const IconData document_filter =
+ IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}
diff --git a/lib/models/requests/news.dart b/lib/models/requests/news.dart
index 1e17e56..e51d673 100644
--- a/lib/models/requests/news.dart
+++ b/lib/models/requests/news.dart
@@ -3,11 +3,13 @@ class NewsRequestArgs {
final String? startDate;
final String? endDate;
final String? search;
+ final List? categories;
const NewsRequestArgs({
required this.page,
this.startDate,
this.endDate,
this.search,
+ this.categories,
});
}
diff --git a/lib/models/view/action_sheet_data.dart b/lib/models/view/action_sheet_data.dart
index 4f3c2d5..991f14f 100644
--- a/lib/models/view/action_sheet_data.dart
+++ b/lib/models/view/action_sheet_data.dart
@@ -9,6 +9,7 @@ class ActionSheetData {
final String? title;
final bool hasPadding;
final IconData? titleIcon;
+ final Widget? titleIconWidget;
final Color? titleColor;
final bool hasDismissButton;
final bool hasConfirmButton;
@@ -28,6 +29,7 @@ class ActionSheetData {
this.hasDismissButton = true,
this.hasConfirmButton = true,
this.titleIcon,
+ this.titleIconWidget,
this.dismissTitle,
this.onDismissed,
this.smallDismissButton = false,
diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart
index 68a9f99..a111787 100644
--- a/lib/routes/route_generator.dart
+++ b/lib/routes/route_generator.dart
@@ -1,4 +1,4 @@
-// ignore_for_file: avoid_print
+// ignore_for_file: avoid_print, deprecated_member_use
import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/models/requests/news.dart';
@@ -650,7 +650,6 @@ class RouteGenerator {
transitionDuration: const Duration(milliseconds: 400),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
switch (animationType) {
- // <<--- تغییر اصلی اینجاست
case 'slide':
const begin = Offset(1.0, 0.0);
const end = Offset.zero;
diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart
index 2b5cdbc..0c031fc 100644
--- a/lib/services/network/request_helper.dart
+++ b/lib/services/network/request_helper.dart
@@ -41,11 +41,15 @@ class RequestHelper {
required int page,
String? search,
List? types,
+ String? startDate,
+ String? endDate,
}) =>
'$_baseHomeUrl/mark/v2${_urlConcatGenerator([
MapEntry('page', page),
MapEntry('q', search),
MapEntry('type', _urlListConcatGenerator(types)),
+ MapEntry('start', startDate),
+ MapEntry('end', endDate),
])}';
static const String confirmUsername = '$_baseUserUrl/confirmUsername';
diff --git a/lib/utils/action_sheet.dart b/lib/utils/action_sheet.dart
index 580bc5e..90e50ea 100644
--- a/lib/utils/action_sheet.dart
+++ b/lib/utils/action_sheet.dart
@@ -129,13 +129,16 @@ class ActionSheetUtils {
if (data.title != null)
Row(
children: [
- if (data.titleIcon != null)
+ if (data.titleIconWidget != null)
+ data.titleIconWidget!
+ else if (data.titleIcon != null)
Icon(
data.titleIcon,
color: data.titleColor ??
Theme.of(context).colorScheme.title,
),
- if (data.titleIcon != null) const SizedBox(width: 8),
+ if (data.titleIcon != null || data.titleIconWidget != null)
+ const SizedBox(width: 8),
DidvanText(
data.title!,
style: Theme.of(context).textTheme.titleMedium,
@@ -151,29 +154,29 @@ class ActionSheetUtils {
Row(
children: [
if (data.hasDismissButton)
- Expanded(
- child: DidvanButton(
- onPressed: () {
- Navigator.of(context).pop();
- data.onDismissed?.call();
- },
- title: data.dismissTitle ?? 'بازگشت',
- style: ButtonStyleMode.secondary,
+ if (data.hasConfirmButton)
+ Expanded(
+ flex: 2,
+ child: DidvanButton(
+ style: ButtonStyleMode.primary,
+ onPressed: () {
+ data.onConfirmed?.call();
+ pop();
+ },
+ title: data.confrimTitle ?? 'تایید',
+ ),
),
- ),
if (data.hasDismissButton) const SizedBox(width: 20),
- if (data.hasConfirmButton)
- Expanded(
- flex: data.smallDismissButton ? 2 : 1,
- child: DidvanButton(
- style: ButtonStyleMode.primary,
- onPressed: () {
- data.onConfirmed?.call();
- pop();
- },
- title: data.confrimTitle ?? 'تایید',
- ),
+ Expanded(
+ child: DidvanButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ data.onDismissed?.call();
+ },
+ title: data.dismissTitle ?? 'بازگشت',
+ style: ButtonStyleMode.secondary,
),
+ ),
],
),
],
@@ -206,9 +209,7 @@ class ActionSheetUtils {
data.backgroundColor ?? Theme.of(context).colorScheme.surface,
),
width: mediaQueryData.size.width * 0.8,
- // BEGIN: EDIT THIS LINE
- padding: const EdgeInsets.fromLTRB(24, 16, 24, 24), // پدینگ بالا از 24 به 16 تغییر کرد
- // END: EDIT THIS LINE
+ padding: const EdgeInsets.fromLTRB(24, 16, 24, 24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
@@ -217,7 +218,12 @@ class ActionSheetUtils {
Row(
mainAxisSize: MainAxisSize.min,
children: [
- if (data.titleIcon != null)
+ if (data.titleIconWidget != null)
+ GestureDetector(
+ onTap: () => Navigator.of(context).pop(),
+ child: data.titleIconWidget!,
+ )
+ else if (data.titleIcon != null)
GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Icon(
@@ -226,7 +232,8 @@ class ActionSheetUtils {
color: data.titleColor,
),
),
- if (data.titleIcon != null)
+ if (data.titleIcon != null ||
+ data.titleIconWidget != null)
const SizedBox(
width: 4,
),
@@ -448,4 +455,4 @@ class ActionSheetUtils {
DesignConfig.updateSystemUiOverlayStyle();
Navigator.of(context).pop();
}
-}
\ No newline at end of file
+}
diff --git a/lib/views/ai/history_ai_chat_page.dart b/lib/views/ai/history_ai_chat_page.dart
index 2b0d172..85efcfd 100644
--- a/lib/views/ai/history_ai_chat_page.dart
+++ b/lib/views/ai/history_ai_chat_page.dart
@@ -33,8 +33,7 @@ class HistoryAiChatPage extends StatefulWidget {
class _HistoryAiChatPageState extends State {
final ScrollController scrollController = ScrollController();
- final GlobalKey scaffKey =
- GlobalKey();
+ final GlobalKey scaffKey = GlobalKey();
Timer? _timer;
late bool archived = widget.archived ?? false;
@@ -62,7 +61,6 @@ class _HistoryAiChatPageState extends State {
}
return true;
},
-
child: Scaffold(
key: scaffKey,
appBar: HoshanAppBar(
@@ -73,12 +71,12 @@ class _HistoryAiChatPageState extends State {
}
Navigator.pop(context);
},
- withActions: false, // شبیه به صفحه چت
- withInfo: true, // برای نمایش دکمه بازگشت
+ withActions: false,
+ withInfo: true,
),
drawer: HoshanDrawer(
scaffKey: scaffKey,
- ), // <-- اضافه شد
+ ),
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
controller: scrollController,
@@ -88,8 +86,7 @@ class _HistoryAiChatPageState extends State {
scrolledUnderElevation: 0,
automaticallyImplyLeading: false,
pinned: true,
- toolbarHeight:
- archived ? 50 : 110, // ارتفاع بر اساس آرشیو بودن تنظیم میشود
+ toolbarHeight: archived ? 50 : 110,
flexibleSpace: Container(
color: Theme.of(context).colorScheme.surface,
padding: const EdgeInsets.fromLTRB(20, 0, 20, 0),
@@ -190,10 +187,8 @@ class _HistoryAiChatPageState extends State {
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Icon(
archived
- ? Icons
- .folder_delete // <-- آیکون کشیدن برای آرشیو
- : Icons
- .create_new_folder_rounded, // <-- آیکون کشیدن برای خروج از آرشیو
+ ? Icons.folder_delete
+ : Icons.create_new_folder_rounded,
color: Theme.of(context).colorScheme.white),
),
movementDuration: const Duration(milliseconds: 600),
@@ -426,7 +421,6 @@ class _HistoryAiChatPageState extends State {
)
],
)
- // --- شروع بلاک تغییر یافته ---
: Row(
mainAxisAlignment:
MainAxisAlignment
@@ -453,8 +447,6 @@ class _HistoryAiChatPageState extends State {
.updatedAt
.toString())
.toPersianDateStr(),
- // DateTimeUtils.momentGenerator(
- // chat.updatedAt.toString()),
style:
const TextStyle(
fontSize:
@@ -518,8 +510,8 @@ class _HistoryAiChatPageState extends State {
archived);
break;
- case 'آرشیو': // برای آرشیو کردن
- case 'خارج کردن از آرشیو': // برای خارج کردن
+ case 'آرشیو':
+ case 'خارج کردن از آرشیو':
await state
.archivedChat(
chat.id!,
@@ -632,7 +624,6 @@ class _HistoryAiChatPageState extends State {
),
],
),
- // --- پایان بلاک تغییر یافته ---
// if (chat.prompts != null &&
// chat.prompts!.isNotEmpty &&
@@ -664,7 +655,6 @@ class _HistoryAiChatPageState extends State {
)
],
),
- // --- پایان تغییرات ---
),
);
}
diff --git a/lib/views/direct/widgets/message.dart b/lib/views/direct/widgets/message.dart
index ac0f0ab..ff329ea 100644
--- a/lib/views/direct/widgets/message.dart
+++ b/lib/views/direct/widgets/message.dart
@@ -12,7 +12,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
-class Message extends StatefulWidget { // 1. تبدیل به StatefulWidget
+class Message extends StatefulWidget {
final MessageData message;
const Message({Key? key, required this.message}) : super(key: key);
@@ -20,9 +20,7 @@ class Message extends StatefulWidget { // 1. تبدیل به StatefulWidget
State createState() => _MessageState();
}
-class _MessageState extends State
- with SingleTickerProviderStateMixin { // 2. اضافه کردن Mixin
-
+class _MessageState extends State with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation _slideAnimation;
late Animation _opacityAnimation;
@@ -30,14 +28,13 @@ class _MessageState extends State
@override
void initState() {
super.initState();
- // 3. مقداردهی اولیه کنترلر و انیمیشن ها
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_slideAnimation = Tween(
- begin: const Offset(0, 0.5), // شروع از کمی پایین تر
+ begin: const Offset(0, 0.5),
end: Offset.zero,
).animate(CurvedAnimation(
parent: _controller,
@@ -45,19 +42,19 @@ class _MessageState extends State
));
_opacityAnimation = Tween(
- begin: 0.0, // شروع با شفافیت صفر
+ begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeIn,
));
- _controller.forward(); // 4. اجرای انیمیشن
+ _controller.forward();
}
@override
void dispose() {
- _controller.dispose(); // 5. آزاد کردن کنترلر
+ _controller.dispose();
super.dispose();
}
@@ -68,15 +65,13 @@ class _MessageState extends State
.dailyMessages[
widget.message.createdAt.replaceAll('T', ' ').split(' ').first]!
.last;
-
- // 6. اعمال انیمیشن ها به ویجت
+
return FadeTransition(
opacity: _opacityAnimation,
child: SlideTransition(
position: _slideAnimation,
child: GestureDetector(
onLongPress: () {
- // 7. استفاده از widget.message
if (state.deletionQueue.contains(widget.message.id) ||
widget.message.writedByAdmin) {
return;
@@ -85,7 +80,8 @@ class _MessageState extends State
state.update();
},
onTap: () {
- if (state.deletionQueue.isEmpty || widget.message.writedByAdmin) return;
+ if (state.deletionQueue.isEmpty || widget.message.writedByAdmin)
+ return;
if (!state.deletionQueue.contains(widget.message.id)) {
state.deletionQueue.add(widget.message.id);
} else {
@@ -149,7 +145,8 @@ class _MessageState extends State
AudioWave(
file: widget.message.audio!,
totalDuration: widget.message.duration != null
- ? Duration(seconds: widget.message.duration!)
+ ? Duration(
+ seconds: widget.message.duration!)
: null,
),
if (widget.message.radar != null ||
@@ -258,7 +255,8 @@ class _MessageState extends State
),
),
DidvanText(
- DateTimeUtils.timeWithAmPm(widget.message.createdAt),
+ DateTimeUtils.timeWithAmPm(
+ widget.message.createdAt),
style: Theme.of(context).textTheme.labelSmall,
color: Theme.of(context).colorScheme.caption,
),
@@ -284,7 +282,6 @@ class _MessageState extends State
}
}
-// ویجت های کمکی پایین بدون تغییر باقی می مانند
class _ReplyRadarOverview extends StatelessWidget {
final MessageData message;
const _ReplyRadarOverview({Key? key, required this.message})
@@ -431,4 +428,4 @@ class _MessageContainer extends StatelessWidget {
child: child,
);
}
-}
\ No newline at end of file
+}
diff --git a/lib/views/home/bookmarks/bookmark_state.dart b/lib/views/home/bookmarks/bookmark_state.dart
index 62eee14..c82ed6c 100644
--- a/lib/views/home/bookmarks/bookmark_state.dart
+++ b/lib/views/home/bookmarks/bookmark_state.dart
@@ -1,22 +1,27 @@
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/overview_data.dart';
-import 'package:didvan/models/home_page_content/swot.dart';
+import 'package:didvan/models/home_page_content/swot.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
-import 'package:didvan/views/home/bookmarks/bookmark_service.dart';
+import 'package:didvan/views/home/bookmarks/bookmark_service.dart';
import 'package:didvan/services/swot_service.dart';
class BookmarksState extends CoreProvier {
- final List bookmarks = [];
+ final List bookmarks = [];
List bookmarkedSwotItems = [];
String search = '';
String lastSearch = '';
- int page = 1;
+ int page = 1;
int lastPage = 1;
+ List selectedTypes = [];
+ DateTime? startDate;
+ DateTime? endDate;
+ bool get isFiltered =>
+ selectedTypes.isNotEmpty || startDate != null || endDate != null;
- bool _swotItemsLoading = false;
+ bool _swotItemsLoading = false;
bool get searching => search.isNotEmpty;
bool get swotItemsLoading => _swotItemsLoading;
@@ -32,12 +37,13 @@ class BookmarksState extends CoreProvier {
_fetchSwotBookmarks(),
]);
-
if (appState != AppState.failed && !searching) {
appState = AppState.idle;
- } else if (appState != AppState.failed && searching && bookmarks.isEmpty && bookmarkedSwotItems.isEmpty) {
-
- appState = AppState.idle;
+ } else if (appState != AppState.failed &&
+ searching &&
+ bookmarks.isEmpty &&
+ bookmarkedSwotItems.isEmpty) {
+ appState = AppState.idle;
}
_swotItemsLoading = false;
notifyListeners();
@@ -49,7 +55,13 @@ class BookmarksState extends CoreProvier {
if (!searching) lastSearch = search;
final service = RequestService(
- RequestHelper.searchMarks(page: page, search: search.isNotEmpty ? search : null),
+ RequestHelper.searchMarks(
+ page: page,
+ search: search.isNotEmpty ? search : null,
+ types: selectedTypes.isNotEmpty ? selectedTypes : null,
+ startDate: startDate?.toIso8601String().split('T').first,
+ endDate: endDate?.toIso8601String().split('T').first,
+ ),
);
await service.httpGet();
if (service.isSuccess) {
@@ -59,21 +71,21 @@ class BookmarksState extends CoreProvier {
bookmarks.add(OverviewData.fromJson(marks[i]));
}
} else {
- appState = AppState.failed;
+ appState = AppState.failed;
}
}
-
+
Future searchAndLoadData({required int page}) async {
appState = AppState.busy;
- _swotItemsLoading = true;
- bookmarks.clear();
+ _swotItemsLoading = true;
+ bookmarks.clear();
notifyListeners();
await Future.wait([
- _fetchGeneralBookmarks(page: page),
+ _fetchGeneralBookmarks(page: page),
_fetchSwotBookmarks(),
]);
-
+
if (appState != AppState.failed) {
appState = AppState.idle;
}
@@ -81,9 +93,13 @@ class BookmarksState extends CoreProvier {
notifyListeners();
}
-
Future _fetchSwotBookmarks() async {
try {
+ if (selectedTypes.isNotEmpty && !selectedTypes.contains(8)) {
+ bookmarkedSwotItems = [];
+ return;
+ }
+
final postIds = await BookmarkService.fetchBookmarks();
if (postIds.isNotEmpty) {
final allSwots = await SwotService.fetchSwotItems();
@@ -91,23 +107,37 @@ class BookmarksState extends CoreProvier {
bookmarkedSwotItems = allSwots.where((swot) {
final isBookmarked = postIds.contains(swot.id);
if (search.isEmpty) return isBookmarked;
- return isBookmarked && swot.title.toLowerCase().contains(search.toLowerCase());
+ return isBookmarked &&
+ swot.title.toLowerCase().contains(search.toLowerCase());
}).toList();
} else {
bookmarkedSwotItems = [];
}
} catch (e) {
- bookmarkedSwotItems = [];
+ bookmarkedSwotItems = [];
}
}
- void onMarkChanged(int id, bool value) {
+ void onMarkChanged(int id, bool value) {
bookmarks.removeWhere((element) => element.id == id);
notifyListeners();
}
void onSwotMarkChanged(int swotId) {
- bookmarkedSwotItems.removeWhere((element) => element.id == swotId);
- notifyListeners();
+ bookmarkedSwotItems.removeWhere((element) => element.id == swotId);
+ notifyListeners();
}
-}
\ No newline at end of file
+
+ void resetFilters([bool notify = true]) {
+ selectedTypes.clear();
+ startDate = null;
+ endDate = null;
+ if (notify) {
+ loadInitialData();
+ }
+ }
+
+ void update() {
+ notifyListeners();
+ }
+}
diff --git a/lib/views/home/bookmarks/bookmarks.dart b/lib/views/home/bookmarks/bookmarks.dart
index c87bb7f..a719ca7 100644
--- a/lib/views/home/bookmarks/bookmarks.dart
+++ b/lib/views/home/bookmarks/bookmarks.dart
@@ -1,14 +1,20 @@
+// ignore_for_file: unused_element_parameter
+
import 'dart:async';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/routes/routes.dart';
+import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/home/bookmarks/bookmark_state.dart';
import 'package:didvan/views/home/main/widgets/swot_bookmark.dart';
+import 'package:didvan/views/widgets/didvan/checkbox.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
+import 'package:didvan/views/widgets/date_picker_button.dart';
import 'package:didvan/views/widgets/item_title.dart';
import 'package:didvan/views/widgets/menu_item.dart';
import 'package:didvan/views/widgets/overview/multitype.dart';
@@ -60,6 +66,108 @@ class _BookmarksState extends State {
});
}
+ Future _showFilterBottomSheet() async {
+ final state = context.read();
+
+ final categories = [
+ {'id': 1, 'label': 'پویش افق'},
+ {'id': 2, 'label': 'دنیای فولاد'},
+ {'id': 3, 'label': 'استودیو آینده'},
+ {'id': 5, 'label': 'رادارهای استراتژیک'},
+ {'id': 6, 'label': 'سها'},
+ {'id': 7, 'label': 'اینفوگرافی'},
+ ];
+
+ await ActionSheetUtils(context).showBottomSheet(
+ data: ActionSheetData(
+ title: 'فیلتر جستجو',
+ titleIconWidget: SvgPicture.asset(
+ 'lib/assets/icons/document-filter.svg',
+ width: 24,
+ height: 24,
+ ),
+ dismissTitle: 'حذف فیلتر',
+ confrimTitle: 'نمایش نتایج',
+ onDismissed: () => state.resetFilters(false),
+ onConfirmed: () => state.loadInitialData(),
+ content: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ItemTitle(
+ title: 'تاریخ',
+ style: Theme.of(context)
+ .textTheme
+ .bodyMedium
+ ?.copyWith(fontWeight: FontWeight.bold),
+ iconWidget: 'lib/assets/icons/calendar.svg',
+ color: const Color.fromARGB(255, 27, 60, 89),
+ ),
+ const SizedBox(height: 8),
+ StatefulBuilder(
+ builder: (context, setState) => Row(
+ children: [
+ DatePickerButton(
+ initialValue:
+ state.startDate?.toIso8601String().split('T').first,
+ emptyText: 'از تاریخ',
+ onPicked: (date) => setState(() {
+ state.startDate =
+ date != null ? DateTime.parse(date) : null;
+ }),
+ lastDate: state.endDate?.toIso8601String().split('T').first,
+ ),
+ const SizedBox(width: 8),
+ DatePickerButton(
+ initialValue:
+ state.endDate?.toIso8601String().split('T').first,
+ emptyText: 'تا تاریخ',
+ onPicked: (date) => setState(() {
+ state.endDate =
+ date != null ? DateTime.parse(date) : null;
+ }),
+ firstDate:
+ state.startDate?.toIso8601String().split('T').first,
+ ),
+ ],
+ ),
+ ),
+ const SizedBox(height: 28),
+ ItemTitle(
+ title: 'دسته بندی',
+ style: Theme.of(context)
+ .textTheme
+ .bodyMedium
+ ?.copyWith(fontWeight: FontWeight.bold),
+ iconWidget: 'lib/assets/icons/ion_extension-puzzle-outline.svg',
+ color: const Color.fromARGB(255, 27, 60, 89),
+ ),
+ const SizedBox(height: 12),
+ Wrap(
+ children: [
+ for (var category in categories)
+ SizedBox(
+ width: (MediaQuery.of(context).size.width - 40) / 2,
+ child: DidvanCheckbox(
+ title: category['label'] as String,
+ value: state.selectedTypes.contains(category['id']),
+ onChanged: (value) {
+ if (value) {
+ state.selectedTypes.add(category['id'] as int);
+ } else {
+ state.selectedTypes.remove(category['id']);
+ }
+ },
+ color: const Color.fromARGB(255, 61, 61, 61),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
@override
Widget build(BuildContext context) {
final state = context.watch();
@@ -110,7 +218,7 @@ class _BookmarksState extends State {
),
GestureDetector(
onTap: () => Navigator.pop(context),
- child: Container(
+ child: SizedBox(
width: 44,
height: 44,
child: Center(
@@ -135,12 +243,8 @@ class _BookmarksState extends State {
title: 'دیدوان',
focusNode: _focuseNode,
onChanged: _onSearchChanged,
- onFilterButtonPressed: () {
- //TODO:fix this
- // Filter functionality for bookmarks
- // Can be implemented later if needed
- },
- isFiltered: false,
+ onFilterButtonPressed: _showFilterBottomSheet,
+ isFiltered: state.isFiltered,
extraIconPath: 'lib/assets/icons/live ai.svg',
onExtraIconPressed: () {
showDialog(
@@ -205,107 +309,158 @@ class _BookmarksState extends State {
),
),
const SizedBox(height: 15),
- MenuOption(
- onTap: () => _onCategorySelected(5),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Stratzhic Radar.svg",
- width: 20,
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 100),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(5),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Stratzhic Radar.svg",
+ width: 20,
+ ),
+ titleWidget: const DidvanText('رادارهای استراتژیک',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('رادارهای استراتژیک',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(2),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Donye_Foolad.svg",
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 150),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 200),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(2),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Donye_Foolad.svg",
+ width: 20,
+ ),
+ titleWidget: const DidvanText('دنیای فولاد',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('دنیای فولاد',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(1),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Pouyesh_Ofogh_New.svg",
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 250),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 300),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(1),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Pouyesh_Ofogh_New.svg",
+ width: 20,
+ ),
+ titleWidget: const DidvanText('پویش افق',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('پویش افق',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(3),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/video-play.svg",
- color: const Color.fromARGB(255, 0, 126, 167),
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 350),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 400),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(3),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/video-play.svg",
+ color: const Color.fromARGB(255, 0, 126, 167),
+ width: 20,
+ ),
+ titleWidget: const DidvanText('ویدیوکست',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('ویدیوکست',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(4),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/microphone-2.svg",
- color: const Color.fromARGB(255, 0, 126, 167),
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 450),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 500),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(4),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/microphone-2.svg",
+ color: const Color.fromARGB(255, 0, 126, 167),
+ width: 20,
+ ),
+ titleWidget: const DidvanText('پادکست',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('پادکست',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(6),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Saha.svg",
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 550),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 600),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(6),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Saha.svg",
+ width: 20,
+ ),
+ titleWidget: const DidvanText('سها',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('سها',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(7),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/hugeicons_chart-02.svg",
- color: const Color.fromARGB(255, 0, 126, 167),
- width: 20,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 650),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 700),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(7),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/hugeicons_chart-02.svg",
+ color: const Color.fromARGB(255, 0, 126, 167),
+ width: 20,
+ ),
+ titleWidget: const DidvanText('اینفوگرافی',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
),
- titleWidget: const DidvanText('اینفوگرافی',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(8),
- titleWidget: const DidvanText(
- 'ماژول بایدها و نبایدها',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Swot_New.svg",
- width: 24),
- iconSize: 24,
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 750),
+ child: DidvanDivider(),
),
- const DidvanDivider(),
- MenuOption(
- onTap: () => _onCategorySelected(9),
- titleWidget: const DidvanText('ماهنامه تحلیلی',
- style: TextStyle(
- color: Color.fromARGB(255, 102, 102, 102))),
- iconWidget: SvgPicture.asset(
- "lib/assets/icons/Monthly.svg",
- width: 24),
- iconSize: 24,
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 800),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(8),
+ titleWidget: const DidvanText(
+ 'ماژول بایدها و نبایدها',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Swot_New.svg",
+ width: 24),
+ iconSize: 24,
+ ),
+ ),
+ const _FadeInSlide(
+ delay: Duration(milliseconds: 850),
+ child: DidvanDivider(),
+ ),
+ _FadeInSlide(
+ delay: const Duration(milliseconds: 900),
+ child: MenuOption(
+ onTap: () => _onCategorySelected(9),
+ titleWidget: const DidvanText('ماهنامه تحلیلی',
+ style: TextStyle(
+ color: Color.fromARGB(255, 102, 102, 102))),
+ iconWidget: SvgPicture.asset(
+ "lib/assets/icons/Monthly.svg",
+ width: 24),
+ iconSize: 24,
+ ),
),
const SizedBox(height: 7),
],
@@ -350,26 +505,29 @@ class _BookmarksState extends State {
if (index >= state.bookmarks.length) {
return const Center(child: CircularProgressIndicator());
}
- return Padding(
- padding: const EdgeInsets.fromLTRB(0, 5, 0, 5),
- child: Container(
- clipBehavior: Clip.antiAlias,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(16),
- border: Border.all(
- color: const Color.fromRGBO(184, 184, 184, 1),
- width: 1,
+ return _FadeInSlide(
+ delay: Duration(milliseconds: (index % 10) * 100),
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(0, 5, 0, 5),
+ child: Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(16),
+ border: Border.all(
+ color: const Color.fromRGBO(184, 184, 184, 1),
+ width: 1,
+ ),
),
- ),
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: MultitypeOverview(
- item: state.bookmarks[index],
- onMarkChanged: state.onMarkChanged,
- hasUnmarkConfirmation: true,
- enableCaption: true,
- enableBookmark: true,
- showDivider: false,
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: MultitypeOverview(
+ item: state.bookmarks[index],
+ onMarkChanged: state.onMarkChanged,
+ hasUnmarkConfirmation: true,
+ enableCaption: true,
+ enableBookmark: true,
+ showDivider: false,
+ ),
),
),
),
@@ -388,25 +546,28 @@ class _BookmarksState extends State {
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = state.bookmarkedSwotItems[index];
- return Padding(
- padding:
- const EdgeInsets.only(bottom: 8, left: 16, right: 16),
- child: Container(
- clipBehavior: Clip.antiAlias,
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(16),
- border: Border.all(
- color: const Color.fromRGBO(184, 184, 184, 1),
- width: 1,
+ return _FadeInSlide(
+ delay: Duration(milliseconds: (index % 10) * 100),
+ child: Padding(
+ padding:
+ const EdgeInsets.only(bottom: 8, left: 16, right: 16),
+ child: Container(
+ clipBehavior: Clip.antiAlias,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(16),
+ border: Border.all(
+ color: const Color.fromRGBO(184, 184, 184, 1),
+ width: 1,
+ ),
),
- ),
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SwotBookmark(
- item: item,
- onSwotUnbookmarked: (postId) {
- state.onSwotMarkChanged(postId);
- },
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SwotBookmark(
+ item: item,
+ onSwotUnbookmarked: (postId) {
+ state.onSwotMarkChanged(postId);
+ },
+ ),
),
),
),
@@ -447,14 +608,66 @@ class _BookmarksState extends State {
}
}
- // void _onChanged(String value) {
- // final state = context.read();
- // if (value.length < 3 && value.isNotEmpty || state.lastSearch == value) {
- // return;
- // }
- // _timer?.cancel();
- // _timer = Timer(const Duration(seconds: 1), () {
- // state.search = value;
- // state.getBookmarks(page: 1);
- // });
- // }
\ No newline at end of file
+// void _onChanged(String value) {
+// final state = context.read();
+// if (value.length < 3 && value.isNotEmpty || state.lastSearch == value) {
+// return;
+// }
+// _timer?.cancel();
+// _timer = Timer(const Duration(seconds: 1), () {
+// state.search = value;
+// state.getBookmarks(page: 1);
+// });
+// }
+// }
+
+class _FadeInSlide extends StatefulWidget {
+ final Widget child;
+ final Duration delay;
+ final Duration duration;
+ final double slideOffset;
+
+ const _FadeInSlide({
+ Key? key,
+ required this.child,
+ this.delay = Duration.zero,
+ // ignore: unused_element_parameter
+ this.duration = const Duration(milliseconds: 400),
+ this.slideOffset = 50.0, // میزانی که ویجت از پایین به بالا حرکت میکند
+ }) : super(key: key);
+
+ @override
+ State<_FadeInSlide> createState() => _FadeInSlideState();
+}
+
+class _FadeInSlideState extends State<_FadeInSlide> {
+ bool _isVisible = false;
+
+ @override
+ void initState() {
+ super.initState();
+ Timer(widget.delay, () {
+ if (mounted) {
+ setState(() {
+ _isVisible = true;
+ });
+ }
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AnimatedOpacity(
+ opacity: _isVisible ? 1.0 : 0.0,
+ duration: widget.duration,
+ curve: Curves.easeOut,
+ child: AnimatedContainer(
+ duration: widget.duration,
+ curve: Curves.easeOut,
+ transform: Matrix4.translationValues(
+ 0, _isVisible ? 0 : widget.slideOffset, 0),
+ child: widget.child,
+ ),
+ );
+ }
+}
diff --git a/lib/views/home/explore/explore.dart b/lib/views/home/explore/explore.dart
index ada2efc..9a17b4f 100644
--- a/lib/views/home/explore/explore.dart
+++ b/lib/views/home/explore/explore.dart
@@ -1,5 +1,3 @@
-import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/main.dart';
import 'package:didvan/models/home_page_content/home_page_list.dart';
import 'package:didvan/models/home_page_content/swot.dart';
@@ -276,12 +274,12 @@ class SwotSection extends StatelessWidget {
Row(
children: [
SvgPicture.asset(
- "lib/assets/images/features/Saha Solid.svg",
- color: Theme.of(context).colorScheme.title,
+ "lib/assets/icons/Swot_New.svg",
+ color: const Color.fromARGB(255, 0, 126, 167),
),
const SizedBox(width: 5),
DidvanText(
- "بایدها و نبایدها",
+ "ماژول بایدها و نبایدها",
style: Theme.of(context).textTheme.titleSmall,
color: const Color.fromARGB(255, 0, 89, 119),
),
@@ -357,28 +355,28 @@ class MainPageSection extends StatelessWidget {
Navigator.of(context).pushNamed(list.link);
}
- IconData? _generateIcon() {
+ String? _generateIcon() {
switch (list.type) {
case 'monthly':
- return DidvanIcons.radar_solid;
+ return 'lib/assets/icons/Monthly.svg';
case 'news':
- return DidvanIcons.foolad_solid;
+ return 'lib/assets/icons/Donye_Foolad.svg';
case 'radar':
- return DidvanIcons.scanning_solid;
+ return 'lib/assets/icons/Pouyesh_Ofogh_New.svg';
case 'video':
- return DidvanIcons.video_solid;
+ return 'lib/assets/icons/video-play.svg';
case 'podcast':
- return DidvanIcons.podcast_solid;
+ return 'lib/assets/icons/play-circle.svg';
case 'trend':
- return DidvanIcons.chart_solid;
+ return 'lib/assets/icons/Ravand.svg';
case 'technology':
- return DidvanIcons.technology_solid;
+ return 'lib/assets/icons/Technology.svg';
case 'risk':
- return DidvanIcons.exclamation_triangle_solid;
+ return 'lib/assets/icons/risk-radar.svg'; //TODO:FIX ICON
case 'startup':
- return DidvanIcons.startup_solid;
+ return 'lib/assets/icons/Startup.svg';
case 'survey':
- return DidvanIcons.saha_solid;
+ return 'lib/assets/icons/Saha.svg';
default:
return null;
}
@@ -445,7 +443,7 @@ class MainPageSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
- final icon = _generateIcon();
+ final iconPath = _generateIcon();
if (list.contents.isEmpty) {
return const SizedBox();
@@ -453,13 +451,13 @@ class MainPageSection extends StatelessWidget {
return Column(
children: [
- _buildSectionHeader(context, icon),
+ _buildSectionHeader(context, iconPath),
_buildSectionSlider(context),
],
);
}
- Padding _buildSectionHeader(BuildContext context, IconData? icon) {
+ Padding _buildSectionHeader(BuildContext context, String? iconPath) {
String headerText = list.header;
if (list.type == 'news') {
headerText = 'دنیای فولاد';
@@ -483,10 +481,12 @@ class MainPageSection extends StatelessWidget {
children: [
Row(
children: [
- if (icon != null)
- Icon(
- icon,
- color: Theme.of(context).colorScheme.title,
+ if (iconPath != null)
+ SvgPicture.asset(
+ iconPath,
+ width: 24,
+ height: 24,
+ color: const Color.fromRGBO(0, 126, 167, 1),
),
const SizedBox(width: 4),
DidvanText(
diff --git a/lib/views/monthly/monthly_list_page.dart b/lib/views/monthly/monthly_list_page.dart
index 7825aba..7a76a4f 100644
--- a/lib/views/monthly/monthly_list_page.dart
+++ b/lib/views/monthly/monthly_list_page.dart
@@ -1,12 +1,18 @@
import 'dart:async';
+import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
+import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/network/request_helper.dart';
+import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/monthly/monthly_list_state.dart';
+import 'package:didvan/views/widgets/date_picker_button.dart';
+import 'package:didvan/views/widgets/didvan/checkbox.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/home_app_bar.dart';
+import 'package:didvan/views/widgets/item_title.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
@@ -29,7 +35,9 @@ class _MonthlyListPageState extends State {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
- context.read().fetchMonthlyList();
+ final state = context.read();
+ state.initCategories();
+ state.fetchMonthlyList();
});
}
@@ -42,6 +50,88 @@ class _MonthlyListPageState extends State {
});
}
+ Future _showFilterBottomSheet() async {
+ final state = context.read();
+ await ActionSheetUtils(context).showBottomSheet(
+ data: ActionSheetData(
+ title: 'فیلتر جستجو',
+ smallDismissButton: true,
+ titleIcon: DidvanIcons.filter_regular,
+ dismissTitle: 'حذف فیلتر',
+ confrimTitle: 'نمایش نتایج',
+ onDismissed: () => state.resetFilters(false),
+ onConfirmed: () {
+ state.filtering = state.startDate != null ||
+ state.endDate != null ||
+ state.selectedCats.isNotEmpty;
+ state.fetchMonthlyList();
+ },
+ content: StatefulBuilder(
+ builder: (context, setState) => Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ItemTitle(
+ title: 'تاریخ ایجاد',
+ style: Theme.of(context).textTheme.bodyMedium,
+ icon: DidvanIcons.calendar_range_regular,
+ ),
+ const SizedBox(height: 8),
+ Row(
+ children: [
+ DatePickerButton(
+ initialValue: state.startDate,
+ emptyText: 'از تاریخ',
+ onPicked: (date) => setState(() => state.startDate = date),
+ lastDate: state.endDate,
+ ),
+ const SizedBox(width: 8),
+ DatePickerButton(
+ initialValue: state.endDate,
+ emptyText: 'تا تاریخ',
+ onPicked: (date) => setState(() => state.endDate = date),
+ firstDate: state.startDate,
+ ),
+ ],
+ ),
+ const SizedBox(height: 28),
+ if (state.categories.isNotEmpty) ...[
+ ItemTitle(
+ title: 'دسته بندی',
+ icon: DidvanIcons.category_regular,
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ const SizedBox(height: 12),
+ Wrap(
+ children: [
+ for (var category in state.categories)
+ SizedBox(
+ width: (MediaQuery.of(context).size.width - 40) / 2,
+ child: DidvanCheckbox(
+ title: category.label,
+ value: state.selectedCats
+ .any((cat) => cat.id == category.id),
+ onChanged: (value) {
+ setState(() {
+ if (value) {
+ state.selectedCats.add(category);
+ } else {
+ state.selectedCats.removeWhere(
+ (cat) => cat.id == category.id);
+ }
+ });
+ },
+ ),
+ ),
+ ],
+ ),
+ ],
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+
@override
void dispose() {
_timer?.cancel();
@@ -67,7 +157,9 @@ class _MonthlyListPageState extends State {
showBackButton: false,
showSearchField: state.appState != AppState.failed,
onSearchChanged: _onChanged,
+ onFilterPressed: _showFilterBottomSheet,
searchFocusNode: _focusNode,
+ isFiltered: state.filtering,
searchValue: state.searchQuery,
),
),
diff --git a/lib/views/monthly/monthly_list_state.dart b/lib/views/monthly/monthly_list_state.dart
index 0acc276..328f679 100644
--- a/lib/views/monthly/monthly_list_state.dart
+++ b/lib/views/monthly/monthly_list_state.dart
@@ -1,4 +1,6 @@
import 'dart:convert';
+import 'package:didvan/constants/assets.dart';
+import 'package:didvan/models/category.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/monthly/monthly_model.dart';
import 'package:didvan/providers/core.dart';
@@ -11,6 +13,48 @@ class MonthlyListState extends CoreProvier {
List monthlyItems = [];
List _allMonthlyItems = [];
String searchQuery = '';
+ String? startDate;
+ String? endDate;
+ final List selectedCats = [];
+ List categories = [];
+ bool filtering = false;
+
+ void initCategories() {
+ categories = [
+ CategoryData(
+ id: 1,
+ label: 'اقتصادی',
+ asset: Assets.economicCategoryIcon,
+ ),
+ CategoryData(
+ id: 2,
+ label: 'سیاسی',
+ asset: Assets.politicalCategoryIcon,
+ ),
+ CategoryData(
+ id: 3,
+ label: 'فناوری',
+ asset: Assets.techCategoryIcon,
+ ),
+ CategoryData(
+ id: 4,
+ label: 'کسب و کار',
+ asset: Assets.businessCategoryIcon,
+ ),
+ CategoryData(
+ id: 5,
+ label: 'زیستمحیطی',
+ asset: Assets.enviromentalCategoryIcon,
+ ),
+ CategoryData(
+ id: 6,
+ label: 'اجتماعی',
+ asset: Assets.socialCategoryIcon,
+ ),
+ ];
+ }
+
+ bool get searching => searchQuery.isNotEmpty;
Future fetchMonthlyList() async {
appState = AppState.busy;
@@ -38,12 +82,13 @@ class MonthlyListState extends CoreProvier {
final List resultList = jsonData['result'] as List;
debugPrint('Found ${resultList.length} items');
- monthlyItems =
+ _allMonthlyItems =
resultList.map((item) => MonthlyItem.fromJson(item)).toList();
- _allMonthlyItems = List.from(monthlyItems);
+ monthlyItems = _applyFilters(_allMonthlyItems);
- debugPrint('Successfully parsed ${monthlyItems.length} monthly items');
+ debugPrint(
+ 'Successfully parsed ${monthlyItems.length} monthly items after filters');
appState = AppState.idle;
} else {
debugPrint('Request failed with status code: ${response.statusCode}');
@@ -59,15 +104,17 @@ class MonthlyListState extends CoreProvier {
void search(String query) {
searchQuery = query;
- if (query.isEmpty) {
- monthlyItems = List.from(_allMonthlyItems);
- } else {
- monthlyItems = _allMonthlyItems
+ var filtered = _allMonthlyItems;
+
+ if (query.isNotEmpty) {
+ filtered = filtered
.where((item) =>
item.title.toLowerCase().contains(query.toLowerCase()) ||
item.description.toLowerCase().contains(query.toLowerCase()))
.toList();
}
+
+ monthlyItems = _applyFilters(filtered);
notifyListeners();
}
@@ -148,4 +195,45 @@ class MonthlyListState extends CoreProvier {
}
}
}
+
+ void resetFilters([bool notify = true]) {
+ startDate = null;
+ endDate = null;
+ selectedCats.clear();
+ filtering = false;
+ if (notify) {
+ fetchMonthlyList();
+ }
+ }
+
+ List _applyFilters(List items) {
+ var filtered = items;
+
+ if (startDate != null || endDate != null) {
+ filtered = filtered.where((item) {
+ final itemDate = DateTime.parse(item.publishedAt);
+
+ if (startDate != null) {
+ final start = DateTime.parse(startDate!);
+ if (itemDate.isBefore(start)) return false;
+ }
+
+ if (endDate != null) {
+ final end = DateTime.parse(endDate!).add(const Duration(days: 1));
+ if (itemDate.isAfter(end)) return false;
+ }
+
+ return true;
+ }).toList();
+ }
+
+ if (selectedCats.isNotEmpty) {
+ filtered = filtered.where((item) {
+ return item.tags
+ .any((tag) => selectedCats.any((cat) => cat.id == tag.id));
+ }).toList();
+ }
+
+ return filtered;
+ }
}
diff --git a/lib/views/news/news.dart b/lib/views/news/news.dart
index 3b60462..6778808 100644
--- a/lib/views/news/news.dart
+++ b/lib/views/news/news.dart
@@ -8,6 +8,7 @@ import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/views/news/news_state.dart';
import 'package:didvan/views/widgets/date_picker_button.dart';
+import 'package:didvan/views/widgets/didvan/checkbox.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/home_app_bar.dart';
import 'package:didvan/views/widgets/item_title.dart';
@@ -68,10 +69,9 @@ class _NewsState extends State {
title: Text(
'دنیای فولاد',
style: theme.textTheme.headlineSmall?.copyWith(
- color: const Color.fromARGB(255, 0, 53, 70),
- fontWeight: FontWeight.bold,
- fontSize: 19
- ),
+ color: const Color.fromARGB(255, 0, 53, 70),
+ fontWeight: FontWeight.bold,
+ fontSize: 19),
),
actions: [
IconButton(
@@ -99,7 +99,8 @@ class _NewsState extends State {
childCount: min(state.visibleCount, state.news.length) +
(_hasMoreItems(state) ? 1 : 0),
builder: (context, state, index) {
- final currentDisplayCount = min(state.visibleCount, state.news.length);
+ final currentDisplayCount =
+ min(state.visibleCount, state.news.length);
if (index == currentDisplayCount && _hasMoreItems(state)) {
return _buildLoadMoreButton(context, state);
@@ -122,7 +123,8 @@ class _NewsState extends State {
onLikedChanged: state.onLikedChanged,
);
},
- enableEmptyState: state.news.isEmpty && state.appState != AppState.busy,
+ enableEmptyState:
+ state.news.isEmpty && state.appState != AppState.busy,
emptyState: EmptyResult(
onNewSearch: () => _focusNode.requestFocus(),
),
@@ -134,17 +136,19 @@ class _NewsState extends State {
}
bool _hasMoreItems(NewsState state) {
- return state.news.length > state.visibleCount || state.page < state.lastPage;
+ return state.news.length > state.visibleCount ||
+ state.page < state.lastPage;
}
Widget _buildLoadMoreButton(BuildContext context, NewsState state) {
- if (state.appState == AppState.busy && state.news.length <= state.visibleCount) {
- return const Padding(
+ if (state.appState == AppState.busy &&
+ state.news.length <= state.visibleCount) {
+ return const Padding(
padding: EdgeInsets.all(16.0),
child: Center(child: CircularProgressIndicator()),
);
}
-
+
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: Center(
@@ -166,7 +170,8 @@ class _NewsState extends State {
children: [
SvgPicture.asset(
'lib/assets/icons/element-plus.svg',
- colorFilter: const ColorFilter.mode(Colors.white, BlendMode.srcIn),
+ colorFilter:
+ const ColorFilter.mode(Colors.white, BlendMode.srcIn),
width: 20,
),
const SizedBox(width: 8),
@@ -209,37 +214,69 @@ class _NewsState extends State {
confrimTitle: 'نمایش نتایج',
onDismissed: state.resetFilters,
onConfirmed: () => state.getNews(page: 1),
- content: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- ItemTitle(
- title: 'تاریخ خبر',
- style: Theme.of(context).textTheme.bodyMedium,
- icon: DidvanIcons.calendar_range_regular,
- ),
- const SizedBox(height: 8),
- StatefulBuilder(
- builder: (context, setState) => Row(
- children: [
- DatePickerButton(
- initialValue: state.startDate,
- emptyText: 'از تاریخ',
- onPicked: (date) {
- setState(() => state.startDate = date);
- },
- lastDate: state.endDate,
- ),
- const SizedBox(width: 8),
- DatePickerButton(
- initialValue: state.endDate,
- emptyText: 'تا تاریخ',
- onPicked: (date) => setState(() => state.endDate = date),
- firstDate: state.startDate,
- ),
- ],
- ),
- ),
- ],
+ content: StatefulBuilder(
+ builder: (context, setState) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ItemTitle(
+ title: 'تاریخ خبر',
+ style: Theme.of(context).textTheme.bodyMedium,
+ icon: DidvanIcons.calendar_range_regular,
+ ),
+ const SizedBox(height: 8),
+ Row(
+ children: [
+ DatePickerButton(
+ initialValue: state.startDate,
+ emptyText: 'از تاریخ',
+ onPicked: (date) {
+ setState(() => state.startDate = date);
+ },
+ lastDate: state.endDate,
+ ),
+ const SizedBox(width: 8),
+ DatePickerButton(
+ initialValue: state.endDate,
+ emptyText: 'تا تاریخ',
+ onPicked: (date) => setState(() => state.endDate = date),
+ firstDate: state.startDate,
+ ),
+ ],
+ ),
+ const SizedBox(height: 28),
+ ItemTitle(
+ title: 'دسته بندی',
+ icon: DidvanIcons.category_regular,
+ style: Theme.of(context).textTheme.bodyMedium,
+ ),
+ const SizedBox(height: 12),
+ Wrap(
+ children: [
+ for (var i = 0; i < state.categories.length; i++)
+ SizedBox(
+ width: (MediaQuery.of(context).size.width - 40) / 2,
+ child: DidvanCheckbox(
+ title: state.categories[i].label,
+ value: state.selectedCats
+ .any((cat) => cat.id == state.categories[i].id),
+ onChanged: (value) {
+ setState(() {
+ if (value) {
+ state.selectedCats.add(state.categories[i]);
+ } else {
+ state.selectedCats.removeWhere(
+ (cat) => cat.id == state.categories[i].id);
+ }
+ });
+ },
+ ),
+ ),
+ ],
+ ),
+ ],
+ );
+ },
),
),
);
diff --git a/lib/views/news/news_state.dart b/lib/views/news/news_state.dart
index 6e00a1b..a7e01d4 100644
--- a/lib/views/news/news_state.dart
+++ b/lib/views/news/news_state.dart
@@ -1,3 +1,5 @@
+import 'package:didvan/constants/assets.dart';
+import 'package:didvan/models/category.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/overview_data.dart';
import 'package:didvan/models/requests/news.dart';
@@ -13,7 +15,8 @@ class NewsState extends CoreProvier {
int page = 1;
int lastPage = 0;
int visibleCount = 4;
-
+ final List selectedCats = [];
+ List categories = [];
final List news = [];
void init() {
@@ -25,6 +28,39 @@ class NewsState extends CoreProvier {
getNews(page: 1);
});
visibleCount = 4;
+
+ categories = [
+ CategoryData(
+ id: 1,
+ label: 'اقتصادی',
+ asset: Assets.economicCategoryIcon,
+ ),
+ CategoryData(
+ id: 2,
+ label: 'سیاسی',
+ asset: Assets.politicalCategoryIcon,
+ ),
+ CategoryData(
+ id: 3,
+ label: 'فناوری',
+ asset: Assets.techCategoryIcon,
+ ),
+ CategoryData(
+ id: 4,
+ label: 'کسب و کار',
+ asset: Assets.businessCategoryIcon,
+ ),
+ CategoryData(
+ id: 5,
+ label: 'زیستمحیطی',
+ asset: Assets.enviromentalCategoryIcon,
+ ),
+ CategoryData(
+ id: 6,
+ label: 'اجتماعی',
+ asset: Assets.socialCategoryIcon,
+ ),
+ ];
}
void resetFilters() {
@@ -63,6 +99,7 @@ class NewsState extends CoreProvier {
startDate: startDate?.split(' ').first,
endDate: endDate?.split(' ').first,
search: search == '' ? null : search,
+ categories: selectedCats.map((e) => e.id).toList(),
),
),
);
@@ -93,5 +130,6 @@ class NewsState extends CoreProvier {
}
}
- bool get isFiltering => startDate != null || endDate != null;
+ bool get isFiltering =>
+ startDate != null || endDate != null || selectedCats.isNotEmpty;
}
diff --git a/lib/views/notification_settings/notification_settings.dart b/lib/views/notification_settings/notification_settings.dart
index e66cdda..947b09c 100644
--- a/lib/views/notification_settings/notification_settings.dart
+++ b/lib/views/notification_settings/notification_settings.dart
@@ -56,7 +56,7 @@ class _NotificationSettingsState extends State
}
void _startAnimationIfNeeded() {
- if (!_hasAnimated &&
+ if (!_hasAnimated &&
customizeState.appState == AppState.idle &&
notificationTimeState.appState == AppState.idle) {
_hasAnimated = true;
@@ -137,7 +137,7 @@ class _NotificationSettingsState extends State
builder: (context, state, child) {
if (state.appState == AppState.idle) {
_startAnimationIfNeeded();
-
+
final mediaKeywords = [
'پادکست',
'ویدئوکست',
@@ -281,8 +281,7 @@ class _NotificationSettingsState extends State
isDisabled: state.isAnytime,
onTimeChanged: (newTime) {
state.selectedTime = newTime;
- state
- .update(); // بهروزرسانی state برای اعمال تغییرات در انیمیشن و UI
+ state.update();
},
),
// Padding(
diff --git a/lib/views/pdf_viewer/pdf_viewer_page.dart b/lib/views/pdf_viewer/pdf_viewer_page.dart
index a17b8d2..2abda31 100644
--- a/lib/views/pdf_viewer/pdf_viewer_page.dart
+++ b/lib/views/pdf_viewer/pdf_viewer_page.dart
@@ -27,12 +27,10 @@ class _PdfViewerPageState extends State {
@override
void initState() {
super.initState();
- // Add access token to URL if needed
_fullPdfUrl = widget.pdfUrl.contains('?')
? 'https://api.didvan.app${widget.pdfUrl}'
: 'https://api.didvan.app${widget.pdfUrl}';
- // Debug: Print the PDF URL
if (kDebugMode) {
print('Original PDF URL: ${widget.pdfUrl}');
print('Full PDF URL : $_fullPdfUrl');
@@ -103,9 +101,9 @@ class _PdfViewerPageState extends State {
color: Colors.red,
),
const SizedBox(height: 16),
- DidvanText(
+ const DidvanText(
'خطا در بارگذاری PDF',
- style: const TextStyle(
+ style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
diff --git a/lib/views/profile/direct_list/direct_list.dart b/lib/views/profile/direct_list/direct_list.dart
index 495be85..6e4f3bc 100644
--- a/lib/views/profile/direct_list/direct_list.dart
+++ b/lib/views/profile/direct_list/direct_list.dart
@@ -80,126 +80,128 @@ class _DirectListState extends State
return Consumer(
builder: (context, state, child) {
_startAnimationIfNeeded(state);
-
+
return DidvanScaffold(
padding: const EdgeInsets.symmetric(vertical: 16),
appBarData: null,
showSliversFirst: true,
slivers: [
- SliverAppBar(
- pinned: true,
- backgroundColor: Theme.of(context).colorScheme.surface,
- automaticallyImplyLeading: false,
- leadingWidth: 200,
- leading: Padding(
- padding: const EdgeInsetsDirectional.only(start: 0.0),
- child: SvgPicture.asset(
- Assets.horizontalLogoWithText,
- fit: BoxFit.contain,
- height: 80,
+ SliverAppBar(
+ pinned: true,
+ backgroundColor: Theme.of(context).colorScheme.surface,
+ automaticallyImplyLeading: false,
+ leadingWidth: 200,
+ leading: Padding(
+ padding: const EdgeInsetsDirectional.only(start: 0.0),
+ child: SvgPicture.asset(
+ Assets.horizontalLogoWithText,
+ fit: BoxFit.contain,
+ height: 80,
+ ),
),
+ actions: [
+ IconButton(
+ onPressed: () {
+ Navigator.of(context).pushNamed(Routes.bookmarks);
+ },
+ icon: SvgPicture.asset(
+ 'lib/assets/icons/hugeicons_telescope-01.svg')),
+ IconButton(
+ onPressed: () => Navigator.of(context).pop(),
+ icon: SvgPicture.asset(
+ 'lib/assets/icons/arrow-left.svg',
+ color: const Color.fromARGB(255, 102, 102, 102),
+ )),
+ const SizedBox(width: 8),
+ ],
),
- actions: [
- IconButton(
- onPressed: () {
- Navigator.of(context).pushNamed(Routes.bookmarks);
- },
- icon: SvgPicture.asset(
- 'lib/assets/icons/hugeicons_telescope-01.svg')),
- IconButton(
- onPressed: () => Navigator.of(context).pop(),
- icon: SvgPicture.asset(
- 'lib/assets/icons/arrow-left.svg',
- color: const Color.fromARGB(255, 102, 102, 102),
- )),
- const SizedBox(width: 8),
- ],
- ),
- SliverToBoxAdapter(
- child: _buildAnimatedSection(
- index: 0,
- child: Padding(
- padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.end,
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- TextButton.icon(
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.all(
- const Color.fromARGB(255, 0, 126, 167),
+ SliverToBoxAdapter(
+ child: _buildAnimatedSection(
+ index: 0,
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ mainAxisAlignment: MainAxisAlignment.end,
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ TextButton.icon(
+ style: ButtonStyle(
+ backgroundColor: MaterialStateProperty.all(
+ const Color.fromARGB(255, 0, 126, 167),
+ ),
+ shape: MaterialStateProperty.all<
+ RoundedRectangleBorder>(
+ RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8.0),
+ ),
+ ),
),
- shape:
- MaterialStateProperty.all(
- RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(8.0),
+ onPressed: () {
+ Navigator.of(context).pushNamed(
+ Routes.direct,
+ arguments: {'type': 'پشتیبانی اپلیکیشن'},
+ ).then((value) {
+ if (mounted) {
+ context
+ .read()
+ .getDirectsList();
+ }
+ });
+ },
+ icon: SvgPicture.asset(
+ 'lib/assets/icons/add.svg',
+ height: 20,
+ color: Theme.of(context).colorScheme.surface,
+ ),
+ label: Text(
+ 'تیکت جدید',
+ style: TextStyle(
+ color: Theme.of(context).colorScheme.surface,
+ fontWeight: FontWeight.bold,
),
),
),
- onPressed: () {
- Navigator.of(context).pushNamed(
- Routes.direct,
- arguments: {'type': 'پشتیبانی اپلیکیشن'},
- ).then((value) {
- if (mounted) {
- context.read().getDirectsList();
- }
- });
- },
- icon: SvgPicture.asset(
- 'lib/assets/icons/add.svg',
- height: 20,
- color: Theme.of(context).colorScheme.surface,
- ),
- label: Text(
- 'تیکت جدید',
- style: TextStyle(
- color: Theme.of(context).colorScheme.surface,
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- // if (state.unreadCount > 0)
- // Padding(
- // padding: const EdgeInsetsDirectional.only(start: 8),
- // child: DidvanBadge(
- // text: state.unreadCount.toString(),
- // ),
- // ),
- ],
- ),
- ],
+ // if (state.unreadCount > 0)
+ // Padding(
+ // padding: const EdgeInsetsDirectional.only(start: 8),
+ // child: DidvanBadge(
+ // text: state.unreadCount.toString(),
+ // ),
+ // ),
+ ],
+ ),
+ ],
+ ),
),
),
),
- ),
- SliverStateHandler(
- onRetry: state.getDirectsList,
- itemPadding: const EdgeInsets.symmetric(horizontal: 16),
- state: state,
- placeholder: const _ChatRoomPlaceholder(),
- builder: (context, state, index) => _buildAnimatedSection(
- index: index + 1,
- child: ChatRoomItem(
- chatRoom: state.chatRooms[index],
- onBackButtonPressed: () {
- state.chatRooms.clear();
- state.getDirectsList();
- },
+ SliverStateHandler(
+ onRetry: state.getDirectsList,
+ itemPadding: const EdgeInsets.symmetric(horizontal: 16),
+ state: state,
+ placeholder: const _ChatRoomPlaceholder(),
+ builder: (context, state, index) => _buildAnimatedSection(
+ index: index + 1,
+ child: ChatRoomItem(
+ chatRoom: state.chatRooms[index],
+ onBackButtonPressed: () {
+ state.chatRooms.clear();
+ state.getDirectsList();
+ },
+ ),
+ ),
+ childCount: state.chatRooms.length,
+ enableEmptyState: state.chatRooms.isEmpty,
+ emptyState: EmptyState(
+ asset: Assets.emptyBookmark,
+ title: 'پیامی وجود ندارد',
),
),
- childCount: state.chatRooms.length,
- enableEmptyState: state.chatRooms.isEmpty,
- emptyState: EmptyState(
- asset: Assets.emptyBookmark,
- title: 'پیامی وجود ندارد',
- ),
- ),
- ],
+ ],
);
},
);
diff --git a/lib/views/widgets/home_app_bar.dart b/lib/views/widgets/home_app_bar.dart
index 97c507c..1ed589d 100644
--- a/lib/views/widgets/home_app_bar.dart
+++ b/lib/views/widgets/home_app_bar.dart
@@ -1,3 +1,5 @@
+// ignore_for_file: deprecated_member_use
+
import 'package:didvan/constants/assets.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/routes/routes.dart';
@@ -5,7 +7,6 @@ import 'package:didvan/views/widgets/search_field.dart';
import 'package:didvan/views/home/home_state.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
-import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/views/widgets/didvan/checkbox.dart';
import 'package:didvan/views/widgets/item_title.dart';
import 'package:didvan/views/widgets/date_picker_button.dart';
@@ -148,7 +149,7 @@ class HomeAppBar extends StatelessWidget {
if (onFilterPressed != null) {
onFilterPressed!();
} else {
- _showFilterBottomSheet(context);
+ showFilterBottomSheet(context);
}
},
isFiltered: isFiltered ?? homeState?.filtering ?? false,
@@ -167,12 +168,17 @@ class HomeAppBar extends StatelessWidget {
);
}
- Future _showFilterBottomSheet(BuildContext context) async {
+ Future showFilterBottomSheet(BuildContext context) async {
final state = Provider.of(context, listen: false);
ActionSheetUtils(context).showBottomSheet(
data: ActionSheetData(
- titleIcon: DidvanIcons.filter_regular,
+ title: 'فیلتر جستجو',
+ titleIconWidget: SvgPicture.asset(
+ 'lib/assets/icons/document-filter.svg',
+ width: 24,
+ height: 24,
+ ),
dismissTitle: 'حذف فیلتر',
confrimTitle: 'نمایش نتایج',
onDismissed: () => state.resetFilters(false),
@@ -180,11 +186,15 @@ class HomeAppBar extends StatelessWidget {
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- if (state.currentPageIndex != 3) ...[
+ if (state.currentPageIndex != 9) ...[
ItemTitle(
- title: 'تاریخ ایجاد',
- style: Theme.of(context).textTheme.bodyMedium,
- icon: DidvanIcons.calendar_range_regular,
+ title: 'تاریخ',
+ style: Theme.of(context)
+ .textTheme
+ .bodyMedium
+ ?.copyWith(fontWeight: FontWeight.bold),
+ iconWidget: 'lib/assets/icons/calendar.svg',
+ color: const Color.fromARGB(255, 27, 60, 89),
),
const SizedBox(height: 8),
StatefulBuilder(
@@ -211,8 +221,12 @@ class HomeAppBar extends StatelessWidget {
],
ItemTitle(
title: 'دسته بندی',
- icon: DidvanIcons.category_regular,
- style: Theme.of(context).textTheme.bodyMedium,
+ style: Theme.of(context)
+ .textTheme
+ .bodyMedium
+ ?.copyWith(fontWeight: FontWeight.bold),
+ iconWidget: 'lib/assets/icons/ion_extension-puzzle-outline.svg',
+ color: const Color.fromARGB(255, 27, 60, 89),
),
const SizedBox(height: 12),
Wrap(
diff --git a/lib/views/widgets/hoshan_home_app_bar.dart b/lib/views/widgets/hoshan_home_app_bar.dart
index ea9f474..c2d3c24 100644
--- a/lib/views/widgets/hoshan_home_app_bar.dart
+++ b/lib/views/widgets/hoshan_home_app_bar.dart
@@ -1,5 +1,5 @@
import 'package:didvan/config/theme_data.dart';
-import 'package:didvan/constants/app_icons.dart'; // <-- این خط اضافه شد
+import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/providers/user.dart';
@@ -276,18 +276,18 @@ class _HistoryDrawerContentState extends State {
String _getMonthName(int month) {
const monthNames = [
- 'فروردین', // 1
- 'اردیبهشت', // 2
- 'خرداد', // 3
- 'تیر', // 4
- 'مرداد', // 5
- 'شهریور', // 6
- 'مهر', // 7
- 'آبان', // 8
- 'آذر', // 9
- 'دی', // 10
- 'بهمن', // 11
- 'اسفند', // 12
+ 'فروردین',
+ 'اردیبهشت',
+ 'خرداد',
+ 'تیر',
+ 'مرداد',
+ 'شهریور',
+ 'مهر',
+ 'آبان',
+ 'آذر',
+ 'دی',
+ 'بهمن',
+ 'اسفند',
];
if (month >= 1 && month <= 12) {
@@ -298,9 +298,7 @@ class _HistoryDrawerContentState extends State {
@override
Widget build(BuildContext context) {
- // --- اضافه شد ---
final theme = Theme.of(context);
- // --- ---
return Align(
alignment: Alignment.centerLeft,
@@ -429,21 +427,20 @@ class _HistoryDrawerContentState extends State {
],
),
),
- // --- شروع کد اضافه شده ---
Padding(
padding: const EdgeInsets.only(top: 30.0),
child: InkWell(
onTap: () {
- // بستن دراور
- Navigator.pop(context);
- // نویگیت به صفحه آرشیو
- Navigator.of(context).pushNamed(Routes.aiArchivedHistory);
+ Navigator.pop(context);
+ Navigator.of(context)
+ .pushNamed(Routes.aiArchivedHistory);
},
child: Row(
children: [
SvgPicture.asset(
'lib/assets/icons/direct-inbox.svg',
- color: const Color.fromARGB(255, 61, 61, 61),
+ color:
+ const Color.fromARGB(255, 61, 61, 61),
height: 20,
),
const SizedBox(width: 8),
@@ -459,7 +456,6 @@ class _HistoryDrawerContentState extends State {
),
),
),
- // --- پایان کد اضافه شده ---
],
),
),
@@ -723,8 +719,8 @@ class _HistoryDrawerContentState extends State {
const PopupMenuDivider(height: 10),
],
),
- ],
- ),
+ ],
+ ),
],
],
),
@@ -797,4 +793,4 @@ class _HistoryDrawerContentState extends State {
),
);
}
-}
\ No newline at end of file
+}
diff --git a/lib/views/widgets/item_title.dart b/lib/views/widgets/item_title.dart
index be2fc13..34fca06 100644
--- a/lib/views/widgets/item_title.dart
+++ b/lib/views/widgets/item_title.dart
@@ -1,12 +1,14 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
class ItemTitle extends StatelessWidget {
final String title;
final TextStyle? style;
final IconData? icon;
final Color? color;
+ final String? iconWidget;
const ItemTitle({
Key? key,
@@ -14,6 +16,7 @@ class ItemTitle extends StatelessWidget {
this.icon,
this.color,
this.style,
+ this.iconWidget,
}) : super(key: key);
@override
@@ -23,9 +26,11 @@ class ItemTitle extends StatelessWidget {
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
+ if (iconWidget != null)
+ SvgPicture.asset(iconWidget!, color: color),
if (icon != null)
Icon(icon, color: color ?? Theme.of(context).colorScheme.title),
- if (icon != null) const SizedBox(width: 4),
+ if (iconWidget != null || icon != null) const SizedBox(width: 4),
DidvanText(
title,
style: style ?? Theme.of(context).textTheme.titleMedium,
diff --git a/lib/views/widgets/search_app_bar.dart b/lib/views/widgets/search_app_bar.dart
index c158f32..c92428a 100644
--- a/lib/views/widgets/search_app_bar.dart
+++ b/lib/views/widgets/search_app_bar.dart
@@ -68,7 +68,6 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
void _onChanged(String value, BuildContext context) {
final state = context.read();
- // Use the improved search functionality from HomeState
if (value.length >= 2) {
state.onSearchChanged(value);
} else if (value.isEmpty) {
@@ -90,7 +89,7 @@ class SearchAppBar extends StatelessWidget implements PreferredSizeWidget {
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- if (state.currentPageIndex != 3) ...[
+ if (state.currentPageIndex != 9) ...[
ItemTitle(
title: 'تاریخ ایجاد',
style: Theme.of(context).textTheme.bodyMedium,