@fixefy/fixefy-ui-components 0.0.37 → 0.0.39

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 (103) hide show
  1. package/.prettierrc.json +10 -0
  2. package/.swcrc +20 -0
  3. package/build/FxTag/FxTag.js +41 -0
  4. package/build/FxTag/fxtag_types.d.js +4 -0
  5. package/build/FxTag/index.js +20 -0
  6. package/build/FxTag/styles/tag.styles.js +94 -0
  7. package/package.json +7 -7
  8. package/src/FxActionsTray/FxActionsTray.tsx +293 -0
  9. package/src/FxActionsTray/actions_tray_types.d.ts +15 -0
  10. package/src/FxActionsTray/index.ts +3 -0
  11. package/src/FxActionsTray/styles/actions_tray.styles.tsx +90 -0
  12. package/src/FxAggregationsBar/FxAggregations.tsx +32 -0
  13. package/src/FxAggregationsBar/aggregations_types.d.ts +21 -0
  14. package/src/FxAggregationsBar/helpers/structureReader.tsx +66 -0
  15. package/src/FxAggregationsBar/index.ts +2 -0
  16. package/src/FxAggregationsBar/operations/query.ts +64 -0
  17. package/src/FxAsyncDropdown/FxAsyncDropdown.tsx +362 -0
  18. package/src/FxAsyncDropdown/async_dropdown_types.d.ts +40 -0
  19. package/src/FxAsyncDropdown/helpers/helpers.ts +105 -0
  20. package/src/FxAsyncDropdown/index.ts +2 -0
  21. package/src/FxAsyncDropdown/styles/dropdown.styles.tsx +162 -0
  22. package/src/FxAvatar/FxAvatar.tsx +50 -0
  23. package/src/FxAvatar/avatar_types.d.ts +11 -0
  24. package/src/FxAvatar/helpers/stringToColor.ts +16 -0
  25. package/src/FxAvatar/index.ts +2 -0
  26. package/src/FxAvatar/styles/avatar.styles.tsx +82 -0
  27. package/src/FxButton/FxButton.tsx +11 -0
  28. package/src/FxButton/index.ts +2 -0
  29. package/src/FxButton/styles/button.styles.jsx +16 -0
  30. package/src/FxButton/styles/button.styles.tsx +14 -0
  31. package/src/FxChip/FxChip.tsx +14 -0
  32. package/src/FxChip/chip_types.d.ts +34 -0
  33. package/src/FxChip/index.ts +2 -0
  34. package/src/FxChip/styles/chip.styles.tsx +51 -0
  35. package/src/FxIcon/FxIcon.tsx +34 -0
  36. package/src/FxIcon/content/dynamic_icon.tsx +3 -0
  37. package/src/FxIcon/content/index.ts +2 -0
  38. package/src/FxIcon/content/lazy_icon.tsx +48 -0
  39. package/src/FxIcon/icon_types.d.ts +10 -0
  40. package/src/FxIcon/index.ts +2 -0
  41. package/src/FxModal/FxModal.tsx +44 -0
  42. package/src/FxModal/index.ts +2 -0
  43. package/src/FxModal/modal_types.d.ts +10 -0
  44. package/src/FxModal/styles/modal.style.tsx +40 -0
  45. package/src/FxNotes/FxNotes.tsx +165 -0
  46. package/src/FxNotes/helpers/stringToColor.ts +19 -0
  47. package/src/FxNotes/index.ts +2 -0
  48. package/src/FxNotes/note_types.d.ts +12 -0
  49. package/src/FxNotes/operations/queries.ts +21 -0
  50. package/src/FxNotes/styles/notes.styles.tsx +135 -0
  51. package/src/FxNumberField/FxNumberField.tsx +37 -0
  52. package/src/FxNumberField/index.ts +2 -0
  53. package/src/FxNumberField/number_field_types.d.ts +7 -0
  54. package/src/FxNumberField/styles/number_field.styles.ts +85 -0
  55. package/src/FxProgressCircle/FxProgressCircle.tsx +40 -0
  56. package/src/FxProgressCircle/index.ts +2 -0
  57. package/src/FxProgressCircle/progress_circle_types.d.ts +9 -0
  58. package/src/FxProgressCircle/styles/progress_circle.styles.tsx +33 -0
  59. package/src/FxProgressCounter/ProgressCounter.tsx +81 -0
  60. package/src/FxProgressCounter/index.ts +2 -0
  61. package/src/FxProgressCounter/progress_counter_types.d.ts +10 -0
  62. package/src/FxProgressCounter/styles/progress_counter.styles.ts +40 -0
  63. package/src/FxScore/FxScore.tsx +75 -0
  64. package/src/FxScore/index.ts +2 -0
  65. package/src/FxScore/score_types.d.ts +16 -0
  66. package/src/FxScore/styles/score.styles.ts +42 -0
  67. package/src/FxShowMore/FxShowMore.tsx +60 -0
  68. package/src/FxShowMore/index.ts +2 -0
  69. package/src/FxShowMore/show_more_types.d.ts +8 -0
  70. package/src/FxShowMore/styles/show_more.styles.ts +67 -0
  71. package/src/FxSlider/FxSlider.tsx +8 -0
  72. package/src/FxSlider/index.ts +2 -0
  73. package/src/FxSlider/slider_types.d.ts +3 -0
  74. package/src/FxStatisticsBar/FxStatisticsBar.tsx +112 -0
  75. package/src/FxStatisticsBar/index.ts +2 -0
  76. package/src/FxStatisticsBar/statistics_bar_types.d.ts +8 -0
  77. package/src/FxStatisticsBar/styles/statistics.styles.ts +41 -0
  78. package/src/FxStatusBar/FxStatusBar.tsx +66 -0
  79. package/src/FxStatusBar/helpers/constants.ts +12 -0
  80. package/src/FxStatusBar/index.ts +2 -0
  81. package/src/FxStatusBar/status_bar_types.d.ts +14 -0
  82. package/src/FxStatusBar/styles/statusBar.styles.tsx +67 -0
  83. package/src/FxStyledComponents/index.tsx +196 -0
  84. package/src/FxTag/FxTag.tsx +14 -0
  85. package/src/FxTag/fxtag_types.d.ts +4 -0
  86. package/src/FxTag/index.ts +2 -0
  87. package/src/FxTag/styles/tag.styles.tsx +24 -0
  88. package/src/FxTextField/FxTextField.tsx +117 -0
  89. package/src/FxTextField/index.ts +2 -0
  90. package/src/FxTextField/text_field_types.d.ts +20 -0
  91. package/src/FxTodo/FxTodo.tsx +58 -0
  92. package/src/FxTodo/index.ts +2 -0
  93. package/src/FxTodo/styles/todo.styles.tsx +113 -0
  94. package/src/FxTodo/todo_types.d.ts +19 -0
  95. package/src/FxWizard/FxWizard.tsx +56 -0
  96. package/src/FxWizard/WizardContext.tsx +108 -0
  97. package/src/FxWizard/index.ts +3 -0
  98. package/src/FxWizard/styles/wizard.styles.tsx +22 -0
  99. package/src/FxWizard/wizard_types.d.ts +37 -0
  100. package/src/index.ts +23 -0
  101. package/tsconfig.json +22 -0
  102. package/webpack.config.js +35 -0
  103. package/yarn-error.log +95 -0
