Skip to content

Commit f48814b

Browse files
authored
Merge pull request #3 from jovnc/feature/populate-tracker-from-repo
Populate dashboard directly from user's progress repo
2 parents 33f5a6c + 807d647 commit f48814b

File tree

3 files changed

+33
-45
lines changed

3 files changed

+33
-45
lines changed

src/Dashboard.tsx

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { Link, useParams } from "react-router";
66
import { Exercise, useGetExercisesQuery } from "./api/queries/get_exercises";
77
import { useGetUserQuery } from "./api/queries/get_user";
88
import { useGetUserProgressQuery } from "./api/queries/get_user_progress";
9-
import { useGetUserUpdateTimeQuery } from "./api/queries/get_user_update_time";
109
import Spinner from "./components/Spinner";
1110

1211
type UserProblemSetStatus = string;
@@ -24,7 +23,7 @@ function Dashboard() {
2423
isLoading: isUserProgressLoading,
2524
isRefetchError: isUserProgressRefetching,
2625
refetch: refetchUserProgress,
27-
} = useGetUserProgressQuery(user?.id);
26+
} = useGetUserProgressQuery(user?.login);
2827

2928
const parsedUserProgress = useMemo(() => {
3029
if (isUserProgressLoading || userProgress == null) {
@@ -74,32 +73,6 @@ function Dashboard() {
7473
await refetchUserProgress()
7574
}, [refetchUserProgress])
7675

77-
const {
78-
data: latestActionRun
79-
} = useGetUserUpdateTimeQuery(user?.id)
80-
81-
const formatTimeWithTimezone = useCallback((dateObj: Date) => {
82-
const formatter = new Intl.DateTimeFormat('en-GB', {
83-
day: '2-digit',
84-
month: 'short',
85-
year: 'numeric',
86-
hour: '2-digit',
87-
minute: '2-digit',
88-
hour12: false,
89-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
90-
});
91-
92-
return formatter.format(dateObj)
93-
}, [])
94-
95-
const expectedNextUpdateTime = useMemo(() => {
96-
if (latestActionRun == null) {
97-
return null
98-
}
99-
const expectedTime = new Date(latestActionRun.getTime() + 30 * 60 * 1000)
100-
return expectedTime
101-
}, [latestActionRun])
102-
10376
return (
10477
<div className="lg:w-[40%] my-16 mx-auto md:w-[60%] w-[80%]">
10578
<h3 className="text-2xl font-bold mb-4">Git Mastery Progress Dashboard</h3>
@@ -115,15 +88,13 @@ function Dashboard() {
11588
<button type="button" className="hover:cursor-pointer" onClick={refreshUserProgress}><MdOutlineRefresh size={24} color="text-gray-500" /></button>
11689
</div>
11790
<p className="text-gray-700 font-semibold">Find your progress for the various Git Mastery exercises.</p>
118-
<p className="text-gray-700">To view all exercises, visit the <a className="text-blue-800 underline" href="https://git-mastery.github.io/exercises">exercises directory</a>.</p>
119-
{latestActionRun != null && expectedNextUpdateTime != null && (
120-
<p className="mt-2 italic">Last updated on {formatTimeWithTimezone(latestActionRun)}.
121-
<br />Next update around {formatTimeWithTimezone(expectedNextUpdateTime)}
122-
<br />If there is a discrepancy, open a ticket with the Git-Mastery team <a className="text-blue-800 underline" href="https://github.com/git-mastery/git-mastery">here</a>
91+
<p className="text-gray-700">To view all exercises, visit the <a className="text-blue-800 underline" href="https://git-mastery.github.io/exercises-directory">exercises directory</a>.</p>
92+
<p className="mt-2 italic">
93+
If there is a discrepancy, open a ticket with the Git-Mastery team <a className="text-blue-800 underline" href="https://github.com/git-mastery/git-mastery">here</a>
12394
</p>
124-
)}
12595
</div>
12696
<div>
97+
{/* TODO: Refactor into components for more modula design */}
12798
{(isUserLoading || isUserProgressLoading || isUserProgressRefetching || isProblemSetsLoading) ? (
12899
<div className="flex justify-center">
129100
<Spinner />
@@ -134,11 +105,26 @@ function Dashboard() {
134105
<p className="mb-4 text-red-700">User <strong>{username}</strong> does not exist</p>
135106
<Link to="/" className="hover:cursor-pointer border-1 border-red-700 bg-red-700 text-white rounded-sm px-4 py-2 font-semibold">← Return to search</Link>
136107
</div>
137-
) : (
108+
) : userProgress == null ? (
109+
<div className="text-center">
110+
<p className="mb-2 text-red-700">
111+
No progress repository found for <strong>{username}</strong>.
112+
</p>
113+
<p className="mb-6 text-red-700">
114+
Ensure that you have enabled remote progress tracking using <code className="bg-gray-100 px-2 py-1">gitmastery progress sync on</code> in the Git-Mastery app.
115+
</p>
116+
<Link
117+
to="/"
118+
className="hover:cursor-pointer border-1 border-red-700 bg-red-700 text-white rounded-sm px-4 py-2 font-semibold"
119+
>
120+
← Return to search
121+
</Link>
122+
</div>
123+
) : (
138124
exerciseGroups.size === 0 ? (
139125
<div className="text-center">
140126
<p className="mb-4">You have not completed any exercises yet</p>
141-
<a href="https://git-mastery.github.io/exercises" target="_blank" className="hover:cursor-pointer border-1 border-blue-800 bg-blue-800 text-white rounded-sm px-4 py-2 font-semibold">Go to exercises directory ↗</a>
127+
<a href="https://git-mastery.github.io/exercises-directory" target="_blank" className="hover:cursor-pointer border-1 border-blue-800 bg-blue-800 text-white rounded-sm px-4 py-2 font-semibold">Go to exercises directory ↗</a>
142128
</div>
143129
) : (
144130
Array.from(exerciseGroups)
@@ -158,7 +144,7 @@ function Dashboard() {
158144
.filter(exercise => parsedUserProgress.has(exercise.exercise_name))
159145
.map((exercise, idx) => (
160146
<tr key={idx}>
161-
<td className="border border-gray-300 px-4 py-2 text-left"><a target="_blank" href={`https://git-mastery.github.io/exercises/${exercise.exercise_name.replace("-", "_")}`}><code className="underline text-blue-800">{exercise.exercise_name}</code></a></td>
147+
<td className="border border-gray-300 px-4 py-2 text-left"><a target="_blank" href={`https://git-mastery.github.io/exercises-directory#exercise-${exercise.exercise_name}`}><code className="underline text-blue-800">{exercise.exercise_name}</code></a></td>
162148
<td className="border border-gray-300 px-4 py-2 text-left">{parsedUserProgress.get(exercise.exercise_name)}</td>
163149
</tr>
164150
))}

src/api/queries/get_user.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import axios from "axios"
22
import { useQuery } from "react-query"
33

44
export interface User {
5-
id: number;
5+
login: string;
66
}
77

88
export const getUser = async (username: string) => {
99
try {
10-
const user = await axios.get<User>(`https://api.github.com/users/${username}`)
10+
const encodedUsername = encodeURIComponent(username);
11+
const user = await axios.get<User>(`https://api.github.com/users/${encodedUsername}`)
1112
return user.data
1213
} catch {
1314
return null

src/api/queries/get_user_progress.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ export interface UserProgress {
66
status: string;
77
}
88

9-
export const getUserProgress = async (userId: number) => {
9+
export const getUserProgress = async (username: string) => {
1010
try {
11-
const result = await axios.get<UserProgress[]>(`https://raw.githubusercontent.com/git-mastery/progress/refs/heads/tracker/students/${userId}.json`);
11+
const encodedUsername = encodeURIComponent(username);
12+
const result = await axios.get<UserProgress[]>(`https://raw.githubusercontent.com/${encodedUsername}/${encodedUsername}-gitmastery-progress/refs/heads/main/progress.json`);
1213
return result.data;
1314
} catch {
1415
return null;
1516
}
1617
}
1718

18-
export const useGetUserProgressQuery = (userId: number | undefined) => {
19+
export const useGetUserProgressQuery = (username: string | undefined) => {
1920
return useQuery<UserProgress[] | null>({
20-
queryKey: ["get-user-progress", userId],
21-
queryFn: () => getUserProgress(userId!),
22-
enabled: userId != null,
21+
queryKey: ["get-user-progress", username],
22+
queryFn: () => getUserProgress(username!),
23+
enabled: username != null,
2324
});
2425
}
2526

0 commit comments

Comments
 (0)