206 lines
7.4 KiB
Dart
206 lines
7.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../models/task_log_model.dart';
|
|
import '../screens/log_form_screen.dart';
|
|
import '../services/task_log_service.dart';
|
|
|
|
class LogCard extends StatelessWidget {
|
|
final TaskLogModel log;
|
|
final bool canEdit;
|
|
|
|
const LogCard({super.key, required this.log, required this.canEdit});
|
|
|
|
Color _getStatusColor() {
|
|
switch (log.status) {
|
|
case 'done': return const Color(0xFF10B981); // Emerald
|
|
case 'in_progress': return Colors.amber.shade700;
|
|
case 'blocked': return const Color(0xFFF43F5E); // Rose
|
|
default: return const Color(0xFF64748B); // Slate
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
const Color rose = Color(0xFFF43F5E);
|
|
|
|
return Container(
|
|
margin: const EdgeInsets.only(bottom: 16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(24),
|
|
border: Border.all(color: Colors.grey.shade100),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.indigo.withOpacity(0.03),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
CircleAvatar(
|
|
radius: 18,
|
|
backgroundColor: _getStatusColor().withOpacity(0.1),
|
|
child: Icon(
|
|
log.status == 'done' ? Icons.check_circle_rounded :
|
|
log.status == 'blocked' ? Icons.error_rounded : Icons.pending_rounded,
|
|
color: _getStatusColor(),
|
|
size: 20,
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
log.projectName,
|
|
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: Color(0xFF1E293B)),
|
|
),
|
|
Text(
|
|
log.userName,
|
|
style: TextStyle(color: Colors.grey.shade500, fontSize: 12, fontWeight: FontWeight.w500),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (log.flavor != null)
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: Colors.indigo.shade50,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Text(
|
|
log.flavor!.toUpperCase(),
|
|
style: const TextStyle(color: Color(0xFF6366F1), fontSize: 9, fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF8FAFC),
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.code, size: 14, color: Color(0xFF64748B)),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
log.moduleName,
|
|
style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 13, color: Color(0xFF334155)),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 6),
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.account_tree_outlined, size: 14, color: Color(0xFF64748B)),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
log.branchName,
|
|
style: TextStyle(color: Colors.grey.shade600, fontSize: 12),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
log.remarks,
|
|
style: const TextStyle(fontSize: 14, color: Color(0xFF475569), height: 1.5),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.calendar_month_rounded, size: 14, color: Color(0xFF94A3B8)),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
DateFormat('dd MMM yyyy').format(log.date),
|
|
style: const TextStyle(color: Color(0xFF94A3B8), fontSize: 11, fontWeight: FontWeight.w600),
|
|
),
|
|
],
|
|
),
|
|
if (canEdit)
|
|
Row(
|
|
children: [
|
|
_actionButton(
|
|
Icons.edit_rounded,
|
|
() => Navigator.push(context, MaterialPageRoute(builder: (_) => LogFormScreen(log: log)))
|
|
),
|
|
const SizedBox(width: 8),
|
|
_actionButton(
|
|
Icons.delete_outline_rounded,
|
|
() => _confirmDelete(context),
|
|
color: rose.withOpacity(0.1),
|
|
iconColor: rose,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _actionButton(IconData icon, VoidCallback onTap, {Color? color, Color? iconColor}) {
|
|
return Material(
|
|
color: color ?? const Color(0xFFF1F5F9),
|
|
borderRadius: BorderRadius.circular(10),
|
|
child: InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(10),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8),
|
|
child: Icon(icon, size: 18, color: iconColor ?? const Color(0xFF64748B)),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _confirmDelete(BuildContext context) {
|
|
const Color rose = Color(0xFFF43F5E);
|
|
showDialog(
|
|
context: context,
|
|
builder: (ctx) => AlertDialog(
|
|
title: const Text("Delete Entry", style: TextStyle(fontWeight: FontWeight.bold)),
|
|
content: const Text("Are you sure you want to delete this log? This action cannot be undone."),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
|
actions: [
|
|
TextButton(onPressed: () => Navigator.pop(ctx), child: const Text("CANCEL")),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: rose,
|
|
minimumSize: const Size(100, 40),
|
|
),
|
|
onPressed: () {
|
|
context.read<TaskLogService>().deleteTaskLog(log.id);
|
|
Navigator.pop(ctx);
|
|
},
|
|
child: const Text("DELETE", style: TextStyle(color: Colors.white)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|