0% found this document useful (0 votes)
29 views

Word Codes

Uploaded by

gunzithanzo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views

Word Codes

Uploaded by

gunzithanzo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

The Welcome Screen

The welcome screen displays the content of the index.tsx file, showing a
brief overview of the application and a button that redirects users to
the home screen.

Update the app/index.tsx file with the code snippet below:


import { ImageBackground, Pressable, Text, View } from "react-native";
import { useRouter } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { LinearGradient } from "expo-linear-gradient";

export default function TabOneScreen() {


const router = useRouter();
return (
<ImageBackground
source={require("../assets/images/background.jpg")}
className='flex-1 items-center justify-center pb-10 bg-gradient-to-bl from-gray-200 to-
gray-900'
>
<LinearGradient
colors={["transparent", "rgba(0,0,0,0.9)"]}
style={{
position: "absolute",
bottom: 0,
width: "100%",
height: "100%",
}}
start={{ x: 0.5, y: 0 }}
end={{ x: 0.5, y: 1 }}
/>
<View className='absolute bottom-14 flex flex-col items-center justify-center w-full
bg-gradient-to-t from-gray-900 px-4'>
<Text
className='text-4xl text-white font text-center mb-4'
style={{ fontFamily: "Bold" }}
>
Breaking Boundaries, Breaking News
</Text>

<Text
className='text-gray-300 text-center text-xl mb-6'
style={{ fontFamily: "Medium" }}
>
Explore the world through our lens. Your passport to a connected and
informed world, right at your fingertips.
</Text>
<Pressable
onPress={() => router.push("/home")}
className='bg-stone-700 rounded-full p-4 w-full items-center justify-center
shadow-lg'
>
<Text
className='text-white text-2xl'
style={{ fontFamily: "Medium" }}
>
Get Started
</Text>
</Pressable>
</View>
<StatusBar style='light' />
</ImageBackground>
);
}

The Tab Screens

It contains the Home, Discover, and Search screens. Update


the (tabs)/_layout.tsx file to display the tab icons and default settings for
each screen within the Tab layout.
import { Tabs } from "expo-router";
import { FontAwesome5, MaterialIcons, FontAwesome } from "@expo/vector-icons";

export default function Page() {


return (
<Tabs
screenOptions={{
tabBarShowLabel: false,
tabBarActiveBackgroundColor: "#fff",
tabBarActiveTintColor: "#a16207",
headerShown: false,
}}
>
<Tabs.Screen
name='home'
options={{
title: "Home",
tabBarIcon: ({ color }) => (
<FontAwesome5 name='home' size={24} color={color} />
),
}}
/>
<Tabs.Screen
name='discover'
options={{
title: "Discover",
tabBarIcon: ({ color }) => (
<MaterialIcons name='explore' size={24} color={color} />
),
}}
/>

<Tabs.Screen
name='search'
options={{
title: "Search",
tabBarIcon: ({ color }) => (
<FontAwesome name='search' size={24} color={color} />
),
}}
/>
</Tabs>
);
}

Import the functions from the fetchNews.ts file declared earlier, execute
the functions using TanStack Query, and display the results within the
Home screen.
import { FlatList, StatusBar } from "react-native";
import Carousel from "react-native-snap-carousel";
import { useQuery } from "@tanstack/react-query";
import {
fetchBreakingNews,
fetchRecommendedNews,
} from "../../assets/fetchNews";

export default function Page() {


//👇🏻 fetch the breaking news
const breakingNewsQuery = useQuery({
queryKey: ["breakingNews"],
queryFn: fetchBreakingNews,
});
//👇🏻 fetch the recommended news
const recommendedNewsQuery = useQuery({
queryKey: ["recommendedNews"],
queryFn: fetchRecommendedNews,
});
return (
<SafeAreaView className='flex-1'>
<View>
{breakingNewsQuery.data && (
<Carousel
data={breakingNewsQuery.data.articles}
renderItem={renderBreakingNewsItem}
firstItem={1}
inactiveSlideScale={0.86}
sliderWidth={width}
itemWidth={width * 0.8}
slideStyle={{ display: "flex", alignItems: "center" }}
/>
)}
</View>

<View>
{recommendedNewsQuery.data && (
<FlatList
data={recommendedNewsQuery.data.articles}
renderItem={renderRecommendedNewsItem}
showsVerticalScrollIndicator={false}
keyExtractor={(item, index) => item.url}
/>
)}
</View>

<StatusBar style='dark' />


</SafeAreaView>
);
}
Create the functions that render each result within the Carousel and
the Flatlist.

