Teaching: direct PDF links for every slide, course plan and TP
Each UQO course card now links directly to all 14 session slide PDFs (numbered pill per séance, topic tooltip on IMM1033), the course plan, and each TP énoncé by name — all via raw.githubusercontent.com so the PDF opens directly in the browser. All 37 URLs verified 200. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 1 changed file with +117 and −24
modified
app/teaching/page.tsx
+117 −24
@@ -25,15 +25,60 @@ export const metadata: Metadata = { | ||
| 25 | 25 | }; |
| 26 | 26 | |
| 27 | 27 | const UQO_REPO = "https://github.com/spboucher-ai/UQO_COURS_PUBLIC"; |
| 28 | +const UQO_RAW = | |
| 29 | + "https://raw.githubusercontent.com/spboucher-ai/UQO_COURS_PUBLIC/main"; | |
| 28 | 30 | |
| 29 | −const uqoCourses = [ | |
| 31 | +const imm1033Slides = [ | |
| 32 | + "seance01_introduction", | |
| 33 | + "seance02_cadre_conceptuel", | |
| 34 | + "seance03_evaluation_terrain", | |
| 35 | + "seance04_analyse_terrain", | |
| 36 | + "seance05_reproduction_remplacement", | |
| 37 | + "seance06_methodes_estimation", | |
| 38 | + "seance07_couts_directs", | |
| 39 | + "seance08_couts_indirects", | |
| 40 | + "seance09_concepts_depreciation", | |
| 41 | + "seance10_depreciation_physique", | |
| 42 | + "seance11_depreciation_fonctionnelle", | |
| 43 | + "seance12_depreciation_economique", | |
| 44 | + "seance13_applications_specialisees", | |
| 45 | + "seance14_synthese_revision", | |
| 46 | +]; | |
| 47 | + | |
| 48 | +interface UqoCourse { | |
| 49 | + code: string; | |
| 50 | + title: string; | |
| 51 | + description: string; | |
| 52 | + dir: string; | |
| 53 | + slides: { label: string; file: string; topic?: string }[]; | |
| 54 | + tps: { label: string; file: string }[]; | |
| 55 | +} | |
| 56 | + | |
| 57 | +const uqoCourses: UqoCourse[] = [ | |
| 30 | 58 | { |
| 31 | 59 | code: "IMM1003", |
| 32 | 60 | title: "Éléments d'évaluation immobilière", |
| 33 | 61 | description: |
| 34 | 62 | "Foundations of real-estate appraisal — market analysis, comparison and income methods.", |
| 35 | 63 | dir: "IMM1003-20_Elements_evaluation_immobiliere", |
| 36 | − slidesLabel: "Slides — 14 sessions (PDF)", | |
| 64 | + slides: Array.from({ length: 14 }, (_, i) => { | |
| 65 | + const n = String(i + 1).padStart(2, "0"); | |
| 66 | + return { label: n, file: `02_Slides/pdf/seance${n}.pdf` }; | |
| 67 | + }), | |
| 68 | + tps: [ | |
| 69 | + { | |
| 70 | + label: "TP1 — Tableau de bord du marché", | |
| 71 | + file: "03_Travaux_pratiques/TP1_Tableau_de_bord_du_marche/enonce/IMM1003-20_TP1_enonce.pdf", | |
| 72 | + }, | |
| 73 | + { | |
| 74 | + label: "TP2 — Méthode de comparaison", | |
| 75 | + file: "03_Travaux_pratiques/TP2_Methode_de_comparaison/enonce/IMM1003-20_TP2_enonce.pdf", | |
| 76 | + }, | |
| 77 | + { | |
| 78 | + label: "TP3 — Méthode du revenu", | |
| 79 | + file: "03_Travaux_pratiques/TP3_Methode_du_revenu/enonce/IMM1003-20_TP3_enonce.pdf", | |
| 80 | + }, | |
| 81 | + ], | |
| 37 | 82 | }, |
| 38 | 83 | { |
| 39 | 84 | code: "IMM1033", |
@@ -41,7 +86,25 @@ const uqoCourses = [ | ||
| 41 | 86 | description: |
| 42 | 87 | "Cost approach to valuation — land value, replacement cost, and depreciation analysis.", |
| 43 | 88 | dir: "IMM1033-20_Methodes_du_cout", |
| 44 | − slidesLabel: "Slides — 14 sessions (PDF)", | |
| 89 | + slides: imm1033Slides.map((name, i) => ({ | |
| 90 | + label: String(i + 1).padStart(2, "0"), | |
| 91 | + file: `02_Slides/pdf/${name}.pdf`, | |
| 92 | + topic: name.slice(9).replace(/_/g, " "), | |
| 93 | + })), | |
| 94 | + tps: [ | |
| 95 | + { | |
| 96 | + label: "TP1 — Évaluation d'un terrain", | |
| 97 | + file: "03_Travaux_pratiques/TP1_Evaluation_d_un_terrain/enonce/IMM1033-20_TP1_enonce.pdf", | |
| 98 | + }, | |
| 99 | + { | |
| 100 | + label: "TP2 — Bordereau de coût neuf", | |
| 101 | + file: "03_Travaux_pratiques/TP2_Bordereau_de_cout_neuf/enonce/IMM1033-20_TP2_enonce.pdf", | |
| 102 | + }, | |
| 103 | + { | |
| 104 | + label: "TP3 — Ventilation de la dépréciation", | |
| 105 | + file: "03_Travaux_pratiques/TP3_Ventilation_de_la_depreciation/enonce/IMM1033-20_TP3_enonce.pdf", | |
| 106 | + }, | |
| 107 | + ], | |
| 45 | 108 | }, |
| 46 | 109 | ]; |
| 47 | 110 | |
@@ -127,9 +190,9 @@ export default function TeachingPage() { | ||
| 127 | 190 | </CardTitle> |
| 128 | 191 | <CardDescription>{course.description}</CardDescription> |
| 129 | 192 | </CardHeader> |
| 130 | − <CardContent className="flex flex-1 flex-col gap-2.5"> | |
| 193 | + <CardContent className="flex flex-1 flex-col gap-4"> | |
| 131 | 194 | <a |
| 132 | − href={`${UQO_REPO}/blob/main/${course.dir}/01_Plan_de_cours/plan_de_cours.pdf`} | |
| 195 | + href={`${UQO_RAW}/${course.dir}/01_Plan_de_cours/plan_de_cours.pdf`} | |
| 133 | 196 | target="_blank" |
| 134 | 197 | rel="noopener noreferrer" |
| 135 | 198 | className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline" |
@@ -137,24 +200,54 @@ export default function TeachingPage() { | ||
| 137 | 200 | <FileText className="h-4 w-4" aria-hidden="true" /> |
| 138 | 201 | Course plan (PDF) |
| 139 | 202 | </a> |
| 140 | − <a | |
| 141 | − href={`${UQO_REPO}/tree/main/${course.dir}/02_Slides/pdf`} | |
| 142 | − target="_blank" | |
| 143 | − rel="noopener noreferrer" | |
| 144 | − className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline" | |
| 145 | − > | |
| 146 | − <Presentation className="h-4 w-4" aria-hidden="true" /> | |
| 147 | − {course.slidesLabel} | |
| 148 | − </a> | |
| 149 | − <a | |
| 150 | − href={`${UQO_REPO}/tree/main/${course.dir}/03_Travaux_pratiques`} | |
| 151 | − target="_blank" | |
| 152 | − rel="noopener noreferrer" | |
| 153 | − className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline" | |
| 154 | − > | |
| 155 | − <Wrench className="h-4 w-4" aria-hidden="true" /> | |
| 156 | − Practical assignments (3 TPs) | |
| 157 | − </a> | |
| 203 | + | |
| 204 | + <div> | |
| 205 | + <p className="inline-flex items-center gap-2 text-sm font-medium"> | |
| 206 | + <Presentation | |
| 207 | + className="h-4 w-4 text-primary" | |
| 208 | + aria-hidden="true" | |
| 209 | + /> | |
| 210 | + Slides — 14 sessions (PDF) | |
| 211 | + </p> | |
| 212 | + <div className="mt-2 flex flex-wrap gap-1.5"> | |
| 213 | + {course.slides.map((slide) => ( | |
| 214 | + <a | |
| 215 | + key={slide.file} | |
| 216 | + href={`${UQO_RAW}/${course.dir}/${slide.file}`} | |
| 217 | + target="_blank" | |
| 218 | + rel="noopener noreferrer" | |
| 219 | + title={slide.topic} | |
| 220 | + aria-label={`Session ${slide.label}${slide.topic ? ` — ${slide.topic}` : ""} (PDF)`} | |
| 221 | + className="inline-flex h-8 w-9 items-center justify-center rounded-full border border-border/70 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/40 hover:bg-accent hover:text-primary" | |
| 222 | + > | |
| 223 | + {slide.label} | |
| 224 | + </a> | |
| 225 | + ))} | |
| 226 | + </div> | |
| 227 | + </div> | |
| 228 | + | |
| 229 | + <div> | |
| 230 | + <p className="inline-flex items-center gap-2 text-sm font-medium"> | |
| 231 | + <Wrench | |
| 232 | + className="h-4 w-4 text-primary" | |
| 233 | + aria-hidden="true" | |
| 234 | + /> | |
| 235 | + Practical assignments (PDF) | |
| 236 | + </p> | |
| 237 | + <div className="mt-2 flex flex-col gap-1.5"> | |
| 238 | + {course.tps.map((tp) => ( | |
| 239 | + <a | |
| 240 | + key={tp.file} | |
| 241 | + href={`${UQO_RAW}/${course.dir}/${tp.file}`} | |
| 242 | + target="_blank" | |
| 243 | + rel="noopener noreferrer" | |
| 244 | + className="text-sm text-primary hover:underline" | |
| 245 | + > | |
| 246 | + {tp.label} | |
| 247 | + </a> | |
| 248 | + ))} | |
| 249 | + </div> | |
| 250 | + </div> | |
| 158 | 251 | </CardContent> |
| 159 | 252 | </Card> |
| 160 | 253 | </Reveal> |
@@ -163,7 +256,7 @@ export default function TeachingPage() { | ||
| 163 | 256 | <Reveal className="mt-4"> |
| 164 | 257 | <div className="flex flex-wrap gap-4"> |
| 165 | 258 | <a |
| 166 | − href={`${UQO_REPO}/blob/main/Rapport_Immobilier_Quebec/rapport_immobilier_quebec.pdf`} | |
| 259 | + href={`${UQO_RAW}/Rapport_Immobilier_Quebec/rapport_immobilier_quebec.pdf`} | |
| 167 | 260 | target="_blank" |
| 168 | 261 | rel="noopener noreferrer" |
| 169 | 262 | className="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline" |
| 170 | 263 | |