import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../../common/domain/metal_type.dart'; import '../../../common/widgets/prototype_ui.dart'; import '../../profile/application/price_color_theme.dart'; import '../../profile/application/profile_settings_controller.dart'; import '../data/mock_market_repository.dart'; import '../data/market_models.dart'; class MarketKlinePage extends ConsumerWidget { const MarketKlinePage({super.key, this.metalId, this.periodId}); final String? metalId; final String? periodId; @override Widget build(BuildContext context, WidgetRef ref) { final repo = ref.watch(mockMarketRepositoryProvider); final metal = _metalFromId(metalId) ?? MetalType.gold; final period = _periodFromId(periodId) ?? MarketPeriod.h24; final quote = repo.quoteFor(metal); final points = repo.chartFor(metal, period); final cs = ShadTheme.of(context).colorScheme; final palette = priceColorPalette( ref.watch(profileSettingsControllerProvider).priceColorMode, ); return Scaffold( backgroundColor: const Color(0xFFFBFAF7), appBar: AppBar( backgroundColor: const Color(0xFFFBFAF7), surfaceTintColor: Colors.transparent, elevation: 0, scrolledUnderElevation: 0, centerTitle: true, leading: IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.chevron_left, size: 20), ), title: Text( '${metal.label} K线', style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600), ), ), body: SafeArea( child: ListView( padding: const EdgeInsets.fromLTRB(0, 8, 0, 24), children: [ PrototypeFrame( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 4), PrototypeCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '¥', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: cs.foreground, ), ), const SizedBox(width: 2), Text( quote.spotPrice.toStringAsFixed(2), style: const TextStyle( fontSize: 29, fontWeight: FontWeight.w600, letterSpacing: -1, ), ), const SizedBox(width: 4), const Padding( padding: EdgeInsets.only(top: 8), child: Text( '元/克', style: TextStyle( fontSize: 12, color: Color(0xFF8A8780), ), ), ), ], ), const SizedBox(height: 6), Text( '${quote.changeAmount >= 0 ? '+' : ''}${quote.changeAmount.toStringAsFixed(2)} · ${quote.changePercent.toStringAsFixed(2)}%', style: TextStyle( color: quote.changeAmount >= 0 ? Color(palette.up) : Color(palette.down), fontSize: 13, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 12), Wrap( spacing: 8, runSpacing: 8, children: [ for (final p in MarketPeriod.values) PrototypePill( label: p.label, selected: p == period, onTap: () => Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (_) => MarketKlinePage( metalId: metal.id, periodId: p.id, ), ), ), ), ], ), const SizedBox(height: 10), Row( children: [ _Ohlc('开', points.first.open), const SizedBox(width: 18), _Ohlc( '高', points .map((e) => e.high) .reduce((a, b) => a > b ? a : b), ), const SizedBox(width: 18), _Ohlc( '低', points .map((e) => e.low) .reduce((a, b) => a < b ? a : b), ), const SizedBox(width: 18), _Ohlc('收', points.last.close), ], ), const SizedBox(height: 12), SizedBox( height: 300, child: ClipRRect( borderRadius: BorderRadius.circular(10), child: PrototypeLineChart( values: points .map((p) => p.close) .toList(growable: false), ), ), ), const SizedBox(height: 10), Text( '${quote.basisLabel} · ${_timeLabel(quote.updatedAt)}', textAlign: TextAlign.center, style: TextStyle( fontSize: 11, color: cs.mutedForeground, ), ), ], ), ), ], ), ), ], ), ), ); } } class _Ohlc extends StatelessWidget { const _Ohlc(this.label, this.value); final String label; final double value; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle(fontSize: 12, color: Color(0xFF8A8780)), ), const SizedBox(height: 2), Text( value.toStringAsFixed(2), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600), ), ], ); } } MetalType? _metalFromId(String? id) { return switch (id) { 'gold' => MetalType.gold, 'platinum' => MetalType.platinum, 'silver' => MetalType.silver, _ => null, }; } MarketPeriod? _periodFromId(String? id) { return switch (id) { '24h' => MarketPeriod.h24, '5d' => MarketPeriod.d5, '1m' => MarketPeriod.m1, '3m' => MarketPeriod.m3, '1y' => MarketPeriod.y1, _ => null, }; } String _timeLabel(DateTime value) { return '${value.hour.toString().padLeft(2, '0')}:${value.minute.toString().padLeft(2, '0')}'; }