import 'dart:async'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/home_page_content/swot.dart'; import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/note_service.dart'; import 'package:didvan/views/home/main/widgets/bookmarked_icon.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text_field.dart'; import 'package:didvan/views/widgets/shimmer_placeholder.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:url_launcher/url_launcher_string.dart'; class SwotBookmark extends StatefulWidget { final SwotItem item; final void Function(int postId)? onSwotUnbookmarked; const SwotBookmark({ super.key, required this.item, this.onSwotUnbookmarked, }); @override State createState() => _SwotBookmark(); } class _SwotBookmark extends State { ValueNotifier myBookmarkStatus = ValueNotifier(true); String noteText = ''; String tempNoteText = ''; bool isLoading = true; bool hasExistingNote = false; // Track if a note exists Timer? _debounce; @override void initState() { super.initState(); loadNote(); } Future loadNote() async { final note = await NoteService.getNoteByPostId(widget.item.id); if (mounted) { setState(() { noteText = note?.content ?? ''; tempNoteText = noteText; hasExistingNote = note != null; // Set flag if note exists isLoading = false; }); } } void saveOrUpdateNote(String content) async { print('Processing note for PostId: ${widget.item.id}, Content: $content'); setState(() { isLoading = true; }); try { bool success; if (hasExistingNote) { // Update existing note success = await NoteService.updateNote(widget.item.id, content); } else { // Save new note success = await NoteService.saveNote(widget.item.id, content); } if (success) { await loadNote(); // Reload note from server if (mounted) { setState(() { isLoading = false; }); } } else { if (mounted) { setState(() { isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('خطا در ذخیره یادداشت: سرور پاسخ ناموفق داد')), ); } } } catch (e) { if (mounted) { setState(() { isLoading = false; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('خطا در ذخیره یادداشت: $e')), ); } } } void onNoteChanged(String value) { setState(() { tempNoteText = value; }); if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 500), () { saveOrUpdateNote(value); }); } @override void dispose() { _debounce?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () { AppInitializer.openWebLink( context, 'http://opportunity-threat.didvan.com/posts/${widget.item.id}/?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); }, child: Container( margin: const EdgeInsets.only(bottom: 10, right: 2, left: 2), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), ), child: Column( children: [ // ... (Row with image and text details for SwotItem) ... Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.only(right: 8, top: 8), child: Stack( children: [ ClipRRect( borderRadius: BorderRadius.circular(8), child: CachedNetworkImage( imageUrl: widget.item.imageUrl, width: 80, height: 80, fit: BoxFit.cover, httpHeaders: { 'Authorization': 'Bearer ${RequestService.token}', }, imageRenderMethodForWeb: ImageRenderMethodForWeb.HttpGet, placeholder: (context, _) => const ShimmerPlaceholder( width: 100, height: 100, ), errorWidget: (context, url, error) => Container( width: 100, height: 100, color: Theme.of(context) .colorScheme .disabledBackground, child: const Icon(Icons.image_not_supported_outlined), ), ), ), Container( padding: const EdgeInsets.symmetric( vertical: 4, horizontal: 8), decoration: BoxDecoration( color: Theme.of(context).colorScheme.secondary, borderRadius: const BorderRadius.horizontal( left: Radius.circular(10), ), ), child: SvgPicture.asset("lib/assets/images/categories/Vector.svg",height: 14,) ), ], ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item.title, style: Theme.of(context).textTheme.bodyLarge, maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox( height: 18, ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon( DidvanIcons.calendar_day_light, size: 16, ), const SizedBox(width: 4), DidvanText( DateTime.parse(widget.item.createdAt) .toPersianDateStr(), style: Theme.of(context).textTheme.labelSmall, ), ], ), ], ), ), ], ), // Notes Title Column Column( children: [ const SizedBox(height: 8), Row( children: [ Icon( Icons.edit_outlined, size: 16, color: Theme.of(context).colorScheme.caption, ), const SizedBox(width: 4), DidvanText( 'یادداشت‌های من', style: Theme.of(context).textTheme.labelSmall, color: Theme.of(context).colorScheme.caption, ), ], ), ], ), // Row for (Divider + TextField) and BookmarkIcon Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: Container( height: 1, color: Theme.of(context).colorScheme.primary, ), ), Flexible( flex: 2, child: Container( height: 1, color: Theme.of(context).colorScheme.border, ), ) ], ), const SizedBox(height: 4), isLoading ? const Padding( padding: EdgeInsets.symmetric(vertical: 12), child: CircularProgressIndicator(strokeWidth: 2), ) : DidvanTextField( disableBorders: true, initialValue: tempNoteText, hintText: 'برای اضافه کردن یادداشت لمس کنید.', onChanged: onNoteChanged, isSmall: true, textInputAction: TextInputAction.done, ), ], ), ), const SizedBox(width: 8), BookmarkedIcon( postId: widget.item.id, onBookmarkChanged: (isBookmarked) { if (!isBookmarked) { widget.onSwotUnbookmarked?.call(widget.item.id); } }, ), ], ), ], ), ), ); } }