codeforlife 2.7.2 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.github/workflows/main.yml +0 -3
  2. package/CHANGELOG.md +7 -0
  3. package/eslint.config.js +17 -0
  4. package/package.json +45 -24
  5. package/src/api/createApi.ts +4 -4
  6. package/src/api/endpoints/authFactor.ts +2 -2
  7. package/src/api/endpoints/klass.ts +8 -8
  8. package/src/api/endpoints/school.ts +2 -2
  9. package/src/api/endpoints/session.ts +2 -1
  10. package/src/api/endpoints/user.ts +3 -3
  11. package/src/api/models.ts +1 -1
  12. package/src/api/schemas.ts +16 -16
  13. package/src/components/App.tsx +7 -5
  14. package/src/components/CopyIconButton.test.tsx +1 -1
  15. package/src/components/CopyIconButton.tsx +2 -2
  16. package/src/components/Countdown.tsx +3 -3
  17. package/src/components/DownloadFileButton.tsx +2 -1
  18. package/src/components/ElevatedAppBar.tsx +5 -5
  19. package/src/components/Image.tsx +7 -7
  20. package/src/components/InputFileButton.tsx +2 -2
  21. package/src/components/ItemizedList.tsx +4 -4
  22. package/src/components/OrderedGrid.tsx +3 -3
  23. package/src/components/ScrollIntoViewLink.tsx +1 -2
  24. package/src/components/SyncError.tsx +1 -1
  25. package/src/components/TablePagination.tsx +19 -9
  26. package/src/components/YouTubeVideo.tsx +2 -2
  27. package/src/components/form/ApiAutocompleteField.tsx +48 -41
  28. package/src/components/form/AutocompleteField.tsx +22 -11
  29. package/src/components/form/CheckboxField.tsx +14 -9
  30. package/src/components/form/CountryField.tsx +5 -4
  31. package/src/components/form/DatePickerField.tsx +18 -11
  32. package/src/components/form/EmailField.tsx +1 -1
  33. package/src/components/form/FirstNameField.tsx +2 -2
  34. package/src/components/form/Form.tsx +13 -12
  35. package/src/components/form/PasswordField.tsx +2 -2
  36. package/src/components/form/RepeatField.tsx +18 -10
  37. package/src/components/form/SubmitButton.tsx +14 -10
  38. package/src/components/form/TextField.tsx +17 -11
  39. package/src/components/form/UkCountyField.tsx +3 -2
  40. package/src/components/form/index.tsx +35 -28
  41. package/src/components/page/Banner.tsx +3 -3
  42. package/src/components/page/Notification.tsx +3 -3
  43. package/src/components/page/Page.tsx +5 -5
  44. package/src/components/page/Section.tsx +1 -1
  45. package/src/components/page/TabBar.tsx +5 -5
  46. package/src/components/router/Link.tsx +2 -1
  47. package/src/components/router/LinkButton.tsx +1 -0
  48. package/src/components/router/LinkIconButton.tsx +1 -0
  49. package/src/components/router/LinkListItem.tsx +1 -0
  50. package/src/components/router/LinkTab.tsx +1 -0
  51. package/src/components/router/Navigate.tsx +2 -2
  52. package/src/components/router/index.tsx +9 -12
  53. package/src/components/table/CellStack.tsx +2 -2
  54. package/src/components/table/index.tsx +2 -4
  55. package/src/features/InactiveDialog.tsx +2 -2
  56. package/src/features/ScreenTimeDialog.tsx +3 -6
  57. package/src/hooks/api.tsx +4 -2
  58. package/src/hooks/auth.tsx +14 -12
  59. package/src/hooks/{general.ts → general.tsx} +3 -3
  60. package/src/hooks/router.tsx +9 -9
  61. package/src/middlewares/session.ts +15 -10
  62. package/src/settings/index.ts +3 -6
  63. package/src/setupTests.ts +1 -0
  64. package/src/theme/ThemedBox.tsx +9 -9
  65. package/src/theme/components/MuiButton.ts +1 -1
  66. package/src/theme/components/MuiCardActions.tsx +1 -1
  67. package/src/theme/components/MuiContainer.ts +1 -1
  68. package/src/theme/components/MuiFormControlLabel.ts +1 -1
  69. package/src/theme/components/MuiFormHelperText.ts +1 -1
  70. package/src/theme/components/MuiInputBase.ts +1 -1
  71. package/src/theme/components/MuiLink.ts +1 -1
  72. package/src/theme/components/MuiListItemText.ts +1 -1
  73. package/src/theme/components/MuiMenuItem.ts +1 -1
  74. package/src/theme/components/MuiSelect.ts +2 -2
  75. package/src/theme/components/MuiTable.ts +1 -1
  76. package/src/theme/components/MuiTableBody.ts +1 -1
  77. package/src/theme/components/MuiTableHead.ts +2 -2
  78. package/src/theme/components/MuiTextField.ts +3 -3
  79. package/src/theme/components/_components.ts +4 -2
  80. package/src/theme/palette.ts +2 -2
  81. package/src/theme/typography.ts +1 -1
  82. package/src/utils/api.tsx +6 -4
  83. package/src/utils/auth.ts +1 -1
  84. package/src/utils/form.test.ts +1 -1
  85. package/src/utils/form.ts +14 -9
  86. package/src/utils/general.test.ts +7 -7
  87. package/src/utils/general.ts +10 -12
  88. package/src/utils/router.test.ts +1 -1
  89. package/src/utils/router.ts +2 -2
  90. package/src/utils/schema.ts +11 -11
  91. package/src/utils/test.tsx +2 -2
  92. package/src/utils/theme.tsx +7 -6
  93. package/src/utils/window.ts +2 -0
  94. package/tsconfig.app.json +4 -0
  95. package/tsconfig.json +4 -28
  96. package/tsconfig.node.json +3 -10
  97. package/vite.config.ts +1 -1
  98. package/.eslintrc.json +0 -47
  99. package/src/vite.config.ts +0 -49
  100. /package/src/{public/images → images/svg}/brain.svg +0 -0
