import { router } from 'expo-router'; import { useEffect, useMemo, useState } from 'react'; import { ScrollView, StyleSheet, View } from 'react-native'; import { CategoryTabs, CommunityGrid, FeatureCarousel, Header, PageLayout, SectionHeader, StatusBarSpacer, type CommunityItem, type FeatureItem } from '@/components/bestai'; import type { FeatureItem as FeatureItemType } from '@/components/bestai/feature-carousel'; import { useAuth } from '@/hooks/use-auth'; import { useAuthGuard } from '@/hooks/use-auth-guard'; import { getActivities, type Activity } from '@/lib/api/activities'; import { categoriesWithChildren } from '@/lib/api/categories-with-children'; import type { CategoryTemplate, CategoryWithChildren } from '@/lib/types/template'; function coalesceText(...values: Array): string { for (const value of values) { const trimmed = (value ?? '').trim(); if (trimmed.length > 0) { return trimmed; } } return ''; } function translateTemplateToCommunity(template: CategoryTemplate): CommunityItem | null { const image = coalesceText(template.coverImageUrl, template.previewUrl); const title = coalesceText(template.titleEn, template.title); if (!image || !title) { return null; } const primaryTag = template.tags?.[0]; const chip = coalesceText(primaryTag?.nameEn, primaryTag?.name, template.aspectRatio) || 'Featured'; return { id: template.id, title, image, chip, actionLabel: 'Generate', }; } function translateActivity(activity: Activity): FeatureItem | null { const image = (activity.coverUrl || '').trim(); const title = (activity.titleEn || '').trim() || (activity.title || '').trim(); if (!image || !title) { return null; } const subtitle = (activity.descEn || '').trim() || (activity.desc || '').trim(); return { id: activity.id, title, subtitle, image, }; } export default function ExploreScreen() { const { isAuthenticated } = useAuth(); const { requireAuth } = useAuthGuard(); const [activeCategory, setActiveCategory] = useState(); const [activityFeatures, setActivityFeatures] = useState([]); const [categoryCollection, setCategoryCollection] = useState([]); useEffect(() => { const hydrateFeatureCarousel = async () => { try { const activities = await getActivities({ isActive: true }); console.log({ activities }) const curatedFeatures = activities .map(translateActivity) .filter((feature): feature is FeatureItem => feature !== null); if (curatedFeatures.length > 0) { setActivityFeatures(curatedFeatures); } } catch (error) { const detail = error instanceof Error ? error.message : String(error); console.warn('FeatureCarousel activities feed unavailable:', detail); } }; hydrateFeatureCarousel(); return () => { }; }, []); useEffect(() => { let isActive = true; const hydrateCategories = async () => { try { const response = await categoriesWithChildren(); if (!isActive) { return; } const payload = response.success && Array.isArray(response.data) ? response.data : []; const curated = payload.filter((category) => category.id && (category.isActive ?? true)); setCategoryCollection(curated.length > 0 ? curated : payload); } catch (error) { if (isActive) { const detail = error instanceof Error ? error.message : String(error); console.warn('Categories feed unavailable:', detail); } } }; hydrateCategories(); return () => { isActive = false; }; }, [isAuthenticated]); useEffect(() => { if (categoryCollection.length === 0) { return; } const hasActive = categoryCollection.some((category) => category.id === activeCategory); if (!hasActive) { setActiveCategory(categoryCollection[0].id); } }, [categoryCollection, activeCategory]); const categoryOptions = useMemo(() => { if (categoryCollection.length === 0) { return []; } const options = categoryCollection .map((category) => { const label = coalesceText(category.nameEn, category.name); return label ? { id: category.id, label, } : null; }) .filter((category): category is { id: string; label: string } => category !== null); return options.length > 0 ? options : []; }, [categoryCollection]); const activeCategoryRecord = useMemo(() => { return categoryCollection.find((category) => category.id === activeCategory) ?? null; }, [categoryCollection, activeCategory]); const templateCommunityItems = useMemo(() => { if (!activeCategoryRecord) { return []; } return (activeCategoryRecord.templates ?? []) .map(translateTemplateToCommunity) .filter((item): item is CommunityItem => item !== null); }, [activeCategoryRecord]); const featureItems = useMemo(() => { return activityFeatures.map((item, index) => ({ ...item, id: `${activeCategory}-${item.id || index}`, })); }, [activityFeatures]); const communityItems = useMemo(() => { const source: CommunityItem[] = templateCommunityItems.length > 0 ? templateCommunityItems : []; return source.map((item, index) => ({ ...item, id: `${activeCategory}-${item.id || index}`, })); }, [activeCategory, templateCommunityItems]); const handleGeneratePress = (item: CommunityItem) => { requireAuth(() => { const templateId = item.id.split('-').pop() || item.id; router.push(`/templates/${templateId}`); }); }; const handleFeaturePress = (item: FeatureItemType) => { requireAuth(() => { console.log('用户已登录,使用功能:', item.title); }); }; return (
{featureItems.length > 0 && } ); } const styles = StyleSheet.create({ scroll: { flex: 1, }, contentContainer: { paddingTop: 16, paddingBottom: 48, }, bottomSpacer: { height: 32, }, });