From 0bcda28e6af6f06f3372923aed8429dce5696947 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Sat, 16 May 2026 20:13:33 +1000 Subject: [PATCH 01/10] Integrate performance scoring endpoint into frontend --- guard_app/src/api/guardScore.ts | 41 ++++++++++++++++++++++++++ guard_app/src/screen/HomeScreen.tsx | 21 ++++++++++++- guard_app/src/screen/ProfileScreen.tsx | 28 ++++++++++++++++-- 3 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 guard_app/src/api/guardScore.ts diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts new file mode 100644 index 000000000..8a50f6395 --- /dev/null +++ b/guard_app/src/api/guardScore.ts @@ -0,0 +1,41 @@ +import axios from 'axios'; + +import http from '../lib/http'; + +export type GuardScore = { + guardId?: string; + score?: number; + rating?: number; + performanceScore?: number; + currentRating?: number; + completedShifts?: number; + totalShifts?: number; + attendanceRate?: number; + punctualityRate?: number; + summary?: string; + message?: string; +}; + +export async function getGuardScore(guardId: string): Promise { + if (!guardId || guardId === 'undefined' || guardId === 'null') { + throw new Error('Missing valid guardId for score request'); + } + + try { + const { data } = await http.get(`/users/guards/${guardId}/score`); + return data; + } catch (error) { + console.log('FULL SCORE ERROR:', error); + + if (axios.isAxiosError(error)) { + console.log('STATUS:', error.response?.status); + console.log('DATA:', error.response?.data); + } + + throw new Error( + `Failed to fetch guard score (${ + axios.isAxiosError(error) ? error.response?.status : 'unknown' + })` + ); + } +} \ No newline at end of file diff --git a/guard_app/src/screen/HomeScreen.tsx b/guard_app/src/screen/HomeScreen.tsx index 350e7c240..e0e64171b 100644 --- a/guard_app/src/screen/HomeScreen.tsx +++ b/guard_app/src/screen/HomeScreen.tsx @@ -5,6 +5,8 @@ import { useFocusEffect, useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useCallback, useLayoutEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { getGuardScore, GuardScore } from '../api/guardScore'; +import { getUserProfile } from '../api/profile'; import { Button, Dimensions, @@ -124,6 +126,7 @@ export default function HomeScreen() { const [todayShifts, setTodayShifts] = useState([]); const [upcomingShifts, setUpcomingShifts] = useState([]); const [refreshing, setRefreshing] = useState(false); + const [guardScore, setGuardScore] = useState(null); useLayoutEffect(() => { navigation.setOptions({ @@ -171,6 +174,16 @@ export default function HomeScreen() { try { const { data: u } = await http.get('/users/me'); setUser(u); + try { + const profile = await getUserProfile(); + const guardId = profile?._id; + if (guardId) { + const score = await getGuardScore(guardId); + setGuardScore(score); + } + } catch (scoreErr) { + console.log('Score error:', scoreErr); + } const { data: myShifts } = await http.get('/shifts/myshifts'); @@ -253,7 +266,13 @@ export default function HomeScreen() { } label={t('home.currentRating')} - value={metrics.rating} + value={ + guardScore?.rating + ? guardScore.rating.toFixed(1) + : guardScore?.score + ? guardScore.score.toFixed(1) + : '0.0' + } extraStyle={styles.tintPurple} colors={colors} /> diff --git a/guard_app/src/screen/ProfileScreen.tsx b/guard_app/src/screen/ProfileScreen.tsx index 879ae80fc..0c5142761 100644 --- a/guard_app/src/screen/ProfileScreen.tsx +++ b/guard_app/src/screen/ProfileScreen.tsx @@ -16,6 +16,7 @@ import { } from 'react-native'; import { getUserProfile } from '../api/profile'; +import { getGuardScore, GuardScore } from '../api/guardScore'; import { LocalStorage } from '../lib/localStorage'; import { LicenseStatus } from '../models/License'; import { UserProfile } from '../models/UserProfile'; @@ -31,6 +32,7 @@ export default function ProfileScreen({ navigation, route }: any) { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [profileImage, setProfileImage] = useState(null); + const [guardScore, setGuardScore] = useState(null); const handleEditProfile = () => { navigation.navigate('EditProfile', { userProfile: data }); @@ -53,6 +55,22 @@ export default function ProfileScreen({ navigation, route }: any) { const profile = await getUserProfile(); setData(profile); + console.log('PROFILE:', profile); + +const guardId = profile?._id; + +console.log('GUARD ID:', guardId); + +if (guardId) { + try { + const score = await getGuardScore(guardId); + console.log('GUARD SCORE:', score); + setGuardScore(score); + } catch (scoreError) { + console.log('GUARD SCORE ERROR:', scoreError); + } +} + } catch (e: any) { setError(e?.message || 'Failed to load profile'); } finally { @@ -153,12 +171,18 @@ export default function ProfileScreen({ navigation, route }: any) { - 140 + + {guardScore?.totalShifts ?? 0} + {t('profile.totalShifts')} - {data?.rating ? data.rating.toFixed(1) : '0.0'} + {guardScore?.rating + ? guardScore.rating.toFixed(1) + : guardScore?.score + ? guardScore.score.toFixed(1) + : '0.0'} {t('profile.rating')} From acf28470b582e1d62e4df99989e12140963291c0 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Sat, 16 May 2026 20:33:18 +1000 Subject: [PATCH 02/10] Fix formatting for performance score integration --- guard_app/src/api/guardScore.ts | 4 +-- guard_app/src/screen/ProfileScreen.tsx | 35 +++++++++++--------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index 8a50f6395..a010f1fa8 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -35,7 +35,7 @@ export async function getGuardScore(guardId: string): Promise { throw new Error( `Failed to fetch guard score (${ axios.isAxiosError(error) ? error.response?.status : 'unknown' - })` + })`, ); } -} \ No newline at end of file +} diff --git a/guard_app/src/screen/ProfileScreen.tsx b/guard_app/src/screen/ProfileScreen.tsx index 0c5142761..8a6797dd1 100644 --- a/guard_app/src/screen/ProfileScreen.tsx +++ b/guard_app/src/screen/ProfileScreen.tsx @@ -55,22 +55,17 @@ export default function ProfileScreen({ navigation, route }: any) { const profile = await getUserProfile(); setData(profile); - console.log('PROFILE:', profile); -const guardId = profile?._id; - -console.log('GUARD ID:', guardId); - -if (guardId) { - try { - const score = await getGuardScore(guardId); - console.log('GUARD SCORE:', score); - setGuardScore(score); - } catch (scoreError) { - console.log('GUARD SCORE ERROR:', scoreError); - } -} + const guardId = profile?._id; + if (guardId) { + try { + const score = await getGuardScore(guardId); + setGuardScore(score); + } catch (scoreError) { + console.log('GUARD SCORE ERROR:', scoreError); + } + } } catch (e: any) { setError(e?.message || 'Failed to load profile'); } finally { @@ -172,17 +167,17 @@ if (guardId) { - {guardScore?.totalShifts ?? 0} - + {guardScore?.totalShifts ?? 0} + {t('profile.totalShifts')} {guardScore?.rating - ? guardScore.rating.toFixed(1) - : guardScore?.score - ? guardScore.score.toFixed(1) - : '0.0'} + ? guardScore.rating.toFixed(1) + : guardScore?.score + ? guardScore.score.toFixed(1) + : '0.0'} {t('profile.rating')} From fa3098adc11baf3d32d0e3e800dbb76f4e853438 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Mon, 18 May 2026 20:53:30 +1000 Subject: [PATCH 03/10] Fix guard score API response handling --- guard_app/src/api/guardScore.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index a010f1fa8..cb053e833 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -22,8 +22,11 @@ export async function getGuardScore(guardId: string): Promise { } try { - const { data } = await http.get(`/users/guards/${guardId}/score`); - return data; + const response = await http.get<{ success: boolean; data: GuardScore }>( + `/users/guards/${guardId}/score` +); + +return response.data.data; } catch (error) { console.log('FULL SCORE ERROR:', error); From 06b5d2752c803765a15685212c377f5e0be43aa5 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Mon, 18 May 2026 21:00:13 +1000 Subject: [PATCH 04/10] Fix guard score API response --- guard_app/src/api/guardScore.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index cb053e833..492d3d64a 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -22,11 +22,11 @@ export async function getGuardScore(guardId: string): Promise { } try { - const response = await http.get<{ success: boolean; data: GuardScore }>( - `/users/guards/${guardId}/score` -); + const response = await http.get<{ success: boolean; data: GuardScore }>( + `/users/guards/${guardId}/score` + ); -return response.data.data; + return response.data.data; } catch (error) { console.log('FULL SCORE ERROR:', error); @@ -36,8 +36,7 @@ return response.data.data; } throw new Error( - `Failed to fetch guard score (${ - axios.isAxiosError(error) ? error.response?.status : 'unknown' + `Failed to fetch guard score (${axios.isAxiosError(error) ? error.response?.status : 'unknown' })`, ); } From e46f747a487957a0b3a5e505a5684d8607e75927 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Mon, 18 May 2026 21:07:49 +1000 Subject: [PATCH 05/10] Fix guard score API response --- guard_app/src/api/guardScore.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index 492d3d64a..34e6aa59c 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -23,7 +23,7 @@ export async function getGuardScore(guardId: string): Promise { try { const response = await http.get<{ success: boolean; data: GuardScore }>( - `/users/guards/${guardId}/score` + `/users/guards/${guardId}/score`, ); return response.data.data; @@ -36,7 +36,8 @@ export async function getGuardScore(guardId: string): Promise { } throw new Error( - `Failed to fetch guard score (${axios.isAxiosError(error) ? error.response?.status : 'unknown' + `Failed to fetch guard score (${ + axios.isAxiosError(error) ? error.response?.status : 'unknown' })`, ); } From 977b071b2c1065a083eb5f3ef72b91f7f532eff5 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Wed, 20 May 2026 20:10:51 +1000 Subject: [PATCH 06/10] Refactor guard score fetching logic --- guard_app/src/api/guardScore.ts | 13 +++++++++---- guard_app/src/screen/HomeScreen.tsx | 10 ++++------ guard_app/src/screen/ProfileScreen.tsx | 13 +++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index 34e6aa59c..b96336220 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -28,11 +28,7 @@ export async function getGuardScore(guardId: string): Promise { return response.data.data; } catch (error) { - console.log('FULL SCORE ERROR:', error); - if (axios.isAxiosError(error)) { - console.log('STATUS:', error.response?.status); - console.log('DATA:', error.response?.data); } throw new Error( @@ -42,3 +38,12 @@ export async function getGuardScore(guardId: string): Promise { ); } } +export async function fetchGuardScore(guardId?: string): Promise { + if (!guardId) return null; + + try { + return await getGuardScore(guardId); + } catch { + return null; + } +} diff --git a/guard_app/src/screen/HomeScreen.tsx b/guard_app/src/screen/HomeScreen.tsx index e0e64171b..cc5113a70 100644 --- a/guard_app/src/screen/HomeScreen.tsx +++ b/guard_app/src/screen/HomeScreen.tsx @@ -5,7 +5,7 @@ import { useFocusEffect, useNavigation } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { useCallback, useLayoutEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { getGuardScore, GuardScore } from '../api/guardScore'; +import { fetchGuardScore, GuardScore } from '../api/guardScore'; import { getUserProfile } from '../api/profile'; import { Button, @@ -177,13 +177,11 @@ export default function HomeScreen() { try { const profile = await getUserProfile(); const guardId = profile?._id; - if (guardId) { - const score = await getGuardScore(guardId); + const score = await fetchGuardScore(guardId); + if (score) { setGuardScore(score); } - } catch (scoreErr) { - console.log('Score error:', scoreErr); - } + } catch (scoreErr) {} const { data: myShifts } = await http.get('/shifts/myshifts'); diff --git a/guard_app/src/screen/ProfileScreen.tsx b/guard_app/src/screen/ProfileScreen.tsx index 8a6797dd1..0d741d7eb 100644 --- a/guard_app/src/screen/ProfileScreen.tsx +++ b/guard_app/src/screen/ProfileScreen.tsx @@ -16,7 +16,7 @@ import { } from 'react-native'; import { getUserProfile } from '../api/profile'; -import { getGuardScore, GuardScore } from '../api/guardScore'; +import { fetchGuardScore, GuardScore } from '../api/guardScore'; import { LocalStorage } from '../lib/localStorage'; import { LicenseStatus } from '../models/License'; import { UserProfile } from '../models/UserProfile'; @@ -58,13 +58,10 @@ export default function ProfileScreen({ navigation, route }: any) { const guardId = profile?._id; - if (guardId) { - try { - const score = await getGuardScore(guardId); - setGuardScore(score); - } catch (scoreError) { - console.log('GUARD SCORE ERROR:', scoreError); - } + const score = await fetchGuardScore(guardId); + + if (score) { + setGuardScore(score); } } catch (e: any) { setError(e?.message || 'Failed to load profile'); From d37b610e516b0fb9fdfd73757046e8d727279199 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Wed, 20 May 2026 20:19:40 +1000 Subject: [PATCH 07/10] Address guard score review comments --- guard_app/src/api/guardScore.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index b96336220..797bfa102 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -28,9 +28,6 @@ export async function getGuardScore(guardId: string): Promise { return response.data.data; } catch (error) { - if (axios.isAxiosError(error)) { - } - throw new Error( `Failed to fetch guard score (${ axios.isAxiosError(error) ? error.response?.status : 'unknown' @@ -38,6 +35,7 @@ export async function getGuardScore(guardId: string): Promise { ); } } + export async function fetchGuardScore(guardId?: string): Promise { if (!guardId) return null; From a64393ca21ed131e21306aa5fd361036b510ed13 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Wed, 20 May 2026 20:33:15 +1000 Subject: [PATCH 08/10] Fix ESLint error in HomeScreen --- guard_app/src/screen/HomeScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guard_app/src/screen/HomeScreen.tsx b/guard_app/src/screen/HomeScreen.tsx index cc5113a70..1fe888c15 100644 --- a/guard_app/src/screen/HomeScreen.tsx +++ b/guard_app/src/screen/HomeScreen.tsx @@ -181,7 +181,7 @@ export default function HomeScreen() { if (score) { setGuardScore(score); } - } catch (scoreErr) {} + } catch {} const { data: myShifts } = await http.get('/shifts/myshifts'); From 8a07ffb8a742e91e13a412d4332ddc2e25cca20b Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Wed, 20 May 2026 20:38:26 +1000 Subject: [PATCH 09/10] Fix HomeScreen empty catch block --- guard_app/src/screen/HomeScreen.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/guard_app/src/screen/HomeScreen.tsx b/guard_app/src/screen/HomeScreen.tsx index 1fe888c15..952614bef 100644 --- a/guard_app/src/screen/HomeScreen.tsx +++ b/guard_app/src/screen/HomeScreen.tsx @@ -181,7 +181,9 @@ export default function HomeScreen() { if (score) { setGuardScore(score); } - } catch {} + } catch { + setGuardScore(null); + } const { data: myShifts } = await http.get('/shifts/myshifts'); From 6fd8d6cc433abea2b7f1feaa968bf423bbd51c76 Mon Sep 17 00:00:00 2001 From: abrar-deakin Date: Sun, 24 May 2026 01:02:51 +1000 Subject: [PATCH 10/10] Fix GuardScore type and score rendering --- guard_app/src/api/guardScore.ts | 26 ++++++++++---------------- guard_app/src/screen/HomeScreen.tsx | 8 +------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/guard_app/src/api/guardScore.ts b/guard_app/src/api/guardScore.ts index 797bfa102..27d3c6e44 100644 --- a/guard_app/src/api/guardScore.ts +++ b/guard_app/src/api/guardScore.ts @@ -1,30 +1,24 @@ import axios from 'axios'; - import http from '../lib/http'; -export type GuardScore = { - guardId?: string; - score?: number; - rating?: number; - performanceScore?: number; - currentRating?: number; - completedShifts?: number; - totalShifts?: number; - attendanceRate?: number; - punctualityRate?: number; - summary?: string; - message?: string; +type ApiGuardScore = { + guardId: string; + score: number; + breakdown: unknown; // exists in API, not in use }; +export type GuardScore = Pick; + export async function getGuardScore(guardId: string): Promise { if (!guardId || guardId === 'undefined' || guardId === 'null') { throw new Error('Missing valid guardId for score request'); } try { - const response = await http.get<{ success: boolean; data: GuardScore }>( - `/users/guards/${guardId}/score`, - ); + const response = await http.get<{ + success: boolean; + data: ApiGuardScore; + }>(`/users/guards/${guardId}/score`); return response.data.data; } catch (error) { diff --git a/guard_app/src/screen/HomeScreen.tsx b/guard_app/src/screen/HomeScreen.tsx index 952614bef..068cfa14e 100644 --- a/guard_app/src/screen/HomeScreen.tsx +++ b/guard_app/src/screen/HomeScreen.tsx @@ -266,13 +266,7 @@ export default function HomeScreen() { } label={t('home.currentRating')} - value={ - guardScore?.rating - ? guardScore.rating.toFixed(1) - : guardScore?.score - ? guardScore.score.toFixed(1) - : '0.0' - } + value={guardScore?.score != null ? guardScore.score.toFixed(1) : '0.0'} extraStyle={styles.tintPurple} colors={colors} />