/opt/canhelp/apps/mobile/lib/widgets
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}';
}
}