import 'package:flutter/material.dart'; import '../../../core/i18n/app_locale.dart'; import '../../../core/theme/tokens.dart'; import '../home_data.dart'; import '../home_screen.dart' show formatPop; /// HOME 주간 정보 — 발주사 9/9 검토회신 2항 · HOME 정보위계 v1.0 §2 의 2 · 3 · 6 · 7번(A-37). /// /// 🟡 **배치는 임시다.** 9/7 회신이 기준으로 든 「REFINE v5A · HOME · Default」 는 계약 시점 사본 /// Figma 에 없다(전 페이지 이름 · 문구 검색, 2026-10-06). 정보 위계 v1.0 §7 「프레임 실측과 무관하게 반드시 /// 포함」에 따라 값만 먼저 싣고, 자리 · 모양은 해석 확인 요청 Q-A16 회신을 따른다. /// 값의 뜻은 [HomeWeekly] — 모르는 값은 0 으로 채우지 않고 「—」. class HomeWeeklyCard extends StatelessWidget { const HomeWeeklyCard({super.key, required this.weekly}); final HomeWeekly weekly; static const _label = TextStyle( fontFamily: AppFonts.body, fontSize: 13, height: 18 / 13, color: AppColors.onCosmicVariant, ); static const _value = TextStyle( fontFamily: AppFonts.body, fontSize: 14, fontWeight: FontWeight.w600, height: 18 / 14, color: AppColors.onCosmic, ); static String _signed(num v) => '${v >= 0 ? '+' : '−'}${formatPop(v.abs().round())}'; @override Widget build(BuildContext context) { final l10n = context.l10n; final w = weekly; final change = w.rankChange; // 라벨 2 : 값 3 으로 나눈다 — 값이 폭을 다 차지하면 긴 언어(es)에서 라벨이 0 폭이 되어 // 한 글자씩 줄바꿈된다(10/8 r11 「Mis POP」). 넘치면 둘 다 단어 단위로 줄바꿈한다. Widget row(String label, Widget value) => Padding( padding: const EdgeInsets.symmetric(vertical: AppSpace.s2), child: Row( children: [ Expanded(flex: 2, child: Text(label, style: _label)), const SizedBox(width: AppSpace.s2), Flexible( flex: 3, child: Align(alignment: Alignment.centerRight, child: value), ), ], ), ); Text text(String s) => Text(s, style: _value, textAlign: TextAlign.end); return Container( padding: const EdgeInsets.symmetric( horizontal: AppSpace.s4, vertical: AppSpace.s2, ), decoration: BoxDecoration( color: AppColors.cosmicSurfaceContainer, borderRadius: BorderRadius.circular(AppRadius.lg), border: Border.all(color: AppColors.cosmicOutline), ), child: Column( children: [ row( l10n.homeWeeklyRank, Row( mainAxisSize: MainAxisSize.min, children: [ text(w.rank == null ? '—' : l10n.homeWeeklyRankValue('${w.rank}')), if (change != null && change != 0) ...[ const SizedBox(width: AppSpace.s1), Text( '${change > 0 ? '▲' : '▼'}${change.abs()}', style: _value.copyWith( fontSize: 12, color: change > 0 ? AppColors.cosmicAccent : AppColors.cosmicBlue, ), ), ], ], ), ), // 두 축 각각 — 단일 백분율로 합치지 않는다(§3 4번). row( l10n.homeWeeklyGrowth, text( '${w.weekGrowthPop == null ? '—' : _signed(w.weekGrowthPop!)} POP · ' '${w.weekSfpi == null ? '—' : _signed(w.weekSfpi!)} sFPI', ), ), row( l10n.homeWeeklyMine, text( '${w.myWeekPop == null ? '—' : formatPop(w.myWeekPop!.round())} POP' '${w.myShare == null ? '' : ' · ${(w.myShare! * 100).toStringAsFixed(1)}%'}', ), ), row( l10n.homeWeeklyBalance, text( '${l10n.popKindGeneral} ${formatPop(w.generalPop)} · ' '${l10n.popKindContribution} ${formatPop(w.supportPop)}', ), ), ], ), ); } }