Files
Tracker/lib/widgets/scripture_card.dart
Sterlen b4b2bfe749 feat: Implement husband features and fix iOS Safari web startup
Implement initial features for husband's companion app, including mock data
service and husband notes screen. Refactor scripture and cycle services
for improved stability and testability. Address iOS Safari web app
startup issue by removing deprecated initialization.

- Implemented MockDataService and HusbandNotesScreen.
- Converted _DashboardTab and DevotionalScreen to StatefulWidgets for robust
  scripture provider initialization.
- Refactored CycleService to use immutable CycleInfo class, reducing UI rebuilds.
- Removed deprecated window.flutterConfiguration from index.html, resolving
  Flutter web app startup failure on iOS Safari.
- Updated and fixed related tests.
2025-12-26 22:40:52 -06:00

194 lines
6.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import '../theme/app_theme.dart';
import '../models/cycle_entry.dart';
class ScriptureCard extends StatelessWidget {
final String verse;
final String reference;
final String? translation;
final CyclePhase phase;
final VoidCallback? onTranslationTap;
const ScriptureCard({
super.key,
required this.verse,
required this.reference,
this.translation,
required this.phase,
this.onTranslationTap,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: _getGradientColors(context, phase),
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isDark
? Colors.white.withOpacity(0.05)
: Colors.black.withOpacity(0.05)),
boxShadow: [
BoxShadow(
color: _getPhaseColor(phase).withOpacity(isDark ? 0.05 : 0.15),
blurRadius: 15,
offset: const Offset(0, 8),
),
],
),
child: Material(
color: Colors.transparent,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Scripture icon
Row(
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: (isDark ? Colors.white : Colors.black)
.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
Icons.menu_book_outlined,
size: 18,
color: isDark
? Colors.white70
: AppColors.charcoal.withOpacity(0.8),
),
),
const SizedBox(width: 8),
Text(
'Today\'s Verse',
style: theme.textTheme.labelLarge?.copyWith(
fontSize: 12,
color: isDark
? Colors.white60
: AppColors.charcoal.withOpacity(0.7),
letterSpacing: 0.5,
),
),
],
),
const SizedBox(height: 16),
// Verse
Text(
'"$verse"',
style: scriptureStyle(context, fontSize: 17),
),
const SizedBox(height: 12),
// Reference & Translation
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'$reference',
style: scriptureRefStyle(context)
.copyWith(fontSize: 13, fontWeight: FontWeight.w600),
),
if (translation != null)
InkWell(
onTap: onTranslationTap,
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 6),
decoration: BoxDecoration(
color: (isDark ? Colors.white : Colors.black)
.withOpacity(0.05),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: (isDark ? Colors.white : Colors.black)
.withOpacity(0.1),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
translation!,
style: scriptureRefStyle(context).copyWith(
fontSize: 10,
fontWeight: FontWeight.w800,
letterSpacing: 0.8,
),
),
const SizedBox(width: 4),
Icon(
Icons.swap_horiz,
size: 14,
color: isDark
? Colors.white38
: AppColors.warmGray,
),
],
),
),
),
],
),
],
),
),
),
);
}
List<Color> _getGradientColors(BuildContext context, CyclePhase phase) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final baseColor = isDark ? const Color(0xFF1E1E1E) : AppColors.cream;
switch (phase) {
case CyclePhase.menstrual:
return [
AppColors.menstrualPhase.withOpacity(isDark ? 0.15 : 0.6),
baseColor,
];
case CyclePhase.follicular:
return [
AppColors.follicularPhase.withOpacity(isDark ? 0.15 : 0.3),
baseColor,
];
case CyclePhase.ovulation:
return [
AppColors.ovulationPhase.withOpacity(isDark ? 0.15 : 0.5),
baseColor,
];
case CyclePhase.luteal:
return [
AppColors.lutealPhase.withOpacity(isDark ? 0.15 : 0.3),
baseColor,
];
}
}
Color _getPhaseColor(CyclePhase phase) {
switch (phase) {
case CyclePhase.menstrual:
return AppColors.menstrualPhase;
case CyclePhase.follicular:
return AppColors.follicularPhase;
case CyclePhase.ovulation:
return AppColors.ovulationPhase;
case CyclePhase.luteal:
return AppColors.lutealPhase;
}
}
}