Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
feat: home screen w/ search and popular novels components
Browse files Browse the repository at this point in the history
  • Loading branch information
mauriciobraz committed Mar 19, 2023
1 parent 8778949 commit 4655f13
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 5 deletions.
110 changes: 110 additions & 0 deletions novels.json

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions source/hooks/useCachedResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ export default function useCachedResources() {
...Feather.font,
});

try {
if (!dataSource.isInitialized) {
await dataSource.initialize();
} catch (e) {
console.warn(e);
}
}

Expand Down
13 changes: 11 additions & 2 deletions source/navigation/navigators/BottomTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import FeatherIcon from '@expo/vector-icons/Feather';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import HistoryScreen from '../../screens/History';
import HomeScreen from '../../screens/Home';
import LibraryScreen from '../../screens/Library';
import SettingsScreen from '../../screens/Settings';
import UpdatesScreen from '../../screens/Updates';
Expand All @@ -12,16 +13,24 @@ const BottomTab = createBottomTabNavigator<RootBottomTabParamList>();
export default function BottomTabNavigator() {
return (
<BottomTab.Navigator
initialRouteName="Library"
initialRouteName="Home"
screenOptions={{
headerShown: false,
tabBarShowLabel: false,
}}>
<BottomTab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: ({ color }) => <BottomTabBarIcon name="home" color={color} />,
}}
/>

<BottomTab.Screen
name="Library"
component={LibraryScreen}
options={{
tabBarIcon: ({ color }) => <BottomTabBarIcon name="home" color={color} />,
tabBarIcon: ({ color }) => <BottomTabBarIcon name="book" color={color} />,
}}
/>

Expand Down
1 change: 1 addition & 0 deletions source/navigation/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type RootStackScreenProps<Screen extends keyof RootStackParamList> = Nati
// @react-navigation/bottom-tabs

export type RootBottomTabParamList = {
Home: undefined;
Library: undefined;
Updates: undefined;
History: undefined;
Expand Down
50 changes: 50 additions & 0 deletions source/screens/Home/components/NovelList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// TODO: Add a lightly shadowed background container of

import { FlatList, Image, ListRenderItemInfo } from 'react-native';

import { Chapters, Container, TextContainer, Title } from './styles';
import type NovelEntity from '../../../../database/entities/NovelEntity';

interface NovelListProps {
novels: NovelEntity[];
}

export default function NovelList({ novels }: NovelListProps) {
function renderItem({ item }: ListRenderItemInfo<NovelEntity>) {
return (
<Container source={{ uri: item.cover.toString() }}>
<TextContainer>
<Title numberOfLines={1}>{item.title}</Title>
<Chapters>{item.chapters.length} Chapter(s)</Chapters>
</TextContainer>

<Image
resizeMethod="scale"
borderRadius={8}
source={{
uri: item.cover.toString(),
width: 100,
height: 150,
}}
/>
</Container>
);
}

return (
<FlatList
horizontal
data={novels}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}
style={{
marginHorizontal: -4,
marginVertical: 15,
}}
showsVerticalScrollIndicator={false}
contentContainerStyle={{
paddingVertical: 8,
}}
/>
);
}
32 changes: 32 additions & 0 deletions source/screens/Home/components/NovelList/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import styled from 'styled-components/native';

export const Container = styled.ImageBackground.attrs({
blurRadius: 4,
borderRadius: 12,
})`
flex-direction: row;
justify-content: space-between;
align-items: flex-end;
margin: 0 8px;
padding: 16px;
width: 350px;
opacity: 0.75;
`;

export const TextContainer = styled.View.attrs({
flex: 1,
display: 'flex',
marginRight: 10,
})``;

export const Title = styled.Text`
font-size: 16px;
font-weight: bold;
color: ${({ theme }) => theme.shades[900]};
`;

export const Chapters = styled.Text`
font-size: 14px;
color: ${({ theme }) => theme.shades[600]};
`;
26 changes: 26 additions & 0 deletions source/screens/Home/components/Search/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// TODO: Add behavior to close keyboard when user click outside of the input.
// TODO: Add a close button to clear the input.

import type { NativeSyntheticEvent, TextInputSubmitEditingEventData } from 'react-native';

import { SearchContainer, SearchIcon, SearchInput } from './styles';

interface SearchProps {
placeholder: string;
onSearch: (search: string) => void;
}

export default function Search({ placeholder, onSearch }: SearchProps) {
function handleOnSubmitEditing(e: NativeSyntheticEvent<TextInputSubmitEditingEventData>) {
if (e.nativeEvent.text) {
onSearch(e.nativeEvent.text);
}
}

return (
<SearchContainer>
<SearchIcon />
<SearchInput onSubmitEditing={handleOnSubmitEditing} placeholder={placeholder} />
</SearchContainer>
);
}
30 changes: 30 additions & 0 deletions source/screens/Home/components/Search/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Feather from '@expo/vector-icons/Feather';
import styled from 'styled-components/native';

export const SearchContainer = styled.View`
flex-direction: row;
align-items: center;
padding: 10px 15px;
border-radius: 15px;
background-color: ${({ theme }) => theme.shades[100]};
`;

export const SearchIcon = styled(Feather).attrs((props) => ({
size: 20,
name: 'search',
color: props.theme.shades[300],
}))``;

export const SearchInput = styled.TextInput.attrs((props) => ({
placeholderTextColor: props.theme.shades[300],
selectionColor: props.theme.primary,
}))`
flex: 1;
font-size: 14px;
margin-left: 10px;
font-size: 16px;
color: ${({ theme }) => theme.shades[600]};
`;
17 changes: 17 additions & 0 deletions source/screens/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// TODO: Create a new component to handle the NovelList and NovelCategory

import NovelList from './components/NovelList';
import Search from './components/Search';
import { Container } from './styles';
import novels from '../../../novels.json';
import NovelEntity from '../../database/entities/NovelEntity';
import type { RootBottomTabScreenProps } from '../../navigation/types';

export default function Home({ navigation, route }: RootBottomTabScreenProps<'Home'>) {
return (
<Container>
<Search placeholder="Search for a novel" onSearch={console.log} />
<NovelList novels={novels as unknown as NovelEntity[]} />
</Container>
);
}
12 changes: 12 additions & 0 deletions source/screens/Home/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SafeAreaView } from 'react-native-safe-area-context';
import styled from 'styled-components/native';

export const Container = styled(SafeAreaView)`
background-color: ${({ theme }) => theme.shades[0]};
display: flex;
align-items: center;
justify-content: center;
margin: 15px;
`;

0 comments on commit 4655f13

Please sign in to comment.