From 36e0aed6f4a4b44b078349e3a23319216dd579f5 Mon Sep 17 00:00:00 2001 From: Charles Nwankwo <39612820+Xavier-Charles@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:41:28 +0100 Subject: [PATCH] feat: Create Portfolio (#253) --- packages/frontend/src/MobileApp.tsx | 22 +++- .../frontend/src/api/services/coins/types.ts | 6 +- packages/frontend/src/api/types/portfolio.ts | 9 ++ packages/frontend/src/api/types/primitives.ts | 2 + packages/frontend/src/assets/icons/close.svg | 4 +- packages/frontend/src/assets/icons/copy.svg | 11 ++ packages/frontend/src/assets/icons/hand.svg | 7 ++ packages/frontend/src/assets/icons/wallet.svg | 5 + .../src/containers/base/BaseContainerMenu.tsx | 5 +- .../navigation/NavBottom.tsx | 74 ------------ .../portfolio/AddHolding.tsx | 98 +++++++++++++++ .../portfolio/SelectHoldingCoin.tsx | 91 ++++++++++++++ .../frontend/src/mobile-pages/add-holding.tsx | 112 ++++++++++++++++++ .../frontend/src/mobile-pages/add-wallet.tsx | 100 ++++++++++++++++ .../src/mobile-pages/connect-wallet.tsx | 40 +++++++ .../frontend/src/mobile-pages/portfolio.tsx | 74 ++++++++++++ packages/ui-kit/index.ts | 4 + packages/ui-kit/src/assets/svg/Info2.svg | 5 + packages/ui-kit/src/assets/svg/close3.svg | 4 +- packages/ui-kit/src/assets/svg/search.svg | 4 +- .../src/components/buttons/TabButton.tsx | 2 +- .../ui-kit/src/components/dialog/Dialog.tsx | 2 +- .../ui-kit/src/components/tabs/TabsBar.tsx | 2 +- .../src/mobile-components/button/buttons.tsx | 42 +++++++ .../form-elements/FormElements.tsx | 44 ++++--- .../src/mobile-components/pager/Pager.tsx | 14 ++- 26 files changed, 678 insertions(+), 105 deletions(-) create mode 100644 packages/frontend/src/assets/icons/copy.svg create mode 100644 packages/frontend/src/assets/icons/hand.svg create mode 100644 packages/frontend/src/assets/icons/wallet.svg delete mode 100644 packages/frontend/src/mobile-components/navigation/NavBottom.tsx create mode 100644 packages/frontend/src/mobile-components/portfolio/AddHolding.tsx create mode 100644 packages/frontend/src/mobile-components/portfolio/SelectHoldingCoin.tsx create mode 100644 packages/frontend/src/mobile-pages/add-holding.tsx create mode 100644 packages/frontend/src/mobile-pages/add-wallet.tsx create mode 100644 packages/frontend/src/mobile-pages/connect-wallet.tsx create mode 100644 packages/frontend/src/mobile-pages/portfolio.tsx create mode 100644 packages/ui-kit/src/assets/svg/Info2.svg diff --git a/packages/frontend/src/MobileApp.tsx b/packages/frontend/src/MobileApp.tsx index f9e86506..2496c0d8 100644 --- a/packages/frontend/src/MobileApp.tsx +++ b/packages/frontend/src/MobileApp.tsx @@ -22,12 +22,19 @@ import "./customIonicStyles.scss"; const SuperfeedPage = lazyRetry(() => import("./mobile-pages/superfeed")); const Placeholder = lazyRetry(() => import("./mobile-pages/placeholder")); const AuthPage = lazyRetry(() => import("./mobile-pages/auth")); +const FiltersPage = lazyRetry(() => import("./mobile-pages/filters")); +const PortfolioPage = lazyRetry(() => import("./mobile-pages/portfolio")); const NotificationsPage = lazyRetry( () => import("./mobile-pages/notifications") ); const UserSettingsPage = lazyRetry( () => import("./mobile-pages/user-settings") ); +const ConnectWalletPage = lazyRetry( + () => import("./mobile-pages/connect-wallet") +); +const AddWalletPage = lazyRetry(() => import("./mobile-pages/add-wallet")); +const AddHoldingPage = lazyRetry(() => import("./mobile-pages/add-holding")); const CustomNavTab: React.FC<{ label: string; @@ -78,8 +85,21 @@ const TabNavigator: React.FC = () => { - + + + + + + + + + + diff --git a/packages/frontend/src/api/services/coins/types.ts b/packages/frontend/src/api/services/coins/types.ts index db7757d4..e4ab580a 100644 --- a/packages/frontend/src/api/services/coins/types.ts +++ b/packages/frontend/src/api/services/coins/types.ts @@ -19,7 +19,11 @@ export type TRemoteCoin = TBaseCoin & { */ // /coins/ -export type TGetCoinsRequest = { tags?: string; limit?: number } | void; +export type TGetCoinsRequest = { + tags?: string; + limit?: number; + page?: number; +} | void; export type TGetCoinsRawResponse = TPagination & { results: TRemoteCoin[]; }; diff --git a/packages/frontend/src/api/types/portfolio.ts b/packages/frontend/src/api/types/portfolio.ts index 10be34e7..32439137 100644 --- a/packages/frontend/src/api/types/portfolio.ts +++ b/packages/frontend/src/api/types/portfolio.ts @@ -1,3 +1,5 @@ +import { TCoin } from "./primitives"; + export type TPortfolioToken = { id: string; networkId: number; @@ -33,3 +35,10 @@ export type TPortfolio = { updatedAt: string; token: TPortfolioToken; }; + +// TODO: Update this type to match the API response +export type THolding = { + coin: TCoin; + amount: number; + date: Date; +}; diff --git a/packages/frontend/src/api/types/primitives.ts b/packages/frontend/src/api/types/primitives.ts index d828da0b..5353807d 100644 --- a/packages/frontend/src/api/types/primitives.ts +++ b/packages/frontend/src/api/types/primitives.ts @@ -93,6 +93,8 @@ export type TCryptoAccount = { // networkId: number | undefined; address: string | null; ens?: string | null; + // name given by user + name?: string | null; }; export enum ECookieChoice { diff --git a/packages/frontend/src/assets/icons/close.svg b/packages/frontend/src/assets/icons/close.svg index 787ab1d6..91531dfc 100644 --- a/packages/frontend/src/assets/icons/close.svg +++ b/packages/frontend/src/assets/icons/close.svg @@ -1,4 +1,4 @@ - - + + diff --git a/packages/frontend/src/assets/icons/copy.svg b/packages/frontend/src/assets/icons/copy.svg new file mode 100644 index 00000000..28485ba1 --- /dev/null +++ b/packages/frontend/src/assets/icons/copy.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/frontend/src/assets/icons/hand.svg b/packages/frontend/src/assets/icons/hand.svg new file mode 100644 index 00000000..f5f9c14e --- /dev/null +++ b/packages/frontend/src/assets/icons/hand.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/packages/frontend/src/assets/icons/wallet.svg b/packages/frontend/src/assets/icons/wallet.svg new file mode 100644 index 00000000..95826a65 --- /dev/null +++ b/packages/frontend/src/assets/icons/wallet.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/packages/frontend/src/containers/base/BaseContainerMenu.tsx b/packages/frontend/src/containers/base/BaseContainerMenu.tsx index 5ccc1867..527f802c 100644 --- a/packages/frontend/src/containers/base/BaseContainerMenu.tsx +++ b/packages/frontend/src/containers/base/BaseContainerMenu.tsx @@ -223,7 +223,10 @@ const BaseContainerMenu: FC = ({ "cursor-not-allowed bg-transparent opacity-50" )} > - +
Remove Widget diff --git a/packages/frontend/src/mobile-components/navigation/NavBottom.tsx b/packages/frontend/src/mobile-components/navigation/NavBottom.tsx deleted file mode 100644 index 28e018c5..00000000 --- a/packages/frontend/src/mobile-components/navigation/NavBottom.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { twMerge } from "@alphaday/ui-kit"; -import { ReactComponent as ExploreSVG } from "src/assets/svg/explore.svg"; -import { ReactComponent as MarketsSVG } from "src/assets/svg/markets.svg"; -import { ReactComponent as PortfolioSVG } from "src/assets/svg/portfolio.svg"; -import { ReactComponent as SuperfeedSVG } from "src/assets/svg/superfeed.svg"; - -const navigation = [ - { - name: "Superfeed", - href: "#", - current: true, - hasNew: true, - icon: , - }, - { - name: "Markets", - href: "#", - current: false, - hasNew: false, - icon: , - }, - { - name: "Portfolio", - href: "#", - current: false, - hasNew: true, - - icon: , - }, - { - name: "Explore", - href: "#", - current: false, - hasNew: false, - icon: , - }, -]; - -const NavItem = ({ href, icon, current, name }: (typeof navigation)[0]) => ( - - - {icon} - - - {name} - - -); - -export const NavBottom = () => { - return ( -
-
- {navigation.map((item) => ( - - ))} -
-
- ); -}; diff --git a/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx b/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx new file mode 100644 index 00000000..316e2ee2 --- /dev/null +++ b/packages/frontend/src/mobile-components/portfolio/AddHolding.tsx @@ -0,0 +1,98 @@ +import { FC } from "react"; +import { FormInput, Pager, ScrollBar } from "@alphaday/ui-kit"; +import moment from "moment"; +import { useHistory } from "react-router"; +import { TCoin, THolding } from "src/api/types"; + +interface IAddHolding { + selectedCoin: TCoin; + setSelectedCoin: React.Dispatch>; + holding: THolding | undefined; + setHolding: React.Dispatch>; +} + +const AddHolding: FC = ({ + selectedCoin, + setSelectedCoin, + holding, + setHolding, +}) => { + const history = useHistory(); + + const defaultHolding: THolding = { + coin: selectedCoin, + amount: 0, + date: new Date(), + }; + + const handleAmountChange = (e: React.ChangeEvent) => { + setHolding((prev) => ({ + ...(prev || defaultHolding), + amount: parseInt(e.target.value, 10), + })); + }; + const handleDateChange = (e: React.ChangeEvent) => { + setHolding((prev) => ({ + ...(prev || defaultHolding), + date: new Date(e.target.value), + })); + }; + + return ( + + + {" "} + + {selectedCoin.ticker} + {" "} + {selectedCoin.name} + + } + handleClose={() => + history.length > 1 ? history.goBack() : history.push("/") + } + handleBack={() => setSelectedCoin(undefined)} + /> +
+ +
+ +
+
+
+ +
+
+ ); +}; + +export default AddHolding; diff --git a/packages/frontend/src/mobile-components/portfolio/SelectHoldingCoin.tsx b/packages/frontend/src/mobile-components/portfolio/SelectHoldingCoin.tsx new file mode 100644 index 00000000..81192fd5 --- /dev/null +++ b/packages/frontend/src/mobile-components/portfolio/SelectHoldingCoin.tsx @@ -0,0 +1,91 @@ +import React, { FC, FormEvent } from "react"; +import { Input, Pager, ScrollBar, Spinner } from "@alphaday/ui-kit"; +import { useHistory } from "react-router"; +import { TCoin } from "src/api/types"; +import { ReactComponent as ChevronSVG } from "src/assets/icons/chevron-right.svg"; +import { ReactComponent as SearchSVG } from "src/assets/svg/search.svg"; + +interface ISelectHoldingCoin { + onScroll: ({ currentTarget }: FormEvent) => void; + onInputChange: (e: React.ChangeEvent) => void; + inputValue: string; + isLoadingCoinsData: boolean; + coins: TCoin[] | undefined; + setSelectedCoin: React.Dispatch>; +} + +const SelectHoldingCoin: FC = ({ + onScroll, + onInputChange, + inputValue, + isLoadingCoinsData, + coins, + setSelectedCoin, +}) => { + const history = useHistory(); + + return ( + + + history.length > 1 ? history.goBack() : history.push("/") + } + /> +

+ Search or select the desired crypto coin that you have in your + portfolio. +

+
+ +
+

Or simply select from the list below.

+ +
+ {isLoadingCoinsData ? ( +
+ +
+ ) : ( + coins?.map((coin) => ( +
{ + setSelectedCoin(coin); + }} + role="button" + tabIndex={0} + key={coin.id} + className="flex items-center justify-between py-4 border-t border-borderLine cursor-pointer hover:bg-backgroundVariant100" + > +
+ {coin.name} + + {coin.name} + +
+ +
+ )) + )} +
+
+ ); +}; + +export default SelectHoldingCoin; diff --git a/packages/frontend/src/mobile-pages/add-holding.tsx b/packages/frontend/src/mobile-pages/add-holding.tsx new file mode 100644 index 00000000..8784234a --- /dev/null +++ b/packages/frontend/src/mobile-pages/add-holding.tsx @@ -0,0 +1,112 @@ +import { FormEvent, useCallback, useEffect, useMemo, useState } from "react"; +import { usePagination } from "src/api/hooks"; +import { useGetCoinsQuery } from "src/api/services"; +import { TCoin, THolding } from "src/api/types"; +import { + buildUniqueItemList, + shouldFetchMoreItems, +} from "src/api/utils/itemUtils"; + +import AddHolding from "src/mobile-components/portfolio/AddHolding"; +import SelectHoldingCoin from "src/mobile-components/portfolio/SelectHoldingCoin"; +import CONFIG from "src/config"; + +const INITIAL_PAGE = 1; + +const AddHoldingPage = () => { + const [searchText, setSearchText] = useState(""); + const [currentPage, setCurrentPage] = useState(INITIAL_PAGE); + const [coins, setCoins] = useState(); + const [selectedCoin, setSelectedCoin] = useState(); + const [holding, setholding] = useState(); + + const { + data: coinsDataResponse, + isLoading: isLoadingCoinsData, + isSuccess, + } = useGetCoinsQuery({ + page: currentPage, + tags: undefined, + limit: CONFIG.WIDGETS.MARKET.QUERY_HARD_LIMIT, + }); + + const { nextPage, handleNextPage } = usePagination( + coinsDataResponse?.links, + CONFIG.UI.BOARD_LIBRARY.MAX_PAGE_NUMBER, + isSuccess + ); + + const coinsData = useMemo( + () => coinsDataResponse?.results ?? [], + [coinsDataResponse] + ); + + const handleInputChange = (e: React.ChangeEvent) => { + setSearchText(e.target.value); + }; + + const handleScrollEvent = useCallback( + ({ currentTarget }: FormEvent) => { + if (shouldFetchMoreItems(currentTarget)) { + handleNextPage("next"); + } + }, + [handleNextPage] + ); + + useEffect(() => { + if (coinsData !== undefined) { + setCoins((prevItems) => { + if (prevItems) { + const newItems = buildUniqueItemList([ + ...prevItems, + ...coinsData, + ]); + return newItems; + } + return coinsData; + }); + } + }, [coinsData]); + + // set current page 350ms after next page is set. + // RTK should cache requests, so we don't need to be too careful about rerenders. + useEffect(() => { + if (nextPage === undefined) { + return () => null; + } + const timeout = setTimeout(() => { + setCurrentPage(nextPage); + }, 350); + return () => { + clearTimeout(timeout); + }; + }, [nextPage]); + + if (selectedCoin !== undefined) { + return ( +
+ +
+ ); + } + return ( +
+ +
+ ); +}; + +export default AddHoldingPage; diff --git a/packages/frontend/src/mobile-pages/add-wallet.tsx b/packages/frontend/src/mobile-pages/add-wallet.tsx new file mode 100644 index 00000000..93cbaf45 --- /dev/null +++ b/packages/frontend/src/mobile-pages/add-wallet.tsx @@ -0,0 +1,100 @@ +import { useState } from "react"; +import { FormInput, MiniDialog, Pager } from "@alphaday/ui-kit"; +import { useHistory } from "react-router"; +import { usePortfolioAccount } from "src/api/hooks"; +import { validateEthAddr } from "src/api/utils/accountUtils"; +import { ReactComponent as GreenCheckSVG } from "src/assets/icons/green-check.svg"; + +type TWalletInfo = { + name: string; + address: string; +}; + +const AddWalletPage = () => { + const history = useHistory(); + const [isWalletAdded, setIsWalletAdded] = useState(false); + const [walletInfo, setwalletInfo] = useState({ + name: "", + address: "", + }); + + // const handleAddNewWallet = (w: TWalletInfo) => {}; + + const handleChange = (e: React.ChangeEvent) => { + setwalletInfo((prev) => ({ + ...prev, + [e.target.name]: e.target.value, + })); + }; + const { addPortfolioAccount } = usePortfolioAccount(); + + const handleAddWallet = () => { + addPortfolioAccount(walletInfo); + setIsWalletAdded(true); + }; + return ( + <> + + history.length > 1 ? history.goBack() : history.push("/") + } + /> +
+ +
+ +
+
+
+ +
+ } + title="CONGRATS" + onActionClick={() => { + setIsWalletAdded(false); + history.push("/portfolio"); + }} + > +
+ Your account has been created! +
+
+ + ); +}; + +export default AddWalletPage; diff --git a/packages/frontend/src/mobile-pages/connect-wallet.tsx b/packages/frontend/src/mobile-pages/connect-wallet.tsx new file mode 100644 index 00000000..454ace2e --- /dev/null +++ b/packages/frontend/src/mobile-pages/connect-wallet.tsx @@ -0,0 +1,40 @@ +import { OutlineButton, Pager } from "@alphaday/ui-kit"; +import { useHistory } from "react-router"; +import { ReactComponent as MetamaskSVG } from "src/assets/icons/metamask.svg"; +import { ReactComponent as WalletConnectSVG } from "src/assets/icons/wallet-connect.svg"; + +const ConnectWalletPage = () => { + const history = useHistory(); + return ( + <> + + history.length > 1 ? history.goBack() : history.push("/") + } + /> +
+ Select your preferred wallet provider to conect to your + portfolio +
+
+ } + onClick={() => {}} + isAuthenticated + /> + } + onClick={() => {}} + isAuthenticated + /> +
+ + ); +}; + +export default ConnectWalletPage; diff --git a/packages/frontend/src/mobile-pages/portfolio.tsx b/packages/frontend/src/mobile-pages/portfolio.tsx new file mode 100644 index 00000000..10a2e56a --- /dev/null +++ b/packages/frontend/src/mobile-pages/portfolio.tsx @@ -0,0 +1,74 @@ +import { FC } from "react"; +import { OutlineButton, Pager } from "@alphaday/ui-kit"; +import { useHistory } from "react-router"; +import { useAuth } from "src/api/hooks"; +import { ReactComponent as CloseSVG } from "src/assets/icons/close.svg"; +import { ReactComponent as CopySVG } from "src/assets/icons/copy.svg"; +import { ReactComponent as HandSVG } from "src/assets/icons/hand.svg"; +import { ReactComponent as WalletSVG } from "src/assets/icons/wallet.svg"; +import { ReactComponent as InfoSVG } from "src/assets/svg/info2.svg"; + +const TopSection: FC<{ isAuthenticated: boolean }> = ({ isAuthenticated }) => { + if (isAuthenticated) { + return ( +
+ Add your portfolio for a quick overview and easy swaps. +
+ ); + } + return ( +
+ +
+ + Sign up or log in to get started + + + Log in or sign up to add your portfolio. + +
+ +
+ ); +}; + +const PortfolioPage = () => { + const history = useHistory(); + const { isAuthenticated } = useAuth(); + return ( + <> + + history.length > 1 ? history.goBack() : history.push("/") + } + /> + +
+ } + onClick={() => history.push("/portfolio/add-wallet")} + isAuthenticated={isAuthenticated} + /> + } + onClick={() => history.push("/portfolio/connect-wallet")} + isAuthenticated={isAuthenticated} + /> + } + onClick={() => history.push("/portfolio/add-holding")} + isAuthenticated={isAuthenticated} + /> +
+ + ); +}; + +export default PortfolioPage; diff --git a/packages/ui-kit/index.ts b/packages/ui-kit/index.ts index 9b5b858c..b0abeabb 100644 --- a/packages/ui-kit/index.ts +++ b/packages/ui-kit/index.ts @@ -91,6 +91,8 @@ import { } from "./src/components/view-tab-menu/ViewTabMenu"; import { breakpoints } from "./src/globalStyles/breakpoints"; import { themeColors } from "./src/globalStyles/themes"; +import { OutlineButton } from "./src/mobile-components/button/buttons"; +import { FormInput } from "./src/mobile-components/form-elements/FormElements"; import { Pager } from "./src/mobile-components/pager/Pager"; export type { TViewTabMenuOption, DatesSetArg, EventClickArg, TDatePos }; @@ -176,4 +178,6 @@ export { Disclosure, Transition, MiniDialog, + OutlineButton, + FormInput, }; diff --git a/packages/ui-kit/src/assets/svg/Info2.svg b/packages/ui-kit/src/assets/svg/Info2.svg new file mode 100644 index 00000000..4aef7036 --- /dev/null +++ b/packages/ui-kit/src/assets/svg/Info2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/ui-kit/src/assets/svg/close3.svg b/packages/ui-kit/src/assets/svg/close3.svg index 093923b0..607ae6f6 100644 --- a/packages/ui-kit/src/assets/svg/close3.svg +++ b/packages/ui-kit/src/assets/svg/close3.svg @@ -1,4 +1,4 @@ - - + + diff --git a/packages/ui-kit/src/assets/svg/search.svg b/packages/ui-kit/src/assets/svg/search.svg index 917c3b90..9101efb6 100644 --- a/packages/ui-kit/src/assets/svg/search.svg +++ b/packages/ui-kit/src/assets/svg/search.svg @@ -1,4 +1,4 @@ - - + + \ No newline at end of file diff --git a/packages/ui-kit/src/components/buttons/TabButton.tsx b/packages/ui-kit/src/components/buttons/TabButton.tsx index 62c919c7..4bde41e7 100644 --- a/packages/ui-kit/src/components/buttons/TabButton.tsx +++ b/packages/ui-kit/src/components/buttons/TabButton.tsx @@ -88,7 +88,7 @@ export const TabButton: FC = ({ {children} {(variant === "removable" || variant === "transparent") && ( { const handler = async () => { e.stopPropagation(); diff --git a/packages/ui-kit/src/components/dialog/Dialog.tsx b/packages/ui-kit/src/components/dialog/Dialog.tsx index ce6eb7d1..496d25f7 100644 --- a/packages/ui-kit/src/components/dialog/Dialog.tsx +++ b/packages/ui-kit/src/components/dialog/Dialog.tsx @@ -84,7 +84,7 @@ export const Dialog: FC = ({ className="border-borderLine bg-background flex h-[34px] w-[34px] items-center justify-center rounded-[50%] border-2 border-solid" {...closeButtonProps} > - + )}
diff --git a/packages/ui-kit/src/components/tabs/TabsBar.tsx b/packages/ui-kit/src/components/tabs/TabsBar.tsx index 61d773de..2c9eb520 100644 --- a/packages/ui-kit/src/components/tabs/TabsBar.tsx +++ b/packages/ui-kit/src/components/tabs/TabsBar.tsx @@ -80,7 +80,7 @@ export const TabsBar: FC<{ {tab.label} {tab.removable && ( { const handler = async () => { e.stopPropagation(); diff --git a/packages/ui-kit/src/mobile-components/button/buttons.tsx b/packages/ui-kit/src/mobile-components/button/buttons.tsx index 9f638424..00ea5fb6 100644 --- a/packages/ui-kit/src/mobile-components/button/buttons.tsx +++ b/packages/ui-kit/src/mobile-components/button/buttons.tsx @@ -61,3 +61,45 @@ export const TagButton: FC<{ ); }; + +export const OutlineButton: FC<{ + title: string; + subtext: string; + icon: React.ReactNode; + onClick: () => void; + isAuthenticated: boolean; +}> = ({ onClick, title, subtext, icon, isAuthenticated }) => { + return ( +
+
+ + {icon} + {title} + + + {subtext} + +
+
+ ); +}; diff --git a/packages/ui-kit/src/mobile-components/form-elements/FormElements.tsx b/packages/ui-kit/src/mobile-components/form-elements/FormElements.tsx index 2a0a19c6..5ea4d22b 100644 --- a/packages/ui-kit/src/mobile-components/form-elements/FormElements.tsx +++ b/packages/ui-kit/src/mobile-components/form-elements/FormElements.tsx @@ -6,36 +6,48 @@ import { ReactComponent as ChevronUpDownSVG } from "../../assets/svg/chevron-up- interface IFormElement { label: string; + placeholder?: string; + defaultValue?: string; + value: string | number; placeholder: string; defaultValue?: string; value: string; onChange: ChangeEventHandler; disabled?: boolean; - classNames?: string; + className?: string; } interface IFormInput extends IFormElement { errorMsg?: string; - type: "text" | "email" | "password"; + type: "text" | "email" | "password" | "number" | "date"; + name?: string; + min?: number; } export const FormInput: FC = ({ label, placeholder, defaultValue, - classNames, + className, value, onChange, disabled, type = "text", errorMsg, + name, + min, }) => { const [hasBlured, sethasBlured] = useState(false); return ( -
-
+
+
@@ -43,26 +55,30 @@ export const FormInput: FC = ({
sethasBlured(true)} className={twMerge( "block w-full bg-backgroundVariant100 rounded-md border-0 py-1.5 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200 ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 placeholder:text-gray-400", - classNames, + className, errorMsg && hasBlured && - "ring-red-400 text-red-900 placeholder-red-300 focus:ring-red-500" + "ring-red-400 placeholder-red-300 focus:ring-red-500" )} placeholder={placeholder} defaultValue={defaultValue} aria-invalid="true" aria-describedby="email-error" disabled={disabled} + min={min} />
{errorMsg && hasBlured && ( -

+

{errorMsg}

)} @@ -74,7 +90,7 @@ export const FormTextArea: FC> = ({ label, placeholder, defaultValue, - classNames, + className, value, onChange, disabled, @@ -94,7 +110,7 @@ export const FormTextArea: FC> = ({ id="comment" className={twMerge( "block w-full bg-backgroundVariant100 rounded-md border-0 py-1.5 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-50 disabled:ring-gray-200 text-primary shadow-sm ring-1 ring-inset placeholder:text-gray-400 focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6", - classNames + className )} defaultValue={defaultValue} value={value} @@ -124,7 +140,7 @@ export const FormSelect: FC = ({ options, placeholder, defaultValue, - classNames, + className, selected, onChange, disabled, @@ -137,7 +153,7 @@ export const FormSelect: FC = ({ onChange={onChange} > {({ open }) => ( -
+
{label} diff --git a/packages/ui-kit/src/mobile-components/pager/Pager.tsx b/packages/ui-kit/src/mobile-components/pager/Pager.tsx index d9563e1c..f0b25286 100644 --- a/packages/ui-kit/src/mobile-components/pager/Pager.tsx +++ b/packages/ui-kit/src/mobile-components/pager/Pager.tsx @@ -1,9 +1,10 @@ +import React from "react"; import { ReactComponent as ChevronLeftIcon } from "src/assets/svg/chevron-left.svg"; import { ReactComponent as Close3Icon } from "src/assets/svg/close3.svg"; import { twMerge } from "tailwind-merge"; interface PagerProps { - title?: string; + title?: string | React.ReactNode; handleClose?: () => void; handleBack?: () => void; } @@ -17,7 +18,10 @@ export const Pager: React.FC = ({
);