1+ using CommunityToolkit . Mvvm . ComponentModel ;
2+ using FinTrackForWindows . Core ;
3+ using FinTrackForWindows . Dtos . DebtDtos ;
4+ using FinTrackForWindows . Enums ;
5+ using FinTrackForWindows . Models . Debt ;
6+ using FinTrackForWindows . Services . Api ;
7+ using Microsoft . Extensions . Logging ;
8+ using System . Collections . ObjectModel ;
9+ using System . IdentityModel . Tokens . Jwt ;
10+ using System . Security . Claims ;
11+
12+ namespace FinTrackForWindows . Services . Debts
13+ {
14+ public partial class DebtStore : ObservableObject , IDebtStore
15+ {
16+ private readonly IApiService _apiService ;
17+ private readonly ILogger < DebtStore > _logger ;
18+ private readonly int _currentUserId ;
19+
20+ [ ObservableProperty ]
21+ private bool _isLoading ;
22+
23+ private readonly ObservableCollection < DebtModel > _pendingOffers ;
24+ public ReadOnlyObservableCollection < DebtModel > PendingOffers { get ; }
25+
26+ private readonly ObservableCollection < DebtModel > _myDebtsList ;
27+ public ReadOnlyObservableCollection < DebtModel > MyDebtsList { get ; }
28+
29+ private readonly ObservableCollection < DebtModel > _activeDebts ;
30+ public ReadOnlyObservableCollection < DebtModel > ActiveDebts { get ; }
31+
32+ public event Action ? DebtsChanged ;
33+
34+ public DebtStore ( IApiService apiService , ILogger < DebtStore > logger )
35+ {
36+ _apiService = apiService ;
37+ _logger = logger ;
38+
39+ _activeDebts = new ObservableCollection < DebtModel > ( ) ;
40+ ActiveDebts = new ReadOnlyObservableCollection < DebtModel > ( _activeDebts ) ;
41+
42+ var handler = new JwtSecurityTokenHandler ( ) ;
43+ var jsonToken = handler . ReadJwtToken ( SessionManager . CurrentToken ) ;
44+ _currentUserId = Convert . ToInt32 ( jsonToken . Claims . FirstOrDefault ( claim => claim . Type == ClaimTypes . NameIdentifier ) ? . Value ) ;
45+
46+ _pendingOffers = new ObservableCollection < DebtModel > ( ) ;
47+ PendingOffers = new ReadOnlyObservableCollection < DebtModel > ( _pendingOffers ) ;
48+
49+ _myDebtsList = new ObservableCollection < DebtModel > ( ) ;
50+ MyDebtsList = new ReadOnlyObservableCollection < DebtModel > ( _myDebtsList ) ;
51+ }
52+
53+ public async Task LoadDebtsAsync ( )
54+ {
55+ IsLoading = true ;
56+ _logger . LogInformation ( "Loading debt data from API..." ) ;
57+ try
58+ {
59+ var debtDtos = await _apiService . GetAsync < List < DebtDto > > ( "Debt" ) ;
60+ if ( debtDtos == null ) return ;
61+
62+ _pendingOffers . Clear ( ) ;
63+ _myDebtsList . Clear ( ) ;
64+ _activeDebts . Clear ( ) ;
65+
66+ foreach ( var dto in debtDtos )
67+ {
68+ var debtModel = new DebtModel
69+ {
70+ Id = dto . Id ,
71+ LenderId = dto . LenderId ,
72+ BorrowerId = dto . BorrowerId ,
73+ CurrentUserId = _currentUserId ,
74+ LenderName = dto . LenderName ,
75+ BorrowerName = dto . BorrowerName ,
76+ borrowerImageUrl = dto . BorrowerProfilePicture ?? "/Assets/Images/Icons/user-red.png" ,
77+ lenderImageUrl = dto . LenderProfilePicture ?? "/Assets/Images/Icons/user-green.png" ,
78+ Amount = dto . Amount ,
79+ DueDate = dto . DueDateUtc . ToLocalTime ( ) ,
80+ Status = dto . Status
81+ } ;
82+
83+ if ( dto . Status == DebtStatusType . PendingBorrowerAcceptance && dto . BorrowerId == _currentUserId )
84+ {
85+ _pendingOffers . Add ( debtModel ) ;
86+ }
87+ else
88+ {
89+ _myDebtsList . Add ( debtModel ) ;
90+ }
91+
92+ if ( dto . Status == DebtStatusType . Active )
93+ {
94+ _activeDebts . Add ( debtModel ) ;
95+ }
96+ }
97+ DebtsChanged ? . Invoke ( ) ;
98+ _logger . LogInformation ( "Successfully loaded and processed {Count} debts." , debtDtos . Count ) ;
99+ }
100+ catch ( Exception ex )
101+ {
102+ _logger . LogError ( ex , "Failed to load debt data." ) ;
103+ }
104+ finally
105+ {
106+ IsLoading = false ;
107+ }
108+ }
109+
110+ public async Task SendOfferAsync ( string borrowerEmail , decimal amount , string currency , DateTime dueDate , string description )
111+ {
112+ IsLoading = true ;
113+ try
114+ {
115+ var createDto = new CreateDebtOfferRequestDto
116+ {
117+ BorrowerEmail = borrowerEmail ,
118+ Amount = amount ,
119+ CurrencyCode = BaseCurrencyType . TRY ,
120+ DueDateUtc = dueDate . ToUniversalTime ( ) ,
121+ Description = description
122+ } ;
123+
124+ _logger . LogInformation ( "Sending new debt offer to API..." ) ;
125+ await _apiService . PostAsync < object > ( "Debt/create-debt-offer" , createDto ) ;
126+ await LoadDebtsAsync ( ) ;
127+ _logger . LogInformation ( "Debt offer sent successfully." ) ;
128+ }
129+ catch ( Exception ex )
130+ {
131+ _logger . LogError ( ex , "Failed to send debt offer." ) ;
132+ throw ;
133+ }
134+ finally
135+ {
136+ IsLoading = false ;
137+ }
138+ }
139+
140+ public async Task RespondToOfferAsync ( DebtModel debt , bool accepted )
141+ {
142+ IsLoading = true ;
143+ try
144+ {
145+ _logger . LogInformation ( "Responding to offer for DebtId: {DebtId} with decision: {Decision}" , debt . Id , accepted ) ;
146+ var requestBody = new { Accepted = accepted } ;
147+ await _apiService . PostAsync < bool > ( $ "Debt/respond-to-offer/{ debt . Id } ", requestBody ) ;
148+ await LoadDebtsAsync ( ) ;
149+ _logger . LogInformation ( "Successfully responded to offer for DebtId: {DebtId}" , debt . Id ) ;
150+ }
151+ catch ( Exception ex )
152+ {
153+ _logger . LogError ( ex , "Failed to respond to debt offer for DebtId: {DebtId}" , debt . Id ) ;
154+ throw ;
155+ }
156+ finally
157+ {
158+ IsLoading = false ;
159+ }
160+ }
161+
162+ public async Task UploadVideoAsync ( DebtModel debt , string filePath )
163+ {
164+ IsLoading = true ;
165+ try
166+ {
167+ _logger . LogInformation ( "Uploading video for DebtId: {DebtId}" , debt . Id ) ;
168+ await _apiService . UploadFileAsync ( $ "Videos/user-upload-video?debtId={ debt . Id } ", filePath ) ;
169+ await LoadDebtsAsync ( ) ;
170+ _logger . LogInformation ( "Video uploaded successfully for DebtId: {DebtId}" , debt . Id ) ;
171+ }
172+ catch ( Exception ex )
173+ {
174+ _logger . LogError ( ex , "Failed to upload video for DebtId: {DebtId}" , debt . Id ) ;
175+ throw ;
176+ }
177+ finally
178+ {
179+ IsLoading = false ;
180+ }
181+ }
182+ }
183+ }
0 commit comments