Skip to content

Commit 6f3b5bf

Browse files
committed
Updated audit card to be more like Figma
1 parent 74684da commit 6f3b5bf

2 files changed

Lines changed: 136 additions & 15 deletions

File tree

entrypoints/popup-app/main.tsx

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,110 @@ export default function App() {
133133
// setHypotheticalCourses((prev) => [...prev, course]);
134134
// // TODO: Store in browser storage and send to degree audit page
135135
// };
136+
const Pill = ({ text }: { text: string }) => (
137+
<span className="inline-flex items-center rounded-full bg-[var(--color-dap-primary)] px-2.5 py-[2px] text-[12px] font-extrabold leading-none text-white">
138+
{text}
139+
</span>
140+
);
141+
142+
const AuditCardDetailed = ({ audit }: { audit: DegreeAuditCardProps }) => (
143+
<div
144+
className="
145+
group
146+
w-full
147+
rounded-[12px]
148+
border
149+
border-gray-200
150+
bg-white
151+
px-5
152+
py-4
153+
hover:cursor-pointer
154+
hover:bg-[var(--color-dap-primary)]
155+
transition-colors
156+
"
157+
onClick={(e) => {
158+
e.stopPropagation();
159+
handleOpenDegreeAuditPage(audit?.auditId);
160+
}}
161+
>
162+
<div className="flex items-start justify-between gap-4">
163+
{/* Left */}
164+
<div className="min-w-0 flex-1">
165+
<div
166+
className="
167+
text-[20px]
168+
font-extrabold
169+
text-[var(--color-dap-primary)]
170+
leading-tight
171+
transition-colors
172+
group-hover:text-white
173+
"
174+
>
175+
{audit.title}
176+
</div>
177+
178+
<div className="mt-3 flex items-center gap-3">
179+
<span
180+
className="
181+
text-[13px]
182+
font-medium
183+
tracking-wide
184+
text-black
185+
transition-colors
186+
hover:text-white
187+
"
188+
>
189+
MAJOR
190+
</span>
191+
192+
{(audit.majors ?? []).map((m, i) => (
193+
<span
194+
key={`${m}-${i}`}
195+
className="
196+
inline-flex items-center
197+
rounded-[6px]
198+
bg-[#068b5e]
199+
px-3 py-[3px]
200+
text-[12px]
201+
leading-none
202+
text-white
203+
"
204+
>
205+
{m}
206+
</span>
207+
))}
208+
</div>
209+
210+
{/* Optional MINOR/CERT row if you want parity with the detailed card */}
211+
{(audit.minors ?? []).length > 0 && (
212+
<div className="mt-2 flex items-center gap-4">
213+
<div className="text-[13px] font-extrabold tracking-wide text-[var(--color-ut-charcoal)]">
214+
MINOR/CERT
215+
</div>
216+
<div className="flex flex-wrap gap-2">
217+
{(audit.minors ?? []).map((m, i) => (
218+
<span
219+
key={`${m}-${i}`}
220+
className="inline-flex items-center rounded-full bg-gray-100 px-2.5 py-[2px] text-[12px] font-bold leading-none text-[var(--color-ut-charcoal)]"
221+
>
222+
{m}
223+
</span>
224+
))}
225+
</div>
226+
</div>
227+
)}
228+
</div>
229+
230+
{/* Right badge */}
231+
<div className="relative top-6">
232+
<div className="rounded-[10px] bg-[var(--color-dap-primary)] px-3.5 py-2 text-white text-[16px] font-extrabold leading-none">
233+
{audit.percentage}%
234+
</div>
235+
</div>
236+
</div>
237+
</div>
238+
);
239+
136240

137241
return (
138242
<div className="w-[438px] h-full min-h-[300px] max-h-[600px] bg-white font-sans overflow-hidden flex flex-col border border-gray-100">
@@ -170,7 +274,7 @@ export default function App() {
170274
style={{ fontFamily: "Roboto Flex" }}
171275
className="text-[25.63px] font-bold text-[var(--color-dap-dark)]"
172276
>
173-
Current Audits
277+
{audits.length} AUDITS
174278
</h1>
175279
{isSyncing && (
176280
<div className="flex items-center gap-1.5 text-[var(--color-dap-gray-light)]">
@@ -224,12 +328,8 @@ export default function App() {
224328
handleOpenDegreeAuditPage(audit?.auditId);
225329
}}
226330
>
227-
<DegreeAuditCardPopup
228-
title={audit.title}
229-
majors={audit.majors}
230-
minors={audit.minors}
231-
percentage={audit.percentage}
232-
/>
331+
<AuditCardDetailed audit={audit} />
332+
233333
</div>
234334
))}
235335
</div>

lib/audit-history-scraper.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,43 @@ function parseMajor(programText: string): string {
99
// Clean up whitespace first (normalize spaces and newlines)
1010
const cleanText = programText.replace(/\s+/g, " ").trim();
1111

12+
// NEW: strip leading punctuation and an optional "major" label
13+
function cleanExtractedMajor(raw: string): string {
14+
return raw
15+
.replace(/^\s*[:,-]+\s*/g, "") // leading ": , -"
16+
.replace(/^\s*major\s*[:,-]?\s*/i, "") // leading "major", "Major:", etc.
17+
.trim();
18+
}
19+
20+
// Accepts: "B S", "BS", "B.S.", "B A", "BA", "B.A."
21+
const BSBA_PREFIX = /B\.?\s*[SA]\.?\s*/;
22+
1223
// Pattern 1: "B S in Communication and Leadership" (with "in")
13-
const withInMatch = cleanText.match(/B [SA] in (.+?)(?:\(|$)/);
14-
if (withInMatch) return withInMatch[1].trim();
24+
const withInMatch = cleanText.match(
25+
new RegExp(`${BSBA_PREFIX.source}in\\s+(.+?)(?:\\(|$)`, "i"),
26+
);
27+
if (withInMatch) return cleanExtractedMajor(withInMatch[1]);
28+
29+
// Pattern 2: "B S Computer Science, CS" or "B A Economics" or "B S Mathematics"
30+
const spacedMatch = cleanText.match(
31+
new RegExp(`${BSBA_PREFIX.source}(.+?)(?:,|\\(|$)`, "i"),
32+
);
33+
if (spacedMatch) return cleanExtractedMajor(spacedMatch[1]);
1534

16-
// Pattern 2: "B S Computer Science, CS" or "B A Economics"
17-
const spacedMatch = cleanText.match(/B [SA] (.+?)(?:,|\()/);
18-
if (spacedMatch) return spacedMatch[1].trim();
35+
// Other degree letters (keep your behavior, just allow dots/no-space and end-of-string)
36+
const degreeMatch = cleanText.match(/B\.?\s*[A-Z]\.?\s*(.+?)(?:,|\(|$)/i);
37+
if (degreeMatch) return cleanExtractedMajor(degreeMatch[1]);
1938

2039
// Pattern 3: "BSGS, Climate System Science" or "DEGREE_CODE, Major Name"
21-
// Handles degrees where code comes first, then major name after comma
2240
const codeFirstMatch = cleanText.match(/^[A-Z]+,\s*(.+?)(?:\(|$)/);
23-
if (codeFirstMatch) return codeFirstMatch[1].trim();
41+
if (codeFirstMatch) return cleanExtractedMajor(codeFirstMatch[1]);
2442

25-
// Fallback: first line
43+
// Fallback: first token
2644
return cleanText.split(" ")[0];
2745
}
46+
47+
48+
2849

2950
function parseCredential(programText: string): string | null {
3051
const match = programText.match(/- Credential:\s*(.+?)\s*\(/);

0 commit comments

Comments
 (0)