Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions app/(app)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { Drawer } from 'expo-router/drawer';
import { Colors } from '../../constants/Colors';
import { MaterialIcons } from '@expo/vector-icons';
import { useRouter, useLocalSearchParams } from 'expo-router';
import { useRouter } from 'expo-router';

import { useAuth } from '../../contexts/authCtx';
import useApi from '@/hooks/useApi';
import { useActiveNameContext } from '../../contexts/activeNameContext';
import { ThemedView } from '@/components/ThemedView';

export default function AppLayout() {
const { user, isLoading } = useAuth();

const router = useRouter();
const api = useApi();
const activeNameContext = useActiveNameContext();
const { id } = useLocalSearchParams<{ id: string }>();

// You can keep the splash screen open, or render a loading screen like we do here.
if (isLoading) {
Expand Down Expand Up @@ -73,6 +70,26 @@ export default function AppLayout() {
), // Hide from drawer navigation
}}
/>
<Drawer.Screen
name="nameContext/[id]/favorites" // This is the name of the page and must match the url from root
options={{
headerTitle: `${activeNameContext.name} Favorites`,
headerStyle: {
backgroundColor: Colors.core.tan, // Set header background color
},
drawerItemStyle: { display: 'none' },
headerRight: () => (
<MaterialIcons
name="close"
size={24}
aria-label='Add Name Context'
color={Colors.core.orange}
onPress={() => router.replace(`/nameContext/${activeNameContext.id}`)}
style={{ marginRight: 10 }}
/>
), // Hide from drawer navigation
}}
/>
<Drawer.Screen
name="nameContext/index" // This is the name of the page and must match the url from root
options={{
Expand Down
29 changes: 26 additions & 3 deletions app/(app)/nameContext/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,28 @@ export default function NameContextDetailsView() {
activeNameContext.setContext({
id: data.id,
name: data.name,
isOwner: data.isOwner
isOwner: data.isOwner,
likedNames: data.likedNames || []
})

}).catch((err) => addApiError(err))
.finally(() => setLoading(false));
}

function updateNameContext() {
setLoading(true);
api.patch(`/nameContext/${id}`, {
name: nameValue,
description: descriptionValue,
noun: nounValue,
filter: {
gender: genderValue,
maxCharacters,
startsWithLetter: startsWithValue
},
participants
}).then((resp) => {
activeNameContext.setContext(resp.data);
}).catch((err) => {
addApiError(err);
}).finally(() => {
Expand Down Expand Up @@ -134,9 +153,14 @@ export default function NameContextDetailsView() {
}} style={{ padding: 5, backgroundColor: Colors.core.purple, borderRadius: 5 }}>
<MaterialIcons name='delete' size={24} color={Colors.core.white} />
</TouchableOpacity>}
<TouchableOpacity onPress={saveNameContext} style={{ padding: 5, backgroundColor: Colors.core.orange, borderRadius: 5 }}>
<TouchableOpacity onPress={ isExistingNameContxt ? updateNameContext : saveNameContext} style={{ padding: 5, backgroundColor: Colors.core.orange, borderRadius: 5 }}>
<MaterialIcons name='save' size={24} color={Colors.core.white} />
</TouchableOpacity>
{isExistingNameContxt &&
<TouchableOpacity onPress={() => router.push(`/nameContext/${id}/favorites`)} style={{ padding: 5, backgroundColor: Colors.core.orange, borderRadius: 5 }}>
<MaterialIcons name='star' size={24} color={Colors.core.white} />
</TouchableOpacity>
}
{isExistingNameContxt &&
<TouchableOpacity onPress={() => router.push(`/nameContext/${id}/match`)} style={{ padding: 5, backgroundColor: Colors.core.orange, borderRadius: 5 }}>
<MaterialIcons name='local-fire-department' size={24} color={Colors.core.white} />
Expand All @@ -148,7 +172,6 @@ export default function NameContextDetailsView() {
style={styles.input}
placeholder='How will you identify this name context?'
maxLength={126}
readOnly={isExistingNameContxt}
autoCapitalize='words'
value={nameValue}
onChangeText={setNameValue}
Expand Down
107 changes: 107 additions & 0 deletions app/(app)/nameContext/[id]/favorites.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { useState } from 'react';
import { View, Text, StyleSheet, Pressable, ActivityIndicator } from 'react-native';
import { ThemedView } from '@/components/ThemedView';
import { Colors } from '@/constants/Colors';
import { ThemedText } from '@/components/ThemedText';
import { useRouter } from 'expo-router';
import { useActiveNameContext, } from '@/contexts/activeNameContext';
import { MaterialIcons } from '@expo/vector-icons';
import useApi from '@/hooks/useApi';
import { useErrorContext } from '@/contexts/errorCtx';

function Favorites() {
const router = useRouter();
const api = useApi();
const activeNameContext = useActiveNameContext();
const { addApiError } = useErrorContext();

const [loading, setLoading] = useState(false);

function removeLikedName(name: string) {
setLoading(true);
api.patch(`/nameContext/${activeNameContext.id}/removeNames`, {
names: [name]
}).then((resp) => activeNameContext.setContext(resp.data))
.catch((err) => addApiError(err))
.finally(() => setLoading(false));
}

function renderContent() {
if (loading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={styles.container}>
<ActivityIndicator size="large" color={Colors.core.orange} />
</View>
</View>
);
}

const { likedNames } = activeNameContext;

if (likedNames.length === 0) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ThemedText type='subtitle' darkColor={Colors.core.black}>No Favorites yet!</ThemedText>
<Pressable style={styles.matchBtn} onPress={() => router.replace(`/nameContext/${activeNameContext.id}/match`)}>
<Text style={styles.matchBtnText}>Start Matching</Text>
<MaterialIcons name='local-fire-department' size={24} color={Colors.core.tanLighter} />
</Pressable>
</View>
)
}

return (
<View style={{ padding: 10, borderRadius: 10 }}>
{likedNames.map((name, index) => (
<View key={name}>
<View style={{ backgroundColor: Colors.core.tan, height: 2 }} key={name}/>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: 5, paddingBottom: 5 }}>
<ThemedText type='defaultSemiBold' darkColor={Colors.core.black} style={{ }}>{index + 1}. {name}</ThemedText>
<Pressable onPress={() => removeLikedName(name)}>
<MaterialIcons name='delete' size={24} color={Colors.core.orange} />
</Pressable>
</View>
</View>
))}
</View>
);
}

