Skip to content

Implementation of dashboard UI and user workflow#1

Closed
NirathH wants to merge 39 commits into
mainfrom
edison-test-br
Closed

Implementation of dashboard UI and user workflow#1
NirathH wants to merge 39 commits into
mainfrom
edison-test-br

Conversation

@NirathH

@NirathH NirathH commented Apr 22, 2026

Copy link
Copy Markdown
Owner

This pull request introduces several new API endpoints and authentication actions to support instructor and participant workflows, Hume AI emotion analysis integration, and robust session management. The changes include new authentication utilities, instructor assignment and student management endpoints, and endpoints for starting and polling Hume AI batch jobs as well as securely generating Hume access tokens. Additionally, a Node.js CI workflow is added for automated testing and builds.

Authentication & User Management:

  • Adds signUp, signIn, and signOut server actions in app/actions/auth.ts to handle user registration, login, and logout, including role-based dashboard redirects and error handling.
  • Implements PATCH endpoint in app/api/instructor/students/[studentId]/route.ts for instructors to update their students’ profiles, with validation to ensure only assigned students can be updated. (app/api/instructor/students/[studentId]/route.tsR1-R128)

Instructor Assignment Management:

  • Adds POST endpoint in app/api/instructor/assignments/route.ts for instructors to create new assignments for participants, including validation and error handling.
  • Adds POST endpoint in app/api/instructor/assignments/[assignmentId]/route.ts for updating or deleting assignments, with intent-based branching and instructor authorization. (app/api/instructor/assignments/[assignmentId]/route.tsR1-R65)

Hume AI Integration:

  • Implements POST endpoint in app/api/hume/batch/start/route.ts to start a Hume AI batch inference job for a session recording, including generating a signed URL for the recording and returning the Hume job ID.
  • Implements POST endpoint in app/api/hume/batch/poll/route.ts to poll the status of a Hume AI job, extract and aggregate emotion data upon completion, and trigger feedback analysis with emotional context.
  • Adds GET endpoint in app/api/hume/token/route.ts to securely generate and return a temporary Hume access token for frontend use, never exposing secret keys.

Infrastructure & Miscellaneous:

  • Adds a Node.js CI workflow in .github/workflows/node.js.yml to automate dependency installation, build, and test processes for multiple Node versions.
  • Refines the Supabase health check endpoint in app/api/health/route.ts with improved comments and error handling.

NirathH and others added 23 commits March 2, 2026 15:30
This workflow sets up Node.js CI to install dependencies, build the code, and run tests across multiple Node.js versions.
…tion, and adding API routes and dependencies
…pdated the page files by adding instructor/participants folder
…ng issues among API routes and client components.
@vercel

vercel Bot commented Apr 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
opendoorsai Ready Ready Preview, Comment May 4, 2026 3:43am

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a new dashboard/UI experience and supporting server utilities/endpoints for participant + instructor workflows, including session management and Hume/OpenAI-based analysis.

Changes:

  • Added participant and instructor dashboard pages/components plus shared UI utilities and styling updates.
  • Introduced new Supabase SSR helpers and role-gated auth utilities (requireParticipant / requireInstructor) and server auth actions (signUp/signIn/signOut).
  • Added multiple API routes for sessions, recordings, instructor student/assignment management, and Hume batch/token operations; added a Node.js CI workflow.

Reviewed changes

Copilot reviewed 69 out of 76 changed files in this pull request and generated 25 comments.

Show a summary per file
File Description
test-fetch.mjs Adds a manual Hume API fetch script.
test-batch.ts Adds a manual Hume batch SDK test script.
proxy.ts Adds Supabase SSR cookie refresh logic intended for middleware.
package.json Adds dependencies (Hume/OpenAI/Supabase SSR/etc.) and tweaks dev script.
lint_output.txt Adds captured eslint output to the repo.
lib/utils/studentHelpers.ts Adds student formatting + streak/status derivation helpers.
lib/supabaseServer.ts Adds server-side Supabase SSR client factory with cookie handling.
lib/supabaseBrowser.ts Adds browser-side Supabase SSR client factory.
lib/server/sessions/analyzeSession.ts Adds OpenAI-powered session feedback generation + persistence.
lib/server/participant/getParticipantSessionDetails.ts Adds participant session details fetch + transcript parsing.
lib/server/participant/getParticipantProfile.ts Adds participant profile fetch with instructor name resolution.
lib/server/participant/getParticipantDashboard.ts Adds participant dashboard data fetch (assignments/sessions/stats).
lib/server/instructor/getInstructorStudents.ts Adds instructor student list fetch + derived stats (streak/avg score).
lib/server/instructor/getInstructorStudentDetails.ts Adds instructor student details fetch + sessions/stats.
lib/server/instructor/getInstructorAssignments.ts Adds instructor assignment history aggregation + filtering/stats.
lib/server/instructor/getInstructorAssignmentForEdit.ts Adds instructor assignment fetch for editing plus participant list.
lib/server/auth/requireParticipant.ts Adds participant role guard (redirects if not authenticated/authorized).
lib/server/auth/requireInstructor.ts Adds instructor role guard (redirects if not authenticated/authorized).
components/ui.tsx Adds basic shared UI primitives (TextInput/PrimaryButton/LinkText).
components/participantNavbar.tsx Adds participant navigation (desktop/mobile) with profile integration.
components/StudentTable.tsx Adds instructor dashboard student table UI.
components/StudentProgressPanel.tsx Adds instructor dashboard student detail side panel UI.
components/StatMiniCard.tsx Adds small stat display card UI.
components/ProfileMenu.tsx Adds profile dropdown menu with sign-out action.
components/InstructorSidebar.tsx Adds instructor sidebar + mobile slide-in navigation.
components/Header.tsx Adds a header component with logo/user display.
components/GoalCard.tsx Adds goal card UI for participant dashboard.
components/FeedbackCard.tsx Adds feedback card UI.
components/DoorLoader.tsx Adds animated loader component used for app loading state.
components/AuthCard.tsx Adds auth form wrapper card component.
components/ActionCircle.tsx Adds action “circle button” component used on dashboards.
app/register/register-form.tsx Adds register form UI wired to signUp.
app/register/page.tsx Adds register page with Suspense wrapper.
app/participant/sessions/page.tsx Adds participant sessions list (assigned + completed) UI + data fetch.
app/participant/sessions/new/page.tsx Adds participant new session entry route (client session UI).
app/participant/sessions/[sessionId]/page.tsx Adds participant session details UI (feedback/transcript/instructor).
app/participant/profile/page.tsx Adds participant profile page UI.
app/participant/dashboard/page.tsx Adds participant dashboard page UI + data integration.
app/page.tsx Replaces default Next landing page with OpenDoorsAI marketing landing page.
app/login/page.tsx Adds login page with Suspense wrapper.
app/login/login-form.tsx Adds login form UI wired to signIn.
app/loading.tsx Adds global loading UI using DoorLoader.
app/layout.tsx Updates site metadata title.
app/instructor/students/page.tsx Adds instructor students list page UI + stats.
app/instructor/students/new/page.tsx Adds instructor “create student account” page and form.
app/instructor/students/[studentId]/page.tsx Adds instructor student detail page UI + session history display.
app/instructor/dashboard/page.tsx Adds instructor dashboard page integrating students + assignments.
app/instructor/dashboard/DashboardClient.tsx Adds client-side selection state for instructor dashboard.
app/instructor/assignments/page.tsx Adds instructor assignments list page UI with filtering.
app/instructor/assignments/new/page.tsx Adds instructor create-assignment page and form.
app/instructor/assignments/[assignmentId]/page.tsx Adds instructor assignment edit page (duplicate route).
app/instructor/assignments/[assignmentId]/edit/page.tsx Adds instructor assignment edit page (canonical edit route).
app/globals.css Replaces default theme variables with brand theme tokens.
app/favicon.ico Adds app favicon.
app/api/sessions/generate-prompt/route.ts Adds OpenAI prompt generation endpoint for session setup.
app/api/sessions/create/route.ts Expands session creation endpoint with auth + assignment linking.
app/api/sessions/complete/route.ts Adds session completion endpoint that updates sessions/transcripts/assignments.
app/api/recordings/upload/route.ts Adds recording upload endpoint to Supabase Storage + metadata persistence.
app/api/recordings/signed-url/route.ts Adds signed recording URL generation endpoint.
app/api/instructor/students/route.ts Adds instructor endpoint to create participant accounts.
app/api/instructor/students/[studentId]/route.ts Adds instructor PATCH endpoint to update assigned student profiles.
app/api/instructor/assignments/route.ts Adds instructor assignment creation endpoint.
app/api/instructor/assignments/[assignmentId]/route.ts Adds instructor assignment update/delete endpoint (intent-based).
app/api/hume/token/route.ts Adds endpoint to mint temporary Hume access tokens.
app/api/hume/batch/start/route.ts Adds endpoint to start Hume batch analysis for a session recording.
app/api/hume/batch/poll/route.ts Adds endpoint to poll Hume jobs and trigger OpenAI feedback generation.
app/api/health/route.ts Improves Supabase health check endpoint comments/formatting.
app/actions/auth.ts Adds server actions for sign up/in/out with role-based redirect.
.github/workflows/node.js.yml Adds GitHub Actions Node.js CI workflow.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +29
export async function POST(req: Request) {
try {
// Extract request body
const { jobId, sessionId } = await req.json();

// Validate required inputs
if (!jobId || !sessionId) {
return NextResponse.json(
{ error: "jobId and sessionId required" },
{ status: 400 }
);
}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This polling endpoint allows any caller to trigger analyzeSession(sessionId, ...) for an arbitrary session ID, without authentication/authorization. That’s both a data access issue and a cost-amplification vector (OpenAI calls). Require auth and verify ownership/permissions for sessionId before polling or running analysis.

Copilot uses AI. Check for mistakes.

const formData = await req.formData();
const intent = String(formData.get("_intent") || "").trim();

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If _intent is missing/invalid, this handler currently just redirects as if successful. That can mask client bugs and makes it harder to debug. Consider validating _intent and returning a 400 for unknown intents.

Suggested change
if (intent !== "delete" && intent !== "update") {
return NextResponse.json({ error: "Invalid intent." }, { status: 400 });
}

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +75
// Build dashboard rows for each student
const rows: StudentRow[] = students.map(
(student: {
user_id: string;
full_name: string | null;
created_at: string | null;
}) => {
// Sessions that belong to the current student
const studentSessions = sessionsData.filter(
(session) => session.participant_id === student.user_id
);

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Building rows currently does sessionsData.filter(...) for each student, which is O(students × sessions) and can become slow as data grows. Consider pre-grouping sessionsData into a Map keyed by participant_id, then doing O(1) lookups per student to compute streak/avg stats.

Copilot uses AI. Check for mistakes.
Comment thread lint_output.txt
Comment on lines +1 to +41

> opendoorsai@0.1.0 lint
> eslint


/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/hume/batch/poll/route.ts
57:39 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
112:19 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/hume/batch/start/route.ts
96:19 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/instructor/assignments/[assignmentId]/route.ts
5:54 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/recordings/upload/route.ts
146:17 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/sessions/complete/route.ts
3:10 warning 'analyzeSession' is defined but never used @typescript-eslint/no-unused-vars

/Users/nirathhussan/GitHub/OpenDoorsAI/app/api/sessions/generate-prompt/route.ts
30:40 warning 'assignmentError' is assigned a value but never used @typescript-eslint/no-unused-vars
114:40 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/app/participant/dashboard/page.tsx
9:3 warning 'Eye' is defined but never used @typescript-eslint/no-unused-vars

/Users/nirathhussan/GitHub/OpenDoorsAI/components/Header.tsx
7:9 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element

/Users/nirathhussan/GitHub/OpenDoorsAI/lib/server/instructor/getInstructorStudents.ts
46:21 error Unexpected any. Specify a different type @typescript-eslint/no-explicit-any

/Users/nirathhussan/GitHub/OpenDoorsAI/proxy.ts
6:7 error 'res' is never reassigned. Use 'const' instead prefer-const

/Users/nirathhussan/GitHub/OpenDoorsAI/test-fetch.mjs
1:8 warning 'fs' is defined but never used @typescript-eslint/no-unused-vars

✖ 13 problems (8 errors, 5 warnings)

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file appears to be a local eslint run output (includes absolute paths like /Users/...) and doesn’t belong in the repository/PR. It will quickly go stale and can leak developer environment details. Consider removing it from source control and relying on CI logs for lint output instead.

Copilot uses AI. Check for mistakes.
Comment thread proxy.ts
Comment on lines +6 to +7
const res = NextResponse.next({ request: req });

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

res is never reassigned, but it’s declared with let. This currently fails eslint (prefer-const) as shown in lint_output. Change it to const res = NextResponse.next(...).

Copilot uses AI. Check for mistakes.
Comment on lines +82 to +88
function StatusBadge({ status }: { status: string }) {
const styles =
status === "Active"
? "bg-emerald-100 text-emerald-700"
: status === "Needs Help"
? "bg-amber-100 text-amber-700"
: "bg-gray-100 text-gray-500";

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StatusBadge checks for "Needs Help", but the derived statuses produced elsewhere in this PR use "Needs Attention" (see DerivedStudentStatus). As a result, “Needs Attention” will fall into the default styling. Align the label enum used across the dashboard (either update the check here or standardize the status strings).

Copilot uses AI. Check for mistakes.
Comment on lines +172 to +177
<Link
href={`/participant/sessions/${session.id}`}
className="inline-flex items-center gap-2 rounded-xl border-2 border-brand-muted bg-white px-4 py-2 text-sm font-semibold text-gray-800 hover:border-brand-primary transition-colors"
>
View Session
</Link>

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This instructor page links to /participant/sessions/${session.id}, but that route is protected by requireParticipant() and will redirect instructors to /login. Provide an instructor-accessible session details route (e.g., /instructor/sessions/[id]) or a shared details page that authorizes both roles.

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/node.js.yml Outdated
cache: 'npm'
- run: npm ci
- run: npm run build --if-present
- run: npm test

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow runs npm test, but this repo’s package.json doesn’t define a test script. On GitHub Actions this will fail with “Missing script: test”. Update the workflow to run an existing script (e.g., npm run lint) or change this step to npm test --if-present / npm run test --if-present.

Suggested change
- run: npm test
- run: npm test --if-present

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +32
export async function GET(req: Request) {
/**
* Step 1: Extract session_id from query params
* Example: /api/... ?session_id=123
*/
const { searchParams } = new URL(req.url);
const session_id = searchParams.get("session_id");

// Validate input
if (!session_id) {
return NextResponse.json(
{ ok: false, error: "session_id required" },
{ status: 400 }
);
}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This route returns a signed URL for any session_id without authenticating/authorizing the caller. Because it uses the Supabase service role client, this can expose private recordings to anyone who can guess a session ID. Require an authenticated user (participant owner or assigned instructor) and verify session ownership before generating the signed URL.

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +33
export async function POST(req: NextRequest) {
try {
const body = await req.json();

const {
sessionId,
compactTranscript,
durationSeconds,
transcriptStatus,
}: {
sessionId?: string;
compactTranscript?: string;
durationSeconds?: number;
transcriptStatus?: string;
} = body;

// ==============================
// 1. VALIDATION
// ==============================
if (!sessionId) {
return NextResponse.json(
{ error: "sessionId is required" },
{ status: 400 }
);
}

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This completion endpoint uses the service-role Supabase client and performs updates purely based on a sessionId from the request body, with no authentication/authorization. That allows anyone to mark any session as completed and write transcripts. Authenticate the caller and verify they own the session (or are an authorized instructor) before updating session/transcript/assignment records.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants