Skip to content

Instantly share code, notes, and snippets.

@bryantee
Created November 18, 2025 16:26
Show Gist options
  • Select an option

  • Save bryantee/6aae82ead381f1e49d71a91e6b94b7b4 to your computer and use it in GitHub Desktop.

Select an option

Save bryantee/6aae82ead381f1e49d71a91e6b94b7b4 to your computer and use it in GitHub Desktop.
FE Interview Coding Exercise
/**
* CODING EXERCISE: Organization Engagement Report
*
* BUGS:
* 1. The engagement summary does not update when the activity range is changed.
* 2. The select component and label are not properly associated for accessibility.
*
* IMPROVEMENTS:
* 1. How could we handle error states in the UI?
* 2. What about loading states?
*
* REFACTOR OPPORTUNITIES:
* - How could we make the component more modular or reusable?
* - What is another way to manage the network request lifecycle?
*
* BONUS: How would you handle cancelling the fetch request if the component unmounts before it completes?
*/
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);
useEffect(() => {
fetchOrgEngagementSummary(orgId, range)
.then((data) => {
setSummary(data)
})
.catch(() => {
})
.finally(() => {
});
// What happens if orgId or range changes quickly, or this component unmounts?
}, []);
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 style={{ display: "block", marginBottom: 12, fontSize: 13 }}>
Activity Range
</label>
<select
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>
{summary && (
<div>
<div style={{ marginBottom: 8 }}>
<strong>{summary.teacherMaterialsAccessed}</strong> Teacher Materials Accessed
</div>
<div style={{ marginBottom: 8 }}>
<strong>{summary.studentMaterialsAccessed}</strong> Student Materials Accessed
</div>
</div>
)}
</section>
);
}
// Simulated network request function
function fetchOrgEngagementSummary(
orgId: string,
range: ActivityRange
): Promise<OrgEngagementSummary> {
return new Promise((resolve) => {
setTimeout(() => {
resolve({
teacherMaterialsAccessed: Math.floor(Math.random() * 1000),
studentMaterialsAccessed: Math.floor(Math.random() * 5000),
});
}, 1000);
});
}

Comments are disabled for this gist.