Skip to content

Commit

Permalink
some fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kharioki committed Sep 23, 2024
1 parent b360f20 commit 62a0ed3
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 273 deletions.
32 changes: 18 additions & 14 deletions app/(tabs)/home/speakers.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
import React from 'react';
import { FlatList, View, ActivityIndicator, StyleSheet } from 'react-native';
import palette from '@/constants/Colors';
import SpeakerCard from '@/components/SpeakerCard';
import BackgroundWrapper from '@/components/containers/BackgroundWrapper';
import Colors from '@/constants/Colors';
import SpeakerCard from '@/components/cards/SpeakerCard';
import { useFetchSpeakers } from '@/hooks/useFetchSpeakers';
import StyledText from '@/components/common/StyledText'; // Import StyledText
import { Stack } from 'expo-router';
import StyledText from '@/components/common/StyledText';
import MainContainer from '@/components/containers/MainContainer';
import { sizes } from '@/constants/Styles';
import { useRouter } from 'expo-router';

const SpeakersTab = () => {
const Speakers = () => {
const router = useRouter();
const { speakerList, loading, error } = useFetchSpeakers();

return (
<BackgroundWrapper>
<MainContainer backgroundImage={require('@/assets/images/bg.png')} ImageBackgroundProps={{ resizeMode: 'cover' }}>
<View style={styles.container}>
<StyledText size="xl" font="semiBold" style={styles.header}>
Speakers
</StyledText>
{loading ? (
<ActivityIndicator size="large" color={palette.palette.secondary} />
<ActivityIndicator size="large" color={Colors.palette.secondary} />
) : error ? (
<StyledText variant="error" style={styles.error}>
Failed to load speakers. Please try again later.
</StyledText>
) : (
<FlatList
data={speakerList}
renderItem={({ item }) => <SpeakerCard speaker={item} />}
renderItem={({ item }) => (
<SpeakerCard speaker={item} onPress={() => router.push(`/speakers/${item.id}`)} />
)}
keyExtractor={(item) => item.id}
/>
)}
</View>
</BackgroundWrapper>
</MainContainer>
);
};

Expand All @@ -40,12 +43,13 @@ const styles = StyleSheet.create({
padding: 16,
},
header: {
marginBottom: 16, // Adjusted to ensure space between the header and the list
color: Colors.palette.secondary,
marginVertical: sizes.md,
},
error: {
textAlign: 'center',
marginTop: 16, // Added margin to position error message properly
marginTop: 16,
},
});

export default SpeakersTab;
export default Speakers;
242 changes: 127 additions & 115 deletions app/(tabs)/speakers/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,167 +1,179 @@
import React, { useState, useMemo } from 'react';
import { View, ScrollView, ActivityIndicator, StyleSheet, TouchableOpacity, Linking, Image } from 'react-native';
import { Stack, useLocalSearchParams, useNavigation } from 'expo-router';
import palette from '@/constants/Colors';
import { useFetchSpeakers } from '@/hooks/useFetchSpeakers';
import SpeakerHeader from '@/components/headers/SpeakerHeader';
import BackgroundWrapper from '@/components/containers/BackgroundWrapper';
import { Image } from 'expo-image';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { AntDesign, FontAwesome6 } from '@expo/vector-icons';
import { useMemo } from 'react';
import { View, StyleSheet, ActivityIndicator, Linking, Pressable } from 'react-native';
import MainContainer from '@/components/containers/MainContainer';
import Colors from '@/constants/Colors';
import { sizes, spacing } from '@/constants/Styles';
import StyledText from '@/components/common/StyledText';
import { FontAwesome } from '@expo/vector-icons';
import { useFetchSpeakers } from '@/hooks/useFetchSpeakers';

