Files
fanuzu/app/lib/features/my/widgets/profile_card.dart
T

109 lines
3.5 KiB
Dart

import 'package:flutter/material.dart';
import '../../../core/theme/tokens.dart';
import '../../../core/ui/app_icons.dart';
import '../my_data.dart';
import 'my_cards.dart';
import '../../../core/i18n/app_locale.dart';
/// 프로필 카드 오버레이 — 시안 `374:15738`(명세 `549:22058`).
///
/// 닫기 · 프로필 사진 80 · 닉네임 · 티어 카드 · 통계 카드 · 공유 4종(36 원형 아이콘).
/// *인스타 공유 · 틱톡 공유 · X 공유 · 링크 복사*
class ProfileCard extends StatelessWidget {
const ProfileCard({super.key, required this.profile, required this.onShare});
final MyProfile profile;
final void Function(String target) onShare;
/// 공유 대상과 시안 아이콘. 명세가 적은 순서 그대로다.
static List<String> get shareTargets => [
appL10n.shareInstagram,
appL10n.shareTiktok,
'X',
appL10n.shareCopyLink,
];
static const _shareIcons = [
'assets/figma/share-instagram.png',
'assets/figma/share-tiktok.png',
'assets/figma/share-x.png',
'assets/figma/share-link.png',
];
ImageProvider<Object> get _photo {
final url = profile.photoUrl;
return url == null || url.isEmpty
? const AssetImage('assets/figma/avatar-sample.png')
: NetworkImage(url);
}
@override
Widget build(BuildContext context) => Padding(
padding: const EdgeInsets.fromLTRB(16, 20, 16, 28),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Align(
alignment: Alignment.centerRight,
child: IconButton(
tooltip: context.l10n.commonClose,
onPressed: () => Navigator.of(context).maybePop(),
padding: EdgeInsets.zero,
constraints: const BoxConstraints.tightFor(width: 24, height: 24),
icon: const ImageIcon(
AppIcons.x,
size: 24,
color: AppColors.onCosmic,
),
),
),
const SizedBox(height: 24),
CircleAvatar(
radius: 40,
backgroundColor: AppColors.cosmicSurfaceRaised,
backgroundImage: _photo,
),
const SizedBox(height: 20),
Text(profile.nickname, style: myText(20, FontWeight.w600)),
const SizedBox(height: 24),
MyTierCard(profile: profile),
const SizedBox(height: 19),
MyStatsCard(profile: profile),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (final (i, target) in shareTargets.indexed) ...[
if (i > 0) const SizedBox(width: 16),
Semantics(
button: true,
label: target,
child: Tooltip(
message: target,
child: GestureDetector(
onTap: () => onShare(target),
child: ClipOval(
child: Container(
width: 36,
height: 36,
color: Colors.black,
alignment: Alignment.center,
child: Image.asset(
_shareIcons[i],
// X 원본은 21 짜리 글리프라 검정 원 안에 그대로 둔다.
width: i == 2 ? 21 : 36,
height: i == 2 ? 21 : 36,
),
),
),
),
),
),
],
],
),
],
),
);
}