286 lines
10 KiB
C#
286 lines
10 KiB
C#
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using CORP_MAUI.Models;
|
||
|
||
namespace CORP_MAUI.Pages;
|
||
|
||
public partial class RequestsPage : ContentPage
|
||
{
|
||
private readonly ObservableCollection<Request> _requests;
|
||
private List<Request> _allRequests = new();
|
||
private string _currentFilter = "all";
|
||
private string _searchText = string.Empty;
|
||
|
||
public RequestsPage()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("=== REQUESTSPAGE CONSTRUCTOR START ===");
|
||
Trace.WriteLine("[RequestsPage] >>> Вызов InitializeComponent");
|
||
|
||
InitializeComponent();
|
||
|
||
Trace.WriteLine("[RequestsPage] >>> InitializeComponent завершен");
|
||
|
||
_requests = new ObservableCollection<Request>();
|
||
|
||
RequestsCollectionView.ItemsSource = _requests;
|
||
|
||
Trace.WriteLine("[RequestsPage] >>> Запуск LoadRequestsAsync");
|
||
// Загружаем заявления
|
||
_ = LoadRequestsAsync();
|
||
|
||
Trace.WriteLine("=== REQUESTSPAGE CONSTRUCTOR END ===");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine("=== REQUESTSPAGE CONSTRUCTOR ERROR ===");
|
||
Trace.WriteLine($"[RequestsPage] ❌ Тип ошибки: {ex.GetType().FullName}");
|
||
Trace.WriteLine($"[RequestsPage] ❌ Сообщение: {ex.Message}");
|
||
Trace.WriteLine($"[RequestsPage] ❌ StackTrace: {ex.StackTrace}");
|
||
|
||
// Показываем ошибку напрямую
|
||
Task.Run(async () =>
|
||
{
|
||
await Task.Delay(100);
|
||
if (Application.Current?.Windows.Count > 0)
|
||
{
|
||
Page? mainPage = Application.Current.Windows[0].Page;
|
||
if (mainPage != null)
|
||
{
|
||
await mainPage.DisplayAlert("Ошибка RequestsPage",
|
||
$"Ошибка инициализации:\n{ex.Message}\n\nStackTrace:\n{ex.StackTrace}", "OK");
|
||
}
|
||
}
|
||
});
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private async Task LoadRequestsAsync()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("[RequestsPage] >>> LoadRequestsAsync START");
|
||
|
||
LoadingIndicator.IsVisible = true;
|
||
LoadingIndicator.IsRunning = true;
|
||
|
||
Trace.WriteLine("[RequestsPage] >>> Вызов GetAllRequestsAsync");
|
||
_allRequests = await ServiceProvider.ApiService.GetAllRequestsAsync();
|
||
|
||
Trace.WriteLine($"[RequestsPage] >>> Получено заявлений: {_allRequests.Count}");
|
||
|
||
ApplyFilters();
|
||
|
||
Trace.WriteLine($"[RequestsPage] ✅ Заявления загружены успешно");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"[RequestsPage] ❌ Ошибка загрузки: {ex.GetType().Name}");
|
||
Trace.WriteLine($"[RequestsPage] Message: {ex.Message}");
|
||
Trace.WriteLine($"[RequestsPage] StackTrace: {ex.StackTrace}");
|
||
|
||
await DisplayAlert("Ошибка", $"Не удалось загрузить список заявлений:\n{ex.Message}", "OK");
|
||
}
|
||
finally
|
||
{
|
||
LoadingIndicator.IsVisible = false;
|
||
LoadingIndicator.IsRunning = false;
|
||
RefreshView.IsRefreshing = false;
|
||
}
|
||
}
|
||
|
||
private void ApplyFilters()
|
||
{
|
||
IEnumerable<Request> filtered = _allRequests;
|
||
|
||
// Фильтр по статусу
|
||
filtered = _currentFilter switch
|
||
{
|
||
"pending" => filtered.Where(r =>
|
||
r.Status.Equals("pending", StringComparison.OrdinalIgnoreCase) ||
|
||
r.Status.Equals("waiting", StringComparison.OrdinalIgnoreCase)),
|
||
"approved" => filtered.Where(r =>
|
||
r.Status.Equals("approved", StringComparison.OrdinalIgnoreCase) ||
|
||
r.Status.Equals("accepted", StringComparison.OrdinalIgnoreCase)),
|
||
"rejected" => filtered.Where(r =>
|
||
r.Status.Equals("rejected", StringComparison.OrdinalIgnoreCase) ||
|
||
r.Status.Equals("declined", StringComparison.OrdinalIgnoreCase) ||
|
||
r.Status.Equals("cancelled", StringComparison.OrdinalIgnoreCase)),
|
||
_ => filtered
|
||
};
|
||
|
||
// Фильтр по поиску
|
||
if (!string.IsNullOrWhiteSpace(_searchText))
|
||
{
|
||
string search = _searchText.ToLower();
|
||
filtered = filtered.Where(r =>
|
||
r.DisplayType.ToLower().Contains(search) ||
|
||
r.DisplayStatus.ToLower().Contains(search) ||
|
||
r.DisplayDescription.ToLower().Contains(search) ||
|
||
r.EmployeeName.ToLower().Contains(search));
|
||
}
|
||
|
||
// Сортировка по дате (новые сверху)
|
||
filtered = filtered.OrderByDescending(r => r.CreatedAt);
|
||
|
||
_requests.Clear();
|
||
foreach (var request in filtered)
|
||
{
|
||
_requests.Add(request);
|
||
}
|
||
|
||
Trace.WriteLine($"[RequestsPage] >>> Отображено заявлений: {_requests.Count}");
|
||
}
|
||
|
||
private async void OnRefreshing(object sender, EventArgs e)
|
||
{
|
||
await LoadRequestsAsync();
|
||
}
|
||
|
||
private void OnSearchTextChanged(object sender, TextChangedEventArgs e)
|
||
{
|
||
_searchText = e.NewTextValue ?? string.Empty;
|
||
ApplyFilters();
|
||
}
|
||
|
||
private async void OnRequestSelected(object sender, SelectionChangedEventArgs e)
|
||
{
|
||
if (e.CurrentSelection.FirstOrDefault() is Request selectedRequest)
|
||
{
|
||
// Сбрасываем выбор
|
||
RequestsCollectionView.SelectedItem = null;
|
||
|
||
// Показываем детали заявления
|
||
await ShowRequestDetails(selectedRequest);
|
||
}
|
||
}
|
||
|
||
private async Task ShowRequestDetails(Request request)
|
||
{
|
||
string details = $"Тип: {request.DisplayType}\n" +
|
||
$"Статус: {request.DisplayStatus}\n" +
|
||
$"Дата создания: {request.DisplayCreatedAt}\n";
|
||
|
||
if (!string.IsNullOrEmpty(request.DisplayPeriod))
|
||
details += $"Период: {request.DisplayPeriod}\n";
|
||
|
||
details += $"\nОт кого: {request.EmployeeName}\n";
|
||
|
||
if (!string.IsNullOrEmpty(request.Comment))
|
||
details += $"\nОписание:\n{request.Comment}\n";
|
||
|
||
// Получатели
|
||
if (request.Recipients != null && request.Recipients.Count > 0)
|
||
{
|
||
details += $"\n📬 Получатели ({request.Recipients.Count}):\n";
|
||
foreach (var recipient in request.Recipients)
|
||
{
|
||
details += $" • {recipient.FullName}\n";
|
||
}
|
||
}
|
||
else if (request.RecipientCount > 0)
|
||
{
|
||
details += $"\n📬 Получателей: {request.RecipientCount}\n";
|
||
}
|
||
|
||
// В копии
|
||
if (request.CcUsers != null && request.CcUsers.Count > 0)
|
||
{
|
||
details += $"\n📋 В копии ({request.CcUsers.Count}):\n";
|
||
foreach (var ccUser in request.CcUsers)
|
||
{
|
||
details += $" • {ccUser.FullName}\n";
|
||
}
|
||
}
|
||
else if (request.CcCount > 0)
|
||
{
|
||
details += $"\n📋 В копии: {request.CcCount}\n";
|
||
}
|
||
|
||
// Решение
|
||
if (request.Approver != null)
|
||
details += $"\n✍️ Решение принял: {request.ApproverName}";
|
||
|
||
if (request.DecidedAt.HasValue)
|
||
details += $"\n📅 Дата решения: {request.DecidedAt.Value:dd.MM.yyyy HH:mm}";
|
||
|
||
await DisplayAlert($"{request.TypeIcon} {request.DisplayType}", details, "Закрыть");
|
||
}
|
||
|
||
// ================================
|
||
// Обработчики фильтров
|
||
// ================================
|
||
|
||
private void OnFilterAllTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("all");
|
||
}
|
||
|
||
private void OnFilterPendingTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("pending");
|
||
}
|
||
|
||
private void OnFilterApprovedTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("approved");
|
||
}
|
||
|
||
private void OnFilterRejectedTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("rejected");
|
||
}
|
||
|
||
private void SetActiveFilter(string filter)
|
||
{
|
||
_currentFilter = filter;
|
||
|
||
// Обновляем визуальное состояние кнопок
|
||
UpdateFilterButtonStyles();
|
||
|
||
// Применяем фильтры
|
||
ApplyFilters();
|
||
}
|
||
|
||
private void UpdateFilterButtonStyles()
|
||
{
|
||
// Сбрасываем все кнопки
|
||
FilterAll.BackgroundColor = Colors.White;
|
||
FilterAll.Stroke = Color.FromArgb("#D1D5DB");
|
||
if (FilterAll.Content is Label labelAll)
|
||
labelAll.TextColor = Color.FromArgb("#374151");
|
||
|
||
FilterPending.BackgroundColor = Colors.White;
|
||
FilterPending.Stroke = Color.FromArgb("#D1D5DB");
|
||
if (FilterPending.Content is Label labelPending)
|
||
labelPending.TextColor = Color.FromArgb("#374151");
|
||
|
||
FilterApproved.BackgroundColor = Colors.White;
|
||
FilterApproved.Stroke = Color.FromArgb("#D1D5DB");
|
||
if (FilterApproved.Content is Label labelApproved)
|
||
labelApproved.TextColor = Color.FromArgb("#374151");
|
||
|
||
FilterRejected.BackgroundColor = Colors.White;
|
||
FilterRejected.Stroke = Color.FromArgb("#D1D5DB");
|
||
if (FilterRejected.Content is Label labelRejected)
|
||
labelRejected.TextColor = Color.FromArgb("#374151");
|
||
|
||
// Активируем выбранную кнопку
|
||
Border activeButton = _currentFilter switch
|
||
{
|
||
"pending" => FilterPending,
|
||
"approved" => FilterApproved,
|
||
"rejected" => FilterRejected,
|
||
_ => FilterAll
|
||
};
|
||
|
||
activeButton.BackgroundColor = (Color)Application.Current!.Resources["Primary"];
|
||
activeButton.Stroke = Colors.Transparent;
|
||
if (activeButton.Content is Label activeLabel)
|
||
activeLabel.TextColor = Colors.White;
|
||
}
|
||
}
|
||
|