inou/app/lib/features/static/invite_page.dart

326 lines
9.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:inou_app/design/inou_theme.dart';
import 'package:inou_app/design/inou_text.dart';
import 'package:inou_app/design/widgets/widgets.dart';
/// Invite a friend page
class InvitePage extends StatefulWidget {
const InvitePage({super.key});
@override
State<InvitePage> createState() => _InvitePageState();
}
class _InvitePageState extends State<InvitePage> {
final _emailController = TextEditingController();
final List<String> _invitedEmails = [];
bool _isSending = false;
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: Check if user is logged in, if not show signup prompt
final isLoggedIn = false; // Placeholder
return InouPage(
currentRoute: '/invite',
maxWidth: 600,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 48),
Text(
'Invite a friend',
style: InouText.pageTitle,
),
const SizedBox(height: 16),
Text(
'Know someone who could benefit from understanding their health better? Invite them to inou.',
style: InouText.body.copyWith(
color: InouTheme.textMuted,
fontWeight: FontWeight.w300,
),
),
const SizedBox(height: 48),
if (!isLoggedIn) ...[
_buildSignupPrompt(context),
] else ...[
_buildInviteForm(),
],
const SizedBox(height: 48),
// Why invite section
_buildWhyInvite(),
const SizedBox(height: 48),
],
),
);
}
Widget _buildSignupPrompt(BuildContext context) {
return Container(
padding: const EdgeInsets.all(32),
decoration: BoxDecoration(
color: InouTheme.bgCard,
borderRadius: InouTheme.borderRadiusLg,
border: Border.all(color: InouTheme.border),
),
child: Column(
children: [
Icon(
Icons.person_add_outlined,
size: 48,
color: InouTheme.accent,
),
const SizedBox(height: 16),
Text(
'Sign in to invite friends',
style: InouText.h3,
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
'Create an account or sign in to share inou with people you care about.',
style: InouText.body.copyWith(
color: InouTheme.textMuted,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InouButton(
text: 'Sign up',
onPressed: () => Navigator.pushNamed(context, '/signup'),
),
const SizedBox(width: 12),
InouButton(
text: 'Log in',
variant: ButtonVariant.secondary,
onPressed: () => Navigator.pushNamed(context, '/login'),
),
],
),
],
),
);
}
Widget _buildInviteForm() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Email input
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: InouTextField(
label: 'Friend\'s email',
controller: _emailController,
placeholder: 'friend@example.com',
keyboardType: TextInputType.emailAddress,
),
),
const SizedBox(width: 12),
InouButton(
text: _isSending ? 'Sending...' : 'Send invite',
onPressed: _isSending ? null : _handleSendInvite,
),
],
),
const SizedBox(height: 24),
// Share link
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: InouTheme.bg,
borderRadius: InouTheme.borderRadiusMd,
border: Border.all(color: InouTheme.border),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Or share your invite link',
style: InouText.labelCaps.copyWith(
color: InouTheme.textMuted,
),
),
const SizedBox(height: 4),
Text(
'https://inou.com/join/abc123',
style: InouText.body.copyWith(
fontFamily: 'SF Mono',
fontSize: 13,
),
),
],
),
),
IconButton(
icon: const Icon(Icons.copy, size: 20),
color: InouTheme.accent,
onPressed: () {
Clipboard.setData(const ClipboardData(
text: 'https://inou.com/join/abc123',
));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Link copied!'),
backgroundColor: InouTheme.success,
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 2),
),
);
},
),
],
),
),
// Sent invites
if (_invitedEmails.isNotEmpty) ...[
const SizedBox(height: 32),
Text(
'Invites sent',
style: InouText.h3,
),
const SizedBox(height: 12),
...(_invitedEmails.map((email) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
Icon(
Icons.check_circle,
size: 16,
color: InouTheme.success,
),
const SizedBox(width: 8),
Text(email, style: InouText.body),
],
),
))),
],
],
);
}
Widget _buildWhyInvite() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Why invite?',
style: InouText.sectionTitle.copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 24),
_buildBenefitItem(
Icons.favorite_outline,
'Help someone you care about',
'Whether they\'re managing a chronic condition, caring for a family member, or just want to understand their health better — inou can help.',
),
const SizedBox(height: 20),
_buildBenefitItem(
Icons.people_outline,
'Build your health circle',
'When family members use inou, sharing relevant health information becomes seamless and secure.',
),
const SizedBox(height: 20),
_buildBenefitItem(
Icons.card_giftcard_outlined,
'Early access perks',
'Friends you invite get priority access to new features and may qualify for special pricing.',
),
],
);
}
Widget _buildBenefitItem(IconData icon, String title, String description) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: InouTheme.accentLight,
borderRadius: BorderRadius.circular(10),
),
child: Icon(icon, color: InouTheme.accent, size: 20),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: InouText.h3.copyWith(fontSize: 16)),
const SizedBox(height: 4),
Text(
description,
style: InouText.body.copyWith(
color: InouTheme.textMuted,
fontWeight: FontWeight.w300,
height: 1.6,
),
),
],
),
),
],
);
}
Future<void> _handleSendInvite() async {
final email = _emailController.text.trim();
if (email.isEmpty || !email.contains('@')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('Please enter a valid email address'),
backgroundColor: InouTheme.danger,
behavior: SnackBarBehavior.floating,
),
);
return;
}
setState(() => _isSending = true);
// TODO: Implement actual invite sending
await Future.delayed(const Duration(seconds: 1));
if (mounted) {
setState(() {
_isSending = false;
_invitedEmails.add(email);
});
_emailController.clear();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Invite sent to $email!'),
backgroundColor: InouTheme.success,
behavior: SnackBarBehavior.floating,
),
);
}
}
}