Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:label="Athletix"
android:name="${applicationName}"
Expand Down
4 changes: 4 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photo library to select profile pictures</string>
<key>NSCameraUsageDescription</key>
<string>This app needs access to camera to take profile pictures</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
32 changes: 8 additions & 24 deletions lib/components/bottom_nav_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
class BottomNavBar extends StatelessWidget {
/// The currently selected index in the navigation bar.
final int currentIndex;

/// Callback when a navigation item is tapped.
final ValueChanged<int> onTap;

/// The role of the current user (affects navigation items).
final String role;

Expand All @@ -23,30 +25,15 @@ class BottomNavBar extends StatelessWidget {

if (role == 'Organization') {
items = const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
label: 'Players',
),
BottomNavigationBarItem(
icon: Icon(Icons.event),
label: 'Tournaments',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.people), label: 'Players'),
BottomNavigationBarItem(icon: Icon(Icons.event), label: 'Tournaments'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
];
} else {
// fallback
items = const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_today),
label: 'Time Table',
Expand All @@ -55,10 +42,7 @@ class BottomNavBar extends StatelessWidget {
icon: Icon(Icons.location_on),
label: 'Tournaments',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Profile',
),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
];
}

Expand Down
138 changes: 78 additions & 60 deletions lib/components/financial_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class FinancialChart extends StatefulWidget {

const FinancialChart({
super.key,
required this.entries, required ViewType viewType,
required this.entries,
required ViewType viewType,
});

@override
Expand Down Expand Up @@ -139,14 +140,17 @@ class _FinancialChartState extends State<FinancialChart> {
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) => Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
_getLabel(value.toInt()),
style: GoogleFonts.poppins(
fontSize: 11, fontWeight: FontWeight.w500),
),
),
getTitlesWidget:
(value, meta) => Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
_getLabel(value.toInt()),
style: GoogleFonts.poppins(
fontSize: 11,
fontWeight: FontWeight.w500,
),
),
),
),
),
leftTitles: AxisTitles(
Expand All @@ -164,32 +168,34 @@ class _FinancialChartState extends State<FinancialChart> {
drawVerticalLine: false,
drawHorizontalLine: true,
horizontalInterval: 2000,
getDrawingHorizontalLine: (value) => FlLine(
color: Colors.grey.withValues(alpha: 0.2),
strokeWidth: 1,
),
getDrawingHorizontalLine:
(value) => FlLine(
color: Colors.grey.withValues(alpha: 0.2),
strokeWidth: 1,
),
),
borderData: FlBorderData(show: false),
barGroups: spots.map((x) {
return BarChartGroupData(
x: x,
barRods: [
BarChartRodData(
toY: incomeMap[x] ?? 0,
width: 10,
borderRadius: BorderRadius.circular(6),
color: pastelGreen,
),
BarChartRodData(
toY: expenseMap[x] ?? 0,
width: 10,
borderRadius: BorderRadius.circular(6),
color: pastelBlue,
),
],
barsSpace: 6,
);
}).toList(),
barGroups:
spots.map((x) {
return BarChartGroupData(
x: x,
barRods: [
BarChartRodData(
toY: incomeMap[x] ?? 0,
width: 10,
borderRadius: BorderRadius.circular(6),
color: pastelGreen,
),
BarChartRodData(
toY: expenseMap[x] ?? 0,
width: 10,
borderRadius: BorderRadius.circular(6),
color: pastelBlue,
),
],
barsSpace: 6,
);
}).toList(),
),
),
),
Expand Down Expand Up @@ -224,30 +230,31 @@ class _FinancialChartState extends State<FinancialChart> {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: ViewType.values.map((type) {
final isSelected = type == _viewType;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 6),
child: ChoiceChip(
label: Text(
_viewLabels[type]!,
style: GoogleFonts.poppins(
fontWeight: FontWeight.w600,
color: isSelected ? Colors.white : Colors.grey[800],
children:
ViewType.values.map((type) {
final isSelected = type == _viewType;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 6),
child: ChoiceChip(
label: Text(
_viewLabels[type]!,
style: GoogleFonts.poppins(
fontWeight: FontWeight.w600,
color: isSelected ? Colors.white : Colors.grey[800],
),
),
selected: isSelected,
selectedColor: activeColor,
backgroundColor: Colors.grey.shade200,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
onSelected: (_) {
setState(() => _viewType = type);
},
),
),
selected: isSelected,
selectedColor: activeColor,
backgroundColor: Colors.grey.shade200,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
onSelected: (_) {
setState(() => _viewType = type);
},
),
);
}).toList(),
);
}).toList(),
),
);
}
Expand All @@ -260,8 +267,20 @@ class _FinancialChartState extends State<FinancialChart> {
case ViewType.weekly:
return "W${value}";
case ViewType.monthly:
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
return (value >= 1 && value <= 12) ? months[value - 1] : '';
case ViewType.yearly:
return value.toString();
Expand All @@ -275,8 +294,7 @@ class _FinancialChartState extends State<FinancialChart> {
label == "Income" ? Icons.arrow_upward : Icons.arrow_downward,
color: color,
),
Text(label,
style: GoogleFonts.poppins(fontWeight: FontWeight.w600)),
Text(label, style: GoogleFonts.poppins(fontWeight: FontWeight.w600)),
Text(
"\$${amount.toStringAsFixed(2)}",
style: GoogleFonts.poppins(
Expand Down
3 changes: 2 additions & 1 deletion lib/models/auth_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class AuthState {
return AuthState(
status: status ?? this.status,
errorMessage: errorMessage ?? this.errorMessage,
pendingVerificationEmail: pendingVerificationEmail ?? this.pendingVerificationEmail,
pendingVerificationEmail:
pendingVerificationEmail ?? this.pendingVerificationEmail,
isResendingEmail: isResendingEmail ?? this.isResendingEmail,
userRole: userRole ?? this.userRole,
);
Expand Down
20 changes: 15 additions & 5 deletions lib/models/financial_entry_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,30 @@ enum IncomeCategory {
/// ```dart
/// expenseCategoryToString(ExpenseCategory.food); // returns 'food'
/// ```
String expenseCategoryToString(ExpenseCategory category) => category.toString().split('.').last;
String expenseCategoryToString(ExpenseCategory category) =>
category.toString().split('.').last;

/// Converts a string to its corresponding [ExpenseCategory].
///
/// Throws a [StateError] if the string does not match any category.
ExpenseCategory expenseCategoryFromString(String value) => ExpenseCategory.values.firstWhere((e) => expenseCategoryToString(e) == value);
ExpenseCategory expenseCategoryFromString(String value) => ExpenseCategory
.values
.firstWhere((e) => expenseCategoryToString(e) == value);

/// Converts an [IncomeCategory] to its string representation.
///
/// Example:
/// ```dart
/// incomeCategoryToString(IncomeCategory.salary); // returns 'salary'
/// ```
String incomeCategoryToString(IncomeCategory category) => category.toString().split('.').last;
String incomeCategoryToString(IncomeCategory category) =>
category.toString().split('.').last;

/// Converts a string to its corresponding [IncomeCategory].
///
/// Throws a [StateError] if the string does not match any category.
IncomeCategory incomeCategoryFromString(String value) => IncomeCategory.values.firstWhere((e) => incomeCategoryToString(e) == value);
IncomeCategory incomeCategoryFromString(String value) =>
IncomeCategory.values.firstWhere((e) => incomeCategoryToString(e) == value);

/// Represents a financial entry, either income or expense, for a user.
///
Expand All @@ -56,14 +61,19 @@ IncomeCategory incomeCategoryFromString(String value) => IncomeCategory.values.f
class FinancialEntry {
/// Unique identifier for the entry (usually the Firestore document ID).
final String id;

/// Type of entry: 'income' or 'expense'.
final String type;

/// Category of the entry (stored as string, e.g., 'food', 'salary').
final String category;

/// Amount of the entry (positive value).
final double amount;

/// Date of the entry.
final DateTime date;

/// Optional notes for the entry.
final String? notes;

Expand Down Expand Up @@ -113,4 +123,4 @@ class FinancialEntry {
notes: map['notes'],
);
}
}
}
8 changes: 8 additions & 0 deletions lib/models/user_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class UserModel {
final bool signupCompleted;
final DateTime createdAt;
final String? fcmToken;
final String? profileImage; // Added profile image field

UserModel({
required this.uid,
Expand All @@ -23,6 +24,7 @@ class UserModel {
required this.signupCompleted,
required this.createdAt,
this.fcmToken,
this.profileImage, // Added to constructor
});

factory UserModel.fromFirestore(DocumentSnapshot doc) {
Expand All @@ -38,6 +40,7 @@ class UserModel {
signupCompleted: data['signupCompleted'] ?? false,
createdAt: (data['createdAt'] as Timestamp).toDate(),
fcmToken: data['fcmToken'],
profileImage: data['profileImage'], // Added profile image parsing
);
}

Expand All @@ -52,6 +55,8 @@ class UserModel {
'signupCompleted': signupCompleted,
'createdAt': Timestamp.fromDate(createdAt),
if (fcmToken != null) 'fcmToken': fcmToken,
if (profileImage != null)
'profileImage': profileImage, // Added profile image to Firestore
};
}

Expand All @@ -66,6 +71,7 @@ class UserModel {
bool? signupCompleted,
DateTime? createdAt,
String? fcmToken,
String? profileImage, // Added to copyWith
}) {
return UserModel(
uid: uid ?? this.uid,
Expand All @@ -78,6 +84,8 @@ class UserModel {
signupCompleted: signupCompleted ?? this.signupCompleted,
createdAt: createdAt ?? this.createdAt,
fcmToken: fcmToken ?? this.fcmToken,
profileImage:
profileImage ?? this.profileImage, // Added profile image to copyWith
);
}
}
Loading