diff --git a/FinTrack/App.xaml b/FinTrack/App.xaml index 14f1a95..8af4b5e 100644 --- a/FinTrack/App.xaml +++ b/FinTrack/App.xaml @@ -1,7 +1,7 @@ - + xmlns:local="clr-namespace:FinTrackForWindows"> diff --git a/FinTrack/App.xaml.cs b/FinTrack/App.xaml.cs index b9107df..07fb0cd 100644 --- a/FinTrack/App.xaml.cs +++ b/FinTrack/App.xaml.cs @@ -1,16 +1,16 @@ using CommunityToolkit.Mvvm.Messaging; -using FinTrack.Core; -using FinTrack.Services; -using FinTrack.Services.Api; -using FinTrack.ViewModels; -using FinTrack.Views; +using FinTrackForWindows.Core; +using FinTrackForWindows.Services; +using FinTrackForWindows.Services.Api; +using FinTrackForWindows.ViewModels; +using FinTrackForWindows.Views; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Serilog; using System.Windows; -namespace FinTrack +namespace FinTrackForWindows { public partial class App : Application { diff --git a/FinTrack/Core/ISecureTokenStorage.cs b/FinTrack/Core/ISecureTokenStorage.cs index fbce6d5..f80ae4e 100644 --- a/FinTrack/Core/ISecureTokenStorage.cs +++ b/FinTrack/Core/ISecureTokenStorage.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public interface ISecureTokenStorage { diff --git a/FinTrack/Core/NewUserInformationManager.cs b/FinTrack/Core/NewUserInformationManager.cs index 58ea2af..4d8ae93 100644 --- a/FinTrack/Core/NewUserInformationManager.cs +++ b/FinTrack/Core/NewUserInformationManager.cs @@ -1,7 +1,9 @@ -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public static class NewUserInformationManager { + public static string? FirstName { get; set; } + public static string? LastName { get; set; } public static string? FullName { get; set; } public static string? Email { get; set; } public static string? Password { get; set; } diff --git a/FinTrack/Core/RelayCommand.cs b/FinTrack/Core/RelayCommand.cs index d58441f..ddd9a43 100644 --- a/FinTrack/Core/RelayCommand.cs +++ b/FinTrack/Core/RelayCommand.cs @@ -1,6 +1,6 @@ using System.Windows.Input; -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public class RelayCommand : ICommand { diff --git a/FinTrack/Core/SecureTokenStorage.cs b/FinTrack/Core/SecureTokenStorage.cs index 8b47b58..7c962d7 100644 --- a/FinTrack/Core/SecureTokenStorage.cs +++ b/FinTrack/Core/SecureTokenStorage.cs @@ -3,7 +3,7 @@ using System.Security.Cryptography; using System.Text; -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public class SecureTokenStorage : ISecureTokenStorage { diff --git a/FinTrack/Core/SessionManager.cs b/FinTrack/Core/SessionManager.cs index ce97767..4e64fb2 100644 --- a/FinTrack/Core/SessionManager.cs +++ b/FinTrack/Core/SessionManager.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public static class SessionManager { diff --git a/FinTrack/Core/TokenValidator.cs b/FinTrack/Core/TokenValidator.cs index dcc03cf..923a05f 100644 --- a/FinTrack/Core/TokenValidator.cs +++ b/FinTrack/Core/TokenValidator.cs @@ -1,6 +1,6 @@ using System.IdentityModel.Tokens.Jwt; -namespace FinTrack.Core +namespace FinTrackForWindows.Core { public static class TokenValidator { diff --git a/FinTrack/Data/AppDatabaseContext.cs b/FinTrack/Data/AppDatabaseContext.cs index 1acc148..6de625b 100644 --- a/FinTrack/Data/AppDatabaseContext.cs +++ b/FinTrack/Data/AppDatabaseContext.cs @@ -1,8 +1,8 @@ -using FinTrack.Models; +using FinTrackForWindows.Models; using Microsoft.EntityFrameworkCore; using System.IO; -namespace FinTrack.Data +namespace FinTrackForWindows.Data { public class AppDatabaseContext : DbContext { diff --git a/FinTrack/Dtos/AccountDtos/AccountCreateDto.cs b/FinTrack/Dtos/AccountDtos/AccountCreateDto.cs new file mode 100644 index 0000000..225564d --- /dev/null +++ b/FinTrack/Dtos/AccountDtos/AccountCreateDto.cs @@ -0,0 +1,12 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.AccountDtos +{ + public class AccountCreateDto + { + public string Name { get; set; } = null!; + public AccountType Type { get; set; } + public bool IsActive { get; set; } + public BaseCurrencyType Currency { get; set; } + } +} diff --git a/FinTrack/Dtos/AccountDtos/AccountDto.cs b/FinTrack/Dtos/AccountDtos/AccountDto.cs new file mode 100644 index 0000000..9aeb750 --- /dev/null +++ b/FinTrack/Dtos/AccountDtos/AccountDto.cs @@ -0,0 +1,16 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.AccountDtos +{ + public class AccountDto + { + public int Id { get; set; } + public string Name { get; set; } = null!; + public AccountType Type { get; set; } + public bool IsActive { get; set; } + public decimal Balance { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime CreatedAtUtc { get; set; } + public DateTime? UpdatedAtUtc { get; set; } + } +} diff --git a/FinTrack/Dtos/AccountDtos/AccountResponseDto.cs b/FinTrack/Dtos/AccountDtos/AccountResponseDto.cs new file mode 100644 index 0000000..af8d932 --- /dev/null +++ b/FinTrack/Dtos/AccountDtos/AccountResponseDto.cs @@ -0,0 +1,14 @@ +namespace FinTrackForWindows.Dtos.AccountDtos +{ + public class AccountResponseDto + { + public int Id { get; set; } + public int UserId { get; set; } + public string Name { get; set; } + public string Type { get; set; } + public bool IsActive { get; set; } + public decimal Balance { get; set; } + public string Currency { get; set; } + public DateTime CreatedAtUtc { get; set; } + } +} diff --git a/FinTrack/Dtos/AccountDtos/AccountUpdateDto.cs b/FinTrack/Dtos/AccountDtos/AccountUpdateDto.cs new file mode 100644 index 0000000..e118f6d --- /dev/null +++ b/FinTrack/Dtos/AccountDtos/AccountUpdateDto.cs @@ -0,0 +1,12 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.AccountDtos +{ + public class AccountUpdateDto + { + public string Name { get; set; } = null!; + public AccountType Type { get; set; } + public bool IsActive { get; set; } + public BaseCurrencyType Currency { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetCategoryCreateDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetCategoryCreateDto.cs new file mode 100644 index 0000000..bb7d61d --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetCategoryCreateDto.cs @@ -0,0 +1,12 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetCategoryCreateDto + { + public int BudgetId { get; set; } + public int CategoryId { get; set; } + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetCategoryDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetCategoryDto.cs new file mode 100644 index 0000000..1bd77ad --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetCategoryDto.cs @@ -0,0 +1,16 @@ +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetCategoryDto + { + public int Id { get; set; } + public BudgetModel Budget { get; set; } = null!; + public CategoryModel Category { get; set; } = null!; + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime CreatedAtUtc { get; set; } + public DateTime? UpdatedAtUtc { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetCategoryUpdateDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetCategoryUpdateDto.cs new file mode 100644 index 0000000..3be6e93 --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetCategoryUpdateDto.cs @@ -0,0 +1,12 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetCategoryUpdateDto + { + public int BudgetId { get; set; } + public int CategoryId { get; set; } + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetCreateDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetCreateDto.cs new file mode 100644 index 0000000..8097b9a --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetCreateDto.cs @@ -0,0 +1,16 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetCreateDto + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string Category { get; set; } = null!; + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public bool IsActive { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetDto.cs new file mode 100644 index 0000000..384cef0 --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetDto.cs @@ -0,0 +1,19 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetDto + { + public int Id { get; set; } + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string Category { get; set; } = null!; + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public bool IsActive { get; set; } + public DateTime CreatedAtUtc { get; set; } + public DateTime? UpdatedAtUtc { get; set; } + } +} diff --git a/FinTrack/Dtos/BudgetDtos/BudgetUpdateDto.cs b/FinTrack/Dtos/BudgetDtos/BudgetUpdateDto.cs new file mode 100644 index 0000000..c4ec848 --- /dev/null +++ b/FinTrack/Dtos/BudgetDtos/BudgetUpdateDto.cs @@ -0,0 +1,16 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.BudgetDtos +{ + public class BudgetUpdateDto + { + public string Name { get; set; } = null!; + public string? Description { get; set; } + public string Category { get; set; } = null!; + public decimal AllocatedAmount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public bool IsActive { get; set; } + } +} diff --git a/FinTrack/Dtos/ChatDtos/ChatRequestDto.cs b/FinTrack/Dtos/ChatDtos/ChatRequestDto.cs new file mode 100644 index 0000000..c3e3bbc --- /dev/null +++ b/FinTrack/Dtos/ChatDtos/ChatRequestDto.cs @@ -0,0 +1,8 @@ +namespace FinTrackForWindows.Dtos.ChatDtos +{ + public class ChatRequestDto + { + public string Message { get; set; } = string.Empty; + public string? ClientChatSessionId { get; set; } + } +} diff --git a/FinTrack/Dtos/ChatDtos/ChatResponseDto.cs b/FinTrack/Dtos/ChatDtos/ChatResponseDto.cs new file mode 100644 index 0000000..b79b81f --- /dev/null +++ b/FinTrack/Dtos/ChatDtos/ChatResponseDto.cs @@ -0,0 +1,8 @@ +namespace FinTrackForWindows.Dtos.ChatDtos +{ + public class ChatResponseDto + { + public string? Reply { get; set; } + public DateTime ResponseTime { get; set; } + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/CalculatedRatesDto.cs b/FinTrack/Dtos/CurrencyDtos/CalculatedRatesDto.cs new file mode 100644 index 0000000..5e97352 --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/CalculatedRatesDto.cs @@ -0,0 +1,9 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class CalculatedRatesDto + { + public DateTime SnapshotTimestamp { get; set; } + public string BaseCurrency { get; set; } = string.Empty; + public Dictionary CrossRates { get; set; } = new(); + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/ChangeSummaryDto.cs b/FinTrack/Dtos/CurrencyDtos/ChangeSummaryDto.cs new file mode 100644 index 0000000..e8c9726 --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/ChangeSummaryDto.cs @@ -0,0 +1,15 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class ChangeSummaryDto + { + // Değişim Miktarı + public decimal? DailyChangeValue { get; set; } + public decimal? WeeklyChangeValue { get; set; } + public decimal? MonthlyChangeValue { get; set; } + + // Değişim Oranı + public decimal? DailyChangePercentage { get; set; } + public decimal? WeeklyChangePercentage { get; set; } + public decimal? MonthlyChangePercentage { get; set; } + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/CurrencyHistoryDto.cs b/FinTrack/Dtos/CurrencyDtos/CurrencyHistoryDto.cs new file mode 100644 index 0000000..6e1bf38 --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/CurrencyHistoryDto.cs @@ -0,0 +1,14 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class CurrencyHistoryDto + { + public string BaseCurrency { get; set; } = string.Empty; + public string TargetCurrency { get; set; } = string.Empty; + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + + public ChangeSummaryDto ChangeSummary { get; set; } = new(); + + public List HistoricalRates { get; set; } = new(); + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/CurrencySummaryDto.cs b/FinTrack/Dtos/CurrencyDtos/CurrencySummaryDto.cs new file mode 100644 index 0000000..0d691bc --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/CurrencySummaryDto.cs @@ -0,0 +1,10 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class CurrencySummaryDto + { + public int Id { get; set; } + public string Code { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string? IconUrl { get; set; } + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/HistoricalRatePointDto.cs b/FinTrack/Dtos/CurrencyDtos/HistoricalRatePointDto.cs new file mode 100644 index 0000000..2e7f8a2 --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/HistoricalRatePointDto.cs @@ -0,0 +1,8 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class HistoricalRatePointDto + { + public DateTime Date { get; set; } + public decimal Rate { get; set; } + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/LatestRatesResponseDto.cs b/FinTrack/Dtos/CurrencyDtos/LatestRatesResponseDto.cs new file mode 100644 index 0000000..35452db --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/LatestRatesResponseDto.cs @@ -0,0 +1,9 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class LatestRatesResponseDto + { + public string BaseCurrency { get; set; } = string.Empty; + public DateTime SnapshotTimestamp { get; set; } + public List Rates { get; set; } = new(); + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/RateDetailDto.cs b/FinTrack/Dtos/CurrencyDtos/RateDetailDto.cs new file mode 100644 index 0000000..96b0961 --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/RateDetailDto.cs @@ -0,0 +1,14 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class RateDetailDto + { + public int Id { get; set; } + public string Code { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + public string? CountryName { get; set; } + public string? CountryCode { get; set; } + public string? IconUrl { get; set; } + + public decimal Rate { get; set; } + } +} diff --git a/FinTrack/Dtos/CurrencyDtos/SpecificCurrencyDto.cs b/FinTrack/Dtos/CurrencyDtos/SpecificCurrencyDto.cs new file mode 100644 index 0000000..195695a --- /dev/null +++ b/FinTrack/Dtos/CurrencyDtos/SpecificCurrencyDto.cs @@ -0,0 +1,17 @@ +namespace FinTrackWebApi.Dtos.CurrencyDtos +{ + public class SpecificCurrencyDto + { + public int Id { get; set; } + public string CurrencyCode { get; set; } = string.Empty; + public string CurrencyName { get; set; } = string.Empty; + public string? CountryCode { get; set; } + public string? CountryName { get; set; } + public string? Status { get; set; } + public DateTime? AvailableFrom { get; set; } + public DateTime? AvailableUntil { get; set; } + public string? IconUrl { get; set; } + + public CalculatedRatesDto? RatesInfo { get; set; } + } +} diff --git a/FinTrack/Dtos/LoginRequestDto.cs b/FinTrack/Dtos/LoginRequestDto.cs index abdc3ee..aa1df57 100644 --- a/FinTrack/Dtos/LoginRequestDto.cs +++ b/FinTrack/Dtos/LoginRequestDto.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Dtos +namespace FinTrackForWindows.Dtos { public class LoginRequestDto { diff --git a/FinTrack/Dtos/RegisterRequestDto.cs b/FinTrack/Dtos/RegisterRequestDto.cs index d2060b4..e66f45e 100644 --- a/FinTrack/Dtos/RegisterRequestDto.cs +++ b/FinTrack/Dtos/RegisterRequestDto.cs @@ -1,8 +1,9 @@ -namespace FinTrack.Dtos +namespace FinTrackForWindows.Dtos { public class RegisterRequestDto { - public string? UserName { get; set; } + public string FirstName { get; set; } = null!; + public string LastName { get; set; } = null!; public string Email { get; set; } = null!; public string Password { get; set; } = null!; public string? ProfilePicture { get; set; } diff --git a/FinTrack/Dtos/TransactionDtos/TransactionCategoriesDto.cs b/FinTrack/Dtos/TransactionDtos/TransactionCategoriesDto.cs new file mode 100644 index 0000000..9d7f1e1 --- /dev/null +++ b/FinTrack/Dtos/TransactionDtos/TransactionCategoriesDto.cs @@ -0,0 +1,13 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.TransactionDtos +{ + public class TransactionCategoriesDto + { + public int Id { get; set; } + public string Name { get; set; } = null!; + public TransactionType Type { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime? UpdatedAt { get; set; } + } +} diff --git a/FinTrack/Dtos/TransactionDtos/TransactionCreateDto.cs b/FinTrack/Dtos/TransactionDtos/TransactionCreateDto.cs new file mode 100644 index 0000000..999d5db --- /dev/null +++ b/FinTrack/Dtos/TransactionDtos/TransactionCreateDto.cs @@ -0,0 +1,14 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.TransactionDtos +{ + public class TransactionCreateDto + { + public int CategoryId { get; set; } + public int AccountId { get; set; } + public decimal Amount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime TransactionDateUtc { get; set; } + public string? Description { get; set; } + } +} diff --git a/FinTrack/Dtos/TransactionDtos/TransactionDto.cs b/FinTrack/Dtos/TransactionDtos/TransactionDto.cs new file mode 100644 index 0000000..2cad418 --- /dev/null +++ b/FinTrack/Dtos/TransactionDtos/TransactionDto.cs @@ -0,0 +1,18 @@ +using FinTrackForWindows.Dtos.AccountDtos; +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.TransactionDtos +{ + public class TransactionDto + { + public int Id { get; set; } + public TransactionCategoriesDto Category { get; set; } = null!; + public AccountDto Account { get; set; } = null!; + public decimal Amount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime TransactionDateUtc { get; set; } + public string? Description { get; set; } + public DateTime CreatedAtUtc { get; set; } + public DateTime? UpdatedAtUtc { get; set; } + } +} diff --git a/FinTrack/Dtos/TransactionDtos/TransactionUpdateDto.cs b/FinTrack/Dtos/TransactionDtos/TransactionUpdateDto.cs new file mode 100644 index 0000000..f8542f3 --- /dev/null +++ b/FinTrack/Dtos/TransactionDtos/TransactionUpdateDto.cs @@ -0,0 +1,14 @@ +using FinTrackForWindows.Enums; + +namespace FinTrackForWindows.Dtos.TransactionDtos +{ + public class TransactionUpdateDto + { + public int CategoryId { get; set; } + public int AccountId { get; set; } + public decimal Amount { get; set; } + public BaseCurrencyType Currency { get; set; } + public DateTime TransactionDateUtc { get; set; } + public string? Description { get; set; } + } +} diff --git a/FinTrack/Dtos/UserProfileDto.cs b/FinTrack/Dtos/UserProfileDto.cs index 0a1d288..90bcd69 100644 --- a/FinTrack/Dtos/UserProfileDto.cs +++ b/FinTrack/Dtos/UserProfileDto.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Dtos +namespace FinTrackForWindows.Dtos { public class UserProfileDto { diff --git a/FinTrack/Enums/AccountType.cs b/FinTrack/Enums/AccountType.cs index a765051..ca115da 100644 --- a/FinTrack/Enums/AccountType.cs +++ b/FinTrack/Enums/AccountType.cs @@ -1,13 +1,28 @@ -namespace FinTrack.Enums +using System.ComponentModel; + +namespace FinTrackForWindows.Enums { public enum AccountType { + [Description("Checking")] Checking, + + [Description("Savings")] Savings, + + [Description("Credit Card")] CreditCard, + + [Description("Cash")] Cash, + + [Description("Investment")] Investment, + + [Description("Loan")] Loan, + + [Description("Other")] Other, } // Kontrol, Tasarruf, Kredi Kartı, Nakit, Yatırım, Kredi, Diğer } diff --git a/FinTrack/Enums/AppearanceType.cs b/FinTrack/Enums/AppearanceType.cs index 42a2505..4d8995f 100644 --- a/FinTrack/Enums/AppearanceType.cs +++ b/FinTrack/Enums/AppearanceType.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum AppearanceType { diff --git a/FinTrack/Enums/BaseCurrencyType.cs b/FinTrack/Enums/BaseCurrencyType.cs index 2190ef7..d492662 100644 --- a/FinTrack/Enums/BaseCurrencyType.cs +++ b/FinTrack/Enums/BaseCurrencyType.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum BaseCurrencyType { diff --git a/FinTrack/Enums/CurrencyConversionType.cs b/FinTrack/Enums/CurrencyConversionType.cs index 0b8a3a7..9ddad28 100644 --- a/FinTrack/Enums/CurrencyConversionType.cs +++ b/FinTrack/Enums/CurrencyConversionType.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum CurrencyConversionType { Increase, Decrease } } diff --git a/FinTrack/Enums/DebtStatus.cs b/FinTrack/Enums/DebtStatus.cs index 1ff5f46..5a78272 100644 --- a/FinTrack/Enums/DebtStatus.cs +++ b/FinTrack/Enums/DebtStatus.cs @@ -1,13 +1,15 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { - public enum DebtStatus + public enum DebtStatusType { - PendingProposal, // Teklif gönderildi, borçlunun onayı bekleniyor - AwaitingVideoUpload, // Teklif kabul edildi, video yüklenmesi bekleniyor - AwaitingOperatorApproval,// Video yüklendi, operatör onayı bekleniyor - Active, // Operatör onayladı, borç aktif - RejectedByBorrower, // Borçlu teklifi reddetti - RejectedByOperator, // Operatör videoyu reddetti - Completed // Borç ödendi + PendingBorrowerAcceptance, // Borç Alan Onayı Bekliyor + PendingOperatorApproval, // Operatör Onayı Bekliyor (eğer varsa) + Active, // Aktif Borç + PaymentConfirmationPending, // Ödeme Onayı Bekliyor + Paid, // Ödendi + Defaulted, // Vadesi Geçmiş/Ödenmemiş + RejectedByBorrower, // Borç Alan Tarafından Reddedildi + RejectedByOperator, // Operatör Tarafından Reddedildi (eğer varsa) + CancelledByLender, // Borç Veren Tarafından İptal Edildi } } diff --git a/FinTrack/Enums/ExportFormat.cs b/FinTrack/Enums/ExportFormat.cs index 53bd38e..e60e973 100644 --- a/FinTrack/Enums/ExportFormat.cs +++ b/FinTrack/Enums/ExportFormat.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum ExportFormat { diff --git a/FinTrack/Enums/FeedbackTypes.cs b/FinTrack/Enums/FeedbackTypes.cs index ef2c4a2..c310365 100644 --- a/FinTrack/Enums/FeedbackTypes.cs +++ b/FinTrack/Enums/FeedbackTypes.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum FeedbackTypes { diff --git a/FinTrack/Enums/MessageAuthor.cs b/FinTrack/Enums/MessageAuthor.cs index c65caa4..2109baa 100644 --- a/FinTrack/Enums/MessageAuthor.cs +++ b/FinTrack/Enums/MessageAuthor.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum MessageAuthor { diff --git a/FinTrack/Enums/NotificationSettingsType.cs b/FinTrack/Enums/NotificationSettingsType.cs index 72f8842..30b966e 100644 --- a/FinTrack/Enums/NotificationSettingsType.cs +++ b/FinTrack/Enums/NotificationSettingsType.cs @@ -1,6 +1,6 @@ using System.ComponentModel; -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum NotificationSettingsType { diff --git a/FinTrack/Enums/NotificationType.cs b/FinTrack/Enums/NotificationType.cs index 6ad2037..a5627b8 100644 --- a/FinTrack/Enums/NotificationType.cs +++ b/FinTrack/Enums/NotificationType.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum NotificationType { diff --git a/FinTrack/Enums/ReportType.cs b/FinTrack/Enums/ReportType.cs index b3624b4..c46aed6 100644 --- a/FinTrack/Enums/ReportType.cs +++ b/FinTrack/Enums/ReportType.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum ReportType { diff --git a/FinTrack/Enums/TransactionType.cs b/FinTrack/Enums/TransactionType.cs index bdd9c06..58f65d2 100644 --- a/FinTrack/Enums/TransactionType.cs +++ b/FinTrack/Enums/TransactionType.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Enums +namespace FinTrackForWindows.Enums { public enum TransactionType { Income, Expense } } diff --git a/FinTrack/FinTrack.csproj b/FinTrack/FinTrackForWindows.csproj similarity index 93% rename from FinTrack/FinTrack.csproj rename to FinTrack/FinTrackForWindows.csproj index 01f2a6c..19aaa5b 100644 --- a/FinTrack/FinTrack.csproj +++ b/FinTrack/FinTrackForWindows.csproj @@ -37,28 +37,28 @@ + - - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + - - + + - + @@ -88,6 +88,9 @@ + + Always + Never diff --git a/FinTrack/FinTrack.sln b/FinTrack/FinTrackForWindows.sln similarity index 83% rename from FinTrack/FinTrack.sln rename to FinTrack/FinTrackForWindows.sln index 2575711..38104f7 100644 --- a/FinTrack/FinTrack.sln +++ b/FinTrack/FinTrackForWindows.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.13.35825.156 d17.13 +VisualStudioVersion = 17.13.35825.156 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FinTrack", "FinTrack.csproj", "{B7CE2567-A28C-4C69-A810-B1C93DF8E9BD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FinTrackForWindows", "FinTrackForWindows.csproj", "{B7CE2567-A28C-4C69-A810-B1C93DF8E9BD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/FinTrack/Helpers/BooleanToVisibilityConverter.cs b/FinTrack/Helpers/BooleanToVisibilityConverter.cs index 0289e15..8904d84 100644 --- a/FinTrack/Helpers/BooleanToVisibilityConverter.cs +++ b/FinTrack/Helpers/BooleanToVisibilityConverter.cs @@ -2,7 +2,7 @@ using System.Windows; using System.Windows.Data; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public class BooleanToVisibilityConverter : IValueConverter { diff --git a/FinTrack/Helpers/BrushToLvcPaintConverter.cs b/FinTrack/Helpers/BrushToLvcPaintConverter.cs new file mode 100644 index 0000000..8f685c1 --- /dev/null +++ b/FinTrack/Helpers/BrushToLvcPaintConverter.cs @@ -0,0 +1,25 @@ +using LiveChartsCore.SkiaSharpView.Painting; +using SkiaSharp; +using System.Globalization; +using System.Windows.Data; +using System.Windows.Media; + +namespace FinTrackForWindows.Helpers +{ + public class BrushToLvcPaintConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is SolidColorBrush brush) + { + return new SolidColorPaint(new SKColor(brush.Color.R, brush.Color.G, brush.Color.B, brush.Color.A)); + } + return new SolidColorPaint(SKColors.Black); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/FinTrack/Helpers/EnumToBooleanConverter.cs b/FinTrack/Helpers/EnumToBooleanConverter.cs index fbaf04f..2e6fdb6 100644 --- a/FinTrack/Helpers/EnumToBooleanConverter.cs +++ b/FinTrack/Helpers/EnumToBooleanConverter.cs @@ -1,7 +1,7 @@ using System.Globalization; using System.Windows.Data; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public class EnumToBooleanConverter : IValueConverter { diff --git a/FinTrack/Helpers/EnumToDescriptionConverter.cs b/FinTrack/Helpers/EnumToDescriptionConverter.cs index 22f0afa..e3f8744 100644 --- a/FinTrack/Helpers/EnumToDescriptionConverter.cs +++ b/FinTrack/Helpers/EnumToDescriptionConverter.cs @@ -3,7 +3,7 @@ using System.Windows; using System.Windows.Data; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public class EnumToDescriptionConverter : IValueConverter { diff --git a/FinTrack/Helpers/InvertedBooleanToVisibilityConverter.cs b/FinTrack/Helpers/InvertedBooleanToVisibilityConverter.cs index d0f7317..1674d12 100644 --- a/FinTrack/Helpers/InvertedBooleanToVisibilityConverter.cs +++ b/FinTrack/Helpers/InvertedBooleanToVisibilityConverter.cs @@ -2,7 +2,7 @@ using System.Windows; using System.Windows.Data; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public class InvertedBooleanToVisibilityConverter : IValueConverter { diff --git a/FinTrack/Helpers/NullToVisibilityConverter.cs b/FinTrack/Helpers/NullToVisibilityConverter.cs index 5fc0802..3382791 100644 --- a/FinTrack/Helpers/NullToVisibilityConverter.cs +++ b/FinTrack/Helpers/NullToVisibilityConverter.cs @@ -2,7 +2,7 @@ using System.Windows; using System.Windows.Data; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public class NullToVisibilityConverter : IValueConverter { diff --git a/FinTrack/Helpers/PasswordBoxAssistant.cs b/FinTrack/Helpers/PasswordBoxAssistant.cs index 1a2683b..b0fbfbe 100644 --- a/FinTrack/Helpers/PasswordBoxAssistant.cs +++ b/FinTrack/Helpers/PasswordBoxAssistant.cs @@ -1,7 +1,7 @@ using System.Windows; using System.Windows.Controls; -namespace FinTrack.Helpers +namespace FinTrackForWindows.Helpers { public static class PasswordBoxAssistant { diff --git a/FinTrack/Messages/LoginSuccessMessage.cs b/FinTrack/Messages/LoginSuccessMessage.cs index 24f6258..c4a27e1 100644 --- a/FinTrack/Messages/LoginSuccessMessage.cs +++ b/FinTrack/Messages/LoginSuccessMessage.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Messages +namespace FinTrackForWindows.Messages { public class LoginSuccessMessage { } } diff --git a/FinTrack/Messages/NavigationMessage.cs b/FinTrack/Messages/NavigationMessage.cs index 3a4e8a4..8041a72 100644 --- a/FinTrack/Messages/NavigationMessage.cs +++ b/FinTrack/Messages/NavigationMessage.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Messages +namespace FinTrackForWindows.Messages { public class LoginSuccessMessag { diff --git a/FinTrack/Migrations/20250626151252_InitialCreate.Designer.cs b/FinTrack/Migrations/20250626151252_InitialCreate.Designer.cs deleted file mode 100644 index 4da329e..0000000 --- a/FinTrack/Migrations/20250626151252_InitialCreate.Designer.cs +++ /dev/null @@ -1,533 +0,0 @@ -// -using System; -using FinTrack.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace FinTrack.Migrations -{ - [DbContext(typeof(AppDatabaseContext))] - [Migration("20250626151252_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.6"); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Balance") - .HasColumnType("decimal(18, 2)") - .HasColumnName("Balance"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreateAt"); - - b.Property("IsActive") - .HasColumnType("INTEGER") - .HasColumnName("IsActive"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("Name"); - - b.Property("Type") - .HasColumnType("INTEGER") - .HasColumnName("AccountType"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdateAt"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Name") - .IsUnique(); - - b.ToTable("Accounts", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetCategoryModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AllocatedAmount") - .HasColumnType("decimal(18, 2)") - .HasColumnName("AllocatedAmount"); - - b.Property("BudgetId") - .HasColumnType("INTEGER") - .HasColumnName("BudgetId"); - - b.Property("CategoryId") - .HasColumnType("INTEGER") - .HasColumnName("CategoryId"); - - b.HasKey("Id"); - - b.HasIndex("CategoryId"); - - b.HasIndex("BudgetId", "CategoryId") - .IsUnique(); - - b.ToTable("BudgetCategories", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreatedAtUtc"); - - b.Property("Description") - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("Description"); - - b.Property("EndDate") - .HasColumnType("TEXT") - .HasColumnName("EndDate"); - - b.Property("IsActive") - .HasColumnType("INTEGER") - .HasColumnName("IsActive"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("BudgetName"); - - b.Property("StartDate") - .HasColumnType("TEXT") - .HasColumnName("StartDate"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdatedAtUtc"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("User"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("Budgets", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("CategoryName"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("CategoryType"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("User"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Name", "Type") - .IsUnique(); - - b.ToTable("Categories", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.NotificationModel", b => - { - b.Property("NotificationId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAtUtc") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("CreatedAtUtc") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("IsRead") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER") - .HasDefaultValue(false) - .HasColumnName("IsRead"); - - b.Property("MessageBody") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT") - .HasColumnName("MessageBody"); - - b.Property("MessageHead") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT") - .HasColumnName("MessageHead"); - - b.Property("NotificationType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("NotificationType"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("NotificationId"); - - b.HasIndex("UserId"); - - b.ToTable("Notifications", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.TransactionModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccountId") - .HasColumnType("INTEGER") - .HasColumnName("AccountId"); - - b.Property("Amount") - .HasColumnType("decimal(18, 2)") - .HasColumnName("Amount"); - - b.Property("CategoryId") - .HasColumnType("INTEGER") - .HasColumnName("CategoryId"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreatedAt"); - - b.Property("Description") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("Description"); - - b.Property("TransactionDateUtc") - .HasColumnType("TEXT") - .HasColumnName("TransactionDate"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdatedAt"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("AccountId"); - - b.HasIndex("CategoryId"); - - b.HasIndex("TransactionDateUtc"); - - b.HasIndex("UserId"); - - b.ToTable("Transactions", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.UserModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER") - .HasColumnName("AccessFailedCount"); - - b.Property("ConcurrencyStamp") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreateAt") - .HasColumnType("TEXT") - .HasColumnName("CreateAt"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("Email"); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER") - .HasColumnName("EmailConfirmed"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER") - .HasColumnName("LockoutEnabled"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT") - .HasColumnName("LockoutEnd"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("NormalizedEmail"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("NormalizedUserName"); - - b.Property("PasswordHash") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("PasswordHash"); - - b.Property("PhoneNumber") - .HasMaxLength(15) - .HasColumnType("TEXT") - .HasColumnName("PhoneNumber"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER") - .HasColumnName("PhoneNumberConfirmed"); - - b.Property("ProfilePicture") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("ProfilePicture"); - - b.Property("SecurityStamp") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("SecurityStamp"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER") - .HasColumnName("TwoFactorEnabled"); - - b.Property("UserName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("UserName"); - - b.HasKey("Id"); - - b.ToTable("Users", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.UserSettingsModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Currency") - .IsRequired() - .HasMaxLength(10) - .HasColumnType("TEXT") - .HasColumnName("Currency"); - - b.Property("EntryDate") - .HasColumnType("TEXT") - .HasColumnName("EntryDate"); - - b.Property("Language") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("Language"); - - b.Property("Notification") - .HasColumnType("INTEGER") - .HasColumnName("Notification"); - - b.Property("Theme") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("Theme"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("UserSettings", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Accounts") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetCategoryModel", b => - { - b.HasOne("FinTrack.Models.BudgetModel", "Budget") - .WithMany("BudgetCategories") - .HasForeignKey("BudgetId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("FinTrack.Models.CategoryModel", "Category") - .WithMany("BudgetAllocations") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Budget"); - - b.Navigation("Category"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Budgets") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Categories") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.NotificationModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Notifications") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.TransactionModel", b => - { - b.HasOne("FinTrack.Models.AccountModel", "Account") - .WithMany("Transactions") - .HasForeignKey("AccountId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("FinTrack.Models.CategoryModel", "Category") - .WithMany("Transactions") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Transactions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Account"); - - b.Navigation("Category"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.UserSettingsModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithOne("UserSettings") - .HasForeignKey("FinTrack.Models.UserSettingsModel", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.Navigation("BudgetCategories"); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.Navigation("BudgetAllocations"); - - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("FinTrack.Models.UserModel", b => - { - b.Navigation("Accounts"); - - b.Navigation("Budgets"); - - b.Navigation("Categories"); - - b.Navigation("Notifications"); - - b.Navigation("Transactions"); - - b.Navigation("UserSettings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/FinTrack/Migrations/20250626151252_InitialCreate.cs b/FinTrack/Migrations/20250626151252_InitialCreate.cs deleted file mode 100644 index 118c4c8..0000000 --- a/FinTrack/Migrations/20250626151252_InitialCreate.cs +++ /dev/null @@ -1,282 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace FinTrack.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Accounts", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(type: "INTEGER", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - AccountType = table.Column(type: "INTEGER", nullable: false), - IsActive = table.Column(type: "INTEGER", nullable: false), - Balance = table.Column(type: "decimal(18, 2)", nullable: false), - CreateAt = table.Column(type: "TEXT", nullable: false), - UpdateAt = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Accounts", x => x.Id); - table.ForeignKey( - name: "FK_Accounts_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Budgets", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - User = table.Column(type: "INTEGER", nullable: false), - BudgetName = table.Column(type: "TEXT", nullable: false), - Description = table.Column(type: "TEXT", maxLength: 500, nullable: true), - StartDate = table.Column(type: "TEXT", nullable: false), - EndDate = table.Column(type: "TEXT", nullable: false), - IsActive = table.Column(type: "INTEGER", nullable: false), - CreatedAtUtc = table.Column(type: "TEXT", nullable: false), - UpdatedAtUtc = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Budgets", x => x.Id); - table.ForeignKey( - name: "FK_Budgets_Users_User", - column: x => x.User, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Categories", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - User = table.Column(type: "INTEGER", nullable: false), - CategoryName = table.Column(type: "TEXT", nullable: false), - CategoryType = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Categories", x => x.Id); - table.ForeignKey( - name: "FK_Categories_Users_User", - column: x => x.User, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Notifications", - columns: table => new - { - NotificationId = table.Column(type: "TEXT", nullable: false), - UserId = table.Column(type: "INTEGER", nullable: false), - MessageHead = table.Column(type: "TEXT", maxLength: 200, nullable: false), - MessageBody = table.Column(type: "TEXT", maxLength: 1000, nullable: false), - NotificationType = table.Column(type: "TEXT", maxLength: 50, nullable: false), - CreatedAtUtc = table.Column(type: "TEXT", nullable: false, defaultValueSql: "CURRENT_TIMESTAMP"), - IsRead = table.Column(type: "INTEGER", nullable: false, defaultValue: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Notifications", x => x.NotificationId); - table.ForeignKey( - name: "FK_Notifications_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserSettings", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(type: "INTEGER", nullable: false), - Theme = table.Column(type: "TEXT", maxLength: 50, nullable: false), - Language = table.Column(type: "TEXT", maxLength: 50, nullable: false), - Currency = table.Column(type: "TEXT", maxLength: 10, nullable: false), - Notification = table.Column(type: "INTEGER", nullable: false), - EntryDate = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_UserSettings", x => x.Id); - table.ForeignKey( - name: "FK_UserSettings_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "BudgetCategories", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - BudgetId = table.Column(type: "INTEGER", nullable: false), - CategoryId = table.Column(type: "INTEGER", nullable: false), - AllocatedAmount = table.Column(type: "decimal(18, 2)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BudgetCategories", x => x.Id); - table.ForeignKey( - name: "FK_BudgetCategories_Budgets_BudgetId", - column: x => x.BudgetId, - principalTable: "Budgets", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_BudgetCategories_Categories_CategoryId", - column: x => x.CategoryId, - principalTable: "Categories", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "Transactions", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(type: "INTEGER", nullable: false), - CategoryId = table.Column(type: "INTEGER", nullable: false), - AccountId = table.Column(type: "INTEGER", nullable: false), - Amount = table.Column(type: "decimal(18, 2)", nullable: false), - TransactionDate = table.Column(type: "TEXT", nullable: false), - Description = table.Column(type: "TEXT", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false), - UpdatedAt = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Transactions", x => x.Id); - table.ForeignKey( - name: "FK_Transactions_Accounts_AccountId", - column: x => x.AccountId, - principalTable: "Accounts", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Transactions_Categories_CategoryId", - column: x => x.CategoryId, - principalTable: "Categories", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - table.ForeignKey( - name: "FK_Transactions_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Accounts_UserId_Name", - table: "Accounts", - columns: new[] { "UserId", "Name" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_BudgetCategories_BudgetId_CategoryId", - table: "BudgetCategories", - columns: new[] { "BudgetId", "CategoryId" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_BudgetCategories_CategoryId", - table: "BudgetCategories", - column: "CategoryId"); - - migrationBuilder.CreateIndex( - name: "IX_Budgets_User", - table: "Budgets", - column: "User"); - - migrationBuilder.CreateIndex( - name: "IX_Categories_User_CategoryName_CategoryType", - table: "Categories", - columns: new[] { "User", "CategoryName", "CategoryType" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Notifications_UserId", - table: "Notifications", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_AccountId", - table: "Transactions", - column: "AccountId"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_CategoryId", - table: "Transactions", - column: "CategoryId"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_TransactionDate", - table: "Transactions", - column: "TransactionDate"); - - migrationBuilder.CreateIndex( - name: "IX_Transactions_UserId", - table: "Transactions", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_UserSettings_UserId", - table: "UserSettings", - column: "UserId", - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "BudgetCategories"); - - migrationBuilder.DropTable( - name: "Notifications"); - - migrationBuilder.DropTable( - name: "Transactions"); - - migrationBuilder.DropTable( - name: "UserSettings"); - - migrationBuilder.DropTable( - name: "Budgets"); - - migrationBuilder.DropTable( - name: "Accounts"); - - migrationBuilder.DropTable( - name: "Categories"); - } - } -} diff --git a/FinTrack/Migrations/AppDatabaseContextModelSnapshot.cs b/FinTrack/Migrations/AppDatabaseContextModelSnapshot.cs deleted file mode 100644 index ab59592..0000000 --- a/FinTrack/Migrations/AppDatabaseContextModelSnapshot.cs +++ /dev/null @@ -1,530 +0,0 @@ -// -using System; -using FinTrack.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace FinTrack.Migrations -{ - [DbContext(typeof(AppDatabaseContext))] - partial class AppDatabaseContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.6"); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Balance") - .HasColumnType("decimal(18, 2)") - .HasColumnName("Balance"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreateAt"); - - b.Property("IsActive") - .HasColumnType("INTEGER") - .HasColumnName("IsActive"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("Name"); - - b.Property("Type") - .HasColumnType("INTEGER") - .HasColumnName("AccountType"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdateAt"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Name") - .IsUnique(); - - b.ToTable("Accounts", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetCategoryModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AllocatedAmount") - .HasColumnType("decimal(18, 2)") - .HasColumnName("AllocatedAmount"); - - b.Property("BudgetId") - .HasColumnType("INTEGER") - .HasColumnName("BudgetId"); - - b.Property("CategoryId") - .HasColumnType("INTEGER") - .HasColumnName("CategoryId"); - - b.HasKey("Id"); - - b.HasIndex("CategoryId"); - - b.HasIndex("BudgetId", "CategoryId") - .IsUnique(); - - b.ToTable("BudgetCategories", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreatedAtUtc"); - - b.Property("Description") - .HasMaxLength(500) - .HasColumnType("TEXT") - .HasColumnName("Description"); - - b.Property("EndDate") - .HasColumnType("TEXT") - .HasColumnName("EndDate"); - - b.Property("IsActive") - .HasColumnType("INTEGER") - .HasColumnName("IsActive"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("BudgetName"); - - b.Property("StartDate") - .HasColumnType("TEXT") - .HasColumnName("StartDate"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdatedAtUtc"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("User"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("Budgets", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("CategoryName"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("CategoryType"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("User"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Name", "Type") - .IsUnique(); - - b.ToTable("Categories", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.NotificationModel", b => - { - b.Property("NotificationId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CreatedAtUtc") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("CreatedAtUtc") - .HasDefaultValueSql("CURRENT_TIMESTAMP"); - - b.Property("IsRead") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER") - .HasDefaultValue(false) - .HasColumnName("IsRead"); - - b.Property("MessageBody") - .IsRequired() - .HasMaxLength(1000) - .HasColumnType("TEXT") - .HasColumnName("MessageBody"); - - b.Property("MessageHead") - .IsRequired() - .HasMaxLength(200) - .HasColumnType("TEXT") - .HasColumnName("MessageHead"); - - b.Property("NotificationType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("NotificationType"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("NotificationId"); - - b.HasIndex("UserId"); - - b.ToTable("Notifications", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.TransactionModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccountId") - .HasColumnType("INTEGER") - .HasColumnName("AccountId"); - - b.Property("Amount") - .HasColumnType("decimal(18, 2)") - .HasColumnName("Amount"); - - b.Property("CategoryId") - .HasColumnType("INTEGER") - .HasColumnName("CategoryId"); - - b.Property("CreatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("CreatedAt"); - - b.Property("Description") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("Description"); - - b.Property("TransactionDateUtc") - .HasColumnType("TEXT") - .HasColumnName("TransactionDate"); - - b.Property("UpdatedAtUtc") - .HasColumnType("TEXT") - .HasColumnName("UpdatedAt"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("AccountId"); - - b.HasIndex("CategoryId"); - - b.HasIndex("TransactionDateUtc"); - - b.HasIndex("UserId"); - - b.ToTable("Transactions", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.UserModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER") - .HasColumnName("AccessFailedCount"); - - b.Property("ConcurrencyStamp") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("ConcurrencyStamp"); - - b.Property("CreateAt") - .HasColumnType("TEXT") - .HasColumnName("CreateAt"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("Email"); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER") - .HasColumnName("EmailConfirmed"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER") - .HasColumnName("LockoutEnabled"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT") - .HasColumnName("LockoutEnd"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("NormalizedEmail"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("NormalizedUserName"); - - b.Property("PasswordHash") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("PasswordHash"); - - b.Property("PhoneNumber") - .HasMaxLength(15) - .HasColumnType("TEXT") - .HasColumnName("PhoneNumber"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER") - .HasColumnName("PhoneNumberConfirmed"); - - b.Property("ProfilePicture") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("ProfilePicture"); - - b.Property("SecurityStamp") - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("SecurityStamp"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER") - .HasColumnName("TwoFactorEnabled"); - - b.Property("UserName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT") - .HasColumnName("UserName"); - - b.HasKey("Id"); - - b.ToTable("Users", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.UserSettingsModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Currency") - .IsRequired() - .HasMaxLength(10) - .HasColumnType("TEXT") - .HasColumnName("Currency"); - - b.Property("EntryDate") - .HasColumnType("TEXT") - .HasColumnName("EntryDate"); - - b.Property("Language") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("Language"); - - b.Property("Notification") - .HasColumnType("INTEGER") - .HasColumnName("Notification"); - - b.Property("Theme") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("TEXT") - .HasColumnName("Theme"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("UserSettings", (string)null); - }); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Accounts") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetCategoryModel", b => - { - b.HasOne("FinTrack.Models.BudgetModel", "Budget") - .WithMany("BudgetCategories") - .HasForeignKey("BudgetId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("FinTrack.Models.CategoryModel", "Category") - .WithMany("BudgetAllocations") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.Navigation("Budget"); - - b.Navigation("Category"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Budgets") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Categories") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.NotificationModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Notifications") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.TransactionModel", b => - { - b.HasOne("FinTrack.Models.AccountModel", "Account") - .WithMany("Transactions") - .HasForeignKey("AccountId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("FinTrack.Models.CategoryModel", "Category") - .WithMany("Transactions") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); - - b.HasOne("FinTrack.Models.UserModel", "User") - .WithMany("Transactions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Account"); - - b.Navigation("Category"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.UserSettingsModel", b => - { - b.HasOne("FinTrack.Models.UserModel", "User") - .WithOne("UserSettings") - .HasForeignKey("FinTrack.Models.UserSettingsModel", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("FinTrack.Models.AccountModel", b => - { - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("FinTrack.Models.BudgetModel", b => - { - b.Navigation("BudgetCategories"); - }); - - modelBuilder.Entity("FinTrack.Models.CategoryModel", b => - { - b.Navigation("BudgetAllocations"); - - b.Navigation("Transactions"); - }); - - modelBuilder.Entity("FinTrack.Models.UserModel", b => - { - b.Navigation("Accounts"); - - b.Navigation("Budgets"); - - b.Navigation("Categories"); - - b.Navigation("Notifications"); - - b.Navigation("Transactions"); - - b.Navigation("UserSettings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/FinTrack/Models/Account/AccountBalanceHistoryPoint.cs b/FinTrack/Models/Account/AccountBalanceHistoryPoint.cs index dcefb8c..c9d0466 100644 --- a/FinTrack/Models/Account/AccountBalanceHistoryPoint.cs +++ b/FinTrack/Models/Account/AccountBalanceHistoryPoint.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Models.Account +namespace FinTrackForWindows.Models.Account { public class AccountBalanceHistoryPoint { diff --git a/FinTrack/Models/Account/AccountModel.cs b/FinTrack/Models/Account/AccountModel.cs index 722c5cd..e104504 100644 --- a/FinTrack/Models/Account/AccountModel.cs +++ b/FinTrack/Models/Account/AccountModel.cs @@ -1,13 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Windows.Media; -namespace FinTrack.Models.Account +namespace FinTrackForWindows.Models.Account { public partial class AccountModel : ObservableObject { [ObservableProperty] - private Guid id = Guid.NewGuid(); + private int? id; [ObservableProperty] private string name = string.Empty; @@ -16,17 +16,13 @@ public partial class AccountModel : ObservableObject private AccountType type; [ObservableProperty] - private decimal currentBalance; - - [ObservableProperty] - private decimal? targetBalance; - - [ObservableProperty] - private string currency = "USD"; + private BaseCurrencyType currency; [ObservableProperty] private List history = new(); + public decimal? balance { get; set; } + public string IconPath => Type switch { AccountType.Checking => "/Assets/Images/Icons/bank.png", @@ -47,27 +43,14 @@ public string BalanceText { get { - if (Type == AccountType.CreditCard && TargetBalance.HasValue) - { - return $"Kullanılan Limit: {CurrentBalance:C} / {TargetBalance.Value:C}"; - } - if (TargetBalance.HasValue && TargetBalance > 0) + var balanceString = balance.ToString(); + return Type switch { - return $"{CurrentBalance:C} / {TargetBalance.Value:C}"; - } - return $"Değer: {CurrentBalance:C}"; - } - } - public double ProgressValue - { - get - { - if (TargetBalance.HasValue && TargetBalance.Value > 0) - { - return (double)Math.Max(0, Math.Min(100, (CurrentBalance / TargetBalance.Value) * 100)); - } - - return Type == AccountType.Loan ? 100 : 0; + AccountType.Checking => $"Bakiye: {balance}", + AccountType.CreditCard => $"Borç: {balance}", + AccountType.Loan => $"Kredi: {balance}", + _ => $"Bakiye: {balance}" + }; } } } diff --git a/FinTrack/Models/AccountModel.cs b/FinTrack/Models/AccountModel.cs index 02e1960..49efeb2 100644 --- a/FinTrack/Models/AccountModel.cs +++ b/FinTrack/Models/AccountModel.cs @@ -1,8 +1,8 @@ -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Accounts")] public class AccountModel diff --git a/FinTrack/Models/Budget/BudgetModel.cs b/FinTrack/Models/Budget/BudgetModel.cs index 4ed5256..3564f50 100644 --- a/FinTrack/Models/Budget/BudgetModel.cs +++ b/FinTrack/Models/Budget/BudgetModel.cs @@ -1,48 +1,67 @@ -using CommunityToolkit.Mvvm.ComponentModel; +// FinTrackForWindows.Models.Budget/BudgetModel.cs + +using CommunityToolkit.Mvvm.ComponentModel; +using FinTrackForWindows.Enums; using System.Globalization; -namespace FinTrack.Models.Budget +namespace FinTrackForWindows.Models.Budget { public partial class BudgetModel : ObservableObject { [ObservableProperty] - private Guid id = Guid.NewGuid(); + private int id; [ObservableProperty] private string name = string.Empty; + [ObservableProperty] + private string? description; + + [ObservableProperty] + private string category = "Other"; + [ObservableProperty] [NotifyPropertyChangedFor(nameof(ProgressValue))] [NotifyPropertyChangedFor(nameof(ProgressText))] - private decimal amount; + private decimal allocatedAmount; [ObservableProperty] [NotifyPropertyChangedFor(nameof(ProgressValue))] [NotifyPropertyChangedFor(nameof(ProgressText))] - private decimal targetAmount; + private decimal currentAmount; [ObservableProperty] - private DateTime startDate; + private BaseCurrencyType currency = BaseCurrencyType.USD; [ObservableProperty] [NotifyPropertyChangedFor(nameof(RemainingTimeText))] - private DateTime endDate; + private DateTime startDate = DateTime.Today; [ObservableProperty] - private string currency = "USD"; + [NotifyPropertyChangedFor(nameof(RemainingTimeText))] + private DateTime endDate = DateTime.Today.AddMonths(1); - public double ProgressValue => TargetAmount <= 0 ? 0 : Math.Max(0, Math.Min(100, (double)(Amount / TargetAmount) * 100)); + public double ProgressValue => AllocatedAmount <= 0 ? 0 : Math.Max(0, Math.Min(100, (double)(CurrentAmount / AllocatedAmount) * 100)); - public string ProgressText => $"{Amount.ToString("C", new CultureInfo("tr-TR"))} / {TargetAmount.ToString("C", new CultureInfo("tr-TR"))}"; + public string ProgressText + { + get + { + var culture = new CultureInfo("tr-TR"); + return $"{CurrentAmount.ToString("C", culture)} / {AllocatedAmount.ToString("C", culture)}"; + } + } public string RemainingTimeText { get { - var remaining = EndDate - DateTime.Today; + var remaining = EndDate.Date - DateTime.Today; if (remaining.TotalDays < 0) return "Süre Doldu"; - return $"Kalan Süre: {remaining.Days} gün"; + if (remaining.TotalDays == 0) + return "Son gün"; + return $"{remaining.Days} gün kaldı"; } } } diff --git a/FinTrack/Models/BudgetCategoryModel.cs b/FinTrack/Models/BudgetCategoryModel.cs index 6b5f30d..60f48d9 100644 --- a/FinTrack/Models/BudgetCategoryModel.cs +++ b/FinTrack/Models/BudgetCategoryModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("BudgetCategories")] public class BudgetCategoryModel diff --git a/FinTrack/Models/BudgetModel.cs b/FinTrack/Models/BudgetModel.cs index bf74356..540c067 100644 --- a/FinTrack/Models/BudgetModel.cs +++ b/FinTrack/Models/BudgetModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Budgets")] public class BudgetModel diff --git a/FinTrack/Models/CategoryModel.cs b/FinTrack/Models/CategoryModel.cs index a3e112d..324f91a 100644 --- a/FinTrack/Models/CategoryModel.cs +++ b/FinTrack/Models/CategoryModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Categories")] public class CategoryModel diff --git a/FinTrack/Models/Currency/CurrencyModel.cs b/FinTrack/Models/Currency/CurrencyModel.cs index f760d11..5a4769d 100644 --- a/FinTrack/Models/Currency/CurrencyModel.cs +++ b/FinTrack/Models/Currency/CurrencyModel.cs @@ -1,11 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Windows.Media; -namespace FinTrack.Models.Currency +namespace FinTrackForWindows.Models.Currency { public partial class CurrencyModel : ObservableObject { + public int Id { get; set; } + [ObservableProperty] private string toCurrencyFlag = string.Empty; diff --git a/FinTrack/Models/Dashboard/AccountDashboard.cs b/FinTrack/Models/Dashboard/AccountDashboard.cs index 3657a8d..8358139 100644 --- a/FinTrack/Models/Dashboard/AccountDashboard.cs +++ b/FinTrack/Models/Dashboard/AccountDashboard.cs @@ -1,6 +1,6 @@ using System.Windows.Media; -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public class AccountDashboard { diff --git a/FinTrack/Models/Dashboard/BudgetDashboard.cs b/FinTrack/Models/Dashboard/BudgetDashboardModel.cs similarity index 81% rename from FinTrack/Models/Dashboard/BudgetDashboard.cs rename to FinTrack/Models/Dashboard/BudgetDashboardModel.cs index 85331e2..f64fdf4 100644 --- a/FinTrack/Models/Dashboard/BudgetDashboard.cs +++ b/FinTrack/Models/Dashboard/BudgetDashboardModel.cs @@ -1,8 +1,8 @@ using System.Windows.Media; -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { - public class BudgetDashboard + public class BudgetDashboardModel { public string Name { get; set; } = string.Empty; public string DueDate { get; set; } = string.Empty; diff --git a/FinTrack/Models/Dashboard/CurrencyRateDashboard.cs b/FinTrack/Models/Dashboard/CurrencyRateDashboard.cs index 10cb703..7a2cf3c 100644 --- a/FinTrack/Models/Dashboard/CurrencyRateDashboard.cs +++ b/FinTrack/Models/Dashboard/CurrencyRateDashboard.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public class CurrencyRateDashboard { diff --git a/FinTrack/Models/Dashboard/DebtDashboard.cs b/FinTrack/Models/Dashboard/DebtDashboard.cs index 19ca059..5bf7a34 100644 --- a/FinTrack/Models/Dashboard/DebtDashboard.cs +++ b/FinTrack/Models/Dashboard/DebtDashboard.cs @@ -1,6 +1,6 @@ using System.Windows.Media; -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public class DebtDashboard { diff --git a/FinTrack/Models/Dashboard/MembershipDashboard.cs b/FinTrack/Models/Dashboard/MembershipDashboard.cs index 088a499..a1624ee 100644 --- a/FinTrack/Models/Dashboard/MembershipDashboard.cs +++ b/FinTrack/Models/Dashboard/MembershipDashboard.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public class MembershipDashboard { diff --git a/FinTrack/Models/Dashboard/ReportDashboardModel.cs b/FinTrack/Models/Dashboard/ReportDashboardModel.cs index 3c5480a..d6b06aa 100644 --- a/FinTrack/Models/Dashboard/ReportDashboardModel.cs +++ b/FinTrack/Models/Dashboard/ReportDashboardModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public partial class ReportDashboardModel : ObservableObject { diff --git a/FinTrack/Models/Dashboard/TransactionDashboard.cs b/FinTrack/Models/Dashboard/TransactionDashboard.cs index d8916d8..23b1971 100644 --- a/FinTrack/Models/Dashboard/TransactionDashboard.cs +++ b/FinTrack/Models/Dashboard/TransactionDashboard.cs @@ -1,7 +1,7 @@ -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Windows.Media; -namespace FinTrack.Models.Dashboard +namespace FinTrackForWindows.Models.Dashboard { public class TransactionDashboard { diff --git a/FinTrack/Models/Debt/DebtModel.cs b/FinTrack/Models/Debt/DebtModel.cs index 661eef3..fd6a6ab 100644 --- a/FinTrack/Models/Debt/DebtModel.cs +++ b/FinTrack/Models/Debt/DebtModel.cs @@ -1,8 +1,8 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Windows.Media; -namespace FinTrack.Models.Debt +namespace FinTrackForWindows.Models.Debt { public partial class DebtModel : ObservableObject { @@ -26,7 +26,7 @@ public partial class DebtModel : ObservableObject [NotifyPropertyChangedFor(nameof(StatusBrush))] [NotifyPropertyChangedFor(nameof(IsActionRequired))] [NotifyPropertyChangedFor(nameof(IsRejected))] - private DebtStatus status; + private DebtStatusType status; [ObservableProperty] [NotifyPropertyChangedFor(nameof(DebtTitle))] @@ -54,33 +54,33 @@ public partial class DebtModel : ObservableObject public Brush StatusBrush => Status switch { - DebtStatus.Active => GreenBrush, - DebtStatus.AwaitingVideoUpload => BlueBrush, - DebtStatus.AwaitingOperatorApproval => OrangeBrush, - DebtStatus.RejectedByOperator => RedBrush, - DebtStatus.RejectedByBorrower => RedBrush, + DebtStatusType.Active => GreenBrush, + DebtStatusType.PendingBorrowerAcceptance => BlueBrush, + DebtStatusType.PendingOperatorApproval => OrangeBrush, + DebtStatusType.RejectedByOperator => RedBrush, + DebtStatusType.RejectedByBorrower => RedBrush, _ => GrayBrush }; public string StatusText => Status switch { - DebtStatus.AwaitingVideoUpload => "Status: Awaiting Video Approval", - DebtStatus.AwaitingOperatorApproval => "Status: FinTrack Operator Approval Pending", - DebtStatus.Active => "Status: Active - In force", - DebtStatus.RejectedByOperator => "Status: Rejected by Operator", - DebtStatus.RejectedByBorrower => "Status: Rejected by Borrower", + DebtStatusType.PendingBorrowerAcceptance => "Status: Awaiting Video Approval", + DebtStatusType.PendingOperatorApproval => "Status: FinTrack Operator Approval Pending", + DebtStatusType.Active => "Status: Active - In force", + DebtStatusType.RejectedByOperator => "Status: Rejected by Operator", + DebtStatusType.RejectedByBorrower => "Status: Rejected by Borrower", _ => "Status: Unknown" }; - public bool IsActionRequired => Status == DebtStatus.AwaitingVideoUpload; + public bool IsActionRequired => Status == DebtStatusType.PendingBorrowerAcceptance; - public bool IsRejected => Status == DebtStatus.RejectedByBorrower || Status == DebtStatus.RejectedByOperator; + public bool IsRejected => Status == DebtStatusType.RejectedByBorrower || Status == DebtStatusType.RejectedByOperator; public string InfoText => Status switch { - DebtStatus.Active => $"Final Payment: {DueDate:dd.MM.yyyy}", - DebtStatus.AwaitingOperatorApproval => "Video uploaded", - DebtStatus.RejectedByOperator => $"Reason: {RejectionReason}", + DebtStatusType.Active => $"Final Payment: {DueDate:dd.MM.yyyy}", + DebtStatusType.PendingOperatorApproval => "Video uploaded", + DebtStatusType.RejectedByOperator => $"Reason: {RejectionReason}", _ => string.Empty }; } diff --git a/FinTrack/Models/DebtModel.cs b/FinTrack/Models/DebtModel.cs index c27d497..82c3015 100644 --- a/FinTrack/Models/DebtModel.cs +++ b/FinTrack/Models/DebtModel.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Models +namespace FinTrackForWindows.Models { public class DebtModel { diff --git a/FinTrack/Models/FinBot/ChatMessageModel.cs b/FinTrack/Models/FinBot/ChatMessageModel.cs index 1f8bce7..0310572 100644 --- a/FinTrack/Models/FinBot/ChatMessageModel.cs +++ b/FinTrack/Models/FinBot/ChatMessageModel.cs @@ -1,8 +1,8 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Collections.ObjectModel; -namespace FinTrack.Models.FinBot +namespace FinTrackForWindows.Models.FinBot { public partial class ChatMessageModel : ObservableObject { diff --git a/FinTrack/Models/Notification/NotificationModel.cs b/FinTrack/Models/Notification/NotificationModel.cs index 5339d65..6eef6b4 100644 --- a/FinTrack/Models/Notification/NotificationModel.cs +++ b/FinTrack/Models/Notification/NotificationModel.cs @@ -1,7 +1,7 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; -namespace FinTrack.Models.Notification +namespace FinTrackForWindows.Models.Notification { public partial class NotificationModel : ObservableObject { diff --git a/FinTrack/Models/NotificationModel.cs b/FinTrack/Models/NotificationModel.cs index c6e8d90..6ce0356 100644 --- a/FinTrack/Models/NotificationModel.cs +++ b/FinTrack/Models/NotificationModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Notifications")] public class NotificationModel diff --git a/FinTrack/Models/Report/SelectableOptionReport.cs b/FinTrack/Models/Report/SelectableOptionReport.cs index edb6041..52f54b3 100644 --- a/FinTrack/Models/Report/SelectableOptionReport.cs +++ b/FinTrack/Models/Report/SelectableOptionReport.cs @@ -1,6 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace FinTrack.Models.Report +namespace FinTrackForWindows.Models.Report { public partial class SelectableOptionReport : ObservableObject { diff --git a/FinTrack/Models/Settings/NotificationSettingItemModel.cs b/FinTrack/Models/Settings/NotificationSettingItemModel.cs index 4e8dc56..b1c34e1 100644 --- a/FinTrack/Models/Settings/NotificationSettingItemModel.cs +++ b/FinTrack/Models/Settings/NotificationSettingItemModel.cs @@ -1,7 +1,7 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; -namespace FinTrack.Models.Settings +namespace FinTrackForWindows.Models.Settings { public partial class NotificationSettingItemModel : ObservableObject { diff --git a/FinTrack/Models/Transaction/TransactionModel.cs b/FinTrack/Models/Transaction/TransactionModel.cs index 6b42a09..24a8884 100644 --- a/FinTrack/Models/Transaction/TransactionModel.cs +++ b/FinTrack/Models/Transaction/TransactionModel.cs @@ -1,13 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using System.Windows.Media; -namespace FinTrack.Models.Transaction +namespace FinTrackForWindows.Models.Transaction { public partial class TransactionModel : ObservableObject { [ObservableProperty] - private Guid id = Guid.NewGuid(); + private int id; [ObservableProperty] private string nameOrDescription = string.Empty; diff --git a/FinTrack/Models/TransactionModel.cs b/FinTrack/Models/TransactionModel.cs index 1fa158f..ae4a6a1 100644 --- a/FinTrack/Models/TransactionModel.cs +++ b/FinTrack/Models/TransactionModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Transactions")] public class TransactionModel diff --git a/FinTrack/Models/UserModel.cs b/FinTrack/Models/UserModel.cs index 4fd601b..0754842 100644 --- a/FinTrack/Models/UserModel.cs +++ b/FinTrack/Models/UserModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("Users")] public class UserModel diff --git a/FinTrack/Models/UserSettingsModel.cs b/FinTrack/Models/UserSettingsModel.cs index 187136e..75aba48 100644 --- a/FinTrack/Models/UserSettingsModel.cs +++ b/FinTrack/Models/UserSettingsModel.cs @@ -1,7 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; -namespace FinTrack.Models +namespace FinTrackForWindows.Models { [Table("UserSettings")] public class UserSettingsModel diff --git a/FinTrack/Services/Api/ApiService.cs b/FinTrack/Services/Api/ApiService.cs index 569f725..0117e8d 100644 --- a/FinTrack/Services/Api/ApiService.cs +++ b/FinTrack/Services/Api/ApiService.cs @@ -1,10 +1,13 @@ -using FinTrack.Core; +using FinTrackForWindows.Core; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.Net.Http; using System.Net.Http.Headers; +using System.Net.Http.Json; using System.Text.Json; +using System.Text.Json.Serialization; -namespace FinTrack.Services.Api +namespace FinTrackForWindows.Services.Api { public class ApiService : IApiService { @@ -12,21 +15,26 @@ public class ApiService : IApiService private readonly HttpClient _httpClient; private readonly ILogger _logger; private readonly JsonSerializerOptions _jsonSerializerOptions; + private readonly IConfiguration _configuration; - public ApiService(ILogger logger) + + public ApiService(ILogger logger, IConfiguration configuration) { - _baseUrl = "http://localhost:5000/api/"; + _logger = logger; + _configuration = configuration; + + _baseUrl = "http://localhost:5246/"; + //_baseUrl = _configuration["BaseServerUrl"]; _httpClient = new HttpClient { BaseAddress = new Uri(_baseUrl) }; _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - _logger = logger; - _jsonSerializerOptions = new JsonSerializerOptions { - PropertyNameCaseInsensitive = true + PropertyNameCaseInsensitive = true, + Converters = { new JsonStringEnumConverter() } }; } @@ -85,7 +93,7 @@ private void AddAuthorizationHeader() response.EnsureSuccessStatusCode(); var strean = await response.Content.ReadAsStreamAsync(); - var result = await JsonSerializer.DeserializeAsync(strean, _jsonSerializerOptions); + var result = await _httpClient.GetFromJsonAsync(endpoint, _jsonSerializerOptions); _logger.LogInformation("GET isteği başarılı: {Endpoint}", endpoint); return result; @@ -107,6 +115,38 @@ private void AddAuthorizationHeader() } } + public async Task?> GetsAsync(string endpoint) + { + _logger.LogInformation("GET (list) isteği başlatılıyor: {Endpoint}", endpoint); + try + { + AddAuthorizationHeader(); + + var response = await _httpClient.GetAsync(endpoint); + response.EnsureSuccessStatusCode(); + + var result = await _httpClient.GetFromJsonAsync>(endpoint, _jsonSerializerOptions); + + _logger.LogInformation("GET (list) isteği başarılı: {Endpoint}", endpoint); + return result; + } + catch (HttpRequestException ex) + { + _logger.LogError(ex, "GET (list) isteği sırasında HTTP hatası oluştu: {Endpoint}. Status Code: {StatusCode}", endpoint, ex.StatusCode); + return default(List); + } + catch (JsonException ex) + { + _logger.LogError(ex, "GET (list) isteği sırasında JSON serileştirme hatası oluştu: {Endpoint}", endpoint); + return default(List); + } + catch (Exception ex) + { + _logger.LogError(ex, "GET (list) isteği sırasında beklenmeyen bir hata oluştu: {Endpoint}", endpoint); + return default(List); + } + } + public async Task PostAsync(string endpoint, object data) { _logger.LogInformation("POST isteği başlatılıyor: {Endpoint}", endpoint); @@ -128,7 +168,7 @@ private void AddAuthorizationHeader() var jsonPayload = JsonSerializer.Serialize(data); var content = new StringContent(jsonPayload, System.Text.Encoding.UTF8, "application/json"); - var response = await _httpClient.PostAsync(endpoint, content); + var response = await _httpClient.PostAsJsonAsync(endpoint, data, _jsonSerializerOptions); response.EnsureSuccessStatusCode(); var stream = await response.Content.ReadAsStreamAsync(); diff --git a/FinTrack/Services/Api/IApiService.cs b/FinTrack/Services/Api/IApiService.cs index 8d86baf..96c374e 100644 --- a/FinTrack/Services/Api/IApiService.cs +++ b/FinTrack/Services/Api/IApiService.cs @@ -1,4 +1,4 @@ -namespace FinTrack.Services.Api +namespace FinTrackForWindows.Services.Api { public interface IApiService { diff --git a/FinTrack/Services/AuthService.cs b/FinTrack/Services/AuthService.cs index 6bc8056..3edee7e 100644 --- a/FinTrack/Services/AuthService.cs +++ b/FinTrack/Services/AuthService.cs @@ -1,19 +1,23 @@ -using FinTrack.Dtos; +using FinTrackForWindows.Dtos; +using Microsoft.Extensions.Configuration; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Http.Json; -namespace FinTrack.Services +namespace FinTrackForWindows.Services { public class AuthService : IAuthService { private readonly HttpClient _httpClient; + private readonly IConfiguration _configuration; - public AuthService() + public AuthService(IConfiguration configuration) { + _configuration = configuration; _httpClient = new HttpClient { - BaseAddress = new Uri("http://localhost:5000/") + BaseAddress = new Uri("http://localhost:5246/") + //BaseAddress = new Uri(_configuration["BaseServerUrl"]) }; _httpClient.DefaultRequestHeaders.Accept.Clear(); @@ -26,7 +30,7 @@ public async Task LoginAsync(string email, string password) { LoginRequestDto request = new LoginRequestDto { Email = email, Password = password }; - HttpResponseMessage response = await _httpClient.PostAsJsonAsync("api/auth/user/login", request); + HttpResponseMessage response = await _httpClient.PostAsJsonAsync("UserAuth/login", request); if (response.IsSuccessStatusCode) { @@ -59,19 +63,20 @@ public void Logout() _httpClient.DefaultRequestHeaders.Authorization = null; } - public async Task InitiateRegistrationAsnc(string userName, string email, string password) + public async Task InitiateRegistrationAsnc(string firstName, string lastName, string email, string password) { try { RegisterRequestDto request = new RegisterRequestDto { - UserName = userName, + FirstName = firstName, + LastName = lastName, Email = email, Password = password, ProfilePicture = null }; - HttpResponseMessage response = await _httpClient.PostAsJsonAsync("api/auth/user/initiate-registration", request); + HttpResponseMessage response = await _httpClient.PostAsJsonAsync("UserAuth/initiate-registration", request); if (response.IsSuccessStatusCode) { return true; @@ -98,7 +103,7 @@ public async Task VerifyOtpAndRegisterCodeAsync(string email, string code) Code = code }; - HttpResponseMessage response = await _httpClient.PostAsJsonAsync("api/auth/user/verify-otp-and-register", request); + HttpResponseMessage response = await _httpClient.PostAsJsonAsync("UserAuth/verify-otp-and-register", request); if (response.IsSuccessStatusCode) { return true; diff --git a/FinTrack/Services/Budgets/BudgetService.cs b/FinTrack/Services/Budgets/BudgetService.cs new file mode 100644 index 0000000..1720a8e --- /dev/null +++ b/FinTrack/Services/Budgets/BudgetService.cs @@ -0,0 +1,6 @@ +namespace FinTrack.Services.Budgets +{ + public class BudgetService : IBudgetService + { + } +} diff --git a/FinTrack/Services/Budgets/IBudgetService.cs b/FinTrack/Services/Budgets/IBudgetService.cs new file mode 100644 index 0000000..23177a2 --- /dev/null +++ b/FinTrack/Services/Budgets/IBudgetService.cs @@ -0,0 +1,12 @@ +namespace FinTrack.Services.Budgets +{ + public interface IBudgetService + { + /* + List GetBudgets(); + void AddBudget(string name, decimal amount, DateTime dueDate); + void UpdateBudget(int budgetId, string name, decimal amount, DateTime dueDate); + void DeleteBudget(int budgetId); + */ + } +} diff --git a/FinTrack/Services/IAuthService.cs b/FinTrack/Services/IAuthService.cs index 9417e99..de3b36b 100644 --- a/FinTrack/Services/IAuthService.cs +++ b/FinTrack/Services/IAuthService.cs @@ -1,10 +1,10 @@ -namespace FinTrack.Services +namespace FinTrackForWindows.Services { public interface IAuthService { Task LoginAsync(string email, string password); void Logout(); - Task InitiateRegistrationAsnc(string userName, string email, string password); + Task InitiateRegistrationAsnc(string firstName, string lastName, string email, string password); Task VerifyOtpAndRegisterCodeAsync(string email, string code); } } diff --git a/FinTrack/Styles/ModernStyles.xaml b/FinTrack/Styles/ModernStyles.xaml index e95c191..e884de6 100644 --- a/FinTrack/Styles/ModernStyles.xaml +++ b/FinTrack/Styles/ModernStyles.xaml @@ -13,6 +13,8 @@ + + diff --git a/FinTrack/ViewModels/AccountViewModel.cs b/FinTrack/ViewModels/AccountViewModel.cs index aa15431..94cbdba 100644 --- a/FinTrack/ViewModels/AccountViewModel.cs +++ b/FinTrack/ViewModels/AccountViewModel.cs @@ -1,22 +1,35 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Account; +using FinTrackForWindows.Dtos.AccountDtos; +using FinTrackForWindows.Dtos.TransactionDtos; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Account; +using FinTrackForWindows.Services.Api; +using LiveChartsCore; +using LiveChartsCore.Defaults; +using LiveChartsCore.SkiaSharpView; +using LiveChartsCore.SkiaSharpView.Painting; +using LiveChartsCore.SkiaSharpView.VisualElements; using Microsoft.Extensions.Logging; +using SkiaSharp; using System.Collections.ObjectModel; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class AccountViewModel : ObservableObject { [ObservableProperty] - private ObservableCollection accounts; + private ObservableCollection accounts = new(); [ObservableProperty] [NotifyPropertyChangedFor(nameof(FormTitle))] [NotifyPropertyChangedFor(nameof(SaveButtonText))] private AccountModel? selectedAccount; + public ObservableCollection CurrencyTypes { get; } + + public ObservableCollection AccountTypes { get; } + private readonly ILogger _logger; public string FormTitle => IsEditing ? "Hesabı Düzenle" : "Yeni Hesap Ekle"; @@ -24,62 +37,198 @@ public partial class AccountViewModel : ObservableObject private bool IsEditing = false; - public AccountViewModel(ILogger logger) + private readonly IApiService _apiService; + + [ObservableProperty] + private ISeries[] series = new ISeries[0]; + + [ObservableProperty] + private Axis[] xAxes = new Axis[0]; + + [ObservableProperty] + private Axis[] yAxes = new Axis[0]; + + [ObservableProperty] + private LabelVisual title = new LabelVisual { /* Başlık için yer tutucu */ }; + + public AccountViewModel(ILogger logger, IApiService apiService) { _logger = logger; - LoadSampleData(); + _apiService = apiService; + + InitializeEmptyChart(); + _ = LoadData(); + _ = InitializeViewModel(); PrepareForNewAccount(); + + CurrencyTypes = new ObservableCollection(); + AccountTypes = new ObservableCollection(); + + CurrencyTypes.Clear(); + foreach (BaseCurrencyType currencyType in Enum.GetValues(typeof(BaseCurrencyType))) + { + CurrencyTypes.Add(currencyType); + } } - partial void OnSelectedAccountChanged(AccountModel? value) + private void InitializeEmptyChart() { - _logger.LogInformation("Seçilen hesap değişti: {AccountName}", value?.Name ?? "Hiçbiri"); + Series = new ISeries[0]; + Title = new LabelVisual + { + Text = "Select an account to view the data.", + TextSize = 18, + Paint = new SolidColorPaint(SKColors.Gray), + Padding = new LiveChartsCore.Drawing.Padding(15) + }; + } - IsEditing = value != null && value.Id != Guid.Empty; + private async Task InitializeViewModel() + { + await LoadData(); + if (Accounts.Any()) + { + var firstAccount = Accounts.First(); + if (firstAccount.Id.HasValue) + { + SelectedAccount = firstAccount; + } + } + } + partial void OnSelectedAccountChanged(AccountModel? value) + { + _logger.LogInformation("Seçilen hesap değişti: {AccountName}", value?.Name ?? "Hiçbiri"); + IsEditing = value != null && value.Id != null; OnPropertyChanged(nameof(FormTitle)); OnPropertyChanged(nameof(SaveButtonText)); + + if (value != null && value.Id.HasValue) + { + _ = LoadTransactionHistory(value.Id.Value, value.Name); + } + else + { + InitializeEmptyChart(); + } } - private void LoadSampleData() + private async Task LoadData() { - Accounts = new ObservableCollection + var accounts = await _apiService.GetAsync>("Account"); + Accounts = new ObservableCollection(); + if (accounts != null) { - new AccountModel + foreach (var item in accounts) { - Id = Guid.NewGuid(), - Name = "ING Bank - Vadesiz", - Type = AccountType.Checking, - CurrentBalance = 15000, - TargetBalance = 20000, - Currency = "USD", - History = new List() - }, - new AccountModel + Accounts.Add(new AccountModel + { + Id = item.Id, + Name = item.Name, + Type = item.Type, + balance = item.Balance, + Currency = item.Currency, + }); + } + } + } + + private async Task LoadTransactionHistory(int accountId, string accountName) + { + var transactions = await _apiService.GetAsync>($"Transactions/account-id/{accountId}"); + + if (transactions == null || !transactions.Any()) + { + Series = new ISeries[0]; + Title = new LabelVisual { - Id = Guid.NewGuid(), - Name = "QNB Bank - Kredi Kartı", - Type = AccountType.CreditCard, - CurrentBalance = 3000, - TargetBalance = 10000, - Currency = "USD", - History = new List() + Text = "No Data", + TextSize = 18, + Paint = new SolidColorPaint(SKColors.Gray), + Padding = new LiveChartsCore.Drawing.Padding(15) + }; + return; + } + + var incomePoints = transactions + .Where(t => t.Category.Type == TransactionType.Income) + .Select(t => new DateTimePoint(t.TransactionDateUtc, (double)t.Amount)) + .ToList(); + + var expensePoints = transactions + .Where(t => t.Category.Type == TransactionType.Expense) + .Select(t => new DateTimePoint(t.TransactionDateUtc, (double)t.Amount)) + .ToList(); + + Series = new ISeries[] + { + new LineSeries + { + Name = "Income", + Values = incomePoints, + Stroke = new SolidColorPaint(SKColors.MediumSpringGreen) { StrokeThickness = 2 }, + GeometryStroke = new SolidColorPaint(SKColors.MediumSpringGreen) { StrokeThickness = 4 }, + Fill = new LinearGradientPaint(SKColors.MediumSpringGreen.WithAlpha(90), SKColors.MediumSpringGreen.WithAlpha(10), new SKPoint(0.5f, 0), new SKPoint(0.5f, 1)) }, - new AccountModel + new LineSeries { - Id = Guid.NewGuid(), - Name = "Yatırım Hesabı - Portföy", - Type = AccountType.Investment, - CurrentBalance = 90000, - TargetBalance = null, - Currency = "USD", - History = new List() + Name = "Expense", + Values = expensePoints, + Stroke = new SolidColorPaint(SKColors.IndianRed) { StrokeThickness = 2 }, + GeometryStroke = new SolidColorPaint(SKColors.IndianRed) { StrokeThickness = 4 }, + Fill = new LinearGradientPaint(SKColors.IndianRed.WithAlpha(90), SKColors.IndianRed.WithAlpha(10), new SKPoint(0.5f, 0), new SKPoint(0.5f, 1)) + } + }; + + Title = new LabelVisual + { + Text = $"{accountName} - Transactions", + TextSize = 16, + Paint = new SolidColorPaint(SKColors.WhiteSmoke), + Padding = new LiveChartsCore.Drawing.Padding(15) + }; + + XAxes = new Axis[] + { + new Axis + { + Labeler = value => + { + try + { + var ticks = (long)value; + if (ticks >= DateTime.MinValue.Ticks && ticks <= DateTime.MaxValue.Ticks) + { + return new DateTime(ticks).ToString("dd MMM"); + } + return string.Empty; + } + catch + { + return string.Empty; + } + } +, + LabelsPaint = new SolidColorPaint(SKColors.LightGray), + UnitWidth = TimeSpan.FromDays(1).Ticks, + MinStep = TimeSpan.FromDays(1).Ticks + + } + }; + + YAxes = new Axis[] + { + new Axis + { + Labeler = value => value.ToString("C0"), + LabelsPaint = new SolidColorPaint(SKColors.LightGray), + SeparatorsPaint = new SolidColorPaint(SKColors.Gray) { StrokeThickness = 0.5f } } }; } [RelayCommand] - private void SaveAccount() + private async Task SaveAccount() { if (SelectedAccount == null || string.IsNullOrWhiteSpace(SelectedAccount.Name)) return; @@ -90,25 +239,42 @@ private void SaveAccount() { existingAccount.Name = SelectedAccount.Name; existingAccount.Type = SelectedAccount.Type; - existingAccount.CurrentBalance = SelectedAccount.CurrentBalance; - existingAccount.TargetBalance = SelectedAccount.TargetBalance; existingAccount.Currency = SelectedAccount.Currency; + + await _apiService.PutAsync($"Account/{SelectedAccount.Id}", new AccountUpdateDto + { + Name = SelectedAccount.Name, + Type = SelectedAccount.Type, + Currency = SelectedAccount.Currency + }); } } else { - SelectedAccount.Id = Guid.NewGuid(); + var newAccount = await _apiService.PostAsync("Account", new AccountCreateDto + { + Name = SelectedAccount.Name, + Type = SelectedAccount.Type, + IsActive = true, + Currency = SelectedAccount.Currency, + }); + + SelectedAccount.Id = newAccount.Id; + Accounts.Add(SelectedAccount); } PrepareForNewAccount(); } [RelayCommand] - private void DeleteAccount(AccountModel accountToDelete) + private async Task DeleteAccount(AccountModel accountToDelete) { if (accountToDelete != null) { Accounts.Remove(accountToDelete); + + await _apiService.DeleteAsync($"Account/{accountToDelete.Id}"); + if (SelectedAccount?.Id == accountToDelete.Id) { PrepareForNewAccount(); diff --git a/FinTrack/ViewModels/AppSettingsContentViewModel.cs b/FinTrack/ViewModels/AppSettingsContentViewModel.cs index 5859837..fbeb618 100644 --- a/FinTrack/ViewModels/AppSettingsContentViewModel.cs +++ b/FinTrack/ViewModels/AppSettingsContentViewModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class AppSettingsContentViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/ApplicationRecognizeSlideViewModel.cs b/FinTrack/ViewModels/ApplicationRecognizeSlideViewModel.cs index 5a197ec..b5f2e78 100644 --- a/FinTrack/ViewModels/ApplicationRecognizeSlideViewModel.cs +++ b/FinTrack/ViewModels/ApplicationRecognizeSlideViewModel.cs @@ -1,9 +1,9 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Core; +using FinTrackForWindows.Core; using Microsoft.Extensions.Logging; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class ApplicationRecognizeSlideViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/AuthenticatorViewModel.cs b/FinTrack/ViewModels/AuthenticatorViewModel.cs index 950747f..19157e8 100644 --- a/FinTrack/ViewModels/AuthenticatorViewModel.cs +++ b/FinTrack/ViewModels/AuthenticatorViewModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; -using FinTrack.Core; -using FinTrack.Messages; +using FinTrackForWindows.Core; +using FinTrackForWindows.Messages; using Microsoft.Extensions.Logging; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class AuthenticatorViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/BottomBarViewModel.cs b/FinTrack/ViewModels/BottomBarViewModel.cs index 5881f52..24f4797 100644 --- a/FinTrack/ViewModels/BottomBarViewModel.cs +++ b/FinTrack/ViewModels/BottomBarViewModel.cs @@ -4,7 +4,7 @@ using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class BottomBarViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/BudgetViewModel.cs b/FinTrack/ViewModels/BudgetViewModel.cs index dca8b37..bdda353 100644 --- a/FinTrack/ViewModels/BudgetViewModel.cs +++ b/FinTrack/ViewModels/BudgetViewModel.cs @@ -1,11 +1,14 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Models.Budget; +using FinTrackForWindows.Dtos.BudgetDtos; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Budget; +using FinTrackForWindows.Services.Api; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class BudgetViewModel : ObservableObject { @@ -20,93 +23,132 @@ public partial class BudgetViewModel : ObservableObject [NotifyPropertyChangedFor(nameof(SaveButtonText))] private bool isEditing; - private readonly ILogger _logger; + public ObservableCollection Categories { get; } + public IEnumerable CurrencyTypes => Enum.GetValues(typeof(BaseCurrencyType)).Cast(); + + public string FormTitle => IsEditing ? "Edit Budget" : "Add New Budget"; + public string SaveButtonText => IsEditing ? "UPDATE THE BUDGET" : "CREATE A BUDGET"; - public string FormTitle => IsEditing ? "Bütçeyi Düzenle" : "Yeni Bütçe Ekle"; - public string SaveButtonText => IsEditing ? "GÜNCELLE" : "BÜTÇE OLUŞTUR"; + private readonly ILogger _logger; + private readonly IApiService _apiService; - public BudgetViewModel(ILogger logger) + public BudgetViewModel(ILogger logger, IApiService apiService) { _logger = logger; - LoadSampleData(); + _apiService = apiService; + + Budgets = new ObservableCollection(); + Categories = new ObservableCollection { "Gıda", "Fatura", "Ulaşım", "Eğlence", "Sağlık", "Diğer" }; + + _ = LoadBudgetsAsync(); PrepareForNewBudget(); } - private void LoadSampleData() + private async Task LoadBudgetsAsync() { - Budgets = new ObservableCollection + try { - new BudgetModel - { - Id = Guid.NewGuid(), - Name = "Yemek Bütçesi", - Amount = 850, - TargetAmount = 1200, - StartDate = DateTime.Today.AddDays(-15), - EndDate = DateTime.Today.AddDays(15), - Currency = "TRY" - }, - new BudgetModel + var budgetsFromApi = await _apiService.GetAsync>("Budgets"); + if (budgetsFromApi == null) return; + + Budgets.Clear(); + foreach (var dto in budgetsFromApi) { - Id = Guid.NewGuid(), - Name = "Ulaşım Bütçesi", - Amount = 300, - TargetAmount = 600, - StartDate = DateTime.Today, - EndDate = DateTime.Today.AddMonths(1), - Currency = "TRY" + Budgets.Add(new BudgetModel + { + Id = dto.Id, + Name = dto.Name, + Description = dto.Description, + Category = dto.Category, + AllocatedAmount = dto.AllocatedAmount, + CurrentAmount = 0, // TODO: API'den gelen veride mevcut tutar yoksa 0 olarak ayarla + Currency = dto.Currency, + StartDate = dto.StartDate, + EndDate = dto.EndDate + }); } - }; + } + catch (Exception ex) + { + _logger.LogError(ex, "Bütçeler yüklenirken bir hata oluştu."); + MessageBox.Show("Bütçeler yüklenemedi. Lütfen internet bağlantınızı kontrol edin.", "Hata", MessageBoxButton.OK, MessageBoxImage.Error); + } } [RelayCommand] - private void SaveBudget() + private async Task SaveBudgetAsync() { - if (SelectedBudget == null || string.IsNullOrWhiteSpace(SelectedBudget.Name)) + if (SelectedBudget == null || string.IsNullOrWhiteSpace(SelectedBudget.Name) || SelectedBudget.AllocatedAmount <= 0) { - _logger.LogWarning("Bütçe kaydedilemedi: Gerekli alanlar doldurulmamış."); - MessageBox.Show("Lütfen bütçe adını ve hedef tutarını doldurun.", "Uyarı", MessageBoxButton.OK, MessageBoxImage.Warning); + MessageBox.Show("Lütfen bütçe adı ve 0'dan büyük bir hedef tutar girin.", "Eksik Bilgi", MessageBoxButton.OK, MessageBoxImage.Warning); return; } - if (IsEditing) + var budgetDto = new BudgetCreateDto { - var existingBudget = Budgets.FirstOrDefault(b => b.Id == SelectedBudget.Id); - if (existingBudget != null) - { - existingBudget.Name = SelectedBudget.Name; - existingBudget.TargetAmount = SelectedBudget.TargetAmount; - existingBudget.StartDate = SelectedBudget.StartDate; - existingBudget.EndDate = SelectedBudget.EndDate; - existingBudget.Currency = SelectedBudget.Currency; + Name = SelectedBudget.Name, + Description = SelectedBudget.Description, + Category = SelectedBudget.Category, + AllocatedAmount = SelectedBudget.AllocatedAmount, + Currency = SelectedBudget.Currency, + StartDate = SelectedBudget.StartDate, + EndDate = SelectedBudget.EndDate, + IsActive = true + }; - _logger.LogInformation("Bütçe güncellendi: {BudgetName}", existingBudget.Name); + try + { + if (IsEditing) + { + // TEST + await _apiService.PutAsync($"Budgets/{SelectedBudget.Id}", budgetDto); + _logger.LogInformation("Bütçe güncellendi: {BudgetId}", SelectedBudget.Id); + + var existingBudget = Budgets.FirstOrDefault(b => b.Id == SelectedBudget.Id); + if (existingBudget != null) + { + var index = Budgets.IndexOf(existingBudget); + Budgets[index] = SelectedBudget; + } } + else + { + var createdBudgetDto = await _apiService.PostAsync("Budgets", budgetDto); + _logger.LogInformation("Yeni bütçe oluşturuldu."); + Budgets.Add(SelectedBudget); + } + PrepareForNewBudget(); } - else + catch (Exception ex) { - SelectedBudget.Id = Guid.NewGuid(); - Budgets.Add(SelectedBudget); - _logger.LogInformation("Yeni bütçe eklendi: {BudgetName}", SelectedBudget.Name); + _logger.LogError(ex, "Bütçe kaydedilirken bir hata oluştu."); + MessageBox.Show("Bütçe kaydedilemedi.", "Hata", MessageBoxButton.OK, MessageBoxImage.Error); } - PrepareForNewBudget(); } [RelayCommand] - private void DeleteBudget(BudgetModel? budgetToDelete) + private async Task DeleteBudgetAsync(BudgetModel? budgetToDelete) { - if (budgetToDelete == null) - { - _logger.LogWarning("Silinecek bütçe bulunamadı."); - return; - } + if (budgetToDelete == null) return; - Budgets.Remove(budgetToDelete); - _logger.LogInformation("Bütçe silindi: {BudgetName}", budgetToDelete.Name); + var result = MessageBox.Show($"'{budgetToDelete.Name}' adlı bütçeyi silmek istediğinizden emin misiniz?", "Silme Onayı", MessageBoxButton.YesNo, MessageBoxImage.Question); + if (result == MessageBoxResult.No) return; - if (SelectedBudget?.Id == budgetToDelete.Id) + try { - PrepareForNewBudget(); + await _apiService.DeleteAsync($"Budgets/{budgetToDelete.Id}"); + Budgets.Remove(budgetToDelete); + _logger.LogInformation("Bütçe silindi: {BudgetId}", budgetToDelete.Id); + + if (SelectedBudget?.Id == budgetToDelete.Id) + { + PrepareForNewBudget(); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Bütçe silinirken hata oluştu: {BudgetId}", budgetToDelete.Id); + MessageBox.Show("Bütçe silinemedi.", "Hata", MessageBoxButton.OK, MessageBoxImage.Error); } } @@ -119,11 +161,13 @@ private void PrepareToEditBudget(BudgetModel? budgetToEdit) { Id = budgetToEdit.Id, Name = budgetToEdit.Name, - Amount = budgetToEdit.Amount, - TargetAmount = budgetToEdit.TargetAmount, + Description = budgetToEdit.Description, + Category = budgetToEdit.Category, + AllocatedAmount = budgetToEdit.AllocatedAmount, + CurrentAmount = budgetToEdit.CurrentAmount, + Currency = budgetToEdit.Currency, StartDate = budgetToEdit.StartDate, - EndDate = budgetToEdit.EndDate, - Currency = budgetToEdit.Currency + EndDate = budgetToEdit.EndDate }; IsEditing = true; } @@ -136,11 +180,7 @@ private void CleanForm() private void PrepareForNewBudget() { - SelectedBudget = new BudgetModel - { - StartDate = DateTime.Today, - EndDate = DateTime.Today.AddMonths(1) - }; + SelectedBudget = new BudgetModel(); IsEditing = false; } } diff --git a/FinTrack/ViewModels/CurrenciesViewModel.cs b/FinTrack/ViewModels/CurrenciesViewModel.cs index 6010076..9155f9f 100644 --- a/FinTrack/ViewModels/CurrenciesViewModel.cs +++ b/FinTrack/ViewModels/CurrenciesViewModel.cs @@ -1,9 +1,12 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Models.Currency; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Currency; +using FinTrackForWindows.Services.Api; +using FinTrackWebApi.Dtos.CurrencyDtos; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class CurrenciesViewModel : ObservableObject { @@ -29,11 +32,15 @@ public partial class CurrenciesViewModel : ObservableObject private readonly ILogger _logger; - public CurrenciesViewModel(ILogger logger) + private readonly IApiService _apiService; + + public CurrenciesViewModel(ILogger logger, IApiService apiService) { _logger = logger; - LoadSampleData(); + _apiService = apiService; + + _ = LoadCurrenciesData(); } partial void OnCurrencySearchChanged(string value) { @@ -57,105 +64,34 @@ private void FilterCurrencies() _logger.LogInformation("Para birimleri '{SearchText}' metnine göre filtrelendi.", CurrencySearch); } - private void LoadSampleData() + private async Task LoadCurrenciesData() { - allCurrencies = new ObservableCollection + var currencies = await _apiService.GetAsync("Currency/latest/USD"); // TODO: USD yerine kullanıcının seçtiği para birimini kullan + allCurrencies = new ObservableCollection(); + if (currencies.Rates != null) { - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/try.png", - ToCurrencyCode = "TRY", - ToCurrencyName = "Turkish Lira", - ToCurrencyPrice = 32.56m, - ToCurrencyChange = "+0.12 (0.37%)", - Type = Enums.CurrencyConversionType.Increase, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" - }, - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/eur.png", - ToCurrencyCode = "EUR", - ToCurrencyName = "Euro", - ToCurrencyPrice = 3.06m, - ToCurrencyChange = "-0.12 (0.37%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" - }, - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/gbp.png", - ToCurrencyCode = "GBP", - ToCurrencyName = "British Pound", - ToCurrencyPrice = 0.08m, - ToCurrencyChange = "+0.20 (0.80%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" - }, - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/eur.png", - ToCurrencyCode = "EUR", - ToCurrencyName = "Euro", - ToCurrencyPrice = 3.06m, - ToCurrencyChange = "-0.12 (0.37%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" - }, - new CurrencyModel + foreach (RateDetailDto item in currencies.Rates) { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/gbp.png", - ToCurrencyCode = "GBP", - ToCurrencyName = "British Pound", - ToCurrencyPrice = 0.08m, - ToCurrencyChange = "+0.20 (0.80%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" - }, - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/eur.png", - ToCurrencyCode = "EUR", - ToCurrencyName = "Euro", - ToCurrencyPrice = 3.06m, - ToCurrencyChange = "-0.12 (0.37%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "32.40", - DailyHigh = "32.60", - WeeklyChange = "+0.2%", - MonthlyChange = "+1.5%" - }, - new CurrencyModel - { - ToCurrencyFlag = "https://currencyfreaks.com/photos/flags/gbp.png", - ToCurrencyCode = "GBP", - ToCurrencyName = "British Pound", - ToCurrencyPrice = 0.08m, - ToCurrencyChange = "+0.20 (0.80%)", - Type = Enums.CurrencyConversionType.Decrease, - DailyLow = "3.05", - DailyHigh = "3.08", - WeeklyChange = "-0.1%", - MonthlyChange = "+0.5%" + allCurrencies.Add(new CurrencyModel + { + Id = item.Id, + ToCurrencyCode = item.Code, + ToCurrencyName = item.CountryCode ?? "N/A", + ToCurrencyFlag = item.IconUrl ?? "N/A", + ToCurrencyPrice = item.Rate, + ToCurrencyChange = "N/A", + Type = CurrencyConversionType.Increase, // TODO: Değişim bilgisi eklenmeli + DailyLow = "N/A", + DailyHigh = "N/A", + WeeklyChange = "N/A", + MonthlyChange = "N/A" + }); } - }; - FilterCurrencies(); - SelectedCurrency = FilteredCurrencies.FirstOrDefault(); - _logger.LogInformation("Örnek para birimleri yüklendi."); + + FilterCurrencies(); + SelectedCurrency = FilteredCurrencies.FirstOrDefault(); + _logger.LogInformation("Para birimleri başarıyla yüklendi. Para birimler: {Currencies}", currencies); + } } } } diff --git a/FinTrack/ViewModels/DashboardViewModel.cs b/FinTrack/ViewModels/DashboardViewModel.cs index 41e120c..fee4fec 100644 --- a/FinTrack/ViewModels/DashboardViewModel.cs +++ b/FinTrack/ViewModels/DashboardViewModel.cs @@ -1,18 +1,23 @@ using CommunityToolkit.Mvvm.ComponentModel; -using FinTrack.Enums; -using FinTrack.Models.Dashboard; +using FinTrackForWindows.Core; +using FinTrackForWindows.Dtos.AccountDtos; +using FinTrackForWindows.Dtos.BudgetDtos; +using FinTrackForWindows.Dtos.TransactionDtos; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Dashboard; +using FinTrackForWindows.Services.Api; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Media; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class DashboardViewModel : ObservableObject { [ObservableProperty] - private ObservableCollection _budgets_DashboardView_ItemsControl; + private ObservableCollection _budgets_DashboardView_ItemsControl; [ObservableProperty] private ObservableCollection _currencyRates_DashboardView_ItemsControl; @@ -42,24 +47,28 @@ public partial class DashboardViewModel : ObservableObject private readonly IServiceProvider _serviceProvider; - public DashboardViewModel(ILogger logger, IServiceProvider serviceProvider) + private readonly IApiService _apiService; + + public DashboardViewModel( + ILogger logger, + IServiceProvider serviceProvider, + IApiService apiService) { _logger = logger; _serviceProvider = serviceProvider; - LoadData(); - } + _apiService = apiService; - private void LoadData() - { - // [TEST] - Budgets_DashboardView_ItemsControl = new ObservableCollection + if (SessionManager.IsLoggedIn) { - new BudgetDashboard { Name = "Tasarruf", DueDate = "15.02.2025", Amount = "6.000$", RemainingTime = "15 gün kaldı", StatusBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") }, - new BudgetDashboard { Name = "Harcama", DueDate = "20.02.2025", Amount = "2.000$", RemainingTime = "10 gün kaldı", StatusBrush = (Brush)Application.Current.FindResource("StatusRedBrush") }, - new BudgetDashboard { Name = "Yatırım", DueDate = "10.03.2025", Amount = "10.000$", RemainingTime = "30 gün kaldı", StatusBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") }, - new BudgetDashboard { Name = "Eğlence", DueDate = "05.04.2025", Amount = "8.000$", RemainingTime = "20 gün kaldı", StatusBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") } - }; + _logger.LogInformation("Kullanıcı zaten giriş yapmış. DashboardViewModel verileri yüklüyor."); + _ = LoadBudgetData(); + _ = LoadAccountData(); + _ = LoadTransactionData(); + } + } + private async Task LoadData() + { // [TEST] CurrencyRates_DashboardView_ItemsControl = new ObservableCollection { @@ -75,41 +84,6 @@ private void LoadData() } }; - // [TEST] - Accounts_DashboardView_ItemsControl = new ObservableCollection - { - new AccountDashboard { Name = "Nakit", Percentage = 50, Balance = "5.000$", ProgressBarBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") }, - new AccountDashboard { Name = "Banka", Percentage = 30, Balance = "3.000$", ProgressBarBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") } - }; - - TotalBalance_DashboardView_TextBlock = "7.000$"; - - // [TEST] - Transactions_DashboardView_ListView = new ObservableCollection - { - new TransactionDashboard { DateText = "01.01.2025", Description = "Market Alışverişi", Amount = "-150$", Category = "Gıda", Type = Enums.TransactionType.Expense }, - new TransactionDashboard { DateText = "02.01.2025", Description = "Maaş", Amount = "+3.000$", Category = "Gelir", Type = Enums.TransactionType.Income }, - new TransactionDashboard { DateText = "03.01.2025", Description = "Elektrik Faturası", Amount = "-200$", Category = "Fatura", Type = Enums.TransactionType.Expense } - }; - - // [TEST] - double totalIncome = Transactions_DashboardView_ListView - .Where(t => t.Type == TransactionType.Income) - .Sum(t => - { - var cleaned = t.Amount.Replace("+", string.Empty).Replace("$", string.Empty).Trim(); - return double.TryParse(cleaned, out var value) ? value : 0; - }); - double totalExpense = Transactions_DashboardView_ListView - .Where(t => t.Type == TransactionType.Expense) - .Sum(t => - { - var cleaned = t.Amount.Replace("-", string.Empty).Replace("$", string.Empty).Trim(); - return double.TryParse(cleaned, out var value) ? value : 0; - }); - double remainingBalance = totalIncome - totalExpense; - TransactionSummary = $"Toplam {Transactions_DashboardView_ListView.Count} işlem bulundu. Gelir: +{totalIncome}$, Gider: -{totalExpense}$ Kalan: {remainingBalance}"; - // [TEST] CurrentMembership_DashboardView_Multiple = new MembershipDashboard { Level = "Pro | AKTF", StartDate = "01.01.2025", RenewalDate = "01.02.2025", Price = "9.99$" }; @@ -147,5 +121,87 @@ private ReportDashboardModel CreateReport(string name) }; return report; } + + private async Task LoadBudgetData() + { + var budgets = await _apiService.GetAsync>("Budgets"); + Budgets_DashboardView_ItemsControl = new ObservableCollection(); + if (budgets != null) + { + for (int i = 0; i < 4; i++) + { + Budgets_DashboardView_ItemsControl.Add(new BudgetDashboardModel + { + Name = budgets[i].Name, + DueDate = budgets[i].EndDate.ToString("dd.MM.yyyy"), + Amount = $"{budgets[i].AllocatedAmount} {budgets[i].Currency}", + RemainingTime = $"Son {(budgets[i].EndDate - budgets[i].StartDate).Days} gün kaldı.", + StatusBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") + }); + } + } + } + + private async Task LoadAccountData() + { + var accounts = await _apiService.GetAsync>("Account"); + Accounts_DashboardView_ItemsControl = new ObservableCollection(); + if (accounts != null) + { + decimal totalBalance = 0; + for (int i = 0; i < 2; i++) + { + Accounts_DashboardView_ItemsControl.Add(new AccountDashboard + { + Name = accounts[i].Name, + Balance = $"{accounts[i].Balance} {accounts[i].Currency}", + Percentage = 70, // Burası yüzdelik bar olduğu için daha iyi bir hesaplama yapılmalı. + ProgressBarBrush = (Brush)Application.Current.FindResource("StatusGreenBrush") + }); + + totalBalance += accounts[i].Balance; + } + + TotalBalance_DashboardView_TextBlock = $"{totalBalance} {accounts[0].Currency}"; + } + } + + private async Task LoadTransactionData() + { + var transactions = await _apiService.GetAsync>("Transactions"); + Transactions_DashboardView_ListView = new ObservableCollection(); + if (transactions != null) + { + foreach (var item in transactions) + { + Transactions_DashboardView_ListView.Add(new TransactionDashboard + { + DateText = item.TransactionDateUtc.ToString("dd.MM.yyyy"), + Description = item.Description ?? "N/A", + Amount = $"{item.Amount} {item.Currency}", + Category = item.Category.Name, + Type = item.Category.Type + }); + } + + double totalIncome = Transactions_DashboardView_ListView + .Where(t => t.Type == TransactionType.Income) + .Sum(t => + { + var cleaned = t.Amount.Replace("+", string.Empty).Replace("$", string.Empty).Trim(); + return double.TryParse(cleaned, out var value) ? value : 0; + }); + double totalExpense = Transactions_DashboardView_ListView + .Where(t => t.Type == TransactionType.Expense) + .Sum(t => + { + var cleaned = t.Amount.Replace("-", string.Empty).Replace("$", string.Empty).Trim(); + return double.TryParse(cleaned, out var value) ? value : 0; + }); + double remainingBalance = totalIncome - totalExpense; + + TransactionSummary = $"Toplam {Transactions_DashboardView_ListView.Count} işlem bulundu. Gelir: +{totalIncome} {transactions[0].Currency}, Gider: -{totalExpense} {transactions[0].Currency} Kalan: {remainingBalance} {transactions[0].Currency}"; + } + } } } diff --git a/FinTrack/ViewModels/DebtViewModel.cs b/FinTrack/ViewModels/DebtViewModel.cs index 5c3e0c1..8e5196c 100644 --- a/FinTrack/ViewModels/DebtViewModel.cs +++ b/FinTrack/ViewModels/DebtViewModel.cs @@ -1,12 +1,12 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Debt; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Debt; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class DebtViewModel : ObservableObject { @@ -57,7 +57,7 @@ private void SendOffer() BorrowerName = "Unknown", Amount = NewProposalAmount, DueDate = NewProposalDueDate, - Status = DebtStatus.PendingProposal, + Status = DebtStatusType.PendingBorrowerAcceptance, CurrentUserName = CurrentUserName }; @@ -74,7 +74,7 @@ private void ConfirmOffer(DebtModel debt) { if (debt == null) return; - debt.Status = DebtStatus.AwaitingVideoUpload; + debt.Status = DebtStatusType.PendingOperatorApproval; debt.BorrowerName = CurrentUserName; RefreshLists(); _logger.LogInformation("{Amount} TRY tutarındaki borç teklifi onaylandı.", debt.Amount); @@ -85,7 +85,7 @@ private void RejectOffer(DebtModel debt) { if (debt == null) return; - debt.Status = DebtStatus.RejectedByBorrower; + debt.Status = DebtStatusType.RejectedByOperator; RefreshLists(); _logger.LogWarning("{Amount} TRY tutarındaki borç teklifi reddedildi.", debt.Amount); } @@ -95,7 +95,7 @@ private void UploadVideo(DebtModel debt) { if (debt == null) return; - debt.Status = DebtStatus.AwaitingOperatorApproval; + debt.Status = DebtStatusType.PendingOperatorApproval; RefreshLists(); _logger.LogInformation("{Amount} TRY borcu için onay videosu yüklendi, operatör onayı bekleniyor.", debt.Amount); MessageBox.Show("Video başarıyla yüklendi. Operatör onayı bekleniyor.", "Başarılı"); @@ -103,11 +103,11 @@ private void UploadVideo(DebtModel debt) private void RefreshLists() { - var pending = allDebts.Where(d => d.Status == DebtStatus.PendingProposal && d.LenderName != CurrentUserName).ToList(); + var pending = allDebts.Where(d => d.Status == DebtStatusType.PendingBorrowerAcceptance && d.LenderName != CurrentUserName).ToList(); PendingOffers.Clear(); foreach (var item in pending) PendingOffers.Add(item); - var myDebts = allDebts.Where(d => d.Status != DebtStatus.PendingProposal && (d.LenderName == CurrentUserName || d.BorrowerName == CurrentUserName)).ToList(); + var myDebts = allDebts.Where(d => d.Status != DebtStatusType.PendingBorrowerAcceptance && (d.LenderName == CurrentUserName || d.BorrowerName == CurrentUserName)).ToList(); MyDebtsList.Clear(); foreach (var item in myDebts) MyDebtsList.Add(item); } @@ -122,7 +122,7 @@ private void LoadSampleData() BorrowerName = "Unknown", Amount = 500, DueDate = new DateTime(2024, 6, 15), - Status = DebtStatus.PendingProposal, + Status = DebtStatusType.RejectedByOperator, CurrentUserName = CurrentUserName }, new DebtModel @@ -131,7 +131,7 @@ private void LoadSampleData() BorrowerName = "Eylül Korkmaz", Amount = 2500, DueDate = new DateTime(2024, 10, 1), - Status = DebtStatus.AwaitingVideoUpload, + Status = DebtStatusType.PendingOperatorApproval, CurrentUserName = CurrentUserName }, new DebtModel @@ -140,7 +140,7 @@ private void LoadSampleData() BorrowerName = CurrentUserName, Amount = 30000, DueDate = new DateTime(2024, 8, 31), - Status = DebtStatus.Active, + Status = DebtStatusType.Active, CurrentUserName = CurrentUserName }, new DebtModel @@ -149,7 +149,7 @@ private void LoadSampleData() BorrowerName = "Ali Veli", Amount = 800000, DueDate = new DateTime(2025, 1, 1), - Status = DebtStatus.AwaitingOperatorApproval, + Status = DebtStatusType.Active, CurrentUserName = CurrentUserName }, new DebtModel @@ -158,7 +158,7 @@ private void LoadSampleData() BorrowerName = "Canan Aslan", Amount = 1000, DueDate = new DateTime(2024, 9, 20), - Status = DebtStatus.RejectedByOperator, + Status = DebtStatusType.RejectedByOperator, RejectionReason = "Insufficient video", CurrentUserName = CurrentUserName } diff --git a/FinTrack/ViewModels/FeedbackViewModel.cs b/FinTrack/ViewModels/FeedbackViewModel.cs index 2effc29..c1a0cb8 100644 --- a/FinTrack/ViewModels/FeedbackViewModel.cs +++ b/FinTrack/ViewModels/FeedbackViewModel.cs @@ -1,12 +1,12 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; +using FinTrackForWindows.Enums; using Microsoft.Extensions.Logging; using Microsoft.Win32; using System.Diagnostics; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class FeedbackViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/FinBotViewModel.cs b/FinTrack/ViewModels/FinBotViewModel.cs index 38ccf25..70a703b 100644 --- a/FinTrack/ViewModels/FinBotViewModel.cs +++ b/FinTrack/ViewModels/FinBotViewModel.cs @@ -1,11 +1,14 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.FinBot; +using FinTrackForWindows.Dtos.ChatDtos; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.FinBot; +using FinTrackForWindows.Services.Api; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; +using System.Text; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class FinBotViewModel : ObservableObject { @@ -17,11 +20,25 @@ public partial class FinBotViewModel : ObservableObject private readonly ILogger _logger; - public FinBotViewModel(ILogger logger) + private readonly IApiService _apiService; + + private const string chars = "qQwWeErRtTyYuUiIoOpPaAsSdDfFgGhHjJkKlLzZxXcCvVbBnNmM0123456789+-*/|<>£&()='!#${[]}"; + private readonly string? clientChatSessionId; + + public FinBotViewModel(ILogger logger, IApiService apiService) { _logger = logger; + _apiService = apiService; Messages = new ObservableCollection(); + Random random = new Random(); + StringBuilder result = new StringBuilder(10); + for (int i = 0; i < 10; i++) + { + result.Append(chars[random.Next(chars.Length)]); + } + clientChatSessionId = result.ToString(); + LoadInitialMessage(); } @@ -31,9 +48,11 @@ private void LoadInitialMessage() { QuickActions = new ObservableCollection { - "View Account Balance", - "Recent Transactions", - "Budget Overview" + "List All My Accounts", + "List All My Budgets", + "List All My Transacitons", + "Total Income Amount", + "Total Expense Amount" } }; Messages.Add(initialMessage); @@ -52,7 +71,17 @@ private async Task SendMessageAsync() _logger.LogInformation("Kullanıcı mesaj yazdı. {MessageText}", userMessage.Text); - await ProcessBotResponseAsync(userMessage.Text); + var chatResponse = await _apiService.PostAsync("Chat/send", new ChatRequestDto + { + Message = userMessage.Text, + ClientChatSessionId = clientChatSessionId, + }); + + if (chatResponse != null) + { + var botResponse = new ChatMessageModel(chatResponse.Reply ?? "N/A", MessageAuthor.Bot); + Messages.Add(botResponse); + } } private bool CanSendMessage => !string.IsNullOrWhiteSpace(MessageInput); @@ -62,43 +91,42 @@ private async Task SendQuickActionAsync(string actionText) { if (string.IsNullOrWhiteSpace(actionText)) return; - var userMessage = new ChatMessageModel(actionText, MessageAuthor.User); + string actionMessage = string.Empty; + switch (actionText) + { + case "List All My Accounts": + actionMessage = "List all my accounts. Don't give too long explanations."; + return; + case "List All My Budgets": + actionMessage = "List all my budgets. Don't give too long explanations."; + return; + case "List All My Transacitons": + actionMessage = "List all my transacitons. Don't give too long explanations."; + return; + case "Total Income Amount": + actionMessage = "The sum of all my income. Don't give too long explanations."; + return; + case "Total Expense Amount": + actionMessage = "The sum of all my expense. Don't give too long explanations."; + return; + } + + var userMessage = new ChatMessageModel(actionMessage, MessageAuthor.User); Messages.Add(userMessage); _logger.LogInformation("Kullanıcı hızlı eylem seçti: {ActionText}", actionText); - await ProcessBotResponseAsync(actionText); + await ProcessBotResponseAsync(actionMessage); } - - - - - - // TODO: [TEST] private async Task ProcessBotResponseAsync(string userMessage) { - // Bot "yazıyor..." efekti için küçük bir bekleme - await Task.Delay(1000); + await Task.Delay(1000); // Bot "yazıyor..." efekti için küçük bir bekleme ChatMessageModel botResponse; string lowerUserMessage = userMessage.ToLower(); - if (lowerUserMessage.Contains("bakiye")) - { - botResponse = new ChatMessageModel("Toplam bakiyeniz tüm hesaplarınızda $12,450.75.", MessageAuthor.Bot); - } - else if (lowerUserMessage.Contains("teşekkür")) - { - botResponse = new ChatMessageModel("Rica ederim! Başka bir konuda yardımcı olabilir miyim?", MessageAuthor.Bot); - } - else - { - botResponse = new ChatMessageModel("Üzgünüm, bu isteği anlayamadım. Lütfen farklı bir şekilde sormayı deneyin.", MessageAuthor.Bot) - { - QuickActions = new ObservableCollection { "Yeni Bütçe Oluştur", "Hesap Bakiyem", "Rapor Oluştur" } - }; - } + botResponse = new ChatMessageModel(lowerUserMessage, MessageAuthor.Bot); Messages.Add(botResponse); } diff --git a/FinTrack/ViewModels/ForgotPasswordViewModel.cs b/FinTrack/ViewModels/ForgotPasswordViewModel.cs index 6915560..0ecba24 100644 --- a/FinTrack/ViewModels/ForgotPasswordViewModel.cs +++ b/FinTrack/ViewModels/ForgotPasswordViewModel.cs @@ -2,7 +2,7 @@ using CommunityToolkit.Mvvm.Input; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class ForgotPasswordViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/LoginViewModel.cs b/FinTrack/ViewModels/LoginViewModel.cs index 2a3c91c..1da99aa 100644 --- a/FinTrack/ViewModels/LoginViewModel.cs +++ b/FinTrack/ViewModels/LoginViewModel.cs @@ -1,13 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; -using FinTrack.Core; -using FinTrack.Messages; -using FinTrack.Services; +using FinTrackForWindows.Core; +using FinTrackForWindows.Messages; +using FinTrackForWindows.Services; using Microsoft.Extensions.Logging; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class LoginViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/MainViewModel.cs b/FinTrack/ViewModels/MainViewModel.cs index 06957f8..d3dd0ec 100644 --- a/FinTrack/ViewModels/MainViewModel.cs +++ b/FinTrack/ViewModels/MainViewModel.cs @@ -1,6 +1,6 @@ using CommunityToolkit.Mvvm.ComponentModel; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class MainViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/NotificationSettingsContentViewModel.cs b/FinTrack/ViewModels/NotificationSettingsContentViewModel.cs index 8bda78e..c0fc418 100644 --- a/FinTrack/ViewModels/NotificationSettingsContentViewModel.cs +++ b/FinTrack/ViewModels/NotificationSettingsContentViewModel.cs @@ -1,12 +1,12 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Settings; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Settings; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class NotificationSettingsContentViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/NotificationViewModel.cs b/FinTrack/ViewModels/NotificationViewModel.cs index ce8681b..b532927 100644 --- a/FinTrack/ViewModels/NotificationViewModel.cs +++ b/FinTrack/ViewModels/NotificationViewModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Notification; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Notification; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class NotificationViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/OtpVerificationViewModel.cs b/FinTrack/ViewModels/OtpVerificationViewModel.cs index f049065..91bd108 100644 --- a/FinTrack/ViewModels/OtpVerificationViewModel.cs +++ b/FinTrack/ViewModels/OtpVerificationViewModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Core; -using FinTrack.Services; +using FinTrackForWindows.Core; +using FinTrackForWindows.Services; using Microsoft.Extensions.Logging; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class OtpVerificationViewModel : ObservableObject { @@ -77,10 +77,14 @@ private async Task VerifyOtpCode_OtpVerificationView_Button() [RelayCommand] private async Task CodeNotFound_OtpVerificationView_Button() { - if (NewUserInformationManager.FullName != null && NewUserInformationManager.Email != null && NewUserInformationManager.Password != null) + if (string.IsNullOrEmpty(NewUserInformationManager.FirstName) || + string.IsNullOrEmpty(NewUserInformationManager.LastName) || + string.IsNullOrEmpty(NewUserInformationManager.Email) || + string.IsNullOrEmpty(NewUserInformationManager.Password)) { bool isInitiateRegistration = await _authService.InitiateRegistrationAsnc( - NewUserInformationManager.FullName, + NewUserInformationManager.FirstName, + NewUserInformationManager.LastName, NewUserInformationManager.Email, NewUserInformationManager.Password); @@ -100,5 +104,12 @@ private async Task CodeNotFound_OtpVerificationView_Button() NavigateToRegisterRequested?.Invoke(); } } + + [RelayCommand] + private void NavigateToRegister_OtpVerificationView_Button() + { + NavigateToRegisterRequested?.Invoke(); + _logger.LogInformation("Kullanıcı giriş sayfasına yönlendirildi."); + } } } diff --git a/FinTrack/ViewModels/ProfileSettingsContentViewModel.cs b/FinTrack/ViewModels/ProfileSettingsContentViewModel.cs index a1b672b..9f9bd7f 100644 --- a/FinTrack/ViewModels/ProfileSettingsContentViewModel.cs +++ b/FinTrack/ViewModels/ProfileSettingsContentViewModel.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class ProfileSettingsContentViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/RegisterViewModel.cs b/FinTrack/ViewModels/RegisterViewModel.cs index b00fefa..ed01f8d 100644 --- a/FinTrack/ViewModels/RegisterViewModel.cs +++ b/FinTrack/ViewModels/RegisterViewModel.cs @@ -1,16 +1,20 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Core; -using FinTrack.Services; +using FinTrackForWindows.Core; +using FinTrackForWindows.Services; using Microsoft.Extensions.Logging; +using System.Text.RegularExpressions; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class RegisterViewModel : ObservableObject { [ObservableProperty] - private string? fullName_RegisterView_TextBox; + private string? firstName_RegisterView_TextBox; + + [ObservableProperty] + private string? lastName_RegisterView_TextBox; [ObservableProperty] private string? email_RegisterView_TextBox; @@ -42,7 +46,8 @@ public RegisterViewModel(ILogger logger, IAuthService authSer private async Task Register_RegisterView_Button() { NavigateToOtpVerificationRequested?.Invoke(); - if (string.IsNullOrEmpty(FullName_RegisterView_TextBox) || + if (string.IsNullOrEmpty(FirstName_RegisterView_TextBox) || + string.IsNullOrEmpty(LastName_RegisterView_TextBox) || string.IsNullOrEmpty(Email_RegisterView_TextBox) || string.IsNullOrEmpty(Password_RegisterView_TextBox)) { @@ -59,8 +64,16 @@ private async Task Register_RegisterView_Button() return; } + if (IsPasswordValid(Password_RegisterView_TextBox) == false) + { + MessageBox.Show("Şifre en az 8 karakter uzunluğunda, en az bir büyük harf, bir küçük harf, bir rakam ve bir özel karakter içermelidir.", "Hata", MessageBoxButton.OK, MessageBoxImage.Error); + _logger.LogWarning("Kayıt işlemi için geçersiz şifre girildi."); + return; + } + bool isInitiateRegistration = await _authService.InitiateRegistrationAsnc( - FullName_RegisterView_TextBox, + FirstName_RegisterView_TextBox, + LastName_RegisterView_TextBox, Email_RegisterView_TextBox, Password_RegisterView_TextBox); if (!isInitiateRegistration) @@ -74,13 +87,22 @@ private async Task Register_RegisterView_Button() _logger.LogInformation("Kayıt işlemi başarılı. E-posta: {Email}", Email_RegisterView_TextBox); // Store user information in the static manager - NewUserInformationManager.FullName = FullName_RegisterView_TextBox; + NewUserInformationManager.FirstName = FirstName_RegisterView_TextBox; + NewUserInformationManager.LastName = LastName_RegisterView_TextBox; + NewUserInformationManager.FullName = FirstName_RegisterView_TextBox.Replace(" ", "").Trim() + "_" + LastName_RegisterView_TextBox.Replace(" ", "").Trim(); NewUserInformationManager.Email = Email_RegisterView_TextBox; NewUserInformationManager.Password = Password_RegisterView_TextBox; NavigateToOtpVerificationRequested?.Invoke(); } + private bool IsPasswordValid(string password) + { + string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':""\\|,.<>\/?]).{8,}$"; + Regex regex = new Regex(pattern); + return regex.IsMatch(password); + } + [RelayCommand] private void TogglePasswordVisibility_RegisterView_Button() { diff --git a/FinTrack/ViewModels/ReportsViewModel.cs b/FinTrack/ViewModels/ReportsViewModel.cs index 860a2a7..9931ed0 100644 --- a/FinTrack/ViewModels/ReportsViewModel.cs +++ b/FinTrack/ViewModels/ReportsViewModel.cs @@ -1,13 +1,13 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Report; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Report; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Text; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class ReportsViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/SecuritySettingsContentViewModel.cs b/FinTrack/ViewModels/SecuritySettingsContentViewModel.cs index 8ec4829..a0a9847 100644 --- a/FinTrack/ViewModels/SecuritySettingsContentViewModel.cs +++ b/FinTrack/ViewModels/SecuritySettingsContentViewModel.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class SecuritySettingsContentViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/SettingsViewModel.cs b/FinTrack/ViewModels/SettingsViewModel.cs index b935fc5..4c078c4 100644 --- a/FinTrack/ViewModels/SettingsViewModel.cs +++ b/FinTrack/ViewModels/SettingsViewModel.cs @@ -4,7 +4,7 @@ using System.Windows; using System.Windows.Input; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class SettingsViewModel : ObservableObject { diff --git a/FinTrack/ViewModels/TopBarViewModel.cs b/FinTrack/ViewModels/TopBarViewModel.cs index 16209f8..7d74ad6 100644 --- a/FinTrack/ViewModels/TopBarViewModel.cs +++ b/FinTrack/ViewModels/TopBarViewModel.cs @@ -1,11 +1,11 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Core; -using FinTrack.Dtos; -using FinTrack.Services.Api; +using FinTrackForWindows.Core; +using FinTrackForWindows.Dtos; +using FinTrackForWindows.Services.Api; using Microsoft.Extensions.Logging; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class TopBarViewModel : ObservableObject { @@ -55,7 +55,7 @@ private async Task LoadProfile() _logger.LogWarning("Kullanıcı oturumu açık değil, profil bilgileri yüklenemedi."); return; } - var userProfile = await _apiService.GetAsync("user"); + var userProfile = await _apiService.GetAsync("User"); if (userProfile != null) { diff --git a/FinTrack/ViewModels/TransactionsViewModel.cs b/FinTrack/ViewModels/TransactionsViewModel.cs index 74a81d1..a614700 100644 --- a/FinTrack/ViewModels/TransactionsViewModel.cs +++ b/FinTrack/ViewModels/TransactionsViewModel.cs @@ -1,17 +1,20 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; -using FinTrack.Enums; -using FinTrack.Models.Transaction; +using FinTrackForWindows.Dtos.TransactionDtos; +using FinTrackForWindows.Enums; +using FinTrackForWindows.Models.Transaction; +using FinTrackForWindows.Services.Api; using Microsoft.Extensions.Logging; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Windows; -namespace FinTrack.ViewModels +namespace FinTrackForWindows.ViewModels { public partial class TransactionsViewModel : ObservableObject { private readonly ILogger _logger; + private readonly IApiService _apiService; [ObservableProperty] private ObservableCollection transactions; @@ -38,10 +41,11 @@ public partial class TransactionsViewModel : ObservableObject [ObservableProperty] private string mostSpending; - public TransactionsViewModel(ILogger logger) + public TransactionsViewModel(ILogger logger, IApiService apiService) { _logger = logger; - LoadSampleData(); + _apiService = apiService; + _ = LoadData(); NewTransaction(); } @@ -84,10 +88,11 @@ private void EditTransaction(TransactionModel transactionToEdit) [RelayCommand] - private void DeleteTransaction(TransactionModel transactionToDelete) + private async Task DeleteTransaction(TransactionModel transactionToDelete) { if (transactionToDelete != null) { + await _apiService.DeleteAsync($"Transactions/{transactionToDelete.Id}"); Transactions.Remove(transactionToDelete); _logger.LogInformation("'{TransactionName}' adlı işlem silindi.", transactionToDelete.NameOrDescription); NewTransaction(); @@ -95,7 +100,7 @@ private void DeleteTransaction(TransactionModel transactionToDelete) } [RelayCommand] - private void SaveTransaction() + private async Task SaveTransaction() { if (string.IsNullOrWhiteSpace(EditableTransaction.NameOrDescription)) { @@ -117,6 +122,12 @@ private void SaveTransaction() existing.Category = EditableTransaction.Category; existing.Currency = EditableTransaction.Currency; + // TODO: Yeni Gelir/Gider şemasına uygun. + //await _apiService.PutAsync($"Transactions/{existing.Id}", new TransactionUpdateDto + //{ + + //}); + _logger.LogInformation("'{TransactionName}' adlı işlem güncellendi.", existing.NameOrDescription); CalculateTotals(); } @@ -130,41 +141,27 @@ private void SaveTransaction() NewTransaction(); } - private void LoadSampleData() + private async Task LoadData() { - Transactions = new ObservableCollection + var transactions = await _apiService.GetAsync>("Transactions"); + Transactions = new ObservableCollection(); + if (transactions != null) { - new TransactionModel - { - NameOrDescription = "Maaş", - Amount = 5000m, - Date = DateTime.Now.AddDays(-2), - AccountName = "ING Bank - Vadesiz", - Category = "Maaş", - Type = TransactionType.Income, - Currency = "TRY" - }, - new TransactionModel + foreach (var transaction in transactions) { - NameOrDescription = "Market Alışverişi", - Amount = 450.75m, - Date = DateTime.Now.AddDays(-5), - AccountName = "Garanti Kredi Kartı", - Category = "Gıda", - Type = TransactionType.Expense, - Currency = "TRY" - }, - new TransactionModel - { - NameOrDescription = "Elektrik Faturası", - Amount = 275.50m, - Date = DateTime.Now.AddDays(-10), - AccountName = "ING Bank - Vadesiz", - Category = "Fatura", - Type = TransactionType.Expense, - Currency = "TRY" + Transactions.Add(new TransactionModel + { + Id = transaction.Id, + NameOrDescription = transaction.Description ?? "N/A", + Amount = transaction.Amount, + Date = transaction.TransactionDateUtc, + AccountName = transaction.Account.Name, + Category = transaction.Category.Name, + Type = transaction.Category.Type, + Currency = transaction.Currency.ToString() + }); } - }; + } Transactions.CollectionChanged += OnTransactionsChanged; CalculateTotals(); diff --git a/FinTrack/Views/AccountView.xaml b/FinTrack/Views/AccountView.xaml index fa0949a..aa23a36 100644 --- a/FinTrack/Views/AccountView.xaml +++ b/FinTrack/Views/AccountView.xaml @@ -1,15 +1,21 @@ - + + + + + @@ -41,9 +47,6 @@ - @@ -68,13 +71,18 @@ - - - - - + + @@ -89,16 +97,24 @@ - - - - - - - + + + + + + + - + + + + + + +