Skip to content

Commit

Permalink
Portal frontend 58 (#68)
Browse files Browse the repository at this point in the history
* student table

* fix: cell props per header

* fix headers

* fix check boxes

* create students form initial

* fix input file button

* fix csv

* fix state

* students credentials

* fix base form

* add type hint

* fix path

* remove submitForm util

* additional class details section

* remove unused path

* feedback

* fix api caching

* fix: caching

* add todos

* new cfl package

* new cfl package

* feedback
  • Loading branch information
SKairinos authored Oct 14, 2024
1 parent 03b9c57 commit de85a1c
Show file tree
Hide file tree
Showing 41 changed files with 1,081 additions and 689 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"✅ Do add `devDependencies` below that are `peerDependencies` in the CFL package."
],
"dependencies": {
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.3.10",
"codeforlife": "github:ocadotechnology/codeforlife-package-javascript#v2.4.1",
"crypto-js": "^4.2.0"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion src/api/authFactor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const authFactorApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData(AUTH_FACTOR_TAG, { includeListTag: true }),
}),
destroyAuthFactor: build.mutation<
DestroyAuthFactorResult,
Expand All @@ -44,7 +45,7 @@ const authFactorApi = api.injectEndpoints({
url: buildUrl(urls.authFactor.detail, { url: { id } }),
method: "DELETE",
}),
invalidatesTags: tagData(AUTH_FACTOR_TAG),
invalidatesTags: tagData(AUTH_FACTOR_TAG, { includeListTag: true }),
}),
}),
})
Expand Down
10 changes: 7 additions & 3 deletions src/api/klass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,33 @@ const classApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData(CLASS_TAG, { includeListTag: true }),
}),
destroyClass: build.mutation<DestroyClassResult, DestroyClassArg>({
query: id => ({
url: buildUrl(urls.class.detail, { url: { id } }),
method: "DELETE",
}),
invalidatesTags: tagData(CLASS_TAG),
invalidatesTags: tagData(CLASS_TAG, { includeListTag: true }),
}),
updateClass: build.mutation<UpdateClassResult, UpdateClassArg>({
query: ({ id, ...body }) => ({
url: buildUrl(urls.class.detail, { url: { id } }),
method: "PATCH",
body,
}),
invalidatesTags: tagData(CLASS_TAG),
invalidatesTags: tagData(CLASS_TAG, { includeListTag: true }),
}),
updateClasses: build.mutation<UpdateClassesResult, UpdateClassesArg>({
query: body => ({
url: urls.class.list + "bulk/",
method: "PATCH",
body,
}),
invalidatesTags: tagData(CLASS_TAG),
invalidatesTags: tagData(CLASS_TAG, {
argKeysAreIds: true,
includeListTag: true,
}),
}),
}),
})
Expand Down
3 changes: 2 additions & 1 deletion src/api/school.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ const schoolApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData(SCHOOL_TAG, { includeListTag: true }),
}),
updateSchool: build.mutation<UpdateSchoolResult, UpdateSchoolArg>({
query: ({ id, ...body }) => ({
url: buildUrl(urls.school.detail, { url: { id } }),
method: "PATCH",
body,
}),
invalidatesTags: tagData(SCHOOL_TAG),
invalidatesTags: tagData(SCHOOL_TAG, { includeListTag: true }),
}),
}),
})
Expand Down
23 changes: 18 additions & 5 deletions src/api/schoolTeacherInvitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
method: "DELETE",
body,
}),
invalidatesTags: tagData("SchoolTeacherInvitation"),
invalidatesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
rejectSchoolTeacherInvitation: build.mutation<
RejectSchoolTeacherInvitationResult,
Expand All @@ -108,7 +110,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
url: buildUrl(detailUrl + "reject/", { url: { id } }),
method: "DELETE",
}),
invalidatesTags: tagData("SchoolTeacherInvitation"),
invalidatesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
refreshSchoolTeacherInvitation: build.mutation<
RefreshSchoolTeacherInvitationResult,
Expand All @@ -118,7 +122,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
url: buildUrl(detailUrl, { url: { id } }),
method: "PUT",
}),
invalidatesTags: tagData("SchoolTeacherInvitation"),
invalidatesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
createSchoolTeacherInvitation: build.mutation<
CreateSchoolTeacherInvitationResult,
Expand All @@ -129,6 +135,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
destroySchoolTeacherInvitation: build.mutation<
DestroySchoolTeacherInvitationResult,
Expand All @@ -138,7 +147,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
url: buildUrl(detailUrl, { url: { id } }),
method: "DELETE",
}),
invalidatesTags: tagData("SchoolTeacherInvitation"),
invalidatesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
retrieveSchoolTeacherInvitation: build.query<
RetrieveSchoolTeacherInvitationResult,
Expand All @@ -158,7 +169,9 @@ const schoolTeacherInvitationApi = api.injectEndpoints({
url: buildUrl(listUrl, { search }),
method: "GET",
}),
providesTags: tagData("SchoolTeacherInvitation"),
providesTags: tagData("SchoolTeacherInvitation", {
includeListTag: true,
}),
}),
}),
})
Expand Down
25 changes: 21 additions & 4 deletions src/api/student.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import { type Student, type User, urls } from "codeforlife/api"

