You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
6.4 KiB

import React, { useState, useEffect } from 'react';
import {
View,
Text,
FlatList,
TouchableOpacity,
StyleSheet,
Image,
Dimensions,
ListRenderItem,
Platform,
StatusBar,
SafeAreaView,
ActivityIndicator
} from 'react-native';
import fontSize from '../utils/fontsizeUtils';
import widthUtils from '../utils/widthUtils';
import { categoriesApi, Category } from '../services/api/categories';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { RootStackParamList } from '../navigation/types';
const { width: SCREEN_WIDTH } = Dimensions.get('window');
const MENU_WIDTH = widthUtils(120, 120).width;
const AVAILABLE_WIDTH = SCREEN_WIDTH - MENU_WIDTH - 20; // 20 for padding
const NUM_COLUMNS = 4;
const ITEM_MARGIN = '2.66%';
const ITEM_WIDTH = (AVAILABLE_WIDTH / NUM_COLUMNS) - (AVAILABLE_WIDTH * 0.0266);
export const CategoryScreen = () => {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList>>();
const [mainCategories, setMainCategories] = useState<Category[]>([]);
const [subCategories, setSubCategories] = useState<Category[]>([]);
const [activeMainCategory, setActiveMainCategory] = useState<number | null>(null);
const [loading, setLoading] = useState(true);
const [subLoading, setSubLoading] = useState(false);
useEffect(() => {
fetchMainCategories();
}, []);
useEffect(() => {
if (activeMainCategory) {
fetchSubCategories(activeMainCategory);
}
}, [activeMainCategory]);
const fetchMainCategories = async () => {
try {
const response = await categoriesApi.getCategories();
setMainCategories(response);
if (response.length > 0) {
setActiveMainCategory(response[0].category_id);
}
} catch (error) {
console.error('Error fetching main categories:', error);
} finally {
setLoading(false);
}
};
const fetchSubCategories = async (parentId: number) => {
setSubLoading(true);
try {
const response = await categoriesApi.getCategory(parentId);
if (Array.isArray(response)) {
setSubCategories(response);
}
} catch (error) {
console.error('Error fetching sub categories:', error);
} finally {
setSubLoading(false);
}
};
const renderMainCategoryItem: ListRenderItem<Category> = ({ item }) => (
<TouchableOpacity
style={[
styles.menuItem,
item.category_id === activeMainCategory && styles.menuItemActive,
]}
onPress={() => setActiveMainCategory(item.category_id)}
>
<Text
style={[
styles.menuText,
item.category_id === activeMainCategory && styles.menuTextActive,
]}
numberOfLines={1}
ellipsizeMode="tail"
>
{item.name_cn}
</Text>
</TouchableOpacity>
);
const renderSubCategoryItem: ListRenderItem<Category> = ({ item }) => (
<TouchableOpacity
style={styles.subCategoryItem}
onPress={() => {
navigation.navigate('SearchResult', { category_id: item.category_id });
}}
>
<Image
source={item.image ? { uri: item.image } : require('../../assets/img/1034058.png')}
style={styles.subCategoryImage}
resizeMode="cover"
/>
<View style={styles.subCategoryInfo}>
<Text
style={styles.subCategoryName}
numberOfLines={2}
ellipsizeMode="tail"
>
{item.name_cn}
</Text>
</View>
</TouchableOpacity>
);
if (loading) {
return (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#e60012" />
</View>
);
}
return (
<SafeAreaView style={styles.safeArea}>
<StatusBar barStyle="dark-content" backgroundColor="#fff" />
<View style={styles.safeAreaContent}>
<View style={styles.container}>
<View style={styles.leftMenu}>
<FlatList
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
data={mainCategories}
renderItem={renderMainCategoryItem}
keyExtractor={(item) => item.category_id.toString()}
/>
</View>
<View style={styles.rightContent}>
{subLoading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#e60012" />
</View>
) : (
<FlatList
data={subCategories}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
renderItem={renderSubCategoryItem}
keyExtractor={(item) => item.category_id.toString()}
numColumns={NUM_COLUMNS}
contentContainerStyle={styles.productGrid}
columnWrapperStyle={styles.columnWrapper}
/>
)}
</View>
</View>
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#fff',
},
safeAreaContent: {
flex: 1,
paddingTop: Platform.OS === 'android' ? 0 : 0,
},
container: {
flex: 1,
flexDirection: 'row',
},
leftMenu: {
width: MENU_WIDTH,
backgroundColor: '#fff',
borderRightWidth: 1,
borderColor: '#eee',
},
menuItem: {
paddingVertical: 16,
alignItems: 'center',
borderBottomWidth: 1,
borderColor: '#f0f0f0',
},
menuItemActive: {
backgroundColor: '#f5f5f5',
},
menuText: {
fontSize: fontSize(14),
color: '#333',
},
menuTextActive: {
color: '#e60012',
fontWeight: 'bold',
},
rightContent: {
flex: 1,
backgroundColor: '#ffffff',
paddingHorizontal: 10,
paddingTop: 12,
},
productGrid: {
paddingBottom: 20,
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
columnWrapper: {
justifyContent: 'flex-start',
marginBottom: 15,
},
subCategoryItem: {
width: ITEM_WIDTH,
overflow: 'hidden',
marginRight: ITEM_MARGIN,
},
subCategoryImage: {
width: '100%',
height: ITEM_WIDTH,
},
subCategoryInfo: {
padding: 8,
height: 26,
justifyContent: 'center',
alignItems: 'center',
},
subCategoryName: {
fontSize: fontSize(12),
color: '#333',
textAlign: 'center',
},
});