diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..4d47d78 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,32 @@ +name: Build and Test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Restore dependencies + working-directory: ./FinTrackWebApi + run: dotnet restore + + - name: Build + working-directory: ./FinTrackWebApi + run: dotnet build --no-restore --configuration Release + + - name: Run Tests + working-directory: ./FinTrackWebApi + run: dotnet test --no-build --configuration Release --verbosity normal \ No newline at end of file diff --git a/.github/workflows/commit-message-check.yml b/.github/workflows/commit-message-check.yml new file mode 100644 index 0000000..1fdb20f --- /dev/null +++ b/.github/workflows/commit-message-check.yml @@ -0,0 +1,36 @@ +name: Commit Message Format Check + +on: + pull_request: + branches: + - main + +jobs: + validate-commit-messages: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Validate commit messages + run: | + echo "⏳ Commit messages are being checked..." + INVALID_FOUND=0 + COMMITS=$(git log origin/${{ github.base_ref }}..HEAD --pretty=format:"%s") + echo "$COMMITS" | while read COMMIT_MSG; do + echo "🔍 $COMMIT_MSG" + echo "$COMMIT_MSG" | grep -Eq "^(feat|fix|chore|docs|style|refactor|test|ci)(\(.+\))?: .{1,}" || { + echo "❌ Incorrect commit message:" + echo "$COMMIT_MSG" + INVALID_FOUND=1 + } + done + if [ $INVALID_FOUND -eq 1 ]; then + echo "🚫 Commit message validation failed." + exit 1 + else + echo "✅ All commit messages are valid." + fi diff --git a/.github/workflows/dependabot-pr-test.yml b/.github/workflows/dependabot-pr-test.yml new file mode 100644 index 0000000..6fb7982 --- /dev/null +++ b/.github/workflows/dependabot-pr-test.yml @@ -0,0 +1,22 @@ +name: Dependabot PR Test + +on: + pull_request: + types: [opened, synchronize] + branches: [ main ] + +jobs: + test-dependabot: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - run: dotnet restore + - run: dotnet build --no-restore --configuration Release + - run: dotnet test --no-build --configuration Release diff --git a/.github/workflows/format-check.yml b/.github/workflows/format-check.yml new file mode 100644 index 0000000..e9ed3d6 --- /dev/null +++ b/.github/workflows/format-check.yml @@ -0,0 +1,24 @@ +name: Format Check + +on: + pull_request: + branches: [ main ] + +jobs: + check-formatting: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Install dotnet-format tool + run: dotnet tool install -g dotnet-format + + - name: Check formatting + run: dotnet format .FinTrack.sln --verify-no-changes \ No newline at end of file diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml new file mode 100644 index 0000000..5302876 --- /dev/null +++ b/.github/workflows/secret-scan.yml @@ -0,0 +1,23 @@ +name: 🔐 Secret Scan with Gitleaks + +on: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + secret-scan: + name: 🔎 Scan for Secrets + runs-on: ubuntu-latest + + steps: + - name: 📥 Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: 🧪 Run Gitleaks scan + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/FinTrack/App.xaml b/FinTrack/App.xaml index 1f1398a..14f1a95 100644 --- a/FinTrack/App.xaml +++ b/FinTrack/App.xaml @@ -1,9 +1,12 @@  + xmlns:local="clr-namespace:FinTrack"> - + + + + + diff --git a/FinTrack/App.xaml.cs b/FinTrack/App.xaml.cs index 33d72fe..f0d47c6 100644 --- a/FinTrack/App.xaml.cs +++ b/FinTrack/App.xaml.cs @@ -1,30 +1,13 @@ -using System.Configuration; -using System.Data; -using System.Windows; -using Microsoft.Extensions.Configuration; +using System.Windows; -namespace FinTrack; - -/// -/// Interaction logic for App.xaml -/// -public partial class App : Application +namespace FinTrack { - public static IConfiguration Configuration { get; private set; } - - protected override void OnStartup(StartupEventArgs e) + public partial class App : Application { - base.OnStartup(e); - - var builder = new ConfigurationBuilder() - .SetBasePath(AppContext.BaseDirectory) - .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); - - Configuration = builder.Build(); - - // Örnek kullanım - string connStr = Configuration.GetConnectionString("PostgresConnection"); - MessageBox.Show("Bağlantı: " + connStr); + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + new LoginWindow().Show(); + } } -} - +} \ No newline at end of file diff --git a/FinTrack/AssemblyInfo.cs b/FinTrack/AssemblyInfo.cs index cc29e7f..b0ec827 100644 --- a/FinTrack/AssemblyInfo.cs +++ b/FinTrack/AssemblyInfo.cs @@ -1,6 +1,6 @@ using System.Windows; -[assembly:ThemeInfo( +[assembly: ThemeInfo( ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located //(used if a resource is not found in the page, // or application resource dictionaries) diff --git a/FinTrack/Images/Icons/conversation.png b/FinTrack/Assets/Images/Icons/conversation.png similarity index 100% rename from FinTrack/Images/Icons/conversation.png rename to FinTrack/Assets/Images/Icons/conversation.png diff --git a/FinTrack/Images/Icons/done.png b/FinTrack/Assets/Images/Icons/done.png similarity index 100% rename from FinTrack/Images/Icons/done.png rename to FinTrack/Assets/Images/Icons/done.png diff --git a/FinTrack/Images/Icons/email.png b/FinTrack/Assets/Images/Icons/email.png similarity index 100% rename from FinTrack/Images/Icons/email.png rename to FinTrack/Assets/Images/Icons/email.png diff --git a/FinTrack/Images/Icons/eyeclose.png b/FinTrack/Assets/Images/Icons/eyeclose.png similarity index 100% rename from FinTrack/Images/Icons/eyeclose.png rename to FinTrack/Assets/Images/Icons/eyeclose.png diff --git a/FinTrack/Images/Icons/eyeopen.png b/FinTrack/Assets/Images/Icons/eyeopen.png similarity index 100% rename from FinTrack/Images/Icons/eyeopen.png rename to FinTrack/Assets/Images/Icons/eyeopen.png diff --git a/FinTrack/Images/Icons/login.png b/FinTrack/Assets/Images/Icons/login.png similarity index 100% rename from FinTrack/Images/Icons/login.png rename to FinTrack/Assets/Images/Icons/login.png diff --git a/FinTrack/Images/Icons/message.png b/FinTrack/Assets/Images/Icons/message.png similarity index 100% rename from FinTrack/Images/Icons/message.png rename to FinTrack/Assets/Images/Icons/message.png diff --git a/FinTrack/Images/Icons/padlock.png b/FinTrack/Assets/Images/Icons/padlock.png similarity index 100% rename from FinTrack/Images/Icons/padlock.png rename to FinTrack/Assets/Images/Icons/padlock.png diff --git a/FinTrack/Images/Icons/passwordpanel.png b/FinTrack/Assets/Images/Icons/passwordpanel.png similarity index 100% rename from FinTrack/Images/Icons/passwordpanel.png rename to FinTrack/Assets/Images/Icons/passwordpanel.png diff --git a/FinTrack/Images/Icons/add.png b/FinTrack/Assets/Images/Icons/register.png similarity index 100% rename from FinTrack/Images/Icons/add.png rename to FinTrack/Assets/Images/Icons/register.png diff --git a/FinTrack/Images/Icons/tick.png b/FinTrack/Assets/Images/Icons/tick.png similarity index 100% rename from FinTrack/Images/Icons/tick.png rename to FinTrack/Assets/Images/Icons/tick.png diff --git a/FinTrack/Images/Icons/user.png b/FinTrack/Assets/Images/Icons/user.png similarity index 100% rename from FinTrack/Images/Icons/user.png rename to FinTrack/Assets/Images/Icons/user.png diff --git a/FinTrack/Images/Icons/verify.png b/FinTrack/Assets/Images/Icons/verify.png similarity index 100% rename from FinTrack/Images/Icons/verify.png rename to FinTrack/Assets/Images/Icons/verify.png diff --git a/FinTrack/Images/Icons/x.png b/FinTrack/Assets/Images/Icons/x.png similarity index 100% rename from FinTrack/Images/Icons/x.png rename to FinTrack/Assets/Images/Icons/x.png diff --git a/FinTrack/FirstWelcome/Images/analytics.png b/FinTrack/Assets/Images/analytics.png similarity index 100% rename from FinTrack/FirstWelcome/Images/analytics.png rename to FinTrack/Assets/Images/analytics.png diff --git a/FinTrack/FirstWelcome/Images/document.png b/FinTrack/Assets/Images/document.png similarity index 100% rename from FinTrack/FirstWelcome/Images/document.png rename to FinTrack/Assets/Images/document.png diff --git a/FinTrack/FirstWelcome/Images/hello.png b/FinTrack/Assets/Images/hello.png similarity index 100% rename from FinTrack/FirstWelcome/Images/hello.png rename to FinTrack/Assets/Images/hello.png diff --git a/FinTrack/FirstWelcome/Images/increase.png b/FinTrack/Assets/Images/increase.png similarity index 100% rename from FinTrack/FirstWelcome/Images/increase.png rename to FinTrack/Assets/Images/increase.png diff --git a/FinTrack/FirstWelcome/Images/investment.png b/FinTrack/Assets/Images/investment.png similarity index 100% rename from FinTrack/FirstWelcome/Images/investment.png rename to FinTrack/Assets/Images/investment.png diff --git a/FinTrack/FirstWelcome/Images/money.png b/FinTrack/Assets/Images/money.png similarity index 100% rename from FinTrack/FirstWelcome/Images/money.png rename to FinTrack/Assets/Images/money.png diff --git a/FinTrack/FirstWelcome/Images/note.png b/FinTrack/Assets/Images/note.png similarity index 100% rename from FinTrack/FirstWelcome/Images/note.png rename to FinTrack/Assets/Images/note.png diff --git a/FinTrack/FirstWelcome/Images/payment.png b/FinTrack/Assets/Images/payment.png similarity index 100% rename from FinTrack/FirstWelcome/Images/payment.png rename to FinTrack/Assets/Images/payment.png diff --git a/FinTrack/FirstWelcome/Images/piggy-bank.png b/FinTrack/Assets/Images/piggy-bank.png similarity index 100% rename from FinTrack/FirstWelcome/Images/piggy-bank.png rename to FinTrack/Assets/Images/piggy-bank.png diff --git a/FinTrack/FirstWelcome/Images/promotion.png b/FinTrack/Assets/Images/promotion.png similarity index 100% rename from FinTrack/FirstWelcome/Images/promotion.png rename to FinTrack/Assets/Images/promotion.png diff --git a/FinTrack/FirstWelcome/Images/start-up.png b/FinTrack/Assets/Images/start-up.png similarity index 100% rename from FinTrack/FirstWelcome/Images/start-up.png rename to FinTrack/Assets/Images/start-up.png diff --git a/FinTrack/FirstWelcome/Images/statistic.png b/FinTrack/Assets/Images/statistic.png similarity index 100% rename from FinTrack/FirstWelcome/Images/statistic.png rename to FinTrack/Assets/Images/statistic.png diff --git a/FinTrack/FirstWelcome/Images/targets.png b/FinTrack/Assets/Images/targets.png similarity index 100% rename from FinTrack/FirstWelcome/Images/targets.png rename to FinTrack/Assets/Images/targets.png diff --git a/FinTrack/FirstWelcome/Images/task.png b/FinTrack/Assets/Images/task.png similarity index 100% rename from FinTrack/FirstWelcome/Images/task.png rename to FinTrack/Assets/Images/task.png diff --git a/FinTrack/Codes/DataAccess/DBScheme.cs b/FinTrack/Codes/DataAccess/DBScheme.cs deleted file mode 100644 index 959b25a..0000000 --- a/FinTrack/Codes/DataAccess/DBScheme.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Reflection.Metadata; - -namespace FinTrack.Codes.DataAccess -{ - // This class defines the database schema for a financial tracking application. - // It includes classes for users, transactions, categories, budgets, targets, goals, reports, and settings. - // Each class represents a table in the database with properties that correspond to the columns in the table. - // The classes are designed to be used with an ORM (Object-Relational Mapping) framework like Entity Framework or Dapper. - // The properties in each class are defined with appropriate data types and attributes to ensure data integrity and relationships between tables. - // The classes are organized in a namespace called FinTrack.Codes.DB, which indicates that they are part of the database layer of the FinTrack application. - // The classes are designed to be easily extendable and maintainable, allowing for future enhancements and modifications as needed. - // The classes are also designed to be used with a variety of database management systems, making them versatile and adaptable to different environments. - // The classes are written in C# and follow standard naming conventions for properties and classes. - // The classes are designed to be used in a financial tracking application, which may include features such as budgeting, goal setting, and reporting. - // The classes are designed to be used in a multi-user environment, allowing for multiple users to access and manage their financial data securely. - // The classes are designed to be used with a variety of data types, including strings, integers, decimals, and dates. - // The classes are designed to be used with a variety of data access technologies, including ADO.NET, Entity Framework, and Dapper. - // The classes are designed to be used with a variety of programming languages, including C#, VB.NET, and F#. - // The classes are designed to be used with a variety of development environments, including Visual Studio, Visual Studio Code, and JetBrains Rider. - // The classes are designed to be used with a variety of deployment environments, including cloud-based and on-premises solutions. - // The classes are designed to be used with a variety of database management systems, including SQL Server, MySQL, PostgreSQL, and SQLite. - // The classes are designed to be used with a variety of operating systems, including Windows, Linux, and macOS. - - // The users class represents a user of the financial tracking application. - public class users - { - public Guid user_id { get; set; } // Primary Key - public string full_name { get; set; } // User's full name. - public string email { get; set; } // User's email address. - public string password_hash { get; set; } // Hashed password for security. - public byte[] profile_picture { get; set; } // User's profile picture. - public DateTime created_at { get; set; } // Account creation date. - } - - // The transactions class represents a financial transaction made by a user. - public class transactions - { - public int transaction_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public int category_id { get; set; } // Foreign Key to categories table. - public decimal amount { get; set; } // Transaction amount. - public string transaction_type { get; set; } // Type of transaction (e.g., income, expense). - public string description { get; set; } // Description of the transaction. - public DateTime transaction_date { get; set; } // Date of the transaction. - } - - // The categories class represents a category for organizing transactions. - public class categories - { - public int category_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public string category_name { get; set; } // Name of the category. - public string category_type { get; set; } // Type of category (e.g., income, expense). - } - - // The budgets class represents a budget set by a user for a specific category. - public class budgets - { - public int budget_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public int category_id { get; set; } // Foreign Key to categories table. - public decimal budget_amount { get; set; } // Budget amount. - public DateTime start_date { get; set; } // Start date of the budget period. - public DateTime end_date { get; set; } // End date of the budget period. - public DateTime created_at { get; set; } // Date the budget was created. - } - - // The targets class represents a financial target set by a user. - public class targets - { - public int target_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public string target_name { get; set; } // Name of the target. - public decimal target_amount { get; set; } // Target amount. - public DateTime target_date { get; set; } // Target date. - public DateTime created_at { get; set; } // Date the target was created. - } - - // The goals class represents a financial goal set by a user. - public class goals - { - public int goal_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public string goal_name { get; set; } // Name of the goal. - public decimal target_amount { get; set; } // Target amount for the goal. - public decimal saved_amount { get; set; } // Amount saved towards the goal. - public DateTime deadline { get; set; } // Deadline for achieving the goal. - public DateTime created_at { get; set; } // Date the goal was created. - } - - public class reports - { - public int report_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public string report_type { get; set; } // Type of report (e.g., income, expense). - public DateTime report_date { get; set; } // Date of the report. - public string report_data { get; set; } // Data for the report (e.g., JSON, XML). - public DateTime created_at { get; set; } // Date the report was created. - } - - public class settings - { - public int setting_id { get; set; } // Primary Key - public int user_id { get; set; } // Foreign Key to users table. - public string currency { get; set; } // User's preferred currency. - public string language { get; set; } // User's preferred language. - public bool dark_mode { get; set; } // User's preference for dark mode. - } -} diff --git a/FinTrack/Codes/DataAccess/UserRepository.cs b/FinTrack/Codes/DataAccess/UserRepository.cs deleted file mode 100644 index 844a9c9..0000000 --- a/FinTrack/Codes/DataAccess/UserRepository.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System.Windows; -using Microsoft.Extensions.Configuration; -using Npgsql; - -namespace FinTrack.Codes.DataAccess -{ - public class UserRepository - { - private static UserRepository instance; - public static UserRepository Instance => instance ??= new UserRepository(); - - private readonly string connectionString; - - public UserRepository() - { - connectionString = App.Configuration.GetConnectionString("PostgresConnection"); - } - - private NpgsqlConnection GetConnection() - { - return new NpgsqlConnection(connectionString); - } - - public async Task LoginUser(string email, string password) - { - using var connection = GetConnection(); - - try - { - await connection.OpenAsync(); - - string query = "SELECT * FROM users WHERE email = @Email AND password_hash = @Password"; - - using var cmd = new NpgsqlCommand(query, connection); - cmd.Parameters.AddWithValue("@Email", email); - cmd.Parameters.AddWithValue("@Password", password); - - using var reader = await cmd.ExecuteReaderAsync(); - - if (await reader.ReadAsync()) - { - return new users - { - user_id = reader.GetGuid(reader.GetOrdinal("user_id")), - full_name = reader.GetString(reader.GetOrdinal("full_name")), - email = reader.GetString(reader.GetOrdinal("email")), - password_hash = "Empty for privacy.", - profile_picture = reader["profile_picture"] == DBNull.Value ? null : (byte[])reader["profile_picture"] - }; - } - - return null; // User not found or login failed. - - } - catch (Exception ex) - { - MessageBox.Show("Error: " + ex.Message); - return null; - } - } - - public async Task RegisterUser(users user) - { - using var connection = GetConnection(); - - try - { - await connection.OpenAsync(); - - string query = "INSERT INTO users (full_name, email, password_hash, profile_picture) VALUES (@FullName, @Email, @PasswordHash, @ProfilePicture)"; - - using var cmd = new NpgsqlCommand(query, connection); - cmd.Parameters.AddWithValue("@FullName", user.full_name); - cmd.Parameters.AddWithValue("@Email", user.email); - cmd.Parameters.AddWithValue("@PasswordHash", user.password_hash); - cmd.Parameters.AddWithValue("@ProfilePicture", user.profile_picture); - await cmd.ExecuteNonQueryAsync(); - } - catch (Exception ex) - { - MessageBox.Show("Error: " + ex.Message); - } - } - - public async Task UpdateUser(users user) - { - using var connection = GetConnection(); - try - { - await connection.OpenAsync(); - string query = "UPDATE users SET full_name = @FullName, email = @Email, password_hash = @PasswordHash, profile_picture = @ProfilePicture WHERE user_id = @UserId"; - using var cmd = new NpgsqlCommand(query, connection); - cmd.Parameters.AddWithValue("@FullName", user.full_name); - cmd.Parameters.AddWithValue("@Email", user.email); - cmd.Parameters.AddWithValue("@PasswordHash", user.password_hash); - cmd.Parameters.AddWithValue("@ProfilePicture", user.profile_picture); - cmd.Parameters.AddWithValue("@UserId", user.user_id); - await cmd.ExecuteNonQueryAsync(); - } - catch (Exception ex) - { - MessageBox.Show("Error: " + ex.Message); - } - } - - public async Task DeleteUser(int userId) - { - using var connection = GetConnection(); - try - { - await connection.OpenAsync(); - string query = "DELETE FROM users WHERE user_id = @UserId"; - using var cmd = new NpgsqlCommand(query, connection); - cmd.Parameters.AddWithValue("@UserId", userId); - await cmd.ExecuteNonQueryAsync(); - } - catch (Exception ex) - { - MessageBox.Show("Error: " + ex.Message); - } - } - - public async Task GetUserById(int userId) - { - using var connection = GetConnection(); - try - { - await connection.OpenAsync(); - string query = "SELECT * FROM users WHERE user_id = @UserId"; - using var cmd = new NpgsqlCommand(query, connection); - cmd.Parameters.AddWithValue("@UserId", userId); - using var reader = await cmd.ExecuteReaderAsync(); - if (await reader.ReadAsync()) - { - return new users - { - user_id = reader.GetGuid(reader.GetOrdinal("user_id")), - full_name = reader.GetString(reader.GetOrdinal("full_name")), - email = reader.GetString(reader.GetOrdinal("email")), - password_hash = "Empty for privacy.", - profile_picture = reader["profile_picture"] == DBNull.Value ? null : (byte[])reader["profile_picture"] - }; - } - return null; // User not found. - } - catch (Exception ex) - { - MessageBox.Show("Error: " + ex.Message); - return null; - } - } - } -} diff --git a/FinTrack/Codes/LoginPanel/LoginPanelViewModel.cs b/FinTrack/Codes/LoginPanel/LoginPanelViewModel.cs deleted file mode 100644 index de1a257..0000000 --- a/FinTrack/Codes/LoginPanel/LoginPanelViewModel.cs +++ /dev/null @@ -1,360 +0,0 @@ -using System.Timers; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using System.Windows; -using System.Windows.Input; -using System.Windows.Media.Imaging; -using FinTrack.Codes.DataAccess; -using FinTrack.Codes.Session; -using System.Threading.Tasks; - -namespace FinTrack.Codes.LoginPanel -{ - public class LoginPanelViewModel : INotifyPropertyChanged - { - private LoginPanelView currentView { get; set; } - private bool showWelcomePanel { get; set; } - - private string inputPassword { get; set; } = ""; - private bool isPasswordVisible = false; - - private string inputEmail { get; set; } = ""; - - private string inputName { get; set; } = ""; - - private string inputCode { get; set; } - private int codeTimer = 300; - private bool codeTimerRunning = true; - private bool codeTimerExpired = false; - private string counterText { get; set; } = "5:00"; - - #region Commands - public ICommand ShowLoginCommand { get; } - public ICommand ShowRegisterCommand { get; } - public ICommand ShowForgotCommand { get; } - public ICommand HideWelcomePanelCommand { get; } - public ICommand ShowCodeVerificationCommand { get; } - public ICommand ShowResetPasswordCommand { get; } - - public ICommand RegisterCommand { get; } - - public ICommand ShowPasswordInputTextBoxCommand { get; } - public ICommand ShowPasswordInputPasswordBoxCommand { get; } - public ICommand TogglePasswordVisibilityCommand { get; } - - public ICommand LoginButton_Click { get; } - public ICommand RegisterButton_Click { get; } - public ICommand CodeVerificationButton_Click { get; } - public ICommand ResetPasswordButton_Click { get; } - #endregion - - private System.Timers.Timer timer; - - public LoginPanelViewModel() - { - currentView = LoginPanelView.Forgot; - showWelcomePanel = false; - - ShowLoginCommand = new RelayCommand(o => CurrentView = LoginPanelView.Login); - ShowRegisterCommand = new RelayCommand(o => CurrentView = LoginPanelView.Register); - ShowForgotCommand = new RelayCommand(o => CurrentView = LoginPanelView.Forgot); - HideWelcomePanelCommand = new RelayCommand(o => ShowWelcomePanel = false); - ShowCodeVerificationCommand = new RelayCommand(o => CurrentView = LoginPanelView.CodeVerification); - ShowResetPasswordCommand = new RelayCommand(o => CurrentView = LoginPanelView.ResetPassword); - - RegisterCommand = new RelayCommand(o => OnRegister()); - - TogglePasswordVisibilityCommand = new RelayCommand(o => TogglePasswordVisibility()); - - LoginButton_Click = new RelayCommand(async o => await UserLogin()); - RegisterButton_Click = new RelayCommand(async o => await RegisterUser()); - - timer = new System.Timers.Timer(1000); - timer.Elapsed += CodeTimer; - timer.AutoReset = true; - timer.Enabled = true; - } - - - #region Navigating Between Panels - public LoginPanelView CurrentView - { - get => currentView; - set - { - currentView = value; - OnPropertyChanged(); - UpdateVisibility(); - } - } - - public bool ShowWelcomePanel - { - get => showWelcomePanel; - set - { - showWelcomePanel = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(WelcomeVisibility)); - } - } - - public Visibility LoginVisibility => CurrentView == LoginPanelView.Login ? Visibility.Visible : Visibility.Hidden; - public Visibility RegisterVisibility => CurrentView == LoginPanelView.Register ? Visibility.Visible : Visibility.Hidden; - public Visibility ForgotVisibility => CurrentView == LoginPanelView.Forgot ? Visibility.Visible : Visibility.Hidden; - public Visibility CodeVerificationVisibility => CurrentView == LoginPanelView.CodeVerification ? Visibility.Visible : Visibility.Hidden; - public Visibility ResetPasswordVisibility => CurrentView == LoginPanelView.ResetPassword ? Visibility.Visible : Visibility.Hidden; - public Visibility WelcomeVisibility => ShowWelcomePanel ? Visibility.Visible : Visibility.Hidden; - - private void UpdateVisibility() - { - OnPropertyChanged(nameof(LoginVisibility)); - OnPropertyChanged(nameof(RegisterVisibility)); - OnPropertyChanged(nameof(ForgotVisibility)); - OnPropertyChanged(nameof(CodeVerificationVisibility)); - OnPropertyChanged(nameof(ResetPasswordVisibility)); - } - - private void OnRegister() - { - ShowWelcomePanel = true; - CurrentView = LoginPanelView.Login; - } - #endregion - - #region User Input Format Control - public bool IsNameValid(string name) => name.Length >= 5; - public static bool IsEmailValid(string email) => email.Contains("@") && email.Contains("."); - public static bool IsPasswordValid(string password) - { - if (password.Length < 8) - { - return false; - } - bool hasUpperCase = false; - bool hasLowerCase = false; - bool hasDigit = false; - foreach (char c in password) - { - if (char.IsUpper(c)) - { - hasUpperCase = true; - } - else if (char.IsLower(c)) - { - hasLowerCase = true; - } - else if (char.IsDigit(c)) - { - hasDigit = true; - } - else if (char.IsWhiteSpace(c)) - { - return false; - } - } - return hasUpperCase && hasLowerCase && hasDigit; - } - - public BitmapImage PasswordApprovalIconSource - { - get - { - string iconPath = IsPasswordValid(InputPassword) - ? "pack://application:,,,/Images/Icons/tick.png" - : "pack://application:,,,/Images/Icons/x.png"; - - return new BitmapImage(new Uri(iconPath)); - } - } - - public string InputEmail - { - get => inputEmail; - set - { - inputEmail = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(EmailApprovalIconSource)); - } - } - - public BitmapImage EmailApprovalIconSource - { - get - { - string iconPath = IsEmailValid(InputEmail) - ? "pack://application:,,,/Images/Icons/tick.png" - : "pack://application:,,,/Images/Icons/x.png"; - - return new BitmapImage(new Uri(iconPath)); - } - } - - public string InputUsername - { - get => inputName; - set - { - inputName = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(UsernameApprovalIconSource)); - } - } - - public BitmapImage UsernameApprovalIconSource - { - get - { - string iconPath = IsNameValid(InputUsername) - ? "pack://application:,,,/Images/Icons/tick.png" - : "pack://application:,,,/Images/Icons/x.png"; - - return new BitmapImage(new Uri(iconPath)); - } - } - #endregion - - #region Password Visibility - public string InputPassword - { - get => inputPassword; - set - { - inputPassword = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(PasswordApprovalIconSource)); - } - } - - public bool IsPasswordVisible - { - get => isPasswordVisible; - set - { - isPasswordVisible = value; - OnPropertyChanged(); - OnPropertyChanged(nameof(EyeIconSource)); - } - } - - public BitmapImage EyeIconSource - { - get - { - string uri = IsPasswordVisible - ? "pack://application:,,,/Images/Icons/eyeopen.png" - : "pack://application:,,,/Images/Icons/eyeclose.png"; - - return new BitmapImage(new Uri(uri)); - } - } - - private void TogglePasswordVisibility() - { - IsPasswordVisible = !IsPasswordVisible; - } - #endregion - - #region Code Verification - public string InputCode - { - get => inputCode; - set - { - inputCode = value; - OnPropertyChanged(); - } - } - - public string CounterText - { - get => counterText; - set - { - counterText = value; - OnPropertyChanged(); - } - } - - private void CodeTimer(object sender, ElapsedEventArgs e) - { - if (codeTimerRunning) - { - codeTimer--; - CounterText = $"{codeTimer / 60}:{codeTimer % 60}"; - if (codeTimer == 0) - { - codeTimerRunning = false; - codeTimerExpired = true; - CodeTimerExpired(); - } - OnPropertyChanged(nameof(CodeTimer)); - } - } - - public void CodeTimerExpired() - { - MessageBox.Show("Code has expired. Please request a new one."); - } - #endregion - - #region Login Button Click - private async Task UserLogin() - { - // Call the login method from the UserRepository - var user = await UserRepository.Instance.LoginUser(InputEmail, InputPassword); - if (user != null) - { - SessionManager.Instance.Login(user); - MessageBox.Show("Login successful!"); - } - else - { - MessageBox.Show("Invalid email or password."); - } - } - #endregion - - #region Register Button Click - private async Task RegisterUser() - { - if (!IsEmailValid(InputEmail) || !IsPasswordValid(InputPassword) || !IsNameValid(InputUsername)) - { - MessageBox.Show("Please fill in all fields correctly."); - return; - } - - //// Call the register method from the UserRepository - //var user = await UserRepository.Instance.RegisterUser(InputEmail, InputPassword, InputUsername); - //if (user != null) - //{ - // MessageBox.Show("Registration successful!"); - // CurrentView = LoginPanelView.Login; - //} - //else - //{ - // MessageBox.Show("Registration failed."); - //} - } - #endregion - - #region INotifyPropertyChanged Implementation - public event PropertyChangedEventHandler PropertyChanged; - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - #endregion - } - - public enum LoginPanelView - { - Welcome, - Login, - Register, - Forgot, - CodeVerification, - ResetPassword - } -} \ No newline at end of file diff --git a/FinTrack/Codes/Session/SessionManager.cs b/FinTrack/Codes/Session/SessionManager.cs deleted file mode 100644 index 02029c3..0000000 --- a/FinTrack/Codes/Session/SessionManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -using FinTrack.Codes.DataAccess; - -namespace FinTrack.Codes.Session -{ - public class SessionManager - { - private static SessionManager instance; - public static SessionManager Instance => instance ??= new SessionManager(); - private SessionManager() { } - - private users currentUser { get; set; } = new users(); - - public users CurrentUser - { - get - { - if (currentUser == null) - { - currentUser = new users(); - } - return currentUser; - } - } - - public void SetCurrentUser(users user) => currentUser = user; - - public void ClearCurrentUser() => currentUser = new users(); - - public bool IsUserLoggedIn() => currentUser != null; - - public bool IsUserLoggedOut() => CurrentUser == null; - - public void UpdateUser(users user) => currentUser = user; - - public void Logout() => currentUser = new users(); - - public void Login(users user) => currentUser = user; - } -} diff --git a/FinTrack/Codes/Verifications/CodeVerifier.cs b/FinTrack/Codes/Verifications/CodeVerifier.cs deleted file mode 100644 index 214af00..0000000 --- a/FinTrack/Codes/Verifications/CodeVerifier.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace FinTrack.Codes.Verifications -{ - public class CodeVerifier - { - private byte[] CodeGenerator(short codeLength) - { - Random random = new Random(); - - byte[] code = new byte[codeLength]; - for (int i = 0; i < code.Length; i++) - { - code[i] = (byte)random.Next(0, 10); - } - return code; - } - } -} diff --git a/FinTrack/RelayCommand.cs b/FinTrack/Core/RelayCommand.cs similarity index 97% rename from FinTrack/RelayCommand.cs rename to FinTrack/Core/RelayCommand.cs index 5a5a221..8e31176 100644 --- a/FinTrack/RelayCommand.cs +++ b/FinTrack/Core/RelayCommand.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using System.Windows.Input; -namespace FinTrack +namespace FinTrack.Core { public class RelayCommand : ICommand { diff --git a/FinTrack/FinTrack.csproj b/FinTrack/FinTrack.csproj index 2c4d01d..e4b816c 100644 --- a/FinTrack/FinTrack.csproj +++ b/FinTrack/FinTrack.csproj @@ -9,38 +9,24 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -50,88 +36,88 @@ - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never - + Never @@ -140,9 +126,10 @@ Always - - Always - + + + + diff --git a/FinTrack/FirstWelcome/DB/SlideDocument.json b/FinTrack/FirstWelcome/DB/SlideDocument.json deleted file mode 100644 index 5741e26..0000000 --- a/FinTrack/FirstWelcome/DB/SlideDocument.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "Header": "Welcome to FinTrack!", - "Body": "A modern solution that simplifies your financial management.", - "ImagePath": "FirstWelcome/Images/hello.png" - }, - { - "Header": "Track Your Income and Expenses Easily!", - "Body": "You can track your daily expenses and income.", - "ImagePath": "FirstWelcome/Images/note.png" - }, - { - "Header": "Plan and Control Your Budget!", - "Body": "You can keep your spending under control by setting a monthly limit.", - "ImagePath": "FirstWelcome/Images/piggy-bank.png" - }, - { - "Header": "Save Money and Achieve Your Goals!", - "Body": "How much should you set aside to save 10,000 TL per month?", - "ImagePath": "FirstWelcome/Images/payment.png" - }, - { - "Header": "Visualize Your Financial Analysis!", - "Body": "You can view graphs of data such as income-expenditure balance, spending habits.", - "ImagePath": "FirstWelcome/Images/increase.png" - }, - { - "Header": "Add targets for your economy.", - "Body": "Targets for economic developments can be added.", - "ImagePath": "FirstWelcome/Images/targets.png" - }, - { - "Header": "Ready to Discover FinTrack?", - "Body": "If you want more information about the app, you can use the Help/Support tab.", - "ImagePath": "FirstWelcome/Images/start-up.png" - } -] \ No newline at end of file diff --git a/FinTrack/FirstWelcome/FirstWelcomeSlideModel.cs b/FinTrack/FirstWelcome/FirstWelcomeSlideModel.cs deleted file mode 100644 index 6bd9411..0000000 --- a/FinTrack/FirstWelcome/FirstWelcomeSlideModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -namespace FinTrack.FirstWelcome -{ - public class FirstWelcomeSlideModel - { - public string ImagePath { get; set; } = string.Empty; - public string Header { get; set; } = string.Empty; - public string Body { get; set; } = string.Empty; - } -} diff --git a/FinTrack/FirstWelcome/FirstWelcomeSlideViewModel.cs b/FinTrack/FirstWelcome/FirstWelcomeSlideViewModel.cs deleted file mode 100644 index ec75447..0000000 --- a/FinTrack/FirstWelcome/FirstWelcomeSlideViewModel.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Newtonsoft.Json; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.IO; -using System.Runtime.CompilerServices; -using System.Windows; - -namespace FinTrack.FirstWelcome -{ - public class FirstWelcomeSlideViewModel : INotifyPropertyChanged - { - private ObservableCollection slides = new ObservableCollection(); - private int activeSlideIndex; - - public ObservableCollection Slides - { - get => slides; - set - { - slides = value; - OnPropertyChanged(); - } - } - - public int ActiveSlideIndex - { - get => activeSlideIndex; - set - { - activeSlideIndex = value; - OnPropertyChanged(); - UpdateUI(); - } - } - - public FirstWelcomeSlideModel ActiveSlide => activeSlideIndex >= 0 && activeSlideIndex < Slides.Count ? Slides[activeSlideIndex] : null; - - public bool CanGoForward => activeSlideIndex < slides.Count - 1; - public bool CanGoBack => activeSlideIndex > 0; - public bool CanSkip => activeSlideIndex < slides.Count - 1; - - public FirstWelcomeSlideViewModel() - { - LoadSlidesFromJson(); - ActiveSlideIndex = 0; - } - - public void GoForward() - { - if (CanGoForward) - { - ActiveSlideIndex++; - } - } - - public void GoBack() - { - if (CanGoBack) - { - ActiveSlideIndex--; - } - } - - public void Skip() - { - if (CanSkip) - { - ActiveSlideIndex = slides.Count - 1; - } - } - - private void UpdateUI() - { - // UI’yı güncellemek için gerekliyse burada ek mantık olabilir - } - - private void LoadSlidesFromJson() - { - // JSON dosyasını oku - string jsonPath = Path.Combine(Directory.GetCurrentDirectory(), "FirstWelcome", "DB", "SlideDocument.json"); - string jsonContent = File.ReadAllText(jsonPath); - - // JSON’u deserialize et - var slides = JsonConvert.DeserializeObject>(jsonContent); - if (slides != null) - { - Slides = slides; - } - } - - public event PropertyChangedEventHandler PropertyChanged; - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - } -} \ No newline at end of file diff --git a/FinTrack/FirstWelcome/WelcomePanel.xaml b/FinTrack/FirstWelcome/WelcomePanel.xaml deleted file mode 100644 index ea2f8eb..0000000 --- a/FinTrack/FirstWelcome/WelcomePanel.xaml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/FinTrack/LoginWindow.xaml.cs b/FinTrack/LoginWindow.xaml.cs deleted file mode 100644 index 49565f5..0000000 --- a/FinTrack/LoginWindow.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FinTrack.Codes.LoginPanel; -using FinTrack.FirstWelcome; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Navigation; - -namespace FinTrack -{ - public partial class LoginWindow : Window - { - public LoginWindow() - { - InitializeComponent(); - DataContext = new LoginPanelViewModel(); - FirstWelcomePanelFrame.Navigate(new WelcomePanel()); - } - - private void FirstWelcomePanelFrame_Navigated(object sender, NavigationEventArgs e) { } - } -} \ No newline at end of file diff --git a/FinTrack/MainWindow.xaml b/FinTrack/MainWindow.xaml deleted file mode 100644 index 5591452..0000000 --- a/FinTrack/MainWindow.xaml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/FinTrack/MainWindow.xaml.cs b/FinTrack/MainWindow.xaml.cs deleted file mode 100644 index 92932d7..0000000 --- a/FinTrack/MainWindow.xaml.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FinTrack.Panels; -using System.Text; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace FinTrack; - -/// -/// Interaction logic for MainWindow.xaml -/// -public partial class MainWindow : Window -{ - public MainWindow() - { - InitializeComponent(); - DataContext = new MainWindowViewModel(); ; - } -} \ No newline at end of file diff --git a/FinTrack/Panels/AccountPanel.xaml b/FinTrack/Panels/AccountPanel.xaml deleted file mode 100644 index 66ab8fb..0000000 --- a/FinTrack/Panels/AccountPanel.xaml +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + +