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
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type EvaluationFormProps = {
courseName: string;
courseShortname: string;
facultyName: string;
facultyProfilePicture?: string | null;
enrollmentSectionName?: string;
activeVersion: { id: string };
faculty: { id: string };
Expand All @@ -44,6 +45,7 @@ export function EvaluationForm({
courseName,
courseShortname,
facultyName,
facultyProfilePicture,
enrollmentSectionName,
activeVersion,
faculty,
Expand Down Expand Up @@ -151,6 +153,7 @@ export function EvaluationForm({
courseName={courseName}
courseShortname={courseShortname}
facultyName={facultyName}
facultyProfilePicture={facultyProfilePicture}
enrollmentSectionName={enrollmentSectionName}
>
<div className="mt-5 sm:mt-8">
Expand All @@ -165,6 +168,7 @@ export function EvaluationForm({
defaultValues={defaultValues}
onChange={handleChange}
facultyName={facultyName}
facultyProfilePicture={facultyProfilePicture}
progressTrailing={
draftStatus !== "idle" ? (
<Badge
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Link from "next/link";
import { ArrowLeft } from "lucide-react";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";

Expand All @@ -9,14 +10,27 @@ type EvaluationPageShellProps = {
courseName?: string;
courseShortname?: string;
facultyName?: string;
facultyProfilePicture?: string | null;
enrollmentSectionName?: string;
};

function getInitials(fullName: string) {
return (
fullName
.split(" ")
.map((part) => part[0])
.join("")
.slice(0, 2)
.toUpperCase() || "F"
);
}

export function EvaluationPageShell({
children,
courseName,
courseShortname,
facultyName,
facultyProfilePicture,
enrollmentSectionName,
}: EvaluationPageShellProps) {
return (
Expand Down Expand Up @@ -60,9 +74,19 @@ export function EvaluationPageShell({
<p className="text-[0.62rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground sm:text-[0.68rem]">
Instructor
</p>
<p className="font-playfair text-base font-semibold leading-tight text-foreground sm:mt-2 sm:text-xl">
{facultyName}
</p>
<div className="flex items-center gap-2.5 sm:mt-2 sm:flex-col sm:gap-2">
<Avatar size="default" className="border border-border/70">
{facultyProfilePicture ? (
<AvatarImage src={facultyProfilePicture} alt={facultyName} />
) : null}
<AvatarFallback className="bg-slate-100 text-xs font-semibold text-slate-700">
{getInitials(facultyName ?? "")}
</AvatarFallback>
</Avatar>
<p className="font-playfair text-base font-semibold leading-tight text-foreground sm:text-xl">
{facultyName}
</p>
</div>
</div>
<div className="flex flex-col items-start gap-0.5 border-t border-border/60 px-4 py-3.5 text-left sm:items-center sm:gap-0 sm:px-6 sm:py-5 sm:text-center md:border-t-0 md:border-l">
<p className="text-[0.62rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground sm:text-[0.68rem]">
Expand Down
14 changes: 12 additions & 2 deletions app/(dashboard)/student/courses/[courseId]/evaluation/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function FacultyEvaluationPage() {
courseName={ctx?.courseName}
courseShortname={ctx?.courseShortname}
facultyName={ctx?.facultyName}
facultyProfilePicture={ctx?.faculty.profilePicture}
enrollmentSectionName={ctx?.enrollmentSectionName}
>
<EvaluationLoading message={result.message} />
Expand Down Expand Up @@ -53,12 +54,14 @@ export default function FacultyEvaluationPage() {
}

if (result.status === "no-version") {
const { courseName, courseShortname, facultyName, enrollmentSectionName } = result.context;
const { courseName, courseShortname, facultyName, faculty, enrollmentSectionName } =
result.context;
return (
<EvaluationPageShell
courseName={courseName}
courseShortname={courseShortname}
facultyName={facultyName}
facultyProfilePicture={faculty.profilePicture}
enrollmentSectionName={enrollmentSectionName}
>
<EvaluationError message="No active questionnaire is available for evaluation at this time." />
Expand All @@ -73,12 +76,19 @@ export default function FacultyEvaluationPage() {
courseName={context.courseName}
courseShortname={context.courseShortname}
facultyName={context.facultyName}
facultyProfilePicture={context.faculty.profilePicture}
enrollmentSectionName={context.enrollmentSectionName}
>
<EvaluationAlreadySubmitted submittedAt={submittedAt} />
</EvaluationPageShell>
);
}

return <EvaluationForm courseId={courseId} {...result.data} />;
return (
<EvaluationForm
courseId={courseId}
{...result.data}
facultyProfilePicture={result.data.faculty.profilePicture}
/>
);
}
31 changes: 28 additions & 3 deletions features/faculty-analytics/components/faculty-report-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useMemo, useState } from "react";
import Link from "next/link";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { APP_ROLES, type AppRole } from "@/constants/roles";
Expand Down Expand Up @@ -49,6 +50,17 @@ const REPORT_EXPORT_ROLES: ReadonlySet<AppRole> = new Set([
APP_ROLES.CAMPUS_HEAD,
]);

function getInitials(fullName: string) {
return (
fullName
.split(" ")
.map((part) => part[0])
.join("")
.slice(0, 2)
.toUpperCase() || "F"
);
}

export function FacultyReportScreen({ facultyId }: FacultyReportScreenProps) {
const [isExportDialogOpen, setIsExportDialogOpen] = useState(false);
const viewModel = useFacultyReportDetailViewModel({ facultyId });
Expand Down Expand Up @@ -147,9 +159,22 @@ export function FacultyReportScreen({ facultyId }: FacultyReportScreenProps) {
{/* Title row — mirrors the dashboard / faculty-list header pattern */}
<div className="flex flex-col gap-4 xl:flex-row xl:items-start xl:justify-between">
<div className="min-w-0">
<h1 className="font-playfair text-2xl font-semibold tracking-tight sm:text-3xl">
{viewModel.report.faculty.name}
</h1>
<div className="flex items-center gap-3">
<Avatar size="lg" className="border border-border/70">
{viewModel.report.faculty.profilePicture ? (
<AvatarImage
src={viewModel.report.faculty.profilePicture}
alt={viewModel.report.faculty.name}
/>
) : null}
<AvatarFallback className="bg-slate-100 text-sm font-semibold text-slate-700">
{getInitials(viewModel.report.faculty.name)}
</AvatarFallback>
</Avatar>
<h1 className="font-playfair text-2xl font-semibold tracking-tight sm:text-3xl">
{viewModel.report.faculty.name}
</h1>
</div>
<p className="mt-3 max-w-3xl text-sm text-muted-foreground">
Review per-question faculty evaluation results for{" "}
<span className="font-medium text-foreground">{viewModel.semesterLabel}</span>.
Expand Down
1 change: 1 addition & 0 deletions features/faculty-analytics/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ export type FacultyReportCommentsQuery = FacultyReportQuery & {
export type FacultyReportFacultyDto = {
id: string;
name: string;
profilePicture?: string | null;
};

export type FacultyReportSemesterDto = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { memo } from "react";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Progress } from "@/components/ui/progress";

import { useAnsweredCountFor, useHasQualitativeContent } from "./questionnaire-form-store";
Expand All @@ -13,13 +14,27 @@ type QuestionnaireFormProgressProps = {
trailing?: React.ReactNode;
/** When provided, displays the faculty being evaluated above the progress row. */
facultyName?: string;
/** Optional profile picture URL for the faculty being evaluated. */
facultyProfilePicture?: string | null;
};

function getInitials(fullName: string) {
return (
fullName
.split(" ")
.map((part) => part[0])
.join("")
.slice(0, 2)
.toUpperCase() || "F"
);
}

function QuestionnaireFormProgressBase({
requiredIds,
qualitativeRequired,
trailing,
facultyName,
facultyProfilePicture,
}: QuestionnaireFormProgressProps) {
const answeredCount = useAnsweredCountFor(requiredIds);
const hasQualitativeContent = useHasQualitativeContent();
Expand All @@ -32,13 +47,23 @@ function QuestionnaireFormProgressBase({
return (
<div className="sticky top-0 z-20 -mx-4 space-y-2 border-b border-border/60 bg-background/95 px-4 py-3 backdrop-blur supports-[backdrop-filter]:bg-background/80 sm:mx-0">
{facultyName && (
<div className="flex flex-col">
<span className="text-[0.62rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground sm:text-[0.68rem]">
Evaluating
</span>
<span className="truncate font-playfair text-sm font-semibold leading-tight text-foreground sm:text-base">
{facultyName}
</span>
<div className="flex items-center gap-2.5">
<Avatar size="sm" className="border border-border/70">
{facultyProfilePicture ? (
<AvatarImage src={facultyProfilePicture} alt={facultyName} />
) : null}
<AvatarFallback className="bg-slate-100 text-[0.65rem] font-semibold text-slate-700">
{getInitials(facultyName)}
</AvatarFallback>
</Avatar>
<div className="flex min-w-0 flex-col">
<span className="text-[0.62rem] font-semibold uppercase tracking-[0.22em] text-muted-foreground sm:text-[0.68rem]">
Evaluating
</span>
<span className="truncate font-playfair text-sm font-semibold leading-tight text-foreground sm:text-base">
{facultyName}
</span>
</div>
</div>
)}
<div className="flex items-center justify-between gap-3 text-sm">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type QuestionnaireFormRendererProps = {
progressTrailing?: React.ReactNode;
/** Faculty being evaluated; surfaced inside the sticky progress header. */
facultyName?: string;
/** Optional faculty profile picture URL for the progress header avatar. */
facultyProfilePicture?: string | null;
};

/**
Expand All @@ -52,6 +54,7 @@ export function QuestionnaireFormRenderer({
onChange,
progressTrailing,
facultyName,
facultyProfilePicture,
}: QuestionnaireFormRendererProps) {
const isInteractive = mode === "interactive";

Expand Down Expand Up @@ -94,6 +97,7 @@ export function QuestionnaireFormRenderer({
qualitativeRequired={model.qualitative.required}
trailing={progressTrailing}
facultyName={facultyName}
facultyProfilePicture={facultyProfilePicture}
/>
)}

Expand Down
Loading