Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.1.5] - 2026-02-09

### Added

- Class-aware state foundations: `Classroom` model support, class utilities (`lib/classes.ts`), and class-focused storage/test coverage.
- Shared `ClassSelector` component for class selection across students, generator, play, breakout rooms, and projects.
- Unified quiz editor test coverage for form + import workflows (`components/quizzes/__tests__/quiz-editor-form.test.tsx`).
- Shared select wrapper tests for popup alignment defaults (`components/ui/__tests__/select.test.tsx`).

### Changed

- Student workflow expanded to class-first management: create/select classes, import full class rosters, and manage students in the active class.
- Generator, quiz play, breakout groups, and project lists now run with active-class scoping.
- Quiz editing/import flow consolidated into `QuizEditorForm`; legacy `quiz-import-card` removed.
- Quiz question list card behavior refined for better overflow/height handling.
- Shared `SelectContent` now defaults to popper-style content-fit behavior and supports explicit trigger-aligned positioning via `alignItemWithTrigger={true}` where needed.
- App version updated to `1.1.5` in `package.json`.
- Sidebar version label now reads version dynamically from `package.json` via server layout prop wiring.
- Dependency/version refresh from the `main..HEAD` baseline commits (including `package.json` and `bun.lock` updates from `e9d61c2`).

### Tests

- Expanded reducer/storage/type-guard coverage for class-aware persistence and migration paths.
- Added class utility tests (`lib/__tests__/classes.test.ts`) and updated student/reducer expectations.
- Added select alignment behavior tests in `components/ui/__tests__/select.test.tsx`.

### Documentation

- Updated README and project docs for class-scoped workflows and unified quiz editing/import.
- Updated component docs to describe select popup auto-sizing defaults and trigger-alignment override.

## [1.1.4] - 2026-02-05

### Changed
Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,18 @@ Open [http://localhost:3000](http://localhost:3000) and use the dashboard to nav
| Route | Description |
| ----------------- | ---------------------------------------------------- |
| `/` | Dashboard with links to all features |
| `/students` | Add, import, edit, and manage student roster |
| `/generator` | Draw random students with no-repeat logic |
| `/students` | Manage classes and class-scoped student rosters |
| `/generator` | Draw random students with no-repeat logic per class |
| `/quizzes` | Build and edit quiz question sets |
| `/play` | Run live quiz sessions with question/student pairing |
| `/breakout-rooms` | Generate random student groups |
| `/projects` | Create and manage project lists |
| `/play` | Run live quiz sessions scoped to selected class |
| `/breakout-rooms` | Generate random student groups per class |
| `/projects` | Create and manage project lists per class |

### Usage Examples

- **Add students**: Go to `/students`, type names (comma-separated for bulk) or import a `.txt` file.
- **Import full classes**: Go to `/students` and import `.txt` with `Class Name: Student A, Student B` lines, or `.json` with `{ className, students }` objects.
- **Quick-add students**: In `/students`, use the student input or student `.txt` import to add names to the currently selected class.
- **Class-aware tools**: `/generator`, `/breakout-rooms`, `/projects`, and `/play` all use the active class selected in the class dropdown.
- **Random draw**: Go to `/generator` and click "Draw" to select a random active student (no repeats until reset).
- **Quiz play**: In `/play`, select a quiz, then draw question/student pairs and click to reveal answers.
- **Timer**: Use the **timer in the header** (on every page): set time, start countdown; alerts at 10min, 5min, 1min, and 0 (with optional sound).
Expand Down Expand Up @@ -73,6 +75,7 @@ teacherbuddy/
│ ├── navigation/ # Sidebar navigation
│ ├── dashboard/ # Dashboard cards (server component)
│ ├── students/ # Student management
│ ├── classes/ # Class selector
│ ├── quizzes/ # Quiz builder
│ ├── play/ # Quiz play + timer card
│ ├── breakout/ # Breakout groups
Expand Down
2 changes: 1 addition & 1 deletion app/breakout-rooms/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const metadata: Metadata = {
*/
export default function Page() {
return (
<div className="flex flex-col gap-4">
<div className="max-w-6xl mx-auto">
<BreakoutGroupsCard />
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion app/generator/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import React from 'react';

import { Metadata } from 'next';

import GeneratorCard from '@/components/generator/generator-card';
Expand All @@ -15,7 +17,7 @@ export const metadata: Metadata = {
*/
export default function Page() {
return (
<div className="flex flex-col gap-4">
<div className="max-w-6xl mx-auto">
<GeneratorCard skeleton={<GeneratorCardSkeleton />} />
</div>
);
Expand Down
20 changes: 18 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { Metadata } from 'next';

import { Geist, Geist_Mono } from 'next/font/google';
import { cookies } from 'next/headers';

import './globals.css';
import packageJson from '@/package.json';

import AppShell from '@/components/app-shell';
import Footer from '@/components/footer';
Expand Down Expand Up @@ -57,11 +59,20 @@ export const metadata: Metadata = {
* Renders the shared HTML shell and providers for all application routes.
* Wrap page content in this layout so theme, state, sidebar, and footer stay consistent.
*/
export default function RootLayout({
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const appVersion = packageJson.version;
const cookieStore = await cookies();
const sidebarCookieValue =
cookieStore.get('teacherbuddy_sidebar_state')?.value ??
cookieStore.get('sidebar_state')?.value ??
cookieStore.get('teacherbuddy:sidebar_state')?.value;
const defaultSidebarOpen =
sidebarCookieValue === undefined ? true : sidebarCookieValue === 'true';

return (
<html lang="en_GB" suppressHydrationWarning>
<head>
Expand Down Expand Up @@ -91,7 +102,12 @@ export default function RootLayout({
className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<ThemeProvider attribute="class" defaultTheme="dark">
<AppStoreProvider>
<AppShell footer={<Footer />}>{children}</AppShell>
<AppShell
appVersion={appVersion}
defaultSidebarOpen={defaultSidebarOpen}
footer={<Footer />}>
{children}
</AppShell>
<PrivacyNotice />
<Toaster closeButton position="bottom-center" />
</AppStoreProvider>
Expand Down
2 changes: 1 addition & 1 deletion app/play/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const metadata: Metadata = {
*/
export default function Page() {
return (
<div className="flex flex-col gap-4">
<div className="max-w-6xl mx-auto">
<QuizPlayCard skeleton={<QuizPlayCardSkeleton />} />
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion app/projects/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export const metadata: Metadata = {
export default function Page() {
return (
<div className="flex flex-col gap-4">
<ProjectListBuilder />
<ProjectListView />
<ProjectListBuilder />
</div>
);
}
6 changes: 1 addition & 5 deletions app/quizzes/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,5 @@ export const metadata: Metadata = {
* Provides the editor workflow with a skeleton shown before hydration.
*/
export default function Page() {
return (
<div className="flex flex-col gap-4">
<QuizEditor skeleton={<QuizEditorSkeleton />} />
</div>
);
return <QuizEditor skeleton={<QuizEditorSkeleton />} />;
}
2 changes: 1 addition & 1 deletion app/students/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const metadata: Metadata = {
*/
export default function Page() {
return (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-4 lg:grid lg:grid-cols-2 lg:items-start">
<StudentForm skeleton={<StudentFormSkeleton />} />
<StudentTable skeleton={<StudentTableSkeleton />} />
</div>
Expand Down
Loading