298 lines
14 KiB
Swift
298 lines
14 KiB
Swift
import SwiftUI
|
||
|
||
struct ProfileTab: View {
|
||
@ObservedObject var viewModel: LoginViewModel
|
||
@State private var showingAccountSwitch = false
|
||
@State private var selectedTabIndex = 0
|
||
@State private var selectedSort = "По дате"
|
||
@State private var selectedCategory = "#все"
|
||
@State private var searchQuery = ""
|
||
@State private var searchQueryArchive = ""
|
||
@State private var searchQuerySaved = ""
|
||
@State private var searchQueryLiked = ""
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
GeometryReader { geometry in
|
||
VStack(spacing: 0) {
|
||
ScrollView {
|
||
VStack(spacing: 12) {
|
||
// Аватар и имя
|
||
VStack(spacing: 6) {
|
||
Image(systemName: "person.crop.circle.fill")
|
||
.resizable()
|
||
.frame(width: 72, height: 72)
|
||
.foregroundColor(.gray)
|
||
|
||
Text("@username")
|
||
.font(.headline)
|
||
}
|
||
.padding(.top, 16)
|
||
|
||
// Статистика
|
||
HStack(spacing: 32) {
|
||
statView("24", "Посты")
|
||
statView("1.2k", "Подписчики")
|
||
statView("156", "Подписки")
|
||
}
|
||
|
||
// Вкладки профиля
|
||
HStack(spacing: 32) {
|
||
menuTab(index: 0)
|
||
tabButton(index: 1, systemIcon: "lock")
|
||
tabButton(index: 2, systemIcon: "bookmark")
|
||
tabButton(index: 3, systemIcon: "heart")
|
||
}
|
||
.padding(.vertical, 12)
|
||
}
|
||
.padding(.horizontal)
|
||
.frame(width: geometry.size.width)
|
||
|
||
if selectedTabIndex == 0 {
|
||
HStack {
|
||
Menu {
|
||
// Здесь список категорий
|
||
Button("#все") { selectedCategory = "#все" }
|
||
Button("#влог") { selectedCategory = "#влог" }
|
||
Button("#игры") { selectedCategory = "#игры" }
|
||
Button("#путешествия") { selectedCategory = "#путешествия" }
|
||
} label: {
|
||
Label(selectedCategory, systemImage: "tag")
|
||
.font(.subheadline)
|
||
.padding(8)
|
||
.background(Color.gray.opacity(0.2))
|
||
.cornerRadius(8)
|
||
}
|
||
|
||
// Поиск
|
||
TextField("Поиск", text: $searchQuery)
|
||
.padding(.horizontal, 10)
|
||
.padding(.vertical, 6)
|
||
.background(Color.gray.opacity(0.15))
|
||
.cornerRadius(8)
|
||
.font(.subheadline)
|
||
|
||
Button(action: {
|
||
// Создание поста
|
||
}) {
|
||
Label("Создать", systemImage: "plus")
|
||
.font(.subheadline)
|
||
.padding(8)
|
||
.background(Color.blue.opacity(0.2))
|
||
.cornerRadius(8)
|
||
}
|
||
}
|
||
.padding(.horizontal)
|
||
} else if selectedTabIndex == 1 {
|
||
HStack {
|
||
// Поиск
|
||
TextField("Поиск", text: $searchQueryArchive)
|
||
.padding(.horizontal, 10)
|
||
.padding(.vertical, 6)
|
||
.background(Color.gray.opacity(0.15))
|
||
.cornerRadius(8)
|
||
.font(.subheadline)
|
||
}
|
||
.padding(.horizontal)
|
||
} else if selectedTabIndex == 2 {
|
||
HStack {
|
||
// Поиск
|
||
TextField("Поиск", text: $searchQuerySaved)
|
||
.padding(.horizontal, 10)
|
||
.padding(.vertical, 6)
|
||
.background(Color.gray.opacity(0.15))
|
||
.cornerRadius(8)
|
||
.font(.subheadline)
|
||
}
|
||
.padding(.horizontal)
|
||
} else if selectedTabIndex == 3 {
|
||
HStack {
|
||
// Поиск
|
||
TextField("Поиск", text: $searchQueryLiked)
|
||
.padding(.horizontal, 10)
|
||
.padding(.vertical, 6)
|
||
.background(Color.gray.opacity(0.15))
|
||
.cornerRadius(8)
|
||
.font(.subheadline)
|
||
}
|
||
.padding(.horizontal)
|
||
}
|
||
|
||
|
||
// Контентная часть
|
||
TabView(selection: $selectedTabIndex) {
|
||
ForEach(0..<4) { index in
|
||
LazyVGrid(columns: Array(repeating: .init(.flexible()), count: 3), spacing: 2) {
|
||
ForEach(0..<36) { _ in
|
||
Rectangle()
|
||
.fill(contentColor(for: index))
|
||
.aspectRatio(1, contentMode: .fit)
|
||
.overlay(
|
||
ZStack {
|
||
// Верхний левый угол — дата
|
||
VStack {
|
||
HStack {
|
||
Text("3 года назад")
|
||
.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("1.2k")
|
||
.font(.caption2)
|
||
}
|
||
.foregroundColor(.white)
|
||
.padding(4)
|
||
.background(Color.black.opacity(0.6))
|
||
.cornerRadius(4)
|
||
|
||
Spacer()
|
||
}
|
||
.padding(4)
|
||
}
|
||
}
|
||
)
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
|
||
// .frame(height: geometry.size.width * 1.2) // Динамическая высота
|
||
}
|
||
}
|
||
}
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .principal) {
|
||
Button(action: { showingAccountSwitch.toggle() }) {
|
||
HStack(spacing: 4) {
|
||
Text("custom_user_name")
|
||
.font(.headline)
|
||
.foregroundColor(.primary)
|
||
Image(systemName: "chevron.down")
|
||
.font(.subheadline)
|
||
.foregroundColor(.gray)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Левый верх — ручка (редактирование)
|
||
ToolbarItem(placement: .navigationBarLeading) {
|
||
Button(action: {
|
||
// действие редактирования профиля
|
||
}) {
|
||
Image(systemName: "paintbrush")
|
||
.imageScale(.large)
|
||
}
|
||
}
|
||
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button(action: {
|
||
// перейти к настройкам
|
||
}) {
|
||
Image(systemName: "wrench")
|
||
.imageScale(.large)
|
||
}
|
||
}
|
||
}
|
||
.sheet(isPresented: $showingAccountSwitch) {
|
||
VStack {
|
||
Text("Выбор аккаунта")
|
||
.font(.title)
|
||
.padding()
|
||
Button("Закрыть") {
|
||
showingAccountSwitch = false
|
||
}
|
||
.padding()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - Статистика
|
||
func statView(_ value: String, _ label: String) -> some View {
|
||
VStack {
|
||
Text(value)
|
||
.font(.headline)
|
||
Text(label)
|
||
.font(.caption)
|
||
}
|
||
}
|
||
|
||
// MARK: - Вкладка с меню
|
||
@ViewBuilder
|
||
func menuTab(index: Int) -> some View {
|
||
Menu {
|
||
if selectedTabIndex == index {
|
||
Button("По дате") { selectedSort = "По дате" }
|
||
Button("По популярности") { selectedSort = "По популярности" }
|
||
}
|
||
} label: {
|
||
VStack(spacing: 4) {
|
||
HStack(spacing: 4) {
|
||
Image(systemName: "rectangle.grid.3x2")
|
||
.font(.system(size: 18, weight: .medium))
|
||
.foregroundColor(.primary)
|
||
|
||
// Показываем стрелку вниз только если вкладка активна
|
||
if selectedTabIndex == index {
|
||
Image(systemName: "chevron.down")
|
||
.font(.system(size: 10))
|
||
.foregroundColor(.gray)
|
||
}
|
||
}
|
||
Rectangle()
|
||
.frame(height: 2)
|
||
.foregroundColor(selectedTabIndex == index ? .primary : .clear)
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
}
|
||
.onTapGesture {
|
||
selectedTabIndex = index
|
||
}
|
||
}
|
||
|
||
// MARK: - Остальные вкладки
|
||
@ViewBuilder
|
||
func tabButton(index: Int, systemIcon: String) -> some View {
|
||
VStack(spacing: 4) {
|
||
Image(systemName: systemIcon)
|
||
.font(.system(size: 18, weight: .medium))
|
||
.foregroundColor(selectedTabIndex == index ? .primary : .gray)
|
||
Rectangle()
|
||
.frame(height: 2)
|
||
.foregroundColor(selectedTabIndex == index ? .primary : .clear)
|
||
}
|
||
.frame(maxWidth: .infinity)
|
||
.onTapGesture {
|
||
selectedTabIndex = index
|
||
}
|
||
}
|
||
|
||
// MARK: - Цвет контента
|
||
func contentColor(for tab: Int) -> Color {
|
||
switch tab {
|
||
case 0: return Color.gray.opacity(0.3)
|
||
case 1: return Color.blue.opacity(0.3)
|
||
case 2: return Color.green.opacity(0.3)
|
||
case 3: return Color.red.opacity(0.3)
|
||
default: return Color.gray.opacity(0.3)
|
||
}
|
||
}
|
||
}
|