From e99902ed0d32403a272eafad6486f3f3d8b72213 Mon Sep 17 00:00:00 2001 From: gemdegen <94614019+gemdegem@users.noreply.github.com> Date: Wed, 13 Mar 2024 18:50:10 +0000 Subject: [PATCH 1/6] resolving tunki's merge conflicts --- frontend/package.json | 22 ++- frontend/src/app/layout.tsx | 2 + frontend/src/app/page.tsx | 2 +- frontend/src/app/profile/page.tsx | 11 +- .../src/app/settings/accesstokens/page.tsx | 120 ++++++++++++++ frontend/src/app/settings/account/page.tsx | 153 ++++++++++++++++++ .../src/app/settings/authentication/page.tsx | 123 ++++++++++++++ frontend/src/app/settings/billing/page.tsx | 95 +++++++++++ frontend/src/app/settings/billing/tab.tsx | 56 +++++++ .../src/app/settings/organizations/page.tsx | 96 +++++++++++ frontend/src/app/settings/profile/page.tsx | 46 +++--- frontend/src/app/settings/theme/page.tsx | 108 +++++++++++++ .../organisms/navbar/navigation-bar.tsx | 13 +- .../components/templates/homepage-header.tsx | 76 +++++---- .../store/action/transaction.record.action.ts | 108 ++++++++++++- frontend/src/store/action/type.ts | 14 +- .../reducers/transaction.record.reducer.ts | 34 +++- frontend/src/store/store.js | 3 +- 18 files changed, 1016 insertions(+), 66 deletions(-) create mode 100644 frontend/src/app/settings/accesstokens/page.tsx create mode 100644 frontend/src/app/settings/account/page.tsx create mode 100644 frontend/src/app/settings/authentication/page.tsx create mode 100644 frontend/src/app/settings/billing/page.tsx create mode 100644 frontend/src/app/settings/billing/tab.tsx create mode 100644 frontend/src/app/settings/organizations/page.tsx create mode 100644 frontend/src/app/settings/theme/page.tsx diff --git a/frontend/package.json b/frontend/package.json index e6153066..045e9e13 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,6 +6,7 @@ "dev": "next dev", "build": "next build", "start": "next start", + "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"", "lint": "next lint" }, "dependencies": { @@ -32,6 +33,7 @@ "moralis": "^2.23.2", "next": "14.0.1", "next-auth": "^4.24.5", + "prettier": "^3.2.5", "react": "^18", "react-dom": "^18", "react-flow-renderer": "^10.3.17", @@ -41,11 +43,13 @@ "react-icons": "^5.0.1", "react-notifications": "^1.7.4", "react-paginate": "8.1.3", - "react-redux": "^9.1.0", + "react-redux": "^8.1.3", + "react-qr-code": "^2.0.12", + "reactflow": "^11.10.4", "redux": "^5.0.1", "redux-devtools-extension": "^2.13.9", - "redux-thunk": "^3.1.0", + "redux-thunk": "2.4.2", "rxjs": "^7.8.1", "stripe": "^14.12.0", "viem": "^1.13.1", @@ -65,5 +69,17 @@ "typescript": "^5", "webpack-bundle-analyzer": "^4.4.2", "webpackbar": "^5.0.0-3" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] } -} +} \ No newline at end of file diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 8625d676..e1c2ff05 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -35,6 +35,8 @@ import ThemeProvider from '@/context/toggle-theme-provider'; import './globals.css'; import 'reactflow/dist/style.css'; +import { Provider } from 'react-redux'; +import { store } from '@/store/index'; const { chains, publicClient } = configureChains( [mainnet, polygon, optimism, arbitrum, base, zora, sepolia, goerli], diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index df5a02eb..ee45e3d7 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -117,7 +117,7 @@ function SectionWrapper({ return (
-
+
{ const router = useRouter() + const address = useSelector(({ transactionRecord: { address } }) => address) + + const handleUserProfile = () => { router.push('/settings/profile'); } @@ -17,9 +22,9 @@ const ProfilePage = () => {
image -

- Alan Guerrero -

+

+ {address} +

+ +
+
+ +
+ { + isShowTokenGenModalOpen && + +
+ + + + + +
+
+ } +
+ ) + +} + +export default AuthenticationPage; \ No newline at end of file diff --git a/frontend/src/app/settings/account/page.tsx b/frontend/src/app/settings/account/page.tsx new file mode 100644 index 00000000..5344b9a8 --- /dev/null +++ b/frontend/src/app/settings/account/page.tsx @@ -0,0 +1,153 @@ +"use client" +import React, { useState } from "react"; +import LogoImage from '../../../../public/gif/logo/CubesShufflingGIF.gif' +import Image from "next/image"; +import axios from "axios"; +import { useDispatch, useSelector } from "react-redux"; +import { usePathname, useRouter } from "next/navigation"; +import { deleteUserAccount, updateWalletAddress } from "@/store/action/transaction.record.action"; + +const AccountPage: React.FC = () => { + + const [Username, setUsername] = useState(''); + const [primaryEmail, setPrimaryEmail] = useState(''); + const [oldWalletAddress, setOldWalletAddress] = useState('') + const [walletAddress, setWalletAddress] = useState('') + const [confirmWalletAddress, setConfirmWalletAddress] = useState('') + + const address = useSelector(({ transactionRecord: { address } }) => address) + const router = useRouter() + const currentLocation = usePathname() + + const dispatch = useDispatch() + + const parts: string[] = currentLocation.split('/'); + // Get the last non-empty part + const selectedItem: string = parts.filter(part => part !== '').pop() || ''; + + const Items = [ + 'Profile', + 'Account', + 'Authentication', + 'Organizations', + 'Billing', + "Access Tokens", + "Notifications", + "Theme" + ] + + const handleSaveUserNameAndEmail = () => { + const formData = new FormData(); + formData.append('Username', Username); + formData.append('primaryEmail', primaryEmail); + + axios.post('http://localhost:8000/authentication/saveUserNameAndEmail/', formData, { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }) + .then((response) => { + console.log('File uploaded successfully!', response.data); + // You can handle success here, e.g., update state, show success message, etc. + }) + .catch((error) => { + console.error('Error uploading file:', error); + // Handle errors here, e.g., show error message to the user + }); + } + + const handleRouters = (item: string) => { + router.push(`/settings/${item.replace(/\s/g, '').toLowerCase()}`) + } + + const handleSaveNewWalletAddress = () => { + dispatch(updateWalletAddress(oldWalletAddress, walletAddress)) + + } + + const handleDeletUserAccount = () => { + dispatch(deleteUserAccount(address)) + } + + return ( +
+
+
+
+ image + { + address && + + Address: {address} + + } + +
+ + { + Items.map((item, index) => { + return
+
handleRouters(item)}> + {item} +
+
+ }) + } + +
+ +
+ +
+
+ +

