@campxdev/shared 1.10.64 → 1.10.66

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campxdev/shared",
3
- "version": "1.10.64",
3
+ "version": "1.10.66",
4
4
  "main": "./exports.ts",
5
5
  "scripts": {
6
6
  "start": "react-scripts start",
@@ -87,6 +87,7 @@ interface MultiSelectProps {
87
87
  helperText?: string
88
88
  multiple?: boolean
89
89
  limitTags?: number
90
+ onOpen?: (e: any) => void
90
91
  noOptionsText?: string
91
92
  }
92
93
 
@@ -119,6 +120,7 @@ export default function MultiSelect({
119
120
  if (!onChange) return
120
121
  onChange(value)
121
122
  }}
123
+ onOpen={props.onOpen}
122
124
  onInputChange={onInputChange}
123
125
  limitTags={limitTags}
124
126
  isOptionEqualToValue={(option: any, value: any) =>
@@ -16,6 +16,7 @@ export interface ITimePicker {
16
16
  placeholder?: string
17
17
  inputProps?: TextFieldProps
18
18
  size?: 'medium' | 'small'
19
+ disabled?: boolean
19
20
  }
20
21
 
21
22
  export default function TimePicker({
@@ -28,6 +29,7 @@ export default function TimePicker({
28
29
  value,
29
30
  placeholder,
30
31
  size = 'medium',
32
+ disabled,
31
33
  ...rest
32
34
  }: ITimePicker) {
33
35
  return (
@@ -68,6 +70,7 @@ export default function TimePicker({
68
70
  </InputAdornment>
69
71
  ),
70
72
  }}
73
+ disabled={disabled}
71
74
  {...rest.inputProps}
72
75
  />
73
76
  )
@@ -9,6 +9,8 @@ const StyledSideMenuHeader = styledMui(Box)(({ theme }) => ({
9
9
  alignItems: 'center',
10
10
  cursor: 'pointer',
11
11
  background: '#1d1d1d',
12
+ padding: '20px',
13
+ marginBottom: '25px',
12
14
  }))
13
15
 
14
16
  export const SideMenuHeader = ({ title, path }) => {
@@ -7,7 +7,7 @@ import {
7
7
  styled,
8
8
  } from '@mui/material'
9
9
  import { Store } from 'pullstate'
10
- import { memo, ReactNode } from 'react'
10
+ import { ReactNode, memo } from 'react'
11
11
  import { Link, useMatch, useResolvedPath } from 'react-router-dom'
12
12
  import { PermissionsStore } from '../../shared-state'
13
13
  import {
@@ -1,10 +1,9 @@
1
1
  import { ChevronRight } from '@mui/icons-material'
2
2
  import {
3
- Box,
4
- ListItemButton as MuiListItemButton,
5
3
  ListItemButtonProps,
6
4
  ListItemIcon,
7
5
  ListItemText,
6
+ ListItemButton as MuiListItemButton,
8
7
  styled,
9
8
  } from '@mui/material'
10
9
  import { ReactNode } from 'react'
@@ -25,11 +24,7 @@ export const ListItemButton = ({
25
24
  }: Props) => {
26
25
  return (
27
26
  <StyledListItemButton isActive={isActive} onClick={onClick}>
28
- {Icon ? (
29
- <ListItemIcon>{<Icon />}</ListItemIcon>
30
- ) : (
31
- <Box minWidth={16}></Box>
32
- )}
27
+ {Icon ? <ListItemIcon>{<Icon />}</ListItemIcon> : null}
33
28
  <ListItemText primary={label} />
34
29
  </StyledListItemButton>
35
30
  )
@@ -0,0 +1,59 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import axios from '../../config/axios'
4
+ import { SingleSelect } from '../Input'
5
+
6
+ type CourseSelectorProps = {
7
+ name?: string
8
+ label: string
9
+ required?: boolean
10
+ onChange?: (value: any) => void
11
+ allowAll?: boolean
12
+ error?: boolean
13
+ helperText?: string
14
+ } & SelectProps
15
+ export default function CourseSelector(props: CourseSelectorProps) {
16
+ const { name, required = false, label, onChange, allowAll = true } = props
17
+ const [options, setOptions] = useState([])
18
+
19
+ const handleOpen = () => {
20
+ if (options.length === 0) {
21
+ axios
22
+ .get('/square/courses')
23
+ .then((response) => {
24
+ setOptions(response.data.courses)
25
+ })
26
+ .catch((error) => {
27
+ console.error('Error fetching data from the API:', error)
28
+ })
29
+ }
30
+ }
31
+ useEffect(() => {
32
+ if (props?.value && props.value != 'all') {
33
+ handleOpen()
34
+ }
35
+ }, [props.value])
36
+ const handleOptions =
37
+ options.length > 0
38
+ ? [
39
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
40
+ ...options.map((item) => ({
41
+ label: `${item.courseName} `,
42
+ value: `${item.id}`,
43
+ })),
44
+ ]
45
+ : allowAll
46
+ ? [{ value: 'all', label: 'All' }]
47
+ : []
48
+
49
+ return (
50
+ <SingleSelect
51
+ name={name}
52
+ label={label}
53
+ required={required}
54
+ options={handleOptions}
55
+ onOpen={handleOpen}
56
+ {...props}
57
+ />
58
+ )
59
+ }
@@ -0,0 +1,60 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import axios from '../../config/axios'
4
+ import { SingleSelect } from '../Input'
5
+
6
+ type FeeTypeSelectorProps = {
7
+ name?: string
8
+ label: string
9
+ required?: boolean
10
+ allowAll?: boolean
11
+ onChange?: (value: any) => void
12
+ error?: boolean
13
+ helperText?: string
14
+ } & SelectProps
15
+ export default function FeeTypeSelector(props: FeeTypeSelectorProps) {
16
+ const { name, required = false, label, onChange, allowAll = true } = props
17
+ const [options, setOptions] = useState([])
18
+
19
+ const handleOpen = () => {
20
+ if (options.length === 0) {
21
+ axios
22
+ .get('/payments/fee-types')
23
+ .then((response) => {
24
+ setOptions(response.data)
25
+ })
26
+ .catch((error) => {
27
+ console.error('Error fetching data from the API:', error)
28
+ })
29
+ }
30
+ }
31
+ useEffect(() => {
32
+ if (props?.value && props.value != 'all') {
33
+ handleOpen()
34
+ }
35
+ }, [props.value])
36
+
37
+ const handleOptions =
38
+ options.length > 0
39
+ ? [
40
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
41
+ ...options.map((item) => ({
42
+ label: `${item.name} `,
43
+ value: `${item.slug}`,
44
+ })),
45
+ ]
46
+ : allowAll
47
+ ? [{ value: 'all', label: 'All' }]
48
+ : []
49
+
50
+ return (
51
+ <SingleSelect
52
+ name={name}
53
+ label={label}
54
+ required={required}
55
+ options={handleOptions}
56
+ onOpen={handleOpen}
57
+ {...props}
58
+ />
59
+ )
60
+ }
@@ -0,0 +1,45 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { Controller } from 'react-hook-form'
3
+ import CourseSelector from '../CourseSelector'
4
+
5
+ type FormCourseSelectorProps = {
6
+ control: any
7
+ name: string
8
+ label: string
9
+ required?: boolean
10
+ multiple?: boolean
11
+ allowAll?: boolean
12
+ onChange?: (value: any) => void
13
+ } & SelectProps
14
+ export default function FormCourseSelector(props: FormCourseSelectorProps) {
15
+ const {
16
+ name,
17
+ required = false,
18
+ control,
19
+ label,
20
+ allowAll = true,
21
+ multiple = false,
22
+ onChange,
23
+ value,
24
+ } = props
25
+
26
+ return (
27
+ <Controller
28
+ name={name}
29
+ control={control}
30
+ render={({ field, fieldState: { error } }) => (
31
+ <CourseSelector
32
+ label={label}
33
+ name={name}
34
+ onChange={onChange ?? field.onChange}
35
+ value={value ?? field?.value}
36
+ allowAll={allowAll}
37
+ required={required}
38
+ error={!!error}
39
+ helperText={error?.message}
40
+ {...props}
41
+ />
42
+ )}
43
+ />
44
+ )
45
+ }
@@ -0,0 +1,44 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { Controller } from 'react-hook-form'
3
+ import FeeTypeSelector from '../FeeTypeSelector'
4
+
5
+ type FormFeeTypeSelectorProps = {
6
+ control: any
7
+ name: string
8
+ label: string
9
+ required?: boolean
10
+ multiple?: boolean
11
+ allowAll?: boolean
12
+ onChange?: (value: any) => void
13
+ } & SelectProps
14
+ export default function FormFeeTypeSelector(props: FormFeeTypeSelectorProps) {
15
+ const {
16
+ name,
17
+ required = false,
18
+ control,
19
+ label,
20
+ allowAll = true,
21
+ multiple = false,
22
+ onChange,
23
+ value,
24
+ } = props
25
+
26
+ return (
27
+ <Controller
28
+ name={name}
29
+ control={control}
30
+ render={({ field, fieldState: { error } }) => (
31
+ <FeeTypeSelector
32
+ label={label}
33
+ name={name}
34
+ onChange={onChange ?? field.onChange}
35
+ value={value ?? field?.value}
36
+ allowAll={allowAll}
37
+ error={!!error}
38
+ helperText={error?.message}
39
+ {...props}
40
+ />
41
+ )}
42
+ />
43
+ )
44
+ }
@@ -0,0 +1,48 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { Controller } from 'react-hook-form'
3
+ import ProgramSelector from '../ProgramSelector'
4
+
5
+ type ProgramSelectorProps = {
6
+ control: any
7
+ name: string
8
+ label: string
9
+ required?: boolean
10
+ multiple?: boolean
11
+ allowAll?: boolean
12
+ filters?: { courseId: number }
13
+ onChange?: (value: any) => void
14
+ } & SelectProps
15
+ export default function FormProgramSelector(props: ProgramSelectorProps) {
16
+ const {
17
+ name,
18
+ required = false,
19
+ control,
20
+ label,
21
+ multiple = false,
22
+ allowAll = true,
23
+ onChange,
24
+ value,
25
+ filters,
26
+ } = props
27
+
28
+ return (
29
+ <Controller
30
+ name={name}
31
+ control={control}
32
+ render={({ field, fieldState: { error } }) => (
33
+ <ProgramSelector
34
+ label={label}
35
+ name={name}
36
+ onChange={onChange ?? field.onChange}
37
+ value={value ?? field?.value}
38
+ allowAll={allowAll}
39
+ filters={filters}
40
+ required={required}
41
+ error={!!error}
42
+ helperText={error?.message}
43
+ {...props}
44
+ />
45
+ )}
46
+ />
47
+ )
48
+ }
@@ -0,0 +1,48 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { Controller } from 'react-hook-form'
3
+ import QuotaSelector from '../QuotaSelector'
4
+
5
+ type FormQuotaSelectorProps = {
6
+ control: any
7
+ name: string
8
+ label: string
9
+ required?: boolean
10
+ multiple?: boolean
11
+ allowAll?: boolean
12
+ onChange?: (value: any) => void
13
+ filters?: { courseId: number }
14
+ } & SelectProps
15
+ export default function FormQuotaSelector(props: FormQuotaSelectorProps) {
16
+ const {
17
+ name,
18
+ required = false,
19
+ control,
20
+ label,
21
+ allowAll = true,
22
+ multiple = false,
23
+ onChange,
24
+ value,
25
+ filters,
26
+ } = props
27
+
28
+ return (
29
+ <Controller
30
+ name={name}
31
+ control={control}
32
+ render={({ field, fieldState: { error } }) => (
33
+ <QuotaSelector
34
+ label={label}
35
+ name={name}
36
+ onChange={onChange ?? field.onChange}
37
+ value={value ?? field?.value}
38
+ allowAll={allowAll}
39
+ filters={filters}
40
+ required={required}
41
+ error={!!error}
42
+ helperText={error?.message}
43
+ {...props}
44
+ />
45
+ )}
46
+ />
47
+ )
48
+ }
@@ -0,0 +1,48 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { Controller } from 'react-hook-form'
3
+ import SemesterSelector from '../SemesterSelector'
4
+
5
+ type SemesterSelectorProps = {
6
+ control: any
7
+ name: string
8
+ label: string
9
+ required?: boolean
10
+ multiple?: boolean
11
+ allowAll?: boolean
12
+ filters?: { courseId: number }
13
+ onChange?: (value: any) => void
14
+ } & SelectProps
15
+ export default function FormSemseterSelector(props: SemesterSelectorProps) {
16
+ const {
17
+ name,
18
+ required = false,
19
+ control,
20
+ label,
21
+ multiple = false,
22
+ allowAll = true,
23
+ onChange,
24
+ value,
25
+ filters,
26
+ } = props
27
+
28
+ return (
29
+ <Controller
30
+ name={name}
31
+ control={control}
32
+ render={({ field, fieldState: { error } }) => (
33
+ <SemesterSelector
34
+ label={label}
35
+ name={name}
36
+ onChange={onChange ?? field.onChange}
37
+ value={value ?? field?.value}
38
+ allowAll={allowAll}
39
+ filters={filters}
40
+ required={required}
41
+ error={!!error}
42
+ helperText={error?.message}
43
+ {...props}
44
+ />
45
+ )}
46
+ />
47
+ )
48
+ }
@@ -0,0 +1,98 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import { Controller } from 'react-hook-form'
4
+ import axios from '../../../../config/axios'
5
+ import { MultiSelect } from '../../../Input'
6
+
7
+ type MultiProgramSelectorProps = {
8
+ control: any
9
+ name?: string
10
+ label: string
11
+ filters?: { courseId: number }
12
+ required?: boolean
13
+ onChange?: (value: any) => void
14
+ allowAll?: boolean
15
+ error?: boolean
16
+ helperText?: string
17
+ } & SelectProps
18
+ const MultiProgramSelector = (props: MultiProgramSelectorProps) => {
19
+ const {
20
+ control,
21
+ onChange,
22
+ name,
23
+ required = false,
24
+ label,
25
+ multiple = false,
26
+ filters,
27
+ value,
28
+ allowAll = true,
29
+ } = props
30
+ const [options, setOptions] = useState([])
31
+ const [prevCourseId, setPrevCourseId] = useState(null)
32
+ const handleOpen = () => {
33
+ if (filters) {
34
+ if (filters.courseId && filters.courseId !== prevCourseId) {
35
+ setOptions([])
36
+ axios
37
+ .get('/square/branches', {
38
+ params: filters,
39
+ })
40
+ .then((response) => {
41
+ setOptions(response.data)
42
+ setPrevCourseId(filters.courseId)
43
+ })
44
+ .catch((error) => {
45
+ console.error('Error fetching data from the API:', error)
46
+ })
47
+ }
48
+ } else if (options.length === 0) {
49
+ axios
50
+ .get('/square/branches')
51
+ .then((response) => {
52
+ setOptions(response.data)
53
+ })
54
+ .catch((error) => {
55
+ console.error('Error fetching data from the API:', error)
56
+ })
57
+ }
58
+ }
59
+ useEffect(() => {
60
+ if (props?.value && props.value != 'all') {
61
+ handleOpen()
62
+ }
63
+ }, [props.value])
64
+
65
+ const handleOptions =
66
+ options.length > 0
67
+ ? [
68
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
69
+ ...options.map((item) => ({
70
+ label: `${item.branchName}`,
71
+ value: `${item.branchCode}`,
72
+ })),
73
+ ]
74
+ : allowAll
75
+ ? [{ value: 'all', label: 'All' }]
76
+ : []
77
+
78
+ return (
79
+ <Controller
80
+ name={name}
81
+ control={control}
82
+ render={({ field, fieldState: { error } }) => (
83
+ <MultiSelect
84
+ name={name}
85
+ label={label}
86
+ required={required}
87
+ options={handleOptions}
88
+ onOpen={handleOpen}
89
+ onChange={onChange ?? field.onChange}
90
+ value={value ?? field?.value}
91
+ error={!!error}
92
+ helperText={error?.message}
93
+ />
94
+ )}
95
+ />
96
+ )
97
+ }
98
+ export default MultiProgramSelector
@@ -0,0 +1,96 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import { Controller } from 'react-hook-form'
4
+ import axios from '../../../../config/axios'
5
+ import { MultiSelect } from '../../../Input'
6
+
7
+ type MultiQuotaSelectorProps = {
8
+ control: any
9
+ name?: string
10
+ label: string
11
+ filters?: { courseId: number }
12
+ required?: boolean
13
+ onChange?: (value: any) => void
14
+ allowAll?: boolean
15
+ error?: boolean
16
+ helperText?: string
17
+ } & SelectProps
18
+ export default function MultiQuotaSelector(props: MultiQuotaSelectorProps) {
19
+ const {
20
+ control,
21
+ onChange,
22
+ name,
23
+ required = false,
24
+ label,
25
+ multiple = false,
26
+ filters,
27
+ value,
28
+ allowAll = true,
29
+ } = props
30
+ const [options, setOptions] = useState([])
31
+ const [prevCourseId, setPrevCourseId] = useState(null)
32
+ const handleOpen = () => {
33
+ if (filters) {
34
+ if (filters.courseId && filters.courseId !== prevCourseId) {
35
+ setOptions([])
36
+ axios
37
+ .get('/square/quotas', {
38
+ params: filters,
39
+ })
40
+ .then((response) => {
41
+ setOptions(response.data)
42
+ setPrevCourseId(filters.courseId)
43
+ })
44
+ .catch((error) => {
45
+ console.error('Error fetching data from the API:', error)
46
+ })
47
+ }
48
+ } else if (options.length === 0) {
49
+ axios
50
+ .get('/square/quotas')
51
+ .then((response) => {
52
+ setOptions(response.data)
53
+ })
54
+ .catch((error) => {
55
+ console.error('Error fetching data from the API:', error)
56
+ })
57
+ }
58
+ }
59
+ useEffect(() => {
60
+ if (props?.value && props.value != 'all') {
61
+ handleOpen()
62
+ }
63
+ }, [props.value])
64
+ const handleOptions =
65
+ options.length > 0
66
+ ? [
67
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
68
+ ...options.map((item) => ({
69
+ label: `${item.name}`,
70
+ value: `${item.id}`,
71
+ })),
72
+ ]
73
+ : allowAll
74
+ ? [{ value: 'all', label: 'All' }]
75
+ : []
76
+
77
+ return (
78
+ <Controller
79
+ name={name}
80
+ control={control}
81
+ render={({ field, fieldState: { error } }) => (
82
+ <MultiSelect
83
+ name={name}
84
+ label={label}
85
+ required={required}
86
+ options={handleOptions}
87
+ onOpen={handleOpen}
88
+ onChange={onChange ?? field.onChange}
89
+ value={value ?? field?.value}
90
+ error={!!error}
91
+ helperText={error?.message}
92
+ />
93
+ )}
94
+ />
95
+ )
96
+ }
@@ -1,20 +1,46 @@
1
- import { useState } from 'react'
2
- import { FormSingleSelect } from '../HookForm'
3
- import axios from '../../config/axios'
4
1
  import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import axios from '../../config/axios'
4
+ import { SingleSelect } from '../Input'
5
5
 
6
6
  type ProgramSelectorProps = {
7
- control: any
8
- name: string
7
+ name?: string
9
8
  label: string
9
+ filters?: { courseId: number }
10
10
  required?: boolean
11
- multiple?: boolean
11
+ onChange?: (value: any) => void
12
+ allowAll?: boolean
13
+ error?: boolean
14
+ helperText?: string
12
15
  } & SelectProps
13
- export default function ProgramSelector(props: ProgramSelectorProps) {
14
- const { name, required = false, control, label, multiple = false } = props
16
+ const ProgramSelector = (props: ProgramSelectorProps) => {
17
+ const {
18
+ name,
19
+ required = false,
20
+ label,
21
+ multiple = false,
22
+ filters,
23
+ allowAll = true,
24
+ } = props
15
25
  const [options, setOptions] = useState([])
16
- const handleOpen = (e) => {
17
- if (options.length === 0) {
26
+ const [prevCourseId, setPrevCourseId] = useState(null)
27
+ const handleOpen = () => {
28
+ if (filters) {
29
+ if (filters.courseId && filters.courseId !== prevCourseId) {
30
+ setOptions([])
31
+ axios
32
+ .get('/square/branches', {
33
+ params: filters,
34
+ })
35
+ .then((response) => {
36
+ setOptions(response.data)
37
+ setPrevCourseId(filters.courseId)
38
+ })
39
+ .catch((error) => {
40
+ console.error('Error fetching data from the API:', error)
41
+ })
42
+ }
43
+ } else if (options.length === 0) {
18
44
  axios
19
45
  .get('/square/branches')
20
46
  .then((response) => {
@@ -25,25 +51,35 @@ export default function ProgramSelector(props: ProgramSelectorProps) {
25
51
  })
26
52
  }
27
53
  }
54
+ useEffect(() => {
55
+ if (props?.value && props.value != 'all') {
56
+ handleOpen()
57
+ }
58
+ }, [props.value])
59
+
28
60
  const handleOptions =
29
61
  options.length > 0
30
62
  ? [
31
- { value: 'all', label: 'All' },
63
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
32
64
  ...options.map((item) => ({
33
- label: `${item.branchName} (${item.course.courseName})`,
34
- value: `${item.id}`,
65
+ label: `${item.branchName}`,
66
+ value: `${item.branchCode}`,
35
67
  })),
36
68
  ]
37
- : [{ value: 'all', label: 'All' }]
69
+ : allowAll
70
+ ? [{ value: 'all', label: 'All' }]
71
+ : []
72
+
38
73
  return (
39
- <FormSingleSelect
40
- control={control}
74
+ <SingleSelect
41
75
  name={name}
42
76
  label={label}
43
77
  required={required}
44
78
  options={handleOptions}
45
79
  onOpen={handleOpen}
80
+ defaultValue="all"
46
81
  {...props}
47
82
  />
48
83
  )
49
84
  }
85
+ export default ProgramSelector
@@ -0,0 +1,83 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import axios from '../../config/axios'
4
+ import { SingleSelect } from '../Input'
5
+
6
+ type QuotaSelectorProps = {
7
+ name?: string
8
+ label: string
9
+ filters?: { courseId: number }
10
+ required?: boolean
11
+ onChange?: (value: any) => void
12
+ allowAll?: boolean
13
+ error?: boolean
14
+ helperText?: string
15
+ } & SelectProps
16
+ export default function QuotaSelector(props: QuotaSelectorProps) {
17
+ const {
18
+ name,
19
+ required = false,
20
+ label,
21
+ multiple = false,
22
+ filters,
23
+ allowAll = true,
24
+ } = props
25
+ const [options, setOptions] = useState([])
26
+ const [prevCourseId, setPrevCourseId] = useState(null)
27
+ const handleOpen = () => {
28
+ if (filters) {
29
+ if (filters.courseId && filters.courseId !== prevCourseId) {
30
+ setOptions([])
31
+ axios
32
+ .get('/square/quotas', {
33
+ params: filters,
34
+ })
35
+ .then((response) => {
36
+ setOptions(response.data)
37
+ setPrevCourseId(filters.courseId)
38
+ })
39
+ .catch((error) => {
40
+ console.error('Error fetching data from the API:', error)
41
+ })
42
+ }
43
+ } else if (options.length === 0) {
44
+ axios
45
+ .get('/square/quotas')
46
+ .then((response) => {
47
+ setOptions(response.data)
48
+ })
49
+ .catch((error) => {
50
+ console.error('Error fetching data from the API:', error)
51
+ })
52
+ }
53
+ }
54
+ useEffect(() => {
55
+ if (props?.value && props.value != 'all') {
56
+ handleOpen()
57
+ }
58
+ }, [props.value])
59
+ const handleOptions =
60
+ options.length > 0
61
+ ? [
62
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
63
+ ...options.map((item) => ({
64
+ label: `${item.name}`,
65
+ value: `${item.id}`,
66
+ })),
67
+ ]
68
+ : allowAll
69
+ ? [{ value: 'all', label: 'All' }]
70
+ : []
71
+
72
+ return (
73
+ <SingleSelect
74
+ name={name}
75
+ label={label}
76
+ required={required}
77
+ options={handleOptions}
78
+ onOpen={handleOpen}
79
+ defaultValue="all"
80
+ {...props}
81
+ />
82
+ )
83
+ }
@@ -0,0 +1,85 @@
1
+ import { SelectProps } from '@mui/material'
2
+ import { useEffect, useState } from 'react'
3
+ import axios from '../../config/axios'
4
+ import { SingleSelect } from '../Input'
5
+
6
+ type SemesterSelectorProps = {
7
+ name?: string
8
+ label: string
9
+ filters?: { courseId: number }
10
+ required?: boolean
11
+ onChange?: (value: any) => void
12
+ allowAll?: boolean
13
+ error?: boolean
14
+ helperText?: string
15
+ } & SelectProps
16
+ const SemesterSelector = (props: SemesterSelectorProps) => {
17
+ const {
18
+ name,
19
+ required = false,
20
+ label,
21
+ multiple = false,
22
+ filters,
23
+ allowAll = true,
24
+ } = props
25
+ const [options, setOptions] = useState([])
26
+ const [prevCourseId, setPrevCourseId] = useState(null)
27
+ const handleOpen = () => {
28
+ if (filters) {
29
+ if (filters.courseId && filters.courseId !== prevCourseId) {
30
+ setOptions([])
31
+ axios
32
+ .get('/square/semesters', {
33
+ params: filters,
34
+ })
35
+ .then((response) => {
36
+ setOptions(response.data)
37
+ setPrevCourseId(filters.courseId)
38
+ })
39
+ .catch((error) => {
40
+ console.error('Error fetching data from the API:', error)
41
+ })
42
+ }
43
+ } else if (options.length === 0) {
44
+ axios
45
+ .get('/square/semesters')
46
+ .then((response) => {
47
+ setOptions(response.data)
48
+ })
49
+ .catch((error) => {
50
+ console.error('Error fetching data from the API:', error)
51
+ })
52
+ }
53
+ }
54
+ useEffect(() => {
55
+ console.log(props.value)
56
+ if (props?.value && props.value != 'all') {
57
+ handleOpen()
58
+ }
59
+ }, [props.value])
60
+
61
+ const handleOptions =
62
+ options.length > 0
63
+ ? [
64
+ ...(allowAll ? [{ value: 'all', label: 'All' }] : []),
65
+ ...options.map((item) => ({
66
+ label: `${item.name}`,
67
+ value: `${item.semNo}`,
68
+ })),
69
+ ]
70
+ : allowAll
71
+ ? [{ value: 'all', label: 'All' }]
72
+ : []
73
+
74
+ return (
75
+ <SingleSelect
76
+ name={name}
77
+ label={label}
78
+ required={required}
79
+ options={handleOptions}
80
+ onOpen={handleOpen}
81
+ {...props}
82
+ />
83
+ )
84
+ }
85
+ export default SemesterSelector
@@ -1,2 +1,27 @@
1
+ import CourseSelector from './CourseSelector'
2
+ import FeeTypeSelector from './FeeTypeSelector'
3
+ import FormCourseSelector from './FormSelectors/FormCourseSelector'
4
+ import FormFeeTypeSelector from './FormSelectors/FormFeeTypeSelector'
5
+ import FormProgramSelector from './FormSelectors/FormProgramSelector'
6
+ import FormQuotaSelector from './FormSelectors/FormQuotaSelector'
7
+ import FormSemseterSelector from './FormSelectors/FormSemesterSelector'
8
+ import MultiProgramSelector from './FormSelectors/MultiSelect/MultiProgramSelector'
9
+ import MultiQuotaSelector from './FormSelectors/MultiSelect/MultiQuotaSelector'
1
10
  import ProgramSelector from './ProgramSelector'
2
- export { ProgramSelector }
11
+ import QuotaSelector from './QuotaSelector'
12
+ import SemesterSelector from './SemesterSelector'
13
+
14
+ export {
15
+ CourseSelector,
16
+ FeeTypeSelector,
17
+ FormCourseSelector,
18
+ FormFeeTypeSelector,
19
+ FormProgramSelector,
20
+ FormQuotaSelector,
21
+ FormSemseterSelector,
22
+ MultiProgramSelector,
23
+ MultiQuotaSelector,
24
+ ProgramSelector,
25
+ QuotaSelector,
26
+ SemesterSelector,
27
+ }
@@ -0,0 +1,218 @@
1
+ import {
2
+ Box,
3
+ IconButton,
4
+ ListItemIcon,
5
+ Table as MuiTable,
6
+ TableBody,
7
+ TableCell,
8
+ TableContainer,
9
+ TableHead,
10
+ TableRow,
11
+ alpha,
12
+ styled,
13
+ } from '@mui/material'
14
+ import _ from 'lodash'
15
+ import { useEffect, useState } from 'react'
16
+ import Spinner from '../../Spinner'
17
+ import TableFooter from '../BasicTable/TableFooter'
18
+ import NoRecordsFound from '../common/NoRecordsFound'
19
+ import { SortAscIcon, SortDescIcon, SortIcon } from '../common/icons'
20
+
21
+ export interface ColumnProps {
22
+ dataIndex: string
23
+ key: string
24
+ title: any
25
+ render?: (cellData: any, row: any, index: number) => any
26
+ textColor?: string
27
+ sort?: boolean
28
+ width?: string //pixels
29
+ }
30
+
31
+ interface TableProps {
32
+ columns: Array<ColumnProps>
33
+ rowKey?: string
34
+ dataSource?: any[]
35
+ loading?: boolean
36
+ onRowClick?: (row: any) => void
37
+ pagination?: {
38
+ page: number
39
+ limit: number
40
+ totalCount: number
41
+ onChange: (v: number) => void
42
+ onChangeLimit?: (v: number) => void
43
+ }
44
+ onSort?: (sort: any) => void
45
+ dense?: boolean
46
+ isLastRowColorChange?: boolean
47
+ }
48
+
49
+ type Order = 'asc' | 'desc' | ''
50
+ type Sort = {}
51
+
52
+ export default function MobileTable({
53
+ columns,
54
+ dataSource,
55
+ onRowClick,
56
+ pagination,
57
+ loading,
58
+ onSort,
59
+ dense = false,
60
+ isLastRowColorChange = false,
61
+ }: TableProps) {
62
+ const [sort, setSort] = useState<Sort>({})
63
+
64
+ const handleSortClick = (sortBykey) => {
65
+ setSort((prev) => {
66
+ if (prev[sortBykey]) {
67
+ if (prev[sortBykey] === 'desc') return { ...prev, [sortBykey]: 'asc' }
68
+ if (prev[sortBykey] === 'asc') {
69
+ delete prev[sortBykey]
70
+ return { ...prev }
71
+ }
72
+ } else {
73
+ return {
74
+ ...prev,
75
+ [sortBykey]: 'desc',
76
+ }
77
+ }
78
+ })
79
+ }
80
+
81
+ useEffect(() => {
82
+ if (!onSort) return
83
+
84
+ onSort({
85
+ sortBy: Object.keys(sort).join(','),
86
+ sortOrder: Object.keys(sort)
87
+ .map((item) => sort[item])
88
+ .join(','),
89
+ })
90
+ }, [sort])
91
+
92
+ return (
93
+ <StyledTableContainer>
94
+ <>
95
+ <StyledMuiTable>
96
+ <TableHead>
97
+ <TableRow>
98
+ {columns.map((col, index) => (
99
+ <TableCell
100
+ key={index}
101
+ sx={{
102
+ ...(col?.width && {
103
+ width: col?.width,
104
+ }),
105
+ borderRightColor: '#1212121A',
106
+ borderRightStyle: 'solid',
107
+ }}
108
+ >
109
+ <Box sx={{ fontWeight: 500, fontSize: '14px' }}>
110
+ {col.title}
111
+ </Box>
112
+ {col.sort && (
113
+ <IconButton onClick={() => handleSortClick(col.dataIndex)}>
114
+ <ListItemIcon>
115
+ {sort[col.dataIndex] === 'asc' ? (
116
+ <SortAscIcon />
117
+ ) : sort[col.dataIndex] === 'desc' ? (
118
+ <SortDescIcon />
119
+ ) : (
120
+ <SortIcon />
121
+ )}
122
+ </ListItemIcon>
123
+ </IconButton>
124
+ )}
125
+ </TableCell>
126
+ ))}
127
+ </TableRow>
128
+ </TableHead>
129
+ {!loading ? (
130
+ <>
131
+ {dataSource?.length ? (
132
+ <TableBody>
133
+ {dataSource?.map((row, index) => (
134
+ <StyledTableRow
135
+ canRowClick={!!onRowClick}
136
+ hover={!!onRowClick}
137
+ key={index}
138
+ onClick={() => {
139
+ return onRowClick && onRowClick(row)
140
+ }}
141
+ isLastRowColorChange={isLastRowColorChange}
142
+ >
143
+ {columns.map((col, colIndex) => (
144
+ <TableCell
145
+ sx={{
146
+ color: col.textColor,
147
+ padding: dense ? '10px' : '15px',
148
+ font: 'avenir',
149
+ fontSize: '14px',
150
+ borderRightColor: '#1212121A',
151
+ borderRightStyle: 'solid',
152
+ }}
153
+ key={colIndex}
154
+ >
155
+ <>
156
+ {col?.render
157
+ ? col.render(row[col.dataIndex], row, index)
158
+ : _.get(row, col.dataIndex)}
159
+ </>
160
+ </TableCell>
161
+ ))}
162
+ </StyledTableRow>
163
+ ))}
164
+ </TableBody>
165
+ ) : (
166
+ <>
167
+ <NoRecordsFound colLength={columns?.length} />
168
+ </>
169
+ )}
170
+ </>
171
+ ) : (
172
+ <Spinner />
173
+ )}
174
+ </StyledMuiTable>
175
+ </>
176
+ <>
177
+ {pagination && (
178
+ <TableFooter
179
+ page={pagination.page + 1}
180
+ limit={pagination.limit}
181
+ totalCount={pagination.totalCount ?? 0}
182
+ handlePagination={pagination.onChange}
183
+ handlePageLimit={pagination.onChangeLimit}
184
+ />
185
+ )}
186
+ </>
187
+ </StyledTableContainer>
188
+ )
189
+ }
190
+
191
+ const StyledTableContainer = styled(TableContainer)<{}>(({ theme }) => ({
192
+ width: '100%',
193
+ overflowX: 'auto',
194
+ borderRadius: '10px 10px 10px 10px',
195
+ border: '1px solid #1212121A',
196
+ }))
197
+
198
+ const StyledMuiTable = styled(MuiTable)<{}>(({ theme }) => ({
199
+ border: 'none',
200
+ }))
201
+
202
+ const StyledTableRow = styled(TableRow, {
203
+ shouldForwardProp: (prop) => prop !== 'canRowClick',
204
+ })<{ canRowClick: boolean; isLastRowColorChange?: boolean }>(
205
+ ({ canRowClick, isLastRowColorChange }) => ({
206
+ ...(canRowClick && {
207
+ cursor: 'pointer',
208
+ '&.MuiTableRow-hover:hover': {
209
+ backgroundColor: alpha('#f2f2f2', 0.4),
210
+ },
211
+ }),
212
+ ...(isLastRowColorChange && {
213
+ '&:last-child': {
214
+ backgroundColor: '#F2F2F2',
215
+ },
216
+ }),
217
+ }),
218
+ )
@@ -0,0 +1 @@
1
+ export { default } from './MobileTable'
@@ -11,17 +11,21 @@ export interface TabsContainerProps {
11
11
  highlight?: boolean
12
12
  }[]
13
13
  size?: 'small' | 'medium'
14
- conatinerVariant?: 'box' | 'page'
14
+ containerVariant?: 'box' | 'page'
15
15
  onTabChange?: (tabKey: string) => void
16
16
  isMobile?: boolean
17
+ tabUnderlineColor?: string
18
+ tabMobileUnderlineColor?: string
17
19
  }
18
20
 
19
21
  export default function TabsContainer({
20
22
  tabs,
21
23
  size = 'small',
22
- conatinerVariant = 'box',
24
+ containerVariant = 'box',
23
25
  isMobile = false,
24
26
  onTabChange,
27
+ tabUnderlineColor,
28
+ tabMobileUnderlineColor,
25
29
  }: TabsContainerProps) {
26
30
  const [currentTab, setCurrentTab] = useState(tabs[0].key)
27
31
 
@@ -36,7 +40,7 @@ export default function TabsContainer({
36
40
  return (
37
41
  <StyledContainer>
38
42
  <StyledTabs
39
- containerVariant={conatinerVariant}
43
+ containerVariant={containerVariant}
40
44
  size={size}
41
45
  onChange={handleTabsChange}
42
46
  value={currentTab}
@@ -45,6 +49,8 @@ export default function TabsContainer({
45
49
  textColor="primary"
46
50
  indicatorColor="primary"
47
51
  isMobile={isMobile}
52
+ underlineColor={tabUnderlineColor}
53
+ mobileUnderlineColor={tabMobileUnderlineColor}
48
54
  >
49
55
  {tabs.map((tab) => (
50
56
  <Tab
@@ -56,7 +62,7 @@ export default function TabsContainer({
56
62
  />
57
63
  ))}
58
64
  </StyledTabs>
59
- <StyledComponentWrapper containerVariant={conatinerVariant}>
65
+ <StyledComponentWrapper containerVariant={containerVariant}>
60
66
  <ErrorBoundary>
61
67
  {tabs.find((tab) => tab.key === currentTab)?.component}
62
68
  </ErrorBoundary>
@@ -1,50 +1,62 @@
1
1
  import { Box, Stack, styled, Tabs } from '@mui/material'
2
2
 
3
- export const StyledTabs = styled(Tabs)<{
3
+ interface StyledTabsProps {
4
4
  size: 'small' | 'medium'
5
5
  containerVariant?: 'page' | 'box'
6
6
  isMobile?: false | true
7
- }>(({ theme, size, containerVariant, isMobile }) => ({
8
- borderTopRightRadius: '10px',
9
- borderTopLeftRadius: '10px',
10
- background: theme.palette.secondary.light,
11
- minHeight: isMobile ? '30px' : '60px',
12
- paddingLeft: '15px',
13
- '& .MuiTabs-indicator': {
14
- backgroundColor: theme.palette.common.yellow,
15
- [theme.breakpoints.down('sm')]: {
16
- backgroundColor: theme.palette.primary.main,
7
+ underlineColor?: string
8
+ mobileUnderlineColor?: string
9
+ }
10
+
11
+ export const StyledTabs = styled(Tabs)<StyledTabsProps>(
12
+ ({
13
+ theme,
14
+ size,
15
+ containerVariant,
16
+ isMobile,
17
+ underlineColor,
18
+ mobileUnderlineColor,
19
+ }) => ({
20
+ borderTopRightRadius: '10px',
21
+ borderTopLeftRadius: '10px',
22
+ background: theme.palette.secondary.light,
23
+ minHeight: isMobile ? '30px' : '60px',
24
+ paddingLeft: '15px',
25
+ '& .MuiTabs-indicator': {
26
+ backgroundColor: isMobile
27
+ ? mobileUnderlineColor
28
+ : underlineColor ?? theme.palette.common.yellow,
17
29
  },
18
- },
19
- '& span': {
20
- color: theme.palette.error.main,
21
- fontSize: '20px',
22
- marginTop: '-20px',
23
- marginLeft: '3px !important',
24
- },
25
- '& .MuiTabs-flexContainer': {
26
- height: '100%',
27
- alignItems: 'end',
28
- justifyContent: isMobile ? 'center' : 'flex-start',
29
- },
30
- '& .MuiTab-root': {
31
- textTransform: 'none',
32
- transition: 'color 0.2s ease-in-out',
33
- padding: '5px 15px',
34
- paddingBottom: '8px',
35
- minHeight: 0,
36
- fontSize: size === 'medium' ? '16px' : '14px',
37
- fontWeight: '600',
38
- },
39
- '& .MuiTab-root.Mui-selected': {
40
- color: theme.palette.secondary.main,
41
- },
42
- ...(containerVariant === 'page' && {
43
- background: 'none',
44
- paddingLeft: 0,
45
- borderBottom: theme.borders.grayLight,
30
+ '& span': {
31
+ color: theme.palette.error.main,
32
+ fontSize: '20px',
33
+ marginTop: '-20px',
34
+ marginLeft: '3px !important',
35
+ },
36
+ '& .MuiTabs-flexContainer': {
37
+ height: '100%',
38
+ alignItems: 'end',
39
+ justifyContent: isMobile ? 'center' : 'flex-start',
40
+ },
41
+ '& .MuiTab-root': {
42
+ textTransform: 'none',
43
+ transition: 'color 0.2s ease-in-out',
44
+ padding: '5px 15px',
45
+ paddingBottom: '8px',
46
+ minHeight: 0,
47
+ fontSize: size === 'medium' ? '16px' : '14px',
48
+ fontWeight: isMobile ? '500' : '600',
49
+ },
50
+ '& .MuiTab-root.Mui-selected': {
51
+ color: theme.palette.secondary.main,
52
+ },
53
+ ...(containerVariant === 'page' && {
54
+ background: 'none',
55
+ paddingLeft: 0,
56
+ borderBottom: theme.borders.grayLight,
57
+ }),
46
58
  }),
47
- }))
59
+ )
48
60
 
49
61
  export const StyledContainer = styled(Stack)(({ theme }) => ({
50
62
  borderRadius: '10px',
@@ -42,7 +42,6 @@ import UploadFileDialog from './UploadFileDialog'
42
42
  export { default as ActionButton } from './ActionButton'
43
43
  export { default as AutocompleteSearch } from './AutocompleteSearch'
44
44
  export { default as Breadcrumbs } from './Breadcrumbs'
45
- export { default as ReportPageHeader } from './ReportPageHeader'
46
45
  export { default as Card } from './Card'
47
46
  export { default as CardsGrid } from './CardsGrid'
48
47
  export { default as DividerHeading } from './DividerHeading'
@@ -56,10 +55,12 @@ export { default as NoDataIllustration } from './NoDataIllustration'
56
55
  export { PageContent } from './PageContent'
57
56
  export { default as PageHeader } from './PageHeader'
58
57
  export { default as useConfirm } from './PopupConfirm/useConfirm'
58
+ export { default as ReportPageHeader } from './ReportPageHeader'
59
59
  export { default as Spinner } from './Spinner'
60
60
  export { default as SwitchButton } from './SwitchButton'
61
61
  export { default as Table } from './Tables/BasicTable'
62
62
  export { default as TableFooter } from './Tables/BasicTable/TableFooter'
63
+ export { default as MobileTable } from './Tables/MobileTable'
63
64
  export { default as ReactTable } from './Tables/ReactTable'
64
65
  export { default as Tabs } from './Tabs/Tabs'
65
66
  export { default as ToastContainer } from './ToastContainer'
@@ -111,5 +112,5 @@ export {
111
112
  export * from './HookForm'
112
113
  export * from './IconButtons'
113
114
  export * from './Input'
114
- export * from './UploadButton/types'
115
115
  export * from './Selectors'
116
+ export * from './UploadButton/types'