🪻 distributed transcription service thistle.dunkirk.sh
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: grey out registered classes and remove section code

+68 -18
+51 -16
src/components/class-registration-modal.ts
··· 10 10 professor: string; 11 11 semester: string; 12 12 year: number; 13 + is_enrolled?: boolean; 13 14 } 14 15 15 16 @customElement("class-registration-modal") ··· 194 195 transition: all 0.2s; 195 196 } 196 197 197 - .class-card:hover:not(:disabled) { 198 + .class-card.enrolled { 199 + opacity: 0.6; 200 + background: var(--background); 201 + cursor: default; 202 + } 203 + 204 + .class-card:hover:not(:disabled):not(.enrolled) { 198 205 border-color: var(--accent); 199 206 transform: translateX(4px); 200 207 } ··· 204 211 cursor: not-allowed; 205 212 } 206 213 214 + .enrolled-badge { 215 + display: inline-block; 216 + padding: 0.25rem 0.5rem; 217 + background: var(--secondary); 218 + color: var(--text); 219 + border-radius: 4px; 220 + font-size: 0.75rem; 221 + font-weight: 600; 222 + text-transform: uppercase; 223 + } 224 + 207 225 .class-header { 208 226 display: flex; 209 227 justify-content: space-between; ··· 422 440 423 441 this.isSearching = true; 424 442 this.error = ""; 443 + this.suggestedQuery = ""; 425 444 this.hasSearched = true; 426 445 446 + // Auto-remove section numbers (e.g., MATH-1720-01 -> MATH-1720) 447 + let queryToSearch = this.searchQuery.trim(); 448 + if (queryToSearch.match(/.*-\d{2,}$/)) { 449 + queryToSearch = queryToSearch.replace(/-\d{2,}$/, ""); 450 + this.searchQuery = queryToSearch; 451 + } 452 + 427 453 try { 428 454 const response = await fetch( 429 - `/api/classes/search?q=${encodeURIComponent(this.searchQuery.trim())}`, 455 + `/api/classes/search?q=${encodeURIComponent(queryToSearch)}`, 430 456 ); 431 457 432 458 if (!response.ok) { ··· 681 707 ${this.results.map( 682 708 (cls) => html` 683 709 <button 684 - class="class-card" 685 - @click=${() => this.handleJoin(cls.id)} 686 - ?disabled=${this.isJoining} 710 + class="class-card ${cls.is_enrolled ? "enrolled" : ""}" 711 + @click=${() => !cls.is_enrolled && this.handleJoin(cls.id)} 712 + ?disabled=${this.isJoining || cls.is_enrolled} 687 713 > 688 714 <div class="class-header"> 689 715 <div class="class-info"> 690 - <div class="course-code">${cls.course_code}</div> 716 + <div class="course-code"> 717 + ${cls.course_code} 718 + ${cls.is_enrolled ? html`<span class="enrolled-badge">Registered</span>` : ""} 719 + </div> 691 720 <div class="class-name">${cls.name}</div> 692 721 <div class="class-meta"> 693 722 <span>👤 ${cls.professor}</span> 694 723 <span>📅 ${cls.semester} ${cls.year}</span> 695 724 </div> 696 725 </div> 697 - <button 698 - class="join-btn" 699 - ?disabled=${this.isJoining} 700 - @click=${(e: Event) => { 701 - e.stopPropagation(); 702 - this.handleJoin(cls.id); 703 - }} 704 - > 705 - ${this.isJoining ? "Joining..." : "Join"} 706 - </button> 726 + ${ 727 + !cls.is_enrolled 728 + ? html` 729 + <button 730 + class="join-btn" 731 + ?disabled=${this.isJoining} 732 + @click=${(e: Event) => { 733 + e.stopPropagation(); 734 + this.handleJoin(cls.id); 735 + }} 736 + > 737 + ${this.isJoining ? "Joining..." : "Join"} 738 + </button> 739 + ` 740 + : "" 741 + } 707 742 </div> 708 743 </button> 709 744 `,
+17 -2
src/index.ts
··· 1549 1549 "/api/classes/search": { 1550 1550 GET: async (req) => { 1551 1551 try { 1552 - requireAuth(req); 1552 + const user = requireAuth(req); 1553 1553 const url = new URL(req.url); 1554 1554 const query = url.searchParams.get("q"); 1555 1555 ··· 1558 1558 } 1559 1559 1560 1560 const classes = searchClassesByCourseCode(query); 1561 - return Response.json({ classes }); 1561 + 1562 + // Get user's enrolled classes to mark them 1563 + const enrolledClassIds = db 1564 + .query<{ class_id: string }, [number]>( 1565 + "SELECT class_id FROM class_members WHERE user_id = ?", 1566 + ) 1567 + .all(user.id) 1568 + .map((row) => row.class_id); 1569 + 1570 + // Add is_enrolled flag to each class 1571 + const classesWithEnrollment = classes.map((cls) => ({ 1572 + ...cls, 1573 + is_enrolled: enrolledClassIds.includes(cls.id), 1574 + })); 1575 + 1576 + return Response.json({ classes: classesWithEnrollment }); 1562 1577 } catch (error) { 1563 1578 return handleError(error); 1564 1579 }