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

Word Codes

Uploaded by

gunzithanzo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views

Word Codes

Uploaded by

gunzithanzo
Copyright
© © All Rights Reserved
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