+ Account Settings +

+ + + setUsername(value)} className="mt-1 dark:bg-slate-600 dark:text-white flex justify-center p-2 w-full rounded-md" /> + + + setPrimaryEmail(value)} className="mt-1 dark:bg-slate-600 dark:text-white flex justify-center p-2 w-full rounded-md" /> + + We will use this email to communicate with you. This is also the email to use to authenticate on comwallet.co and comchat.io. + + + + + setOldWalletAddress(value)} className="mt-1 dark:bg-slate-600 dark:text-white flex justify-center p-2 w-full rounded-md" /> + + + setWalletAddress(value)} className="mt-1 dark:bg-slate-600 dark:text-white flex justify-center p-2 w-full rounded-md" /> + + + setConfirmWalletAddress(value)} className="mt-1 dark:bg-slate-600 dark:text-white flex justify-center p-2 w-full rounded-md" /> + + + + Delete your account + + + + Delete your Commune account permanently, this action is irreversible. All your informations + will be deleted. + + +
+ +
+
+ ) + +} + +export default AccountPage; + diff --git a/frontend/src/app/settings/authentication/page.tsx b/frontend/src/app/settings/authentication/page.tsx new file mode 100644 index 00000000..7b50136a --- /dev/null +++ b/frontend/src/app/settings/authentication/page.tsx @@ -0,0 +1,123 @@ +"use client" +import React, { useState } from "react"; +import LogoImage from '../../../../public/gif/logo/CubesShufflingGIF.gif' +import Image from "next/image"; +import { useSelector } from "react-redux"; +import { usePathname, useRouter } from "next/navigation"; +import QRCode from "react-qr-code"; + +const AuthenticationPage: React.FC = () => { + + const address = useSelector(({ transactionRecord: { address } }) => address) + const router = useRouter() + const currentLocation = usePathname() + + const [isShow2Factor, setIsShow2Factor] = useState(false) + + const parts: string[] = currentLocation.split('/'); + // Get the last non-empty part + const selectedItem: string = parts.filter(part => part !== '').pop() || ''; + + const Items = [ + 'Profile', + 'Account', + 'Authentication', + 'Organizations', + 'Billing', + "Access Tokens", + "Notifications", + "Theme" + ] + + const handleRouters = (item: string) => { + router.push(`/settings/${item.replace(/\s/g, '').toLowerCase()}`) + } + + const handleShow2Auth = () => { + setIsShow2Factor(!isShow2Factor) + } + + const handleCancel = () => { + setIsShow2Factor(false) + } + + return ( +
+
+
+
+ image + { + address && + + Address: {address} + + } + +
+ + { + Items.map((item, index) => { + return
+
handleRouters(item)}> + {item} +
+
+ }) + } + +
+ +
+ +
+
+ +