//👇🏻 Renders the Breaking News UI (horizontal row)


const renderBreakingNewsItem = ({ item }: any) => {
return (
<Link
href={{
pathname: "/[title]",
params: {
data: JSON.stringify([item.url, item.title]),
},
}}
asChild
>
<Pressable>
<View className='relative'>
<Image
source={{ uri: item.urlToImage || generateRandomImage() }}
style={{
width: width * 0.8,
height: height * 0.22,
borderRadius: 10,
}}
resizeMode='cover'
className='rounded-3xl'
/>
<LinearGradient
colors={["transparent", "rgba(0,0,0,0.9)"]}
start={{ x: 0.5, y: 0 }}
end={{ x: 0, y: 1 }}
style={{
position: "absolute",
bottom: 0,
width: "100%",
height: "100%",
borderBottomLeftRadius: 24,
borderBottomRightRadius: 24,
}}
/>

<View className='absolute bottom-0 left-4 right-0 justify-end h-[80%] px-4 pb-4'>


<Text
className='text-xl text-white mb-2'
style={{ fontFamily: "Bold" }}
>
{item.title.length > 48
? item.title.slice(0, 47) + "..."
: item.title}
</Text>
<Text className=' text-stone-200' style={{ fontFamily: "Medium" }}>
{item.author}
</Text>
</View>
</View>
</Pressable>
</Link>
);
};

//👇🏻 Renders the Recommended News UI (vertical row)


const renderRecommendedNewsItem = ({ item }: any) => {
return (
<Link
href={{
pathname: "/[title]",
params: {
data: JSON.stringify([item.url, item.title]),
},
}}
asChild
>
<Pressable className='px-4 w-full'>
<View className='flex flex-row items-center justify-between w-full mb-4 bg-white
shadow-xl rounded-xl'>
<Image
source={{ uri: item.urlToImage || generateRandomImage() }}
style={{
width: width * 0.4,
height: width * 0.3,
borderRadius: 5,
}}
resizeMode='cover'
className='rounded-3xl mr-[1px]'
/>

<View className='px-3 flex-1'>


<Text
style={{ fontFamily: "Medium" }}
className='text-stone-500 text-sm'
>
{item.author}
</Text>
<Text className='text-lg mb-[1px]' style={{ fontFamily: "Bold" }}>
{item.title.length > 48
? item.title.slice(0, 47) + "..."
: item.title}
</Text>
<Text
style={{ fontFamily: "Medium" }}
className='text-stone-500 text-sm'
>
{convertToReadableDate(item.publishedAt)}
</Text>
</View>
</View>
</Pressable>
</Link>
);
};

The discover.tsx file displays the news categories within the application
and redirects users to the (stack)/news screens containing all the news
under that category. Copy the code snippet below into
the discover.tsx file to render the news categories:
import { Categories, categories } from "../../assets/util";

export default function Page() {


return (
<View className='rounded-2xl shadow-xl'>
<FlatList
data={categories}
renderItem={renderItem}
keyExtractor={(item, index) => item.id}
numColumns={2}
contentContainerStyle={{
justifyContent: "space-between",
alignItems: "center",
padding: 10,
width: "100%",
}}
/>
</View>
);
}
The renderItem function below represents the layout of each item
rendered within the FlatList.
const renderItem = ({ item }: { item: Categories }) => {
return (
<Link
href={{
pathname: "/news",
params: {
category: item.id,
},
}}
asChild
>
<Pressable>
<View className='relative m-[7px]'>
<Image
source={{ uri: item.image_url }}
style={{
width: width * 0.47,
height: width * 0.45,
borderRadius: 10,
}}
resizeMode='cover'
className='rounded-xl'
/>
<LinearGradient
colors={["transparent", "rgba(0,0,0,0.9)"]}
start={{ x: 0.5, y: 0 }}
end={{ x: 0, y: 1 }}
style={{
position: "absolute",
bottom: 0,
width: "100%",
height: "100%",
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
}}
/>
<View className='absolute bottom-0 left-4 right-0 justify-end h-[80%] px-4 pb-4'>
<Text
className='text-xl text-white mb-2'
style={{ fontFamily: "Bold" }}
>
{item.name}
</Text>
</View>
</View>
</Pressable>
</Link>
);
};

