Skip to content

Commit 44484ba

Browse files
feat(student-tasks): display list of current tasks
1 parent f2d9257 commit 44484ba

12 files changed

Lines changed: 2334 additions & 2342 deletions
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// src/components/EductionPortal/StudentTasks/RubricModal.jsx
2+
import React from 'react';
3+
import styles from './StudentTasks.module.css';
4+
5+
export default function RubricModal({ task, onClose }) {
6+
const handleOverlayClick = e => {
7+
if (e.target.classList.contains(styles.modalOverlay)) onClose();
8+
};
9+
10+
const handleOverlayKeyDown = e => {
11+
if (e.key === 'Escape' || e.key === 'Enter' || e.key === ' ') {
12+
onClose();
13+
}
14+
};
15+
16+
return (
17+
<div
18+
className={styles.modalOverlay}
19+
role="button"
20+
onClick={handleOverlayClick}
21+
onKeyDown={handleOverlayKeyDown}
22+
tabIndex={0}
23+
aria-label="Close modal"
24+
>
25+
<div className={styles.modal}>
26+
<button
27+
className={styles.closeBtn}
28+
type="button"
29+
aria-label="Close rubric modal"
30+
onClick={onClose}
31+
>
32+
33+
</button>
34+
35+
<h2 className={styles.rubricTitle}>{task.title}</h2>
36+
<h3 className={styles.rubricSubtitle}>Grading Rubric</h3>
37+
38+
<ul className={styles.rubricList}>
39+
{task.rubric.map((criteria, idx) => (
40+
<li key={idx} className={styles.rubricItem}>
41+
{criteria}
42+
</li>
43+
))}
44+
</ul>
45+
</div>
46+
</div>
47+
);
48+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// src/components/EductionPortal/StudentTasks/StudentDashboard.jsx
2+
import React from 'react';
3+
import { useHistory } from 'react-router-dom';
4+
import { useSelector } from 'react-redux';
5+
import Sidebar from './StudentSidebar';
6+
import styles from './StudentDashboard.module.css';
7+
8+
export default function StudentDashboard() {
9+
const history = useHistory();
10+
// 👇 use global dark mode from Redux
11+
const darkMode = useSelector(state => state.theme?.darkMode);
12+
13+
// Mock preview tasks (swap for real data later)
14+
const tasks = [
15+
{
16+
id: 1,
17+
title: 'Activity 1: Technology, Art, Trades, Health',
18+
subtitle: 'Technology, Art, Trades, Health',
19+
progress: 25,
20+
},
21+
{
22+
id: 2,
23+
title: 'Activity 2: Math, Science, Innovation',
24+
subtitle: 'Math, Science, Innovation',
25+
progress: 50,
26+
},
27+
{
28+
id: 3,
29+
title: 'Activity 3: Social Sciences, English, Values',
30+
subtitle: 'Social Sciences, English, Values',
31+
progress: 33,
32+
},
33+
];
34+
35+
const subjects = [
36+
'Arts/ Trades',
37+
'English',
38+
'Health',
39+
'Math',
40+
'Science',
41+
'Social Sciences',
42+
'Tech & Innovation',
43+
'Values',
44+
];
45+
46+
return (
47+
<div className={`${styles.pageLayout} ${darkMode ? styles.pageLayoutDark : ''}`}>
48+
<Sidebar active="home" />
49+
<div className={`${styles.content} ${darkMode ? styles.contentDark : ''}`}>
50+
{/* Header */}
51+
<div className={styles.headerRow}>
52+
<h1 className={styles.title}>Dashboard</h1>
53+
<div className={styles.welcomeArea}>
54+
<span className={styles.welcomeLabel}>Welcome, Student Name</span>
55+
<div className={styles.icons}>
56+
<span className={styles.icon} aria-hidden>
57+
👤
58+
</span>
59+
<span className={styles.icon} aria-hidden>
60+
🔔
61+
</span>
62+
</div>
63+
</div>
64+
</div>
65+
<hr className={styles.divider} />
66+
67+
<div className={styles.mainGrid}>
68+
{/* Left: Visual placeholder */}
69+
<section className={styles.visualArea} aria-label="Knowledge map">
70+
<div className={styles.visualPlaceholder} />
71+
</section>
72+
73+
{/* Right: To Do preview */}
74+
<aside className={styles.todoPanel} aria-label="To Do">
75+
<div className={styles.todoHeaderRow}>
76+
<h2 className={styles.todoTitle}>To Do</h2>
77+
<button
78+
className={styles.viewAllBtn}
79+
type="button"
80+
onClick={() => history.push('/educationportal/student/tasks')}
81+
>
82+
View all tasks
83+
</button>
84+
</div>
85+
<hr className={styles.todoDivider} />
86+
87+
<ul className={styles.todoList}>
88+
{tasks.map(t => (
89+
<li key={t.id} className={styles.todoItem}>
90+
<button
91+
className={styles.todoBtn}
92+
type="button"
93+
onClick={() => history.push(`/educationportal/student/tasks/${t.id}`)}
94+
aria-label={`Open ${t.title}`}
95+
>
96+
<div className={styles.todoText}>
97+
<div className={styles.todoName}>{t.title}</div>
98+
<div className={styles.todoSub}>{t.subtitle}</div>
99+
</div>
100+
<div className={styles.todoRight}>
101+
<div className={styles.progressTrack}>
102+
<div className={styles.progressFill} style={{ width: `${t.progress}%` }} />
103+
</div>
104+
<span className={styles.chev} aria-hidden>
105+
106+
</span>
107+
</div>
108+
</button>
109+
</li>
110+
))}
111+
</ul>
112+
113+
{/* Teaching Strategies */}
114+
<div className={styles.block}>
115+
<h3 className={styles.blockTitle}>Teaching Strategies</h3>
116+
<hr className={styles.blockDivider} />
117+
<ul className={styles.strategyList}>
118+
{[
119+
'Body Smart Exploration',
120+
'Crazy Creative Combo Cooperative',
121+
'Curious Copycat',
122+
'Existential Smart Exploration',
123+
'Freedom Learning',
124+
].map((s, i) => (
125+
<li key={i} className={styles.strategyItem}>
126+
{s}
127+
</li>
128+
))}
129+
</ul>
130+
</div>
131+
132+
{/* Life Strategies */}
133+
<div className={styles.block}>
134+
<h3 className={styles.blockTitle}>Life Strategies</h3>
135+
<hr className={styles.blockDivider} />
136+
<div className={styles.lifeGrid}>
137+
{[...Array(6)].map((_, i) => (
138+
<div key={i} className={styles.lifeCard} />
139+
))}
140+
</div>
141+
</div>
142+
</aside>
143+
</div>
144+
145+
{/* Subject chips row */}
146+
<div className={styles.subjectChips}>
147+
{subjects.map((s, i) => (
148+
<span key={i} className={styles.chip}>
149+
{s}
150+
</span>
151+
))}
152+
</div>
153+
</div>
154+
</div>
155+
);
156+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
.pageLayout { display:flex; min-height:calc(100vh - 72px); background:#f9fafb; }
2+
.content { flex:1; padding:1.5rem 2rem 2.5rem; }
3+
4+
/* Header */
5+
.headerRow { display:flex; align-items:center; justify-content:space-between; }
6+
.title { font-size:1.75rem; font-weight:700; color:#111827; margin:0; }
7+
.welcomeArea { display:flex; align-items:center; gap:.75rem; color:#111827; }
8+
.welcomeLabel { font-weight:600; }
9+
.icons { display:flex; gap:8px; }
10+
.icon { opacity:.75; }
11+
.divider { border:none; border-top:1px solid #e5e7eb; margin:.75rem 0 1.25rem; }
12+
13+
/* Main grid */
14+
.mainGrid { display:grid; grid-template-columns:1fr 360px; gap:24px; }
15+
16+
/* Visualization placeholder */
17+
.visualArea {
18+
background:#ffffff; border:1px dashed #d1d5db; border-radius:12px;
19+
min-height:360px; display:grid; place-items:center;
20+
}
21+
.visualPlaceholder { width:420px; height:280px; background:repeating-radial-gradient(#e5e7eb 0 4px, transparent 4px 8px); border-radius:12px; opacity:.5; }
22+
23+
/* To Do panel */
24+
.todoPanel { background:#fff; border:1px solid #e5e7eb; border-radius:12px; padding:14px 14px 18px; height:fit-content; }
25+
.todoHeaderRow { display:flex; align-items:center; justify-content:space-between; }
26+
.todoTitle { font-size:1.2rem; font-weight:700; color:#111827; margin:0; }
27+
.viewAllBtn { background:transparent; border:1px solid #d1d5db; color:#374151; padding:6px 10px; border-radius:8px; cursor:pointer; font-size:.85rem; }
28+
.viewAllBtn:hover { border-color:#2563eb; color:#2563eb; }
29+
.todoDivider { border:none; border-top:1px solid #e5e7eb; margin:8px 0 12px; }
30+
31+
.todoList { list-style:none; margin:0; padding:0; display:grid; gap:10px; }
32+
.todoItem { margin:0; }
33+
.todoBtn {
34+
width:100%; display:flex; align-items:center; justify-content:space-between; gap:12px;
35+
background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:10px 12px; cursor:pointer; text-align:left;
36+
}
37+
.todoBtn:hover { background:#f9fafb; }
38+
.todoText { display:grid; gap:2px; }
39+
.todoName { font-weight:700; color:#111827; font-size:.98rem; }
40+
.todoSub { color:#6b7280; font-size:.8rem; }
41+
.todoRight { display:flex; align-items:center; gap:8px; min-width:120px; width:160px; }
42+
.progressTrack { flex:1; height:8px; background:#e5e7eb; border-radius:9999px; overflow:hidden; }
43+
.progressFill { height:100%; background:#9ca3af; }
44+
.chev { font-size:1.1rem; color:#111827; }
45+
46+
/* Blocks */
47+
.block { margin-top:14px; }
48+
.blockTitle { font-size:.95rem; font-weight:700; color:#111827; margin:6px 0; }
49+
.blockDivider { border:none; border-top:1px solid #e5e7eb; margin:6px 0 10px; }
50+
.strategyList { list-style:none; margin:0; padding:0; display:grid; gap:8px; }
51+
.strategyItem { color:#111827; font-size:.92rem; }
52+
53+
/* Life strategy placeholders */
54+
.lifeGrid { display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
55+
.lifeCard { height:64px; background:#f3f4f6; border:1px solid #e5e7eb; border-radius:10px; }
56+
57+
/* Subject chips row */
58+
.subjectChips { margin-top:18px; display:flex; flex-wrap:wrap; gap:8px; }
59+
.chip { display:inline-block; padding:6px 10px; border-radius:9999px; background:#f3f4f6; color:#111827; font-size:.85rem; border:1px solid #e5e7eb; }
60+
61+
/* Responsive */
62+
@media (max-width:1100px){ .mainGrid{ grid-template-columns:1fr; } .todoPanel{ order:2; } .visualArea{ order:1; min-height:280px; } }
63+
/* ===========================
64+
DARK MODE (class-based)
65+
Usage: add styles.contentDark to the same element that has styles.content
66+
=========================== */
67+
68+
.contentDark {
69+
background-color: #0b1220;
70+
color: #ffffff;
71+
}
72+
73+
/* Header text + divider */
74+
.contentDark .title,
75+
.contentDark .welcomeArea { color: #e57eeb; }
76+
.contentDark .divider { border-top-color: #1f2937; }
77+
78+
/* Panels + placeholder */
79+
.contentDark .todoPanel,
80+
.contentDark .visualArea {
81+
background-color: #0f172a;
82+
border-color: #1f2937;
83+
color: #e5e7eb;
84+
}
85+
86+
/* To-Do preview items */
87+
.contentDark .todoBtn {
88+
background-color: #0b1220;
89+
border-color: #1f2937;
90+
color: #e5e7eb;
91+
}
92+
.contentDark .todoBtn:hover { background-color: #0f172a; }
93+
.contentDark .todoTitle { color: #e5e7eb; }
94+
.contentDark .todoName { color: #e5e7eb; }
95+
.contentDark .todoSub { color: #94a3b8; }
96+
97+
/* Progress track */
98+
.contentDark .progressTrack { background-color: #1f2937; }
99+
.contentDark .progressFill { background-color: #9ca3af; }
100+
101+
/* Teaching/Life blocks */
102+
.contentDark .blockTitle { color: #e5e7eb; }
103+
.contentDark .blockDivider { border-top-color: #1f2937; }
104+
contentDark .strategyItem { color: #e5e7eb; } /* (typo guard) */
105+
.contentDark .strategyItem { color: #e5e7eb; }
106+
.contentDark .lifeCard {
107+
background-color: #0b1220;
108+
border-color: #1f2937;
109+
}
110+
111+
/* Subject chips */
112+
.contentDark .chip {
113+
background-color: #111827;
114+
border-color: #1f2937;
115+
color: #cbd5e1;
116+
}
117+
/* Dark mode: "View all tasks" button */
118+
.contentDark .viewAllBtn {
119+
color: #e5e7eb;
120+
background: #0f172a;
121+
border: 1px solid #334155;
122+
}
123+
124+
.contentDark .viewAllBtn:hover {
125+
background: #111827;
126+
border-color: #475569;
127+
}
128+
/* Dark mode background for the whole dashboard page wrapper */
129+
.pageLayoutDark {
130+
background: #0b1220; /* same tone used on StudentTasks/TaskDetails */
131+
}

0 commit comments

Comments
 (0)