import 'package:flutter/material.dart'; import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/utils/size_config.dart'; import 'package:tm_app/views/shared/desktop_navigation_widget.dart'; // مدل Task برای نگهداری اطلاعات هر کارت class TaskItem { final String id; final String title; final String description; final DateTime deadline; final String assignedTo; final bool isReady; TaskStatus status; TaskItem({ required this.id, required this.title, required this.description, required this.deadline, required this.assignedTo, required this.isReady, required this.status, }); } enum TaskStatus { toDo, inProgress, done } class BoardScreen extends StatefulWidget { const BoardScreen({super.key}); @override State createState() => _BoardScreenState(); } class _BoardScreenState extends State { // لیست تسک‌های نمونه List tasks = [ TaskItem( id: '1', title: 'موضوع مناقصه', description: 'لورم سد می تورتور اوی پوروس سنکتوس. موربی لائورت تورتور...', deadline: DateTime(2025, 6, 15), assignedTo: 'Pratyush Tewari', isReady: false, status: TaskStatus.toDo, ), TaskItem( id: '2', title: 'موضوع مناقصه', description: 'لورم سد موربی لائورت تورتور...', deadline: DateTime(2025, 6, 15), assignedTo: 'Pratyush Tewari', isReady: true, status: TaskStatus.toDo, ), TaskItem( id: '3', title: 'موضوع مناقصه', description: 'لورم ایپسوم. سد می تورتور اوی پوروس سنکتوس. موربی لائورت تورتور...', deadline: DateTime(2025, 6, 15), assignedTo: 'Pratyush Tewari', isReady: false, status: TaskStatus.inProgress, ), TaskItem( id: '4', title: 'موضوع مناقصه', description: 'لورم ایپسوم امت...', deadline: DateTime(2025, 6, 15), assignedTo: 'Pratyush Tewari', isReady: true, status: TaskStatus.inProgress, ), TaskItem( id: '5', title: 'موضوع مناقصه', description: 'لورم سد می تورتور اوی پوروس سنکتوس. موربی لائورت تورتور...', deadline: DateTime(2025, 6, 15), assignedTo: 'Pratyush Tewari', isReady: false, status: TaskStatus.done, ), ]; // متد برای تغییر وضعیت task void _updateTaskStatus(TaskItem task, TaskStatus newStatus) { // اگر وضعیت تغییر نکرده، نیازی به آپدیت نیست if (task.status == newStatus) { return; } final oldStatus = task.status; setState(() { task.status = newStatus; }); // نمایش پیام تایید _showStatusChangeMessage(context, task, oldStatus, newStatus); } // نمایش پیام تغییر وضعیت void _showStatusChangeMessage( BuildContext context, TaskItem task, TaskStatus oldStatus, TaskStatus newStatus, ) { final statusNames = { TaskStatus.toDo: 'To Do', TaskStatus.inProgress: 'In Progress', TaskStatus.done: 'Done', }; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( 'کارت "${task.title}" از ${statusNames[oldStatus]} به ${statusNames[newStatus]} منتقل شد', style: const TextStyle(fontFamily: 'Peyda'), ), duration: const Duration(seconds: 2), backgroundColor: AppColors.successColor, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), ); } // گرفتن تسک‌های هر دسته List _getTasksByStatus(TaskStatus status) { return tasks.where((task) => task.status == status).toList(); } @override Widget build(BuildContext context) { SizeConfig.init(context); return Scaffold( backgroundColor: AppColors.backgroundColor, body: Column( children: [ const DesktopNavigationWidget( currentIndex: 2, // Tenders index ), SizedBox( width: 740, height: 735, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 64), Text( 'My board', style: TextStyle( fontSize: 20.0.sp(), fontWeight: FontWeight.w600, color: AppColors.titleColor, ), ), const SizedBox(height: 20), Expanded( child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: AppColors.primary20, ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // ستون To Do Expanded( child: _BoardColumn( title: 'To do', color: AppColors.primary20, textColor: const Color(0xFF1976D2), tasks: _getTasksByStatus(TaskStatus.toDo), status: TaskStatus.toDo, onTaskDropped: _updateTaskStatus, ), ), const SizedBox(width: 12), // ستون In Progress Expanded( child: _BoardColumn( title: 'In progress', color: const Color(0xFFFFF3E0), textColor: const Color(0xFFF57C00), tasks: _getTasksByStatus(TaskStatus.inProgress), status: TaskStatus.inProgress, onTaskDropped: _updateTaskStatus, ), ), const SizedBox(width: 12), // ستون Done Expanded( child: _BoardColumn( title: 'Done', color: const Color(0xFFE8F5E9), textColor: const Color(0xFF388E3C), tasks: _getTasksByStatus(TaskStatus.done), status: TaskStatus.done, onTaskDropped: _updateTaskStatus, ), ), ], ), ), ), ], ), ), ], ), ); } } // ویجت ستون بورد class _BoardColumn extends StatelessWidget { final String title; final Color color; final Color textColor; final List tasks; final TaskStatus status; final Function(TaskItem, TaskStatus) onTaskDropped; const _BoardColumn({ required this.title, required this.color, required this.textColor, required this.tasks, required this.status, required this.onTaskDropped, }); @override Widget build(BuildContext context) { return DragTarget( onWillAcceptWithDetails: (details) { // فقط اگر task از ستون دیگری باشد، قبول کن return details.data.status != status; }, onAcceptWithDetails: (details) { onTaskDropped(details.data, status); }, builder: (context, candidateData, rejectedData) { final isHovering = candidateData.isNotEmpty; return Container( decoration: BoxDecoration( color: isHovering ? color.withOpacity(0.3) : AppColors.primary0, borderRadius: BorderRadius.circular(12), border: Border.all( color: isHovering ? textColor : AppColors.borderBlue, width: isHovering ? 2 : 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // هدر ستون Container( width: double.infinity, height: 34, margin: const EdgeInsets.all(8), decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(4), ), alignment: Alignment.center, child: Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.primaryColor, ), ), ), // لیست تسک‌ها Expanded( child: ListView.builder( padding: const EdgeInsets.all(12), itemCount: tasks.length, itemBuilder: (context, index) { return _TaskCard(task: tasks[index]); }, ), ), ], ), ); }, ); } } // ویجت کارت Task class _TaskCard extends StatelessWidget { final TaskItem task; const _TaskCard({required this.task}); String _formatDate(DateTime date) { return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; } @override Widget build(BuildContext context) { return Draggable( data: task, feedback: Material( elevation: 8, borderRadius: BorderRadius.circular(12), child: Container( width: 280, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.primary0, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderBlue, width: 2), ), child: _buildCardContent(context), ), ), childWhenDragging: Opacity(opacity: 0.3, child: _buildCard(context)), child: _buildCard(context), ); } Widget _buildCard(BuildContext context) { return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppColors.primary0, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.grey30), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 4, offset: const Offset(0, 2), ), ], ), child: _buildCardContent(context), ); } Widget _buildCardContent(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Deadline Container( height: 24.0, padding: EdgeInsets.symmetric(horizontal: 10.0.w()), decoration: BoxDecoration( color: AppColors.primary20, borderRadius: BorderRadius.circular(4), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Deadline :', style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w500, color: AppColors.textBlue, ), ), Text( _formatDate(task.deadline), style: TextStyle( fontSize: 14.0, fontWeight: FontWeight.w500, color: AppColors.grey80, ), ), ], ), ), // Row( // children: [ // Text( // 'Deadline:', // style: TextStyle( // fontSize: 12, // color: AppColors.grey60, // fontWeight: FontWeight.w500, // ), // ), // const SizedBox(width: 8), // Text( // _formatDate(task.deadline), // style: TextStyle( // fontSize: 12, // color: AppColors.primaryTextColor, // fontWeight: FontWeight.w600, // ), // ), // ], // ), const SizedBox(height: 12), // عنوان Text( task.title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: AppColors.primaryTextColor, ), ), const SizedBox(height: 8), // توضیحات Text( task.description, style: TextStyle(fontSize: 12, color: AppColors.grey60, height: 1.5), maxLines: 3, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 12), // وضعیت و اطلاعات کاربر Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // وضعیت Row( children: [ Container( width: 8, height: 8, decoration: BoxDecoration( color: task.isReady ? Colors.blue : Colors.red, shape: BoxShape.circle, ), ), const SizedBox(width: 6), Text( task.isReady ? 'Ready' : 'Incomplete', style: TextStyle( fontSize: 11, color: task.isReady ? Colors.blue : Colors.red, fontWeight: FontWeight.w500, ), ), ], ), // آیکون کاربر و نام Row( children: [ Icon(Icons.account_circle, size: 16, color: AppColors.grey60), const SizedBox(width: 4), Text( task.assignedTo, style: TextStyle(fontSize: 11, color: AppColors.grey60), ), ], ), ], ), ], ); } }