326 lines
9.5 KiB
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,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|