import api from "."

export const STUDENT_ID = "user.id"

export type CreateStudentsResult = BulkCreateResult<
Student,
"auto_gen_password",
{
user: Result<User, "password">
user: Result<User, "first_name" | "password">
}
>
export type CreateStudentsArg = BulkCreateArg<
Expand Down Expand Up @@ -76,14 +78,22 @@ const studentApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData("User", {
id: STUDENT_ID,
includeListTag: true,
}),
}),
releaseStudents: build.mutation<ReleaseStudentsResult, ReleaseStudentsArg>({
query: body => ({
url: urls.student.list + "release/",
method: "PUT",
body,
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: STUDENT_ID,
argKeysAreIds: true,
includeListTag: true,
}),
}),
transferStudents: build.mutation<
TransferStudentsResult,
Expand All @@ -94,7 +104,11 @@ const studentApi = api.injectEndpoints({
method: "PUT",
body,
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: STUDENT_ID,
argKeysAreIds: true,
includeListTag: true,
}),
}),
resetStudentsPassword: build.mutation<
ResetStudentsPasswordResult,
Expand All @@ -112,7 +126,10 @@ const studentApi = api.injectEndpoints({
method: "DELETE",
body,
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: STUDENT_ID,
includeListTag: true,
}),
}),
}),
})
Expand Down
21 changes: 18 additions & 3 deletions src/api/teacher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { type Teacher, type User, urls } from "codeforlife/api"

import api from "."

export const TEACHER_ID = "user.id"

