didvan-app/lib/views/home/main/widgets/swot_bookmark.dart

305 lines
10 KiB
Dart

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<SwotBookmark> createState() => _SwotBookmark();
}
class _SwotBookmark extends State<SwotBookmark> {
ValueNotifier<bool> 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<void> 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);
}
},
),
],
),
],
),
),
);
}
}