+ Authentication Settings +

+ +
+

Two-Factor Authentication

+

Add an extra identity check at sign-in. Use a trusted app or extension such as Google Authenticator, 1Password, + Authy, or Microsoft Authenticator to create your single-use passwords. +

+ { + isShow2Factor ? +
+ + You can also use your setup key ( +
NLPT5XNAOLP6DKEK
+ ) to manually configure your authenticator app. +
+ + + + +
+ + +
+
+ : + + } + +
+
+ +
+
+ ) + +} + +export default AuthenticationPage; \ No newline at end of file diff --git a/frontend/src/app/settings/billing/page.tsx b/frontend/src/app/settings/billing/page.tsx new file mode 100644 index 00000000..5336d97e --- /dev/null +++ b/frontend/src/app/settings/billing/page.tsx @@ -0,0 +1,95 @@ +"use client" +import React, { useState } from "react"; +import LogoImage from '../../../../public/gif/logo/CubesShufflingGIF.gif' +import Image from "next/image"; +import { useSelector } from "react-redux"; +import { usePathname, useRouter } from "next/navigation"; +import QRCode from "react-qr-code"; +import TabComponent from "./tab"; + +const BillingPage: React.FC = () => { + + const address = useSelector(({ transactionRecord: { address } }) => address) + const router = useRouter() + const currentLocation = usePathname() + + const [isShow2Factor, setIsShow2Factor] = useState(false) + + const parts: string[] = currentLocation.split('/'); + // Get the last non-empty part + const selectedItem: string = parts.filter(part => part !== '').pop() || ''; + + const Items = [ + 'Profile', + 'Account', + 'Authentication', + 'Organizations', + 'Billing', + "Access Tokens", + "Notifications", + "Theme" + ] + + const handleRouters = (item: string) => { + router.push(`/settings/${item.replace(/\s/g, '').toLowerCase()}`) + } + + const handleShow2Auth = () => { + setIsShow2Factor(!isShow2Factor) + } + + const handleCancel = () => { + setIsShow2Factor(false) + } + + return ( +
+
+
+
+ image + { + address && + + Address: {address} + + } + +
+ + { + Items.map((item, index) => { + return
+
handleRouters(item)}> + {item} +
+
+ }) + } + +
+ +
+ +
+
+ +

+ Billing +

