Skip to content

Commit 1b9b81b

Browse files
Merge pull request #4246 from OneCommunityGlobal/Neeraj_Display_List_Of_Current_Tasks_To_Students
Neeraj Display List of Current Tasks
2 parents d3eed17 + 54a848c commit 1b9b81b

13 files changed

Lines changed: 2135 additions & 26644 deletions

package-lock.json

Lines changed: 0 additions & 26249 deletions
This file was deleted.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import React, { useEffect, useRef } from 'react';
2+
import PropTypes from 'prop-types';
3+
import styles from './StudentTasks.module.css';
4+
5+
export default function RubricModal({ task, onClose }) {
6+
const dialogRef = useRef(null);
7+
8+
useEffect(() => {
9+
dialogRef.current?.focus();
10+
const onKey = e => {
11+
if (e.key === 'Escape') onClose();
12+
};
13+
window.addEventListener('keydown', onKey);
14+
return () => window.removeEventListener('keydown', onKey);
15+
}, [onClose]);
16+
17+
const handleOverlayClick = e => {
18+
if (e.target.classList.contains(styles.modalOverlay)) onClose();
19+
};
20+
21+
return (
22+
<div className={styles.modalOverlay} onClick={handleOverlayClick} role="presentation">
23+
<div
24+
className={styles.modal}
25+
ref={dialogRef}
26+
role="dialog"
27+
aria-modal="true"
28+
aria-labelledby="rubric-modal-title"
29+
tabIndex={-1}
30+
>
31+
<button
32+
className={styles.closeBtn}
33+
type="button"
34+
aria-label="Close rubric modal"
35+
onClick={onClose}
36+
>
37+
38+
</button>
39+
40+
<h2 id="rubric-modal-title" className={styles.rubricTitle}>
41+
{task.title}
42+
</h2>
43+
<h3 className={styles.rubricSubtitle}>Grading Rubric</h3>
44+
45+
<ul className={styles.rubricList}>
46+
{task.rubric.map(crit => (
47+
<li key={crit} className={styles.rubricItem}>
48+
{crit}
49+
</li>
50+
))}
51+
</ul>
52+
</div>
53+
</div>
54+
);
55+
}
56+
57+
RubricModal.propTypes = {
58+
task: PropTypes.shape({
59+
title: PropTypes.string.isRequired,
60+
rubric: PropTypes.arrayOf(PropTypes.string).isRequired,
61+
}).isRequired,
62+
onClose: PropTypes.func.isRequired,
63+
};
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import React from 'react';
2+
import { useHistory } from 'react-router-dom';
3+
import { useSelector } from 'react-redux';
4+
import Sidebar from './StudentSidebar';
5+
import styles from './StudentDashboard.module.css';
6+
7+
const LIFE_CARD_IDS = ['lc-a', 'lc-b', 'lc-c', 'lc-d', 'lc-e', 'lc-f'];
8+
9+
export default function StudentDashboard() {
10+
const history = useHistory();
11+
const darkMode = useSelector(state => state.theme?.darkMode);
12+
13+
const tasks = [
14+
{
15+
id: 1,
16+
title: 'Activity 1: Technology, Art, Trades, Health',
17+
subtitle: 'Technology, Art, Trades, Health',
18+
progress: 25,
19+
},
20+
{
21+
id: 2,
22+
title: 'Activity 2: Math, Science, Innovation',
23+
subtitle: 'Math, Science, Innovation',
24+
progress: 50,
25+
},
26+
{
27+
id: 3,
28+
title: 'Activity 3: Social Sciences, English, Values',
29+
subtitle: 'Social Sciences, English, Values',
30+
progress: 33,
31+
},
32+
];
33+
34+
const subjects = [
35+
'Arts/ Trades',
36+
'English',
37+
'Health',
38+
'Math',
39+
'Science',
40+
'Social Sciences',
41+
'Tech & Innovation',
42+
'Values',
43+
];
44+
45+
return (
46+
<div className={`${styles.pageLayout} ${darkMode ? styles.pageLayoutDark : ''}`}>
47+
<Sidebar active="home" />
48+
<div className={`${styles.content} ${darkMode ? styles.contentDark : ''}`}>
49+
<div className={styles.headerRow}>
50+
<h1 className={styles.title}>Dashboard</h1>
51+
<div className={styles.welcomeArea}>
52+
<span className={styles.welcomeLabel}>Welcome, Student Name</span>
53+
<div className={styles.icons}>
54+
<span className={styles.icon} aria-hidden="true">
55+
👤
56+
</span>
57+
<span className={styles.icon} aria-hidden="true">
58+
🔔
59+
</span>
60+
</div>
61+
</div>
62+
</div>
63+
<hr className={styles.divider} />
64+
65+
<div className={styles.mainGrid}>
66+
<section className={styles.visualArea} aria-label="Knowledge map">
67+
<div className={styles.visualPlaceholder} />
68+
</section>
69+
70+
<aside className={styles.todoPanel} aria-label="To Do">
71+
<div className={styles.todoHeaderRow}>
72+
<h2 className={styles.todoTitle}>To Do</h2>
73+
<button
74+
className={styles.viewAllBtn}
75+
type="button"
76+
onClick={() => history.push('/educationportal/student/tasks')}
77+
>
78+
View all tasks
79+
</button>
80+
</div>
81+
<hr className={styles.todoDivider} />
82+
83+
<ul className={styles.todoList}>
84+
{tasks.map(t => (
85+
<li key={t.id} className={styles.todoItem}>
86+
<button
87+
className={styles.todoBtn}
88+
type="button"
89+
onClick={() => history.push(`/educationportal/student/tasks/${t.id}`)}
90+
aria-label={`Open ${t.title}`}
91+
>
92+
<div className={styles.todoText}>
93+
<div className={styles.todoName}>{t.title}</div>
94+
<div className={styles.todoSub}>{t.subtitle}</div>
95+
</div>
96+
<div className={styles.todoRight}>
97+
<div className={styles.progressTrack} aria-hidden="true">
98+
<div className={styles.progressFill} style={{ width: `${t.progress}%` }} />
99+
</div>
100+
<span className={styles.chev} aria-hidden="true">
101+
102+
</span>
103+
</div>
104+
</button>
105+
</li>
106+
))}
107+
</ul>
108+
109+
<div className={styles.block}>
110+
<h3 className={styles.blockTitle}>Teaching Strategies</h3>
111+
<hr className={styles.blockDivider} />
112+
<ul className={styles.strategyList}>
113+
{[
114+
'Body Smart Exploration',
115+
'Crazy Creative Combo Cooperative',
116+
'Curious Copycat',
117+
'Existential Smart Exploration',
118+
'Freedom Learning',
119+
].map(s => (
120+
<li key={s} className={styles.strategyItem}>
121+
{s}
122+
</li>
123+
))}
124+
</ul>
125+
</div>
126+
127+
<div className={styles.block}>
128+
<h3 className={styles.blockTitle}>Life Strategies</h3>
129+
<hr className={styles.blockDivider} />
130+
<div className={styles.lifeGrid}>
131+
{LIFE_CARD_IDS.map(id => (
132+
<div key={id} className={styles.lifeCard} />
133+
))}
134+
</div>
135+
</div>
136+
</aside>
137+
</div>
138+
139+
<div className={styles.subjectChips}>
140+
{subjects.map(s => (
141+
<span key={s} className={styles.chip}>
142+
{s}
143+
</span>
144+
))}
145+
</div>
146+
</div>
147+
</div>
148+
);
149+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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 */
65+
.contentDark { background-color:#0b1220; color:#ffffff; }
66+
.contentDark .title, .contentDark .welcomeArea { color:#e57eeb; }
67+
.contentDark .divider { border-top-color:#1f2937; }
68+
.contentDark .todoPanel, .contentDark .visualArea { background-color:#0f172a; border-color:#1f2937; color:#e5e7eb; }
69+
.contentDark .todoBtn { background-color:#0b1220; border-color:#1f2937; color:#e5e7eb; }
70+
.contentDark .todoBtn:hover { background-color:#0f172a; }
71+
.contentDark .todoTitle { color:#e5e7eb; }
72+
.contentDark .todoName { color:#e5e7eb; }
73+
.contentDark .todoSub { color:#94a3b8; }
74+
.contentDark .progressTrack { background-color:#1f2937; }
75+
.contentDark .progressFill { background-color:#9ca3af; }
76+
.contentDark .blockTitle { color:#e5e7eb; }
77+
.contentDark .blockDivider { border-top-color:#1f2937; }
78+
.contentDark .strategyItem { color:#e5e7eb; }
79+
.contentDark .lifeCard { background-color:#0b1220; border-color:#1f2937; }
80+
.contentDark .chip { background-color:#111827; border-color:#1f2937; color:#cbd5e1; }
81+
.contentDark .viewAllBtn { color:#e5e7eb; background:#0f172a; border:1px solid #334155; }
82+
.contentDark .viewAllBtn:hover { background:#111827; border-color:#475569; }
83+
.pageLayoutDark { background:#0b1220; }

0 commit comments

Comments
 (0)