Ilo/design/student-screens.jsx
2026-05-02 20:01:30 +03:30

448 lines
25 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Student-facing screens: dashboard (continue learning), catalog, course detail.
function StudentSidebar({ active, onNav }) {
const items = [
{ id: 'dash', fa: 'خانه', icon: 'home' },
{ id: 'mycourses',fa: 'دوره‌های من', icon: 'book', badge: '۳' },
{ id: 'catalog', fa: 'کاوش دوره‌ها', icon: 'search' },
{ id: 'cert', fa: 'گواهی‌نامه‌ها', icon: 'cert' },
{ id: 'chat', fa: 'گفت‌وگو', icon: 'chat' },
];
return (
<aside className="sb">
<div className="sb-brand">
<div className="sb-mark">il</div>
<div>
<div className="sb-name">ایلو</div>
<div className="sb-sub en">student</div>
</div>
</div>
<div className="sb-section">یادگیری</div>
{items.map(n => (
<button key={n.id} className="sb-item"
aria-current={active === n.id ? 'page' : undefined}
onClick={() => onNav(n.id)}>
<Icon name={n.icon} />
<span>{n.fa}</span>
{n.badge && <span className="badge num">{n.badge}</span>}
</button>
))}
<div className="sb-bottom">
<button className="sb-item"><Icon name="cog" /><span>تنظیمات</span></button>
<div className="sb-user">
<div className="sb-avatar" style={{ background: 'linear-gradient(135deg, oklch(0.78 0.10 260), oklch(0.72 0.10 220))' }}>سم</div>
<div className="sb-user-meta">
<div className="sb-user-name">سارا محمدی</div>
<div className="sb-user-role">عضو از ۱۴۰۳/۰۹</div>
</div>
</div>
</div>
</aside>
);
}
function CourseCard({ c, onOpen }) {
return (
<div className="card" onClick={() => onOpen?.(c)} style={{ cursor: 'pointer', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
<div style={{ aspectRatio: '16/10', background: c.color, position: 'relative', display: 'grid', placeItems: 'center', color: 'white' }}>
<Icon name="book" style={{ width: 32, height: 32, opacity: 0.9 }} />
{c.badge && (
<span style={{ position: 'absolute', top: 12, insetInlineStart: 12, background: 'rgba(255,255,255,.95)', color: 'var(--ink)', padding: '4px 10px', borderRadius: 999, fontSize: 11, fontWeight: 600 }}>
{c.badge}
</span>
)}
</div>
<div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 10, flex: 1 }}>
<div className="muted" style={{ fontSize: 11.5 }}>{c.cat} · {c.level}</div>
<div style={{ fontSize: 15, fontWeight: 600, lineHeight: 1.4, minHeight: 42 }}>{c.title}</div>
<div className="muted" style={{ fontSize: 12 }}>توسط {c.instructor}</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
{c.rating && (<>
<Icon name="star" className="ic-sm" style={{ color: 'oklch(0.74 0.13 70)', fill: 'oklch(0.78 0.13 70)' }} />
<span className="num" style={{ fontWeight: 600 }}>{String(c.rating).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])}</span>
<span className="muted num">({String(c.reviews).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])})</span>
</>)}
<span className="muted" style={{ marginInlineStart: 'auto' }} className="num">
<Icon name="clock" className="ic-sm" /> {String(c.hours).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d])} ساعت
</span>
</div>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginTop: 'auto', paddingTop: 8, borderTop: '1px solid var(--line-soft)' }}>
<span className="num" style={{ fontSize: 16, fontWeight: 700 }}>{c.price}</span>
<span className="muted" style={{ fontSize: 11 }}>تومان</span>
{c.oldPrice && (
<span className="muted num" style={{ fontSize: 12, textDecoration: 'line-through', marginInlineStart: 'auto' }}>{c.oldPrice}</span>
)}
</div>
</div>
</div>
);
}
function fa(s) { return String(s).replace(/\d/g, d => '۰۱۲۳۴۵۶۷۸۹'[d]); }
// — Dashboard —
function StudentDash({ onOpen }) {
const { MY_COURSES, CATALOG, FEATURED_INSTRUCTORS } = window.STUDENT_DATA;
const inProgress = MY_COURSES.filter(c => !c.completed);
const continueWith = inProgress[0];
return (
<div className="page-inner">
{/* greeting + continue hero */}
<div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 'var(--gap-lg)' }}>
<div className="card card-pad" style={{ background: 'linear-gradient(135deg, var(--accent-soft), color-mix(in oklch, var(--accent-soft) 50%, var(--surface)))', borderColor: 'transparent', minHeight: 200 }}>
<div className="muted" style={{ fontSize: 13, marginBottom: 6 }}>سلام سارا 👋 ادامه بدیم؟</div>
<h1 style={{ fontSize: 24, fontWeight: 700, letterSpacing: '-0.015em', margin: '0 0 6px' }}>{continueWith.title}</h1>
<div className="muted" style={{ fontSize: 13, marginBottom: 16 }}>درس بعدی: {continueWith.nextLesson}</div>
<div style={{ marginBottom: 16 }}>
<div className="prog"><i style={{ width: continueWith.progress + '%' }} /></div>
<div className="muted num" style={{ fontSize: 11.5, marginTop: 6, display: 'flex', justifyContent: 'space-between' }}>
<span>{fa(continueWith.completedLessons)} از {fa(continueWith.totalLessons)} درس</span>
<span>{fa(continueWith.progress)}٪</span>
</div>
</div>
<div style={{ display: 'flex', gap: 8 }}>
<button className="btn primary"><Icon name="play" className="ic-sm" /> ادامهی یادگیری</button>
<button className="btn">جزئیات دوره</button>
</div>
</div>
<div className="card card-pad col">
<div className="between">
<span style={{ fontSize: 14, fontWeight: 600 }}>هدف هفتگی</span>
<span className="pill ok num">۴ از ۵ روز</span>
</div>
<div style={{ display: 'flex', gap: 8, justifyContent: 'space-between' }}>
{['ش','ی','د','س','چ','پ','ج'].map((d, i) => (
<div key={i} style={{ flex: 1, textAlign: 'center' }}>
<div className="muted" style={{ fontSize: 11, marginBottom: 6 }}>{d}</div>
<div style={{
width: '100%', aspectRatio: '1', borderRadius: 8,
background: i < 4 ? 'var(--accent)' : (i === 4 ? 'var(--accent-soft)' : 'var(--surface-2)'),
display: 'grid', placeItems: 'center',
color: i < 4 ? 'white' : 'var(--ink-3)',
}}>
{i < 4 && <Icon name="flame" className="ic-sm" />}
{i === 4 && <span style={{ fontSize: 10, fontWeight: 700 }}>اکنون</span>}
</div>
</div>
))}
</div>
<div className="muted" style={{ fontSize: 12.5 }}>
<Icon name="flame" className="ic-sm" style={{ color: 'var(--accent)' }} /> ۴ روز پیاپی! امروز هم ادامه بده.
</div>
</div>
</div>
{/* my courses */}
<div>
<div className="page-h" style={{ marginBottom: 16 }}>
<h1 style={{ fontSize: 18 }}>دورههای من</h1>
<a className="muted" style={{ fontSize: 13, cursor: 'pointer' }}>مشاهده همه </a>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 'var(--gap-md)' }}>
{MY_COURSES.map(c => (
<div key={c.id} className="card" style={{ overflow: 'hidden', cursor: 'pointer' }}>
<div style={{ aspectRatio: '16/8', background: c.color, position: 'relative', display: 'grid', placeItems: 'center' }}>
<div style={{ width: 48, height: 48, borderRadius: '50%', background: 'rgba(255,255,255,.95)', display: 'grid', placeItems: 'center', color: 'var(--accent)' }}>
<Icon name="play" style={{ width: 22, height: 22 }} />
</div>
{c.completed && <span className="pill ok" style={{ position: 'absolute', top: 12, insetInlineStart: 12, background: 'white' }}><Icon name="check" className="ic-sm" /> تکمیل شد</span>}
</div>
<div style={{ padding: 14 }}>
<div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>{c.title}</div>
<div className="muted" style={{ fontSize: 12, marginBottom: 12 }}>توسط {c.instructor}</div>
<div className="prog" style={{ marginBottom: 6 }}><i style={{ width: c.progress + '%', background: c.completed ? 'oklch(0.62 0.14 155)' : 'var(--accent)' }} /></div>
<div className="muted num" style={{ fontSize: 11.5, display: 'flex', justifyContent: 'space-between' }}>
<span>{fa(c.completedLessons)} از {fa(c.totalLessons)} درس</span>
<span>{fa(c.progress)}٪</span>
</div>
</div>
</div>
))}
</div>
</div>
{/* recommended */}
<div>
<div className="page-h" style={{ marginBottom: 16 }}>
<div>
<h1 style={{ fontSize: 18 }}>پیشنهاد برای تو</h1>
<p className="lede">بر اساس دورههای در حال یادگیری</p>
</div>
<a className="muted" style={{ fontSize: 13, cursor: 'pointer' }} onClick={() => onOpen('catalog')}>کاوش بیشتر </a>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 'var(--gap-md)' }}>
{CATALOG.slice(0, 4).map(c => <CourseCard key={c.id} c={c} onOpen={() => onOpen('detail')} />)}
</div>
</div>
</div>
);
}
// — Catalog —
function StudentCatalog({ onOpen }) {
const { CATALOG, CATEGORIES, FEATURED_INSTRUCTORS } = window.STUDENT_DATA;
const [cat, setCat] = React.useState('all');
return (
<div className="page-inner">
{/* hero search */}
<div className="card card-pad" style={{ background: 'linear-gradient(135deg, oklch(0.96 0.04 40), oklch(0.97 0.03 60))', borderColor: 'transparent', textAlign: 'center', padding: '40px 24px' }}>
<h1 style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.015em', margin: '0 0 8px' }}>چی میخوای یاد بگیری امروز؟</h1>
<p className="lede" style={{ marginBottom: 20 }}>۲۴۰ دوره از بهترین مدرسهای ایران</p>
<div className="search" style={{ maxWidth: 520, margin: '0 auto', padding: '10px 16px', background: 'white', height: 'auto' }}>
<Icon name="search" />
<input placeholder="جستجو در دوره‌ها، مدرس‌ها، موضوع‌ها…" style={{ fontSize: 14 }} />
<button className="btn primary sm">جستجو</button>
</div>
</div>
{/* categories */}
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
{CATEGORIES.map(c => (
<button key={c.id} className="btn sm" onClick={() => setCat(c.id)}
style={{
background: cat === c.id ? 'var(--accent)' : 'var(--surface)',
color: cat === c.id ? 'white' : 'var(--ink)',
borderColor: cat === c.id ? 'transparent' : 'var(--line)',
padding: '8px 14px',
}}>
{c.fa}
<span className="num" style={{ marginInlineStart: 4, opacity: 0.7 }}>{fa(c.count)}</span>
</button>
))}
</div>
{/* featured instructors strip */}
<div className="card">
<div className="card-h">
<div>
<h3>مدرسهای منتخب</h3>
<div className="muted" style={{ fontSize: 12, marginTop: 2 }}>پس از خرید پکیج هر مدرس، به فضای اختصاصی او دسترسی پیدا میکنی</div>
</div>
<a className="muted" style={{ fontSize: 13, cursor: 'pointer' }}>همه </a>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, padding: 16 }}>
{FEATURED_INSTRUCTORS.map(i => (
<div key={i.id} style={{ padding: 14, border: '1px solid var(--line)', borderRadius: 'var(--r-md)', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', gap: 8, cursor: 'pointer' }}>
<div className="av av-lg" style={{ background: i.color, width: 56, height: 56, fontSize: 16 }}>{i.initials}</div>
<div>
<div style={{ fontSize: 14, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 4, justifyContent: 'center' }}>
{i.name}
{i.verified && <Icon name="check" className="ic-sm" style={{ color: 'var(--accent)', background: 'var(--accent-soft)', borderRadius: '50%', padding: 2, width: 14, height: 14 }} />}
</div>
<div className="muted" style={{ fontSize: 11.5, marginTop: 2 }}>{i.topic}</div>
</div>
<div className="muted num" style={{ fontSize: 11 }}>
{fa(i.rating)} · {fa(i.students)} دانشجو
</div>
</div>
))}
</div>
</div>
{/* course grid */}
<div>
<div className="between" style={{ marginBottom: 16 }}>
<h1 style={{ fontSize: 18, margin: 0 }}>همهی دورهها</h1>
<div style={{ display: 'flex', gap: 8 }}>
<button className="btn sm"><Icon name="sort" className="ic-sm" /> مرتبسازی</button>
<button className="btn sm"><Icon name="filter" className="ic-sm" /> فیلترها</button>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 'var(--gap-md)' }}>
{CATALOG.map(c => <CourseCard key={c.id} c={c} onOpen={() => onOpen('detail')} />)}
</div>
</div>
</div>
);
}
// — Course Detail —
function StudentCourseDetail() {
const c = window.STUDENT_DATA.COURSE_DETAIL;
const [tab, setTab] = React.useState('overview');
return (
<div className="page-inner">
{/* hero */}
<div className="card" style={{ overflow: 'hidden' }}>
<div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', minHeight: 280 }}>
<div style={{ padding: 32, display: 'flex', flexDirection: 'column', gap: 14 }}>
<div style={{ display: 'flex', gap: 8 }}>
<span className="pill accent">پرفروش</span>
<span className="pill">طراحی</span>
<span className="pill">{c.level}</span>
</div>
<div>
<h1 style={{ fontSize: 28, fontWeight: 700, letterSpacing: '-0.015em', margin: '0 0 6px' }}>{c.title}</h1>
<div className="muted en" style={{ fontSize: 13 }}>{c.titleEn}</div>
</div>
<p className="lede" style={{ fontSize: 15, lineHeight: 1.7, margin: 0 }}>{c.tagline}</p>
<div style={{ display: 'flex', alignItems: 'center', gap: 16, fontSize: 13 }}>
<span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<Icon name="star" className="ic-sm" style={{ color: 'oklch(0.74 0.13 70)' }} />
<b className="num">{fa(c.rating)}</b>
<span className="muted num">({fa(c.reviews)} نظر)</span>
</span>
<span className="muted num"><Icon name="users" className="ic-sm" /> {fa(c.students)} دانشجو</span>
<span className="muted num"><Icon name="clock" className="ic-sm" /> {fa(c.hours)} ساعت</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 'auto', paddingTop: 12, borderTop: '1px solid var(--line-soft)' }}>
<div className="av av-lg" style={{ background: c.instructor.color }}>{c.instructor.initials}</div>
<div>
<div style={{ fontSize: 13.5, fontWeight: 600 }}>توسط {c.instructor.name}</div>
<div className="muted" style={{ fontSize: 11.5 }}>{c.instructor.topic}</div>
</div>
</div>
</div>
<div style={{ background: c.color, position: 'relative', display: 'grid', placeItems: 'center' }}>
<div style={{ width: 80, height: 80, borderRadius: '50%', background: 'rgba(255,255,255,.95)', display: 'grid', placeItems: 'center', boxShadow: '0 12px 32px rgba(0,0,0,.2)' }}>
<Icon name="play" style={{ color: 'var(--accent)', width: 32, height: 32 }} />
</div>
<div style={{ position: 'absolute', bottom: 16, insetInlineStart: 16, background: 'rgba(0,0,0,.5)', color: 'white', padding: '6px 12px', borderRadius: 999, fontSize: 12 }}>
پیشنمایش رایگان · ۲ دقیقه
</div>
</div>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: '1.5fr 1fr', gap: 'var(--gap-lg)', alignItems: 'flex-start' }}>
<div className="col">
{/* highlights */}
<div className="card card-pad">
<h3 style={{ margin: '0 0 16px', fontSize: 16 }}>چی یاد میگیری</h3>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
{c.highlights.map((h, i) => (
<div key={i} style={{ display: 'flex', gap: 10, fontSize: 13.5 }}>
<Icon name="check" className="ic-sm" style={{ color: 'var(--accent)', flexShrink: 0, marginTop: 2 }} />
<span>{h}</span>
</div>
))}
</div>
</div>
{/* tabs */}
<div className="card">
<div className="tabs" style={{ paddingInline: 20 }}>
{[['overview','سرفصل‌ها'],['instructor','مدرس'],['reviews','نظرات'],['faq','سؤالات']].map(([k,v]) => (
<button key={k} className="tab" aria-selected={tab===k} onClick={() => setTab(k)}>{v}</button>
))}
</div>
{tab === 'overview' && (
<div style={{ padding: 6 }}>
{c.curriculum.map((m, i) => (
<div key={i} style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px', borderTop: i ? '1px solid var(--line-soft)' : 'none' }}>
<div style={{ width: 28, height: 28, borderRadius: 8, background: 'var(--accent-soft)', color: 'var(--accent-ink)', display: 'grid', placeItems: 'center', fontSize: 12, fontWeight: 700 }}>{fa(i+1)}</div>
<div style={{ flex: 1 }}>
<div style={{ fontSize: 14, fontWeight: 600 }}>{m.title}</div>
<div className="muted num" style={{ fontSize: 11.5, marginTop: 2 }}>{fa(m.lessons)} درس · {fa(m.minutes)} دقیقه</div>
</div>
<Icon name="chevron" className="ic-sm flipx" style={{ color: 'var(--ink-3)' }} />
</div>
))}
</div>
)}
{tab === 'instructor' && (
<div style={{ padding: 24 }}>
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
<div className="av av-lg" style={{ background: c.instructor.color, width: 64, height: 64, fontSize: 18 }}>{c.instructor.initials}</div>
<div>
<div style={{ fontSize: 18, fontWeight: 700 }}>{c.instructor.name}</div>
<div className="muted" style={{ fontSize: 13 }}>{c.instructor.topic}</div>
<div style={{ display: 'flex', gap: 14, marginTop: 8, fontSize: 12 }}>
<span className="num"> {fa(c.instructor.rating)}</span>
<span className="muted num">{fa(c.instructor.students)} دانشجو</span>
<span className="muted num">{fa(c.instructor.courses)} دوره</span>
</div>
</div>
</div>
<p style={{ marginTop: 20, fontSize: 13.5, lineHeight: 1.8, color: 'var(--ink-2)' }}>
آرش پاکدل ۱۰ سال در شرکتهای فناوری ایرانی بهعنوان طراح ارشد محصول کار کرده و تجربهی همکاری با تیمهای مهندسی، محصول و بازاریابی را دارد. علاقهاش آموزش طراحی به زبان ساده و کاربردی است.
</p>
</div>
)}
{tab === 'reviews' && (
<div>
{c.reviewsList.map((r, i) => (
<div key={i} style={{ padding: '16px 20px', borderTop: i ? '1px solid var(--line-soft)' : 'none', display: 'flex', gap: 12 }}>
<div className="av" style={{ background: r.color }}>{r.initials}</div>
<div style={{ flex: 1 }}>
<div className="between">
<b style={{ fontSize: 13.5 }}>{r.name}</b>
<span className="muted" style={{ fontSize: 11.5 }}>{r.when}</span>
</div>
<div style={{ display: 'flex', gap: 1, margin: '4px 0 8px' }}>
{[1,2,3,4,5].map(n => (
<Icon key={n} name="star" className="ic-sm" style={{ color: n <= r.rating ? 'oklch(0.74 0.13 70)' : 'var(--line)', fill: n <= r.rating ? 'oklch(0.78 0.13 70)' : 'transparent' }} />
))}
</div>
<p style={{ margin: 0, fontSize: 13, lineHeight: 1.7, color: 'var(--ink-2)' }}>{r.text}</p>
</div>
</div>
))}
</div>
)}
{tab === 'faq' && (
<div>
{c.faq.map((f, i) => (
<details key={i} style={{ padding: '16px 20px', borderTop: i ? '1px solid var(--line-soft)' : 'none' }}>
<summary style={{ fontSize: 14, fontWeight: 600, cursor: 'pointer', listStyle: 'none', display: 'flex', justifyContent: 'space-between' }}>
{f.q}
<Icon name="plus" className="ic-sm" style={{ color: 'var(--ink-3)' }} />
</summary>
<p style={{ margin: '10px 0 0', fontSize: 13, lineHeight: 1.8, color: 'var(--ink-2)' }}>{f.a}</p>
</details>
))}
</div>
)}
</div>
</div>
{/* purchase rail */}
<div style={{ position: 'sticky', top: 84 }}>
<div className="card card-pad col">
<div style={{ display: 'flex', alignItems: 'baseline', gap: 10 }}>
<span className="num" style={{ fontSize: 28, fontWeight: 700 }}>{c.price}</span>
<span className="muted">تومان</span>
{c.oldPrice && (<>
<span className="muted num" style={{ fontSize: 14, textDecoration: 'line-through', marginInlineStart: 'auto' }}>{c.oldPrice}</span>
<span className="pill accent num">{c.discount} تخفیف</span>
</>)}
</div>
<div className="muted" style={{ fontSize: 12 }}>
<Icon name="clock" className="ic-sm" /> این تخفیف <b className="num">۲ روز</b> دیگر تموم میشه
</div>
<button className="btn primary full" style={{ width: '100%', justifyContent: 'center', padding: '12px', fontSize: 14, fontWeight: 600 }}>
<Icon name="store" className="ic-sm" /> ثبتنام در دوره
</button>
<button className="btn full" style={{ width: '100%', justifyContent: 'center' }}>
<Icon name="play" className="ic-sm" /> پیشنمایش رایگان
</button>
<div className="divider" />
<div className="col" style={{ gap: 10 }}>
{[
{ ic: 'video', t: `${fa(c.lessons)} درس · ${fa(c.hours)} ساعت ویدیو` },
{ ic: 'file', t: 'فایل‌های دانلودی + تمرین‌های عملی' },
{ ic: 'cert', t: 'گواهی پایان دوره با امضای مدرس' },
{ ic: 'phone', t: 'دسترسی مادام‌العمر، روی هر دستگاه' },
{ ic: 'globe', t: `زبان: ${c.language} · به‌روزرسانی: ${c.updated}` },
].map((x, i) => (
<div key={i} style={{ display: 'flex', gap: 10, fontSize: 12.5, alignItems: 'center' }}>
<Icon name={x.ic} className="ic-sm" style={{ color: 'var(--ink-3)' }} />
<span>{x.t}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
}
window.StudentDash = StudentDash;
window.StudentCatalog = StudentCatalog;
window.StudentCourseDetail = StudentCourseDetail;
window.StudentSidebar = StudentSidebar;