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: 2 additions & 1 deletion android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
}
apply(plugin = "com.google.gms.google-services")
30 changes: 30 additions & 0 deletions android/app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"project_info": {
"project_number": "835298460246",
"firebase_url": "https://vector-7729b-default-rtdb.asia-southeast1.firebasedatabase.app",
"project_id": "vector-7729b",
"storage_bucket": "vector-7729b.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:835298460246:android:6d4a4f9da1b2a5a69ab1f7",
"android_client_info": {
"package_name": "com.example.vector"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyA2414zGiQceTrFLSkyuympsmP8Qp2FrOs"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
4 changes: 4 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
plugins {
id("com.google.gms.google-services") version "4.4.2" apply false
}

allprojects {
repositories {
google()
Expand Down
Binary file added assets/images/welcome_illustration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions lib/core/config/env_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class EnvConfig {
static const String firebaseDatabaseUrl = String.fromEnvironment(
'FIREBASE_DB_URL',
defaultValue: '',
);

static bool get isConfigured => firebaseDatabaseUrl.isNotEmpty;
}
54 changes: 53 additions & 1 deletion lib/core/constants.dart
Original file line number Diff line number Diff line change
@@ -1 +1,53 @@
// Add your API keys/colors here
import 'config/env_config.dart';

// App Info
const String appName = 'Vector';

// Firebase Database
const String firebaseDatabaseUrl = EnvConfig.firebaseDatabaseUrl;

// Database Paths
const String usersPath = 'users';
const String onboardingPath = 'onboarding';
const String connectionTestPath = '_connection_test';
const String connectedInfoPath = '.info/connected';

// Colors
const int colorBackground = 0xFF0B0B0F;
const int colorPrimary = 0xFF693298;
const int colorPrimaryDark = 0xFF562A7D;
const int colorSecondary = 0xFF2A2438;
const int colorAccent = 0xFFEE94FE;
const int colorTextPrimary = 0xFFF5F5F5;
const int colorTextSecondary = 0xFFFFFFFF;

// Sizes
const double paddingSmall = 8.0;
const double paddingMedium = 16.0;
const double paddingLarge = 24.0;
const double borderRadius = 12.0;
const double borderRadiusButton = 26.0;
const double buttonHeight = 52.0;
const double iconSizeSmall = 16.0;
const double iconSizeMedium = 24.0;
const double iconSizeLarge = 32.0;

// Text Sizes
const double textSizeSmall = 14.0;
const double textSizeMedium = 18.0;
const double textSizeLarge = 24.0;
const double textSizeXLarge = 28.0;

// Age Picker
const int minAge = 13;
const int maxAge = 120;
const double agePickerHeight = 192.6;
const double agePickerItemExtent = 50.0;

// Height Picker (in cm)
const int minHeight = 100;
const int maxHeight = 250;

// Weight Picker (in kg)
const int minWeight = 30;
const int maxWeight = 200;
41 changes: 41 additions & 0 deletions lib/core/services/auth_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:firebase_auth/firebase_auth.dart';

class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;

// REGISTER
Future<User?> register({
required String email,
required String password,
}) async {
final userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
return userCredential.user;
}

// LOGIN
Future<User?> login({
required String email,
required String password,
}) async {
final userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
return userCredential.user;
}

// FORGOT PASSWORD
Future<void> resetPassword({
required String email,
}) async {
await _auth.sendPasswordResetEmail(email: email);
}

// LOGOUT (future use)
Future<void> logout() async {
await _auth.signOut();
}
}
119 changes: 119 additions & 0 deletions lib/core/utils/firebase_test_util.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import 'package:flutter/foundation.dart';
import '../services/firebase_database_service.dart';
import '../../models/onboarding_data_model.dart';

class FirebaseTestUtil {
static final FirebaseDatabaseService _service = FirebaseDatabaseService();

static Future<void> runAllTests() async {
debugPrint('═══════════════════════════════════════════');
debugPrint('🔥 Firebase Realtime Database Test Suite');
debugPrint('═══════════════════════════════════════════\n');

await _testConnection();
await _testWriteAndRead();
await _testUpdate();
await _testDelete();

debugPrint('═══════════════════════════════════════════');
debugPrint('✅ All tests completed');
debugPrint('═══════════════════════════════════════════');
}

static Future<void> _testConnection() async {
debugPrint('📡 Test 1: Connection Test');
debugPrint('───────────────────────────────────────────');

final result = await _service.testConnection();

if (result.success) {
debugPrint(' ✅ ${result.message}');
} else {
debugPrint(' ❌ ${result.message}');
}
debugPrint('');
}

static Future<void> _testWriteAndRead() async {
debugPrint('📝 Test 2: Write and Read');
debugPrint('───────────────────────────────────────────');

const testUserId = 'test_user_001';
final testData = OnboardingDataModel(
gender: Gender.male,
age: 25,
height: 175,
heightUnit: 'cm',
weight: 70,
weightUnit: 'kg',
goals: [FitnessGoal.muscleGain, FitnessGoal.betterEndurance],
);

try {
await _service.saveOnboardingData(testUserId, testData);
debugPrint(' ✅ Write successful');

final readData = await _service.getOnboardingData(testUserId);
if (readData != null) {
debugPrint(' ✅ Read successful');
debugPrint(
' 📄 Data: Gender=${readData.gender?.name}, Age=${readData.age}',
);
debugPrint(' 📄 Height=${readData.height}${readData.heightUnit}');
debugPrint(' 📄 Weight=${readData.weight}${readData.weightUnit}');
debugPrint(
' 📄 Goals=${readData.goals?.map((g) => g.name).join(", ")}',
);
} else {
debugPrint(' ❌ Read failed: No data returned');
}
} catch (e) {
debugPrint(' ❌ Error: $e');
}
debugPrint('');
}

static Future<void> _testUpdate() async {
debugPrint('🔄 Test 3: Update');
debugPrint('───────────────────────────────────────────');

const testUserId = 'test_user_001';

try {
await _service.updateOnboardingField(testUserId, {'age': 26});
debugPrint(' ✅ Update successful');

final updated = await _service.getOnboardingData(testUserId);
if (updated?.age == 26) {
debugPrint(' ✅ Verified: Age updated to ${updated?.age}');
} else {
debugPrint(' ❌ Update verification failed');
}
} catch (e) {
debugPrint(' ❌ Error: $e');
}
debugPrint('');
}

static Future<void> _testDelete() async {
debugPrint('🗑️ Test 4: Delete');
debugPrint('───────────────────────────────────────────');

const testUserId = 'test_user_001';

try {
await _service.deleteOnboardingData(testUserId);
debugPrint(' ✅ Delete successful');

final deleted = await _service.getOnboardingData(testUserId);
if (deleted == null) {
debugPrint(' ✅ Verified: Data removed');
} else {
debugPrint(' ❌ Delete verification failed');
}
} catch (e) {
debugPrint(' ❌ Error: $e');
}
debugPrint('');
}
}
66 changes: 47 additions & 19 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
// import 'package:flutter/material.dart';
// import 'package:provider/provider.dart';

// import 'view_models/home_view_model.dart';

// void main() {
// runApp(const MyApp());
// }

// class MyApp extends StatelessWidget {
// const MyApp({super.key});

// @override
// Widget build(BuildContext context) {
// return MultiProvider(
// providers: [ChangeNotifierProvider(create: (_) => HomeViewModel())],
// child: MaterialApp(
// title: 'Vector',
// debugShowCheckedModeBanner: false,
// theme: ThemeData(
// colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
// useMaterial3: true,
// ),
// home: const Scaffold(body: Center(child: Text('Vector'))),
// ),
// );
// }
// }

import 'package:flutter/material.dart';
import 'views/welcome_view.dart';
import 'package:provider/provider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'view_models/auth_view_model.dart';

import 'view_models/home_view_model.dart';

void main() {
runApp(const MyApp());
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const VectorApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});
class VectorApp extends StatelessWidget {
const VectorApp({super.key});

@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [ChangeNotifierProvider(create: (_) => HomeViewModel())],
child: MaterialApp(
title: 'Vector',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const Scaffold(body: Center(child: Text('Vector'))),
),
);
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthViewModel()),
],
child: const MaterialApp(
debugShowCheckedModeBanner: false,
home: WelcomeView(),
),
);
}
}
Loading