@@ -0,0 +1,2 @@
1
+ export { FxStatusBar } from './FxStatusBar'
2
+ export { StatusBarPropsType } from './status_bar_types'
@@ -0,0 +1,14 @@
1
+ import { EntityStatusType, ChargeStateType, InvoiceStateType, RecoStateType } from '@fixefy/fixefy-ui-utils'
2
+
3
+ export type StatusBarPropsType = {
4
+ onSearch?: (searchValue: string) => void
5
+ onChangeStatus: (statuses: string[]) => void
6
+ defaultStatus?: string | string[]
7
+ title?: string
8
+ options?: Options
9
+ chipsVariant?: 'outlined' | 'filled'
10
+ }
11
+
12
+ type Options = {
13
+ [x: string]: keyof EntityStatusType | keyof ChargeStateType | keyof InvoiceStateType | keyof RecoStateType | string
14
+ }
@@ -0,0 +1,67 @@
1
+ import { styled } from "@mui/material/styles";
2
+ import { Box, Chip as MuiChip } from "@mui/material";
3
+
4
+ export const StatusBarCard = styled(Box)(({ theme }) => ({
5
+ background: theme.palette.common.white,
6
+ borderRadius: 4,
7
+ padding: 16,
8
+ boxShadow: "0px 0px 10px rgba(86, 135, 147, 0.3)",
9
+ display: "flex",
10
+ alignItems: "center",
11
+ width: "fit-content",
12
+ }));
13
+
14
+ export const StatusBarTitle = styled("span")(({ theme }) => ({
15
+ ...theme.typography.body1,
16
+ color: theme.palette.common.black,
17
+ }));
18
+
19
+ export const StatusChipStyled = styled(MuiChip)(({ theme, variant }) => {
20
+ let backgroundColor, border, labelColor;
21
+
22
+ if (variant === "filled") {
23
+ backgroundColor = theme.palette.primary.light;
24
+ labelColor = theme.palette.common.white;
25
+ } else {
26
+ backgroundColor = theme.palette.common.white;
27
+ }
28
+ border = "#F0F0F0";
29
+
30
+ return {
31
+ height: 20,
32
+ minWidth: 34,
33
+ maxWidth: 120,
34
+ ["& .MuiChip-label"]: {
35
+ fontSize: 9,
36
+ fontWeight: 600,
37
+ lineHeight: "12px",
38
+ color: labelColor ? labelColor : theme.palette["statistics"].label,
39
+ },
40
+ backgroundColor,
41
+ border: `1px solid ${border}`,
42
+ };
43
+ });
44
+
45
+ // export const StatusBarSearchWrapper = styled("div")(({ theme }) => ({
46
+ // position: "relative",
47
+ // display: "flex",
48
+ // alignItems: "center",
49
+ // ["& input"]: {
50
+ // ...theme.typography.body1,
51
+ // color: theme.palette.statistics.label,
52
+ // paddingLeft: 40,
53
+ // width: "100%",
54
+ // },
55
+ // ["& svg"]: {å
56
+ // position: "absolute",
57
+ // left: 16,
58
+ // color: theme.palette.primary.light,
59
+ // },
60
+ // }));
61
+
62
+ // export const StatusBarSearchBar = styled("input")(({ theme }) => ({
63
+ // background: theme.palette.common.white,
64
+ // border: "1px solid #C6DDE2",
65
+ // borderRadius: 4,
66
+ // height: 36,
67
+ // }));
@@ -0,0 +1,196 @@
1
+ import React, { ReactElement, useMemo } from 'react'
2
+
3
+ import { styled } from '@mui/material/styles'
4
+ import { titleCase } from '@fixefy/fixefy-ui-utils'
5
+ import { Paper, Link as MuiLink, Typography, Box, Grid } from '@mui/material'
6
+
7
+ export const Card = styled(Paper)(({}) => ({
8
+ borderRadius: 8,
9
+ padding: 16,
10
+ // transition: "max-height 1000ms cubic-bezier(0.4, 0, 0.2, 1) 0ms",
11
+ overflow: 'hidden',
12
+ position: 'relative',
13
+ }))
14
+
15
+ export const PageHeader = styled(Box)(({}) => ({
16
+ backgroundColor: '#E2EEF1',
17
+ width: '100%',
18
+ height: 220,
19
+ padding: 32,
20
+ }))
21
+
22
+ export const Label = styled(Typography)(({ theme }) => ({
23
+ ...theme.typography.overLineCaption,
24
+ color: theme.palette.statistics.label,
25
+ }))
26
+
27
+ export const BoldValue = styled(Typography)(({ theme }) => ({
28
+ ...theme.typography.subtitle2,
29
+ fontWeight: 700,
30
+ lineHeight: '16px',
31
+ color: theme.palette.typography.title,
32
+ }))
33
+
34
+ export const Value = styled(Typography)(({ theme }) => ({
35
+ ...theme.typography.body1,
36
+ fontFamily: theme.typography.fontFamily,
37
+ lineHeight: '20px',
38
+ color: theme.palette.typography.title,
39
+ }))
40
+
41
+ export const PageTitle = styled(Typography)(({ theme }) => ({
42
+ ...theme.typography.h4,
43
+ color: theme.palette.common.black,
44
+ }))
45
+
46
+ export const Link = styled(MuiLink)(({ theme }) => ({
47
+ ...theme.typography.body1,
48
+ lineHeight: '20px',
49
+ fontStyle: 'italic',
50
+ color: theme.palette.primary[500],
51
+ cursor: 'pointer',
52
+ textDecoration: 'none',
53
+ }))
54
+
55
+ export const Text = styled(Typography)(({ theme }) => ({
56
+ ...theme.typography.body1,
57
+ color: theme.palette.typography.title,
58
+ textOverflow: 'ellipsis',
59
+ whiteSpace: 'nowrap',
60
+ overflow: 'hidden',
61
+ }))
62
+
63
+ export const ShowMore = styled(Typography)(({ theme }) => ({
64
+ ...theme.typography.body1,
65
+ color: theme.palette.primary['500'],
66
+ fontWeight: 600,
67
+ fontSize: '12px',
68
+ letterSpacing: '0.5px',
69
+ lineHeight: '24px',
70
+ cursor: 'pointer',
71
+ }))
72
+
73
+ export const ShowMoreContainer = styled(Grid)(({ theme }) => ({
74
+ backgroundColor: theme.palette.common.white,
75
+ width: '100%',
76
+ display: 'flex',
77
+ justifyContent: 'center',
78
+ cursor: 'pointer',
79
+ }))
80
+
81
+ export const DataWrapper = ({
82
+ values = [],
83
+ title,
84
+ icon,
85
+ columns = 4,
86
+ cardStyle = {},
87
+ wrapperStyle = {},
88
+ }: {
89
+ values: ReactElement[]
90
+ title?: string
91
+ columns?: number
92
+ icon?: any
93
+ cardStyle?: any
94
+ wrapperStyle?: any
95
+ }) => {
96
+ const normalizedValues =
97
+ values.length % columns !== 0 ? [...values, ...new Array(columns - (values.length % columns))] : values
98
+
99
+ const last4Items = normalizedValues.splice(-columns)
100
+ const containerColumns = columns === 5 ? 10 : 12
101
+ return (
102
+ <Box sx={{ ...wrapperStyle }}>
103
+ {(title || icon) && (
104
+ <Box display='flex' alignItems='center' sx={{ ml: 2, mb: 1 }}>
105
+ {icon && icon}
106
+ {title && <BoldValue sx={{ ml: 1 }}>{titleCase(title)}</BoldValue>}
107
+ </Box>
108
+ )}
109
+ <Card elevation={0} sx={{ padding: 0, border: `1px solid #F0F0F0`, ...cardStyle }}>
110
+ <Grid container columns={containerColumns}>
111
+ {normalizedValues.map((value, index) => {
112
+ return (
113
+ <Grid
114
+ sx={{
115
+ minHeight: 74,
116
+ padding: 2,
117
+ borderRight: value && (index + 1) % columns !== 0 && `1px solid #F0F0F0`,
118
+ borderBottom: value && `1px solid #F0F0F0`,
119
+ display: 'flex',
120
+ alignItems: 'center',
121
+ }}
122
+ item
123
+ key={index}
124
+ xs={containerColumns / columns}
125
+ >
126
+ {value && React.cloneElement(value)}
127
+ </Grid>
128
+ )
129
+ })}
130
+ {last4Items.map((value, index) => {
131
+ return (
132
+ <Grid
133
+ sx={{
134
+ minHeight: 74,
135
+ padding: 2,
136
+ borderRight: value && (index + 1) % columns !== 0 && `1px solid #F0F0F0`,
137
+ display: 'flex',
138
+ alignItems: 'center',
139
+ }}
140
+ item
141
+ key={index}
142
+ xs={containerColumns / columns}
143
+ >
144
+ {value && React.cloneElement(value)}
145
+ </Grid>
146
+ )
147
+ })}
148
+ </Grid>
149
+ </Card>
150
+ </Box>
151
+ )
152
+ }
153
+
154
+ interface field {
155
+ value: number
156
+ color: string
157
+ }
158
+
159
+ export const Bars = ({ fields }: { fields: field[] }) => {
160
+ const max = useMemo(() => {
161
+ return fields.reduce((total, acc) => {
162
+ return acc.value > total ? acc.value : total
163
+ }, 0)
164
+ }, [fields])
165
+
166
+ const calculateTheValue = (value: number) => {
167
+ const calculatedValue = (value * 24) / max
168
+
169
+ if (calculatedValue > 0 && calculatedValue < 2) {
170
+ return 2
171
+ }
172
+ if (calculatedValue < 1) {
173
+ return 1
174
+ }
175
+ return calculatedValue
176
+ }
177
+
178
+ return (
179
+ <div style={{ display: 'flex', alignItems: 'flex-end' }}>
180
+ {fields.map((field, index) => {
181
+ return (
182
+ <div
183
+ key={index}
184
+ style={{
185
+ width: 8,
186
+ borderRadius: '0.75px',
187
+ height: calculateTheValue(field.value),
188
+ backgroundColor: field.color,
189
+ marginRight: 2,
190
+ }}
191
+ />
192
+ )
193
+ })}
194
+ </div>
195
+ )
196
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react'
2
+ import { Box } from '@mui/material'
3
+ import { TagPropsType } from './fxtag_types'
4
+ import { titleCase } from '@fixefy/fixefy-ui-utils/'
5
+ import { StyledCount, StyledLabel, StyledTag } from './styles/tag.styles'
6
+
7
+ export const FxTag = ({ name, count = 0 }: TagPropsType) => (
8
+ <Box display="flex" alignItems="center" justifyContent="center" sx={{ maxWidth: 'fit-content', mb: 1 }}>
9
+ <StyledTag name={name}>
10
+ <StyledLabel>{titleCase(name)}</StyledLabel>
11
+ </StyledTag>
12
+ <StyledCount name={name}>{count}</StyledCount>
13
+ </Box>
14
+ )
@@ -0,0 +1,4 @@
1
+ export type TagPropsType = {
2
+ name: string;
3
+ count?: number;
4
+ };
@@ -0,0 +1,2 @@
1
+ export { FxTag } from "./FxTag";
2
+ export { TagPropsType } from "./fxtag_types";
@@ -0,0 +1,24 @@
1
+ import { styled } from '@mui/material/styles'
2
+ import { Box, Typography } from '@mui/material'
3
+ //
4
+ export const StyledTag = styled(Box)<{ name: string }>(({ theme, name }) => ({
5
+ background: name === 'in_dispute' ? '#56CCF2' : name === '' ? '#BB6BD9' : theme.palette.reconcilation[name].background,
6
+ borderRadius: 8,
7
+ padding: '2px 8px',
8
+ border: `1px solid ${name === 'in_dispute' ? '#56CCF2' : name === '' ? '#BB6BD9' : theme.palette.reconcilation[name].border}`,
9
+ display: 'flex',
10
+ alignItems: 'center',
11
+ width: 'fit-content',
12
+ }))
13
+ export const StyledLabel = styled(Typography)(({ theme }) => ({
14
+ ...theme.typography.body1,
15
+ lineHeight: '20px',
16
+ color: theme.palette.common.white,
17
+ }))
18
+ export const StyledCount = styled(Typography)<{ name: string }>(({ theme, name }) => ({
19
+ ...theme.typography.subtitle2,
20
+ lineHeight: '16px',
21
+ fontWeight: 700,
22
+ color: name === 'in_dispute' ? '#56CCF2' : name === '' ? '#BB6BD9' : theme.palette.reconcilation[name].background,
23
+ marginLeft: 8,
24
+ }))
@@ -0,0 +1,117 @@
1
+ import React, { useEffect, useState } from 'react'
2
+
3
+ import { titleCase } from '@fixefy/fixefy-ui-utils'
4
+ import { TextFieldPropsType } from './text_field_types'
5
+ import { FormControl, FormHelperText, InputBase, InputLabel } from '@mui/material'
6
+
7
+ import ErrorRoundedIcon from '@mui/icons-material/ErrorRounded'
8
+
9
+ export const FxTextField = ({
10
+ autoFocus,
11
+ droppedItem,
12
+ defaultValue = '',
13
+ onChange,
14
+ structure,
15
+ endAdornment,
16
+ startAdornment,
17
+ required,
18
+ helperText,
19
+ error = false,
20
+ errorText,
21
+ disabled,
22
+ }: TextFieldPropsType) => {
23
+ const [value, setValue] = useState(defaultValue)
24
+
25
+ const {
26
+ input_type,
27
+ extended: { placeholder, title_path },
28
+ title,
29
+ } = structure
30
+
31
+ useEffect(() => {
32
+ if (droppedItem) {
33
+ const { item } = droppedItem
34
+ setValue(item[title_path])
35
+ }
36
+ }, [droppedItem])
37
+
38
+ const _onChange = (e: any) => {
39
+ onChange && onChange(e)
40
+ setValue(e.target.value)
41
+ }
42
+
43
+ return (
44
+ <FormControl variant='standard' error={error}>
45
+ {title && (
46
+ <InputLabel
47
+ shrink
48
+ htmlFor={title}
49
+ sx={(theme) => ({
50
+ color: theme.palette.greyscale.light,
51
+ '&.Mui-focused': {
52
+ color: theme.palette.greyscale.light,
53
+ },
54
+ ...(disabled && { opacity: '0.3' }),
55
+ '&.Mui-error': { color: theme.palette.greyscale.light },
56
+ ...(required && {
57
+ '&:before': {
58
+ content: "'*'",
59
+ color: theme.palette.redscale.main,
60
+ display: 'inline-block',
61
+ marginRight: '5px',
62
+ },
63
+ }),
64
+ })}
65
+ >
66
+ {titleCase(title)}
67
+ </InputLabel>
68
+ )}
69
+ <InputBase
70
+ endAdornment={endAdornment}
71
+ startAdornment={startAdornment}
72
+ id={title}
73
+ autoFocus={autoFocus ? autoFocus : false}
74
+ placeholder={titleCase(placeholder)}
75
+ onChange={_onChange}
76
+ type={input_type && input_type.value}
77
+ value={value}
78
+ error={error}
79
+ />
80
+ {error && errorText ? (
81
+ <FormHelperText
82
+ sx={(theme) => ({
83
+ '&.Mui-error': {
84
+ color: theme.palette.redscale.main,
85
+ },
86
+ display: 'grid',
87
+ gridAutoFlow: 'column',
88
+ alignItems: 'center',
89
+ justifyContent: 'left',
90
+ columnGap: theme.spacing(0.6),
91
+ fontSize: '11px',
92
+ })}
93
+ >
94
+ <ErrorRoundedIcon
95
+ sx={(theme) => ({
96
+ color: theme.palette.redscale.main,
97
+ width: 10,
98
+ height: 10,
99
+ })}
100
+ />
101
+ {titleCase(errorText)}
102
+ </FormHelperText>
103
+ ) : (
104
+ <FormHelperText
105
+ sx={(theme) => ({
106
+ color: theme.palette.greyscale.light,
107
+ fontSize: '11px',
108
+ })}
109
+ >
110
+ {helperText}
111
+ </FormHelperText>
112
+ )}
113
+ </FormControl>
114
+ )
115
+ }
116
+
117
+ export default FxTextField
@@ -0,0 +1,2 @@
1
+ export { FxTextField } from './FxTextField'
2
+ export type { TextFieldPropsType } from './text_field_types'
@@ -0,0 +1,20 @@
1
+ import { ReactNode } from 'react'
2
+ import { InputBaseProps } from '@mui/material'
3
+
4
+ export interface TextFieldPropsType {
5
+ autoFocus?: boolean
6
+ droppedItem?: {
7
+ item: any
8
+ type: string
9
+ }
10
+ defaultValue?: string
11
+ onChange?: (e: any) => void
12
+ structure: any
13
+ helperText?: ReactNode
14
+ errorText?: string
15
+ endAdornment?: InputBaseProps['endAdornment']
16
+ startAdornment?: InputBaseProps['startAdornment']
17
+ required?: InputBaseProps['required']
18
+ disabled?: InputBaseProps['disabled']
19
+ error?: InputBaseProps['error']
20
+ }
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+ import Image from 'next/image'
3
+
4
+ import { FxAvatar } from '../FxAvatar'
5
+ import { Divider } from '@mui/material'
6
+ import { TodoPropsType } from './todo_types'
7
+ import { imageLoader, normalizeTimestamp, titleCase } from '@fixefy/fixefy-ui-utils'
8
+ import { TodoCard, TodoCardHeader, TodoCardContent, TodoCardPriority, TodoCardTag, TodoCardFooter, TodoCardFooterDueDate, TodoCardContentButton } from './styles/todo.styles'
9
+
10
+ export function FxTodo({ todo }: TodoPropsType) {
11
+ return (
12
+ <TodoCard>
13
+ <TodoCardHeader>
14
+ <TodoCardPriority priority={todo.priority}>
15
+ <Image
16
+ alt={todo.title}
17
+ width={16}
18
+ height={16}
19
+ loader={() =>
20
+ imageLoader({
21
+ root: 'https://cdn-dev.fixefy.me/',
22
+ src: 'invoices/severity_low.svg',
23
+ }) as any
24
+ }
25
+ src={`invoices/severity_${todo.priority}.svg`}
26
+ onLoad={() => console.log('loaded')}
27
+ onError={(e) => console.log('error:', e)}
28
+ />
29
+
30
+ {titleCase(todo.priority)}
31
+ </TodoCardPriority>
32
+ {todo.isNew && <TodoCardTag>New</TodoCardTag>}
33
+ </TodoCardHeader>
34
+ <TodoCardContent>
35
+ <p>{titleCase(todo.title)}</p>
36
+ <span>{titleCase(todo.description)}</span>
37
+ {todo.actionTitle && (
38
+ <TodoCardContentButton size="small" onClick={todo.action ? todo.action : () => {}}>
39
+ {todo.actionTitle}
40
+ </TodoCardContentButton>
41
+ )}
42
+ </TodoCardContent>
43
+ <Divider sx={{ mb: '16px' }} />
44
+ <TodoCardFooter>
45
+ <TodoCardFooterDueDate>
46
+ <span>Due Date</span>
47
+ <p>
48
+ {normalizeTimestamp(todo.created_date, {
49
+ dateOnly: true,
50
+ format: 'dd.mm.yyyy',
51
+ })}
52
+ </p>
53
+ </TodoCardFooterDueDate>
54
+ <FxAvatar max={4} isEditable={todo.isUserEditable} users={todo.users} />
55
+ </TodoCardFooter>
56
+ </TodoCard>
57
+ )
58
+ }
@@ -0,0 +1,2 @@
1
+ export { FxTodo } from './FxTodo'
2
+ export { PriorityPropsType, TodoPropsType } from './todo_types'
@@ -0,0 +1,113 @@
1
+ import { styled } from '@mui/material/styles'
2
+ import { FxButton } from '../../FxButton'
3
+ import { PriorityPropsType } from '../todo_types'
4
+
5
+ export const TodoCard = styled('div')(({ theme }) => ({
6
+ background: theme.palette.common.white,
7
+ borderRadius: 8,
8
+ padding: 16,
9
+ marginBottom: 4,
10
+ }))
11
+
12
+ // Card Header
13
+ export const TodoCardHeader = styled('div')(({}) => ({
14
+ display: 'flex',
15
+ alignItems: 'center',
16
+ justifyContent: 'space-between',
17
+ marginBottom: 16,
18
+ }))
19
+
20
+ export const TodoCardPriority = styled('div')<PriorityPropsType>(({ theme, priority }) => ({
21
+ display: 'flex',
22
+ alignItems: 'center',
23
+ justifyContent: 'center',
24
+
25
+ ...theme.typography.table,
26
+ color: theme.palette.priority[priority],
27
+
28
+ ['& img']: {
29
+ marginRight: 4,
30
+ },
31
+ }))
32
+
33
+ export const TodoCardTag = styled('div')(({ theme }) => ({
34
+ ...theme.typography.table,
35
+ color: theme.palette.common.white,
36
+ width: 42,
37
+ height: 18,
38
+ background: '#6FCF97',
39
+ borderRadius: 50,
40
+
41
+ display: 'flex',
42
+ alignItems: 'center',
43
+ justifyContent: 'center',
44
+ }))
45
+
46
+ // Card Content
47
+ export const TodoCardContent = styled('div')(({ theme }) => ({
48
+ display: 'flex',
49
+ alignItems: 'flex-start',
50
+ justifyContent: 'space-between',
51
+ flexDirection: 'column',
52
+ marginBottom: 16,
53
+
54
+ ['& p']: {
55
+ fontStyle: 'normal',
56
+ fontSize: 14,
57
+ letterSpacing: '0.15px',
58
+ color: theme.palette.typography.title,
59
+ fontWeight: 700,
60
+ lineHeight: '16px',
61
+ margin: 0,
62
+ },
63
+ ['& span']: {
64
+ fontStyle: 'normal',
65
+ fontSize: 14,
66
+ letterSpacing: '0.15px',
67
+ color: theme.palette.typography.title,
68
+ fontWeight: 400,
69
+ lineHeight: '20px',
70
+ marginBottom: 16,
71
+ },
72
+ }))
73
+
74
+ export const TodoCardContentButton = styled(FxButton)(({ theme }) => ({
75
+ ...theme.typography.button,
76
+ color: '#568793',
77
+ fontSize: 12,
78
+ maxHeight: 32,
79
+ minHeight: 32,
80
+ paddingLeft: 12,
81
+ paddingRight: 12,
82
+ }))
83
+
84
+ // Card Footer
85
+ export const TodoCardFooter = styled('div')(({}) => ({
86
+ display: 'flex',
87
+ alignItems: 'center',
88
+ justifyContent: 'space-between',
89
+ flexDirection: 'row',
90
+ }))
91
+
92
+ export const TodoCardFooterDueDate = styled('div')(({ theme }) => ({
93
+ display: 'flex',
94
+ alignItems: 'flex-start',
95
+ flexDirection: 'column',
96
+ ['& p']: {
97
+ fontWeight: 'normal',
98
+ fontStyle: 'normal',
99
+ fontSize: 11,
100
+ lineHeight: '16px',
101
+ letterSpacing: '0.1px',
102
+ color: theme.palette.typography.title,
103
+ margin: 0,
104
+ },
105
+ ['& span']: {
106
+ fontWeight: 'normal',
107
+ fontStyle: 'normal',
108
+ fontSize: 14,
109
+ lineHeight: '24px',
110
+ letterSpacing: '0.15px',
111
+ color: theme.palette.statistics.label,
112
+ },
113
+ }))
@@ -0,0 +1,19 @@
1
+ type TodoItemType = {
2
+ title: string;
3
+ description: string;
4
+ created_date: string;
5
+ users: any[];
6
+ isUserEditable?: boolean;
7
+ onUsersEdit?: () => void;
8
+ priority: "critical" | "high" | "low";
9
+ actionTitle?: string;
10
+ action?: () => void;
11
+ isNew?: boolean;
12
+ };
13
+ export type TodoPropsType = {
14
+ todo: TodoItemType;
15
+ };
16
+
17
+ export interface PriorityPropsType {
18
+ priority: "critical" | "high" | "low";
19
+ }