Skip to content

Instantly share code, notes, and snippets.

@bryantee
Created November 18, 2025 19:48
Show Gist options
  • Select an option

  • Save bryantee/600d73e3ec106c33e784e0cdb591136c to your computer and use it in GitHub Desktop.

Select an option

Save bryantee/600d73e3ec106c33e784e0cdb591136c to your computer and use it in GitHub Desktop.
FE Interview Coding Exercise Solution
import React, { useEffect, useState } from "react";
type ActivityRange = "CURRENT_SCHOOL_YEAR" | "LAST_30_DAYS";
interface OrgEngagementSummary {
teacherMaterialsAccessed: number;
studentMaterialsAccessed: number;
}
interface OrgEngagementMetricsProps {
orgId: string;
}
export function OrgEngagementMetrics({ orgId }: OrgEngagementMetricsProps) {
const [range, setRange] = useState<ActivityRange>("CURRENT_SCHOOL_YEAR");
const [summary, setSummary] = useState<OrgEngagementSummary | null>(null);
/**
* Setup state for tracking error and loading states
*/
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(false);
useEffect(() => {
/**
* Initialize loading and error states before fetching data
*/
setLoading(true);
setError(null);
/**
* Setup AbortController to cancel fetch if component unmounts or params change
*/
const abortController = new AbortController();
/**
* Could elect to either swap API call with a library like SWR or React Query for better data fetching management.
* Or refactor into a custom hook that manages loading, error, and data states.
*/
fetchOrgEngagementSummary(orgId, range, abortController.signal)
.then((data) => {
setSummary(data)
})
.catch(() => {
/**
* Set error state if the fetch fails
*/
setError("Failed to fetch engagement summary.");
})
.finally(() => {
/**
* Reset loading state after fetch completes
*/
setLoading(false);
});
return () => {
/**
* Cleanup function to abort fetch on unmount or param change
*/
abortController.abort();
}
/**
* Add orgId and range to dependency array to refetch data when they change 👇
*/
}, [orgId, range]);
return (
<section style={{ padding: 16, border: "1px solid #eee", borderRadius: 8 }}>
<header style={{ marginBottom: 12 }}>
<h2>Engagement Summary</h2>
<div>
Hogwarts School of Witchcraft and Wizardry
</div>
</header>
<div>
<label
htmlFor="activity-range-select" // Associate label with form element using `htmlFor` attribute
style={{ display: "block", marginBottom: 12, fontSize: 13 }}
>
Activity Range
</label>
<select
id="activity-range-select" // Add id to select for accessibility
value={range}
onChange={(e) => setRange(e.target.value as ActivityRange)}
style={{ marginLeft: 8 }}
>
<option value="CURRENT_SCHOOL_YEAR">Current School Year</option>
<option value="LAST_30_DAYS">Last 30 Days</option>
</select>
</div>
/**
* Handles loading and error states in the UI.
* Conditionally renders loading indicator, error message, or summary data.
*
* Optionally, could elect to:
* - Show a toast for errors
* - Disable the select while loading
* - Use a skeleton loader for better UX
*/
{loading && <div>Loading...</div>}
{error && <div style={{ color: 'red' }}>{error}</div>}
{summary && !loading && !error && (
<div>
<MetricCard
title="Teacher Materials Accessed"
value={summary.teacherMaterialsAccessed}
/>
<MetricCard
title="Student Materials Accessed"
value={summary.studentMaterialsAccessed}
/>
</div>
)}
</section>
);
}
/**
* Refactor out metric card into its own component for reusability and cleaner code
*/
function MetricCard(props: { title: string; value: number }) {
return (
<div style={{ marginBottom: 8 }}>
<strong>{props.value}</strong> {props.title}
</div>
);
}
// Simulated network request function
function fetchOrgEngagementSummary(
orgId: string,
range: ActivityRange,
abortSignal: AbortSignal = new AbortController().signal // Pass the abort signal to the fetch request (if using fetch API)
): Promise<OrgEngagementSummary> {
return fetch(`/api/orgs/${orgId}/engagement-summary?range=${range}`, { signal: abortSignal })
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((data) => {
return {
teacherMaterialsAccessed: data.teacherMaterialsAccessed,
studentMaterialsAccessed: data.studentMaterialsAccessed,
};
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment