diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..b94845011 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 ALPHABOX SOLUTIONS PTE. LTD. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 0e2630deb..cccaed97e 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -1,7 +1,7 @@ { "name": "@alphaday/frontend", "private": true, - "version": "3.1.6", + "version": "3.1.7", "type": "module", "scripts": { "prepare": "export VITE_COMMIT=$(git rev-parse --short HEAD)", diff --git a/packages/frontend/src/api/store/migrations.ts b/packages/frontend/src/api/store/migrations.ts index b00a8334a..851fe04cd 100644 --- a/packages/frontend/src/api/store/migrations.ts +++ b/packages/frontend/src/api/store/migrations.ts @@ -11,6 +11,7 @@ import { } from "../types"; import { Logger } from "../utils/logging"; import { RootState } from "./reducer"; +import { IUIState } from "./slices/ui"; import { IViewsState } from "./slices/views"; type PersistedRootState = (PersistedState & RootState) | undefined; @@ -37,7 +38,14 @@ type PersistedRootState = (PersistedState & RootState) | undefined; * 102: (s: RootStateV101) => PersistedRootState */ -type RootStateV105 = PersistedRootState; +type RootStateV106 = PersistedRootState; + +type RootStateV105 = + | (PersistedState & + Omit & { + ui: Omit; + }) + | undefined; type RootStateV104 = | (PersistedState & Omit) @@ -102,6 +110,7 @@ type TMigrations = MigrationManifest & { 103: (s: RootStateV102) => RootStateV103; 104: (s: RootStateV103) => RootStateV104; 105: (s: RootStateV104) => RootStateV105; + 106: (s: RootStateV105) => RootStateV106; }; /** @@ -261,6 +270,16 @@ const migrations: TMigrations = { }, }; }, + 106: (s: RootStateV105): RootStateV106 => { + if (!s) return undefined; + return { + ...s, + ui: { + ...s.ui, + showAboutModal: false, + }, + }; + }, }; export default migrations; diff --git a/packages/frontend/src/api/store/slices/ui.ts b/packages/frontend/src/api/store/slices/ui.ts index ebeb00995..6003917fe 100644 --- a/packages/frontend/src/api/store/slices/ui.ts +++ b/packages/frontend/src/api/store/slices/ui.ts @@ -10,6 +10,7 @@ export interface IUIState { theme: TTheme; showWidgetLib: boolean; showBalance: boolean; + showAboutModal: boolean; tutorial: ITutorialState; cookieChoice: ECookieChoice | undefined; mobile: { @@ -24,6 +25,7 @@ export interface IUIState { const initialState: IUIState = { theme: "dark", showWidgetLib: false, + showAboutModal: false, showBalance: true, tutorial: { showTutorial: undefined, currentTutorialTip: undefined }, cookieChoice: undefined, @@ -53,6 +55,9 @@ const uiSlice = createSlice({ toggleShowBalance(draft) { draft.showBalance = !draft.showBalance; }, + toggleAboutModal(draft) { + draft.showAboutModal = !draft.showAboutModal; + }, toggleWidgetsNavOpen(draft) { draft.mobile.widgetsNavOpen = !draft.mobile.widgetsNavOpen; }, @@ -99,6 +104,7 @@ export const { toggleTheme, toggleShowWidgetLib, toggleShowBalance, + toggleAboutModal, toggleWidgetsNavOpen, setStoreShowTutorial, setCurrentTutorialTip, diff --git a/packages/frontend/src/assets/icons/Info2.svg b/packages/frontend/src/assets/icons/Info2.svg deleted file mode 100644 index 4aef7036a..000000000 --- a/packages/frontend/src/assets/icons/Info2.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/frontend/src/assets/icons/info2.svg b/packages/frontend/src/assets/icons/info2.svg new file mode 100644 index 000000000..c954c90e6 --- /dev/null +++ b/packages/frontend/src/assets/icons/info2.svg @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/packages/frontend/src/components/AboutUsModal.tsx b/packages/frontend/src/components/AboutUsModal.tsx new file mode 100644 index 000000000..9906a8c40 --- /dev/null +++ b/packages/frontend/src/components/AboutUsModal.tsx @@ -0,0 +1,102 @@ +import { + Button, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + ModalTitle, +} from "@alphaday/ui-kit"; + +interface IProps { + showModal: boolean; + onClose?: () => void; +} +export const AboutUsModal: React.FC = ({ showModal, onClose }) => { + return ( + + + About Us + + + +
Company Overview:
+

+ Registered Name: Alphabox Solutions Pte. Ltd. +
+ Registration Number: 202136261C +
+ Registered Office: 45 North Canal Road #01-01 Lew Building + Singapore +

+ +
Contact Information:
+

+ Email Address:{" "} + hello@alphaday.com +
+ X.com:{" "} + + https://x.com/AlphadayHQ + +

+ +
Legal Information:
+

+ Terms & Conditions:{" "} + + https://alphaday.com/terms + +
+ Privacy Policy:{" "} + + https://alphaday.com/privacy + +

+ +
Additional Resources:
+

+ FAQs:{" "} + + alphaday.com + +
+ Feedback:{" "} + + https://forms.gle/RbrrLGdFPAeuNJhk9 + +

+

+ Alphaday's mission is to bring you all the tools needed + to follow your favorite projects, stay up-to-date with the + latest narratives, and use your favorite dapps, all from the + comfort of one easy-to-use customizable dashboard. +

+
+ + + +
+ ); +}; diff --git a/packages/frontend/src/config/config.ts b/packages/frontend/src/config/config.ts index e23a53234..cf57d53e6 100644 --- a/packages/frontend/src/config/config.ts +++ b/packages/frontend/src/config/config.ts @@ -104,7 +104,7 @@ const CONFIG = { APP: { VERSION: import.meta.env.VITE_VERSION || "", STORAGE_KEY: "alphaday", - STORAGE_VERSION: 105, + STORAGE_VERSION: 106, COMMIT: import.meta.env.VITE_COMMIT, COMMIT_TIMESTAMP: import.meta.env.VITE_COMMIT_TS || "", X_APP_ID: import.meta.env.VITE_X_APP_ID || "", diff --git a/packages/frontend/src/containers/AboutUsModalContainer.tsx b/packages/frontend/src/containers/AboutUsModalContainer.tsx new file mode 100644 index 000000000..b23b08b58 --- /dev/null +++ b/packages/frontend/src/containers/AboutUsModalContainer.tsx @@ -0,0 +1,17 @@ +import { toggleAboutModal } from "src/api/store"; +import { useAppDispatch, useAppSelector } from "src/api/store/hooks"; +import { AboutUsModal } from "src/components/AboutUsModal"; + +export const AboutUsModalContainer = () => { + const dispatch = useAppDispatch(); + const showModal = useAppSelector((state) => state.ui.showAboutModal); + const toggleModal = () => dispatch(toggleAboutModal()); + + const onClose = () => { + if (showModal) { + toggleModal(); + } + }; + + return ; +}; diff --git a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx index 104ec5ad7..b92458c15 100644 --- a/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx +++ b/packages/frontend/src/containers/header/profile-dropdown/ProfileDropdownContainer.tsx @@ -2,10 +2,13 @@ import { FC } from "react"; import { useAccount } from "src/api/hooks"; import { useAuth } from "src/api/hooks/useAuth"; import { useTutorial } from "src/api/hooks/useTutorial"; +import { toggleAboutModal } from "src/api/store"; +import { useAppDispatch } from "src/api/store/hooks"; import { ETutorialTipId } from "src/api/types"; import ProfileDropdownWrapper from "./ProfileDropdownWrapper"; const ProfileDropdownContainer: FC = () => { + const dispatch = useAppDispatch(); const { openAuthModal, isAuthenticated, logout } = useAuth(); const { userProfile } = useAccount(); const { @@ -15,12 +18,15 @@ const ProfileDropdownContainer: FC = () => { setTutFocusElemRef, } = useTutorial(); + const toggleAboutUsModal = () => dispatch(toggleAboutModal()); + return ( void; showTutorial: boolean | undefined; + onShowAboutUsModal: () => void; setTutFocusElemRef?: | React.Dispatch> | undefined; @@ -36,14 +37,15 @@ const ProfileDropdownWrapper: React.FC = ({ onSignUpSignIn, onShowTutorial, showTutorial, + onShowAboutUsModal, isAuthenticated, setTutFocusElemRef, profile, }) => { - const [toggleState, setToggleState] = useState(false); + const [toggleTutorialState, setToggleTutorialState] = useState(false); const handleToggle = () => { - setToggleState((prev) => !prev); + setToggleTutorialState((prev) => !prev); setTimeout(() => { onShowTutorial(true); }, 500); @@ -64,7 +66,7 @@ const ProfileDropdownWrapper: React.FC = ({ }; useEffect(() => { - if (!showTutorial) setToggleState(false); + if (!showTutorial) setToggleTutorialState(false); }, [showTutorial]); return ( @@ -123,10 +125,16 @@ const ProfileDropdownWrapper: React.FC = ({ type="checkbox" className={styles.toggle} onChange={handleToggle} - checked={toggleState} + checked={toggleTutorialState} /> + + + About Us + + + {CONFIG.APP.VERSION && CONFIG.APP.COMMIT && (
diff --git a/packages/frontend/src/mobile-components/profile/UserSettings.tsx b/packages/frontend/src/mobile-components/profile/UserSettings.tsx index bdf217e23..26da80686 100644 --- a/packages/frontend/src/mobile-components/profile/UserSettings.tsx +++ b/packages/frontend/src/mobile-components/profile/UserSettings.tsx @@ -9,6 +9,7 @@ import { Logger } from "src/api/utils/logging"; import { ReactComponent as ChevronSVG } from "src/assets/icons/chevron-down2.svg"; import { ReactComponent as DocSVG } from "src/assets/icons/doc.svg"; import { ReactComponent as GreenCheckSVG } from "src/assets/icons/green-check.svg"; +import { ReactComponent as InfoSVG } from "src/assets/icons/info2.svg"; import { ReactComponent as LogoutSVG } from "src/assets/icons/logout.svg"; import { ReactComponent as StarSVG } from "src/assets/icons/star.svg"; import { ReactComponent as UserSVG } from "src/assets/icons/user.svg"; @@ -97,6 +98,7 @@ interface IUserSettings { onSaveProfile: (req: { handle: string }) => void; isSavingProfile: boolean; onLogout: () => Promise; + onShowAboutUsModal: () => void; } const UserSettings: FC = ({ profile, @@ -104,6 +106,7 @@ const UserSettings: FC = ({ onSaveProfile, isSavingProfile, onLogout, + onShowAboutUsModal, }) => { const [showProfileEditModal, setShowProfileEditModal] = useState(false); @@ -154,6 +157,13 @@ const UserSettings: FC = ({ "https://app.termly.io/document/terms-of-use-for-website/0f183823-fe52-47af-87d2-d1058b844918" ), }, + { + id: "about", + icon: InfoSVG, + title: "About Us", + subtext: "Learn more about Alphaday", + onClick: onShowAboutUsModal, + }, { id: "rate", icon: StarSVG, diff --git a/packages/frontend/src/mobile-containers/UserSettingsContainer.tsx b/packages/frontend/src/mobile-containers/UserSettingsContainer.tsx index bf72ec92c..a87c11eba 100644 --- a/packages/frontend/src/mobile-containers/UserSettingsContainer.tsx +++ b/packages/frontend/src/mobile-containers/UserSettingsContainer.tsx @@ -1,12 +1,17 @@ import { FC } from "react"; import { useAccount, useAuth } from "src/api/hooks"; +import { toggleAboutModal } from "src/api/store"; +import { useAppDispatch } from "src/api/store/hooks"; import { debounce } from "src/api/utils/helpers"; import UserSettings from "src/mobile-components/profile/UserSettings"; const UserSettingsContainer: FC = () => { + const dispatch = useAppDispatch(); const { isAuthenticated, logout } = useAuth(); const { userProfile, saveProfile, isSavingProfile } = useAccount(); + const toggleAboutUsModal = () => dispatch(toggleAboutModal()); + return ( { onSaveProfile={debounce(saveProfile, 1000)} isSavingProfile={isSavingProfile} onLogout={logout} + onShowAboutUsModal={toggleAboutUsModal} /> ); }; diff --git a/packages/frontend/src/mobile-pages/portfolio.tsx b/packages/frontend/src/mobile-pages/portfolio.tsx index 558dacbde..6f215dd68 100644 --- a/packages/frontend/src/mobile-pages/portfolio.tsx +++ b/packages/frontend/src/mobile-pages/portfolio.tsx @@ -2,7 +2,7 @@ import { FC } from "react"; import { Pager } from "@alphaday/ui-kit"; import { useAuth, useHistory } from "src/api/hooks"; import { ReactComponent as CloseSVG } from "src/assets/icons/close.svg"; -import { ReactComponent as InfoSVG } from "src/assets/icons/Info2.svg"; +import { ReactComponent as InfoSVG } from "src/assets/icons/info2.svg"; import WalletConnectionOptions from "src/mobile-components/portfolio/WalletConnectionOptions"; const TopSection: FC<{ isAuthenticated: boolean }> = ({ isAuthenticated }) => { diff --git a/packages/frontend/src/mobile-pages/user-settings.tsx b/packages/frontend/src/mobile-pages/user-settings.tsx index 5eb8135db..bbd543e3f 100644 --- a/packages/frontend/src/mobile-pages/user-settings.tsx +++ b/packages/frontend/src/mobile-pages/user-settings.tsx @@ -1,3 +1,4 @@ +import { AboutUsModalContainer } from "src/containers/AboutUsModalContainer"; import PagedMobileLayout from "src/layout/PagedMobileLayout"; import UserSettingsContainer from "src/mobile-containers/UserSettingsContainer"; @@ -5,6 +6,7 @@ const UserSettings: React.FC = () => { return ( + ); }; diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index c4dcc6dc3..0b91c94e8 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -26,6 +26,7 @@ import { import { Logger } from "src/api/utils/logging"; import { EToastRole, toast } from "src/api/utils/toastUtils"; import CONFIG from "src/config/config"; +import { AboutUsModalContainer } from "src/containers/AboutUsModalContainer"; import ModuleWrapper from "src/containers/base/ModuleWrapper"; import CookieDisclaimerContainer from "src/containers/cookie-disclaimer/CookieDisclaimerContainer"; import AuthContainer from "src/containers/dialogs/AuthContainer"; @@ -357,6 +358,7 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { + ); } diff --git a/packages/ui-kit/index.ts b/packages/ui-kit/index.ts index 72aac5f28..91b77978a 100644 --- a/packages/ui-kit/index.ts +++ b/packages/ui-kit/index.ts @@ -65,7 +65,13 @@ import { } from "./src/components/listItem/ListItem"; import { ErrorModal } from "./src/components/modal/ErrorModal"; import { FullPageModal } from "./src/components/modal/FullPageModal"; -import { Modal } from "./src/components/modal/Modal"; +import { + Modal, + ModalHeader, + ModalBody, + ModalTitle, + ModalFooter, +} from "./src/components/modal/Modal"; import { ModulePreview } from "./src/components/module-preview/ModulePreview"; import { ModuleLoader } from "./src/components/moduleLoader/ModuleLoader"; import { Overlay } from "./src/components/overlay/Overlay"; @@ -143,6 +149,10 @@ export { Dialog, TextOverlay, Modal, + ModalHeader, + ModalBody, + ModalTitle, + ModalFooter, Input, ModuleLoader, ListItem,