Files
fanuzu/app/lib/features/my/tier_screens.dart
T

227 lines
7.6 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/theme/tokens.dart';
import '../home/home_screen.dart' show formatPop;
import 'my_data.dart';
import 'widgets/my_cards.dart';
import '../../core/i18n/app_locale.dart';
/// 티어 정보 — 화면 대조 원장 F6 · Figma `373:633256`.
///
/// 명세 `549:22185` — *티어별 이미지 · 티어명 · 기준치 · **티어가 낮은 순으로 소팅***
///
/// C-18 — 기준치는 **레벨 구간**이다. 누적 기여 POP 문턱과 칭호별 권한·보상은 적지
/// 않는다. Passport Tier(B-65)는 별개 체계라 따로 늘어놓는다.
class TierInfoScreen extends StatelessWidget {
const TierInfoScreen({super.key});
@override
Widget build(BuildContext context) {
// 시안 `373:633256` 한 줄 — 새싹 80 · 간격 17 · 이름 20/500 · 기준 12/400 #84868e ·
// 위아래 12 · 밑줄 #1b1c1c.
Widget row(String label, String note, {bool sprout = true}) => Container(
margin: const EdgeInsets.only(bottom: 20),
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Color(0xFF1B1C1C))),
),
child: Row(
children: [
SizedBox(
width: 80,
height: 80,
child: sprout
? Image.asset('assets/figma/icon-tier-sprout.png')
: null,
),
const SizedBox(width: 17),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: myText(20, FontWeight.w500)),
if (note.isNotEmpty)
Text(
note,
style: myText(
12,
FontWeight.w400,
color: const Color(0xFF84868E),
),
),
],
),
),
],
),
);
return Scaffold(
appBar: AppBar(title: Text(context.l10n.tierInfoTitle)),
body: ListView(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 0),
children: [
Text.rich(
TextSpan(
style: myText(18, FontWeight.w500),
children: [
TextSpan(text: context.l10n.tierPromptPrefix),
TextSpan(
text: context.l10n.tierPromptRank,
style: TextStyle(color: AppColors.cosmicAccent),
),
TextSpan(text: context.l10n.tierPromptSuffix),
],
),
),
const SizedBox(height: 20),
// 낮은 순으로. LevelTitle 선언 순서가 곧 낮은 순이다. 기준치는 레벨 구간(C-18).
for (final title in LevelTitle.values)
row('${title.label} TIER', title.rangeLabel),
// Passport Tier 는 레벨과 별개 체계다(B-65 · FR-MY-01). 시안에 없는 구획이다.
Text('PASSPORT', style: myText(16, FontWeight.w600)),
const SizedBox(height: 4),
Text(
context.l10n.tierPassportNote,
style: myText(12, FontWeight.w400, color: const Color(0xFF84868E)),
),
const SizedBox(height: 8),
for (final tier in PassportTier.values)
row(tier.label, '', sprout: false),
],
),
);
}
}
/// 티어 상세 — 화면 대조 원장 F6 · Figma `494:16177`.
///
/// 명세 `549:22206` — *갤럭시에서 선택된 기본 행성의 티어를 메인으로 상단에 위치 ·*
/// *나머지 행성 티어는 티어 높은순으로 소팅*
///
/// 칭호는 개인 레벨에서만 나오므로(C-18) 행성별로는 **기여 실적(POP)만** 보인다.
class TierDetailScreen extends StatelessWidget {
const TierDetailScreen({super.key, required this.tiers});
final List<PlanetTier> tiers;
/// 기본 행성이 맨 앞, 나머지는 기여 POP 높은 순.
List<PlanetTier> get ordered {
final primary = tiers.where((p) => p.isPrimary).toList();
final rest = tiers.where((p) => !p.isPrimary).toList()
..sort((a, b) => b.contributedPop.compareTo(a.contributedPop));
return [...primary, ...rest];
}
@override
Widget build(BuildContext context) {
final list = ordered;
final top = list.fold<int>(
0,
(m, p) => p.contributedPop > m ? p.contributedPop : m,
);
// 시안 `494:16177` — 기본 행성 카드(#19191c · 분홍 획) · 구분선 #2c2c2c · 나머지 카드.
// 행성별 칭호는 두지 않는다(C-18) — 시안의 「GLOW TIER」 줄은 비우고 기여 실적만 그린다.
return Scaffold(
appBar: AppBar(title: const Text('TIER')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
for (final (i, planet) in list.indexed) ...[
if (i > 0) const SizedBox(height: 16),
_PlanetCard(
planet: planet,
progress: top == 0 ? 0 : planet.contributedPop / top,
),
if (i == 0 && planet.isPrimary && list.length > 1) ...[
const SizedBox(height: 16),
const SizedBox(
height: 1,
child: ColoredBox(color: MyColors.divider),
),
],
],
],
),
);
}
}
/// 행성 한 장 — 행성 60 + 이름 12/600 · 진행 바 · 「누적 기여 / N POP」.
class _PlanetCard extends StatelessWidget {
const _PlanetCard({required this.planet, required this.progress});
final PlanetTier planet;
final double progress;
@override
Widget build(BuildContext context) => Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: planet.isPrimary
? BoxDecoration(
color: MyColors.card,
borderRadius: BorderRadius.circular(AppRadius.lg),
border: Border.all(color: AppColors.cosmicAccent),
)
: null,
child: Row(
children: [
SizedBox(
width: 60,
child: Column(
children: [
Image.asset(
'assets/figma/my-planet-1.png',
width: 60,
height: 60,
),
Text(
planet.fandomName,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontFamily: AppFonts.body,
fontSize: 12,
fontWeight: FontWeight.w600,
height: 1,
color: AppColors.onCosmic,
),
),
],
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MyProgressBar(value: progress),
const SizedBox(height: 8),
Row(
children: [
Text(
context.l10n.tierTotalContribution,
style: myText(
12,
FontWeight.w500,
color: AppColors.cosmicAccent,
),
),
const Spacer(),
Text(
'${formatPop(planet.contributedPop)} POP',
style: myText(
12,
FontWeight.w500,
color: AppColors.cosmicAccent,
),
),
],
),
],
),
),
],
),
);
}