+ +
+ +
+
+ +
+
+ ) + +} + +export default BillingPage; \ No newline at end of file diff --git a/frontend/src/app/settings/billing/tab.tsx b/frontend/src/app/settings/billing/tab.tsx new file mode 100644 index 00000000..04cc19cd --- /dev/null +++ b/frontend/src/app/settings/billing/tab.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { Tabs } from 'antd'; +import type { TabsProps } from 'antd'; + +const onChange = (key: string) => { + console.log(key); +}; + +const items: TabsProps['items'] = [ + { + key: '1', + label: 'Overview', + children: +
+
+
Current period usage
+
$0.00
+
+
+
+
Ends on
+
Mar 31
+
+
+
, + }, + { + key: '2', + label: 'Payment information', + children:
+
+

Payment method

+

There is no payment method for this account.

+
+ +
, + }, + { + key: '3', + label: 'PRO Subscription', + children:
+
+
+
+

Active Plan

+

Free

+ Upgrade account +
+
+
, + }, +]; + +const TabComponent: React.FC = () => ; + +export default TabComponent; \ No newline at end of file diff --git a/frontend/src/app/settings/organizations/page.tsx b/frontend/src/app/settings/organizations/page.tsx new file mode 100644 index 00000000..0bc0c018 --- /dev/null +++ b/frontend/src/app/settings/organizations/page.tsx @@ -0,0 +1,96 @@ +"use client" +import React, { useState } from "react"; +import LogoImage from '../../../../public/gif/logo/CubesShufflingGIF.gif' +import Image from "next/image"; +import { useSelector } from "react-redux"; +import { usePathname, useRouter } from "next/navigation"; +import QRCode from "react-qr-code"; + +const OrganizationPage: React.FC = () => { + + const address = useSelector(({ transactionRecord: { address } }) => address) + const router = useRouter() + const currentLocation = usePathname() + + const [isShow2Factor, setIsShow2Factor] = useState(false) + + const parts: string[] = currentLocation.split('/'); + // Get the last non-empty part + const selectedItem: string = parts.filter(part => part !== '').pop() || ''; + + const Items = [ + 'Profile', + 'Account', + 'Authentication', + 'Organizations', + 'Billing', + "Access Tokens", + "Notifications", + "Theme" + ] + + const handleRouters = (item: string) => { + router.push(`/settings/${item.replace(/\s/g, '').toLowerCase()}`) + } + + const handleShow2Auth = () => { + setIsShow2Factor(!isShow2Factor) + } + + const handleCancel = () => { + setIsShow2Factor(false) + } + + return ( +
+
+
+
+ image + { + address && + + Address: {address} + + } + +
+ + { + Items.map((item, index) => { + return
+
handleRouters(item)}> + {item} +
+
+ }) + } + +
+ +
+ +
+
+ +

+ Organizations Settings +

+ +
+
+ You are not a member of any organization. +
+
+
+ +
+
+ ) + +} + +export default OrganizationPage; \ No newline at end of file diff --git a/frontend/src/app/settings/profile/page.tsx b/frontend/src/app/settings/profile/page.tsx index b1dbdaa6..37fce673 100644 --- a/frontend/src/app/settings/profile/page.tsx +++ b/frontend/src/app/settings/profile/page.tsx @@ -6,6 +6,8 @@ import { PlusOutlined } from '@ant-design/icons'; import { Modal, Upload } from 'antd'; import type { GetProp, UploadFile, UploadProps } from 'antd'; import axios from "axios"; +import { useSelector } from "react-redux"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; type FileType = Parameters>[0]; @@ -27,6 +29,14 @@ const ProfileEditPage: React.FC = () => { const [previewImage, setPreviewImage] = useState(''); const [previewTitle, setPreviewTitle] = useState(''); + const address = useSelector(({ transactionRecord: { address } }) => address) + const router = useRouter() + const currentLocation = usePathname() + + const parts: string[] = currentLocation.split('/'); + // Get the last non-empty part + const selectedItem: string = parts.filter(part => part !== '').pop() || ''; + const handleCancel = () => setPreviewOpen(false); const handlePreview = async (file: UploadFile) => { @@ -50,6 +60,7 @@ const ProfileEditPage: React.FC = () => { ); const Items = [ + 'Profile', 'Account', 'Authentication', 'Organizations', @@ -83,32 +94,31 @@ const ProfileEditPage: React.FC = () => { }); } + const handleRouters = (item: string) => { + router.push(`/settings/${item.replace(/\s/g, '').toLowerCase()}`) + } + return (
-
- image + image -
-

- Alan Guerrero -

- - Alan1201 + { + address && + Address: {address} -
- -
+ } -
- Profile
{ Items.map((item, index) => { return
-
+
handleRouters(item)}> {item}
@@ -125,10 +135,10 @@ const ProfileEditPage: React.FC = () => { Profile Settings -