Files
submanager/lib/widgets/subscription_group_header.dart
2025-11-14 16:53:41 +09:00

165 lines
4.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../l10n/app_localizations.dart';
import '../utils/payment_card_utils.dart';
import '../utils/subscription_grouping_helper.dart';
class SubscriptionGroupHeader extends StatelessWidget {
final SubscriptionGroupData group;
final int subscriptionCount;
final double totalCostUSD;
final double totalCostKRW;
final double totalCostJPY;
final double totalCostCNY;
const SubscriptionGroupHeader({
super.key,
required this.group,
required this.subscriptionCount,
required this.totalCostUSD,
required this.totalCostKRW,
required this.totalCostJPY,
required this.totalCostCNY,
});
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
return Padding(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
if (group.mode == SubscriptionGroupingMode.paymentCard &&
group.paymentCard != null)
_PaymentCardAvatar(colorHex: group.paymentCard!.colorHex)
else if (group.mode == SubscriptionGroupingMode.paymentCard)
const _PaymentCardAvatar(),
if (group.mode == SubscriptionGroupingMode.paymentCard)
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
group.title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w700,
color: scheme.onSurface,
),
),
if (group.subtitle != null)
Text(
group.subtitle!,
style: TextStyle(
fontSize: 13,
color: scheme.onSurfaceVariant,
),
),
],
),
),
],
),
),
Text(
_buildCostDisplay(context),
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: scheme.onSurfaceVariant,
),
),
],
),
const SizedBox(height: 8),
Divider(
height: 1,
thickness: 1,
color: scheme.outline.withValues(alpha: 0.3),
),
],
),
);
}
String _buildCostDisplay(BuildContext context) {
final parts = <String>[];
parts
.add(AppLocalizations.of(context).subscriptionCount(subscriptionCount));
final currencyParts = <String>[];
if (totalCostUSD > 0) {
final formatter = NumberFormat.currency(
locale: 'en_US',
symbol: '\$',
decimalDigits: 2,
);
currencyParts.add(formatter.format(totalCostUSD));
}
if (totalCostKRW > 0) {
final formatter = NumberFormat.currency(
locale: 'ko_KR',
symbol: '',
decimalDigits: 0,
);
currencyParts.add(formatter.format(totalCostKRW));
}
if (totalCostJPY > 0) {
final formatter = NumberFormat.currency(
locale: 'ja_JP',
symbol: '¥',
decimalDigits: 0,
);
currencyParts.add(formatter.format(totalCostJPY));
}
if (totalCostCNY > 0) {
final formatter = NumberFormat.currency(
locale: 'zh_CN',
symbol: '¥',
decimalDigits: 2,
);
currencyParts.add(formatter.format(totalCostCNY));
}
if (currencyParts.isNotEmpty) {
parts.add(currencyParts.join(' + '));
}
return parts.join(' · ');
}
}
class _PaymentCardAvatar extends StatelessWidget {
final String? colorHex;
const _PaymentCardAvatar({this.colorHex});
@override
Widget build(BuildContext context) {
final color = colorHex != null
? PaymentCardUtils.colorFromHex(colorHex!)
: Theme.of(context).colorScheme.outlineVariant;
final icon =
colorHex != null ? Icons.credit_card : Icons.credit_card_off_rounded;
return CircleAvatar(
radius: 18,
backgroundColor: color.withValues(alpha: 0.15),
child: Icon(
icon,
color: color,
size: 16,
),
);
}
}