생성 때 고른 행성 형태·색 표시 · HOME 주간 정보

This commit is contained in:
Sn-Kinos
2026-10-05 23:21:44 +09:00
parent 55424bd4a2
commit c8c1a1ae67
40 changed files with 688 additions and 40 deletions
@@ -0,0 +1,110 @@
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).
///
/// 🟡 **배치는 임시다.** 기준 화면 「REFINE v5A · HOME · Default」 를 아직 실측하지 못해(당사 사본에
/// 없고 원본 파일은 로그인 필요) 정보 위계 v1.0 §7 「프레임 실측과 무관하게 반드시 포함」에 따라
/// 값만 먼저 싣는다. 자리 · 모양은 해석 확인 요청 영역A 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;
Widget row(String label, Widget value) => Padding(
padding: const EdgeInsets.symmetric(vertical: AppSpace.s2),
child: Row(
children: [
Expanded(child: Text(label, style: _label)),
value,
],
),
);
Text text(String s) => Text(s, style: _value);
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)}',
),
),
],
),
);
}
}