Update the search.tsx file to enable users enter an input to the search
field and displays the results within a FlatList.
import {
View,
Text,
Pressable,
Image,
Dimensions,
FlatList,
} from "react-native";
import { Link } from "expo-router";
import { SafeAreaView } from "react-native-safe-area-context";
import { TextInput } from "react-native-gesture-handler";
import { FontAwesome, MaterialIcons } from "@expo/vector-icons";
import { useState } from "react";
import { fetchSearchNews } from "../../assets/fetchNews";
import {
News,
convertToReadableDate,
generateRandomImage,
} from "../../assets/util";
const { width } = Dimensions.get("window");

export default function Page() {


const [query, onChangeQuery] = useState<string>("");
const [results, setResults] = useState<any[]>([]);
const [resultsCount, setResultsCount] = useState<number>(0);

const handleTextChange = (text: string) => {


onChangeQuery(text);
if (text.length > 2) {
fetchSearchNews(text).then((res) => {
setResults(res.articles);
setResultsCount(res.totalResults);
});
}
};
return (
<SafeAreaView>
<View className='px-4 '>
<Text
className='text-3xl text-stone-500 mb-3'
style={{ fontFamily: "Bold" }}
>
Search
</Text>
<View className='flex flex-row items-center justify-between w-full rounded-2xl bg-
gray-100 border-[1px] px-3 border-stone-300'>
<FontAwesome name='search' size={24} color='gray' className='mr-2' />
<TextInput
className='flex-1
rounded-xl px-4 py-4'
placeholder='Search for news'
style={{ fontFamily: "Medium" }}
value={query}
onChangeText={(text) => handleTextChange(text)}
/>
</View>
<Text className='text-lg mt-4 mb-4' style={{ fontFamily: "Semibold" }}>
Total Results: {resultsCount}
</Text>

<View>
{results && (
<FlatList
data={results}
renderItem={newsItem}
showsVerticalScrollIndicator={false}
keyExtractor={(item) => item.url}
/>
)}
</View>
</View>
</SafeAreaView>
);
}

The results are rendered via a newItem component created as shown


below.
export interface News {
title: string;
url: string;
image?: string;
publishedAt?: string;
author?: string;
urlToImage?: string;
}

const newsItem = ({ item }: { item: News }) => {


return (
<Link
href={{
pathname: "/[title]",
params: {
url: item.url,
title: item.title,
},
}}
asChild
>
<Pressable className='px-4 w-full'>
<View className='flex flex-row items-center justify-between w-full mb-4 bg-white
shadow-xl rounded-xl p-3'>
<Image
source={{ uri: item.urlToImage || generateRandomImage() }}
style={{ width: width * 0.2, height: width * 0.2, borderRadius: 5 }}
resizeMode='cover'
className='rounded-3xl mr-[1px]'
/>

<View className='px-3 flex-1'>


<Text
style={{ fontFamily: "Medium" }}
className='text-stone-500 text-sm'
>
{item.author}
</Text>
<Text className='text-lg mb-[1px]' style={{ fontFamily: "Bold" }}>
{item.title.length > 48
? item.title.slice(0, 47) + "..."
: item.title}
</Text>
<Text
style={{ fontFamily: "Medium" }}
className='text-stone-500 text-sm'
>
{convertToReadableDate(item.publishedAt)}
</Text>
</View>
<MaterialIcons name='keyboard-arrow-right' size={26} color='brown' />
</View>
</Pressable>
</Link>
);
};

The Stack Screens

Update the (stack)/_layout.tsx file to display its files using the Stack layout.
import { Stack } from "expo-router";

export default function Page() {


return <Stack></Stack>;
}
Modify the news.tsx file to display the list of news based on a chosen
category. When a user selects a news category, the user is redirected
to the news route where the API results (category news) are displayed.
export default function Page() {
const { category }: {category: string} = useLocalSearchParams();

if (category === "breaking") {


const breakingNewsQuery = useQuery({
queryKey: ["breakingNews"],
queryFn: fetchBreakingNews,
});
return <DisplayNews news={breakingNewsQuery} title='Breaking News' />;

} else if (category === "recommended") {


const recommendedNewsQuery = useQuery({
queryKey: ["recommendedNews"],
queryFn: fetchRecommendedNews,
});
return <DisplayNews news={recommendedNewsQuery} title='Recommended News' />;

} else {
const discoverNewsQuery = useQuery({
queryKey: ["discoverNews", category],
queryFn: () => fetchDiscoverNews(category),
});
return (
<DisplayNews
news={discoverNewsQuery}
title={`${category[0].toUpperCase() + category.slice(1)} News`}
/>
);
}
}

The DisplayNews component above displays the results in a FlatList.

You might also like