From 26a96c7b3232e0fe26726b2a52fadccb3b13c052 Mon Sep 17 00:00:00 2001 From: pooja Date: Wed, 6 Sep 2023 11:19:10 +0530 Subject: [PATCH 1/4] TP-40366 | adding yarn.lock file --- package.json | 3 + src/Pages/Team/Team.module.scss | 25 ++++- src/Pages/Team/constants.ts | 4 + src/Pages/Team/index.tsx | 28 +++++- src/Pages/Team/partials/CreateTeam.tsx | 121 +++++++++++++++++++++++++ src/components/Footer/index.tsx | 3 +- 6 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 src/Pages/Team/partials/CreateTeam.tsx diff --git a/package.json b/package.json index 20554c9..cc8ad44 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ ] }, "dependencies": { + "@headlessui/react": "^1.7.17", + "@heroicons/react": "^2.0.18", "@navi/web-ui": "^1.49.8", "@super-app/dark-knight": "^1.0.6", "axios": "^1.3.4", @@ -39,6 +41,7 @@ "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.8.2", "sass": "^1.58.3" }, diff --git a/src/Pages/Team/Team.module.scss b/src/Pages/Team/Team.module.scss index edf1cc6..901a80d 100644 --- a/src/Pages/Team/Team.module.scss +++ b/src/Pages/Team/Team.module.scss @@ -44,7 +44,14 @@ width: fit-content; margin-top: 12px; } - +.create-team-btn-wrapper { + padding: 6px 0 12px 0px; +} +.create-team-btn { + width: (164px); + height: (36px); + margin-top: 12px; +} .content-wrapper { width: 50%; padding: 0 12px 12px; @@ -98,3 +105,19 @@ .filter-container { border: 1px solid var(--navi-color-gray-border); } +.input-wrapper { + display: flex; + align-items: center; + gap: 0 8px; + margin: 8px 0; +} + +.helperText { + span { + color: #f98600 !important; + font-size: 14px; + } + svg { + color: #f98600 !important; + } +} diff --git a/src/Pages/Team/constants.ts b/src/Pages/Team/constants.ts index 7f39e88..b563221 100644 --- a/src/Pages/Team/constants.ts +++ b/src/Pages/Team/constants.ts @@ -8,6 +8,10 @@ export const UPDATE_TEAM_DATA = (): string => { return `${window?.config?.BASE_API_URL}/teams`; }; +export const ADD_TEAM_DATA = (): string => { + return `https://mock-server.np.navi-tech.in/houston/teams/add`; +}; + export interface TeamsData { id: string; name: string; diff --git a/src/Pages/Team/index.tsx b/src/Pages/Team/index.tsx index 634f28b..2ddc248 100644 --- a/src/Pages/Team/index.tsx +++ b/src/Pages/Team/index.tsx @@ -1,18 +1,22 @@ import { FC, useEffect, useState } from 'react'; - +import axios from 'axios'; import Typography from '@navi/web-ui/lib/primitives/Typography'; import { toast } from '@navi/web-ui/lib/primitives/Toast'; import FallbackComponent from '@src/components/Fallback'; import { ApiService } from '@src/services/api'; -import { FETCH_TEAM_DATA } from './constants'; +import { ADD_TEAM_DATA, FETCH_TEAM_DATA } from './constants'; import TeamResultsTable from './partials/TeamResultsTable'; - +import CreateTeam from './partials/CreateTeam'; import styles from './Team.module.scss'; +import Button from '@navi/web-ui/lib/primitives/Button'; +import { AddIcon } from '@navi/web-ui/lib/icons'; +import { BorderedInput, ModalDialog } from '@navi/web-ui/lib/primitives'; const Team: FC = () => { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); + const [open, setOpen] = useState(false); const startTeamSearch = (): void => { const endPoint = FETCH_TEAM_DATA; @@ -38,6 +42,10 @@ const Team: FC = () => { startTeamSearch(); }, []); + const createHandler = props => { + setOpen(true); + }; + const returnTable = (): JSX.Element => { if (isLoading) { return ; @@ -63,9 +71,23 @@ const Team: FC = () => { {' '} {data?.length} teams{' '} +
+ +
+ {returnTable()} + + ); }; diff --git a/src/Pages/Team/partials/CreateTeam.tsx b/src/Pages/Team/partials/CreateTeam.tsx new file mode 100644 index 0000000..5c0dd96 --- /dev/null +++ b/src/Pages/Team/partials/CreateTeam.tsx @@ -0,0 +1,121 @@ +import TeamResultsTable from './TeamResultsTable'; +import { TeamsData } from '../constants'; +import { returnFormattedDate } from '@src/services/globalUtils'; +import styles from '../Team.module.scss'; +import { + AccordionGroup, + Accordion, + Typography, +} from '@navi/web-ui/lib/primitives'; +import { useState } from 'react'; +import { ADD_TEAM_DATA } from '../constants'; +import Button from '@navi/web-ui/lib/primitives/Button'; +import { AddIcon, AlertOutlineIcon } from '@navi/web-ui/lib/icons'; +import { BorderedInput, ModalDialog } from '@navi/web-ui/lib/primitives'; +import { toast } from '@navi/web-ui/lib/primitives/Toast'; +import { ApiService } from '@src/services/api'; + +const CreateTeam = props => { + // const [isLoading, setIsLoading] = useState(false); + + const [teamName, setTeamName] = useState(''); + const [teamNameError, setTeamNameError] = useState(''); + + const [validInput, setValidInput] = useState(false); + + const regularExpression = '^[A-Za-z][A-Za-z0-9_]{2,29}$'; + + const validateTeamName = (value: string): void => { + setTeamName(value); + if (!value.match(regularExpression)) { + setValidInput(false); + } else { + setValidInput(true); + } + }; + + const apiCall = (endpoint, teamName) => { + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + resolve({ + status: 200, + }); + // reject( + // { + // 'status': 400, + // } + // ) + }, 1000); + }); + }; + + const addTeamHandler = (): void => { + const endPoint = ADD_TEAM_DATA(); + + apiCall(endPoint, { name: teamName }) + .then((response: any) => { + console.log({ response }); + + props.apicalled(); + props.setOpen(false); + setTeamName(''); + }) + .catch(error => { + console.log('catching error'); + setTeamNameError('Team name already exists'); + // const toastMessage = error; + + // toast.error(toastMessage); + + setTeamName(''); + }); + }; + + const clearErrors = () => { + props.setOpen(false); + setTeamNameError(''); + }; + + return ( +
+ {props.open && ( + props.setOpen(false)} + onClose={clearErrors} + > +
+ + validateTeamName(e.target.value)} + error={teamNameError} + placeholder="New team " + helperTextClasses={styles.helperText} + Icon={ + + } + /> + +
+
+ )} +
+ ); +}; + +export default CreateTeam; diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index 990472c..db35618 100644 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -1,4 +1,4 @@ -import { Typography } from '@navi/web-ui/lib/primitives'; +import { Button, Typography } from '@navi/web-ui/lib/primitives'; import HelpIcon from '@src/assets/HelpIcon'; import styles from './Footer.module.scss'; @@ -22,6 +22,7 @@ const Footer = ({ isExpanded }) => { > Get help on Slack + {/* */} ); From b44b8cbd70eead40c3738d343f9d5bd9280af532 Mon Sep 17 00:00:00 2001 From: pooja Date: Tue, 12 Sep 2023 23:44:29 +0530 Subject: [PATCH 2/4] TP-40366 | Updated add team UI and api integration --- src/Pages/Team/Team.module.scss | 19 ++-- src/Pages/Team/constants.ts | 16 ++- src/Pages/Team/index.tsx | 36 ++++--- src/Pages/Team/partials/CreateTeam.tsx | 131 ++++++++++++++----------- 4 files changed, 116 insertions(+), 86 deletions(-) diff --git a/src/Pages/Team/Team.module.scss b/src/Pages/Team/Team.module.scss index 901a80d..238c1ee 100644 --- a/src/Pages/Team/Team.module.scss +++ b/src/Pages/Team/Team.module.scss @@ -48,8 +48,8 @@ padding: 6px 0 12px 0px; } .create-team-btn { - width: (164px); - height: (36px); + width: 164px; + height: 36px; margin-top: 12px; } .content-wrapper { @@ -109,15 +109,12 @@ display: flex; align-items: center; gap: 0 8px; - margin: 8px 0; + margin-bottom: 24px; + // margin: 8px 0px; } -.helperText { - span { - color: #f98600 !important; - font-size: 14px; - } - svg { - color: #f98600 !important; - } +.email-wrapper { + display: flex; + align-items: center; + gap: 0 8px; } diff --git a/src/Pages/Team/constants.ts b/src/Pages/Team/constants.ts index b563221..0938984 100644 --- a/src/Pages/Team/constants.ts +++ b/src/Pages/Team/constants.ts @@ -1,4 +1,5 @@ export const FETCH_TEAM_DATA = `${window?.config?.BASE_API_URL}/teams`; +export const CREATE_TEAM = `${window?.config?.BASE_API_URL}/houston/teams/add`; export const FETCH_SINGLE_TEAM_DATA = (payload: string): string => { return `${window?.config?.BASE_API_URL}/teams/${payload}`; @@ -8,10 +9,18 @@ export const UPDATE_TEAM_DATA = (): string => { return `${window?.config?.BASE_API_URL}/teams`; }; +export const regularExpression = /^[a-zA-Z][a-zA-Z0-9_ -]{1,48}[a-zA-Z0-9]$/; + +export const emailRegularExpression = /^[a-zA-Z]+\.[a-zA-Z]+@navi\.com$/; + +//TODO: change this to mock server + export const ADD_TEAM_DATA = (): string => { - return `https://mock-server.np.navi-tech.in/houston/teams/add`; + return ``; }; +export const ADD_TEAM = `${window?.config?.BASE_API_URL}/teams/add`; + export interface TeamsData { id: string; name: string; @@ -41,3 +50,8 @@ export const userInputPlaceholders = { 'Email-id': 'email ids', 'Slack user-id': 'slack user ids', }; +export interface CreateTeamProps { + open: boolean; + startTeamSearch: () => void; + setOpen: (open: boolean) => void; +} diff --git a/src/Pages/Team/index.tsx b/src/Pages/Team/index.tsx index 2ddc248..2d521e3 100644 --- a/src/Pages/Team/index.tsx +++ b/src/Pages/Team/index.tsx @@ -1,17 +1,16 @@ import { FC, useEffect, useState } from 'react'; -import axios from 'axios'; + import Typography from '@navi/web-ui/lib/primitives/Typography'; import { toast } from '@navi/web-ui/lib/primitives/Toast'; import FallbackComponent from '@src/components/Fallback'; import { ApiService } from '@src/services/api'; -import { ADD_TEAM_DATA, FETCH_TEAM_DATA } from './constants'; +import { FETCH_TEAM_DATA } from './constants'; import TeamResultsTable from './partials/TeamResultsTable'; import CreateTeam from './partials/CreateTeam'; import styles from './Team.module.scss'; import Button from '@navi/web-ui/lib/primitives/Button'; import { AddIcon } from '@navi/web-ui/lib/icons'; -import { BorderedInput, ModalDialog } from '@navi/web-ui/lib/primitives'; const Team: FC = () => { const [data, setData] = useState([]); @@ -38,11 +37,14 @@ const Team: FC = () => { }); }; + const userData = JSON.parse(localStorage.getItem('user-data') || '{}'); + const userRole = userData.roles || []; + useEffect(() => { startTeamSearch(); }, []); - const createHandler = props => { + const createHandler = () => { setOpen(true); }; @@ -72,22 +74,28 @@ const Team: FC = () => { {data?.length} teams{' '}
- + {userRole.includes('Admin') && ( + + )}
{returnTable()} - + ); }; diff --git a/src/Pages/Team/partials/CreateTeam.tsx b/src/Pages/Team/partials/CreateTeam.tsx index 5c0dd96..da5b4cb 100644 --- a/src/Pages/Team/partials/CreateTeam.tsx +++ b/src/Pages/Team/partials/CreateTeam.tsx @@ -1,86 +1,86 @@ import TeamResultsTable from './TeamResultsTable'; -import { TeamsData } from '../constants'; +import { CREATE_TEAM, TeamsData } from '../constants'; import { returnFormattedDate } from '@src/services/globalUtils'; import styles from '../Team.module.scss'; -import { - AccordionGroup, - Accordion, - Typography, -} from '@navi/web-ui/lib/primitives'; +import { Typography } from '@navi/web-ui/lib/primitives'; import { useState } from 'react'; import { ADD_TEAM_DATA } from '../constants'; -import Button from '@navi/web-ui/lib/primitives/Button'; -import { AddIcon, AlertOutlineIcon } from '@navi/web-ui/lib/icons'; +import { AlertOutlineIcon } from '@navi/web-ui/lib/icons'; import { BorderedInput, ModalDialog } from '@navi/web-ui/lib/primitives'; import { toast } from '@navi/web-ui/lib/primitives/Toast'; +import { regularExpression, emailRegularExpression } from '../constants'; +import { CreateTeamProps } from '../constants'; import { ApiService } from '@src/services/api'; -const CreateTeam = props => { - // const [isLoading, setIsLoading] = useState(false); - +const CreateTeam: React.FC = ({ + open, + startTeamSearch, + setOpen, +}) => { const [teamName, setTeamName] = useState(''); const [teamNameError, setTeamNameError] = useState(''); - - const [validInput, setValidInput] = useState(false); - - const regularExpression = '^[A-Za-z][A-Za-z0-9_]{2,29}$'; + const [emailError, setEmailError] = useState(''); + const [email, setEmail] = useState(''); const validateTeamName = (value: string): void => { - setTeamName(value); - if (!value.match(regularExpression)) { - setValidInput(false); + value = value.trim(); + if (!regularExpression.test(value)) { + setTeamNameError('Please enter a valid team name'); } else { - setValidInput(true); + setTeamNameError(''); } }; - const apiCall = (endpoint, teamName) => { - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - resolve({ - status: 200, - }); - // reject( - // { - // 'status': 400, - // } - // ) - }, 1000); - }); + const validateEmail = (value: string): void => { + if (!emailRegularExpression.test(value)) { + setEmailError('This is not a Navi e-mail ID'); + } else { + setEmailError(''); + } + }; + + const handleTeamNameChange = (e: React.ChangeEvent) => { + const inputValue = e.target.value; + setTeamName(inputValue); + validateTeamName(inputValue); + }; + const handleEmailChange = (e: React.ChangeEvent) => { + const inputValue = e.target.value; + setEmail(inputValue); + validateEmail(inputValue); }; const addTeamHandler = (): void => { - const endPoint = ADD_TEAM_DATA(); - - apiCall(endPoint, { name: teamName }) + ApiService.post(CREATE_TEAM, { name: teamName, manager_email: email }) .then((response: any) => { - console.log({ response }); - - props.apicalled(); - props.setOpen(false); + toast.success('Team added successfully'); + startTeamSearch(); + setOpen(false); setTeamName(''); }) .catch(error => { - console.log('catching error'); - setTeamNameError('Team name already exists'); - // const toastMessage = error; - - // toast.error(toastMessage); - - setTeamName(''); + const toastMessage = `${ + error?.response?.data?.error?.message + ? `${error?.response?.data?.error?.message},` + : 'Something went wrong. Please try again later' + }`; + toast.error(toastMessage); }); }; const clearErrors = () => { - props.setOpen(false); + setOpen(false); setTeamNameError(''); + setEmailError(''); + setTeamName(''); + setEmail(''); }; return ( -
- {props.open && ( +
+ {open && ( { { label: 'Submit', onClick: addTeamHandler, - disabled: !validInput, + disabled: !!teamNameError || !!emailError || !teamName || !email, }, ]} - header="Enter team name " - // onClose={() => props.setOpen(false)} + header="Set up new team " onClose={clearErrors} >
validateTeamName(e.target.value)} + onChange={handleTeamNameChange} error={teamNameError} - placeholder="New team " - helperTextClasses={styles.helperText} - Icon={ - - } + Icon={} + placeholder="E.g. NaviPay_Operations" + /> + +
+ +
+ + } />
@@ -117,5 +129,4 @@ const CreateTeam = props => {
); }; - export default CreateTeam; From 41fe55c8634c47104ff7d99b5bc7c1d1f4d8ed7c Mon Sep 17 00:00:00 2001 From: pooja Date: Wed, 13 Sep 2023 17:21:22 +0530 Subject: [PATCH 3/4] TP-40366 | resolved PR reviews --- package.json | 2 -- src/Pages/Team/Hook.tsx | 11 +++++++++++ src/Pages/Team/Team.module.scss | 1 - src/Pages/Team/constants.ts | 8 -------- src/Pages/Team/index.tsx | 11 ++++------- src/components/Footer/index.tsx | 3 +-- 6 files changed, 16 insertions(+), 20 deletions(-) create mode 100644 src/Pages/Team/Hook.tsx diff --git a/package.json b/package.json index cc8ad44..a9d8a63 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,6 @@ ] }, "dependencies": { - "@headlessui/react": "^1.7.17", - "@heroicons/react": "^2.0.18", "@navi/web-ui": "^1.49.8", "@super-app/dark-knight": "^1.0.6", "axios": "^1.3.4", diff --git a/src/Pages/Team/Hook.tsx b/src/Pages/Team/Hook.tsx new file mode 100644 index 0000000..f919051 --- /dev/null +++ b/src/Pages/Team/Hook.tsx @@ -0,0 +1,11 @@ +import { useState, useEffect } from 'react'; +export const Hook = () => { + const [userRole, setUserRole] = useState(''); + + useEffect(() => { + const userData = JSON.parse(localStorage.getItem('user-data') || '{}'); + setUserRole(userData?.roles || []); + }, []); + + return userRole; +}; diff --git a/src/Pages/Team/Team.module.scss b/src/Pages/Team/Team.module.scss index 238c1ee..1bf33ed 100644 --- a/src/Pages/Team/Team.module.scss +++ b/src/Pages/Team/Team.module.scss @@ -110,7 +110,6 @@ align-items: center; gap: 0 8px; margin-bottom: 24px; - // margin: 8px 0px; } .email-wrapper { diff --git a/src/Pages/Team/constants.ts b/src/Pages/Team/constants.ts index 0938984..a62e048 100644 --- a/src/Pages/Team/constants.ts +++ b/src/Pages/Team/constants.ts @@ -13,14 +13,6 @@ export const regularExpression = /^[a-zA-Z][a-zA-Z0-9_ -]{1,48}[a-zA-Z0-9]$/; export const emailRegularExpression = /^[a-zA-Z]+\.[a-zA-Z]+@navi\.com$/; -//TODO: change this to mock server - -export const ADD_TEAM_DATA = (): string => { - return ``; -}; - -export const ADD_TEAM = `${window?.config?.BASE_API_URL}/teams/add`; - export interface TeamsData { id: string; name: string; diff --git a/src/Pages/Team/index.tsx b/src/Pages/Team/index.tsx index 2d521e3..2257ce7 100644 --- a/src/Pages/Team/index.tsx +++ b/src/Pages/Team/index.tsx @@ -1,8 +1,6 @@ import { FC, useEffect, useState } from 'react'; - import Typography from '@navi/web-ui/lib/primitives/Typography'; import { toast } from '@navi/web-ui/lib/primitives/Toast'; - import FallbackComponent from '@src/components/Fallback'; import { ApiService } from '@src/services/api'; import { FETCH_TEAM_DATA } from './constants'; @@ -11,12 +9,14 @@ import CreateTeam from './partials/CreateTeam'; import styles from './Team.module.scss'; import Button from '@navi/web-ui/lib/primitives/Button'; import { AddIcon } from '@navi/web-ui/lib/icons'; - +import { Hook } from './Hook'; const Team: FC = () => { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [open, setOpen] = useState(false); + const Role = Hook(); + const startTeamSearch = (): void => { const endPoint = FETCH_TEAM_DATA; setIsLoading(true); @@ -37,9 +37,6 @@ const Team: FC = () => { }); }; - const userData = JSON.parse(localStorage.getItem('user-data') || '{}'); - const userRole = userData.roles || []; - useEffect(() => { startTeamSearch(); }, []); @@ -74,7 +71,7 @@ const Team: FC = () => { {data?.length} teams{' '}
- {userRole.includes('Admin') && ( + {Role.includes('Admin') && ( */}
); From 29b89542c547bc2de66c9c6ed04de4dd6c1dbe0d Mon Sep 17 00:00:00 2001 From: pooja Date: Wed, 13 Sep 2023 18:06:11 +0530 Subject: [PATCH 4/4] TP40366 | committing pr review changes --- package.json | 1 - src/Pages/Team/Hook.tsx | 2 +- src/Pages/Team/index.tsx | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a9d8a63..20554c9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-modal": "^3.16.1", "react-router-dom": "^6.8.2", "sass": "^1.58.3" }, diff --git a/src/Pages/Team/Hook.tsx b/src/Pages/Team/Hook.tsx index f919051..aa42c22 100644 --- a/src/Pages/Team/Hook.tsx +++ b/src/Pages/Team/Hook.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -export const Hook = () => { +export const useAuthData = () => { const [userRole, setUserRole] = useState(''); useEffect(() => { diff --git a/src/Pages/Team/index.tsx b/src/Pages/Team/index.tsx index 2257ce7..b06ff90 100644 --- a/src/Pages/Team/index.tsx +++ b/src/Pages/Team/index.tsx @@ -9,13 +9,13 @@ import CreateTeam from './partials/CreateTeam'; import styles from './Team.module.scss'; import Button from '@navi/web-ui/lib/primitives/Button'; import { AddIcon } from '@navi/web-ui/lib/icons'; -import { Hook } from './Hook'; +import { useAuthData } from './Hook'; const Team: FC = () => { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [open, setOpen] = useState(false); - const Role = Hook(); + const Role = useAuthData(); const startTeamSearch = (): void => { const endPoint = FETCH_TEAM_DATA;