const SpeakerPage = () => {
const { id } = useLocalSearchParams(); // Fetch dynamic ID from route
const navigation = useNavigation();
const { id } = useLocalSearchParams();

const { speakerList, loading, error } = useFetchSpeakers();
const [savedSessions, setSavedSessions] = useState<{ [key: string]: boolean }>({});

const router = useRouter();

const speaker = useMemo(() => speakerList.find((s) => s.id === id), [speakerList, id]);

if (loading) {
return <ActivityIndicator size="large" color={palette.palette.secondary} style={styles.loader} />;
return (
<MainContainer backgroundImage={require('@/assets/images/bg.png')} ImageBackgroundProps={{ resizeMode: 'cover' }}>
<ActivityIndicator size="large" color={Colors.palette.secondary} style={styles.loader} />
</MainContainer>
);
}

if (error || !speaker) {
if (error) {
return (
<StyledText variant="error" style={styles.error}>
Speaker not found
</StyledText>
<MainContainer backgroundImage={require('@/assets/images/bg.png')} ImageBackgroundProps={{ resizeMode: 'cover' }}>
<View style={styles.container}>
<StyledText style={styles.error}>Speaker not found</StyledText>
</View>
</MainContainer>
);
}

const toggleSaveSession = (sessionIndex: number) => {
setSavedSessions((prevState) => ({
...prevState,
[sessionIndex]: !prevState[sessionIndex],
}));
const openURL = (url: string) => {
Linking.openURL(url);
};

const socialMediaLinks = [
{
name: 'twitter',
url: speaker.socialMedia?.twitter || 'https://x.com/renderconke',
icon: require('@/assets/images/x.png'),
},
{
name: 'linkedin',
url: speaker.socialMedia?.linkedin || 'https://www.linkedin.com/company/renderconke/',
icon: require('@/assets/images/linkedin.png'),
},
];
const renderLinkIcon = (linkType: string) => {
switch (linkType.toLowerCase()) {
case 'twitter':
return <FontAwesome6 name="x-twitter" size={36} color={Colors.palette.secondary} />;
case 'linkedin':
return <FontAwesome6 name="linkedin" size={36} color={Colors.palette.secondary} />;
default:
return <FontAwesome6 name="link" size={36} color={Colors.palette.secondary} />;
}
};

return (
<BackgroundWrapper>
<ScrollView contentContainerStyle={styles.container}>
{/* Back Button */}
<TouchableOpacity style={styles.backButton} onPress={() => navigation.goBack()}>
<FontAwesome name="arrow-left" size={18} color={palette.palette.secondary} />
</TouchableOpacity>

<SpeakerHeader
name={speaker.fullName}
occupation={speaker.occupation}
profilePicture={speaker.profilePicture}
/>
<MainContainer backgroundImage={require('@/assets/images/bg.png')} ImageBackgroundProps={{ resizeMode: 'cover' }}>
<View style={styles.container}>
<View style={styles.header}>
<Pressable
onPress={() => router.back()}
style={({ pressed }) => [
styles.backBtn,
{ backgroundColor: pressed ? Colors.palette.cardBg : 'transparent' },
]}
>
<View>
<AntDesign name="arrowleft" size={24} color={Colors.palette.secondary} />
</View>
</Pressable>
<View style={styles.name}>
<StyledText size="xl" font="bold" style={{ color: Colors.palette.secondary }}>
{speaker?.fullName}
</StyledText>
</View>
</View>

<StyledText size="md" variant="text" style={styles.bio}>
{speaker.bio}
</StyledText>
<View style={styles.top}>
<Image source={{ uri: speaker?.profilePicture }} style={styles.image} contentFit="cover" />
<StyledText size="md" style={styles.tagline}>
{speaker?.tagLine}
</StyledText>
</View>

<View style={styles.socialMediaContainer}>
{socialMediaLinks.map((social, index) => (
<TouchableOpacity key={index} onPress={() => Linking.openURL(social.url)} style={styles.socialIconImage}>
<Image source={social.icon} />
</TouchableOpacity>
<View style={styles.row}>
{speaker?.links.map((link, index) => (
<Pressable key={index} onPress={() => openURL(link.url)} style={styles.iconBtn}>
<View>{renderLinkIcon(link.linkType)}</View>
</Pressable>
))}
</View>

{speaker.sessions.map((session, index) => (
<StyledText style={styles.bio}>{speaker?.bio}</StyledText>

{speaker?.sessions.map((session, index) => (
<View key={index} style={styles.sessionCard}>
<View style={styles.sessionHeader}>
<View>
<StyledText size="md" variant="text" style={styles.sessionTime}>
{session.time}
</StyledText>
<StyledText size="sm" font="bold" style={styles.sessionTitle}>
{session.name}
</StyledText>
</View>
<TouchableOpacity onPress={() => toggleSaveSession(index)}>
<FontAwesome
name={savedSessions[index] ? 'bookmark' : 'bookmark-o'}
size={20}
color={savedSessions[index] ? palette.palette.secondary : '#ccc'}
/>
</TouchableOpacity>
</View>
<StyledText size="lg" font="medium" style={{ color: Colors.palette.secondary }}>
{session?.name}
</StyledText>
</View>
))}
</ScrollView>
</BackgroundWrapper>
</View>
</MainContainer>
);
};

const styles = StyleSheet.create({
container: {
padding: 16,
justifyContent: 'center',
marginTop: 30,
},
backButton: {
position: 'absolute',
top: 10,
left: 10,
zIndex: 10,
padding: 8,
flex: 1,
padding: spacing.lg,
},
loader: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
error: {
color: Colors.palette.error,
textAlign: 'center',
marginTop: 20,
},
bio: {
marginTop: 0,
marginBottom: 20,
lineHeight: 22,
},
socialMediaContainer: {
header: {
width: '100%',
flexDirection: 'row',
justifyContent: 'center',
marginVertical: 15,
gap: 16,
alignItems: 'center',
marginBottom: spacing.lg,
},
socialIconImage: {
borderWidth: 1,
borderColor: '#eee',
padding: 6,
borderRadius: 5,
backgroundColor: 'rgba(250, 250, 250, 0.2)',
backBtn: {
paddingVertical: spacing.sm,
paddingHorizontal: spacing.lg,
borderRadius: spacing.sm,
},
sessionCard: {
backgroundColor: 'rgba(250, 250, 250, 0.2)',
padding: 16,
borderRadius: 12,
marginBottom: 16,
borderWidth: 1,
borderColor: '#eee',
name: {
flex: 1,
alignItems: 'center',
},
sessionHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
top: {
alignItems: 'center',
paddingHorizontal: 4,
marginBottom: sizes.lg,
},
image: {
width: sizes.cardImage,
height: sizes.cardImage,
borderRadius: spacing.sm,
marginBottom: spacing.lg,
},
sessionTime: {
color: '#eee',
tagline: {
color: Colors.palette.secondary,
},
sessionTitle: {
marginTop: 4,
marginRight: 6,
flexShrink: 1,
row: {
flexDirection: 'row',
justifyContent: 'center',
flexWrap: 'wrap',
gap: sizes.md,
},
iconBtn: {
backgroundColor: Colors.palette.iconBg,
padding: sizes.sm,
borderColor: Colors.palette.border,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: sizes.sm,
},
socialIcon: {
marginHorizontal: 15,
},
bio: {
fontSize: 14,
color: Colors.palette.text,
marginVertical: 20,
lineHeight: 22,
},
sessionCard: {
backgroundColor: Colors.palette.cardBg,
padding: spacing.lg,
borderRadius: sizes.sm,
marginBottom: spacing.lg,
borderWidth: StyleSheet.hairlineWidth,
borderColor: Colors.palette.border,
},
});

Expand Down
Loading

0 comments on commit 62a0ed3

Please sign in to comment.