Skip to content

Commit

Permalink
Popular Series (#259)
Browse files Browse the repository at this point in the history
* Added popular series section
loadSeriesById now uses updateSeriesImage for image uri handling
Fixed no-restricted-syntax error

* Added popular series

Co-authored-by: George Bell <47749730+GeorgeBellTMH@users.noreply.github.com>
  • Loading branch information
itbel and GeorgeBellTMH committed Jun 20, 2021
1 parent fcd111f commit d90f8e9
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 36 deletions.
11 changes: 7 additions & 4 deletions src/navigation/MainTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Thumbnail } from 'native-base';
import { StyleSheet } from 'react-native';
import { Announcement } from 'src/services/AnnouncementService';
import HomeScreen from '../screens/home/HomeScreen';
import TeachingScreen from '../screens/teaching/TeachingScreen';
import AllSeriesScreen from '../screens/teaching/AllSeriesScreen';
Expand All @@ -22,12 +23,12 @@ import { Theme } from '../Theme.style';
import MediaContext from '../contexts/MediaContext';
import { GetVideoByVideoTypeQuery } from '../services/API';
import LiveStreamScreen from '../screens/LiveStreamScreen';
import {EventQueryResult} from "../services/EventsService";
import { EventQueryResult } from '../services/EventsService';

export type HomeStackParamList = {
HomeScreen: {questionResult?:boolean};
HomeScreen: { questionResult?: boolean };
EventDetailsScreen: { item: NonNullable<EventQueryResult>[0] };
AnnouncementDetailsScreen: { item: any };
AnnouncementDetailsScreen: { item: Announcement };
LiveStreamScreen: undefined;
};

Expand All @@ -53,7 +54,9 @@ type PopularVideoData = NonNullable<

