139 lines
5.7 KiB
Swift
139 lines
5.7 KiB
Swift
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
|
||
}
|
||
|
||
}
|