-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial page and route * page * release button * fix: duplicate ids * fix spacing * new cfl package * fix disabled state * small fixes
- Loading branch information
Showing
8 changed files
with
1,173 additions
and
932 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
src/pages/teacherDashboard/classes/releaseStudents/ReleaseStudents.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import * as pages from "codeforlife/components/page" | ||
import { type Class, type StudentUser } from "codeforlife/api" | ||
import { Link, Navigate } from "codeforlife/components/router" | ||
import { useLocation, useParams } from "codeforlife/hooks" | ||
import { type FC } from "react" | ||
import { Typography } from "@mui/material" | ||
import { generatePath } from "react-router-dom" | ||
import { handleResultState } from "codeforlife/utils/api" | ||
|
||
import { type ListUsersResult } from "../../../../api/user" | ||
import ReleaseStudentsForm from "./ReleaseStudentsForm" | ||
import { classIdSchema } from "../../../../app/schemas" | ||
import { paths } from "../../../../routes" | ||
import { useRetrieveClassQuery } from "../../../../api/klass" | ||
|
||
const _ReleaseStudents: FC< | ||
ReleaseStudentsState & { | ||
classId: Class["id"] | ||
classPath: string | ||
} | ||
> = ({ classId, classPath, ...state }) => | ||
handleResultState(useRetrieveClassQuery(classId), klass => ( | ||
<pages.Section> | ||
<Typography align="center" variant="h4"> | ||
Release students from class {klass.name} ({klass.id}) | ||
</Typography> | ||
<Link className="back-to" to={classPath}> | ||
Class | ||
</Link> | ||
<Typography>Convert students into independent students.</Typography> | ||
<Typography variant="h5">Students to release from school</Typography> | ||
<Typography> | ||
You are about to remove students from your class and set them up as | ||
independent students. Neither you nor your school will be able to manage | ||
them once you have submitted this request. | ||
</Typography> | ||
<Typography> | ||
Email addresses are required for independent student accounts. If a | ||
student is too young to own an email address, a parent or | ||
guardian's email address will be required. | ||
</Typography> | ||
<Typography> | ||
The email address will have to be validated through a verification email | ||
before the student can log in. The email has to be unique and not used | ||
for other accounts in Code for Life.{" "} | ||
<strong> | ||
Make sure you type the correct email, as otherwise we may not be able | ||
to recover the account | ||
</strong> | ||
. | ||
</Typography> | ||
<Typography> | ||
The students will then log in with their email via the{" "} | ||
<Link className="body" to={paths.login.indy._}> | ||
independent student login | ||
</Link> | ||
. Their passwords will stay the same. Independent students do not need | ||
to provide a class access code. | ||
</Typography> | ||
<ReleaseStudentsForm classPath={classPath} {...state} /> | ||
</pages.Section> | ||
)) | ||
|
||
export interface ReleaseStudentsState { | ||
studentUsers: Array<StudentUser<ListUsersResult["data"][number]>> | ||
} | ||
|
||
export interface ReleaseStudentsProps {} | ||
|
||
const ReleaseStudents: FC<ReleaseStudentsProps> = () => { | ||
const params = useParams({ classId: classIdSchema.required() }) | ||
const { state } = useLocation<ReleaseStudentsState>() | ||
|
||
if (!params) | ||
return <Navigate to={paths.teacher.dashboard.tab.classes._} replace /> | ||
|
||
const { classId } = params | ||
|
||
const classPath = generatePath(paths.teacher.dashboard.tab.classes.class._, { | ||
classId, | ||
}) | ||
|
||
return !state || !state.studentUsers || !state.studentUsers.length ? ( | ||
<Navigate to={classPath} replace /> | ||
) : ( | ||
<_ReleaseStudents | ||
classId={classId} | ||
classPath={classPath} | ||
studentUsers={state.studentUsers} | ||
/> | ||
) | ||
} | ||
|
||
export default ReleaseStudents |
139 changes: 139 additions & 0 deletions
139
src/pages/teacherDashboard/classes/releaseStudents/ReleaseStudentsForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import * as forms from "codeforlife/components/form" | ||
import { | ||
EmailOutlined as EmailOutlinedIcon, | ||
PersonRemoveAlt1Outlined as PersonRemoveAlt1OutlinedIcon, | ||
} from "@mui/icons-material" | ||
import { InputAdornment, Stack } from "@mui/material" | ||
import { type FC } from "react" | ||
import { LinkButton } from "codeforlife/components/router" | ||
import { type StudentUser } from "codeforlife/api" | ||
import { submitForm } from "codeforlife/utils/form" | ||
import { useNavigate } from "codeforlife/hooks" | ||
|
||
import { | ||
type ReleaseStudentsArg, | ||
useReleaseStudentsMutation, | ||
} from "../../../../api/student" | ||
import { type ListUsersResult } from "../../../../api/user" | ||
|
||
export interface ReleaseStudentsFormProps { | ||
studentUsers: Array<StudentUser<ListUsersResult["data"][number]>> | ||
classPath: string | ||
} | ||
|
||
const ReleaseStudentsForm: FC<ReleaseStudentsFormProps> = ({ | ||
studentUsers, | ||
classPath, | ||
}) => { | ||
const [releaseStudents] = useReleaseStudentsMutation() | ||
const navigate = useNavigate() | ||
|
||
return ( | ||
<forms.Form | ||
initialValues={studentUsers.reduce( | ||
(arg, studentUser) => ({ | ||
...arg, | ||
[studentUser.student.id]: { | ||
user: { | ||
original_first_name: studentUser.first_name, | ||
first_name: studentUser.first_name, | ||
email: "", | ||
email_repeat: "", | ||
}, | ||
}, | ||
}), | ||
{} as ReleaseStudentsArg, | ||
)} | ||
onSubmit={submitForm(releaseStudents, { | ||
exclude: studentUsers.reduce( | ||
(exclude, studentUser) => [ | ||
...exclude, | ||
`${studentUser.student.id}.user.original_first_name`, | ||
`${studentUser.student.id}.user.email_repeat`, | ||
], | ||
[] as string[], | ||
), | ||
then: () => { | ||
navigate(classPath, { | ||
state: { | ||
notifications: [ | ||
{ | ||
props: { | ||
children: "The students have been released successfully", | ||
}, | ||
}, | ||
], | ||
}, | ||
}) | ||
}, | ||
catch: () => { | ||
navigate(classPath, { | ||
state: { | ||
notifications: [ | ||
{ | ||
props: { | ||
error: true, | ||
children: "Failed to release students", | ||
}, | ||
}, | ||
], | ||
}, | ||
}) | ||
}, | ||
})} | ||
> | ||
<Stack gap={6}> | ||
{studentUsers.map(studentUser => ( | ||
<Stack key={`user-${studentUser.id}`} gap={2}> | ||
<Stack direction="row" gap={2}> | ||
<forms.FirstNameField | ||
disabled | ||
name={`${studentUser.student.id}.user.original_first_name`} | ||
label="Original student name" | ||
/> | ||
<forms.FirstNameField | ||
required | ||
name={`${studentUser.student.id}.user.first_name`} | ||
label="New student name" | ||
placeholder="Enter student address" | ||
/> | ||
</Stack> | ||
<Stack direction="row" gap={2}> | ||
<forms.EmailField | ||
required | ||
name={`${studentUser.student.id}.user.email`} | ||
label="New email address" | ||
placeholder="Enter email address" | ||
/> | ||
<forms.RepeatField | ||
name={`${studentUser.student.id}.user.email`} | ||
label="Repeat email address" | ||
placeholder="Repeat email address" | ||
InputProps={{ | ||
endAdornment: ( | ||
<InputAdornment position="end"> | ||
<EmailOutlinedIcon /> | ||
</InputAdornment> | ||
), | ||
}} | ||
/> | ||
</Stack> | ||
</Stack> | ||
))} | ||
<Stack direction="row" gap={2}> | ||
<LinkButton to={classPath} variant="outlined"> | ||
Cancel | ||
</LinkButton> | ||
<forms.SubmitButton | ||
className="alert" | ||
endIcon={<PersonRemoveAlt1OutlinedIcon />} | ||
> | ||
Remove students | ||
</forms.SubmitButton> | ||
</Stack> | ||
</Stack> | ||
</forms.Form> | ||
) | ||
} | ||
|
||
export default ReleaseStudentsForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.