export type CreateTeacherResult = CreateResult<Teacher>
export type CreateTeacherArg = {
user: Arg<User, "first_name" | "last_name" | "password" | "email"> & {
Expand All @@ -36,6 +38,10 @@ const teacherApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData("User", {
id: TEACHER_ID,
includeListTag: true,
}),
}),
removeTeacherFromSchool: build.mutation<
RemoveTeacherFromSchoolResult,
Expand All @@ -47,7 +53,10 @@ const teacherApi = api.injectEndpoints({
}),
method: "PUT",
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: TEACHER_ID,
includeListTag: true,
}),
}),
setTeacherAdminAccess: build.mutation<
SetTeacherAdminAccessResult,
Expand All @@ -60,14 +69,20 @@ const teacherApi = api.injectEndpoints({
method: "PUT",
body,
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: TEACHER_ID,
includeListTag: true,
}),
}),
destroyTeacher: build.mutation<DestroyTeacherResult, DestroyTeacherArg>({
query: id => ({
url: buildUrl(urls.teacher.detail, { url: { id } }),
method: "DELETE",
}),
invalidatesTags: tagData("User", { id: "user" }),
invalidatesTags: tagData("User", {
id: TEACHER_ID,
includeListTag: true,
}),
}),
}),
})
Expand Down
7 changes: 4 additions & 3 deletions src/api/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const userApi = api.injectEndpoints({
method: "PUT",
body,
}),
invalidatesTags: tagData(USER_TAG),
invalidatesTags: tagData(USER_TAG, { includeListTag: true }),
}),
requestPasswordReset: build.query<
RequestPasswordResetResult,
Expand Down Expand Up @@ -161,7 +161,7 @@ const userApi = api.injectEndpoints({
method: "PATCH",
body,
}),
invalidatesTags: tagData(USER_TAG),
invalidatesTags: tagData(USER_TAG, { includeListTag: true }),
}),
destroyIndependentUser: build.mutation<
DestroyIndependentUserResult,
Expand All @@ -172,7 +172,7 @@ const userApi = api.injectEndpoints({
method: "DELETE",
body,
}),
invalidatesTags: tagData(USER_TAG),
invalidatesTags: tagData(USER_TAG, { includeListTag: true }),
}),
createIndependentUser: build.mutation<
CreateIndependentUserResult,
Expand All @@ -183,6 +183,7 @@ const userApi = api.injectEndpoints({
method: "POST",
body,
}),
invalidatesTags: tagData(USER_TAG, { includeListTag: true }),
}),
// TODO: create action on the backend.
validatePassword: build.query<ValidatePasswordResult, ValidatePasswordArg>({
Expand Down
7 changes: 3 additions & 4 deletions src/features/footer/RegisterToNewsletterForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as forms from "codeforlife/components/form"
import { FormHelperText, Stack, useMediaQuery, useTheme } from "@mui/material"
import { type FC } from "react"
import { submitForm } from "codeforlife/utils/form"
import { useNavigate } from "react-router-dom"

import { useRegisterToNewsletterMutation } from "../../api/user"
Expand All @@ -11,7 +10,6 @@ export interface RegisterToNewsletterFormProps {}
const RegisterToNewsletterForm: FC<RegisterToNewsletterFormProps> = () => {
const theme = useTheme()
const onlyXS = useMediaQuery(theme.breakpoints.only("xs"))
const [registerToNewsletter] = useRegisterToNewsletterMutation()
const navigate = useNavigate()

return (
Expand All @@ -25,7 +23,8 @@ const RegisterToNewsletterForm: FC<RegisterToNewsletterFormProps> = () => {
email: "",
over18: false,
}}
onSubmit={submitForm(registerToNewsletter, {
useMutation={useRegisterToNewsletterMutation}
submitOptions={{
exclude: ["over18"],
then: () => {
navigate(".", {
Expand Down Expand Up @@ -54,7 +53,7 @@ const RegisterToNewsletterForm: FC<RegisterToNewsletterFormProps> = () => {
},
})
},
})}
}}
>
<Stack spacing={2}>
<forms.EmailField
Expand Down
17 changes: 13 additions & 4 deletions src/pages/login/BaseForm.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
import { Form, type FormProps } from "codeforlife/components/form"
import { Stack, Typography, useTheme } from "@mui/material"
import { ThemedBox, type ThemedBoxProps } from "codeforlife/theme"
import { type FormikValues } from "formik"
import { type FormValues } from "codeforlife/utils/form"

import { themeOptions } from "../../app/theme"

export interface BaseFormProps<Values> extends FormProps<Values> {
export type BaseFormProps<
Values extends FormValues,
QueryArg extends FormValues,
ResultType,
> = FormProps<Values, QueryArg, ResultType> & {
themedBoxProps: Omit<ThemedBoxProps, "withShapes">
header: string
subheader?: string
}

const BaseForm = <Values extends FormikValues = FormikValues>({
const BaseForm = <
Values extends FormValues = FormValues,
QueryArg extends FormValues = FormValues,
ResultType = unknown,
>({
themedBoxProps,
header,
subheader,
...formProps
}: BaseFormProps<Values>): JSX.Element => {
}: BaseFormProps<Values, QueryArg, ResultType>): JSX.Element => {
const theme = useTheme()

return (
Expand All @@ -35,6 +43,7 @@ const BaseForm = <Values extends FormikValues = FormikValues>({
{subheader}
</Typography>
)}
{/* @ts-expect-error props */}
<Form {...formProps} />
</Stack>
</ThemedBox>
Expand Down
Loading

0 comments on commit de85a1c

Please sign in to comment.