petsHero-AI/lib/features/profile/profile_screen.dart
2026-03-09 11:41:49 +08:00

276 lines
7.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_spacing.dart';
import '../../core/theme/app_typography.dart';
import '../../shared/widgets/top_nav_bar.dart';
/// Profile screen - matches Pencil KXeow
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.background,
appBar: PreferredSize(
preferredSize: const Size.fromHeight(56),
child: TopNavBar(
title: 'Profile',
credits: '1,280',
onCreditsTap: () => Navigator.of(context).pushNamed('/recharge'),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(
AppSpacing.screenPadding,
AppSpacing.xxl,
AppSpacing.screenPadding,
AppSpacing.screenPaddingLarge,
),
child: Column(
children: [
_ProfileHeader(
userName: 'Alex Johnson',
uid: 'UID 84920133',
),
const SizedBox(height: AppSpacing.xl),
_BalanceCard(
balance: '1,280',
onRecharge: () => Navigator.of(context).pushNamed('/recharge'),
),
const SizedBox(height: AppSpacing.xxl),
_MenuSection(
items: [
_MenuItem(
title: 'Credit Store',
icon: LucideIcons.chevron_right,
onTap: () => Navigator.of(context).pushNamed('/recharge'),
),
_MenuItem(
title: 'Settings',
icon: LucideIcons.chevron_right,
onTap: () {},
),
],
),
],
),
),
);
}
}
class _ProfileHeader extends StatelessWidget {
const _ProfileHeader({
required this.userName,
required this.uid,
});
final String userName;
final String uid;
@override
Widget build(BuildContext context) {
return Container(
height: 220,
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 80,
height: 80,
decoration: BoxDecoration(
color: AppColors.border,
borderRadius: BorderRadius.circular(40),
border: Border.all(
color: AppColors.primaryLight,
width: 2,
),
),
child: const Icon(
LucideIcons.user,
size: 40,
color: AppColors.textSecondary,
),
),
const SizedBox(height: AppSpacing.lg),
Text(
userName,
style: AppTypography.bodyLarge.copyWith(
color: AppColors.textPrimary,
),
),
const SizedBox(height: AppSpacing.lg),
Container(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
vertical: AppSpacing.sm,
),
decoration: BoxDecoration(
color: AppColors.surfaceAlt,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.border),
),
child: Text(
uid,
style: AppTypography.caption.copyWith(
color: AppColors.textSecondary,
),
),
),
],
),
);
}
}
class _BalanceCard extends StatelessWidget {
const _BalanceCard({
required this.balance,
required this.onRecharge,
});
final String balance;
final VoidCallback onRecharge;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.xxl,
vertical: AppSpacing.xl,
),
decoration: BoxDecoration(
color: AppColors.surface,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: AppColors.shadowLight,
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AVAILABLE BALANCE',
style: AppTypography.label.copyWith(
color: AppColors.textSecondary,
),
),
const SizedBox(height: AppSpacing.sm),
Text(
balance,
style: AppTypography.bodyLarge.copyWith(
fontSize: 24,
fontWeight: FontWeight.w700,
color: AppColors.primary,
),
),
],
),
GestureDetector(
onTap: onRecharge,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 14,
vertical: AppSpacing.md,
),
decoration: BoxDecoration(
color: AppColors.primary,
borderRadius: BorderRadius.circular(12),
),
child: Text(
'Recharge',
style: AppTypography.bodyRegular.copyWith(
color: AppColors.surface,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
);
}
}
class _MenuSection extends StatelessWidget {
const _MenuSection({required this.items});
final List<_MenuItem> items;
@override
Widget build(BuildContext context) {
return Column(
children: items
.map(
(item) => Padding(
padding: const EdgeInsets.only(bottom: AppSpacing.md),
child: _MenuItem(
title: item.title,
icon: item.icon,
onTap: item.onTap,
),
),
)
.toList(),
);
}
}
class _MenuItem extends StatelessWidget {
const _MenuItem({
required this.title,
required this.icon,
required this.onTap,
});
final String title;
final IconData icon;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.xl,
vertical: 14,
),
decoration: BoxDecoration(
color: AppColors.surface,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: AppColors.shadowLight,
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: AppTypography.bodyRegular.copyWith(
color: AppColors.textPrimary,
),
),
Icon(icon, size: 20, color: AppColors.textMuted),
],
),
),
);
}
}