273 lines
9.9 KiB
C#
273 lines
9.9 KiB
C#
using System.Collections.ObjectModel;
|
||
using System.Diagnostics;
|
||
using CORP_MAUI.Models;
|
||
|
||
namespace CORP_MAUI.Pages;
|
||
|
||
public partial class DocumentsPage : ContentPage
|
||
{
|
||
private readonly ObservableCollection<Document> _documents;
|
||
private List<Document> _allDocuments = new();
|
||
private string _currentFilter = "all";
|
||
private string _searchText = string.Empty;
|
||
|
||
public DocumentsPage()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("=== DOCUMENTS PAGE CONSTRUCTOR START ===");
|
||
Trace.WriteLine("[DocumentsPage] >>> Вызов InitializeComponent");
|
||
|
||
InitializeComponent();
|
||
|
||
Trace.WriteLine("[DocumentsPage] >>> InitializeComponent завершен");
|
||
|
||
_documents = new ObservableCollection<Document>();
|
||
|
||
DocumentsCollectionView.ItemsSource = _documents;
|
||
|
||
Trace.WriteLine("[DocumentsPage] >>> Запуск LoadDocumentsAsync");
|
||
// Загружаем документы
|
||
_ = LoadDocumentsAsync();
|
||
|
||
Trace.WriteLine("=== DOCUMENTS PAGE CONSTRUCTOR END ===");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine("=== DOCUMENTS PAGE CONSTRUCTOR ERROR ===");
|
||
Trace.WriteLine($"[DocumentsPage] ❌ Тип ошибки: {ex.GetType().FullName}");
|
||
Trace.WriteLine($"[DocumentsPage] ❌ Сообщение: {ex.Message}");
|
||
Trace.WriteLine($"[DocumentsPage] ❌ 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("Ошибка DocumentsPage",
|
||
$"Ошибка инициализации:\n{ex.Message}\n\nStackTrace:\n{ex.StackTrace}", "OK");
|
||
}
|
||
}
|
||
});
|
||
throw;
|
||
}
|
||
}
|
||
|
||
private async Task LoadDocumentsAsync()
|
||
{
|
||
try
|
||
{
|
||
Trace.WriteLine("[DocumentsPage] >>> LoadDocumentsAsync START");
|
||
|
||
LoadingIndicator.IsVisible = true;
|
||
LoadingIndicator.IsRunning = true;
|
||
|
||
Trace.WriteLine("[DocumentsPage] >>> Вызов GetAllDocumentsAsync");
|
||
_allDocuments = await ServiceProvider.ApiService.GetAllDocumentsAsync();
|
||
|
||
Trace.WriteLine($"[DocumentsPage] >>> Получено документов: {_allDocuments.Count}");
|
||
|
||
ApplyFilters();
|
||
|
||
Trace.WriteLine($"[DocumentsPage] ✅ Документы загружены успешно");
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"[DocumentsPage] ❌ Ошибка загрузки: {ex.GetType().Name}");
|
||
Trace.WriteLine($"[DocumentsPage] Message: {ex.Message}");
|
||
Trace.WriteLine($"[DocumentsPage] StackTrace: {ex.StackTrace}");
|
||
|
||
await DisplayAlert("Ошибка", $"Не удалось загрузить список документов:\n{ex.Message}", "OK");
|
||
}
|
||
finally
|
||
{
|
||
LoadingIndicator.IsVisible = false;
|
||
LoadingIndicator.IsRunning = false;
|
||
RefreshView.IsRefreshing = false;
|
||
}
|
||
}
|
||
|
||
private void ApplyFilters()
|
||
{
|
||
IEnumerable<Document> filtered = _allDocuments;
|
||
|
||
// Фильтр по статусу ознакомления
|
||
filtered = _currentFilter switch
|
||
{
|
||
"acknowledged" => filtered.Where(d => d.IsAcknowledged),
|
||
"not_acknowledged" => filtered.Where(d => !d.IsAcknowledged),
|
||
_ => filtered
|
||
};
|
||
|
||
// Фильтр по поиску
|
||
if (!string.IsNullOrWhiteSpace(_searchText))
|
||
{
|
||
string search = _searchText.ToLower();
|
||
filtered = filtered.Where(d =>
|
||
d.Title.ToLower().Contains(search) ||
|
||
d.Description.ToLower().Contains(search) ||
|
||
d.UploaderName.ToLower().Contains(search));
|
||
}
|
||
|
||
// Сортировка по дате загрузки (новые сверху)
|
||
filtered = filtered.OrderByDescending(d => d.UploadedAt);
|
||
|
||
_documents.Clear();
|
||
foreach (var document in filtered)
|
||
{
|
||
_documents.Add(document);
|
||
}
|
||
|
||
Trace.WriteLine($"[DocumentsPage] >>> Отображено документов: {_documents.Count}");
|
||
}
|
||
|
||
private async void OnRefreshing(object sender, EventArgs e)
|
||
{
|
||
await LoadDocumentsAsync();
|
||
}
|
||
|
||
private void OnSearchTextChanged(object sender, TextChangedEventArgs e)
|
||
{
|
||
_searchText = e.NewTextValue ?? string.Empty;
|
||
ApplyFilters();
|
||
}
|
||
|
||
private async void OnDocumentSelected(object sender, SelectionChangedEventArgs e)
|
||
{
|
||
if (e.CurrentSelection.FirstOrDefault() is Document selectedDocument)
|
||
{
|
||
// Сбрасываем выделение
|
||
DocumentsCollectionView.SelectedItem = null;
|
||
|
||
Trace.WriteLine($"[DocumentsPage] >>> Выбран документ: {selectedDocument.Title}");
|
||
|
||
// Показываем диалог с выбором действия
|
||
string action = await DisplayActionSheet(
|
||
selectedDocument.Title,
|
||
"Отмена",
|
||
null,
|
||
"📥 Открыть документ",
|
||
"ℹ️ Информация о документе");
|
||
|
||
if (action == "📥 Открыть документ")
|
||
{
|
||
await OpenDocumentAsync(selectedDocument);
|
||
}
|
||
else if (action == "ℹ️ Информация о документе")
|
||
{
|
||
await ShowDocumentInfoAsync(selectedDocument);
|
||
}
|
||
}
|
||
}
|
||
|
||
private async Task OpenDocumentAsync(Document document)
|
||
{
|
||
try
|
||
{
|
||
if (string.IsNullOrEmpty(document.FileUrl))
|
||
{
|
||
await DisplayAlert("Ошибка", "URL документа не найден", "OK");
|
||
return;
|
||
}
|
||
|
||
Trace.WriteLine($"[DocumentsPage] >>> Открытие документа: {document.FileUrl}");
|
||
|
||
// Открываем документ в браузере
|
||
await Launcher.OpenAsync(new Uri(document.FileUrl));
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Trace.WriteLine($"[DocumentsPage] ❌ Ошибка открытия документа: {ex.Message}");
|
||
await DisplayAlert("Ошибка", $"Не удалось открыть документ:\n{ex.Message}", "OK");
|
||
}
|
||
}
|
||
|
||
private async Task ShowDocumentInfoAsync(Document document)
|
||
{
|
||
string info = $"📄 {document.Title}\n\n";
|
||
|
||
if (!string.IsNullOrEmpty(document.Description))
|
||
{
|
||
info += $"📝 Описание:\n{document.Description}\n\n";
|
||
}
|
||
|
||
info += $"👤 Загрузил: {document.UploaderName}\n";
|
||
info += $"📅 Дата загрузки: {document.DisplayUploadedAt}\n";
|
||
info += $"📁 Тип файла: {document.FileExtension.ToUpper()}\n";
|
||
info += $"📨 Для всех: {(document.SentToAll ? "Да" : "Нет")}\n";
|
||
info += $"{document.AcknowledgedIcon} Статус: {document.AcknowledgedText}";
|
||
|
||
await DisplayAlert("Информация о документе", info, "OK");
|
||
}
|
||
|
||
private async void OnBackClicked(object sender, EventArgs e)
|
||
{
|
||
await Shell.Current.GoToAsync("..");
|
||
}
|
||
|
||
#region Фильтры
|
||
|
||
private void OnFilterAllTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("all");
|
||
ApplyFilters();
|
||
}
|
||
|
||
private void OnFilterAcknowledgedTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("acknowledged");
|
||
ApplyFilters();
|
||
}
|
||
|
||
private void OnFilterNotAcknowledgedTapped(object sender, TappedEventArgs e)
|
||
{
|
||
SetActiveFilter("not_acknowledged");
|
||
ApplyFilters();
|
||
}
|
||
|
||
private void SetActiveFilter(string filter)
|
||
{
|
||
_currentFilter = filter;
|
||
|
||
// Получаем стили из Application.Current.Resources
|
||
Style? chipButton = Application.Current?.Resources["ChipButton"] as Style;
|
||
Style? chipButtonActive = Application.Current?.Resources["ChipButtonActive"] as Style;
|
||
Color? grayColor = Application.Current?.Resources["Gray700"] as Color ?? Colors.Gray;
|
||
|
||
// Сбрасываем все фильтры на неактивные
|
||
if (chipButton != null)
|
||
{
|
||
FilterAll.Style = chipButton;
|
||
FilterAcknowledged.Style = chipButton;
|
||
FilterNotAcknowledged.Style = chipButton;
|
||
}
|
||
|
||
// Обновляем цвет текста у неактивных
|
||
if (FilterAll.Content is Label allLabel)
|
||
allLabel.TextColor = grayColor;
|
||
if (FilterAcknowledged.Content is Label acknowledgedLabel)
|
||
acknowledgedLabel.TextColor = grayColor;
|
||
if (FilterNotAcknowledged.Content is Label notAcknowledgedLabel)
|
||
notAcknowledgedLabel.TextColor = grayColor;
|
||
|
||
// Активируем выбранный фильтр
|
||
Border activeFilter = filter switch
|
||
{
|
||
"acknowledged" => FilterAcknowledged,
|
||
"not_acknowledged" => FilterNotAcknowledged,
|
||
_ => FilterAll
|
||
};
|
||
|
||
if (chipButtonActive != null)
|
||
activeFilter.Style = chipButtonActive;
|
||
if (activeFilter.Content is Label activeLabel)
|
||
activeLabel.TextColor = Colors.White;
|
||
}
|
||
|
||
#endregion
|
||
}
|