coloring change

This commit is contained in:
2026-04-08 14:12:28 -07:00
parent 4b435ccdb4
commit 9e1bef0ee1
5 changed files with 25 additions and 51 deletions
@@ -4,7 +4,7 @@ import { ModalShell } from '../modal-shell/modal-shell';
import { StudentService } from '../../../shared/services/student.service'; import { StudentService } from '../../../shared/services/student.service';
import { BenchmarkDto } from '../../../shared/classes/benchmark.dto'; import { BenchmarkDto } from '../../../shared/classes/benchmark.dto';
import { ProgressEventDto } from '../../../shared/classes/progress-event.dto'; import { ProgressEventDto } from '../../../shared/classes/progress-event.dto';
import { getCategoryColor } from '../../../shared/classes/category-colors'; import { GOAL_COLOR } from '../../../shared/classes/category-colors';
@Component({ @Component({
selector: 'app-edit-event-modal', selector: 'app-edit-event-modal',
@@ -17,7 +17,7 @@ export class EditEventModal {
readonly studentId = input.required<string>(); readonly studentId = input.required<string>();
readonly goalId = input.required<string>(); readonly goalId = input.required<string>();
readonly goalCategory = input<string>('');
readonly benchmarks = input<BenchmarkDto[]>([]); readonly benchmarks = input<BenchmarkDto[]>([]);
/** null for new event, populated for edit */ /** null for new event, populated for edit */
readonly event = input<ProgressEventDto | null>(null); readonly event = input<ProgressEventDto | null>(null);
@@ -47,7 +47,7 @@ export class EditEventModal {
} }
get colors() { get colors() {
return getCategoryColor(this.goalCategory()); return GOAL_COLOR;
} }
isBenchmarkSelected(id: string): boolean { isBenchmarkSelected(id: string): boolean {
@@ -18,7 +18,7 @@
} }
@if (showEditEventModal()) { @if (showEditEventModal()) {
<app-edit-event-modal [studentId]="studentId()!" [goalId]="selectedGoal()!.goalId" <app-edit-event-modal [studentId]="studentId()!" [goalId]="selectedGoal()!.goalId"
[goalCategory]="selectedGoal()!.category" [benchmarks]="goalBenchmarks()" [benchmarks]="goalBenchmarks()"
[event]="showEditEventModal() === 'new' ? null : $any(showEditEventModal())" (saved)="onEventSaved()" [event]="showEditEventModal() === 'new' ? null : $any(showEditEventModal())" (saved)="onEventSaved()"
(closed)="showEditEventModal.set(null)" /> (closed)="showEditEventModal.set(null)" />
} }
@@ -32,9 +32,6 @@
<div class="goal-tabs"> <div class="goal-tabs">
@for (g of goals(); track g.goalId) { @for (g of goals(); track g.goalId) {
<button class="goal-tab" [class.active]="selectedGoalId() === g.goalId || (selectedGoal()?.goalId === g.goalId)" <button class="goal-tab" [class.active]="selectedGoalId() === g.goalId || (selectedGoal()?.goalId === g.goalId)"
[style.border-color]="(selectedGoalId() === g.goalId || selectedGoal()?.goalId === g.goalId) ? getCatColor(g.category).border : '#E5E5E0'"
[style.background]="(selectedGoalId() === g.goalId || selectedGoal()?.goalId === g.goalId) ? getCatColor(g.category).bg : '#FFF'"
[style.color]="(selectedGoalId() === g.goalId || selectedGoal()?.goalId === g.goalId) ? getCatColor(g.category).text : '#666'"
(click)="onSelectGoal(g.goalId)"> (click)="onSelectGoal(g.goalId)">
{{ g.category }} {{ g.category }}
</button> </button>
@@ -49,8 +46,7 @@
<!-- Goal Card --> <!-- Goal Card -->
<div class="goal-card"> <div class="goal-card">
<div class="goal-card-header"> <div class="goal-card-header">
<span class="goal-badge" [style.color]="goalColors().text" <span class="goal-badge">{{ selectedGoal()!.category }} Goal</span>
[style.background]="goalColors().bg">{{ selectedGoal()!.category }} Goal</span>
@if (selectedGoal()!.targetCompletionDate) { @if (selectedGoal()!.targetCompletionDate) {
<span class="goal-due">Due {{ formatDate(selectedGoal()!.targetCompletionDate) }}</span> <span class="goal-due">Due {{ formatDate(selectedGoal()!.targetCompletionDate) }}</span>
} }
@@ -67,14 +63,10 @@
<!-- Sub Tabs --> <!-- Sub Tabs -->
<div class="sub-tabs"> <div class="sub-tabs">
<button class="sub-tab" [class.active]="activeTab() === 'benchmarks'" <button class="sub-tab" [class.active]="activeTab() === 'benchmarks'"
[style.color]="activeTab() === 'benchmarks' ? goalColors().text : '#888'"
[style.border-bottom-color]="activeTab() === 'benchmarks' ? goalColors().accent : 'transparent'"
(click)="onTabChange('benchmarks')"> (click)="onTabChange('benchmarks')">
Benchmarks ({{ goalBenchmarks().length }}) Benchmarks ({{ goalBenchmarks().length }})
</button> </button>
<button class="sub-tab" [class.active]="activeTab() === 'progress'" <button class="sub-tab" [class.active]="activeTab() === 'progress'"
[style.color]="activeTab() === 'progress' ? goalColors().text : '#888'"
[style.border-bottom-color]="activeTab() === 'progress' ? goalColors().accent : 'transparent'"
(click)="onTabChange('progress')"> (click)="onTabChange('progress')">
Progress Events ({{ sortedProgressEvents().length }}) Progress Events ({{ sortedProgressEvents().length }})
</button> </button>
@@ -83,10 +75,11 @@
<!-- Benchmarks Tab --> <!-- Benchmarks Tab -->
@if (activeTab() === 'benchmarks') { @if (activeTab() === 'benchmarks') {
<div class="tab-content"> <div class="tab-content">
<button class="add-btn" (click)="onAddBenchmark()">+ Add Benchmark</button>
@for (b of goalBenchmarks(); track b.benchmarkId) { @for (b of goalBenchmarks(); track b.benchmarkId) {
<div class="benchmark-card"> <div class="benchmark-card">
<div class="benchmark-header"> <div class="benchmark-header">
<span class="benchmark-name" [style.color]="goalColors().text">{{ b.shortName || b.benchmark }}</span> <span class="benchmark-name">{{ b.shortName || b.benchmark }}</span>
<button class="edit-icon" (click)="onEditBenchmark(b)" aria-label="Edit benchmark"> <button class="edit-icon" (click)="onEditBenchmark(b)" aria-label="Edit benchmark">
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="#999" stroke-width="1.5" <svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="#999" stroke-width="1.5"
stroke-linecap="round" stroke-linejoin="round"> stroke-linecap="round" stroke-linejoin="round">
@@ -97,18 +90,17 @@
<p class="benchmark-desc">{{ b.benchmark }}</p> <p class="benchmark-desc">{{ b.benchmark }}</p>
</div> </div>
} }
<button class="add-btn" (click)="onAddBenchmark()">+ Add Benchmark</button>
</div> </div>
} }
<!-- Progress Tab --> <!-- Progress Tab -->
@if (activeTab() === 'progress') { @if (activeTab() === 'progress') {
<div class="tab-content timeline"> <div class="tab-content timeline">
<button class="add-btn" (click)="onNewEvent()">+ Log Progress Event</button>
<div class="timeline-line"></div> <div class="timeline-line"></div>
@for (ev of sortedProgressEvents(); track ev.progressEventId) { @for (ev of sortedProgressEvents(); track ev.progressEventId) {
<div class="timeline-item"> <div class="timeline-item">
<div class="timeline-dot" [style.background]="goalColors().bg" <div class="timeline-dot"></div>
[style.border-color]="goalColors().border"></div>
<div class="event-card"> <div class="event-card">
<div class="event-header"> <div class="event-header">
<span class="event-date">{{ formatDate(ev.createdAt) }}</span> <span class="event-date">{{ formatDate(ev.createdAt) }}</span>
@@ -123,7 +115,6 @@
</div> </div>
</div> </div>
} }
<button class="add-btn" (click)="onNewEvent()">+ Log Progress Event</button>
</div> </div>
} }
</div> </div>
@@ -65,6 +65,9 @@
&.active { &.active {
font-weight: 600; font-weight: 600;
border-color: #818CF8;
background: #EEF2FF;
color: #4338CA;
} }
&.add-goal { &.add-goal {
@@ -104,6 +107,8 @@
letter-spacing: 0.05em; letter-spacing: 0.05em;
padding: 3px 8px; padding: 3px 8px;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
color: #4338CA;
background: #EEF2FF;
} }
.goal-due { .goal-due {
@@ -156,6 +161,8 @@
&.active { &.active {
font-weight: 600; font-weight: 600;
color: #4338CA;
border-bottom-color: #6366F1;
} }
} }
@@ -184,6 +191,7 @@
.benchmark-name { .benchmark-name {
font-weight: 600; font-weight: 600;
font-size: 14px; font-size: 14px;
color: #4338CA;
} }
.benchmark-events { .benchmark-events {
@@ -227,7 +235,8 @@
width: 12px; width: 12px;
height: 12px; height: 12px;
border-radius: 50%; border-radius: 50%;
border: 2px solid; border: 2px solid #818CF8;
background: #EEF2FF;
} }
.event-card { .event-card {
@@ -5,7 +5,6 @@ import { StudentCardDto } from '../../../shared/classes/student-card.dto';
import { StudentGoalItem } from '../../../shared/classes/student-goal'; import { StudentGoalItem } from '../../../shared/classes/student-goal';
import { BenchmarkDto } from '../../../shared/classes/benchmark.dto'; import { BenchmarkDto } from '../../../shared/classes/benchmark.dto';
import { ProgressEventDto } from '../../../shared/classes/progress-event.dto'; import { ProgressEventDto } from '../../../shared/classes/progress-event.dto';
import { getCategoryColor, CategoryColor } from '../../../shared/classes/category-colors';
import { EditGoalModal } from '../edit-goal-modal/edit-goal-modal'; import { EditGoalModal } from '../edit-goal-modal/edit-goal-modal';
import { EditBenchmarkModal } from '../edit-benchmark-modal/edit-benchmark-modal'; import { EditBenchmarkModal } from '../edit-benchmark-modal/edit-benchmark-modal';
import { EditEventModal } from '../edit-event-modal/edit-event-modal'; import { EditEventModal } from '../edit-event-modal/edit-event-modal';
@@ -81,9 +80,6 @@ export class Workspace {
return this.goals().find(g => g.goalId === id) ?? null; return this.goals().find(g => g.goalId === id) ?? null;
}); });
protected readonly goalColors = computed<CategoryColor>(() => {
return getCategoryColor(this.selectedGoal()?.category ?? '');
});
protected readonly goalBenchmarks = computed<BenchmarkDto[]>(() => { protected readonly goalBenchmarks = computed<BenchmarkDto[]>(() => {
const goalId = this.selectedGoal()?.goalId; const goalId = this.selectedGoal()?.goalId;
@@ -169,26 +165,12 @@ export class Workspace {
// ************************ Formatting Helpers ********************** // ************************ Formatting Helpers **********************
getCatColor(category: string): CategoryColor {
return getCategoryColor(category);
}
formatDate(d: string | Date | null): string { formatDate(d: string | Date | null): string {
if (!d) return ''; if (!d) return '';
const date = new Date(d); const date = new Date(d);
return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }); return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });
} }
truncate(text: string, max: number): string {
return text.length > max ? text.slice(0, max) + '…' : text;
}
getRelatedEventCount(benchmarkId: string): number {
// We don't have benchmark associations in the event DTO from the list endpoint,
// so we return 0. The mockup shows this but we can't derive it without extra API calls.
return 0;
}
// ********************** Support Procedures *********************** // ********************** Support Procedures ***********************
private async loadStudentData(studentId: string) { private async loadStudentData(studentId: string) {
@@ -5,18 +5,10 @@ export interface CategoryColor {
accent: string; accent: string;
} }
const CATEGORY_COLORS: Record<string, CategoryColor> = { /** Single color used for all goals, regardless of category. */
Reading: { bg: '#EEF2FF', border: '#818CF8', text: '#4338CA', accent: '#6366F1' }, export const GOAL_COLOR: CategoryColor = {
Math: { bg: '#FFF7ED', border: '#FB923C', text: '#C2410C', accent: '#F97316' }, bg: '#EEF2FF',
Writing: { bg: '#F0FDF4', border: '#4ADE80', text: '#15803D', accent: '#22C55E' }, border: '#818CF8',
Behavior: { bg: '#FDF4FF', border: '#C084FC', text: '#7E22CE', accent: '#A855F7' }, text: '#4338CA',
Speech: { bg: '#FFF1F2', border: '#FB7185', text: '#BE123C', accent: '#F43F5E' }, accent: '#6366F1',
}; };
const DEFAULT_COLOR: CategoryColor = {
bg: '#F5F5F0', border: '#A0A090', text: '#444', accent: '#666',
};
export function getCategoryColor(category: string): CategoryColor {
return CATEGORY_COLORS[category] ?? DEFAULT_COLOR;
}