Added core data models, repositories, and utilities

This commit is contained in:
Tomas Dvorak
2026-01-03 18:37:48 +01:00
parent 1639de69d4
commit 572fbb971c
17 changed files with 1248 additions and 0 deletions
@@ -0,0 +1,77 @@
import 'package:intl/intl.dart';
class DateTimeUtils {
static const int countdownDays = 1356;
static DateTime calculateEndDate(DateTime startDate) {
return startDate.add(const Duration(days: countdownDays));
}
static Duration calculateRemainingTime(DateTime endDate) {
return endDate.difference(DateTime.now());
}
static String formatCountdown(Duration duration) {
final days = duration.inDays;
final hours = duration.inHours % 24;
final minutes = duration.inMinutes % 60;
final seconds = duration.inSeconds % 60;
return '${days}d ${hours}h ${minutes}m ${seconds}s';
}
static String formatCountdownCompact(Duration duration) {
final days = duration.inDays;
final hours = duration.inHours % 24;
final minutes = duration.inMinutes % 60;
if (days > 0) {
return '${days}d ${hours}h';
} else if (hours > 0) {
return '${hours}h ${minutes}m';
} else {
return '${minutes}m';
}
}
static double calculateProgress(DateTime startDate, DateTime endDate) {
final now = DateTime.now();
final totalDuration = endDate.difference(startDate).inSeconds;
final elapsedDuration = now.difference(startDate).inSeconds;
if (elapsedDuration >= totalDuration) {
return 1.0;
}
return elapsedDuration / totalDuration;
}
static String formatDate(DateTime date) {
return DateFormat('MMM dd, yyyy').format(date);
}
static String formatDateTime(DateTime dateTime) {
return DateFormat('MMM dd, yyyy • HH:mm').format(dateTime);
}
static String formatRelativeTime(DateTime dateTime) {
final now = DateTime.now();
final difference = now.difference(dateTime);
if (difference.inSeconds < 60) {
return 'Just now';
} else if (difference.inMinutes < 60) {
return '${difference.inMinutes}m ago';
} else if (difference.inHours < 24) {
return '${difference.inHours}h ago';
} else if (difference.inDays < 7) {
return '${difference.inDays}d ago';
} else {
return formatDate(dateTime);
}
}
static bool isCountdownFinished(DateTime endDate) {
return DateTime.now().isAfter(endDate);
}
}
+87
View File
@@ -0,0 +1,87 @@
class Validators {
static String? validateEmail(String? value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
if (!emailRegex.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
}
static String? validatePassword(String? value) {
if (value == null || value.isEmpty) {
return 'Password is required';
}
if (value.length < 6) {
return 'Password must be at least 6 characters';
}
return null;
}
static String? validateUsername(String? value) {
if (value == null || value.isEmpty) {
return 'Username is required';
}
if (value.length < 3) {
return 'Username must be at least 3 characters';
}
if (value.length > 20) {
return 'Username must not exceed 20 characters';
}
final usernameRegex = RegExp(r'^[a-zA-Z0-9_]+$');
if (!usernameRegex.hasMatch(value)) {
return 'Username can only contain letters, numbers, and underscores';
}
return null;
}
static String? validateGoalTitle(String? value) {
if (value == null || value.isEmpty) {
return 'Goal title is required';
}
if (value.length > 100) {
return 'Goal title must not exceed 100 characters';
}
return null;
}
static String? validateGoalDescription(String? value) {
if (value != null && value.length > 500) {
return 'Description must not exceed 500 characters';
}
return null;
}
static String? validateGoalProgress(int? value) {
if (value == null) {
return 'Progress is required';
}
if (value < 0 || value > 100) {
return 'Progress must be between 0 and 100';
}
return null;
}
static String? validateRequired(String? value, String fieldName) {
if (value == null || value.isEmpty) {
return '$fieldName is required';
}
return null;
}
}