spb/spboucher.ai Public
spboucher.ai — personal website of Simon-Pierre Boucher.
TypeScript 93.4%
HTML 5.5%
CSS 1%
1/*2 page.tsx3 spboucher.ai Web4 Author: Simon-Pierre Boucher5 Mail: contact@spboucher.ai6*/78import type { Metadata } from "next";9import type { LucideIcon } from "lucide-react";10import {11 BadgeCheck,12 BookOpen,13 FileText,14 Github,15 Library,16 NotebookPen,17 PencilLine,18 Presentation,19 School,20 Sigma,21 Terminal,22 Users,23 Wrench,24} from "lucide-react";2526import { Badge } from "@/components/ui/badge";27import {28 Card,29 CardContent,30 CardDescription,31 CardHeader,32 CardTitle,33} from "@/components/ui/card";34import { PillLink } from "@/components/pill-link";35import { Reveal } from "@/components/reveal";36import { SectionHeading } from "@/components/section-heading";3738export const metadata: Metadata = {39 title: "Teaching",40 description:41 "Courses taught by Simon-Pierre Boucher at Université Laval — capital markets, financial econometrics, financial management, and financial theory.",42};4344const UQO_REPO = "https://git.spboucher.ai/uqo_cours_public";45const UQO_RAW =46 "https://raw.githubusercontent.com/spboucher-ai/UQO_COURS_PUBLIC/main";4748const imm1033Slides = [49 "seance01_introduction",50 "seance02_cadre_conceptuel",51 "seance03_evaluation_terrain",52 "seance04_analyse_terrain",53 "seance05_reproduction_remplacement",54 "seance06_methodes_estimation",55 "seance07_couts_directs",56 "seance08_couts_indirects",57 "seance09_concepts_depreciation",58 "seance10_depreciation_physique",59 "seance11_depreciation_fonctionnelle",60 "seance12_depreciation_economique",61 "seance13_applications_specialisees",62 "seance14_synthese_revision",63];6465interface UqoCourse {66 code: string;67 title: string;68 description: string;69 dir: string;70 slides: { label: string; file: string; topic?: string }[];71 tps: { label: string; file: string }[];72}7374const uqoCourses: UqoCourse[] = [75 {76 code: "IMM1003",77 title: "Éléments d'évaluation immobilière",78 description:79 "Foundations of real-estate appraisal — market analysis, comparison and income methods.",80 dir: "IMM1003-20_Elements_evaluation_immobiliere",81 slides: Array.from({ length: 14 }, (_, i) => {82 const n = String(i + 1).padStart(2, "0");83 return { label: n, file: `02_Slides/pdf/seance${n}.pdf` };84 }),85 tps: [86 {87 label: "TP1 — Tableau de bord du marché",88 file: "03_Travaux_pratiques/TP1_Tableau_de_bord_du_marche/enonce/IMM1003-20_TP1_enonce.pdf",89 },90 {91 label: "TP2 — Méthode de comparaison",92 file: "03_Travaux_pratiques/TP2_Methode_de_comparaison/enonce/IMM1003-20_TP2_enonce.pdf",93 },94 {95 label: "TP3 — Méthode du revenu",96 file: "03_Travaux_pratiques/TP3_Methode_du_revenu/enonce/IMM1003-20_TP3_enonce.pdf",97 },98 ],99 },100 {101 code: "IMM1033",102 title: "Méthodes du coût",103 description:104 "Cost approach to valuation — land value, replacement cost, and depreciation analysis.",105 dir: "IMM1033-20_Methodes_du_cout",106 slides: imm1033Slides.map((name, i) => ({107 label: String(i + 1).padStart(2, "0"),108 file: `02_Slides/pdf/${name}.pdf`,109 topic: name.slice(9).replace(/_/g, " "),110 })),111 tps: [112 {113 label: "TP1 — Évaluation d'un terrain",114 file: "03_Travaux_pratiques/TP1_Evaluation_d_un_terrain/enonce/IMM1033-20_TP1_enonce.pdf",115 },116 {117 label: "TP2 — Bordereau de coût neuf",118 file: "03_Travaux_pratiques/TP2_Bordereau_de_cout_neuf/enonce/IMM1033-20_TP2_enonce.pdf",119 },120 {121 label: "TP3 — Ventilation de la dépréciation",122 file: "03_Travaux_pratiques/TP3_Ventilation_de_la_depreciation/enonce/IMM1033-20_TP3_enonce.pdf",123 },124 ],125 },126];127128const GH_RAW = "https://raw.githubusercontent.com/spboucher-ai";129130interface MaterialGroup {131 title: string;132 kind: "pills" | "list";133 icon: LucideIcon;134 links: { label: string; file: string; topic?: string }[];135}136137interface UlavalCourse {138 code: string;139 title: string;140 term: string;141 repoName: string;142 description: string;143 groups: MaterialGroup[];144}145146const ulavalCourses: UlavalCourse[] = [147 {148 code: "GSF-3100",149 title: "Capital Markets (Marché des capitaux)",150 term: "Undergraduate · F2021–W2023",151 repoName: "gsf3100",152 description:153 "Fixed income and capital markets — LaTeX Beamer slides for every section of the course.",154 groups: [155 {156 title: "Slides — 13 section decks (PDF)",157 kind: "pills",158 icon: Presentation,159 links: [160 { label: "01", file: "Section 1/GSF3100_S01.pdf" },161 { label: "02", file: "Section 2/GSF3100_S02.pdf" },162 { label: "03", file: "Section 3/GSF3100_S03.pdf" },163 { label: "04", file: "Section 4/GSF3100_S04.pdf" },164 { label: "05", file: "Section 5/GSF3100_S05.pdf" },165 { label: "06", file: "Section 6/GSF3100_S6.pdf" },166 { label: "07", file: "Section 7/GSF3100_S7.pdf" },167 { label: "08", file: "Section 8/GSF3100_S08.pdf" },168 { label: "9a", file: "Section 9/a/GSF3100_S09a.pdf" },169 { label: "9b", file: "Section 9/b/GSF3100_S09b.pdf" },170 { label: "9c", file: "Section 9/c/GSF3100_S09c.pdf" },171 { label: "10a", file: "Section 10/a/GSF3100_S10a.pdf" },172 { label: "10b", file: "Section 10/b/GSF3100_S10b.pdf" },173 ],174 },175 ],176 },177 {178 code: "GSF-6053",179 title: "Financial Econometrics I",180 term: "Graduate · W2022",181 repoName: "gsf6053",182 description:183 "OLS, MLE, hypothesis testing, and time-series econometrics — session slides plus Stata lab sessions.",184 groups: [185 {186 title: "Slides — sessions 2–12 (PDF)",187 kind: "pills",188 icon: Presentation,189 links: Array.from({ length: 11 }, (_, i) => {190 const n = i + 2;191 return {192 label: String(n).padStart(2, "0"),193 file: `Séance ${n}/GSF6053_S${n}.pdf`,194 };195 }),196 },197 {198 title: "Stata labs (PDF)",199 kind: "list",200 icon: Terminal,201 links: [202 { label: "Stata session 02", file: "STATA_S02/GSF6053_STATA_02.pdf" },203 { label: "Stata session 03", file: "STATA_S03/GSF6053_STATA_03.pdf" },204 ],205 },206 ],207 },208 {209 code: "GSF-6053",210 title: "Financial Econometrics I",211 term: "Graduate · W2025",212 repoName: "gsf6053_h25",213 description:214 "Full W2025 edition — lecture slides, typed lecture notes, formal proofs, and 14 exercise sets with complete solutions.",215 groups: [216 {217 title: "Lecture slides (PDF)",218 kind: "list",219 icon: Presentation,220 links: [221 {222 label: "S1 — Introduction",223 file: "PDF/GSF6053_H25_Séance1_Introduction.pdf",224 },225 {226 label: "S1 — Statistics review",227 file: "PDF/GSF6053_H25_Séance1_Révision.pdf",228 },229 { label: "S1 — OLS (MCO)", file: "PDF/GSF6053_H25_Séance1_MCO.pdf" },230 {231 label: "S2 — Maximum likelihood (MLE)",232 file: "PDF/GSF6053_H25_Séance2_MLE.pdf",233 },234 {235 label: "S3 — Hypothesis tests & ANOVA",236 file: "PDF/GS6053_H25_Séance3_Tests_ANOVA.pdf",237 },238 {239 label: "S4 — Extensions of the linear model",240 file: "PDF/GSF6053_H25_Séance4_Extensions_Modèle_Linéaire.pdf",241 },242 {243 label: "S5 — Heteroskedasticity",244 file: "PDF/GSF6053_H25_Séance5_Hétéroscédasticité.pdf",245 },246 {247 label: "S6 — Autocorrelation",248 file: "PDF/GSF6053_H25_Séance6_Autocorrélation.pdf",249 },250 ],251 },252 {253 title: "Lecture notes (PDF)",254 kind: "list",255 icon: NotebookPen,256 links: [257 { label: "Introduction", file: "PDF/GSF6053_H25_NOTE_INTRO.pdf" },258 {259 label: "Prerequisites",260 file: "PDF/GSF6053_H25_NOTE_PRÉALABLE.pdf",261 },262 { label: "OLS (MCO)", file: "PDF/GSF6053_H25_NOTE_MCO.pdf" },263 { label: "MLE", file: "PDF/GSF6053_H25_NOTE_MLE.pdf" },264 {265 label: "Hypothesis testing",266 file: "PDF/GSF6053_H25_NOTE_Test_hypothèse.pdf",267 },268 { label: "ANOVA", file: "PDF/GSF6053_H25_NOTE_ANOVA.pdf" },269 { label: "GLS (MCG)", file: "PDF/GSF6053_H25_NOTE_MCG.pdf" },270 {271 label: "Heteroskedasticity",272 file: "PDF/GSF6053_H25_NOTE_HETEROSCEDASTICITE.pdf",273 },274 { label: "White test", file: "PDF/GSF6053_H25_NOTE_WHITE_TEST.pdf" },275 {276 label: "Breusch–Pagan test",277 file: "PDF/GSF6053_H25_Note_Breusch_Pagan.pdf",278 },279 {280 label: "Autocorrelation",281 file: "PDF/GSF6053_H25_NOTE_AUTOCORÉLATION.pdf",282 },283 ],284 },285 {286 title: "Formal proofs (PDF)",287 kind: "list",288 icon: Sigma,289 links: [290 {291 label: "OLS — summation form",292 file: "PDF/GSF6053_H25_preuve_MCO_sommation.pdf",293 },294 {295 label: "OLS — matrix form",296 file: "PDF/GSF6053_H25_preuve_MCO_matriciel.pdf",297 },298 { label: "GLS", file: "PDF/GSF6053_H25_preuve_MCG.pdf" },299 { label: "MLE", file: "PDF/GSF6053_H25_preuve_MLE.pdf" },300 {301 label: "Cramér–Rao bound",302 file: "PDF/GSF6053_H25_preuve_cramer_rao.pdf",303 },304 {305 label: "Cochrane–Orcutt",306 file: "PDF/GSF6053_H25_preuve_cochrane_orcutt.pdf",307 },308 {309 label: "Prais–Winsten",310 file: "PDF/GSF6053_H25_preuve_prais_winsten.pdf",311 },312 ],313 },314 {315 title: "Exercise sets 1–14 (PDF)",316 kind: "pills",317 icon: PencilLine,318 links: Array.from({ length: 14 }, (_, i) => {319 const n = String(i + 1).padStart(3, "0");320 return {321 label: String(i + 1).padStart(2, "0"),322 file: `PDF/GSF6053_H25_EXO_${n}.pdf`,323 };324 }),325 },326 {327 title: "Solutions 1–14 (PDF)",328 kind: "pills",329 icon: BadgeCheck,330 links: Array.from({ length: 14 }, (_, i) => {331 const n = String(i + 1).padStart(3, "0");332 return {333 label: String(i + 1).padStart(2, "0"),334 file: `PDF/GSF6053_H25_SOL_${n}.pdf`,335 };336 }),337 },338 ],339 },340];341342const courses = [343 {344 code: "GSF-3100",345 title: "Capital Markets",346 level: "Undergraduate",347 terms: "F2021, W2021, F2022, W2023",348 },349 {350 code: "GSF-6053",351 title: "Financial Econometrics I",352 level: "Graduate",353 terms: "W2022, W2025",354 },355 {356 code: "GSF-1500",357 title: "Financial Management",358 level: "Undergraduate",359 terms: "S2022",360 },361 {362 code: "GSF-6028",363 title: "Financial Theory",364 level: "Graduate",365 terms: "W2024",366 },367];368369const taCourses = [370 { code: "GSF-2101", title: "Portfolio Management" },371 { code: "GSF-2102", title: "Corporate Finance" },372 { code: "GSF-6008", title: "Corporate Finance" },373 { code: "GSF-6025", title: "Financial Strategies & Policies I" },374 { code: "GSF-6028", title: "Financial Theory" },375];376377export default function TeachingPage() {378 return (379 <div className="mx-auto max-w-5xl px-4 py-16 sm:px-6">380 <Reveal>381 <SectionHeading382 as="h1"383 eyebrow="Courses"384 title="Teaching"385 icon={BookOpen}386 description="Professor at Université du Québec en Outaouais (UQO), previously Lecturer (2021–Present) and Teaching Assistant (2018–2021) at Université Laval."387 />388 </Reveal>389390 {/* UQO courses with material */}391 <section className="mt-12">392 <Reveal>393 <SectionHeading394 title="Professor — Université du Québec en Outaouais (UQO)"395 icon={School}396 description="Complete course material — Beamer slides, practical assignments with Excel templates, and a Québec real-estate market report — is openly available on GitHub."397 />398 </Reveal>399 <div className="mt-4 grid gap-4 sm:grid-cols-2">400 {uqoCourses.map((course, i) => (401 <Reveal key={course.code} delay={i * 0.08} className="h-full">402 <Card className="flex h-full flex-col">403 <CardHeader>404 <Badge className="w-fit font-mono">{course.code}</Badge>405 <CardTitle className="text-lg leading-snug">406 {course.title}407 </CardTitle>408 <CardDescription>{course.description}</CardDescription>409 </CardHeader>410 <CardContent className="flex flex-1 flex-col gap-4">411 <div>412 <PillLink413 href={`${UQO_RAW}/${course.dir}/01_Plan_de_cours/plan_de_cours.pdf`}414 icon={FileText}415 >416 Course plan (PDF)417 </PillLink>418 </div>419420 <div>421 <p className="inline-flex items-center gap-2 text-sm font-medium">422 <Presentation423 className="h-4 w-4 text-primary"424 aria-hidden="true"425 />426 Slides — 14 sessions (PDF)427 </p>428 <div className="mt-2 flex flex-wrap gap-1.5">429 {course.slides.map((slide) => (430 <a431 key={slide.file}432 href={`${UQO_RAW}/${course.dir}/${slide.file}`}433 target="_blank"434 rel="noopener noreferrer"435 title={slide.topic}436 aria-label={`Session ${slide.label}${slide.topic ? ` — ${slide.topic}` : ""} (PDF)`}437 className="inline-flex h-8 w-9 items-center justify-center rounded-full border border-border/70 bg-card/70 text-xs font-medium text-muted-foreground shadow-sm transition-all hover:-translate-y-px hover:border-primary/40 hover:bg-primary/10 hover:text-primary"438 >439 {slide.label}440 </a>441 ))}442 </div>443 </div>444445 <div>446 <p className="inline-flex items-center gap-2 text-sm font-medium">447 <Wrench448 className="h-4 w-4 text-primary"449 aria-hidden="true"450 />451 Practical assignments (PDF)452 </p>453 <div className="mt-2 flex flex-wrap gap-1.5">454 {course.tps.map((tp) => (455 <PillLink456 key={tp.file}457 href={`${UQO_RAW}/${course.dir}/${tp.file}`}458 >459 {tp.label}460 </PillLink>461 ))}462 </div>463 </div>464 </CardContent>465 </Card>466 </Reveal>467 ))}468 </div>469 <Reveal className="mt-4">470 <div className="flex flex-wrap gap-2">471 <PillLink472 href={`${UQO_RAW}/Rapport_Immobilier_Quebec/rapport_immobilier_quebec.pdf`}473 icon={FileText}474 >475 Québec real-estate market report (PDF)476 </PillLink>477 <PillLink href={UQO_REPO} icon={Github}>478 Full course repository479 </PillLink>480 </div>481 </Reveal>482 </section>483484 {/* Lecturer */}485 <section className="mt-12">486 <Reveal>487 <SectionHeading488 title="Lecturer — Université Laval (2021–Present)"489 icon={BookOpen}490 />491 <Card className="mt-4 overflow-x-auto">492 <CardContent className="p-0">493 <table className="w-full text-sm">494 <thead>495 <tr className="border-b border-border text-left">496 <th scope="col" className="px-4 py-3 font-medium">497 Code498 </th>499 <th scope="col" className="px-4 py-3 font-medium">500 Course501 </th>502 <th scope="col" className="px-4 py-3 font-medium">503 Level504 </th>505 <th scope="col" className="px-4 py-3 font-medium">506 Terms507 </th>508 </tr>509 </thead>510 <tbody>511 {courses.map((course) => (512 <tr513 key={`${course.code}-${course.terms}`}514 className="border-b border-border last:border-0"515 >516 <td className="px-4 py-3 font-mono text-xs">517 {course.code}518 </td>519 <td className="px-4 py-3 font-medium">{course.title}</td>520 <td className="px-4 py-3">521 <Badge522 variant={523 course.level === "Graduate"524 ? "default"525 : "secondary"526 }527 >528 {course.level}529 </Badge>530 </td>531 <td className="px-4 py-3 text-muted-foreground">532 {course.terms}533 </td>534 </tr>535 ))}536 </tbody>537 </table>538 </CardContent>539 </Card>540 </Reveal>541542 <Reveal className="mt-8">543 <SectionHeading544 as="h3"545 title="Course Material — Université Laval"546 icon={Library}547 description="Complete material from courses previously taught at Université Laval — LaTeX Beamer slides, lecture notes, formal proofs, Stata labs, and exercise sets with solutions — openly available on GitHub."548 />549 </Reveal>550 <div className="mt-4 space-y-4">551 {ulavalCourses.map((course, i) => (552 <Reveal key={course.repoName} delay={i * 0.08}>553 <Card>554 <CardHeader>555 <div className="flex flex-wrap items-center gap-2">556 <Badge className="w-fit font-mono">{course.code}</Badge>557 <Badge variant="secondary" className="w-fit">558 {course.term}559 </Badge>560 </div>561 <CardTitle className="text-lg leading-snug">562 {course.title}563 </CardTitle>564 <CardDescription>{course.description}</CardDescription>565 </CardHeader>566 <CardContent className="flex flex-col gap-4">567 {course.groups.map((group) => (568 <div key={group.title}>569 <p className="inline-flex items-center gap-2 text-sm font-medium">570 <group.icon571 className="h-4 w-4 text-primary"572 aria-hidden="true"573 />574 {group.title}575 </p>576 {group.kind === "pills" ? (577 <div className="mt-2 flex flex-wrap gap-1.5">578 {group.links.map((link) => (579 <a580 key={link.file}581 href={encodeURI(582 `${GH_RAW}/${course.repoName}/main/${link.file}`,583 )}584 target="_blank"585 rel="noopener noreferrer"586 aria-label={`${course.code} — ${group.title} — ${link.label} (PDF)`}587 className="inline-flex h-8 min-w-9 items-center justify-center rounded-full border border-border/70 bg-card/70 px-2 text-xs font-medium text-muted-foreground shadow-sm transition-all hover:-translate-y-px hover:border-primary/40 hover:bg-primary/10 hover:text-primary"588 >589 {link.label}590 </a>591 ))}592 </div>593 ) : (594 <div className="mt-2 flex flex-wrap gap-1.5">595 {group.links.map((link) => (596 <PillLink597 key={link.file}598 href={encodeURI(599 `${GH_RAW}/${course.repoName}/main/${link.file}`,600 )}601 >602 {link.label}603 </PillLink>604 ))}605 </div>606 )}607 </div>608 ))}609 <div>610 <PillLink611 href={`https://git.spboucher.ai/${course.repoName}`}612 icon={Github}613 >614 Full course repository615 </PillLink>616 </div>617 </CardContent>618 </Card>619 </Reveal>620 ))}621 </div>622 </section>623624 {/* Teaching assistant */}625 <section className="mt-12">626 <Reveal>627 <SectionHeading628 title="Teaching Assistant — Université Laval (2018–2021)"629 icon={Users}630 />631 </Reveal>632 <div className="mt-4 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">633 {taCourses.map((course, i) => (634 <Reveal key={`${course.code}-${course.title}`} delay={i * 0.06}>635 <Card className="h-full">636 <CardHeader>637 <Badge variant="outline" className="w-fit font-mono">638 {course.code}639 </Badge>640 <CardTitle className="text-base">{course.title}</CardTitle>641 </CardHeader>642 </Card>643 </Reveal>644 ))}645 </div>646 </section>647 </div>648 );649}650