Skip to content

Commit

Permalink
Merge pull request #97 from FYP-2024-IQMA/SCRUM-170-Create-Frontend-f…
Browse files Browse the repository at this point in the history
…or-All-Badges-and-Integrate-with-Backend

SCRUM-170 Create frontend for all badges
  • Loading branch information
germainetan authored Oct 21, 2024
2 parents 134ca70 + d6356b5 commit 84a0b5d
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 10 deletions.
202 changes: 202 additions & 0 deletions frontend/iQMA-Skills-Builder/app/Achievements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import {
Text,
View,
TextInput,
TouchableOpacity,
StyleSheet,
ScrollView,
Image,
} from 'react-native';
import {useState, useContext, useEffect} from 'react';
import {AuthContext} from '@/context/AuthContext';
import {LoadingIndicator} from '@/components/LoadingIndicator';
import * as gamificationEndpoints from '@/helpers/gamificationEndpoints';
import {Colors} from '@/constants/Colors';
import { formatSection } from '@/helpers/formatSectionID';

export default function Achievements() {
const {currentUser} = useContext(AuthContext);
const [badges, setBadges] = useState<any[]>([]);
const [loading, setLoading] = useState<boolean>(true);

const mock = [
{
sectionID: 'SEC0001',
badges: [
{
unitName: 'Foundations of Communication',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/placeholder.png',
},
{
unitName: 'Written Communication Proficiency',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/placeholder.png',
},
{
unitName: 'Visual Communication Strategies',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/placeholder.png',
},
{
unitName: 'Stakeholder Analysis and Audience Engagement',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/placeholder.png',
},
{
unitName: 'Interpersonal Communication Excellence',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/SEC0001/unit3.png',
},
{
unitName: 'Mastering Two-Way Communication',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/SEC0001/unit2.png',
},
{
unitName: 'The Art of Persuasion',
badgeUrl:
"https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/locked.png",
},
],
},
{
sectionID: 'SEC0002',
badges: [
{
unitName: 'Foundations of Communication',
badgeUrl:
'https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/placeholder.png',
},
{
unitName: 'Written Communication Proficiency',
badgeUrl:
"https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/locked.png",
},
{
unitName: 'Visual Communication Strategies',
badgeUrl:
"https://lugppkebziopzwushqcg.supabase.co/storage/v1/object/public/badges/locked.png",
},
],
},
];

const fetchAchievements = async () => {
try {
const badges = await gamificationEndpoints.getBadges(
currentUser.sub
);

setBadges(badges);

console.log(badges);
} catch (error) {
console.error('Error fetching achievements', error);
} finally {
setLoading(false);
}
};

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

if (loading) {
return <LoadingIndicator />;
}

return (
<ScrollView style={styles.container}>
<View>
{badges.map((section) => (
<>
<View style={styles.sectionContainer}>
<Text style={styles.sectionHeading}>
{/* {section.sectionID} */}
Section {formatSection(section.sectionID)}
</Text>
<View
key={section.sectionID}
style={styles.badgeOuterContainer}
>
{section.badges.map(
(badge: {
badgeUrl: string;
unitName: string;
}) => (
<View style={styles.badgeContainer}>
<Image
source={{uri: badge.badgeUrl}}
style={styles.badgeImage}
/>
{/* <Text style={styles.unlockedBadgeText}> */}
<Text
style={
badge.badgeUrl.endsWith(
'locked.png'
)
? styles.lockedBadgeText
: styles.unlockedBadgeText
}
>
{badge.unitName}
</Text>
</View>
)
)}
</View>
</View>
</>
))}
</View>
</ScrollView>
);
}

const styles = StyleSheet.create({
container: {
// flex: 1,
// padding: 20,
paddingHorizontal: 20,
},
sectionContainer: {
marginTop: 20,
},
sectionHeading: {
color: Colors.light.color,
fontWeight: 'bold',
fontSize: 16,
textAlign: "center"
},
badgeOuterContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
marginTop: 10,
// backgroundColor: 'red',
},
badgeImage: {
width: '100%',
aspectRatio: 1,
resizeMode: 'contain',
},
badgeContainer: {
width: '30%',
marginBottom: 20,
alignItems: 'center',
},
unlockedBadgeText: {
marginTop: 10,
textAlign: 'center',
// color: Colors.light.text,
color: Colors.default.purple500,
fontWeight: 'bold',
},
lockedBadgeText: {
marginTop: 10,
textAlign: 'center',
color: Colors.light.text,
fontWeight: 'bold',
},
});
10 changes: 10 additions & 0 deletions frontend/iQMA-Skills-Builder/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,16 @@ export default function RootLayout() {
headerTintColor: Colors.light.background
}}
/>
<Stack.Screen
name="Achievements"
options={{
headerTitle: "Achievements",
headerStyle: {
backgroundColor: Colors.default.purple100,
},
headerTintColor: Colors.light.background
}}
/>
</Stack>
</AuthProvider>
</Auth0Provider>
Expand Down
43 changes: 34 additions & 9 deletions frontend/iQMA-Skills-Builder/components/Achievement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
FlatList,
} from 'react-native';
import {OverviewCard} from '@/components/OverviewCard';
import {router} from 'expo-router';

interface AchievementsProps {
achievements: any[];
}

export const Achievements: React.FC<AchievementsProps> = ({achievements}) => {
// console.log('achievements:', achievements);
console.log('achievements:', achievements);

let topThreeAchievements: any[] = [];

Expand All @@ -26,18 +27,37 @@ export const Achievements: React.FC<AchievementsProps> = ({achievements}) => {
);
}

const handlePress = () => {
router.push("Achievements");
};

// console.log('topThreeAchievements:', topThreeAchievements);
return (
<View style={styles.outerContainer}>
<Text
style={[
styles.achievementsHeader,
topThreeAchievements.length === 0 &&
styles.achievementsError,
]}
<View
style={{flexDirection: 'row', justifyContent: 'space-between'}}
>
Achievements
</Text>
<Text
style={[
styles.achievementsHeader,
topThreeAchievements.length === 0 &&
styles.achievementsError,
]}
>
Achievements
</Text>
<TouchableOpacity onPress={handlePress}>
<Text
style={{
textDecorationLine: 'underline',
textDecorationColor: '#5C5776',
fontWeight: 'bold',
}}
>
View all
</Text>
</TouchableOpacity>
</View>
{topThreeAchievements.length === 0 && (
<OverviewCard
text="Sorry, our system is currently under maintenance."
Expand Down Expand Up @@ -74,6 +94,11 @@ const styles = StyleSheet.create({
paddingHorizontal: 20,
marginTop: 20,
},
header: {
fontSize: 16,
fontWeight: 'bold',
color: '#18113C',
},
achievementsHeader: {
fontSize: 16,
fontWeight: 'bold',
Expand Down
2 changes: 1 addition & 1 deletion frontend/iQMA-Skills-Builder/context/AuthContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export const AuthProvider = ({children}: {children: React.ReactNode}) => {
} else {
// await AsyncStorage.removeItem('userID');
await AsyncStorage.clear();
setIsLoading(false);
// setIsLoading(false);
}
setIsLoading(false);
};
Expand Down

0 comments on commit 84a0b5d

Please sign in to comment.