Figma 설명 프레임 반영 — 로그인·온보딩·스플래시 · HOME · GALAXY · 퀘스트·이클립스·알림
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/theme/tokens.dart';
|
||||
import '../planet_data.dart';
|
||||
|
||||
/// 팬덤 규모 칩 — Figma 「대형 팬덤」 `#AEC054` · 「중형 / 소형 팬덤」 `#54C07D`(바탕 10%, r4).
|
||||
/// 행성 상세 히어로는 12/500 + 1px 테두리, GALAXY 목록은 10/500.
|
||||
class FandomSizeBadge extends StatelessWidget {
|
||||
const FandomSizeBadge({super.key, required this.members, this.large = false});
|
||||
|
||||
final int members;
|
||||
|
||||
/// 행성 상세 히어로 크기(12 · 테두리).
|
||||
final bool large;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = FandomSize.of(members);
|
||||
final color = size == FandomSize.large
|
||||
? const Color(0xFFAEC054)
|
||||
: const Color(0xFF54C07D);
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.1),
|
||||
border: large ? Border.all(color: color) : null,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
size.label,
|
||||
style: TextStyle(
|
||||
fontFamily: AppFonts.body,
|
||||
fontSize: large ? 12 : 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import '../../../core/ui/live_planet.dart';
|
||||
import '../../../core/data/planet_visual_state.dart';
|
||||
import '../../home/home_screen.dart' show formatPop;
|
||||
import '../../../core/i18n/app_locale.dart';
|
||||
import 'fandom_size_badge.dart';
|
||||
|
||||
/// 행성 상세 히어로 — 시안 `373:441117` 의 `Frame 1984081117`(375×543).
|
||||
///
|
||||
@@ -24,15 +25,20 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
this.nebula = false,
|
||||
this.onHeroParticipate,
|
||||
this.onJoin,
|
||||
this.isOwner = false,
|
||||
this.onOpenHistory,
|
||||
this.fandomId = '',
|
||||
this.watchPlanet = noPlanetWatch,
|
||||
this.stage,
|
||||
this.ownerName,
|
||||
this.ownerPhoto,
|
||||
this.sizeLabel,
|
||||
this.onOpenOwner,
|
||||
});
|
||||
|
||||
/// 개설자 줄을 눌렀을 때 — Figma `544:19765` 「프로필 및 닉네임 클릭 시 해당 사용자의 MY로 이동」.
|
||||
/// 타인 프로필 화면(`549:21969`)이 생기면 연결한다(3차 MY). null 이면 누르지 않는다.
|
||||
final VoidCallback? onOpenOwner;
|
||||
|
||||
final VoidCallback? onOpenHistory;
|
||||
final String fandomId;
|
||||
final PlanetWatch watchPlanet;
|
||||
@@ -46,6 +52,9 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
/// 알약을 눌렀을 때 — 「가입하기」면 가입, 「가입중」이면 탈퇴 시트. null 이면 상태만 보인다.
|
||||
final VoidCallback? onJoin;
|
||||
|
||||
/// 내가 만든 행성이면 가입 알약을 숨긴다(Figma `544:19765` 「가입 버튼 - 내가 생성했을 경우 hide」).
|
||||
final bool isOwner;
|
||||
|
||||
/// 성운 상세(`373:442708`)는 규모 칩과 FPI 줄이 없다.
|
||||
final bool nebula;
|
||||
|
||||
@@ -56,9 +65,6 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
/// 개설자 사진(URL 또는 에셋). 없으면 회색 원.
|
||||
final String? ownerPhoto;
|
||||
|
||||
/// 팬덤 규모 라벨. 정책 §P-08 등급명이 붙기 전까지 시안 문구를 쓴다.
|
||||
final String? sizeLabel;
|
||||
|
||||
static const double designHeight = 543;
|
||||
|
||||
/// 시안의 상태 표시줄 + 내비 높이. 본문은 그 아래 439 안에 가운데 놓인다.
|
||||
@@ -74,7 +80,8 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 1인당 화력 — 시안 「1.44」. 총 FPI 를 멤버 수로 나눈 값이며 정책 확정 전 표시용이다.
|
||||
// 1인당 화력 — 시안 「1.44」. Figma `544:19765` 정의(「모든 포인트 획득, 소비 활동 및 1인당 활동 값을
|
||||
// 집계한 값」)와 FPI 원천(C-34 활동 기준)이 갈려 해석 확인 중(전수대조 영역A Q-A23). 회신 전 임시로 총 FPI ÷ 멤버 수.
|
||||
final perHead = members == 0 ? 0.0 : totalFpi / members;
|
||||
const info = Color(0xFFDEDEDE);
|
||||
|
||||
@@ -111,31 +118,36 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (ownerName case final owner?) ...[
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 13,
|
||||
backgroundColor: const Color(0xFFD9D9D9),
|
||||
backgroundImage: switch (ownerPhoto) {
|
||||
final p? when p.startsWith('http') => NetworkImage(p),
|
||||
final p? => AssetImage(p),
|
||||
null => null,
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 9),
|
||||
Text(
|
||||
owner,
|
||||
style: const TextStyle(
|
||||
fontFamily: AppFonts.display,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 16,
|
||||
height: 1.3,
|
||||
letterSpacing: -0.4,
|
||||
color: AppColors.onCosmic,
|
||||
GestureDetector(
|
||||
onTap: onOpenOwner,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 13,
|
||||
backgroundColor: const Color(0xFFD9D9D9),
|
||||
backgroundImage: switch (ownerPhoto) {
|
||||
final p? when p.startsWith('http') => NetworkImage(
|
||||
p,
|
||||
),
|
||||
final p? => AssetImage(p),
|
||||
null => null,
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 9),
|
||||
Text(
|
||||
owner,
|
||||
style: const TextStyle(
|
||||
fontFamily: AppFonts.display,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 16,
|
||||
height: 1.3,
|
||||
letterSpacing: -0.4,
|
||||
color: AppColors.onCosmic,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
],
|
||||
@@ -159,21 +171,8 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (!nebula) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0x1A54C07D),
|
||||
border: Border.all(color: const Color(0xFF54C07D)),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
sizeLabel ?? context.l10n.planetSizeMedium,
|
||||
style: _body(12, const Color(0xFF54C07D)),
|
||||
),
|
||||
),
|
||||
// 소형 · 중형 · 대형 — 가입자 수 기준(Figma `544:19765`).
|
||||
FandomSizeBadge(members: members, large: true),
|
||||
const SizedBox(width: 4),
|
||||
],
|
||||
Image.asset(
|
||||
@@ -227,31 +226,32 @@ class PlanetDetailHero extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
Semantics(
|
||||
button: onJoin != null,
|
||||
child: GestureDetector(
|
||||
onTap: onJoin,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF1A1A1A),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
child: Text(
|
||||
joined
|
||||
? context.l10n.planetJoined
|
||||
: context.l10n.planetJoin,
|
||||
style: _body(
|
||||
14,
|
||||
const Color(0xFFD5D7D9),
|
||||
).copyWith(letterSpacing: -0.35),
|
||||
if (!isOwner)
|
||||
Semantics(
|
||||
button: onJoin != null,
|
||||
child: GestureDetector(
|
||||
onTap: onJoin,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF1A1A1A),
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
child: Text(
|
||||
joined
|
||||
? context.l10n.planetJoined
|
||||
: context.l10n.planetJoin,
|
||||
style: _body(
|
||||
14,
|
||||
const Color(0xFFD5D7D9),
|
||||
).copyWith(letterSpacing: -0.35),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user