diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts deleted file mode 100644 index 51512e22..00000000 --- a/src/api/endpoints.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { type EndpointBuilder as _EndpointBuilder } from "@reduxjs/toolkit/query/react" - -import { - buildUrl, - tagData, - type ListArg, - type ListResult, - type RetrieveArg, - type RetrieveResult, -} from "../utils/api" -import type { AuthFactor, Class, School, User } from "./models" -import { type TagTypes } from "./tagTypes" -import urls from "./urls" - -type EndpointBuilder = _EndpointBuilder - -export function getReadUserEndpoints(build: EndpointBuilder) { - const tagType: TagTypes = "User" - - return { - retrieveUser: build.query< - RetrieveResult< - User, - | "first_name" - | "last_name" - | "email" - | "is_active" - | "date_joined" - | "requesting_to_join_class" - | "student" - | "teacher" - >, - RetrieveArg - >({ - query: id => ({ - url: buildUrl(urls.user.detail, { url: { id } }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - listUsers: build.query< - ListResult< - User, - | "first_name" - | "last_name" - | "email" - | "is_active" - | "date_joined" - | "requesting_to_join_class" - | "student" - | "teacher" - >, - ListArg<{ students_in_class: string }> - >({ - query: search => ({ - url: buildUrl(urls.user.list, { search }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - } -} - -export function getReadSchoolEndpoints(build: EndpointBuilder) { - const tagType: TagTypes = "School" - - return { - retrieveSchool: build.query< - RetrieveResult, - RetrieveArg - >({ - query: id => ({ - url: buildUrl(urls.school.detail, { url: { id } }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - } -} - -export function getReadClassEndpoints(build: EndpointBuilder) { - const tagType: TagTypes = "Class" - - return { - retrieveClass: build.query< - RetrieveResult< - Class, - | "name" - | "read_classmates_data" - | "receive_requests_until" - | "school" - | "teacher" - >, - RetrieveArg - >({ - query: id => ({ - url: buildUrl(urls.class.detail, { url: { id } }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - listClasses: build.query< - ListResult< - Class, - | "name" - | "read_classmates_data" - | "receive_requests_until" - | "school" - | "teacher" - >, - ListArg - >({ - query: search => ({ - url: buildUrl(urls.class.list, { search }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - } -} - -export function getReadAuthFactorEndpoints(build: EndpointBuilder) { - const tagType: TagTypes = "AuthFactor" - - return { - listAuthFactors: build.query, ListArg>({ - query: search => ({ - url: buildUrl(urls.authFactor.list, { search }), - method: "GET", - }), - providesTags: tagData(tagType), - }), - } -} diff --git a/src/api/endpoints/authFactor.ts b/src/api/endpoints/authFactor.ts new file mode 100644 index 00000000..4712baaa --- /dev/null +++ b/src/api/endpoints/authFactor.ts @@ -0,0 +1,30 @@ +import { type EndpointBuilder } from "@reduxjs/toolkit/query/react" + +import { + buildUrl, + tagData, + type ListArg, + type ListResult, +} from "../../utils/api" +import type { AuthFactor } from "../models" +import { type TagTypes } from "../tagTypes" +import urls from "../urls" + +export const AUTH_FACTOR_TAG: TagTypes = "AuthFactor" + +export type ListAuthFactorsResult = ListResult +export type ListAuthFactorsArg = ListArg + +export default function getReadAuthFactorEndpoints( + build: EndpointBuilder, +) { + return { + listAuthFactors: build.query({ + query: search => ({ + url: buildUrl(urls.authFactor.list, { search }), + method: "GET", + }), + providesTags: tagData(AUTH_FACTOR_TAG), + }), + } +} diff --git a/src/api/endpoints/index.ts b/src/api/endpoints/index.ts new file mode 100644 index 00000000..3f8ebfe2 --- /dev/null +++ b/src/api/endpoints/index.ts @@ -0,0 +1,47 @@ +import getReadAuthFactorEndpoints, { + type ListAuthFactorsArg, + type ListAuthFactorsResult, + AUTH_FACTOR_TAG, +} from "./authFactor" +import getReadClassEndpoints, { + type ListClassesArg, + type ListClassesResult, + type RetrieveClassArg, + type RetrieveClassResult, + CLASS_TAG, +} from "./klass" +import getReadSchoolEndpoints, { + type RetrieveSchoolArg, + type RetrieveSchoolResult, + SCHOOL_TAG, +} from "./school" +import getReadUserEndpoints, { + type ListUsersArg, + type ListUsersResult, + type RetrieveUserArg, + type RetrieveUserResult, + USER_TAG, +} from "./user" + +export { + AUTH_FACTOR_TAG, + CLASS_TAG, + getReadAuthFactorEndpoints, + getReadClassEndpoints, + getReadSchoolEndpoints, + getReadUserEndpoints, + SCHOOL_TAG, + USER_TAG, + type ListAuthFactorsArg, + type ListAuthFactorsResult, + type ListClassesArg, + type ListClassesResult, + type ListUsersArg, + type ListUsersResult, + type RetrieveClassArg, + type RetrieveClassResult, + type RetrieveSchoolArg, + type RetrieveSchoolResult, + type RetrieveUserArg, + type RetrieveUserResult, +} diff --git a/src/api/endpoints/klass.ts b/src/api/endpoints/klass.ts new file mode 100644 index 00000000..92627306 --- /dev/null +++ b/src/api/endpoints/klass.ts @@ -0,0 +1,56 @@ +import { type EndpointBuilder } from "@reduxjs/toolkit/query/react" + +import { + buildUrl, + tagData, + type ListArg, + type ListResult, + type RetrieveArg, + type RetrieveResult, +} from "../../utils/api" +import type { Class } from "../models" +import { type TagTypes } from "../tagTypes" +import urls from "../urls" + +export const CLASS_TAG: TagTypes = "Class" + +export type RetrieveClassResult = RetrieveResult< + Class, + | "name" + | "read_classmates_data" + | "receive_requests_until" + | "school" + | "teacher" +> +export type RetrieveClassArg = RetrieveArg + +export type ListClassesResult = ListResult< + Class, + | "name" + | "read_classmates_data" + | "receive_requests_until" + | "school" + | "teacher" +> +export type ListClassesArg = ListArg + +export default function getReadClassEndpoints( + build: EndpointBuilder, +) { + return { + retrieveClass: build.query({ + query: id => ({ + url: buildUrl(urls.class.detail, { url: { id } }), + method: "GET", + }), + providesTags: tagData(CLASS_TAG), + }), + listClasses: build.query({ + query: search => ({ + url: buildUrl(urls.class.list, { search }), + method: "GET", + }), + providesTags: tagData(CLASS_TAG), + }), + } +} diff --git a/src/api/endpoints/school.ts b/src/api/endpoints/school.ts new file mode 100644 index 00000000..75f0dd4e --- /dev/null +++ b/src/api/endpoints/school.ts @@ -0,0 +1,33 @@ +import { type EndpointBuilder } from "@reduxjs/toolkit/query/react" + +import { + buildUrl, + tagData, + type RetrieveArg, + type RetrieveResult, +} from "../../utils/api" +import type { School } from "../models" +import { type TagTypes } from "../tagTypes" +import urls from "../urls" + +export const SCHOOL_TAG: TagTypes = "School" + +export type RetrieveSchoolResult = RetrieveResult< + School, + "name" | "country" | "uk_county" +> +export type RetrieveSchoolArg = RetrieveArg + +export default function getReadSchoolEndpoints( + build: EndpointBuilder, +) { + return { + retrieveSchool: build.query({ + query: id => ({ + url: buildUrl(urls.school.detail, { url: { id } }), + method: "GET", + }), + providesTags: tagData(SCHOOL_TAG), + }), + } +} diff --git a/src/api/endpoints/user.ts b/src/api/endpoints/user.ts new file mode 100644 index 00000000..fd70554a --- /dev/null +++ b/src/api/endpoints/user.ts @@ -0,0 +1,62 @@ +import { type EndpointBuilder } from "@reduxjs/toolkit/query/react" + +import { + buildUrl, + tagData, + type ListArg, + type ListResult, + type RetrieveArg, + type RetrieveResult, +} from "../../utils/api" +import type { User } from "../models" +import { type TagTypes } from "../tagTypes" +import urls from "../urls" + +export const USER_TAG: TagTypes = "User" + +export type RetrieveUserResult = RetrieveResult< + User, + | "first_name" + | "last_name" + | "email" + | "is_active" + | "date_joined" + | "requesting_to_join_class" + | "student" + | "teacher" +> +export type RetrieveUserArg = RetrieveArg + +export type ListUsersResult = ListResult< + User, + | "first_name" + | "last_name" + | "email" + | "is_active" + | "date_joined" + | "requesting_to_join_class" + | "student" + | "teacher" +> +export type ListUsersArg = ListArg<{ students_in_class: string }> + +export default function getReadUserEndpoints( + build: EndpointBuilder, +) { + return { + retrieveUser: build.query({ + query: id => ({ + url: buildUrl(urls.user.detail, { url: { id } }), + method: "GET", + }), + providesTags: tagData(USER_TAG), + }), + listUsers: build.query({ + query: search => ({ + url: buildUrl(urls.user.list, { search }), + method: "GET", + }), + providesTags: tagData(USER_TAG), + }), + } +} diff --git a/src/api/index.ts b/src/api/index.ts index b6bcdb65..4afd96a0 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,17 +1,22 @@ import baseQuery from "./baseQuery" -import { - getReadAuthFactorEndpoints, - getReadClassEndpoints, - getReadSchoolEndpoints, - getReadUserEndpoints, -} from "./endpoints" import type { + AdminSchoolTeacher, + AdminSchoolTeacherUser, AuthFactor, Class, + IndependentUser, + NonAdminSchoolTeacher, + NonAdminSchoolTeacherUser, + NonSchoolTeacher, + NonSchoolTeacherUser, OtpBypassToken, School, + SchoolTeacher, + SchoolTeacherUser, Student, + StudentUser, Teacher, + TeacherUser, User, } from "./models" import tagTypes from "./tagTypes" @@ -19,17 +24,24 @@ import urls from "./urls" export { baseQuery, - getReadAuthFactorEndpoints, - getReadClassEndpoints, - getReadSchoolEndpoints, - getReadUserEndpoints, tagTypes, urls, + type AdminSchoolTeacher, + type AdminSchoolTeacherUser, type AuthFactor, type Class, + type IndependentUser, + type NonAdminSchoolTeacher, + type NonAdminSchoolTeacherUser, + type NonSchoolTeacher, + type NonSchoolTeacherUser, type OtpBypassToken, type School, + type SchoolTeacher, + type SchoolTeacherUser, type Student, + type StudentUser, type Teacher, + type TeacherUser, type User, } diff --git a/src/api/models.ts b/src/api/models.ts index 6835e44a..e1035885 100644 --- a/src/api/models.ts +++ b/src/api/models.ts @@ -1,6 +1,10 @@ import type { Model } from "../utils/api" import type { CountryIsoCodes, UkCounties } from "../utils/general" +// ----------------------------------------------------------------------------- +// User Models +// ----------------------------------------------------------------------------- + export type User = Model< number, { @@ -18,6 +22,45 @@ export type User = Model< } > +export type TeacherUser = Fields & { + teacher: Teacher + student: undefined +} + +export type SchoolTeacherUser = Fields & { + teacher: SchoolTeacher + student: undefined +} + +export type AdminSchoolTeacherUser = Fields & { + teacher: AdminSchoolTeacher + student: undefined +} + +export type NonAdminSchoolTeacherUser = Fields & { + teacher: NonAdminSchoolTeacher + student: undefined +} + +export type NonSchoolTeacherUser = Fields & { + teacher: NonSchoolTeacher + student: undefined +} + +export type StudentUser = Fields & { + teacher: undefined + student: Student +} + +export type IndependentUser = Fields & { + teacher: undefined + student: undefined +} + +// ----------------------------------------------------------------------------- +// Teacher Models +// ----------------------------------------------------------------------------- + export type Teacher = Model< number, { @@ -27,6 +70,28 @@ export type Teacher = Model< } > +export type SchoolTeacher = Fields & { + school: number +} + +export type AdminSchoolTeacher = Fields & { + school: number + is_admin: true +} + +export type NonAdminSchoolTeacher = Fields & { + school: number + is_admin: false +} + +export type NonSchoolTeacher = Fields & { + school: undefined +} + +// ----------------------------------------------------------------------------- +// Other Models +// ----------------------------------------------------------------------------- + export type Student = Model< number, { diff --git a/src/components/form/FirstNameField.tsx b/src/components/form/FirstNameField.tsx index 143933a9..3300934a 100644 --- a/src/components/form/FirstNameField.tsx +++ b/src/components/form/FirstNameField.tsx @@ -1,3 +1,5 @@ +import { PersonOutlined as PersonOutlinedIcon } from "@mui/icons-material" +import { InputAdornment } from "@mui/material" import type { FC } from "react" import { string as YupString } from "yup" @@ -13,6 +15,7 @@ const FirstNameField: FC = ({ name = "first_name", label = "First name", placeholder = "Enter your first name", + InputProps = {}, ...otherTextFieldProps }) => { return ( @@ -21,6 +24,14 @@ const FirstNameField: FC = ({ name={name} label={label} placeholder={placeholder} + InputProps={{ + endAdornment: ( + + + + ), + ...InputProps, + }} {...otherTextFieldProps} /> )