|
|
@@ -0,0 +1,167 @@
|
|
|
+import SwiftUI
|
|
|
+
|
|
|
+struct SidebarView: View {
|
|
|
+ @ObservedObject var viewModel: HomeViewModel
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ VStack(alignment: .leading, spacing: 0) {
|
|
|
+ brandHeader
|
|
|
+ .padding(.bottom, 28)
|
|
|
+
|
|
|
+ newChatButton
|
|
|
+ .padding(.bottom, 20)
|
|
|
+
|
|
|
+ VStack(alignment: .leading, spacing: 4) {
|
|
|
+ ForEach(viewModel.navigationItems) { item in
|
|
|
+ SidebarNavRow(item: item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ VStack(alignment: .leading, spacing: 0) {
|
|
|
+ Text("Recents")
|
|
|
+ .font(.system(size: 15, weight: .bold))
|
|
|
+ .foregroundStyle(AppTheme.textPrimary)
|
|
|
+ .padding(.top, 28)
|
|
|
+ .padding(.bottom, 16)
|
|
|
+
|
|
|
+ recentsEmptyState
|
|
|
+ }
|
|
|
+
|
|
|
+ Spacer(minLength: 12)
|
|
|
+
|
|
|
+ upgradeButton
|
|
|
+ }
|
|
|
+ .padding(.horizontal, 20)
|
|
|
+ .padding(.top, 24)
|
|
|
+ .padding(.bottom, 20)
|
|
|
+ .frame(width: AppTheme.sidebarWidth)
|
|
|
+ .frame(maxHeight: .infinity)
|
|
|
+ .background(AppTheme.sidebarBackground)
|
|
|
+ }
|
|
|
+
|
|
|
+ private var brandHeader: some View {
|
|
|
+ HStack(spacing: 10) {
|
|
|
+ RoundedRectangle(cornerRadius: 10, style: .continuous)
|
|
|
+ .fill(AppTheme.accent)
|
|
|
+ .frame(width: 36, height: 36)
|
|
|
+ .overlay {
|
|
|
+ Image(systemName: "sparkle")
|
|
|
+ .font(.system(size: 16, weight: .bold))
|
|
|
+ .foregroundStyle(.white)
|
|
|
+ }
|
|
|
+
|
|
|
+ Text("AI ChatBot")
|
|
|
+ .font(.system(size: 17, weight: .bold))
|
|
|
+ .foregroundStyle(AppTheme.textPrimary)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private var newChatButton: some View {
|
|
|
+ Button(action: {}) {
|
|
|
+ HStack(spacing: 10) {
|
|
|
+ Image(systemName: "plus")
|
|
|
+ .font(.system(size: 13, weight: .bold))
|
|
|
+ Text("New Chat")
|
|
|
+ .font(.system(size: 14, weight: .semibold))
|
|
|
+ }
|
|
|
+ .foregroundStyle(AppTheme.accentDark)
|
|
|
+ .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
+ .padding(.horizontal, 14)
|
|
|
+ .padding(.vertical, 11)
|
|
|
+ .background(
|
|
|
+ RoundedRectangle(cornerRadius: AppTheme.cornerRadiusMedium, style: .continuous)
|
|
|
+ .fill(AppTheme.newChatBackground)
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .buttonStyle(.plain)
|
|
|
+ .accessibilityLabel("New Chat")
|
|
|
+ }
|
|
|
+
|
|
|
+ private var recentsEmptyState: some View {
|
|
|
+ VStack(alignment: .leading, spacing: 10) {
|
|
|
+ ZStack(alignment: .topTrailing) {
|
|
|
+ Image(systemName: "bubble.left.and.bubble.right")
|
|
|
+ .font(.system(size: 34))
|
|
|
+ .foregroundStyle(AppTheme.accent.opacity(0.35))
|
|
|
+ .frame(maxWidth: .infinity, alignment: .center)
|
|
|
+ .padding(.top, 8)
|
|
|
+
|
|
|
+ Circle()
|
|
|
+ .fill(AppTheme.accent)
|
|
|
+ .frame(width: 18, height: 18)
|
|
|
+ .overlay {
|
|
|
+ Image(systemName: "xmark")
|
|
|
+ .font(.system(size: 8, weight: .bold))
|
|
|
+ .foregroundStyle(.white)
|
|
|
+ }
|
|
|
+ .offset(x: 8, y: 0)
|
|
|
+ }
|
|
|
+ .frame(maxWidth: .infinity)
|
|
|
+ .padding(.bottom, 4)
|
|
|
+
|
|
|
+ Text("No recents Chats")
|
|
|
+ .font(.system(size: 15, weight: .bold))
|
|
|
+ .foregroundStyle(AppTheme.textPrimary)
|
|
|
+
|
|
|
+ Text("Your conversations will\nappear here.")
|
|
|
+ .font(.system(size: 12))
|
|
|
+ .foregroundStyle(AppTheme.textSecondary)
|
|
|
+ .lineSpacing(2)
|
|
|
+ }
|
|
|
+ .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
+ }
|
|
|
+
|
|
|
+ private var upgradeButton: some View {
|
|
|
+ Button(action: {}) {
|
|
|
+ HStack(spacing: 8) {
|
|
|
+ Image(systemName: "sparkles")
|
|
|
+ .font(.system(size: 13, weight: .semibold))
|
|
|
+ .foregroundStyle(AppTheme.accent)
|
|
|
+
|
|
|
+ Text("Upgrade to pro")
|
|
|
+ .font(.system(size: 13, weight: .semibold))
|
|
|
+ .foregroundStyle(AppTheme.textPrimary)
|
|
|
+
|
|
|
+ Spacer()
|
|
|
+
|
|
|
+ Image(systemName: "chevron.right")
|
|
|
+ .font(.system(size: 10, weight: .bold))
|
|
|
+ .foregroundStyle(AppTheme.textSecondary)
|
|
|
+ }
|
|
|
+ .padding(.horizontal, 14)
|
|
|
+ .padding(.vertical, 12)
|
|
|
+ .background(
|
|
|
+ RoundedRectangle(cornerRadius: AppTheme.cornerRadiusMedium, style: .continuous)
|
|
|
+ .stroke(AppTheme.accent.opacity(0.45), lineWidth: 1)
|
|
|
+ .background(
|
|
|
+ RoundedRectangle(cornerRadius: AppTheme.cornerRadiusMedium, style: .continuous)
|
|
|
+ .fill(Color.white)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+ .buttonStyle(.plain)
|
|
|
+ .accessibilityLabel("Upgrade to pro")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private struct SidebarNavRow: View {
|
|
|
+ let item: SidebarItem
|
|
|
+
|
|
|
+ var body: some View {
|
|
|
+ Button(action: {}) {
|
|
|
+ HStack(spacing: 12) {
|
|
|
+ Image(systemName: item.symbol)
|
|
|
+ .font(.system(size: 14, weight: .regular))
|
|
|
+ .frame(width: 18)
|
|
|
+ Text(item.title)
|
|
|
+ .font(.system(size: 14, weight: .medium))
|
|
|
+ }
|
|
|
+ .foregroundStyle(AppTheme.textPrimary)
|
|
|
+ .frame(maxWidth: .infinity, alignment: .leading)
|
|
|
+ .padding(.horizontal, 10)
|
|
|
+ .padding(.vertical, 9)
|
|
|
+ }
|
|
|
+ .buttonStyle(.plain)
|
|
|
+ .accessibilityLabel(item.title)
|
|
|
+ }
|
|
|
+}
|