import SwiftUI struct MainContentRecommendationView: View { let onTapContent: (Int) -> Void let onTapBanner: (AudioBannerResponse) -> Void let onTapSeries: (Int) -> Void let onTapLatestAudioAll: () -> Void let onTapNewAndHotAll: () -> Void let onTapVoiceOnOnlyAll: () -> Void let onTapFreeAudioAll: () -> Void let onTapPointAudioAll: () -> Void @StateObject private var viewModel = MainContentRecommendationViewModel() var body: some View { ZStack { Color.black .ignoresSafeArea() if viewModel.isLoading && viewModel.recommendations == nil { ProgressView() .progressViewStyle(CircularProgressViewStyle(tint: .white)) } else if viewModel.shouldShowEmptyState { MainContentAudioEmptyStateView(message: viewModel.emptyStateMessage) } else { ScrollView(showsIndicators: false) { VStack(alignment: .leading, spacing: SodaSpacing.s24) { if let recommendations = viewModel.recommendations { MainContentAudioBannerSection( items: recommendations.banners, onTapBanner: onTapBanner ) MainContentAudioHorizontalCardSection( title: I18n.MainContentRecommendation.latestAudioSectionTitle, items: recommendations.latestAudios, action: onTapLatestAudioAll, onTapContent: onTapContent ) MainContentAudioListCarouselSection( title: I18n.MainContentRecommendation.newAndHotSectionTitle, items: recommendations.newAndHotAudios, action: onTapNewAndHotAll, onTapContent: onTapContent ) MainContentVoiceOnOnlySection( title: I18n.MainContentRecommendation.voiceOnOnlySectionTitle, items: recommendations.originalSeries, action: onTapVoiceOnOnlyAll, onTapSeries: onTapSeries ) MainContentAudioHorizontalCardSection( title: I18n.MainContentRecommendation.freeAudioSectionTitle, items: recommendations.freeAudios, action: onTapFreeAudioAll, onTapContent: onTapContent ) MainContentAudioHorizontalCardSection( title: I18n.MainContentRecommendation.pointAudioSectionTitle, items: recommendations.pointAudios, action: onTapPointAudioAll, onTapContent: onTapContent ) MainContentMostCommentedAudioSection( title: I18n.MainContentRecommendation.mostCommentedAudioSectionTitle, items: recommendations.mostCommentedAudios, onTapContent: onTapContent ) MainContentRecommendedAudioGridSection( title: I18n.MainContentRecommendation.recommendedAudioSectionTitle, items: recommendations.recommendedAudios, onTapContent: onTapContent ) } } .padding(.vertical, SodaSpacing.s20) } } } .onAppear { if !viewModel.hasLoaded { viewModel.fetchRecommendations() } } .sodaToast( isPresented: $viewModel.isShowPopup, message: viewModel.errorMessage, autohideIn: 2 ) } }