/opt/canhelp/apps/mobile/lib/widgets
NameSizeModeActions
admin_preview_overlay.dart146700644editdlrm
app_bar_actions.dart23230644editdlrm
app_drawer.dart145250644editdlrm
auth_terms_consent.dart39280644editdlrm
plan_badge.dart11030644editdlrm
task_card.dart75050644editdlrm
upgrade_prompt.dart61970644editdlrm
Edit: /opt/canhelp/apps/mobile/lib/widgets/task_card.dart (7505B)
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:go_router/go_router.dart'; import '../models/task.dart'; import '../providers/categories_provider.dart'; import '../providers/locale_provider.dart'; import '../providers/locations_provider.dart'; import '../theme/app_theme.dart'; class TaskCard extends StatelessWidget { final Task task; const TaskCard({super.key, required this.task}); @override Widget build(BuildContext context) { final locale = context.watch(); final loc = locale.locale; final t = locale.t; final catProvider = context.watch(); final locProvider = context.watch(); final title = task.localizedTitle(loc); final desc = task.localizedDescription(loc); final catName = catProvider.nameFor(task.category, loc); final locName = locProvider.nameFor(task.location, loc); final catIcon = catProvider.iconFor(task.category); return GestureDetector( onTap: () => context.push('/tasks/${task.id}'), child: Container( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 5), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(AppTheme.cardRadius), boxShadow: const [ BoxShadow( color: AppTheme.shadowColor, blurRadius: 8, offset: Offset(0, 2), ), ], ), child: Padding( padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // ── Top row: icon + title + budget ── Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Category icon circle Container( width: 44, height: 44, decoration: BoxDecoration( color: AppTheme.primaryLight, borderRadius: BorderRadius.circular(AppTheme.inputRadius), ), child: Center( child: catIcon.isNotEmpty ? Text(catIcon, style: const TextStyle(fontSize: 22)) : const Icon( Icons.category_outlined, size: 22, color: AppTheme.primary, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: AppTheme.textPrimary, height: 1.3, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), if (catName.isNotEmpty) ...[ const SizedBox(height: 3), Text( catName, style: const TextStyle( fontSize: 12, color: AppTheme.primary, fontWeight: FontWeight.w500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ], ), ), if (task.budget != null && task.budget! > 0) ...[ const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 4, ), decoration: BoxDecoration( color: AppTheme.primaryLight, borderRadius: BorderRadius.circular( AppTheme.chipRadius, ), ), child: Text( '€${task.budget!.toStringAsFixed(0)}', style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w700, color: AppTheme.primary, ), ), ), ], ], ), // ── Description ── if (desc.isNotEmpty) ...[ const SizedBox(height: 10), Text( desc, style: const TextStyle( fontSize: 13, color: AppTheme.textSecondary, height: 1.4, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], // ── Footer chips ── if (locName.isNotEmpty || task.deadline != null || true) ...[ const SizedBox(height: 10), const Divider(height: 1, color: AppTheme.border), const SizedBox(height: 10), Row( children: [ if (locName.isNotEmpty) ...[ const Icon( Icons.location_on_outlined, size: 13, color: AppTheme.textSecondary, ), const SizedBox(width: 3), Expanded( child: Text( locName, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], if (locName.isEmpty) const Spacer(), const SizedBox(width: 8), const Icon( Icons.calendar_today_outlined, size: 13, color: AppTheme.textSecondary, ), const SizedBox(width: 3), Text( task.deadline != null ? '${t('tasks.deadline')}: ${_formatDate(task.deadline!)}' : '${t('tasks.createdAt')}: ${_formatDate(task.createdAt)}', style: const TextStyle( fontSize: 12, color: AppTheme.textPrimary, ), ), ], ), ], ], ), ), ), ); } String _formatDate(DateTime d) { return '${d.day.toString().padLeft(2, '0')}.${d.month.toString().padLeft(2, '0')}.${d.year}'; } }