Fix certificate View link (wrong /study/certificate URL), certificates in My Account, name on certificate; v2.10.10
Publish Container / build (push) Successful in 15m29s
Publish Container / build (push) Successful in 15m29s
- Certificate URLs in the account overview and the issuance email pointed at /study/certificate/:token, which the router treated as a lesson page; now /certificate/:token (old links redirect) - My Account Certificates card lists every enrolled study: progress, Generate, View, Copy link, Download PNG, Share - Certificate canvas used a non-existent /api/study-account route and always printed 'Student'; now reads the account name - Panel no longer collapses after generating Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
899e715067
commit
7301982bb1
8 files changed
+123
-30
No files matched your search
+34
-10
@@ -2872,6 +2872,7 @@ export function StudyAccountPage() {
|
||||
const [pwMessage, setPwMessage] = useState('')
|
||||
const [pwSuccess, setPwSuccess] = useState(false)
|
||||
|
||||
const [certOpen, setCertOpen] = useState<Record<string, boolean>>({})
|
||||
const [signOutBusy, setSignOutBusy] = useState(false)
|
||||
const [signOutAllBusy, setSignOutAllBusy] = useState(false)
|
||||
const [signOutAllMessage, setSignOutAllMessage] = useState('')
|
||||
@@ -3298,18 +3299,41 @@ export function StudyAccountPage() {
|
||||
})}
|
||||
</section>
|
||||
|
||||
{overview.certificates.length > 0 && (
|
||||
{enrolledProgress.length > 0 && (
|
||||
<section className="account-card" aria-label="Certificates">
|
||||
<div className="account-card-head"><h2>Certificates</h2></div>
|
||||
{overview.certificates.map(cert => (
|
||||
<div className="account-cert" key={cert.studySlug}>
|
||||
<span>🏅 {cert.studyTitle} <small>— {new Date(cert.issuedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}</small></span>
|
||||
<div className="account-cert-actions">
|
||||
<a href={cert.url} target="_blank" rel="noopener noreferrer" className="btn-secondary">View</a>
|
||||
<button type="button" className="btn-secondary" onClick={() => { navigator.clipboard?.writeText(cert.url).catch(() => {}) }}>Copy link</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<p className="account-muted">Finish every lesson in a study to earn a certificate of completion you can view, download and share.</p>
|
||||
{enrolledProgress.map(item => {
|
||||
const cert = overview.certificates.find(c => c.studySlug === item.slug)
|
||||
const ready = !cert && item.completedLessons >= item.totalLessons
|
||||
return (
|
||||
<details
|
||||
className="account-cert-study"
|
||||
key={item.slug}
|
||||
open={certOpen[item.slug] ?? ready}
|
||||
onToggle={e => {
|
||||
const isOpen = (e.currentTarget as HTMLDetailsElement).open
|
||||
setCertOpen(prev => (prev[item.slug] === isOpen ? prev : { ...prev, [item.slug]: isOpen }))
|
||||
}}
|
||||
>
|
||||
<summary>
|
||||
<span className="account-cert-title">{cert ? '🏅' : '🎓'} {item.title}</span>
|
||||
{cert
|
||||
? <span className="account-chip account-chip--ok">Earned {new Date(cert.issuedAt).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}</span>
|
||||
: ready
|
||||
? <span className="account-chip account-chip--warn">Ready to claim</span>
|
||||
: <span className="account-chip account-chip--muted">{item.completedLessons} of {item.totalLessons} lessons</span>}
|
||||
</summary>
|
||||
{cert && (
|
||||
<div className="account-cert-actions">
|
||||
<Link to={new URL(cert.url).pathname} target="_blank" rel="noopener noreferrer" className="btn-primary">View certificate</Link>
|
||||
<button type="button" className="btn-secondary" onClick={() => { navigator.clipboard?.writeText(cert.url).catch(() => {}) }}>Copy link</button>
|
||||
</div>
|
||||
)}
|
||||
<StudyCertificate studySlug={item.slug} onIssued={() => { void refreshOverview() }} />
|
||||
</details>
|
||||
)
|
||||
})}
|
||||
</section>
|
||||
)}
|
||||
|
||||
|
||||
Reference in new issue
Block a user