import SwiftUI struct ProfileContentGrid: View { let isContentLoaded: Bool let selectedTabIndex: Int let searchQuery: String let selectedCategory: String @State private var allPosts: [Post] = [] @State private var selectedPostID: PostIDWrapper? = nil @State private var isLoading = true var body: some View { VStack(alignment: .leading, spacing: 0) { if isLoading { // LazyVGrid(columns: Array(repeating: .init(.flexible()), count: 3), spacing: 2) { // ForEach(0..<100, id: \.self) { _ in // RoundedRectangle(cornerRadius: 4) // .fill(Color.gray.opacity(0.15)) // .aspectRatio(1, contentMode: .fit) // } // } // .padding(.horizontal) // .redacted(reason: .placeholder) // ⬅️ делает «размытый» стиль VStack { ProgressView("Загрузка...") .padding() Spacer() } .frame(maxWidth: .infinity, minHeight: 300) // 👈 гарантированная высота } else if filteredPosts.isEmpty { VStack { Text("Нет постов") .foregroundColor(.secondary) .padding() } .frame(maxWidth: .infinity, minHeight: 300) } else { LazyVGrid(columns: Array(repeating: .init(.flexible()), count: 3), spacing: 2) { ForEach(filteredPosts) { post in Button { selectedPostID = PostIDWrapper(id: post.id) } label: { Rectangle() .fill(Color.gray.opacity(0.2)) .aspectRatio(1, contentMode: .fit) .overlay( ZStack { VStack { HStack { Text("3 года назад") // Можно заменить на `post.createdAt` .font(.caption2) .foregroundColor(.white) .padding(4) .background(Color.black.opacity(0.6)) .cornerRadius(4) Spacer() } Spacer() } .padding(4) VStack { Spacer() HStack { HStack(spacing: 4) { Image(systemName: "play.fill") .font(.caption2) Text("\(post.views)") .font(.caption2) } .foregroundColor(.white) .padding(4) .background(Color.black.opacity(0.6)) .cornerRadius(4) Spacer() } .padding(4) } } ) } .buttonStyle(PlainButtonStyle()) } } .padding(.horizontal) } } .frame(maxWidth: .infinity, alignment: .topLeading) .onAppear { // guard isContentLoaded else { return } if allPosts.isEmpty { isLoading = true PostService.shared.fetchAllPosts { result in self.allPosts = result self.isLoading = false } } } .fullScreenCover(item: $selectedPostID) { wrapper in PostDetailView(postID: wrapper.id) } } private var filteredPosts: [Post] { var result: [Post] switch selectedTabIndex { case 1: result = allPosts.filter { $0.accessLevel == .archive } case 2: result = allPosts.filter { $0.isSavedByCurrentUser } case 3: result = allPosts.filter { $0.isLikedByCurrentUser } default: result = allPosts } // 🔍 Поиск по названию или описанию if !searchQuery.isEmpty { result = result.filter { ($0.title?.localizedCaseInsensitiveContains(searchQuery) ?? false) || ($0.description?.localizedCaseInsensitiveContains(searchQuery) ?? false) } } // 🏷️ Фильтрация по категории (если не "#все") if selectedCategory != "#все" { result = result.filter { $0.hashtags?.contains(where: { $0 == selectedCategory }) ?? false } } return result } }