Skip to content

Commit

Permalink
[feat] resources rendered and scrolling by buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
arfamomin committed Oct 23, 2024
1 parent 79337e2 commit 99a79e7
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 34 deletions.
7 changes: 7 additions & 0 deletions App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HealingResources from '@/screens/HealingResources';
import HealingCatalogue from '@/screens/HealingResources/HealingCatalogue';
import HFHGuide from '@/screens/HealingResources/HFHGuide';
import Home from '@/screens/Home';
import LegalRights from '@/screens/LegalRights';
import SeekHelp from '@/screens/SeekHelp';
Expand All @@ -16,6 +18,11 @@ export default function App() {
<Stack.Screen name="Healing Resources" component={HealingResources} />
<Stack.Screen name="Legal Rights" component={LegalRights} />
<Stack.Screen name="Seek Help" component={SeekHelp} />
<Stack.Screen
name="Themed Healing Resources"
component={HealingCatalogue}
/>
<Stack.Screen name="Hope for Healing Guide" component={HFHGuide} />
</Stack.Navigator>
</NavigationContainer>
);
Expand Down
9 changes: 9 additions & 0 deletions src/screens/HealingResources/HFHGuide/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Text, View } from 'react-native';

export default function HFHGuide() {
return (
<View>
<Text> This is the HFH page </Text>
</View>
);
}
89 changes: 89 additions & 0 deletions src/screens/HealingResources/HealingCatalogue/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useEffect, useRef, useState } from 'react';
import { ScrollView, Text, TouchableOpacity, View } from 'react-native';
import { getHealingResourceData } from '@/supabase/queries/generalQueries';
import { HealingResource } from '@/types/types';
import styles from './styles';

const themes = ['Breathing', 'Meditation', 'Joy', 'Resilience'];

export default function HealingCatalogue() {
const [resources, setResources] = useState<HealingResource[]>([]);
const scrollViewRef = useRef<ScrollView | null>(null);
const [headerPositions, setHeaderPositions] = useState<number[]>([]);

useEffect(() => {
const fetchResources = async () => {
const data = await getHealingResourceData();
setResources(data);
};
fetchResources();
}, []);

const groupedResources = themes.reduce(
(acc, theme) => {
acc[theme] = resources.filter(resource =>
resource.topics.includes(theme),
);
return acc;
},
{} as Record<string, HealingResource[]>,
);

// Scroll to top of theme header
const scrollToTheme = (index: number) => {
const targetY = headerPositions[index] || 0;
const paddingTop = 30;
scrollViewRef.current?.scrollTo({
y: targetY - paddingTop,
animated: true,
});
};

// Captures the position of headers as being rendered to use for scrolling
const onLayoutHeader =
(index: number) => (event: { nativeEvent: { layout: { y: number } } }) => {
const { y } = event.nativeEvent.layout;
setHeaderPositions(prevPositions => {
const newPositions = [...prevPositions];
newPositions[index] = y;
return newPositions;
});
};

return (
<View style={styles.container}>
<View style={styles.themesContainer}>
{themes.map((theme, index) => (
<TouchableOpacity
key={index}
style={styles.themeButton}
onPress={() => scrollToTheme(index)}
>
<Text>{theme}</Text>
</TouchableOpacity>
))}
</View>
<ScrollView ref={scrollViewRef}>
<View style={styles.resourcesContainer}>
{themes.map((theme, index) => (
<>
<View style={styles.themeHeader} onLayout={onLayoutHeader(index)}>
<Text style={styles.themeHeaderText}>{theme}</Text>
</View>
<View style={styles.cardsContainer}>
{groupedResources[theme].map((resource, resourcesIndex) => (
<View style={styles.resourceContainer} key={resourcesIndex}>
<View style={styles.resourceCard}></View>
<Text style={styles.resourceText}>
{resource.text_content}
</Text>
</View>
))}
</View>
</>
))}
</View>
</ScrollView>
</View>
);
}
76 changes: 76 additions & 0 deletions src/screens/HealingResources/HealingCatalogue/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
container: {
width: '100%',
height: '100%',
backgroundColor: '#FFFFFF',
flexDirection: 'row',
alignItems: 'center',
},
themesContainer: {
paddingTop: 30,
height: '100%',
width: '20%',
padding: 10,
flexDirection: 'column',
alignItems: 'center',
rowGap: 10,
},
themeButton: {
backgroundColor: '#e8e8e8',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 10,
width: '90%',
height: 40,
},
resourcesContainer: {
paddingTop: 30,
width: '100%',
height: '100%',
borderLeftColor: '#e8e8e8',
flexDirection: 'row',
flexWrap: 'wrap',
padding: 10,
rowGap: 10,
columnGap: 10,
borderLeftWidth: 1,
},
themeHeader: {
justifyContent: 'center',
alignItems: 'flex-start',
width: '100%',
borderRadius: 50,
backgroundColor: '#F3F3F3',
borderColor: '#D9D9D9',
borderWidth: 1.5,
height: 50,
},
themeHeaderText: {
fontSize: 20,
marginLeft: 15,
},
cardsContainer: {
width: '100%',
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'flex-start',
},
resourceContainer: {
flexDirection: 'column',
margin: '1.1%',
width: '31%',
},
resourceCard: {
height: 250,
borderRadius: 10,
backgroundColor: '#D9D9D9',
},
resourceText: {
fontSize: 16,
margin: 10,
color: '#7839dj',
},
});
Empty file.
Empty file.
45 changes: 16 additions & 29 deletions src/screens/HealingResources/index.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
import React, { useEffect, useState } from 'react';
import { Button, View } from 'react-native';
import { getHealingResourceData } from '@/supabase/queries/generalQueries';
import { Resource } from '@/types/types';