return (
<ThemedView style={{ flex: 1, alignItems: 'center', padding: 10 }}>
<View style={styles.container}>
<ThemedText style={{textAlign: 'center'}} type='subtitle' darkColor={Colors.core.black} >Favorites</ThemedText>
{renderContent()}
</View>
</ThemedView>
);
}

const styles = StyleSheet.create({
container: {
width: '100%',
padding: 10,
backgroundColor: Colors.core.tanLighter,
borderRadius: 10,
marginTop: 10,
},
matchBtn: {
backgroundColor: Colors.core.orange,
padding: 10,
borderRadius: 5,
marginTop: 10,
alignItems: 'center',
maxWidth: 300,
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-around'
},
matchBtnText: {
color: Colors.core.tanLighter,
fontSize: 16,
fontFamily: 'Bricolage-Grotesque'
}
});

export default Favorites;
14 changes: 12 additions & 2 deletions app/(app)/nameContext/[id]/match.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import { Colors } from '@/constants/Colors';
import useApi from '@/hooks/useApi';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { NamePopularityGraph } from '@/components/NamePopularityGraph';
import { useErrorContext } from '@/contexts/errorCtx';
import { useActiveNameContext } from '@/contexts/activeNameContext';

export default function NameContextDetailsMatchs() {
const api = useApi();
const router = useRouter();

const { id } = useLocalSearchParams<{ id: string }>();
const [isLoading, setLoading] = useState(false);
const { addApiError } = useErrorContext();
const { setContext } = useActiveNameContext();

const [searchValue, setSearchValue] = useState('');
const [currentName, setCurrentName] = useState<{ name: string; description: string; popularity: {}; gender: 'male' | 'female' }>({ name: '', description: '', popularity: {}, gender: 'male' });
Expand All @@ -38,11 +42,17 @@ export default function NameContextDetailsMatchs() {
}, []);

function handleLikeName() {
setLoading(true);
api.patch(`/nameContext/${id}/match`, {
name: currentName.name,
}).then(() => {
}).then((resp) => {
setSearchValue('');
setContext(resp.data);
fetchNewName();
}).catch((err) => {
addApiError(err);
}).finally(() => {
setLoading(false);
});
}

Expand Down
14 changes: 11 additions & 3 deletions contexts/activeNameContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ type ActiveNameContextType = {
id: string;
name: string;
isOwner: boolean;
likedNames: string[];
setContext: (context: Partial<ActiveNameContextType>) => void;
resetContext: () => void;
};
Expand All @@ -12,15 +13,19 @@ const ActiveNameContext = createContext<ActiveNameContextType>({
id: '',
name: '',
isOwner: false,
likedNames: [],
setContext: () => {},
resetContext: () => {},
});

export const ActiveNameProvider = ({ children }: PropsWithChildren<{}>) => {
const [context, setContextState] = useState({
const [context, setContextState] = useState<ActiveNameContextType>({
id: '',
name: '',
likedNames: [],
isOwner: false,
setContext: () => {},
resetContext: () => {},
});

const setContext = (newContext: Partial<ActiveNameContextType>) => {
Expand All @@ -31,11 +36,14 @@ export const ActiveNameProvider = ({ children }: PropsWithChildren<{}>) => {
};

const resetContext = () => {
setContextState({
setContextState((prevContext) => ({
id: '',
name: '',
likedNames: [],
isOwner: false,
});
setContext: prevContext.setContext,
resetContext: prevContext.resetContext,
}));
};

return (
Expand Down
Loading