From e684451cf5deec997f9b66e0f0de66748f0a6e77 Mon Sep 17 00:00:00 2001 From: alaa-yahia <alaay873@live.com> Date: Sun, 2 Mar 2025 14:04:43 +0200 Subject: [PATCH 1/2] feat: update breakpoints --- .babelrc | 3 +- .eslintrc | 10 +- .../DataEntry/DataEntry.component.js | 2 +- .../ProgramSelector.component.js | 4 +- .../RegUnitSelector.component.js | 4 +- .../ProgramSelector.component.js | 4 +- .../RegUnitSelector.component.js | 4 +- .../DataEntry/DataEntry.component.js | 2 +- .../EditEventDataEntry.component.js | 4 +- .../ViewEventDataEntry.component.js | 2 +- src/styles/theme.js | 412 ++++++++++++++++++ 11 files changed, 436 insertions(+), 15 deletions(-) create mode 100644 src/styles/theme.js diff --git a/.babelrc b/.babelrc index 1f6b0c3c0b..289abc9e4f 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,6 @@ { "plugins": [ - "@babel/plugin-transform-flow-strip-types" + "@babel/plugin-transform-flow-strip-types", + ["styled-jsx/babel"] ] } diff --git a/.eslintrc b/.eslintrc index d19b2d5412..5bfa2180fa 100644 --- a/.eslintrc +++ b/.eslintrc @@ -128,7 +128,15 @@ ] } ], - "import/extensions": ["error", "never"] + "import/extensions": ["error", "never"], + "react/no-unknown-property": [ + 2, + { + "ignore": [ + "jsx" + ] + } + ] }, "settings": { "import/resolver": { diff --git a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.js b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.js index 6f967eaf72..e3ed4c1ca9 100644 --- a/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.js +++ b/src/core_modules/capture-core/components/DataEntries/SingleEventRegistrationEntry/DataEntryWrapper/DataEntry/DataEntry.component.js @@ -78,7 +78,7 @@ const getStyles = theme => ({ paddingBottom: theme.typography.pxToRem(15), }, fieldLabelMediaBased: { - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js index d8445f9570..51c703408f 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js @@ -4,10 +4,10 @@ import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; import { ComposedProgramSelector } from './ComposedProgramSelector.component'; -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ programLabel: { paddingTop: '10px', - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js index fc4f52cfa5..42a3f1083a 100644 --- a/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/NewRelationship/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js @@ -6,10 +6,10 @@ import { withStyles } from '@material-ui/core/styles'; import { ComposedRegUnitSelector } from './ComposedRegUnitSelector.component'; import { getProgramFromProgramIdThrowIfNotFound } from '../../../../../../metaData'; -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ label: { paddingTop: '10px', - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js index d8445f9570..51c703408f 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/ProgramSelector/ProgramSelector.component.js @@ -4,10 +4,10 @@ import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; import { ComposedProgramSelector } from './ComposedProgramSelector.component'; -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ programLabel: { paddingTop: '10px', - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js index 42cba9027f..3bea3ab743 100644 --- a/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/common/TEIRelationshipsWidget/RegisterTei/RegistrationSection/RegUnitSelector/RegUnitSelector.component.js @@ -6,10 +6,10 @@ import { withStyles } from '@material-ui/core/styles'; import { ComposedRegUnitSelector } from './ComposedRegUnitSelector.component'; import { getProgramFromProgramIdThrowIfNotFound } from '../../../../../../../metaData'; -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ label: { paddingTop: '10px', - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/DataEntry/DataEntry.component.js b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/DataEntry/DataEntry.component.js index 25265e2e42..dc50eb1b1c 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/DataEntry/DataEntry.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollmentEventNew/DataEntry/DataEntry.component.js @@ -73,7 +73,7 @@ const getStyles = theme => ({ paddingBottom: theme.typography.pxToRem(15), }, fieldLabelMediaBased: { - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.component.js b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.component.js index 1903a9ae5f..d0dec586c1 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.component.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/EditEventDataEntry/EditEventDataEntry.component.js @@ -57,11 +57,11 @@ const tabMode = Object.freeze({ SCHEDULE: 'SCHEDULE', }); -const getStyles = (theme: Theme) => ({ +const getStyles = () => ({ dataEntryContainer: { }, fieldLabelMediaBased: { - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/ViewEventDataEntry.component.js b/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/ViewEventDataEntry.component.js index ffdff870ac..f0e4faa2cc 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/ViewEventDataEntry.component.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/ViewEventDataEntry/ViewEventDataEntry.component.js @@ -62,7 +62,7 @@ const getStyles = (theme: Theme) => ({ whiteSpace: 'nowrap', }, fieldLabelMediaBased: { - [theme.breakpoints.down(523)]: { + '@media (max-width: 523px)': { paddingTop: '0px !important', }, }, diff --git a/src/styles/theme.js b/src/styles/theme.js new file mode 100644 index 0000000000..22c51d959d --- /dev/null +++ b/src/styles/theme.js @@ -0,0 +1,412 @@ +// @flow +import { theme as dhis2Theme, colors } from '@dhis2/ui'; + +const HTMLFONTSIZE = 16; + +export const theme = { + direction: 'ltr', + breakpoints: { + values: { + xs: 0, // phone + sm: 600, // tablet + md: 960, // small laptop + lg: 1280, // desktop + xl: 1920, // large screen + }, + }, + palette: { + type: 'light', + primary: { + main: '#1976D2', + dark: '#004BA0', + light: colors.blue600, + lightest: '#EAF4FF', + /* 50: dhis2Theme.primary050, + 100: dhis2Theme.primary100, + 200: dhis2Theme.primary200, + 300: dhis2Theme.primary300, + 400: dhis2Theme.primary400, + 500: dhis2Theme.primary500, + 600: dhis2Theme.primary600, + 700: dhis2Theme.primary700, + 800: dhis2Theme.primary800, + 900: dhis2Theme.primary900, */ + contrastText: '#fff', + }, + secondary: { + main: colors.teal600, + dark: '#004C40', + light: '#48A999', + lightest: colors.teal200, + /* 50: dhis2Theme.secondary050, + 100: dhis2Theme.secondary100, + 200: dhis2Theme.secondary200, + 300: dhis2Theme.secondary300, + 400: dhis2Theme.secondary400, + 500: dhis2Theme.secondary500, + 600: dhis2Theme.secondary600, + 700: dhis2Theme.secondary700, + 800: dhis2Theme.secondary800, + 900: dhis2Theme.secondary900, */ + contrastText: '#fff', + }, + success: { + main: '#3D9305', + green600: colors.green600, + }, + warning: { + lighter: '#FFF9C4', + light: '#FFF176', + main: '#F19C02', + dark: '#F57F17', + }, + error: { + lighter: '#FBEAE5', + light: colors.red300, + main: '#E53935', + dark: colors.red500, + contrastText: '#fff', + red200: colors.red200, + }, + red: { + /* 50: colors.red050, + 100: colors.red100, + 200: colors.red200, + 300: colors.red300, + 400: colors.red400, + 500: colors.red500, + 600: colors.red600, + 700: colors.red700, + 800: colors.red800, + 900: colors.red900, */ + }, + grey: { + /* 50: colors.grey050, + 100: colors.grey100, + 200: colors.grey200, + 300: colors.grey300, + 400: colors.grey400, + 500: colors.grey500, + 600: colors.grey600, + 700: colors.grey700, + 800: colors.grey800, + 900: colors.grey900, */ + A100: '#d5d5d5', + A200: '#aaaaaa', + A400: '#303030', + A700: '#616161', + main: '#9E9E9E', + light: '#E0E0E0', + lighter: '#F6F6F6', + lightest: '#FBFBFB', + dark: '#494949', + blueGrey: '#ECEFF1', + snow: '#F4F6F8', + black: '#000000', + }, + text: { + primary: 'rgba(0, 0, 0, 0.87)', + secondary: 'rgba(0, 0, 0, 0.54)', + disabled: 'rgba(0, 0, 0, 0.38)', + hint: 'rgba(0, 0, 0, 0.38)', + }, + contrastThreshold: 3, + tonalOffset: 0.2, + action: { + active: 'rgba(0, 0, 0, 0.54)', + hover: 'rgba(0, 0, 0, 0.08)', + hoverOpacity: 0.08, + selected: 'rgba(0, 0, 0, 0.14)', + disabled: 'rgba(0, 0, 0, 0.26)', + disabledBackground: 'rgba(0, 0, 0, 0.12)', + }, + info: { + main: '#EAF4FF', + }, + accent: { + lighter: colors.blue100, + light: '#BBDEFB', + main: '#64b5F6', + dark: colors.blue500, + contrastText: '#000000', + }, + input: { + bottomLine: 'rgba(0, 0, 0, 0.42)', + }, + divider: 'rgba(0, 0, 0, 0.12)', + dividerForm: '#f2f4f5', + dividerDarker: 'rgba(0, 0, 0, 1)', + dividerLighter: 'rgba(224, 224, 224, 1)', + default: dhis2Theme.default, + disabled: dhis2Theme.disabled, + required: colors.red400, + focus: dhis2Theme.focus, + }, + typography: { + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontSize: 14, + fontWeightLight: 300, + fontWeightRegular: 400, + fontWeightMedium: 500, + pxToRem(size: number) { + const coef = this.fontSize / 14; + return `${(size / HTMLFONTSIZE) * coef}rem`; + }, + display4: { + fontSize: '7rem', + fontWeight: 300, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + letterSpacing: '-.04em', + lineHeight: '1.14286em', + marginLeft: '-.04em', + color: 'rgba(0, 0, 0, 0.54)', + }, + display3: { + fontSize: '3.5rem', + fontWeight: 400, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + letterSpacing: '-.02em', + lineHeight: '1.30357em', + marginLeft: '-.02em', + color: 'rgba(0, 0, 0, 0.54)', + }, + display2: { + fontSize: '2.8125rem', + fontWeight: 400, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + lineHeight: '1.13333em', + marginLeft: '-.02em', + color: 'rgba(0, 0, 0, 0.54)', + }, + display1: { + fontSize: '2.125rem', + fontWeight: 400, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + lineHeight: '1.20588em', + color: 'rgba(0, 0, 0, 0.54)', + }, + headline: { + fontSize: '1.5rem', + fontWeight: 400, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + lineHeight: '1.35417em', + color: 'rgba(0, 0, 0, 0.87)', + }, + title: { + fontSize: '1.3125rem', + fontWeight: 500, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + lineHeight: '1.16667em', + color: 'rgba(0, 0, 0, 0.87)', + }, + subheading: { + fontSize: '1rem', + fontWeight: 400, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + lineHeight: '1.5em', + color: 'rgba(0, 0, 0, 0.87)', + }, + body2: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '0.875rem', + lineHeight: 1.5, + letterSpacing: '0.01071em', + }, + body1: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '1rem', + lineHeight: 1.5, + letterSpacing: '0.00938em', + }, + caption: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '0.75rem', + lineHeight: 1.66, + letterSpacing: '0.03333em', + }, + button: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '0.875rem', + lineHeight: 1.75, + letterSpacing: '0.02857em', + textTransform: 'uppercase', + }, + h1: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 300, + fontSize: '6rem', + lineHeight: 1, + letterSpacing: '-0.01562em', + }, + h2: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 300, + fontSize: '3.75rem', + lineHeight: 1, + letterSpacing: '-0.00833em', + }, + h3: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '3rem', + lineHeight: 1.04, + letterSpacing: '0em', + }, + h4: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '2.125rem', + lineHeight: 1.17, + letterSpacing: '0.00735em', + }, + h5: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '1.5rem', + lineHeight: 1.33, + letterSpacing: '0em', + }, + h6: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '1.25rem', + lineHeight: 1.6, + letterSpacing: '0.0075em', + }, + subtitle1: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '1rem', + lineHeight: 1.75, + letterSpacing: '0.00938em', + }, + subtitle2: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '0.875rem', + lineHeight: 1.57, + letterSpacing: '0.00714em', + }, + body1Next: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '1rem', + lineHeight: 1.5, + letterSpacing: '0.00938em', + }, + body2Next: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '0.875rem', + lineHeight: 1.5, + letterSpacing: '0.01071em', + }, + buttonNext: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '0.875rem', + lineHeight: 1.75, + letterSpacing: '0.02857em', + textTransform: 'uppercase', + }, + captionNext: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '0.75rem', + lineHeight: 1.66, + letterSpacing: '0.03333em', + }, + overline: { + color: 'rgba(0, 0, 0, 0.87)', + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 400, + fontSize: '0.75rem', + lineHeight: 2.66, + letterSpacing: '0.08333em', + textTransform: 'uppercase', + }, + useNextVariants: true, + formFieldTitle: { + fontSize: '0.75rem', + }, + }, + mixins: { + toolbar: { + minHeight: 56, + '@media (min-width:0px) and (orientation: landscape)': { + minHeight: 48, + }, + '@media (min-width:600px)': { + minHeight: 64, + }, + }, + }, + overrides: { + MuiDialog: { + paperWidthLg: { + width: 800, + }, + }, + MuiSvgIcon: { + colorAction: { + color: '#494949', + }, + }, + MuiCircularProgress: { + colorPrimary: { + color: '#147cd7', + }, + }, + }, + shape: { + borderRadius: 4, + }, + spacing: { + unit: 8, + }, + transitions: { + easing: { + easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)', + easeOut: 'cubic-bezier(0.0, 0, 0.2, 1)', + easeIn: 'cubic-bezier(0.4, 0, 1, 1)', + sharp: 'cubic-bezier(0.4, 0, 0.6, 1)', + }, + duration: { + shortest: 150, + shorter: 200, + short: 250, + standard: 300, + complex: 375, + enteringScreen: 225, + leavingScreen: 195, + }, + }, + zIndex: { + mobileStepper: 1000, + appBar: 1100, + drawer: 1200, + modal: 1300, + snackbar: 1400, + tooltip: 1500, + }, +}; From b20937f1a42d30eaee87c96355e2135881e1c412 Mon Sep 17 00:00:00 2001 From: alaa-yahia <alaay873@live.com> Date: Sun, 2 Mar 2025 16:56:13 +0200 Subject: [PATCH 2/2] feat: replace material ui with styled-jsx and a theme file --- .../BorderBox/BorderBox.component.js | 29 ++-- .../EnrollmentBreadcrumb.js | 26 ++-- .../Breadcrumbs/common/BreadcrumbItem.js | 56 ++++---- .../CardList/CardListButtons.component.js | 61 +++++--- .../PolygonCoordinates/PolygonCoordinates.js | 68 ++++----- .../EnrollmentAddEventPage.container.js | 23 ++- .../EnrollmentAddEventPage.types.js | 5 - ...EnrollmentAddEventPageDefault.component.js | 72 +++++----- .../EnrollmentAddEventPageDefault.types.js | 1 - .../NewEventWorkspace.component.js | 27 ++-- .../WidgetStageHeader.component.js | 39 +++-- .../widgetStageHeader.types.js | 1 - .../newEventWorkspace.types.js | 1 - .../ProgramStageSelector.component.js | 65 +++++---- .../components/Pages/New/NewPage.component.js | 17 +-- .../Sticky/StickyOnScroll.component.js | 55 +++---- .../Actions/Actions.component.js | 37 +++-- .../WidgetEnrollment/Actions/actions.types.js | 1 - .../WidgetEnrollment/Date/Date.component.js | 123 ++++++++-------- .../MiniMap/MiniMap.component.js | 32 ++--- .../WidgetEnrollment/MiniMap/MiniMap.types.js | 1 - .../Status/Status.component.js | 23 ++- .../WidgetEnrollment/Status/status.types.js | 1 - .../WidgetEnrollment.component.js | 79 ++++++----- .../WidgetEnrollment/enrollment.types.js | 1 - .../WidgetNote/NoteSection/NoteSection.js | 134 +++++++++--------- .../WidgetProfile/WidgetProfile.component.js | 47 +++--- .../BulkActionBar/BulkActionBar.component.js | 38 +++-- .../BulkActionBar/BulkActionBar.types.js | 1 - .../NewTemplateContents.component.js | 61 ++++---- 30 files changed, 548 insertions(+), 577 deletions(-) delete mode 100644 src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.types.js diff --git a/src/core_modules/capture-core/components/BorderBox/BorderBox.component.js b/src/core_modules/capture-core/components/BorderBox/BorderBox.component.js index 9794f74981..6e46efd8b2 100644 --- a/src/core_modules/capture-core/components/BorderBox/BorderBox.component.js +++ b/src/core_modules/capture-core/components/BorderBox/BorderBox.component.js @@ -1,33 +1,28 @@ // @flow import * as React from 'react'; -import { withStyles } from '@material-ui/core/styles'; +import { theme } from '../../../../styles/theme'; type Props = { - classes: { - borderBox: string, - }, contentClassName?: ?string, children: React.Node, }; -const styles = (theme: Theme) => ({ - borderBox: { - borderRadius: theme.typography.pxToRem(6), - borderWidth: theme.typography.pxToRem(2), - borderColor: '#e0e0e0', - borderStyle: 'solid', - }, -}); - -const BorderBoxPlain = (props: Props) => { - const { classes, children, contentClassName } = props; +export const BorderBox = (props: Props) => { + const { children, contentClassName } = props; return ( - <div className={classes.borderBox}> + <div className="borderBox"> <div className={contentClassName}> {children} </div> + <style jsx>{` + .borderBox { + border-radius: ${theme.typography.pxToRem(6)}; + border-width: ${theme.typography.pxToRem(2)}; + border-color: #e0e0e0; + border-style: solid; + } + `}</style> </div> ); }; -export const BorderBox = withStyles(styles)(BorderBoxPlain); diff --git a/src/core_modules/capture-core/components/Breadcrumbs/EnrollmentBreadcrumb/EnrollmentBreadcrumb.js b/src/core_modules/capture-core/components/Breadcrumbs/EnrollmentBreadcrumb/EnrollmentBreadcrumb.js index faee011bd6..7af1c58bbc 100644 --- a/src/core_modules/capture-core/components/Breadcrumbs/EnrollmentBreadcrumb/EnrollmentBreadcrumb.js +++ b/src/core_modules/capture-core/components/Breadcrumbs/EnrollmentBreadcrumb/EnrollmentBreadcrumb.js @@ -1,8 +1,6 @@ // @flow -import type { ComponentType } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core/styles'; import { colors, IconChevronRight16 } from '@dhis2/ui'; import { useWorkingListLabel } from './hooks/useWorkingListLabel'; import { BreadcrumbItem } from '../common/BreadcrumbItem'; @@ -20,6 +18,8 @@ type Props = { programId: string, userInteractionInProgress?: boolean, trackedEntityName?: string, + eventStatus?: string, + page?: string, }; export const EventStatuses = { @@ -30,13 +30,6 @@ export const EventStatuses = { OVERDUE: 'OVERDUE', }; -const styles = { - container: { - display: 'flex', - alignItems: 'center', - }, -}; - const pageKeys = Object.freeze({ MAIN_PAGE: 'mainPage', ...EnrollmentPageKeys, @@ -45,7 +38,7 @@ const pageKeys = Object.freeze({ const eventIsScheduled = eventStatus => [EventStatuses.SCHEDULE, EventStatuses.OVERDUE, EventStatuses.SKIPPED] .includes(eventStatus); -const BreadcrumbsPlain = ({ +export const EnrollmentBreadcrumb = ({ onBackToMainPage, onBackToDashboard, onBackToViewEvent, @@ -55,8 +48,7 @@ const BreadcrumbsPlain = ({ displayFrontPageList, userInteractionInProgress = false, page, - classes, -}) => { +}: Props) => { const [openWarning, setOpenWarning] = useState(null); const { label } = useWorkingListLabel({ @@ -121,7 +113,7 @@ const BreadcrumbsPlain = ({ ]); return ( - <div className={classes.container}> + <div className="container"> {breadcrumbItems.map((button, index) => ( <React.Fragment key={button.key}> <BreadcrumbItem @@ -165,8 +157,14 @@ const BreadcrumbsPlain = ({ onCancel={() => setOpenWarning(null)} {...defaultDialogProps} /> + + <style jsx>{` + .container { + display: flex; + align-items: center; + } + `}</style> </div> ); }; -export const EnrollmentBreadcrumb: ComponentType<$Diff<Props, CssClasses>> = withStyles(styles)(BreadcrumbsPlain); diff --git a/src/core_modules/capture-core/components/Breadcrumbs/common/BreadcrumbItem.js b/src/core_modules/capture-core/components/Breadcrumbs/common/BreadcrumbItem.js index 9e553b556d..3ac6761c66 100644 --- a/src/core_modules/capture-core/components/Breadcrumbs/common/BreadcrumbItem.js +++ b/src/core_modules/capture-core/components/Breadcrumbs/common/BreadcrumbItem.js @@ -1,7 +1,6 @@ // @flow -import React, { type ComponentType } from 'react'; +import React from 'react'; import cx from 'classnames'; -import { withStyles } from '@material-ui/core/styles'; import { colors } from '@dhis2/ui'; type Props = { @@ -11,39 +10,38 @@ type Props = { dataTest: string, }; -const styles = { - button: { - // Reset button styles - background: 'none', - border: 'none', - cursor: 'pointer', - font: 'inherit', - - // Custom button styles - fontSize: '14px', - padding: '6px 4px', - color: colors.grey800, - borderRadius: '3px', - - '&:hover': { - textDecoration: 'underline', - color: 'black', - }, - '&.selected': { - color: 'black', - }, - }, -}; - -const BreadcrumbItemPlain = ({ label, onClick, selected, dataTest, classes }) => ( +export const BreadcrumbItem = ({ label, onClick, selected, dataTest }: Props) => ( <button type="button" - className={cx(classes.button, { selected })} + className={cx('button', { selected })} onClick={onClick} data-test={dataTest} > {label} + <style jsx>{` + .button { + /* Reset button styles */ + background: none; + border: none; + cursor: pointer; + font: inherit; + + /* Custom button styles */ + font-size: 14px; + padding: 6px 4px; + color: ${colors.grey800}; + border-radius: 3px; + } + + .button:hover { + text-decoration: underline; + color: black; + } + + .button.selected { + color: black; + } + `}</style> </button> ); -export const BreadcrumbItem: ComponentType<$Diff<Props, CssClasses>> = withStyles(styles)(BreadcrumbItemPlain); diff --git a/src/core_modules/capture-core/components/CardList/CardListButtons.component.js b/src/core_modules/capture-core/components/CardList/CardListButtons.component.js index ca1fc06ea1..a0071f8928 100644 --- a/src/core_modules/capture-core/components/CardList/CardListButtons.component.js +++ b/src/core_modules/capture-core/components/CardList/CardListButtons.component.js @@ -1,6 +1,5 @@ // @flow import React from 'react'; -import { withStyles } from '@material-ui/core'; import i18n from '@dhis2/d2-i18n'; import { Button } from '@dhis2/ui'; import { useDispatch } from 'react-redux'; @@ -9,6 +8,7 @@ import { availableCardListButtonState, enrollmentTypes } from './CardList.consta import { navigateToEnrollmentOverview, } from '../../actions/navigateToEnrollmentOverview/navigateToEnrollmentOverview.actions'; +import { theme } from '../../../../styles/theme'; type Props = { currentSearchScopeId?: string, @@ -19,14 +19,6 @@ type Props = { programName?: string, } -const buttonStyles = (theme: Theme) => ({ - buttonMargin: { - '&:not(:first-child)': { - marginLeft: theme.typography.pxToRem(8), - }, - }, -}); - const deriveNavigationButtonState = (type): $Keys<typeof availableCardListButtonState> => { switch (type) { case enrollmentTypes.ACTIVE: @@ -39,20 +31,44 @@ const deriveNavigationButtonState = (type): $Keys<typeof availableCardListButton } }; -const ActionButtons = withStyles(buttonStyles)(({ buttonProps, classes }) => ( - <>{buttonProps.map(props => ( - !props.hide && <Button - small - className={classes.buttonMargin} - dataTest={props.dataTest} - onClick={props.onClick} - > - {props.label} - </Button> - ))}</> -)); -const CardListButtons = ({ +const ActionButton = ({ dataTest, onClick, label, hide }) => { + if (hide) return null; + + return ( + <> + <Button + small + className="buttonMargin" + dataTest={dataTest} + onClick={onClick} + > + {label} + </Button> + <style jsx>{` + :global(.button-margin:not(:first-child)) { + margin-left: ${theme.typography.pxToRem(8)}; + } + `}</style> + </> + ); +}; + +const ActionButtons = ({ buttonProps }: { buttonProps: Array<Object>}) => ( + <> + {buttonProps.map((props, index) => ( + <ActionButton + key={props.dataTest || index} + dataTest={props.dataTest} + onClick={props.onClick} + label={props.label} + hide={props.hide} + /> + ))} + </> +); + +export const CardListButtons = ({ currentSearchScopeId, currentSearchScopeType, id, @@ -108,4 +124,3 @@ const CardListButtons = ({ return <ActionButtons buttonProps={buttonLists} />; }; -export { CardListButtons }; diff --git a/src/core_modules/capture-core/components/Coordinates/PolygonCoordinates/PolygonCoordinates.js b/src/core_modules/capture-core/components/Coordinates/PolygonCoordinates/PolygonCoordinates.js index c019bdb5fe..a85436f4a3 100644 --- a/src/core_modules/capture-core/components/Coordinates/PolygonCoordinates/PolygonCoordinates.js +++ b/src/core_modules/capture-core/components/Coordinates/PolygonCoordinates/PolygonCoordinates.js @@ -1,59 +1,59 @@ // @flow import React, { useState } from 'react'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core/styles'; import { IconChevronUp16, IconChevronDown16, colors, spacers } from '@dhis2/ui'; type Props = $ReadOnly<{| coordinates: Array<Array<number>>, - classes: { - buttonContainer: string, - viewButton: string, - }, |}>; -const styles = { - buttonContainer: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - }, - viewButton: { - background: 'none', - border: 'none', - cursor: 'pointer', - color: colors.grey800, - marginTop: spacers.dp8, - display: 'flex', - alignItems: 'center', - '&:hover': { - textDecoration: 'underline', - color: 'black', - }, - }, -}; - -const PolygonCoordinatesPlain = ({ coordinates, classes }: Props) => { +export const PolygonCoordinates = ({ coordinates }: Props) => { const [showMore, setShowMore] = useState(false); return ( - <> - <div> + <div className="polygon-coordinates"> + <div className="coordinates-list"> {coordinates.slice(0, showMore ? coordinates.length : 1).map((coordinatePair, index) => ( // eslint-disable-next-line react/no-array-index-key - <div key={index}> + <div key={index} className="coordinate-pair"> {`${i18n.t('lat')}: ${coordinatePair[1]}`}<br /> {`${i18n.t('long')}: ${coordinatePair[0]}`} </div> ))} </div> - <div className={classes.buttonContainer}> - <button className={classes.viewButton} onClick={() => setShowMore(!showMore)}> + <div className="button-container"> + <button className="view-button" onClick={() => setShowMore(!showMore)}> {showMore ? i18n.t('Show less') : i18n.t('Show more')} {showMore ? <IconChevronUp16 /> : <IconChevronDown16 />} </button> </div> - </> + + <style jsx>{` + .coordinates-list { + margin-bottom: ${spacers.dp4}px; + } + .coordinate-pair { + margin-bottom: ${spacers.dp4}px; + } + .button-container { + display: flex; + flex-direction: column; + align-items: center; + } + .view-button { + background: none; + border: none; + cursor: pointer; + color: ${colors.grey800}; + margin-top: ${spacers.dp8}px; + display: flex; + align-items: center; + } + .view-button:hover { + text-decoration: underline; + color: black; + } + `}</style> + </div> ); }; -export const PolygonCoordinates = withStyles(styles)(PolygonCoordinatesPlain); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.container.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.container.js index aa0ef61d87..e3051dd37f 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.container.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.container.js @@ -2,7 +2,6 @@ import React, { useMemo, useEffect } from 'react'; import i18n from '@dhis2/d2-i18n'; import { NoticeBox, spacersNum } from '@dhis2/ui'; -import withStyles from '@material-ui/core/styles/withStyles'; import { EnrollmentAddEventPageDefault } from './EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.container'; import { useNavigate, useLocationQuery, buildUrlQueryString } from '../../../utils/routing'; import { @@ -12,21 +11,14 @@ import { import { useCommonEnrollmentDomainData } from '../common/EnrollmentOverviewDomain'; import { EnrollmentAddEventPageStatuses } from './EnrollmentAddEventPage.constants'; import { LoadingMaskForPage } from '../../LoadingMasks'; -import { type Props } from './EnrollmentAddEventPage.types'; import { useEnrollmentPageLayout, } from '../common/EnrollmentOverviewDomain/EnrollmentPageLayout/hooks/useEnrollmentPageLayout'; import { DataStoreKeyByPage } from '../common/EnrollmentOverviewDomain/EnrollmentPageLayout'; import { DefaultPageLayout } from './PageLayout/DefaultPageLayout.constants'; -const styles = { - informativeMessage: { - marginLeft: spacersNum.dp16, - marginTop: spacersNum.dp24, - marginRight: spacersNum.dp16, - }, -}; -const EnrollmentAddEventPagePlain = ({ classes }: Props) => { +/* eslint-disable complexity */ +export const EnrollmentAddEventPage = () => { const { navigate } = useNavigate(); const { teiId, programId, orgUnitId, enrollmentId } = useLocationQuery(); const { valid: validIds, loading, error: validatedIdsError } = useValidatedIDsFromCache({ programId, orgUnitId }); @@ -87,7 +79,7 @@ const EnrollmentAddEventPagePlain = ({ classes }: Props) => { } return ( - <div className={classes.informativeMessage}> + <div className="informative-message"> <NoticeBox error title={'An error has occurred'} @@ -104,8 +96,15 @@ const EnrollmentAddEventPagePlain = ({ classes }: Props) => { i18n.t('There was an error opening the Page') )} </NoticeBox> + + <style jsx>{` + .informative-message { + margin-left: ${spacersNum.dp16}px; + margin-top: ${spacersNum.dp24}px; + margin-right: ${spacersNum.dp16}px; + } + `}</style> </div> ); }; -export const EnrollmentAddEventPage = withStyles(styles)(EnrollmentAddEventPagePlain); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.types.js deleted file mode 100644 index 1cfd6132f2..0000000000 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPage.types.js +++ /dev/null @@ -1,5 +0,0 @@ -// @flow - -export type Props = { - ...CssClasses, -} diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.component.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.component.js index 1e3b7b907a..e6dfa2fe54 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.component.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.component.js @@ -1,42 +1,15 @@ // @flow -import React, { type ComponentType } from 'react'; +import React from 'react'; import i18n from '@dhis2/d2-i18n'; import { spacersNum } from '@dhis2/ui'; -import withStyles from '@material-ui/core/styles/withStyles'; +import { theme } from '../../../../../../styles/theme'; import type { Props } from './EnrollmentAddEventPageDefault.types'; import { EnrollmentPageLayout } from '../../common/EnrollmentOverviewDomain/EnrollmentPageLayout'; import { EnrollmentPageKeys, } from '../../common/EnrollmentOverviewDomain/EnrollmentPageLayout/DefaultEnrollmentLayout.constants'; -const styles = ({ typography }) => ({ - container: { - padding: '16px 24px 16px 24px', - }, - columns: { - display: 'flex', - }, - leftColumn: { - flexGrow: 3, - flexShrink: 1, - width: 872, - }, - rightColumn: { - flexGrow: 1, - flexShrink: 1, - paddingLeft: spacersNum.dp16, - width: 360, - display: 'flex', - flexDirection: 'column', - gap: '12px', - }, - title: { - ...typography.title, - margin: `${spacersNum.dp16}px 0`, - }, -}); - -const EnrollmentAddEventPagePain = ({ +export const EnrollmentAddEventPageDefaultComponent = ({ pageLayout, availableWidgets, program, @@ -53,7 +26,6 @@ const EnrollmentAddEventPagePain = ({ pageFailure, ready, onAccessLostFromTransfer, - classes, ...passOnProps }: Props) => { if (pageFailure) { @@ -68,7 +40,7 @@ const EnrollmentAddEventPagePain = ({ return null; } return ( - <div> + <div className="container"> <EnrollmentPageLayout {...passOnProps} currentPage={EnrollmentPageKeys.NEW_EVENT} @@ -89,9 +61,41 @@ const EnrollmentAddEventPagePain = ({ feedbackEmptyText={i18n.t('No feedback for this event yet')} indicatorEmptyText={i18n.t('No indicator output for this event yet')} /> + + <style jsx>{` + .container { + padding: 16px 24px 16px 24px; + } + + .columns { + display: flex; + } + + .left-column { + flex-grow: 3; + flex-shrink: 1; + width: 872px; + } + + .right-column { + flex-grow: 1; + flex-shrink: 1; + padding-left: ${spacersNum.dp16}px; + width: 360px; + display: flex; + flex-direction: column; + gap: 12px; + } + + .title { + font-size: ${theme.typography.title.fontSize}; + font-weight: ${theme.typography.title.fontWeight}; + line-height: ${theme.typography.title.lineHeight}; + color: ${theme.typography.title.color}; + margin: ${spacersNum.dp16}px 0; + } + `}</style> </div> ); }; -export const EnrollmentAddEventPageDefaultComponent: ComponentType<$Diff<Props, CssClasses>> = - withStyles(styles)(EnrollmentAddEventPagePain); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js index 99fe0e57e3..bb4f95365a 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.types.js @@ -38,7 +38,6 @@ export type Props = {| pageLayout: PageLayoutConfig, availableWidgets: $ReadOnly<{ [key: string]: WidgetConfig }>, onDeleteTrackedEntitySuccess: () => void, - ...CssClasses, |}; export type ContainerProps = {| diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/NewEventWorkspace.component.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/NewEventWorkspace.component.js index 36dc29f928..8f4a502962 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/NewEventWorkspace.component.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/NewEventWorkspace.component.js @@ -1,9 +1,8 @@ // @flow -import React, { type ComponentType, useState, useRef, useMemo } from 'react'; +import React, { useState, useRef, useMemo } from 'react'; import { TabBar, Tab, spacersNum } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import { useSelector } from 'react-redux'; -import withStyles from '@material-ui/core/styles/withStyles'; import { tabMode } from './newEventWorkspace.constants'; import { getProgramAndStageForProgram } from '../../../../metaData'; import { WidgetEnrollmentEventNew } from '../../../WidgetEnrollmentEventNew'; @@ -12,17 +11,11 @@ import { Widget } from '../../../Widget'; import { WidgetStageHeader } from './WidgetStageHeader'; import { WidgetEventSchedule } from '../../../WidgetEventSchedule'; import { addEnrollmentEventPageDefaultActionTypes } from '../EnrollmentAddEventPageDefault/EnrollmentAddEventPageDefault.actions'; -import type { PlainProps, Props } from './newEventWorkspace.types'; +import type { Props } from './newEventWorkspace.types'; import { useLocationQuery } from '../../../../utils/routing'; import { defaultDialogProps } from '../../../Dialogs/DiscardDialog.constants'; -const styles = () => ({ - innerWrapper: { - padding: `0 ${spacersNum.dp16}px`, - }, -}); - -const NewEventWorkspacePlain = ({ +export const NewEventWorkspace = ({ stageId, programId, orgUnitId, @@ -31,9 +24,8 @@ const NewEventWorkspacePlain = ({ dataEntryHasChanges, onCancel, onSave, - classes, ...passOnProps -}: PlainProps) => { +}: Props) => { const { tab } = useLocationQuery(); const { events, enrolledAt, occurredAt } = useSelector(({ enrollmentDomain }) => enrollmentDomain?.enrollment); const [mode, setMode] = useState(tab ?? tabMode.REPORT); @@ -58,7 +50,7 @@ const NewEventWorkspacePlain = ({ <WidgetStageHeader stage={stage} /> } > - <div data-test={'add-event-enrollment-page-content'} className={classes.innerWrapper}> + <div data-test={'add-event-enrollment-page-content'} className="inner-wrapper"> <TabBar dataTest="new-event-tab-bar"> <Tab key="report-tab" @@ -114,6 +106,11 @@ const NewEventWorkspacePlain = ({ enableUserAssignment />} </div> + <style jsx>{` + .inner-wrapper { + padding: 0 ${spacersNum.dp16}px; + } + `}</style> </Widget> <DiscardDialog {...defaultDialogProps} @@ -124,7 +121,3 @@ const NewEventWorkspacePlain = ({ </> ); }; - -export const NewEventWorkspace: ComponentType< - Props, -> = withStyles(styles)(NewEventWorkspacePlain); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/WidgetStageHeader.component.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/WidgetStageHeader.component.js index ed3d91c05c..162323b2d9 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/WidgetStageHeader.component.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/WidgetStageHeader.component.js @@ -1,31 +1,15 @@ // @flow -import React, { type ComponentType } from 'react'; +import React from 'react'; import { spacersNum } from '@dhis2/ui'; -import withStyles from '@material-ui/core/styles/withStyles'; import { NonBundledDhis2Icon } from '../../../../NonBundledDhis2Icon'; import type { Props } from './widgetStageHeader.types'; -const styles = () => ({ - wrapper: { - paddingLeft: spacersNum.dp16, - }, - header: { - display: 'flex', - alignItems: 'center', - padding: spacersNum.dp8, - }, - icon: { - paddingRight: spacersNum.dp8, - }, -}); - -const WidgetStageHeaderPlain = ({ +export const WidgetStageHeader = ({ stage, - classes, }: Props) => ( - <div className={classes.header}> + <div className="header"> {stage?.icon && ( - <div className={classes.icon}> + <div className="icon"> <NonBundledDhis2Icon name={stage?.icon?.name} color={stage?.icon?.color} @@ -36,9 +20,18 @@ const WidgetStageHeaderPlain = ({ </div> )} <span>{stage?.name}</span> + + <style jsx>{` + .header { + display: flex; + align-items: center; + padding: ${spacersNum.dp8}px; + } + + .icon { + padding-right: ${spacersNum.dp8}px; + } + `}</style> </div> ); -export const WidgetStageHeader: ComponentType< - $Diff<Props, CssClasses>, -> = withStyles(styles)(WidgetStageHeaderPlain); diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/widgetStageHeader.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/widgetStageHeader.types.js index 8b7705bdeb..ee1f9571bb 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/widgetStageHeader.types.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/WidgetStageHeader/widgetStageHeader.types.js @@ -2,5 +2,4 @@ export type Props = {| stage: Object, - ...CssClasses |}; diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/newEventWorkspace.types.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/newEventWorkspace.types.js index 0621fb2b54..d3df19de20 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/newEventWorkspace.types.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/NewEventWorkspace/newEventWorkspace.types.js @@ -16,5 +16,4 @@ export type Props = {| export type PlainProps = {| ...Props, - ...CssClasses |}; diff --git a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/ProgramStageSelector/ProgramStageSelector.component.js b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/ProgramStageSelector/ProgramStageSelector.component.js index 1ab8895d04..d3f5c65ddf 100644 --- a/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/ProgramStageSelector/ProgramStageSelector.component.js +++ b/src/core_modules/capture-core/components/Pages/EnrollmentAddEvent/ProgramStageSelector/ProgramStageSelector.component.js @@ -3,28 +3,28 @@ import React from 'react'; import i18n from '@dhis2/d2-i18n'; import { Button, spacers, spacersNum } from '@dhis2/ui'; import { ConditionalTooltip } from 'capture-core/components/Tooltips/ConditionalTooltip'; -import { withStyles } from '@material-ui/core'; import { NonBundledDhis2Icon } from '../../../NonBundledDhis2Icon'; -const styles = { - container: { - display: 'flex', - flexDirection: 'column', - gap: spacers.dp8, - padding: spacers.dp16, - paddingTop: 0, - }, - button: { - alignSelf: 'start', - }, - cancelbutton: { - alignSelf: 'start', - marginTop: spacersNum.dp16, - }, -}; -const ProgramStageSelectorComponentPlain = ({ programStages, onSelectProgramStage, onCancel, classes }) => ( - <div className={classes.container}> +type Props = { + programStages: Array<{ + id: string, + displayName: string, + dataAccess: { write: boolean }, + repeatable: boolean, + eventCount: number, + hiddenProgramStage: boolean, + style?: { + icon?: string, + color?: string + } + }>, + onSelectProgramStage: (id: string) => void, + onCancel: () => void + }; + +export const ProgramStageSelectorComponent = ({ programStages, onSelectProgramStage, onCancel }: Props) => ( + <div className="container"> {programStages.map((programStage) => { const disableStage = !programStage.dataAccess.write || (!programStage.repeatable && programStage.eventCount > 0) || programStage.hiddenProgramStage; @@ -40,14 +40,14 @@ const ProgramStageSelectorComponentPlain = ({ programStages, onSelectProgramStag enabled={disableStage} > <Button - className={classes.button} + className="button" secondary disabled={disableStage} onClick={() => onSelectProgramStage(programStage.id)} dataTest={'program-stage-selector-button'} icon={ programStage.style?.icon && ( - <div className={classes.icon}> + <div className="icon"> <NonBundledDhis2Icon name={programStage.style?.icon} color={programStage.style?.color} @@ -66,14 +66,31 @@ const ProgramStageSelectorComponentPlain = ({ programStages, onSelectProgramStag ); })} <Button - className={classes.cancelbutton} + className="cancel-button" secondary big onClick={onCancel} > {i18n.t('Cancel without saving')} </Button> + + <style jsx>{` + .container { + display: flex; + flex-direction: column; + gap: ${spacers.dp8}; + padding: ${spacers.dp16}; + padding-top: 0; + } + + .button { + align-self: start; + } + + .cancel-button { + align-self: start; + margin-top: ${spacersNum.dp16}px; + } + `}</style> </div> ); - -export const ProgramStageSelectorComponent = withStyles(styles)(ProgramStageSelectorComponentPlain); diff --git a/src/core_modules/capture-core/components/Pages/New/NewPage.component.js b/src/core_modules/capture-core/components/Pages/New/NewPage.component.js index 35939b44f6..324f02c957 100644 --- a/src/core_modules/capture-core/components/Pages/New/NewPage.component.js +++ b/src/core_modules/capture-core/components/Pages/New/NewPage.component.js @@ -3,7 +3,6 @@ import React, { useEffect, useState } from 'react'; import { compose } from 'redux'; import { useSelector } from 'react-redux'; import type { ComponentType } from 'react'; -import withStyles from '@material-ui/core/styles/withStyles'; import { OrgUnitFetcher } from 'capture-core/components/OrgUnitFetcher'; import i18n from '@dhis2/d2-i18n'; import { Button } from '@dhis2/ui'; @@ -16,19 +15,12 @@ import { RegistrationDataEntry } from './RegistrationDataEntry'; import { NoWriteAccessMessage } from '../../NoWriteAccessMessage'; import { IncompleteSelectionsMessage } from '../../IncompleteSelectionsMessage'; -const getStyles = () => ({ - container: { - padding: '24px 24px 16px 24px', - }, -}); - const NewPagePlain = ({ showMessageToSelectOrgUnitOnNewPage, showMessageToSelectProgramCategoryOnNewPage, showMessageThatCategoryOptionIsInvalidForOrgUnit, showDefaultViewOnNewPage, handleMainPageNavigation, - classes, currentScopeId, newPageStatus, writeAccess, @@ -69,7 +61,7 @@ const NewPagePlain = ({ const orgUnitId = useSelector(({ currentSelections }) => currentSelections.orgUnitId); return ( - <div data-test="registration-page-content" className={classes.container} > + <div data-test="registration-page-content" className="container"> { !writeAccess ? <NoWriteAccessMessage @@ -140,6 +132,12 @@ const NewPagePlain = ({ </OrgUnitFetcher> } + + <style jsx>{` + .container { + padding: 24px 24px 16px 24px; + } + `}</style> </div> ); }; @@ -148,5 +146,4 @@ export const NewPageComponent: ComponentType<ContainerProps> = compose( withLoadingIndicator(), withErrorMessageHandler(), - withStyles(getStyles), )(NewPagePlain); diff --git a/src/core_modules/capture-core/components/Sticky/StickyOnScroll.component.js b/src/core_modules/capture-core/components/Sticky/StickyOnScroll.component.js index 58d98a2758..6891860541 100644 --- a/src/core_modules/capture-core/components/Sticky/StickyOnScroll.component.js +++ b/src/core_modules/capture-core/components/Sticky/StickyOnScroll.component.js @@ -1,37 +1,14 @@ // @flow import * as React from 'react'; -import { withStyles } from '@material-ui/core/styles'; type Props = { offsetTop: number, minViewpointWidth: number, children: React.Node, containerClass?: ?string, - classes: { - container: string, - stickyContainerAbsolute: string, - stickyContainerFixed: string, - stickyContainerAtBottom: string, - }, } -const styles = () => ({ - container: { - position: 'relative', - }, - stickyContainerAbsolute: { - position: 'static', - }, - stickyContainerFixed: { - position: 'fixed', - }, - stickyContainerAtBottom: { - position: 'absolute', - bottom: 0, - }, -}); - -class StickyOnScrollPlain extends React.Component<Props> { +export class StickyOnScroll extends React.Component<Props> { stickyContainer: any; scrollTimer: any; resizeTimer: any; @@ -67,7 +44,7 @@ class StickyOnScrollPlain extends React.Component<Props> { width < this.props.minViewpointWidth; } - setStickyContainerInstance = (instance) => { + setStickyContainerInstance = (instance: HTMLDivElement | null) => { this.stickyContainer = instance; this.setSticky(); } @@ -80,22 +57,21 @@ class StickyOnScrollPlain extends React.Component<Props> { } setSticky = () => { - const classes = this.props.classes; if (this.stickyContainer && (this.stickyDisabled() || !this.isNearTop())) { - this.stickyContainer.className = classes.stickyContainerAbsolute; + this.stickyContainer.className = 'sticky-container-absolute'; this.stickyContainer.style.top = 'initial'; this.stickyContainer.style.marginRight = 'initial'; this.stickyContainer.style.width = 'initial'; return; } if (this.stickyContainer && this.isAtBottomOfContainer()) { - this.stickyContainer.className = classes.stickyContainerAtBottom; + this.stickyContainer.className = 'sticky-container-at-bottom'; this.stickyContainer.style.top = 'initial'; this.stickyContainer.style.marginRight = 'initial'; return; } if (this.stickyContainer) { - this.stickyContainer.className = classes.stickyContainerFixed; + this.stickyContainer.className = 'sticky-container-fixed'; this.stickyContainer.style.top = `${this.props.offsetTop}px`; this.stickyContainer.style.width = `${this.stickyContainer.parentElement.clientWidth}px`; this.stickyContainer.style.marginRight = `${this.getRightMargin()}px`; @@ -116,17 +92,30 @@ class StickyOnScrollPlain extends React.Component<Props> { this.scrollTimer = window.setTimeout(this.setSticky, 10); } - render() { - const { classes, children, containerClass } = this.props; + const { children, containerClass } = this.props; return ( - <div className={containerClass || classes.container}> + <div className={containerClass || 'container'}> <div ref={(stickyContainerInstance) => { this.setStickyContainerInstance(stickyContainerInstance); }}> {children} </div> + <style jsx>{` + .container { + position: relative; + } + .sticky-container-absolute { + position: static; + } + .sticky-container-fixed { + position: fixed; + } + .sticky-container-at-bottom { + position: absolute; + bottom: 0; + } + `}</style> </div> ); } } -export const StickyOnScroll = withStyles(styles)(StickyOnScrollPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js index e3e08de57d..f54af65b70 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/Actions.component.js @@ -1,8 +1,7 @@ // @flow import { DropdownButton, FlyoutMenu, MenuDivider, spacersNum, colors } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core'; -import React, { type ComponentType, useState } from 'react'; +import React, { useState } from 'react'; import { Cancel } from './Cancel'; import { Complete, CompleteModal } from './Complete'; import { Delete } from './Delete'; @@ -15,20 +14,7 @@ import { MapModal } from '../MapModal'; import { Transfer } from './Transfer'; import { TransferModal } from '../TransferModal'; -const styles = { - actions: { - margin: `${spacersNum.dp8}px 0 0 0`, - }, - loading: { - display: 'flex', - alignItems: 'center', - margin: `${spacersNum.dp8}px 0 0 0`, - fontSize: '14px', - color: colors.grey900, - }, -}; - -export const ActionsPlain = ({ +export const ActionsComponent = ({ enrollment = {}, events, programStages, @@ -44,7 +30,6 @@ export const ActionsPlain = ({ onAddNew, loading, onlyEnrollOnce, - classes, }: PlainProps) => { const [isOpenActions, setOpenActions] = useState(false); const [isOpenMap, setOpenMap] = useState(false); @@ -71,7 +56,7 @@ export const ActionsPlain = ({ secondary small disabled={loading} - className={classes.actions} + className="actions" open={isOpenActions} onClick={() => setOpenActions(prev => !prev)} component={ @@ -128,7 +113,7 @@ export const ActionsPlain = ({ {i18n.t('Enrollment actions')} </DropdownButton> {loading && ( - <div className={classes.loading}> + <div className="loading"> <LoadingMaskForButton /> {i18n.t('We are processing your request.')} @@ -157,8 +142,18 @@ export const ActionsPlain = ({ onUpdateStatus={handleOnUpdateStatus} /> )} + <style jsx>{` + .actions { + margin: ${spacersNum.dp8}px 0 0 0; + } + .loading { + display: flex; + align-items: center; + margin: ${spacersNum.dp8}px 0 0 0; + font-size: 14px; + color: ${colors.grey900}; + } + `}</style> </> ); }; - -export const ActionsComponent: ComponentType<$Diff<PlainProps, CssClasses>> = withStyles(styles)(ActionsPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/actions.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/actions.types.js index b40adc2282..1a0a5c55ad 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Actions/actions.types.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Actions/actions.types.js @@ -38,6 +38,5 @@ export type PlainProps = {| canAddNew: boolean, onlyEnrollOnce: boolean, tetName: string, - ...CssClasses, |}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Date/Date.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/Date/Date.component.js index 5d4f6e83b8..09d7c29770 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Date/Date.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Date/Date.component.js @@ -9,12 +9,12 @@ import { spacersNum, } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core'; import { systemSettingsStore } from '../../../metaDataMemoryStores'; import { convertValue as convertValueClientToView } from '../../../converters/clientToView'; import { convertValue as convertValueFormToClient } from '../../../converters/formToClient'; import { convertValue as convertValueClientToServer } from '../../../converters/clientToServer'; import { dataElementTypes } from '../../../metaData'; +import { theme } from '../../../../../styles/theme'; type Props = { @@ -24,61 +24,15 @@ type Props = { editEnabled: boolean, displayAutoGeneratedEventWarning: boolean, onSave: (string) => void, - ...CssClasses, } -const styles = (theme: Theme) => ({ - editButton: { - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'center', - flexShrink: 0, - cursor: 'pointer', - border: 'none', - borderRadius: '3px', - background: 'transparent', - color: colors.grey600, - padding: 0, - marginLeft: '2px', - '&:focus': { - outline: 'none', - background: colors.grey200, - color: colors.grey800, - }, - '&:hover': { - background: colors.grey200, - color: colors.grey800, - }, - }, - calendar: { - paddingTop: '6px', - }, - inputField: { - maxWidth: '200px', - }, - buttonStrip: { - display: 'flex', - gap: `${spacersNum.dp4}px`, - margin: `${spacersNum.dp4}px 0`, - }, - note: { - fontSize: '12px', - color: colors.grey700, - }, - error: { - ...theme.typography.caption, - color: theme.palette.error.main, - }, -}); - -const DateComponentPlain = ({ +export const Date = ({ date, dateLabel, locale, editEnabled, displayAutoGeneratedEventWarning, onSave, - classes, }: Props) => { const [editMode, setEditMode] = useState(false); const [selectedDate, setSelectedDate] = useState(); @@ -107,7 +61,7 @@ const DateComponentPlain = ({ return editMode ? ( <div data-test="widget-enrollment-date"> - <div className={classes.inputField}> + <div className="input-field"> <DateField width={200} value={selectedDate} @@ -118,11 +72,11 @@ const DateComponentPlain = ({ calendarType={systemSettingsStore.get().calendar} dateFormat={systemSettingsStore.get().dateFormat} /> - <div className={classes.error}> + <div className="error"> {validation && validation.error ? i18n.t('Please provide a valid date') : ''} </div> </div> - <div className={classes.buttonStrip}> + <div className="button-strip"> <Button primary small @@ -140,13 +94,36 @@ const DateComponentPlain = ({ </Button> </div> {displayAutoGeneratedEventWarning && ( - <div className={classes.note}> + <div className="note"> {i18n.t('Existing dates for auto-generated events will not be updated.')} </div> )} + + <style jsx>{` + .input-field { + max-width: 200px; + } + .button-strip { + display: flex; + gap: ${spacersNum.dp4}px; + margin: ${spacersNum.dp4}px 0; + } + .note { + font-size: 12px; + color: ${colors.grey700}; + } + .error { + font-family: ${theme.typography.fontFamily}; + font-weight: ${theme.typography.caption.fontWeight}; + font-size: ${theme.typography.caption.fontSize}; + line-height: ${theme.typography.caption.lineHeight}; + letter-spacing: ${theme.typography.caption.letterSpacing}; + color: ${theme.palette.error.main}; + } + `}</style> </div> ) : ( - <div className={classes.row} data-test="widget-enrollment-date"> + <div className="row" data-test="widget-enrollment-date"> <span data-test="widget-enrollment-icon-calendar"> <IconCalendar16 color={colors.grey600} /> </span> @@ -154,15 +131,49 @@ const DateComponentPlain = ({ {displayDate} {editEnabled && <button - className={classes.editButton} + className="edit-button" data-test="widget-enrollment-icon-edit-date" onClick={onOpenEdit} > <IconEdit16 /> </button> } + + <style jsx>{` + .row { + display: flex; + align-items: center; + margin: ${spacersNum.dp8}px 0; + font-size: 14px; + color: ${colors.grey900}; + gap: ${spacersNum.dp4}px; + } + .edit-button { + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + cursor: pointer; + border: none; + border-radius: 3px; + background: transparent; + color: ${colors.grey600}; + padding: 0; + margin-left: 2px; + } + .edit-button:focus { + outline: none; + background: ${colors.grey200}; + color: ${colors.grey800}; + } + .edit-button:hover { + background: ${colors.grey200}; + color: ${colors.grey800}; + } + .calendar { + padding-top: 6px; + } + `}</style> </div> ); }; - -export const Date = withStyles(styles)(DateComponentPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js index a8d3304847..e86afaaf01 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.component.js @@ -1,32 +1,19 @@ // @flow import React, { useState } from 'react'; import { Map, TileLayer, Marker, Polygon } from 'react-leaflet'; -import { withStyles } from '@material-ui/core'; import { dataElementTypes } from '../../../metaData'; import { MapModal } from '../MapModal'; import type { MiniMapProps } from './MiniMap.types'; import { convertToClientCoordinates } from './converters'; import { useUpdateEnrollment } from '../dataMutation/dataMutation'; -const styles = () => ({ - mapContainer: { - width: 150, - height: 120, - }, - map: { - width: '100%', - height: '100%', - }, -}); - -const MiniMapPlain = ({ +export const MiniMap = ({ coordinates, geometryType, enrollment, refetchEnrollment, refetchTEI, onError, - classes, }: MiniMapProps) => { const [isOpenMap, setOpenMap] = useState(false); const { updateMutation } = useUpdateEnrollment(refetchEnrollment, refetchTEI, onError); @@ -38,16 +25,15 @@ const MiniMapPlain = ({ map?.fitBounds(clientValues); } }; - return ( <> - <div className={classes.mapContainer}> + <div className="map-container"> <Map ref={(mapRef) => { onMapReady(mapRef); }} center={center} - className={classes.map} + className="map" zoom={11} zoomControl={false} attributionControl={false} @@ -73,8 +59,16 @@ const MiniMapPlain = ({ enrollment={enrollment} /> )} + <style jsx>{` + .map-container { + width: 150px; + height: 120px; + } + .map { + width: 100%; + height: 100%; + } + `}</style> </> ); }; - -export const MiniMap = withStyles(styles)(MiniMapPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js index b905c28783..d566f2840d 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/MiniMap/MiniMap.types.js @@ -9,5 +9,4 @@ export type MiniMapProps = { refetchTEI: QueryRefetchFunction, onError?: (message: string) => void, geometryType: typeof dataElementTypes.COORDINATE | typeof dataElementTypes.POLYGON, - ...CssClasses } diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Status/Status.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/Status/Status.component.js index 3a4d14cd18..31e3246ec1 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Status/Status.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Status/Status.component.js @@ -1,29 +1,24 @@ // @flow -import React, { type ComponentType } from 'react'; -import { withStyles } from '@material-ui/core'; +import React from 'react'; import { Tag, spacersNum } from '@dhis2/ui'; import { plainStatus, translatedStatus } from '../constants/status.const'; import type { Props } from './status.types'; -const styles = { - status: { - margin: `0 0 ${spacersNum.dp4}px 0`, - }, -}; - -export const StatusPlain = ({ status = '', classes }: Props) => ( +export const Status = ({ status = '' }: Props) => ( <> <Tag - className={classes.status} + className="status-tag" neutral={status === plainStatus.ACTIVE} negative={status === plainStatus.CANCELLED} > {translatedStatus[status] || status} </Tag> + + <style jsx>{` + :global(.status-tag) { + margin: 0 0 ${spacersNum.dp4}px 0; + } + `}</style> </> ); - -export const Status: ComponentType<$Diff<Props, CssClasses>> = withStyles( - styles, -)(StatusPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/Status/status.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/Status/status.types.js index 0285640bef..df2e6f4771 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/Status/status.types.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/Status/status.types.js @@ -2,6 +2,5 @@ export type Props = {| status: string, - ...CssClasses, |}; diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js index b5eae0842b..e127d04bf3 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/WidgetEnrollment.component.js @@ -1,5 +1,5 @@ // @flow -import React, { useState, useCallback, type ComponentType } from 'react'; +import React, { useState, useCallback } from 'react'; import moment from 'moment'; import { IconClock16, @@ -11,7 +11,6 @@ import { } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import { useTimeZoneConversion } from '@dhis2/app-runtime'; -import { withStyles } from '@material-ui/core'; import { LoadingMaskElementCenter } from '../LoadingMasks'; import { Widget } from '../Widget'; import type { PlainProps } from './enrollment.types'; @@ -23,31 +22,12 @@ import { Date } from './Date'; import { Actions } from './Actions'; import { MiniMap } from './MiniMap'; -const styles = { - enrollment: { - padding: `0 ${spacersNum.dp16}px ${spacersNum.dp16}px ${spacersNum.dp16}px`, - }, - row: { - display: 'flex', - alignItems: 'center', - margin: `${spacersNum.dp8}px 0`, - fontSize: '14px', - color: colors.grey900, - gap: `${spacersNum.dp4}px`, - }, - statuses: { - display: 'flex', - gap: `${spacersNum.dp4}px`, - }, -}; - const getGeometryType = geometryType => (geometryType === 'Point' ? dataElementTypes.COORDINATE : dataElementTypes.POLYGON); const getEnrollmentDateLabel = program => program.displayEnrollmentDateLabel || i18n.t('Enrollment date'); const getIncidentDateLabel = program => program.displayIncidentDateLabel || i18n.t('Incident date'); -export const WidgetEnrollmentPlain = ({ - classes, +export const WidgetEnrollment = ({ events, enrollment = {}, program = {}, @@ -91,16 +71,16 @@ export const WidgetEnrollmentPlain = ({ open={open} > {initError && ( - <div className={classes.enrollment}> + <div className="enrollment"> {i18n.t('Enrollment widget could not be loaded. Please try again later')} </div> )} {loading && <LoadingMaskElementCenter />} {!initError && !loading && ( - <div className={classes.enrollment} data-test="widget-enrollment-contents"> - <div className={classes.statuses} data-test="widget-enrollment-status"> + <div className="enrollment" data-test="widget-enrollment-contents"> + <div className="statuses" data-test="widget-enrollment-status"> {enrollment.followUp && ( - <Tag className={classes.followup} negative> + <Tag className="followup" negative> {i18n.t('Follow-up')} </Tag> )} @@ -115,7 +95,6 @@ export const WidgetEnrollmentPlain = ({ editEnabled={editDateEnabled} displayAutoGeneratedEventWarning={displayAutoGeneratedEventWarning} onSave={updateEnrollmentDate} - classes={classes} /> </span> @@ -128,13 +107,12 @@ export const WidgetEnrollmentPlain = ({ editEnabled={editDateEnabled} displayAutoGeneratedEventWarning={displayAutoGeneratedEventWarning} onSave={updateIncidentDate} - classes={classes} /> </span> )} - <div className={classes.row} data-test="widget-enrollment-orgunit"> - <span className={classes.icon} data-test="widget-enrollment-icon-orgunit"> + <div className="row" data-test="widget-enrollment-orgunit"> + <span className="icon" data-test="widget-enrollment-icon-orgunit"> <IconDimensionOrgUnit16 color={colors.grey600} /> </span> {i18n.t('Started at{{escape}}', { @@ -143,8 +121,8 @@ export const WidgetEnrollmentPlain = ({ {convertValue(orgUnitClientValue, type)} </div> - <div className={classes.row} data-test="widget-enrollment-owner-orgunit"> - <span className={classes.icon} data-test="widget-enrollment-icon-owner-orgunit"> + <div className="row" data-test="widget-enrollment-owner-orgunit"> + <span className="icon" data-test="widget-enrollment-icon-owner-orgunit"> <IconDimensionOrgUnit16 color={colors.grey600} /> </span> {i18n.t('Owned by{{escape}}', { @@ -153,8 +131,8 @@ export const WidgetEnrollmentPlain = ({ {convertValue(ownerOrgUnitClientValue, type)} </div> - <div className={classes.row} data-test="widget-enrollment-last-update"> - <span className={classes.icon} data-test="widget-enrollment-icon-clock"> + <div className="row" data-test="widget-enrollment-last-update"> + <span className="icon" data-test="widget-enrollment-icon-clock"> <IconClock16 color={colors.grey600} /> </span> {i18n.t('Last updated')} @@ -164,7 +142,7 @@ export const WidgetEnrollmentPlain = ({ </div> {enrollment.geometry && ( - <div className={classes.row}> + <div className="row"> <MiniMap coordinates={enrollment.geometry.coordinates} geometryType={geometryType} @@ -197,8 +175,35 @@ export const WidgetEnrollmentPlain = ({ </div> )} </Widget> + + <style jsx>{` + .enrollment { + padding: 0 ${spacersNum.dp16}px ${spacersNum.dp16}px ${spacersNum.dp16}px; + } + + .statuses { + display: flex; + gap: ${spacersNum.dp4}px; + margin-bottom: ${spacersNum.dp16}px; + } + + .row { + display: flex; + align-items: center; + margin: ${spacersNum.dp8}px 0; + font-size: 14px; + color: ${colors.grey900}; + gap: ${spacersNum.dp4}px; + } + + .icon { + margin-right: ${spacersNum.dp8}px; + } + + .followup { + margin-right: ${spacersNum.dp4}px; + } + `}</style> </div> ); }; - -export const WidgetEnrollment: ComponentType<$Diff<PlainProps, CssClasses>> = withStyles(styles)(WidgetEnrollmentPlain); diff --git a/src/core_modules/capture-core/components/WidgetEnrollment/enrollment.types.js b/src/core_modules/capture-core/components/WidgetEnrollment/enrollment.types.js index 3417c900d5..41c61ecfe9 100644 --- a/src/core_modules/capture-core/components/WidgetEnrollment/enrollment.types.js +++ b/src/core_modules/capture-core/components/WidgetEnrollment/enrollment.types.js @@ -47,5 +47,4 @@ export type PlainProps = {| onUpdateEnrollmentStatusSuccess?: ({ redirect?: boolean }) => void, onUpdateEnrollmentStatusError?: (message: string) => void, onAccessLostFromTransfer?: () => void, - ...CssClasses, |}; diff --git a/src/core_modules/capture-core/components/WidgetNote/NoteSection/NoteSection.js b/src/core_modules/capture-core/components/WidgetNote/NoteSection/NoteSection.js index 91d18f4c3e..d2d5eaa7d5 100644 --- a/src/core_modules/capture-core/components/WidgetNote/NoteSection/NoteSection.js +++ b/src/core_modules/capture-core/components/WidgetNote/NoteSection/NoteSection.js @@ -1,10 +1,8 @@ // @flow -import React, { type ComponentType, useState, useCallback } from 'react'; +import React, { useState, useCallback } from 'react'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core'; import { withFocusSaver } from 'capture-ui'; import { Parser, Editor } from '@dhis2/d2-ui-rich-text'; -import cx from 'classnames'; import { colors, spacersNum, Button, Tooltip } from '@dhis2/ui'; import moment from 'moment'; import { useTimeZoneConversion } from '@dhis2/app-runtime'; @@ -19,65 +17,13 @@ type Props = { handleAddNote: (text: string) => void, placeholder: string, emptyNoteMessage: string, - ...CssClasses } -const styles = { - item: { - padding: spacersNum.dp12, - marginRight: spacersNum.dp4, - background: colors.grey200, - borderRadius: '5px', - display: 'flex', - fontSize: '14px', - lineHeight: '19px', - color: colors.grey900, - '& + &': { - marginTop: spacersNum.dp8, - }, - }, - wrapper: { - padding: `0 ${spacersNum.dp16}px`, - marginBottom: spacersNum.dp16, - }, - notesWrapper: { - maxHeight: 400, - overflowY: 'auto', - }, - editor: { - paddingTop: spacersNum.dp16, - }, - emptyNotes: { - fontSize: 14, - color: colors.grey600, - }, - name: { - fontSize: '13px', - fontWeight: 500, - }, - lastUpdated: { - fontSize: '12px', - marginLeft: '8px', - color: colors.grey700, - }, - body: { - '& p': { - margin: `${spacersNum.dp8}px 0 0 0`, - }, - }, - newNoteButtonContainer: { - paddingTop: spacersNum.dp4, - display: 'flex', - gap: '4px', - }, -}; - -const NoteSectionPlain = ({ +export const NoteSection = ({ placeholder, emptyNoteMessage, notes, handleAddNote, - classes, }: Props) => { const [isEditing, setEditing] = useState(false); const [newNoteValue, setNewNoteValue] = useState(''); @@ -100,41 +46,68 @@ const NoteSectionPlain = ({ }, [handleAddNote, newNoteValue]); const NoteItem = ({ value, storedAt, createdBy }) => ( - <div data-test="note-item" className={cx(classes.item)}> + <div data-test="note-item" className="item"> {/* TODO: add avatar */} - <div className={classes.rightColumn}> - <div className={classes.header}> - {createdBy && <span className={cx(classes.headerText, classes.name)}> + <div className="right-column"> + <div className="header"> + {createdBy && <span className="name"> {createdBy.firstName} {' '} {createdBy.surname} </span>} - <span className={cx(classes.headerText, classes.lastUpdated)}> + <span className="last-updated"> <Tooltip content={convertClientToList(moment(fromServerDate(storedAt).getClientZonedISOString()).toISOString(), dataElementTypes.DATETIME)}> {moment(fromServerDate(storedAt)).fromNow()} </Tooltip> </span> </div> - <div className={classes.body}> + <div className="body"> <Parser>{value}</Parser> </div> </div> + <style jsx>{` + .item { + padding: ${spacersNum.dp12}px; + margin-right: ${spacersNum.dp4}px; + background: ${colors.grey200}; + border-radius: 5px; + display: flex; + font-size: 14px; + line-height: 19px; + color: ${colors.grey900}; + } + .item + .item { + margin-top: ${spacersNum.dp8}px; + } + .name { + font-size: 13px; + font-weight: 500; + } + .last-updated { + font-size: 12px; + margin-left: 8px; + color: ${colors.grey700}; + } + .body :global(p) { + margin: ${spacersNum.dp8}px 0 0 0; + } + `}</style> </div> ); return ( - <div className={classes.wrapper}> - <div className={classes.notesWrapper}> + <div className="wrapper"> + <div className="notes-wrapper"> {notes .sort((a, b) => moment(a.storedAt).valueOf() - moment(b.storedAt).valueOf()) .map(note => <NoteItem key={`note-item-${note.note}-`} {...note} />) } {notes.length === 0 && - <div className={classes.emptyNotes}> + <div className="empty-notes"> {emptyNoteMessage} </div>} </div> - <div className={classes.editor}> + <div className="editor"> <Editor> <FocusTextField placeholder={placeholder} @@ -145,7 +118,7 @@ const NoteSectionPlain = ({ </Editor> </div> - {isEditing && <div className={classes.newNoteButtonContainer} data-test="note-buttons-container"> + {isEditing && <div className="new-note-button-container" data-test="note-buttons-container"> <Button dataTest="add-note-btn" onClick={onAddNote} @@ -160,7 +133,30 @@ const NoteSectionPlain = ({ {i18n.t('Cancel')} </Button> </div>} - </div>); + + <style jsx>{` + .wrapper { + padding: 0 ${spacersNum.dp16}px; + margin-bottom: ${spacersNum.dp16}px; + } + .notes-wrapper { + max-height: 400px; + overflow-y: auto; + } + .editor { + padding-top: ${spacersNum.dp16}px; + } + .empty-notes { + font-size: 14px; + color: ${colors.grey600}; + } + .new-note-button-container { + padding-top: ${spacersNum.dp4}px; + display: flex; + gap: 4px; + } + `}</style> + </div> + ); }; -export const NoteSection: ComponentType<Props> = withStyles(styles)(NoteSectionPlain); diff --git a/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.js b/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.js index 26ac54e7b6..e9684ce326 100644 --- a/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.js +++ b/src/core_modules/capture-core/components/WidgetProfile/WidgetProfile.component.js @@ -1,11 +1,9 @@ // @flow /* eslint-disable complexity */ import React, { useEffect, useState, useCallback, useMemo } from 'react'; -import type { ComponentType } from 'react'; import { useSelector } from 'react-redux'; import i18n from '@dhis2/d2-i18n'; import { Button, spacers } from '@dhis2/ui'; -import { withStyles } from '@material-ui/core'; import log from 'loglevel'; import { FlatList } from 'capture-ui'; import { useQueryClient } from 'react-query'; @@ -29,34 +27,16 @@ import { useDataEntryFormConfig, } from '../DataEntries/common/TEIAndEnrollment'; -const styles = { - header: { - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - width: '100%', - }, - container: { - padding: `0 ${spacers.dp16}`, - marginBottom: spacers.dp8, - }, - actions: { - display: 'flex', - gap: '4px', - }, -}; - const showEditModal = (loading, error, showEdit, modalState) => !loading && !error && showEdit && modalState !== TEI_MODAL_STATE.CLOSE; -const WidgetProfilePlain = ({ +export const WidgetProfile = ({ teiId, programId, readOnlyMode = false, orgUnitId = '', onUpdateTeiAttributeValues, onDeleteSuccess, - classes, }: PlainProps) => { const supportsChangelog = useFeature(FEATURES.changelogs); const queryClient = useQueryClient(); @@ -135,8 +115,14 @@ const WidgetProfilePlain = ({ } return ( - <div className={classes.container}> + <div className="container"> <FlatList dataTest="profile-widget-flatlist" list={displayInListAttributes} /> + <style jsx>{` + .container { + padding: 0 ${spacers.dp16}; + margin-bottom: ${spacers.dp8}; + } + `}</style> </div> ); }; @@ -147,7 +133,7 @@ const WidgetProfilePlain = ({ <div data-test="profile-widget"> <Widget header={ - <div className={classes.header}> + <div className="header"> <div> {trackedEntityTypeName ? i18n.t('{{trackedEntityTypeName}} profile', { @@ -156,7 +142,7 @@ const WidgetProfilePlain = ({ }) : i18n.t('Profile')} </div> - <div className={classes.actions}> + <div className="actions"> {isEditable && ( <Button onClick={() => setTeiModalState(TEI_MODAL_STATE.OPEN)} secondary small> {i18n.t('Edit')} @@ -174,6 +160,18 @@ const WidgetProfilePlain = ({ readOnlyMode={readOnlyMode || false} /> </div> + <style jsx>{` + .header { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + } + .actions { + display: flex; + gap: 4px; + } + `}</style> </div> } onOpen={useCallback(() => setOpenStatus(true), [setOpenStatus])} @@ -208,4 +206,3 @@ const WidgetProfilePlain = ({ ); }; -export const WidgetProfile: ComponentType<$Diff<PlainProps, CssClasses>> = withStyles(styles)(WidgetProfilePlain); diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.component.js index a100abb1f6..4c21225ae0 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.component.js @@ -2,31 +2,15 @@ import React from 'react'; import { Button, colors } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; -import { withStyles } from '@material-ui/core/styles'; import type { ComponentProps } from './BulkActionBar.types'; -const styles = { - container: { - background: colors.teal100, - height: '60px', - border: `2px solid ${colors.teal400}`, - width: '100%', - padding: '8px', - fontSize: '14px', - gap: '8px', - display: 'flex', - alignItems: 'center', - }, -}; - -export const BulkActionBarComponentPlain = ({ +export const BulkActionBarComponent = ({ selectedRowsCount, onClearSelection, children, - classes, }: ComponentProps) => ( <div - className={classes.container} + className="container" data-test="bulk-action-bar" > <span> @@ -42,9 +26,19 @@ export const BulkActionBarComponentPlain = ({ > {i18n.t('Deselect all')} </Button> + + <style jsx>{` + .container { + background: ${colors.teal100}; + height: 60px; + border: 2px solid ${colors.teal400}; + width: 100%; + padding: 8px; + font-size: 14px; + gap: 8px; + display: flex; + align-items: center; + } + `}</style> </div> ); - -export const BulkActionBarComponent = withStyles( - styles, -)(BulkActionBarComponentPlain); diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.types.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.types.js index 140806a1fe..6895f86813 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.types.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/BulkActionBar/BulkActionBar.types.js @@ -12,5 +12,4 @@ export type ContainerProps = {| export type ComponentProps = {| ...SharedProps, - ...CssClasses, |} diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js index ca1a446e8f..b5437a93cc 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js @@ -1,32 +1,17 @@ // @flow import * as React from 'react'; import { Button, ButtonStrip, colors, ModalActions, ModalContent, ModalTitle } from '@dhis2/ui'; -import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; import { NewTemplateTextField } from './NewTemplateTextField.component'; +import { theme } from '../../../../../../styles/theme'; -const getStyles = (theme: Theme) => ({ - error: { - padding: 4, - color: colors.red500, - fontSize: theme.typography.pxToRem(14), - }, - input: { - width: '100%', - }, - buttonContainer: { - display: 'flex', - justifyContent: 'space-between', - }, -}); type Props = { onSaveTemplate: (name: string) => void, onClose: () => void, - classes: Object, }; -const NewTemplateContentsPlain = (props: Props) => { - const { onSaveTemplate, onClose, classes } = props; +export const NewTemplateContents = (props: Props) => { + const { onSaveTemplate, onClose } = props; const [name, setName] = React.useState(''); const [error, setError] = React.useState(); @@ -47,19 +32,20 @@ const NewTemplateContentsPlain = (props: Props) => { <React.Fragment> <ModalTitle>{i18n.t('Save As view')}</ModalTitle> <ModalContent> - <NewTemplateTextField - onBlur={nameBlurHandler} - className={classes.input} - label={i18n.t('View name')} - error={!!error} - dataTest="view-name" - initialFocus - required - name="viewName" - /> + <div className="input-container"> + <NewTemplateTextField + onBlur={nameBlurHandler} + label={i18n.t('View name')} + error={!!error} + dataTest="view-name" + initialFocus + required + name="viewName" + /> + </div> <div data-test="view-name-error-message" - className={classes.error} + className="error-message" > {error} </div> @@ -74,8 +60,21 @@ const NewTemplateContentsPlain = (props: Props) => { </Button> </ButtonStrip> </ModalActions> + + <style jsx>{` + .error-message { + padding: 4px; + color: ${colors.red500}; + font-size: ${theme.typography.pxToRem(14)}; + } + .input-container { + width: 100%; + } + .button-container { + display: flex; + justify-content: space-between; + } + `}</style> </React.Fragment> ); }; - -export const NewTemplateContents = withStyles(getStyles)(NewTemplateContentsPlain);