@@ -4,9 +4,6 @@ on:
4
4
  push:
5
5
  paths-ignore:
6
6
  - '**/*.md'
7
- - '**/*.code-*'
8
- - '.vscode/**'
9
- - '.devcontainer.json'
10
7
  pull_request:
11
8
  issues:
12
9
  issue_comment:
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [2.8.0](https://github.com/ocadotechnology/codeforlife-package-javascript/compare/v2.7.2...v2.8.0) (2025-08-21)
2
+
3
+
4
+ ### Features
5
+
6
+ * type fixes ([#89](https://github.com/ocadotechnology/codeforlife-package-javascript/issues/89)) ([386f6e3](https://github.com/ocadotechnology/codeforlife-package-javascript/commit/386f6e3fe135d59480a18034741ff5d33a7a76ac))
7
+
1
8
  ## [2.7.2](https://github.com/ocadotechnology/codeforlife-package-javascript/compare/v2.7.1...v2.7.2) (2025-08-15)
2
9
 
3
10
 
@@ -0,0 +1,17 @@
1
+ import workspaceConfig from "@codeforlife/workspace/eslint.config.js"
2
+ import ts from "typescript-eslint"
3
+
4
+ export default ts.config(
5
+ ...workspaceConfig,
6
+ {
7
+ ignores: [
8
+ "src/scripts/*",
9
+ "src/server.js", // TODO: convert to src/server.ts and remove this ignore
10
+ ],
11
+ },
12
+ {
13
+ languageOptions: {
14
+ parserOptions: { tsconfigRootDir: import.meta.dirname },
15
+ },
16
+ },
17
+ )
package/package.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "name": "codeforlife",
3
3
  "description": "Common frontend code",
4
4
  "private": false,
5
- "version": "2.7.2",
5
+ "version": "2.8.0",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "cli": "VITE_CONFIG=./vite.config.ts ../scripts/frontend $@"
8
+ "cli": "../scripts/frontend $@"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
@@ -17,6 +17,48 @@
17
17
  "url": "https://github.com/ocadotechnology/codeforlife-package-javascript/issues"
18
18
  },
19
19
  "homepage": "https://github.com/ocadotechnology/codeforlife-package-javascript#readme",
20
+ "//": [
21
+ "Export rules:",
22
+ "🚫 Don't export anything not contained in the src directory.",
23
+ "",
24
+ "Dependency rules:",
25
+ "✅ Do add `dependencies` that are required to use this package.",
26
+ "✅ Do add `dependencies` that are shared across all services.",
27
+ "🚫 Don't add `devDependencies` that are inherited from the CFL workspace.",
28
+ "✅ Do add `devDependencies` that are unique to this package."
29
+ ],
30
+ "exports": {
31
+ ".": "./src/index.ts",
32
+ "./api": "./src/api/index.ts",
33
+ "./api/endpoints": "./src/api/endpoints/index.ts",
34
+ "./api/*": "./src/api/*.ts",
35
+ "./components": "./src/components/index.ts",
36
+ "./components/form": "./src/components/form/index.tsx",
37
+ "./components/page": "./src/components/page/index.ts",
38
+ "./components/router": "./src/components/router/index.tsx",
39
+ "./components/table": "./src/components/table/index.tsx",
40
+ "./components/*": "./src/components/*.tsx",
41
+ "./features": "./src/features/index.ts",
42
+ "./features/*": "./src/features/*.tsx",
43
+ "./fonts/*": "./src/fonts/*.ttf",
44
+ "./hooks": "./src/hooks/index.ts",
45
+ "./hooks/*": "./src/hooks/*.tsx",
46
+ "./images/svg/*": "./src/images/svg/*.svg",
47
+ "./middlewares": "./src/middlewares/index.ts",
48
+ "./middlewares/*": "./src/middlewares/*.ts",
49
+ "./settings": "./src/settings/index.ts",
50
+ "./settings/*": "./src/settings/*.ts",
51
+ "./slices": "./src/slices/index.ts",
52
+ "./slices/*": "./src/slices/*.ts",
53
+ "./theme": "./src/theme/index.ts",
54
+ "./theme/components": "./src/theme/components/index.ts",
55
+ "./theme/*": "./src/theme/*.ts",
56
+ "./utils/api": "./src/utils/api.tsx",
57
+ "./utils/test": "./src/utils/test.tsx",
58
+ "./utils/theme": "./src/utils/theme.tsx",
59
+ "./utils/*": "./src/utils/*.ts",
60
+ "./server": "./src/server.js"
61
+ },
20
62
  "dependencies": {
21
63
  "@emotion/react": "^11.10.6",
22
64
  "@emotion/styled": "^11.10.6",
@@ -39,28 +81,7 @@
39
81
  "yup": "^1.1.1"
40
82
  },
41
83
  "devDependencies": {
42
- "@testing-library/dom": "^9.3.4",
43
- "@testing-library/jest-dom": "^6.2.0",
44
- "@testing-library/react": "^14.1.2",
45
- "@testing-library/user-event": "^14.5.2",
46
- "@types/express": "^5.0.0",
47
- "@types/js-cookie": "^3.0.3",
48
- "@types/node": "^22.14.1",
49
- "@types/qs": "^6.9.7",
50
- "@types/react": "^18.2.47",
51
- "@types/react-dom": "^18.2.18",
52
- "@vitejs/plugin-react": "^4.2.1",
53
- "@vitest/coverage-istanbul": "^1.6.0",
54
- "@vitest/ui": "^1.6.0",
55
- "eslint": "^8.56.0",
56
- "eslint-config-prettier": "^9.1.0",
57
- "eslint-config-react-app": "^7.0.1",
58
- "eslint-plugin-prettier": "^5.1.3",
59
- "jsdom": "^23.2.0",
60
- "prettier": "^3.2.1",
61
- "typescript": "^5.3.3",
62
- "vite": "^5.0.11",
63
- "vitest": "^1.2.0"
84
+ "@codeforlife/workspace": "link:../configs/frontend"
64
85
  },
65
86
  "release": {
66
87
  "branches": [
@@ -1,12 +1,12 @@
1
1
  import {
2
+ type FetchArgs,
2
3
  createApi as _createApi,
3
4
  fetchBaseQuery,
4
- type FetchArgs,
5
5
  } from "@reduxjs/toolkit/query/react"
6
6
 
7
7
  import { SERVICE_API_URL } from "../settings"
8
- import defaultTagTypes from "./tagTypes"
9
8
  import { buildLogoutEndpoint } from "./endpoints/session"
9
+ import defaultTagTypes from "./tagTypes"
10
10
  import { getCsrfCookie } from "../utils/auth"
11
11
  import { isSafeHttpMethod } from "../utils/api"
12
12
 
@@ -45,7 +45,7 @@ export default function createApi<TagTypes extends string = never>({
45
45
  const method = typeof arg === "string" ? "GET" : arg.method || "GET"
46
46
 
47
47
  if (type === "mutation" || !isSafeHttpMethod(method)) {
48
- let csrfToken = getCsrfCookie()
48
+ const csrfToken = getCsrfCookie()
49
49
  if (csrfToken) headers.set("x-csrftoken", csrfToken)
50
50
  }
51
51
 
@@ -55,7 +55,7 @@ export default function createApi<TagTypes extends string = never>({
55
55
 
56
56
  const api = _createApi({
57
57
  // https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#implementing-a-custom-basequery
58
- baseQuery: async (args, api, extraOptions) => {
58
+ baseQuery: async (args: string | FetchArgs, api, extraOptions) => {
59
59
  if (api.type === "mutation" && getCsrfCookie() === undefined) {
60
60
  // Get the CSRF token.
61
61
  const { error } = await fetch(
@@ -1,10 +1,10 @@
1
1
  import { type EndpointBuilder } from "@reduxjs/toolkit/query/react"
2
2
 
3
3
  import {
4
- buildUrl,
5
- tagData,
6
4
  type ListArg as _ListArg,
7
5
  type ListResult as _ListResult,
6
+ buildUrl,
7
+ tagData,
8
8
  } from "../../utils/api"
9
9
  import type { AuthFactor } from "../models"
10
10
  import { type TagTypes } from "../tagTypes"
@@ -1,19 +1,19 @@
1
1
  import { type EndpointBuilder } from "@reduxjs/toolkit/query/react"
2
2
 
3
+ import type {
4
+ Class,
5
+ SchoolTeacher,
6
+ SchoolTeacherUser,
7
+ Teacher,
8
+ } from "../models"
3
9
  import {
4
- buildUrl,
5
- tagData,
6
10
  type ListArg as _ListArg,
7
11
  type ListResult as _ListResult,
8
12
  type RetrieveArg as _RetrieveArg,
9
13
  type RetrieveResult as _RetrieveResult,
14
+ buildUrl,
15
+ tagData,
10
16
  } from "../../utils/api"
11
- import type {
12
- Class,
13
- Teacher,
14
- SchoolTeacher,
15
- SchoolTeacherUser,
16
- } from "../models"
17
17
  import { type TagTypes } from "../tagTypes"
18
18
  import urls from "../urls"
19
19
 
@@ -1,10 +1,10 @@
1
1
  import { type EndpointBuilder } from "@reduxjs/toolkit/query/react"
2
2
 
3
3
  import {
4
- buildUrl,
5
- tagData,
6
4
  type RetrieveArg as _RetrieveArg,
7
5
  type RetrieveResult as _RetrieveResult,
6
+ buildUrl,
7
+ tagData,
8
8
  } from "../../utils/api"
9
9
  import type { School } from "../models"
10
10
  import { type TagTypes } from "../tagTypes"
@@ -1,4 +1,4 @@
1
- import { type EndpointBuilder, type Api } from "@reduxjs/toolkit/query/react"
1
+ import { type Api, type EndpointBuilder } from "@reduxjs/toolkit/query/react"
2
2
 
3
3
  import { login, logout } from "../../slices/session"
4
4
 
@@ -39,6 +39,7 @@ export function buildLogoutEndpoint<ResultType, QueryArg>(
39
39
  console.error("Failed to call logout endpoint...", error)
40
40
  } finally {
41
41
  dispatch(logout())
42
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
42
43
  dispatch(api.util.resetApiState())
43
44
  }
44
45
  },
@@ -1,14 +1,14 @@
1
1
  import { type EndpointBuilder } from "@reduxjs/toolkit/query/react"
2
2
 
3
+ import type { Class, User } from "../models"
3
4
  import {
4
- buildUrl,
5
- tagData,
6
5
  type ListArg as _ListArg,
7
6
  type ListResult as _ListResult,
8
7
  type RetrieveArg as _RetrieveArg,
9
8
  type RetrieveResult as _RetrieveResult,
9
+ buildUrl,
10
+ tagData,
10
11
  } from "../../utils/api"
11
- import type { Class, User } from "../models"
12
12
  import { type TagTypes } from "../tagTypes"
13
13
  import urls from "../urls"
14
14
 
package/src/api/models.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { Model } from "../utils/api"
2
1
  import type { CountryIsoCodes, UkCounties } from "../utils/general"
2
+ import type { Model } from "../utils/api"
3
3
 
4
4
  // -----------------------------------------------------------------------------
5
5
  // User Models
@@ -1,31 +1,31 @@
1
1
  import * as yup from "yup"
2
2
 
3
- import { UK_COUNTIES, COUNTRY_ISO_CODES } from "../utils/general"
4
3
  import type {
5
- User,
6
- TeacherUser,
7
- SchoolTeacherUser,
4
+ AdminSchoolTeacher,
8
5
  AdminSchoolTeacherUser,
9
- NonAdminSchoolTeacherUser,
10
- NonSchoolTeacherUser,
11
- Teacher,
12
- Student,
13
- Class,
14
- School,
15
6
  AuthFactor,
16
- OtpBypassToken,
17
- StudentUser,
7
+ Class,
18
8
  IndependentUser,
19
- SchoolTeacher,
20
- AdminSchoolTeacher,
21
9
  NonAdminSchoolTeacher,
10
+ NonAdminSchoolTeacherUser,
22
11
  NonSchoolTeacher,
12
+ NonSchoolTeacherUser,
13
+ OtpBypassToken,
14
+ School,
15
+ SchoolTeacher,
16
+ SchoolTeacherUser,
17
+ Student,
18
+ StudentUser,
19
+ Teacher,
20
+ TeacherUser,
21
+ User,
23
22
  } from "./models"
23
+ import { COUNTRY_ISO_CODES, UK_COUNTIES } from "../utils/general"
24
24
  import {
25
- unicodeAlphanumericString,
26
- uppercaseAsciiAlphanumericString,
27
25
  lowercaseAsciiAlphanumericString,
28
26
  numericId,
27
+ unicodeAlphanumericString,
28
+ uppercaseAsciiAlphanumericString,
29
29
  } from "../utils/schema"
30
30
  import { type Schemas } from "../utils/api"
31
31
 
@@ -1,14 +1,14 @@
1
+ import { BrowserRouter, Routes as RouterRoutes } from "react-router-dom"
1
2
  import { CssBaseline, ThemeProvider } from "@mui/material"
2
- import { type ThemeProviderProps } from "@mui/material/styles/ThemeProvider"
3
- import { type FC, type ReactNode } from "react"
3
+ import { type FC, type JSX, type ReactNode } from "react"
4
4
  import { Provider, type ProviderProps } from "react-redux"
5
- import { BrowserRouter, Routes as RouterRoutes } from "react-router-dom"
6
- import { StaticRouter } from "react-router-dom/server"
7
5
  import { type Action } from "redux"
6
+ import { StaticRouter } from "react-router-dom/server"
7
+ import { type ThemeProviderProps } from "@mui/material/styles/ThemeProvider"
8
8
 
9
9
  import "./App.css"
10
- import { useLocation } from "../hooks"
11
10
  import { SSR } from "../settings"
11
+ import { useLocation } from "../hooks"
12
12
  // import { InactiveDialog, ScreenTimeDialog } from "../features"
13
13
  // import { useCountdown, useEventListener } from "../hooks"
14
14
  // import "../scripts"
@@ -60,7 +60,9 @@ const App = <A extends Action = Action, S = unknown>({
60
60
  path,
61
61
  theme,
62
62
  store,
63
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
64
  maxIdleSeconds = 60 * 60,
65
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
66
  maxTotalSeconds = 60 * 60,
65
67
  ...routesProps
66
68
  }: AppProps<A, S>): JSX.Element => {
@@ -1,7 +1,7 @@
1
1
  import { screen } from "@testing-library/react"
2
2
 
3
- import { renderWithUser } from "../utils/test"
4
3
  import CopyIconButton from "./CopyIconButton"
4
+ import { renderWithUser } from "../utils/test"
5
5
 
6
6
  test("Clicking button should copy content", async () => {
7
7
  const content = "Example string to be copied."
@@ -1,5 +1,5 @@
1
- import { ContentCopy as ContentCopyIcon } from "@mui/icons-material"
2
1
  import { IconButton, type IconButtonProps } from "@mui/material"
2
+ import { ContentCopy as ContentCopyIcon } from "@mui/icons-material"
3
3
  import type { FC } from "react"
4
4
 
5
5
  export interface CopyIconButtonProps extends Omit<IconButtonProps, "onClick"> {
@@ -15,7 +15,7 @@ const CopyIconButton: FC<CopyIconButtonProps> = ({
15
15
  <IconButton
16
16
  data-testid="copy-icon-button"
17
17
  onClick={() => {
18
- navigator.clipboard.writeText(content)
18
+ void navigator.clipboard.writeText(content)
19
19
  }}
20
20
  {...otherIconButtonProps}
21
21
  >
@@ -1,4 +1,4 @@
1
- import React from "react"
1
+ import { type FC, useState } from "react"
2
2
  import { Typography, type TypographyProps } from "@mui/material"
3
3
 
4
4
  import { useCountdown } from "../hooks"
@@ -9,7 +9,7 @@ export interface CountdownProps extends Omit<TypographyProps, "children"> {
9
9
  onEnd: () => void
10
10
  }
11
11
 
12
- const Countdown: React.FC<CountdownProps> = ({
12
+ const Countdown: FC<CountdownProps> = ({
13
13
  seconds,
14
14
  start = true,
15
15
  onEnd,
@@ -17,7 +17,7 @@ const Countdown: React.FC<CountdownProps> = ({
17
17
  }) => {
18
18
  seconds = Math.floor(seconds)
19
19
  const _seconds = useCountdown(seconds)[0]
20
- const [end, setEnd] = React.useState(!start)
20
+ const [end, setEnd] = useState(!start)
21
21
 
22
22
  if (_seconds === 0 && !end) {
23
23
  setEnd(true)
@@ -24,7 +24,8 @@ const DownloadFileButton: FC<DownloadFileButtonProps> = ({
24
24
  let url: undefined | string = undefined
25
25
  let anchorProps: undefined | { download?: string; href: string } = undefined
26
26
  if ("mimeType" in file) {
27
- let { text, mimeType, name, charset = "utf-8", extension } = file
27
+ const { text, mimeType, name, charset = "utf-8" } = file
28
+ let { extension } = file
28
29
 
29
30
  if (!extension) extension = "." + { plain: "txt", csv: "csv" }[mimeType]
30
31
 
@@ -1,20 +1,20 @@
1
- import React from "react"
2
1
  import {
3
2
  AppBar,
4
3
  type AppBarProps,
4
+ Container,
5
+ type ContainerProps,
5
6
  Toolbar,
6
7
  type ToolbarProps,
7
8
  useScrollTrigger,
8
- Container,
9
- type ContainerProps,
10
9
  } from "@mui/material"
10
+ import { type FC, cloneElement } from "react"
11
11
 
12
12
  export interface ElevatedAppBarProps extends Omit<AppBarProps, "position"> {
13
13
  containerProps: ContainerProps
14
14
  toolbarProps?: ToolbarProps
15
15
  }
16
16
 
17
- const ElevatedAppBar: React.FC<ElevatedAppBarProps> = ({
17
+ const ElevatedAppBar: FC<ElevatedAppBarProps> = ({
18
18
  containerProps,
19
19
  toolbarProps,
20
20
  elevation = 4,
@@ -26,7 +26,7 @@ const ElevatedAppBar: React.FC<ElevatedAppBarProps> = ({
26
26
  threshold: 0,
27
27
  })
28
28
 
29
- return React.cloneElement(
29
+ return cloneElement(
30
30
  <AppBar elevation={elevation} {...otherProps}>
31
31
  <Container {...containerProps}>
32
32
  <Toolbar {...toolbarProps}>{children}</Toolbar>
@@ -1,5 +1,5 @@
1
1
  import { Box, type BoxProps } from "@mui/material"
2
- import type React from "react"
2
+ import { type FC } from "react"
3
3
 
4
4
  import { openInNewTab } from "../utils/general"
5
5
 
@@ -10,12 +10,12 @@ export interface ImageProps extends Omit<BoxProps, "component"> {
10
10
  hrefInNewTab?: boolean
11
11
  }
12
12
 
13
- const Image: React.FC<ImageProps> = ({
14
- href,
15
- hrefInNewTab = false,
16
- ...props
17
- }) => {
18
- let { onClick, style = {}, ...otherProps } = props
13
+ const Image: FC<ImageProps> = ({ href, hrefInNewTab = false, ...props }) => {
14
+ let {
15
+ onClick,
16
+ style = {},
17
+ ...otherProps // eslint-disable-line prefer-const
18
+ } = props
19
19
 
20
20
  if (style.width === undefined) {
21
21
  style.width = "100%"
@@ -1,9 +1,9 @@
1
+ import { Button, type ButtonProps } from "@mui/material"
1
2
  import {
2
- type FC,
3
3
  type DetailedHTMLProps,
4
+ type FC,
4
5
  type InputHTMLAttributes,
5
6
  } from "react"
6
- import { Button, type ButtonProps } from "@mui/material"
7
7
 
8
8
  export interface InputFileButtonProps
9
9
  extends Omit<ButtonProps<"label">, "component"> {
@@ -1,12 +1,12 @@
1
- import type React from "react"
1
+ import { type FC, type ReactElement } from "react"
2
2
  import {
3
3
  List,
4
- type ListProps,
5
4
  type ListItem,
6
5
  type ListItemText,
6
+ type ListProps,
7
7
  } from "@mui/material"
8
8
 
9
- type ListItemElement = React.ReactElement<typeof ListItem | typeof ListItemText>
9
+ type ListItemElement = ReactElement<typeof ListItem | typeof ListItemText>
10
10
 
11
11
  export interface ItemizedListProps {
12
12
  styleType:
@@ -33,7 +33,7 @@ export interface ItemizedListProps {
33
33
  children: ListItemElement | ListItemElement[]
34
34
  }
35
35
 
36
- const ItemizedList: React.FC<ItemizedListProps> = ({
36
+ const ItemizedList: FC<ItemizedListProps> = ({
37
37
  styleType,
38
38
  listProps = {},
39
39
  pl = 4,
@@ -1,4 +1,4 @@
1
- import type React from "react"
1
+ import { type FC, type ReactElement } from "react"
2
2
  import { Unstable_Grid2 as Grid, type Grid2Props } from "@mui/material"
3
3
 
4
4
  interface ItemProps
@@ -29,7 +29,7 @@ interface GlobalItemProps extends ItemProps {
29
29
  export interface OrderedGridProps {
30
30
  rows: Array<
31
31
  Array<{
32
- element: React.ReactElement
32
+ element: ReactElement
33
33
  itemProps?: ItemProps
34
34
  }>
35
35
  >
@@ -37,7 +37,7 @@ export interface OrderedGridProps {
37
37
  globalItemProps: GlobalItemProps
38
38
  }
39
39
 
40
- const OrderedGrid: React.FC<OrderedGridProps> = ({
40
+ const OrderedGrid: FC<OrderedGridProps> = ({
41
41
  rows,
42
42
  containerProps = {},
43
43
  globalItemProps,
@@ -1,6 +1,5 @@
1
- import { type FC } from "react"
2
1
  import { Link, type LinkProps } from "@mui/material"
3
-
2
+ import { type FC } from "react"
4
3
  export interface ScrollIntoViewLinkProps extends Omit<LinkProps, "onClick"> {
5
4
  elementId: string
6
5
  options?: ScrollIntoViewOptions
@@ -1,6 +1,6 @@
1
- import { SyncProblem as SyncProblemIcon } from "@mui/icons-material"
2
1
  import { Stack, Typography } from "@mui/material"
3
2
  import { type FC } from "react"
3
+ import { SyncProblem as SyncProblemIcon } from "@mui/icons-material"
4
4
 
5
5
  export interface SyncErrorProps {}
6
6
 
@@ -1,3 +1,10 @@
1
+ import {
2
+ type ElementType,
3
+ type JSX,
4
+ type JSXElementConstructor,
5
+ type ReactNode,
6
+ useEffect,
7
+ } from "react"
1
8
  import {
2
9
  TablePagination as MuiTablePagination,
3
10
  type TablePaginationProps as MuiTablePaginationProps,
@@ -6,15 +13,9 @@ import {
6
13
  type TablePaginationBaseProps,
7
14
  } from "@mui/material"
8
15
  import type { TypedUseLazyQuery } from "@reduxjs/toolkit/query/react"
9
- import {
10
- type ElementType,
11
- type JSXElementConstructor,
12
- type ReactNode,
13
- useEffect,
14
- } from "react"
15
16
 
16
- import { type Pagination, usePagination } from "../hooks/api"
17
17
  import { type ListArg, type ListResult, handleResultState } from "../utils/api"
18
+ import { type Pagination, usePagination } from "../hooks/api"
18
19
 
19
20
  export type TablePaginationProps<
20
21
  QueryArg extends ListArg,
@@ -83,10 +84,17 @@ const TablePagination = <
83
84
 
84
85
  useEffect(
85
86
  () => {
86
- trigger({ limit, offset, ...filters } as QueryArg, preferCacheValue)
87
+ void trigger({ limit, offset, ...filters } as QueryArg, preferCacheValue)
87
88
  },
88
89
  // eslint-disable-next-line react-hooks/exhaustive-deps
89
- [trigger, limit, offset, ...Object.values(filters || {}), preferCacheValue],
90
+ [
91
+ trigger,
92
+ limit,
93
+ offset,
94
+ // eslint-disable-next-line react-hooks/exhaustive-deps,@typescript-eslint/no-unsafe-assignment
95
+ ...Object.values(filters || {}),
96
+ preferCacheValue,
97
+ ],
90
98
  )
91
99
 
92
100
  const { count, max_limit } = result.data || {}
@@ -114,11 +122,13 @@ const TablePagination = <
114
122
  rowsPerPage={limit}
115
123
  onRowsPerPageChange={event => {
116
124
  setPagination({ limit: parseInt(event.target.value), page: 0 })
125
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
117
126
  if (onRowsPerPageChange) onRowsPerPageChange(event)
118
127
  }}
119
128
  page={page}
120
129
  onPageChange={(event, page) => {
121
130
  setPagination(({ limit }) => ({ limit, page }))
131
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
122
132
  if (onPageChange) onPageChange(event, page)
123
133
  }}
124
134
  // ascending order
@@ -1,11 +1,11 @@
1
- import type React from "react"
2
1
  import { Box, type BoxProps } from "@mui/material"
2
+ import { type FC } from "react"
3
3
 
4
4
  export interface YouTubeVideoProps extends Omit<BoxProps, "component"> {
5
5
  src: string
6
6
  }
7
7
 
8
- const YouTubeVideo: React.FC<YouTubeVideoProps> = ({
8
+ const YouTubeVideo: FC<YouTubeVideoProps> = ({
9
9
  src,
10
10
  style = {},
11
11
  ...otherProps