import 'package:flutter/material.dart'; import '../about/internal/application/TextType.dart'; import '../about/internal/application/DeploymentRecord.dart'; import '../utils/Colors.dart'; import 'text/Text.dart'; import '../utils/CommonUtils.dart'; /// A compact "recently deployed" list of the latest deployments. class RecentDeploys extends StatelessWidget { final List history; final VoidCallback onViewAll; final int max; const RecentDeploys({ super.key, required this.history, required this.onViewAll, this.max = 5, }); @override Widget build(BuildContext context) { final jp = context.jp; final items = history.take(max).toList(); return Container( decoration: PeachTheme.panel(context), child: Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 12, 8, 8), child: Row( children: [ const Icon(Icons.bolt, size: 16, color: PeachTheme.seed), const SizedBox(width: 6), text( 'RECENTLY DEPLOYED', 12, TextType.Regular, color: jp.textDim, letterSpacing: 1.2, weight: FontWeight.w700, ), const Spacer(), TextButton(onPressed: onViewAll, child: const Text('View all')), ], ), ), for (var i = 0; i < items.length; i++) ...[ if (i > 0) Divider(height: 1, indent: 16, endIndent: 16, color: jp.border), _row(jp, items[i]), ], ], ), ); } Widget _row(JpColors jp, DeploymentRecord r) { final (color, icon) = switch (r.status) { DeployStatus.success => (PeachTheme.seed, Icons.check_circle), DeployStatus.failure => (PeachTheme.danger, Icons.error), DeployStatus.reverted => (PeachTheme.warn, Icons.undo), }; return Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), child: Row( children: [ Icon(icon, size: 18, color: color), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ text( '${r.serverName} ยท ${r.serviceLabel}', 13.5, TextType.Regular, color: jp.text, maxLines: 1, overflow: TextOverflow.ellipsis, weight: FontWeight.w600, ), const SizedBox(height: 1), Text( r.jarName.isEmpty ? r.remotePath : r.jarName, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 11.5, fontFamily: 'monospace', color: jp.textFaint, ), ), ], ), ), const SizedBox(width: 8), text( timeAgo(r.time), 11.5, TextType.Regular, color: jp.textFaint, weight: FontWeight.w400, ), ], ), ); } }