export type TeachingStackParamList = {
Teaching: undefined;
AllSeriesScreen: { customPlaylists: boolean } | undefined;
AllSeriesScreen:
| { customPlaylists?: boolean; popularSeries?: boolean }
| undefined;
AllSermonsScreen: { startDate: string; endDate: string } | undefined;
SeriesLandingScreen: {
seriesId?: string;
Expand Down
31 changes: 21 additions & 10 deletions src/screens/teaching/AllSeriesScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,15 @@ export default function AllSeriesScreen({
100
);
};
const loadPopularSeries = async () => {
const data: any = await SeriesService.fetchPopularSeries();
setAllSeries({ items: data, loading: false, nextToken: null });
};

generateYears();
if (route?.params?.customPlaylists) {
loadCustomPlaylists();
if (route?.params?.popularSeries || route?.params?.customPlaylists) {
if (route?.params?.popularSeries) loadPopularSeries();
if (route?.params?.customPlaylists) loadCustomPlaylists();
} else {
loadAllSeriesAsync();
}
Expand All @@ -145,7 +150,11 @@ export default function AllSeriesScreen({
useLayoutEffect(() => {
navigation.setOptions({
headerShown: true,
title: route?.params?.customPlaylists ? 'Video Playlists' : 'All Series',
title: route?.params?.customPlaylists
? 'Video Playlists'
: route?.params?.popularSeries
? 'Popular Series'
: 'All Series',
headerTitleStyle: style.headerTitle,
headerStyle: { backgroundColor: Theme.colors.background },
headerLeft: function render() {
Expand Down Expand Up @@ -185,13 +194,15 @@ export default function AllSeriesScreen({
return (
<Container>
<Content style={style.content}>
<SearchBar
style={style.searchBar}
searchText={searchText}
handleTextChanged={(newStr) => setSearchText(newStr)}
placeholderLabel="Search by name..."
/>
{!route?.params?.customPlaylists ? (
{!route?.params?.popularSeries ? (
<SearchBar
style={style.searchBar}
searchText={searchText}
handleTextChanged={(newStr) => setSearchText(newStr)}
placeholderLabel="Search by name..."
/>
) : null}
{!route?.params?.customPlaylists && !route?.params?.popularSeries ? (
<>
<View style={style.dateSelectBar}>
<FlatList
Expand Down
6 changes: 1 addition & 5 deletions src/screens/teaching/SeriesLandingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,7 @@ export default function SeriesLandingScreen({
let loadedSeries = series;
if (!loadedSeries && seriesId) {
loadedSeries = await SeriesService.loadSeriesById(seriesId);
const uri = `https://themeetinghouse.com/cache/640/static/photos/series/adult-sunday-${loadedSeries.id.replace(
'?',
''
)}.jpg`;
setSeries({ ...loadedSeries, image640px: uri });
setSeries(loadedSeries);
}
if (!customPlaylist) {
const json = (await API.graphql(
Expand Down
57 changes: 57 additions & 0 deletions src/screens/teaching/TeachingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import SermonsService from '../../services/SermonsService';
import SeriesService, {
LoadPlaylistData,
LoadSeriesListData,
SeriesDataWithHeroImage,
} from '../../services/SeriesService';
import SpeakersService from '../../services/SpeakersService';
import loadSomeAsync from '../../utils/loading';
Expand Down Expand Up @@ -211,6 +212,11 @@ interface PlaylistData extends LoadPlaylistData {
loading: boolean;
}

interface PopularSeriesData {
items: Array<SeriesDataWithHeroImage>;
loading: boolean;
}

export default function TeachingScreen({ navigation }: Params): JSX.Element {
const user = useContext(UserContext);
const [recentTeaching, setRecentTeaching] = useState({
Expand All @@ -228,6 +234,10 @@ export default function TeachingScreen({ navigation }: Params): JSX.Element {
items: [],
nextToken: null,
});
const [popularSeries, setPopularSeries] = useState<PopularSeriesData>({
loading: true,
items: [],
});
const [highlights, setHighlights] = useState({
loading: true,
items: [],
Expand Down Expand Up @@ -317,6 +327,15 @@ export default function TeachingScreen({ navigation }: Params): JSX.Element {
);
};

const loadPopularSeries = async () => {
try {
const data = await SeriesService.fetchPopularSeries();
setPopularSeries({ items: data, loading: false });
} catch (err) {
setPopularSeries({ items: [], loading: false });
}
};

useEffect(() => {
const getPopularTeaching = async () => {
const startDate = moment().subtract(150, 'days').format('YYYY-MM-DD');
Expand All @@ -337,6 +356,7 @@ export default function TeachingScreen({ navigation }: Params): JSX.Element {
);
setPopular(popularTeaching);
};
loadPopularSeries();
// These trigger "The user is not authenticated" message
loadRecentSeries();
loadRecentSermons();
Expand Down Expand Up @@ -536,6 +556,43 @@ export default function TeachingScreen({ navigation }: Params): JSX.Element {
More popular teaching
</AllButton>
</View>
<View style={style.categorySection}>
<Text style={style.categoryTitle}>Popular Series</Text>
<Text style={style.highlightsText}>
A collection of our favourite and most popular series
</Text>
{customPlaylists.loading && (
<View
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}
>
<ActivityIndicator />
</View>
)}
<View style={style.seriesListContainer}>
{popularSeries?.items?.map((s: any, key: any) => {
if (key < 4)
return (
<SeriesItem
key={s.id}
navigation={navigation as any}
seriesData={s}
/>
);
return null;
})}
</View>
<AllButton
handlePress={() =>
navigation.push('AllSeriesScreen', { popularSeries: true })
}
>
More Popular Series
</AllButton>
</View>
<View style={style.categorySection}>
<Text style={style.categoryTitle}>Video Playlists</Text>
<Text style={style.highlightsText}>
Expand Down
55 changes: 38 additions & 17 deletions src/services/SeriesService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export interface SeriesHighlights {
loading?: boolean;
}

interface SeriesDataWithHeroImage extends SeriesData {
export interface SeriesDataWithHeroImage extends SeriesData {
heroImage?: string;
image640px?: string;
}
Expand Down Expand Up @@ -131,6 +131,26 @@ export default class SeriesService {
return series;
};

static fetchPopularSeries = async (): Promise<
Array<SeriesDataWithHeroImage>
> => {
const res = await fetch(
'https://www.themeetinghouse.com/static/content/teaching.json'
);
const data = await res.json();
// TODO: does this need typing?
const findSeries =
data?.page?.content?.filter((a) => a?.collection)[0]?.collection ?? [];

const arr: Array<Promise<SeriesDataWithHeroImage>> = [];
findSeries.forEach(async (seriesName: string) => {
arr.push(SeriesService.loadSeriesById(seriesName));
});
return Promise.all(arr).then((series) => {
return series;
});
};

static loadSeriesList = async (
limit: number,
nextToken?: string
Expand All @@ -146,10 +166,8 @@ export default class SeriesService {

const items = queryResult?.data?.getSeriesBySeriesType?.items;
if (items) {
for (const item of items) {
if (item) {
SeriesService.updateSeriesImage(item as SeriesData);
}
for (let i = 0; i < items.length; i++) {
SeriesService.updateSeriesImage(items[i] as SeriesData);
}
}
return {
Expand All @@ -168,6 +186,7 @@ export default class SeriesService {
variables: { id: seriesId },
});
const series = queryResult.getSeries;
await SeriesService.updateSeriesImage(series as SeriesData);
return series;
};

Expand Down Expand Up @@ -208,18 +227,20 @@ export default class SeriesService {
series: SeriesDataWithHeroImage
): Promise<void> => {
if (series?.title) {
series.image = `https://themeetinghouse.com/cache/320/static/photos/playlists/${series.title.replace(
'?',
''
)}.jpg`
.replace(/ /g, '%20')
.replace("'", '');
series.image640px = `https://themeetinghouse.com/cache/640/static/photos/playlists/${series.title.replace(
'?',
''
)}.jpg`
.replace(/ /g, '%20')
.replace("'", '');
series.image =
`https://themeetinghouse.com/cache/320/static/photos/playlists/${series.title.replace(
'?',
''
)}.jpg`
.replace(/ /g, '%20')
.replace("'", '');
series.image640px =
`https://themeetinghouse.com/cache/640/static/photos/playlists/${series.title.replace(
'?',
''
)}.jpg`
.replace(/ /g, '%20')
.replace("'", '');
series.heroImage = `https://www.themeetinghouse.com/static/photos/playlists/${series.title.replace(
/ /g,
'%20'
Expand Down

0 comments on commit d90f8e9

Please sign in to comment.