205 lines
6.9 KiB
Dart
205 lines
6.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../../app/theme/app_colors.dart';
|
|
import '../../../../app/theme/app_typography.dart';
|
|
import '../../../../app/theme/app_spacing.dart';
|
|
import '../../../../shared/widgets/status_tag.dart';
|
|
import '../../../../shared/widgets/empty_state.dart';
|
|
import '../../../../app/i18n/app_localizations.dart';
|
|
|
|
/// A5. 交易模块(二级市场)
|
|
///
|
|
/// 我的挂单、我的交易记录
|
|
class TradingPage extends StatefulWidget {
|
|
const TradingPage({super.key});
|
|
|
|
@override
|
|
State<TradingPage> createState() => _TradingPageState();
|
|
}
|
|
|
|
class _TradingPageState extends State<TradingPage>
|
|
with SingleTickerProviderStateMixin {
|
|
late TabController _tabController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_tabController = TabController(length: 2, vsync: this);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_tabController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(context.t('tradingPage.title')),
|
|
bottom: TabBar(
|
|
controller: _tabController,
|
|
tabs: [
|
|
Tab(text: context.t('tradingPage.pendingOrders')),
|
|
Tab(text: context.t('tradingPage.tradeRecords')),
|
|
],
|
|
),
|
|
),
|
|
body: TabBarView(
|
|
controller: _tabController,
|
|
children: [
|
|
_buildMyListings(),
|
|
_buildTransactionHistory(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildMyListings() {
|
|
return ListView.separated(
|
|
padding: const EdgeInsets.fromLTRB(20, 16, 20, 100),
|
|
itemCount: 3,
|
|
separatorBuilder: (_, __) => const SizedBox(height: 12),
|
|
itemBuilder: (context, index) {
|
|
final statuses = [
|
|
StatusTags.onSale(context),
|
|
StatusTags.completed(context),
|
|
StatusTags.cancelled(context),
|
|
];
|
|
return Container(
|
|
padding: AppSpacing.cardPadding,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.surface,
|
|
borderRadius: AppSpacing.borderRadiusMd,
|
|
border: Border.all(color: AppColors.borderLight),
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Container(
|
|
width: 48,
|
|
height: 48,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.primarySurface,
|
|
borderRadius: AppSpacing.borderRadiusSm,
|
|
),
|
|
child: Icon(Icons.confirmation_number_outlined,
|
|
color: AppColors.primary.withValues(alpha: 0.4), size: 22),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(['星巴克 \$25', 'Amazon \$50', 'Nike \$80'][index],
|
|
style: AppTypography.labelMedium),
|
|
const SizedBox(height: 4),
|
|
Row(
|
|
children: [
|
|
Text('${context.t('tradingPage.listPrice')} ', style: AppTypography.caption),
|
|
Text('\$${[21.25, 42.50, 68.00][index]}',
|
|
style: AppTypography.priceSmall.copyWith(fontSize: 14)),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
statuses[index],
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.gray50,
|
|
borderRadius: AppSpacing.borderRadiusSm,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text('${context.t('tradingPage.listTime')}: 2026/02/${9 - index}',
|
|
style: AppTypography.caption),
|
|
if (index == 0)
|
|
GestureDetector(
|
|
onTap: () {},
|
|
child: Text(context.t('tradingPage.cancelOrder'), style: AppTypography.labelSmall.copyWith(
|
|
color: AppColors.error,
|
|
)),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _buildTransactionHistory() {
|
|
return ListView.separated(
|
|
padding: const EdgeInsets.fromLTRB(20, 16, 20, 100),
|
|
itemCount: 6,
|
|
separatorBuilder: (_, __) => const SizedBox(height: 8),
|
|
itemBuilder: (context, index) {
|
|
final isBuy = index % 2 == 0;
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.surface,
|
|
borderRadius: AppSpacing.borderRadiusSm,
|
|
border: Border.all(color: AppColors.borderLight),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
width: 36,
|
|
height: 36,
|
|
decoration: BoxDecoration(
|
|
color: isBuy ? AppColors.successLight : AppColors.errorLight,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(
|
|
isBuy ? Icons.arrow_downward_rounded : Icons.arrow_upward_rounded,
|
|
size: 18,
|
|
color: isBuy ? AppColors.success : AppColors.error,
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
isBuy ? context.t('trading.buy') : context.t('trading.sell'),
|
|
style: AppTypography.labelMedium,
|
|
),
|
|
Text(
|
|
'品牌 ${index + 1} 礼品卡',
|
|
style: AppTypography.caption,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
'${isBuy ? "-" : "+"}\$${(index + 1) * 15}.00',
|
|
style: AppTypography.labelMedium.copyWith(
|
|
color: isBuy ? AppColors.textPrimary : AppColors.success,
|
|
),
|
|
),
|
|
Text('02/${10 - index} 14:${30 + index}',
|
|
style: AppTypography.caption),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|