-
Notifications
You must be signed in to change notification settings - Fork 290
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Phani | BAH-3117 | Create React components for OT Notes Save, Edit & …
…Delete Popups using carbon components (#954) * Phani | Include next-ui in OT Moulde * Phani | Create Notes Save & Delete popups * Phani | Add update flow & integrate BE APIs * Phani | Fix bug in delete flow * Phani | Remove unused Angular code * Phani | Move notes save & delete components into components directory * Phani | Update translations * Phani | Add tests for Save & Delete Popups * Phani | Fix uglify * Phani | Fix uglify by refactoring the imports * Phani | Rename folder otNotes in components
- Loading branch information
1 parent
9978734
commit 185ae88
Showing
22 changed files
with
1,088 additions
and
322 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
micro-frontends/src/next-ui/Components/OtNotes/DeletePopup.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import React, { useState } from "react"; | ||
import PropTypes from "prop-types"; | ||
import { Modal } from "carbon-components-react"; | ||
import "../../../styles/carbon-conflict-fixes.scss"; | ||
import "../../../styles/carbon-theme.scss"; | ||
import { deleteOtNote } from "./utils"; | ||
import {FormattedMessage} from "react-intl"; | ||
import "./OtNotes.scss"; | ||
export function DeletePopup(props) { | ||
const { hostData, hostApi} = props; | ||
const [isLoading, setIsLoading] = useState(false); | ||
return <Modal | ||
open | ||
danger | ||
className="next-ui ot-notes-popup" | ||
modalHeading={<FormattedMessage id={"DELETE_NOTE_TITLE"} defaultMessage={"Delete Note"}/>} | ||
primaryButtonText={isLoading? <FormattedMessage id={"LOADING"} defaultMessage={"Loading..."}/> : <FormattedMessage id={"YES"} defaultMessage={"Yes"}/>} | ||
secondaryButtonText={<FormattedMessage id={"NO"} defaultMessage={"No"}/>} | ||
onRequestClose={hostApi?.onClose} | ||
onSecondarySubmit={hostApi?.onClose} | ||
onRequestSubmit={() => { | ||
setIsLoading(true); | ||
deleteOtNote(hostData?.noteId).then(() => { | ||
setIsLoading(false); | ||
hostApi?.onSuccess(); | ||
}); | ||
}} | ||
> | ||
<FormattedMessage id={"DELETE_NOTE_MESSAGE"} defaultMessage={"Are you sure you want to delete this OT Note?"}/> | ||
</Modal> | ||
} | ||
|
||
DeletePopup.propTypes = { | ||
hostData: PropTypes.Object, | ||
hostApi: PropTypes.Object, | ||
} |
29 changes: 29 additions & 0 deletions
29
micro-frontends/src/next-ui/Components/OtNotes/DeletePopup.spec.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from "react"; | ||
import {render, screen, waitFor} from "@testing-library/react"; | ||
import { DeletePopup } from "./DeletePopup"; | ||
import {I18nProvider} from "../i18n/I18nProvider"; | ||
|
||
const mockDeletePopup = jest.fn(); | ||
|
||
jest.mock('../i18n/utils'); | ||
jest.mock("./utils", () => ({ | ||
deleteOtNote : () => mockDeletePopup(), | ||
})); | ||
describe("DeletePopup", () => { | ||
it("should render", async () => { | ||
const {container, getByText} = render(<I18nProvider><DeletePopup hostData={{noteId: 10}}/></I18nProvider>); | ||
await waitFor(() => { | ||
expect(getByText("Delete Note")).toBeTruthy(); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); | ||
it("should call deleteOtNote on submit", async () => { | ||
const {getByText}= render(<I18nProvider><DeletePopup hostData={{noteId: 10}}/></I18nProvider>); | ||
await waitFor(() => { | ||
expect(getByText("Delete Note")).toBeTruthy(); | ||
}); | ||
mockDeletePopup.mockResolvedValue(() => {}) | ||
screen.getByText("Yes").click(); | ||
expect(mockDeletePopup).toHaveBeenCalled(); | ||
}); | ||
}); |
22 changes: 22 additions & 0 deletions
22
micro-frontends/src/next-ui/Components/OtNotes/OtNotes.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
.ot-notes-popup{ | ||
.bx--modal-close{ | ||
top: 0; | ||
right: 0; | ||
&:hover{ | ||
background-color: #e5e5e5 !important; | ||
} | ||
} | ||
.date-range{ | ||
display: flex; | ||
justify-content: space-between; | ||
} | ||
.bx--date-picker.bx--date-picker--single .bx--date-picker__input{ | ||
width: 230px; | ||
} | ||
.error-text{ | ||
color: #da1e28; | ||
} | ||
.bx--date-picker__input:disabled{ | ||
color: #8d8d8d; | ||
} | ||
} |
145 changes: 145 additions & 0 deletions
145
micro-frontends/src/next-ui/Components/OtNotes/SavePopup.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import React, {useEffect, useState} from "react"; | ||
import PropTypes from "prop-types"; | ||
import {Modal, TextArea, DatePicker, DatePickerInput} from "carbon-components-react"; | ||
import "../../../styles/carbon-conflict-fixes.scss"; | ||
import "../../../styles/carbon-theme.scss"; | ||
import "./OtNotes.scss"; | ||
import {FormattedMessage, useIntl} from "react-intl"; | ||
import {I18nProvider} from '../i18n/I18nProvider'; | ||
import moment from "moment"; | ||
import {saveNote, updateNoteForADay} from "./utils"; | ||
|
||
export function SavePopup(props) { | ||
const {hostData, hostApi} = props; | ||
const { | ||
notes, | ||
weekEndDateTime = moment().endOf('day'), | ||
weekStartDateTime = moment().startOf('day'), | ||
isDayView, | ||
noteId, | ||
noteDate, | ||
providerUuid | ||
} = hostData; | ||
const [modalNotes, setModalNotes] = useState(notes || ""); | ||
const [startDate, setStartDate] = useState(new Date(noteDate)); | ||
const [endDate, setEndDate] = useState(new Date(noteDate)); | ||
const [shouldShowErrors, setShouldShowErrors] = useState(false); | ||
const validMinStartDate = noteId || isDayView ? new Date(noteDate) : new Date(weekStartDateTime); | ||
const [validMinEndDate, setValidMinEndDate] = useState(noteId || isDayView ? new Date(noteDate) : new Date(weekEndDateTime)); | ||
const [isLoading, setIsLoading] = useState(false); | ||
const intl = useIntl(); | ||
|
||
const hasActiveErrors = () => { | ||
return !modalNotes || !startDate || !endDate || startDate > endDate; | ||
} | ||
|
||
const handleSave = () => { | ||
if (noteId) { | ||
updateNoteForADay(noteId, modalNotes, providerUuid).then(() => { | ||
setIsLoading(false); | ||
hostApi?.onSuccess(); | ||
}); | ||
} else if (isDayView) { | ||
saveNote(modalNotes, startDate).then(() => { | ||
setIsLoading(false); | ||
hostApi?.onSuccess(); | ||
}); | ||
} else { | ||
saveNote(modalNotes, startDate, endDate).then(() => { | ||
setIsLoading(false); | ||
hostApi?.onSuccess(); | ||
}); | ||
} | ||
} | ||
useEffect(() => { | ||
setValidMinEndDate(startDate); | ||
}, [startDate]); | ||
return ( | ||
<I18nProvider> | ||
<Modal | ||
open | ||
className={"next-ui ot-notes-popup"} | ||
modalHeading={noteId ? <FormattedMessage id={'UPDATE_NOTE_TITLE'} defaultMessage={"Update Notes"}/> : | ||
<FormattedMessage id={'ADD_NOTE_TITLE'} defaultMessage={"Add Notes"}/>} | ||
primaryButtonText={isLoading ? | ||
<FormattedMessage id={"LOADING"} defaultMessage={"Loading..."}/> : noteId ? | ||
<FormattedMessage id={"UPDATE"} defaultMessage={"Update"}/> : | ||
<FormattedMessage id={"SAVE"} defaultMessage={"Save"}/>} | ||
secondaryButtonText={<FormattedMessage id={"CANCEL"} defaultMessage={"Cancel"}/>} | ||
onRequestClose={hostApi?.onClose} | ||
onRequestSubmit={() => { | ||
setShouldShowErrors(true); | ||
if (!hasActiveErrors()) { | ||
setIsLoading(true); | ||
handleSave(); | ||
} | ||
}} | ||
> | ||
<TextArea labelText={<FormattedMessage id={"OT_NOTES"} defaultMessage={"Notes"}/>} | ||
value={modalNotes} | ||
placeholder={intl.formatMessage({ | ||
id: "NOTES_PLACEHOLDER", | ||
defaultMessage: "Enter a maximum of 150 characters" | ||
})} maxCount={150} onChange={e => { | ||
setModalNotes(e?.target?.value); | ||
}}/> | ||
{shouldShowErrors && !modalNotes ? | ||
<p className={"error-text"}><FormattedMessage id={"EMPTY_NOTES_ERROR"} | ||
defaultMessage={"Note cannot be empty"}/> | ||
</p> : <div style={{height: "20px"}}></div>} | ||
<div className={"date-range"}> | ||
<div> | ||
<DatePicker datePickerType="single" maxDate={new Date(weekEndDateTime)} dateFormat={"d/m/Y"} | ||
minDate={validMinStartDate} value={startDate} | ||
onChange={(e) => { | ||
if (e.length === 1) { | ||
setStartDate(e[0]); | ||
} | ||
}}> | ||
<DatePickerInput | ||
id="date-picker-input-id-start" | ||
placeholder="dd/mm/yyyy" | ||
labelText="Start date" | ||
disabled={Boolean(isDayView || noteId)} | ||
/> | ||
</DatePicker> | ||
{shouldShowErrors && !startDate ? | ||
<div className={"error-text"}><FormattedMessage id={'DATE_OUT_OF_RANGE_ERROR'} | ||
defaultMessage={"Please select date within the valid range"}/> | ||
</div> : startDate > endDate ? | ||
<div className={"error-text"}><FormattedMessage id={'FROM_DATE_BEFORE_TO_DATE_ERROR'} | ||
defaultMessage={"From date should be before To date"}/> | ||
</div> : | ||
<div style={{height: "20px"}}></div> | ||
} | ||
</div> | ||
<div> | ||
<DatePicker datePickerType="single" maxDate={new Date(weekEndDateTime)} dateFormat={"d/m/Y"} | ||
minDate={validMinEndDate} value={endDate} | ||
onChange={(e) => { | ||
if (e.length === 1) { | ||
setEndDate(e[0]); | ||
} | ||
}}> | ||
<DatePickerInput | ||
id="date-picker-input-id-finish" | ||
placeholder="dd/mm/yyyy" | ||
labelText="End date" | ||
disabled={Boolean(isDayView || noteId)} | ||
/> | ||
</DatePicker> | ||
{shouldShowErrors && !endDate ? | ||
<div className={"error-text"}><FormattedMessage id={'DATE_OUT_OF_RANGE_ERROR'} | ||
defaultMessage={"Please select date within the valid range"}/> | ||
</div> : <div style={{height: "20px"}}></div>} | ||
</div> | ||
</div> | ||
</Modal> | ||
</I18nProvider> | ||
); | ||
} | ||
|
||
SavePopup.propTypes = { | ||
hostData: PropTypes.any, | ||
hostApi: PropTypes.any, | ||
} |
Oops, something went wrong.