export default function HealingResources() {
const [, setSummaries] = useState<Resource[]>([]);

useEffect(() => {
fetchData();
}, []);

const fetchData = async () => {
try {
const data = await getHealingResourceData();
setSummaries(data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
import { Text, TouchableOpacity, View } from 'react-native';
import styles from './styles';

export default function HealingResources({ navigation }: { navigation: any }) {
return (
<View>
<Button
title="Hope Healing Guide"
onPress={() => console.log('does this work')}
/>
<Button
title="Theme Healing Resources"
onPress={() => console.log('does this work')}
/>
<View style={styles.container}>
<TouchableOpacity
style={styles.pagebutton}
onPress={() => navigation.navigate('Hope for Healing Guide')}
>
<Text style={styles.buttonText}>Hope for Healing Guide</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.pagebutton} // Reusing the same style for consistency
onPress={() => navigation.navigate('Themed Healing Resources')}
>
<Text style={styles.buttonText}>Resources Catalogue</Text>
</TouchableOpacity>
</View>
);
}
18 changes: 17 additions & 1 deletion src/screens/HealingResources/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ export default StyleSheet.create({
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'flex-start',
justifyContent: 'center',
backgroundColor: '#f5f5f5',
flexDirection: 'row',
columnGap: 20,
},
pagebutton: {
borderColor: '#e8e8e8',
backgroundColor: '#ffffff',
borderWidth: 2,
borderRadius: 20,
width: 500,
height: 200,
justifyContent: 'center',
alignItems: 'center',
},
buttonText: {
fontSize: 20,
},
});
13 changes: 9 additions & 4 deletions src/supabase/queries/generalQueries.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { Resource } from '@/types/types';
import { HealingResource, Resource } from '@/types/types';
import supabase from '../createClient';

export const getHealingResourceData = async (): Promise<Resource[]> => {
export const getHealingResourceData = async (): Promise<HealingResource[]> => {
const { data, error } = await supabase.from('healing_resources').select('*');
if (error) {
throw new Error(`Error fetching resources: ${error.message}`);
}

return data as Resource[];
// Convert comma-separated list of strings from `topics` into an array of strings
return data.map(resource => ({
...resource,
topics: resource.topics
? resource.topics.split(',').map((topic: string) => topic.trim())
: [],
}));
};

export const getSeekHelpData = async (): Promise<Resource[]> => {
Expand Down
8 changes: 8 additions & 0 deletions src/types/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ export interface Resource {
summary: string;
[key: string]: any;
}

export type HealingResource = {
id: number;
video_id: number;
text_content: string;
is_video: boolean;
topics: string[];
};

0 comments on commit 99a79e7

Please sign in to comment.