Skip to content

Newcomer workshop

Mariana Almeida edited this page Mar 13, 2026 · 10 revisions

Welcome! This workshop gets you inside the TTS codebase by fixing three real bugs that were introduced on purpose. Each bug teaches you a core React concept. By the end you will have used useState, useEffect, and a custom hook with useSWR.

Before starting, read the File Structure page — especially the React primer at the top.


Setup

Follow the full setup in Running the project. The short version:

# 1. Clone the repo (if you haven't already)
git clone git@github.com:NIAEFEUP/tts-fe.git
cd tts-fe

# 2. Switch to the workshop branch
git checkout newcomer-workshop-2025

# 3. Copy the env file
cp .env.example .env
# Set VITE_APP_BACKEND_URL=https://tts-dev.niaefeup.pt/api and VITE_APP_FEDERATED_AUTH=0

# 4. Run the app
npm install
npm run dev

Open http://localhost:3100 in your browser. The app loads but three things are broken. Your job is to find and fix them.


Bug 1 — Switching between options does nothing

The planner lets you have multiple timetable "options" (Option 1, Option 2, …). Clicking a different option should update the schedule on screen. Right now nothing changes — it always shows the first option.

Hint 1

Open src/contexts/CombinedProvider.tsx and look for where selectedOption is defined.

Hint 2

selectedOption should be a piece of React state created with useState. Check if it actually is, or if it has been replaced with something else.

Hint 3

A useState call looks like this:

const [value, setValue] = useState(initialValue)

The initial value should come from StorageAPI.getSelectedOptionStorage().

Concept practised: useState — how React tracks values that change over time.


Bug 2 — The course list is always empty

When you open "Unidades Curriculares" and select a course (major), no course units appear. The list stays empty regardless of what you pick.

Hint 1

Open src/components/planner/sidebar/sessionController/CoursePicker.tsx. Find the line that defines courseUnits and loadingCourseUnits. What is it currently returning?

Hint 2

It should be calling a custom hook named useCourseUnits. Check src/hooks/ — does that file exist?

Hint 3

You need to create src/hooks/useCourseUnits.tsx. It should use useSWR to call getCoursesByMajorId(id) from the API. Look at src/hooks/useVerifyCourseUnitHashes.tsx for an example of how useSWR is used.

Hint 4

Once the hook exists, import it in CoursePicker.tsx and replace the static [[], false] with the real hook call:

const { courseUnits, loading: loadingCourseUnits } = useCourseUnits(selectedMajor ? selectedMajor.id : null)

Concept practised: Custom hooks and useSWR — how React fetches data from a backend.


Bug 3 — The option name doesn't update when switching options

When you switch between options, the name shown in the input (e.g. "Option 1", "Option 2") stays stuck on the name of whichever option was active when the page loaded.

Hint 1

Open src/components/planner/sidebar/SelectedOptionController.tsx. Find where optionName is defined with useState.

Hint 2

optionName is initialised once when the component mounts, but it's never updated afterwards. You need to add something that re-syncs it whenever the selected option changes. Which React hook runs code in response to a value changing?

Hint 3

A useEffect with dependencies looks like this:

useEffect(() => {
  // runs whenever dep1 or dep2 changes
}, [dep1, dep2])

Inside the effect, call setOptionName(multipleOptions[selectedOption].name). The dependencies should be selectedOption and multipleOptions.

Concept practised: useEffect — how React keeps derived values in sync when state changes.


Done?

If all three bugs are fixed:

  • Switching options updates the schedule
  • Selecting a major shows its course units
  • Switching options updates the name in the input

Well done! Have a look at the File Structure page for a deeper tour of the codebase, and check out the Contributing guide when you're ready to open your first PR.

Clone this wiki locally