Skip to content

Commit f7cd37e

Browse files
committed
feat(#78): add Open in SIS button to student detail page
1 parent c06d4f8 commit f7cd37e

1 file changed

Lines changed: 53 additions & 1 deletion

File tree

  • codebenders-dashboard/app/students/[guid]

codebenders-dashboard/app/students/[guid]/page.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useEffect, useState } from "react"
44
import { useParams, useRouter } from "next/navigation"
5-
import { ArrowLeft, ShieldCheck } from "lucide-react"
5+
import { ArrowLeft, ExternalLink, ShieldCheck } from "lucide-react"
66
import { Button } from "@/components/ui/button"
77
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
88

@@ -88,6 +88,8 @@ export default function StudentDetailPage() {
8888
const [student, setStudent] = useState<StudentDetail | null>(null)
8989
const [loading, setLoading] = useState(true)
9090
const [error, setError] = useState<string | null>(null)
91+
const [sisLink, setSisLink] = useState<string | null>(null)
92+
const [sisStatus, setSisStatus] = useState<"loading" | "available" | "unavailable" | "hidden">("loading")
9193

9294
useEffect(() => {
9395
if (!guid) return
@@ -102,6 +104,33 @@ export default function StudentDetailPage() {
102104
.catch(e => { setError(e.message); setLoading(false) })
103105
}, [guid])
104106

107+
useEffect(() => {
108+
if (!guid) return
109+
fetch(`/api/students/${encodeURIComponent(guid)}/sis-link`)
110+
.then(r => {
111+
if (r.status === 403) {
112+
setSisStatus("hidden")
113+
return null
114+
}
115+
if (r.status === 404) {
116+
setSisStatus("unavailable")
117+
return null
118+
}
119+
if (!r.ok) {
120+
setSisStatus("hidden")
121+
return null
122+
}
123+
return r.json()
124+
})
125+
.then(data => {
126+
if (data?.url) {
127+
setSisLink(data.url)
128+
setSisStatus("available")
129+
}
130+
})
131+
.catch(() => setSisStatus("hidden"))
132+
}, [guid])
133+
105134
// ─── Loading skeleton ────────────────────────────────────────────────────
106135

107136
if (loading) {
@@ -179,6 +208,29 @@ export default function StudentDetailPage() {
179208
</div>
180209
</div>
181210
<div className="flex items-center gap-2">
211+
{sisStatus === "available" && sisLink && (
212+
<Button
213+
variant="outline"
214+
size="sm"
215+
className="gap-1.5"
216+
onClick={() => window.open(sisLink, "_blank", "noopener,noreferrer")}
217+
>
218+
<ExternalLink className="h-3.5 w-3.5" />
219+
Open in SIS
220+
</Button>
221+
)}
222+
{sisStatus === "unavailable" && (
223+
<Button
224+
variant="outline"
225+
size="sm"
226+
className="gap-1.5 opacity-50 cursor-not-allowed"
227+
disabled
228+
title="No SIS record linked for this student"
229+
>
230+
<ExternalLink className="h-3.5 w-3.5" />
231+
Open in SIS
232+
</Button>
233+
)}
182234
{student.at_risk_alert && (
183235
<Badge
184236
label={student.at_risk_alert}

0 commit comments

Comments
 (0)