From 03e43d00148142077e30b19a4e27fffe9aa663d9 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sun, 24 Nov 2024 20:29:00 +0300 Subject: [PATCH 01/56] Feat add authorisation buttons and authorisation window --- src/app/layout.js | 4 +- .../HasAdminAccess/HasAdminAccess.js | 1 + .../Registration/RegistrationWindow.js | 14 ++++ .../Registration/RegistrationWindow.scss | 24 ++++++ .../RegistrationButton/RegistrationButton.js | 14 ++++ .../RegistrationButton.scss | 78 +++++++++++++++++++ 6 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/components/Registration/RegistrationWindow.js create mode 100644 src/components/Registration/RegistrationWindow.scss create mode 100644 src/components/UI/Button/RegistrationButton/RegistrationButton.js create mode 100644 src/components/UI/Button/RegistrationButton/RegistrationButton.scss diff --git a/src/app/layout.js b/src/app/layout.js index 36ca47a..25ea2ab 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -1,6 +1,7 @@ import HasAdminAccess from '@/components/HasAdminAccess/HasAdminAccess' -import './globals.css' import EditingWindow from '@/components/UI/EditingWindow/EditingWindow' +import RegistrationWindow from '@/components/Registration/RegistrationWindow' +import './globals.css' export const metadata = { title: 'pshenmic.Dev', @@ -13,6 +14,7 @@ export default function RootLayout ({ children }) { + {children} diff --git a/src/components/HasAdminAccess/HasAdminAccess.js b/src/components/HasAdminAccess/HasAdminAccess.js index c4529cd..4f8dcfc 100644 --- a/src/components/HasAdminAccess/HasAdminAccess.js +++ b/src/components/HasAdminAccess/HasAdminAccess.js @@ -19,6 +19,7 @@ function HasAdminAccess () { localStorage.setItem('isAdminPshenmic', 'true') localStorage.setItem('dataClear', `${now.getTime() + 86400000}`) setOpenAdminAccessPopup(false) + console.log('true' ) } reset() } diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js new file mode 100644 index 0000000..926b012 --- /dev/null +++ b/src/components/Registration/RegistrationWindow.js @@ -0,0 +1,14 @@ +import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' +import './RegistrationWindow.scss' + +export default function RegistrationWindow () { + return ( +
+

Import to your Dash Wallet

+
+ + +
+
+ ) +} diff --git a/src/components/Registration/RegistrationWindow.scss b/src/components/Registration/RegistrationWindow.scss new file mode 100644 index 0000000..3ea0211 --- /dev/null +++ b/src/components/Registration/RegistrationWindow.scss @@ -0,0 +1,24 @@ +.RegistrationWindow { + position: fixed; + bottom: 25px; + left: 25px; + width: 618px; + display: flex; + flex-direction: column; + gap: 20px; + padding: 40px; + background: #131619; + z-index: 3; + + &__Title { + font-weight: 400; + font-size: 16px; + color: #fff; + } + + &__Buttons { + display: flex; + gap: 12px; + align-items: center; + } +} diff --git a/src/components/UI/Button/RegistrationButton/RegistrationButton.js b/src/components/UI/Button/RegistrationButton/RegistrationButton.js new file mode 100644 index 0000000..cb16b54 --- /dev/null +++ b/src/components/UI/Button/RegistrationButton/RegistrationButton.js @@ -0,0 +1,14 @@ +import './RegistrationButton.scss' + +export default function RegistrationButton({ text, handleClick, ariaLabel, ...props }) { + return ( + + ) +} diff --git a/src/components/UI/Button/RegistrationButton/RegistrationButton.scss b/src/components/UI/Button/RegistrationButton/RegistrationButton.scss new file mode 100644 index 0000000..10601c7 --- /dev/null +++ b/src/components/UI/Button/RegistrationButton/RegistrationButton.scss @@ -0,0 +1,78 @@ +.RegistrationButton { + position: relative; + padding: 13px 22px; + font-weight: 400; + font-size: 10px; + color: #d2e8fe; + width: fit-content; + font-family: "Press Start 2P"; + text-transform: uppercase; + background-color: #2e3845; + cursor: pointer; + transition: padding .5s; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + + span { + transition: all .5s; + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 0; + top: 0; + left: 0; + background: rgba(0, 117, 255, 0.10); + transition: .5s; + } + } + + &:before { + content: ''; + position: absolute; + height: 100%; + width: 0; + top: 0; + left: 0; + background: rgba(0, 117, 255, 0.10); + transition: .5s; + } + + &:hover { + padding: 13px 17px 13px 27px; + + @media screen and ( max-width: 1024px ) { + // padding: 15px 30px 15px 50px; + } + + @media screen and ( max-width: 600px ) { + // padding: 15px 30px; + } + + span { + &:before { + animation-duration: .5s; + animation-name: slidein; + } + } + } +} + +@keyframes slidein { + from { + width: 0; + left: 0; + } + + 50% { + width: 100%; + left: 0; + } + + to { + width: 0; + left: 100%; + } +} \ No newline at end of file From f096a2f8e8adeefe8c3fc8ad124779151535210a Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sun, 24 Nov 2024 21:26:25 +0300 Subject: [PATCH 02/56] Feat add ImportWalletWindow add opening and closing it --- src/app/layout.js | 2 ++ .../Registration/ImportWalletWindow.js | 26 +++++++++++++++++ .../Registration/ImportWalletWindow.scss | 12 ++++++++ .../Registration/RegistrationWindow.js | 28 +++++++++++++------ .../Registration/RegistrationWindow.scss | 21 ++++++++++++++ .../RegistrationButton/RegistrationButton.js | 5 ++-- .../RegistrationButton.scss | 14 ++++++++++ src/components/UI/DarkWrapper/DarkWrapper.jsx | 4 +-- src/store/store.js | 3 ++ 9 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/components/Registration/ImportWalletWindow.js create mode 100644 src/components/Registration/ImportWalletWindow.scss diff --git a/src/app/layout.js b/src/app/layout.js index 25ea2ab..35365ab 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -2,6 +2,7 @@ import HasAdminAccess from '@/components/HasAdminAccess/HasAdminAccess' import EditingWindow from '@/components/UI/EditingWindow/EditingWindow' import RegistrationWindow from '@/components/Registration/RegistrationWindow' import './globals.css' +import ImportWalletWindow from '@/components/Registration/ImportWalletWindow' export const metadata = { title: 'pshenmic.Dev', @@ -15,6 +16,7 @@ export default function RootLayout ({ children }) { + {children} diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js new file mode 100644 index 0000000..d30c869 --- /dev/null +++ b/src/components/Registration/ImportWalletWindow.js @@ -0,0 +1,26 @@ +'use client' + +import useGlobalStore from "@/store/store"; +import { useSpring, animated } from "@react-spring/web"; +import './ImportWalletWindow.scss' +import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; + +export default function ImportWalletWindow() { + const { openImportWalletWindow, setOpenImportWalletWindow } = useGlobalStore(); + + const animation = useSpring({ + transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', + config: { + tension: 200, + friction: 30 + } + }); + + return ( + setOpenImportWalletWindow(false)}> + +

Import Wallet

+
+
+ ) +} \ No newline at end of file diff --git a/src/components/Registration/ImportWalletWindow.scss b/src/components/Registration/ImportWalletWindow.scss new file mode 100644 index 0000000..ad466ff --- /dev/null +++ b/src/components/Registration/ImportWalletWindow.scss @@ -0,0 +1,12 @@ +.ImportWalletWindow { + position: fixed; + top: 0; + right: 0; + width: 800px; + height: 100vh; + background-color: #fff; + padding: 60px 100px; + display: flex; + flex-direction: column; + z-index: 10; +} \ No newline at end of file diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index 926b012..d3a40ca 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -1,14 +1,24 @@ +'use client' + +import Link from 'next/link' import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' +import useGlobalStore from '@/store/store'; import './RegistrationWindow.scss' -export default function RegistrationWindow () { - return ( -
-

Import to your Dash Wallet

-
- - +export default function RegistrationWindow() { + const { setOpenImportWalletWindow } = useGlobalStore(); + + return ( +
+

Import to your Dash Wallet

+
+ setOpenImportWalletWindow(true)} style={{ background: '#0275ff' }} /> + +
+
+

Not using Dash yet?

+ Generate a new wallet here +
-
- ) + ) } diff --git a/src/components/Registration/RegistrationWindow.scss b/src/components/Registration/RegistrationWindow.scss index 3ea0211..955e34e 100644 --- a/src/components/Registration/RegistrationWindow.scss +++ b/src/components/Registration/RegistrationWindow.scss @@ -21,4 +21,25 @@ gap: 12px; align-items: center; } + + &__CallToAction { + display: flex; + align-items: center; + gap: 5px; + font-weight: 400; + font-size: 12px; + color: #8fa0b6; + font-family: var(--font-mono); + + > a { + color: #97e8fc; + cursor: pointer; + opacity: 1; + transition: opacity .3s; + + &:hover { + opacity: .7; + } + } + } } diff --git a/src/components/UI/Button/RegistrationButton/RegistrationButton.js b/src/components/UI/Button/RegistrationButton/RegistrationButton.js index cb16b54..e38cce0 100644 --- a/src/components/UI/Button/RegistrationButton/RegistrationButton.js +++ b/src/components/UI/Button/RegistrationButton/RegistrationButton.js @@ -1,11 +1,12 @@ import './RegistrationButton.scss' -export default function RegistrationButton({ text, handleClick, ariaLabel, ...props }) { +export default function RegistrationButton({ text, handleClick, ariaLabel, disabled, ...props }) { return ( +

IMPORT WALLET

+
+ + +
) diff --git a/src/components/Registration/ImportWalletWindow.scss b/src/components/Registration/ImportWalletWindow.scss index ad466ff..ee79af0 100644 --- a/src/components/Registration/ImportWalletWindow.scss +++ b/src/components/Registration/ImportWalletWindow.scss @@ -8,5 +8,115 @@ padding: 60px 100px; display: flex; flex-direction: column; - z-index: 10; + z-index: 11; + gap: 50px; + + &__CloseButton { + position: absolute; + top: 0; + left: 0; + transform: translate(-100%, 0%); + cursor: pointer; + height: 100%; + width: 64px; + background: rgba(45, 59, 75, 0.71); + font-family: "Press Start 2P"; + display: flex; + justify-content: center; + padding-top: 24px; + + &__Icon { + width: 16px; + height: 16px; + } + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 0; + top: 0; + left: 0; + background: rgba(0, 117, 255, 0.10); + transition: .5s; + } + + &:hover { + &:before { + animation-duration: .5s; + animation-name: slidein; + } + } + } + + &__Title { + font-family: "Press Start 2P"; + font-weight: 400; + font-size: 16px; + color: #000; + } + + &__ButtonsContentSeedPhrase { + &::before { + transform: translateX(-100%) !important; + } + } + + &__ButtonsContent { + position: relative; + display: flex; + align-items: center; + width: 100%; + background: #d2e8fe; + + &::before { + content: ''; + position: absolute; + right: 0; + top: 0; + width: 50%; + height: calc(100% - 2px); + background: #fff; + border: 1px solid #0051a4; + transform: translateX(0%); + transition: transform .3s ease-in-out; + } + + &__Button { + font-family: "Press Start 2P"; + font-weight: 400; + font-size: 10px; + color: #016dc4; + padding: 13px 16px; + display: flex; + align-items: center; + justify-content: center; + width: 50%; + cursor: pointer; + background-color: transparent; + z-index: 1; + transition: color .3s ease-in-out; + } + } +} + +.Active { + color: #013984 !important; +} + +@keyframes slidein { + from { + width: 0; + left: 0; + } + + 50% { + width: 100%; + left: 0; + } + + to { + width: 0; + left: 100%; + } } \ No newline at end of file diff --git a/src/components/UI/DarkWrapper/DarkWrapper.jsx b/src/components/UI/DarkWrapper/DarkWrapper.jsx index f3910f1..9fc801e 100644 --- a/src/components/UI/DarkWrapper/DarkWrapper.jsx +++ b/src/components/UI/DarkWrapper/DarkWrapper.jsx @@ -3,7 +3,7 @@ import { easings, useSpring, animated } from '@react-spring/web' import './DarkWrapper.scss' -function DarkWrapper ({ duration = 600, open, children, onClick }) { +function DarkWrapper ({ duration = 600, open, children }) { const animationPopUpWrapper = useSpring({ to: { opacity: open ? '1' : '0', @@ -16,7 +16,7 @@ function DarkWrapper ({ duration = 600, open, children, onClick }) { }) return ( - + {children} ) From c41aa8909e9ebb3e842b0b790217a75fc2a42f80 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sun, 24 Nov 2024 23:10:51 +0300 Subject: [PATCH 04/56] Feat add and sanitised the RegistrationForm --- .../Registration/ImportWalletWindow.js | 78 ++++++++++++++----- .../Registration/ImportWalletWindow.scss | 14 +++- .../Registration/RegistrationForm.js | 47 +++++++++++ .../Registration/RegistrationForm.scss | 73 +++++++++++++++++ .../RegistrationButton/RegistrationButton.js | 4 +- 5 files changed, 192 insertions(+), 24 deletions(-) create mode 100644 src/components/Registration/RegistrationForm.js create mode 100644 src/components/Registration/RegistrationForm.scss diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index 36824f9..8d62fd2 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -1,15 +1,31 @@ 'use client' +import { useEffect, useState } from "react"; +import { useSpring, animated, useTransition, easings } from "@react-spring/web"; import useGlobalStore from "@/store/store"; -import { useSpring, animated } from "@react-spring/web"; -import './ImportWalletWindow.scss' import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; -import { useState } from "react"; +import RegistrationForm from "./RegistrationForm"; +import './ImportWalletWindow.scss' + +const dataSeedPhrase = { + description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', + inputDescription: 'Enter your 12 word Seed Phrase you want to import', + placeholder: 'eg. white purple lucky...', + buttonText: 'LOG IN' +} + +const dataPrivateKey = { + description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', + inputDescription: 'Please enter your Private Key', + placeholder: 'HEX / WIF / Base64...', + buttonText: 'LOG IN' +} export default function ImportWalletWindow() { const { openImportWalletWindow, setOpenImportWalletWindow } = useGlobalStore(); const [activeButton, setActiveButton] = useState('seedPhrase'); + const [form, setForm] = useState(

Off course

) const animation = useSpring({ transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', @@ -19,30 +35,56 @@ export default function ImportWalletWindow() { } }); + useEffect(() => { + if (activeButton === 'seedPhrase') { + setForm() + } else if (activeButton === 'privateKey') { + setForm() + } else { + setForm(

Off course

) + } + }, [activeButton]) + + const transitions = useTransition(form, { + from: { opacity: 0, transform: 'translateX(-30%)' }, + enter: { opacity: 1, transform: 'translateX(0%)' }, + leave: { opacity: 0, transform: 'translateX(30%)' }, + config: { duration: 400, easing: easings.easeInBack }, + trail: 100, + exitBeforeEnter: true, + }) + return ( -

IMPORT WALLET

-
- - +
+

IMPORT WALLET

+
+ + +
+ {transitions((style, item) => + + {item} + + )}
diff --git a/src/components/Registration/ImportWalletWindow.scss b/src/components/Registration/ImportWalletWindow.scss index ee79af0..20e409d 100644 --- a/src/components/Registration/ImportWalletWindow.scss +++ b/src/components/Registration/ImportWalletWindow.scss @@ -5,11 +5,17 @@ width: 800px; height: 100vh; background-color: #fff; - padding: 60px 100px; - display: flex; - flex-direction: column; z-index: 11; - gap: 50px; + + &__Wrapper { + width: 100%; + height: 100%; + overflow: hidden; + padding: 60px 100px; + display: flex; + flex-direction: column; + gap: 50px; + } &__CloseButton { position: absolute; diff --git a/src/components/Registration/RegistrationForm.js b/src/components/Registration/RegistrationForm.js new file mode 100644 index 0000000..59ed5c0 --- /dev/null +++ b/src/components/Registration/RegistrationForm.js @@ -0,0 +1,47 @@ +'use client' + +import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' +import { useSpring, animated } from '@react-spring/web' +import { useState } from 'react' +import './RegistrationForm.scss' + +// type: +// data: { description: string, inputDescription: string, placeholder: string, buttonText: string } +export default function RegistrationForm({ data }) { + const [inputValue, setInputValue] = useState('') + + const animation = useSpring({ + transform: inputValue ? 'translate(0%, 20%)' : 'translate(-50%, 20%)', + opacity: inputValue ? 0 : 1, + config: { + tension: 200, + friction: 30 + } + }); + + return ( +
+ {data?.description &&
+

{data.description}

+
} +
+ {'>'} + {data?.inputDescription &&

{data.inputDescription}

} + setInputValue(e.target.value)} + type={"text"} + placeholder={data?.placeholder || ''} + required + /> +
+ + + ) +} \ No newline at end of file diff --git a/src/components/Registration/RegistrationForm.scss b/src/components/Registration/RegistrationForm.scss new file mode 100644 index 0000000..dabfbb5 --- /dev/null +++ b/src/components/Registration/RegistrationForm.scss @@ -0,0 +1,73 @@ +.RegistrationForm { + width: 100%; + display: flex; + flex-direction: column; + gap: 50px; + + &__Description { + position: relative; + padding: 32px; + padding-bottom: 24px; + background: #d2e8fe; + width: 100%; + + >p { + font-family: "Press Start 2P"; + font-weight: 400; + font-size: 12px; + line-height: 180%; + color: #000; + } + } + + &__InputWrapper { + display: flex; + flex-direction: column; + position: relative; + + &__Arrow { + position: absolute; + top: 0; + left: -17px; + font-weight: 400; + font-size: 16px; + color: #ff522b; + } + + &__InputDescription { + font-family: var(--font-mono); + font-weight: 700; + font-size: 18px; + color: #01296d; + } + + > input { + width: 100%; + padding: 14px 0px; + border-bottom: 1px solid #000; + background: transparent; + font-weight: 400; + font-size: 18px; + color: #0275ff; + font-family: var(--font-mono); + + &::placeholder { + color: #000; + opacity: 0.3; + } + } + } + + &__Button { + width: 100% !important; + background: #0275ff !important; + color: #caf6fd !important; + transition: all .5s; + + &.disabled { + background: #d2e8fe !important; + color: #016dc4 !important; + transition: .5s; + } + } +} \ No newline at end of file diff --git a/src/components/UI/Button/RegistrationButton/RegistrationButton.js b/src/components/UI/Button/RegistrationButton/RegistrationButton.js index e38cce0..cab57f9 100644 --- a/src/components/UI/Button/RegistrationButton/RegistrationButton.js +++ b/src/components/UI/Button/RegistrationButton/RegistrationButton.js @@ -1,9 +1,9 @@ import './RegistrationButton.scss' -export default function RegistrationButton({ text, handleClick, ariaLabel, disabled, ...props }) { +export default function RegistrationButton({ text, handleClick, ariaLabel, className, disabled, ...props }) { return ( + ) +} diff --git a/src/components/UI/WalletSelection/WalletSelection.scss b/src/components/UI/WalletSelection/WalletSelection.scss new file mode 100644 index 0000000..13ffa8e --- /dev/null +++ b/src/components/UI/WalletSelection/WalletSelection.scss @@ -0,0 +1,51 @@ +@import '../../../assets/styles/mixins.scss'; + +.WalletSelection { + position: relative; + width: 100%; + display: flex; + align-items: center; + gap: 3px; + + &__Open { + cursor: pointer; + + &:hover { + > p { + color: #5199fc; + } + + > svg { + color: #5199fc; + } + } + } + + > p { + font-weight: 400; + font-size: 10px; + color: #97e8fc; + font-family: "Press Start 2P"; + transition: color 0.3s ease; + } + + > svg { + width: 24px; + height: 24px; + color: #fff; + transition: color 0.3s ease; + } + + &__Dropdown { + position: absolute; + width: 100%; + top: 100%; + right: 0; + display: flex; + flex-direction: column; + gap: 16px; + padding: 17px; + background: #131619; + border: 1px solid #565656; + } +} From f458c231ea27a79ad20ab2ccd2cc0ad1d984eec2 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Thu, 5 Dec 2024 23:54:00 +0300 Subject: [PATCH 09/56] Add SvgIcons --- .../Registration/RegistrationWindow.js | 3 +- src/components/UI/SvgIcons/SvgIcons.js | 29 +++++++++++++++++++ .../UI/WalletSelection/WalletSelection.js | 13 ++++----- 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 src/components/UI/SvgIcons/SvgIcons.js diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index f2af619..8cd7ea8 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -4,6 +4,7 @@ import './RegistrationWindow.scss' import Link from 'next/link' import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' import useGlobalStore from '@/store/store'; +import WalletSelection from '../UI/WalletSelection/WalletSelection'; import { useEffect, useState } from 'react'; import { easings, useTransition, animated } from '@react-spring/web'; @@ -72,7 +73,7 @@ function UserWindow( {data} ) { return (

{data?.name}

- +
) } diff --git a/src/components/UI/SvgIcons/SvgIcons.js b/src/components/UI/SvgIcons/SvgIcons.js new file mode 100644 index 0000000..a548db7 --- /dev/null +++ b/src/components/UI/SvgIcons/SvgIcons.js @@ -0,0 +1,29 @@ +export default function SvgIcons({ type }) { + const renderIcon = () => { + switch (type) { + case 'arrowSelection': + return + + + case 'logOut': + return + + + + + + + + + ; + default: + return null; + } + }; + + return ( + <> + {renderIcon()} + + ) +} \ No newline at end of file diff --git a/src/components/UI/WalletSelection/WalletSelection.js b/src/components/UI/WalletSelection/WalletSelection.js index 7ff40d3..2d0b8a0 100644 --- a/src/components/UI/WalletSelection/WalletSelection.js +++ b/src/components/UI/WalletSelection/WalletSelection.js @@ -17,18 +17,15 @@ export default function WalletSelection({ identityIds, identityIdentifier }) { return ( ) From d5761b53f1bd9a186a501c861acd4e69c333dcb2 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Fri, 6 Dec 2024 16:03:30 +0300 Subject: [PATCH 10/56] Add loading on user acquisition And user cards --- .env | 1 + package.json | 2 +- .../Registration/ImportWalletWindow.js | 51 ++++++++--- .../Registration/ImportWalletWindow.scss | 31 ++++++- .../Registration/RegistrationWindow.js | 90 +++++++++++++++---- .../Registration/RegistrationWindow.scss | 72 +++++++++++++++ .../RegistrationButton.scss | 12 +++ src/components/UI/Loading/Loading.js | 7 ++ src/components/UI/Loading/Loading.scss | 21 +++++ src/components/UI/SvgIcons/SvgIcons.js | 22 ++--- .../UI/WalletSelection/WalletSelection.js | 6 +- .../UI/WalletSelection/WalletSelection.scss | 5 +- src/store/store.js | 4 +- yarn.lock | 44 ++++++--- 14 files changed, 304 insertions(+), 64 deletions(-) create mode 100644 src/components/UI/Loading/Loading.js create mode 100644 src/components/UI/Loading/Loading.scss diff --git a/.env b/.env index 898ae96..dc85898 100644 --- a/.env +++ b/.env @@ -1 +1,2 @@ NEXT_PUBLIC_PASSWORD_ADMIN=adminadmin +NEXT_PUBLIC_LIST_ADMIN=2MfmHqYmAk1jAQNv7SsGJPT22MrfKFcHKZDc7cTu2biX diff --git a/package.json b/package.json index 7d3f56b..f2b19e9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ }, "dependencies": { "@react-spring/web": "^9.7.4", - "bip39": "^3.1.0", "dash": "^4.5.1", "framer-motion": "^10.16.16", "next": "^14.0.0", @@ -21,6 +20,7 @@ "react-router": "^6.21.1", "react-router-dom": "^6.21.1", "react-toastify": "^10.0.6", + "rooks": "^7.14.1", "sass": "^1.69.5", "zustand": "^4.5.5" }, diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index ef48227..23a93f3 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -1,14 +1,15 @@ 'use client' +import './ImportWalletWindow.scss' import { useCallback, useEffect, useState } from "react"; import { useSpring, animated, useTransition, easings } from "@react-spring/web"; +import { useLocalstorageState } from 'rooks'; import useGlobalStore from "@/store/store"; import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; import Dash from "dash"; -import { validateMnemonic } from 'bip39'; -import './ImportWalletWindow.scss' +import Loading from '../UI/Loading/Loading'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -25,13 +26,17 @@ const dataPrivateKey = { } export default function ImportWalletWindow() { - const { openImportWalletWindow, setOpenImportWalletWindow, setClient, client } = useGlobalStore(); + const { openImportWalletWindow, setOpenImportWalletWindow, setLoadingGetUser, loadingGetUser } = useGlobalStore(); const [activeButton, setActiveButton] = useState('seedPhrase'); const [form, setForm] = useState(

Off course

) + const [client, setClient] = useLocalstorageState('userDash', ''); + const getNewClient = useCallback(async (mnemonic) => { const mnemonicTrim = mnemonic.trim(); - if (validateMnemonic(mnemonicTrim)) { + setLoadingGetUser(true) + + if (mnemonicTrim) { const client = new Dash.Client({ network: 'testnet', wallet: { @@ -41,7 +46,8 @@ export default function ImportWalletWindow() { }, }, }); - try{ + try { + console.log('client', client) const account = await client.getWalletAccount(); const identityIds = account.identities.getIdentityIds(); @@ -54,23 +60,25 @@ export default function ImportWalletWindow() { const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); console.log('document', document) - if ( document.length > 0 ) { + if (document.length > 0) { let name document.forEach(doc => { console.log('doc.getData()', doc.getData()) const data = doc.getData() - data.records.identity === identityIdentifier ? + data.records.identity === identityIdentifier ? data.label && data.parentDomainName ? name = `${data.label}.${data.parentDomainName}` - : name = data.records.identity - : name = null + : name = data.records.identity + : name = null }) - - if ( name ) { + + if (name) { setClient({ name, identityIdentifier, identityIds }) + setLoadingGetUser(false) + setOpenImportWalletWindow(false) console.log('name', name) } } @@ -78,13 +86,13 @@ export default function ImportWalletWindow() { } catch (error) { console.error('Error retrieving account:', error); setClient(null) + setLoadingGetUser(false) } } else { console.error('Invalid mnemonic phrase.'); + setLoadingGetUser(false) } - }, [setClient]); - - console.log('client', client) + }, [setClient, setLoadingGetUser]); const animation = useSpring({ transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', @@ -94,6 +102,15 @@ export default function ImportWalletWindow() { } }); + const animationLoading = useSpring({ + opacity: loadingGetUser ? 1 : 0, + pointerEvents: loadingGetUser ? 'auto' : 'none', + config: { + tension: 200, + friction: 30 + } + }); + useEffect(() => { if (activeButton === 'seedPhrase') { setForm() @@ -116,6 +133,12 @@ export default function ImportWalletWindow() { return ( + +
+ +
+

It usually takes up to 3 minutes to connect to the blockchain. You can continue using the platform, and we will notify you once the process is successful or if it fails.

+
) } -function AdminWindow() { +function AdminWindow({ data, setClient }) { return ( -
-

Import to your Dash Wallet

+
+
+

{data?.name}

+ +
+ + + +
+
+
) } \ No newline at end of file diff --git a/src/components/Registration/RegistrationWindow.scss b/src/components/Registration/RegistrationWindow.scss index 282ba86..4647670 100644 --- a/src/components/Registration/RegistrationWindow.scss +++ b/src/components/Registration/RegistrationWindow.scss @@ -6,6 +6,24 @@ padding: 40px; background: #131619; z-index: 3; + min-height: 166px; + display: flex; + align-items: center; + + &__Loading { + position: relative; + width: 31px; + height: 31px; + flex-shrink: 0; + } + + &__Connecting { + font-weight: 400; + font-size: 12px; + line-height: 120%; + color: #8fa0b6; + font-family: var(--font-mono); + } &__Container { display: flex; @@ -13,6 +31,60 @@ gap: 20px; } + &__ContainerUser { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + } + + &__InfoUser { + display: flex; + flex-direction: column; + gap: 20px; + } + + &__Status { + position: absolute; + left: 0; + top: 0; + padding-left: 4px; + padding-right: 4px; + + > p { + font-weight: 400; + font-size: 8px; + line-height: 200%; + letter-spacing: 0.06em; + color: #ecfacf; + } + } + + &__LogOut { + cursor: pointer; + width: 36px; + height: 36px; + position: relative; + background-color: transparent; + + > svg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + color: #caf6fd; + transition: color .3s ease; + } + + &:hover { + > svg { + color: #5199fc; + } + } + } + &__Title { font-weight: 400; font-size: 16px; diff --git a/src/components/UI/Button/RegistrationButton/RegistrationButton.scss b/src/components/UI/Button/RegistrationButton/RegistrationButton.scss index 21ac10d..2a95fe3 100644 --- a/src/components/UI/Button/RegistrationButton/RegistrationButton.scss +++ b/src/components/UI/Button/RegistrationButton/RegistrationButton.scss @@ -16,6 +16,18 @@ &.disabled { cursor: not-allowed; + color: #caf6fd; + + &::after { + content: ''; + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; + background: #2e3845; + opacity: 0.4; + } &:hover { padding: 13px 22px; diff --git a/src/components/UI/Loading/Loading.js b/src/components/UI/Loading/Loading.js new file mode 100644 index 0000000..bdf9a79 --- /dev/null +++ b/src/components/UI/Loading/Loading.js @@ -0,0 +1,7 @@ +import './Loading.scss' + +export default function Loading ({ className, style }) { + return ( +
+ ) +} diff --git a/src/components/UI/Loading/Loading.scss b/src/components/UI/Loading/Loading.scss new file mode 100644 index 0000000..8c2709e --- /dev/null +++ b/src/components/UI/Loading/Loading.scss @@ -0,0 +1,21 @@ +@import '../../../assets/styles/mixins.scss'; + +.Loading { + position: absolute; + width: 100%; + height: 100%; + border: 2px solid #fff; + border-top: 2px solid transparent; + flex-shrink: 0; + border-radius: 50%; + animation: rotate 2s linear infinite; +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/src/components/UI/SvgIcons/SvgIcons.js b/src/components/UI/SvgIcons/SvgIcons.js index a548db7..3afe606 100644 --- a/src/components/UI/SvgIcons/SvgIcons.js +++ b/src/components/UI/SvgIcons/SvgIcons.js @@ -6,16 +6,18 @@ export default function SvgIcons({ type }) { case 'logOut': - return - - - - - - - - - ; + return + + + + + + + + + + + default: return null; } diff --git a/src/components/UI/WalletSelection/WalletSelection.js b/src/components/UI/WalletSelection/WalletSelection.js index 2d0b8a0..2eacee3 100644 --- a/src/components/UI/WalletSelection/WalletSelection.js +++ b/src/components/UI/WalletSelection/WalletSelection.js @@ -8,7 +8,7 @@ export default function WalletSelection({ identityIds, identityIdentifier }) { const [openWalletSelection, setOpenWalletSelection] = useState(false) const animation = useSpring({ - opacity: openWalletSelection ? 0 : 1, + opacity: openWalletSelection ? 1 : 0, config: { tension: 200, friction: 30 @@ -20,11 +20,11 @@ export default function WalletSelection({ identityIds, identityIdentifier }) { className={'WalletSelection' + (identityIds?.length > 1 ? ' WalletSelection__Open' : '')} onClick={() => identityIds?.length > 1 ? setOpenWalletSelection(true) : null} > -

{identityIdentifier}

+

{identityIdentifier}

{ identityIds?.length > 1 && } {identityIds?.map((id, index) => ( -

{id}

+

{id}

))}
diff --git a/src/components/UI/WalletSelection/WalletSelection.scss b/src/components/UI/WalletSelection/WalletSelection.scss index 13ffa8e..fae3ab2 100644 --- a/src/components/UI/WalletSelection/WalletSelection.scss +++ b/src/components/UI/WalletSelection/WalletSelection.scss @@ -6,6 +6,7 @@ display: flex; align-items: center; gap: 3px; + background-color: transparent; &__Open { cursor: pointer; @@ -21,7 +22,7 @@ } } - > p { + &__Text { font-weight: 400; font-size: 10px; color: #97e8fc; @@ -39,7 +40,7 @@ &__Dropdown { position: absolute; width: 100%; - top: 100%; + bottom: calc(100% + 7px); right: 0; display: flex; flex-direction: column; diff --git a/src/store/store.js b/src/store/store.js index ac079d8..fe8ec61 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -2,8 +2,8 @@ import { createWithEqualityFn } from 'zustand/traditional' const useGlobalStore = createWithEqualityFn( (set, get) => ({ - client: null, - setClient: (client) => set({ client }), + loadingGetUser: false, + setLoadingGetUser: (loadingGetUser) => set({ loadingGetUser }), openImportWalletWindow: false, setOpenImportWalletWindow: (openImportWalletWindow) => set({ openImportWalletWindow }), diff --git a/yarn.lock b/yarn.lock index 5c24af9..513a0ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -375,11 +375,6 @@ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.6.tgz#6b63a7b4ff3b7b410a038e3ee839c951a3136dc9" integrity sha512-NANtw+ead1rSDK1jxmzq3TYkl03UNK2KHqUYf1nIhNci6NkeqBD4s1njSzYGIlSHxCK+wSaL8RXZm4v+NF/pMw== -"@noble/hashes@^1.2.0": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" - integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1061,13 +1056,6 @@ binascii@0.0.2: resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== -bip39@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" - integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== - dependencies: - "@noble/hashes" "^1.2.0" - bloom-filter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bloom-filter/-/bloom-filter-0.2.0.tgz#84d63bbf9172d8303e64c1ff16eb9dbf33a981a3" @@ -2887,6 +2875,11 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -3401,6 +3394,11 @@ pbkdf2@^3.1.1: safe-buffer "^5.0.1" sha.js "^2.4.8" +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + picocolors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -3507,6 +3505,13 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +raf@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" + integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== + dependencies: + performance-now "^2.1.0" + react-dom@^18: version "18.3.1" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" @@ -3699,6 +3704,16 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" +rooks@^7.14.1: + version "7.14.1" + resolved "https://registry.yarnpkg.com/rooks/-/rooks-7.14.1.tgz#f3660752c299da02eb6cc733c55f8270c3376a87" + integrity sha512-oPuLNGm3OaFm3WfZHzmDvJvRit8QrXGm9/Kn49Bz8lJUjkThSBtERWzuQ9wb5DveqrpUZvmNyBXjBE0KWVt13w== + dependencies: + fast-deep-equal "^3.1.3" + lodash.debounce "^4.0.8" + raf "^3.4.1" + use-sync-external-store "^1.2.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -4269,6 +4284,11 @@ use-sync-external-store@1.2.2: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== +use-sync-external-store@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" From 308d7481fa7874a71b5464d1cf70bd15323b5a83 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Fri, 6 Dec 2024 20:57:15 +0300 Subject: [PATCH 11/56] Add receiving client and add check --- package.json | 1 + .../Registration/ImportWalletWindow.js | 147 ++++++++++++++---- .../Registration/ImportWalletWindow.scss | 27 ++++ .../Registration/RegistrationForm.js | 2 - .../Registration/RegistrationForm.scss | 19 +++ .../Registration/RegistrationWindow.js | 41 ++--- .../Registration/RegistrationWindow.scss | 41 ++++- .../RegistrationButton.scss | 3 +- .../UI/WalletSelection/WalletSelection.js | 26 +++- .../UI/WalletSelection/WalletSelection.scss | 18 ++- src/store/store.js | 3 + yarn.lock | 12 ++ 12 files changed, 276 insertions(+), 64 deletions(-) diff --git a/package.json b/package.json index f2b19e9..0f3d2c1 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@react-spring/web": "^9.7.4", + "bip39": "^3.1.0", "dash": "^4.5.1", "framer-motion": "^10.16.16", "next": "^14.0.0", diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index 23a93f3..16ba93a 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -10,6 +10,8 @@ import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; import Dash from "dash"; import Loading from '../UI/Loading/Loading'; +import { showToast } from '@/lib/showToast'; +import { validateMnemonic } from 'bip39'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -31,12 +33,11 @@ export default function ImportWalletWindow() { const [form, setForm] = useState(

Off course

) const [client, setClient] = useLocalstorageState('userDash', ''); - - const getNewClient = useCallback(async (mnemonic) => { + const getNewClientd = useCallback(async (mnemonic) => { const mnemonicTrim = mnemonic.trim(); setLoadingGetUser(true) - if (mnemonicTrim) { + if (validateMnemonic(mnemonicTrim)) { const client = new Dash.Client({ network: 'testnet', wallet: { @@ -46,51 +47,129 @@ export default function ImportWalletWindow() { }, }, }); + if (!client) { + showToast('error', 'Error retrieving account') + setClient(null) + setLoadingGetUser(false) + return + } try { - console.log('client', client) const account = await client.getWalletAccount(); + // const newAccount = await client.platform.identities.register();; const identityIds = account.identities.getIdentityIds(); if (identityIds.length > 0) { - const identity = await client.platform.identities.get(identityIds[0]); - console.log('identity', identity) - const identityIdentifier = identity.getId().toString(); - console.log('identityIdentifier:', identityIdentifier); - - const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); - console.log('document', document) - - if (document.length > 0) { - let name - document.forEach(doc => { - console.log('doc.getData()', doc.getData()) - const data = doc.getData() - data.records.identity === identityIdentifier ? - data.label && data.parentDomainName ? name = `${data.label}.${data.parentDomainName}` - : name = data.records.identity - : name = null - }) - - if (name) { - setClient({ - name, - identityIdentifier, - identityIds - }) - setLoadingGetUser(false) - setOpenImportWalletWindow(false) - console.log('name', name) + const identitiesData = await Promise.all(identityIds.map(async (id) => { + const identity = await client.platform.identities.get(id); + const identityIdentifier = identity.getId().toString(); + const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); + + const firstPart = identityIdentifier.slice(0, 5); + const lastPart = identityIdentifier.slice(-5); + + let name = `${firstPart}...${lastPart}`; + if (document.length > 0) { + document.forEach(doc => { + const data = doc.getData(); + if (data.records.identity === identityIdentifier) { + name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; + } + }); } + return { name, identityIdentifier }; + })); + if (identitiesData) { + showToast('success', 'Wallet imported successfully') + setClient({ + identities: identitiesData, + identityIds + }); + setLoadingGetUser(false) + setOpenImportWalletWindow(false) } } } catch (error) { - console.error('Error retrieving account:', error); + showToast('error', 'Error retrieving account') setClient(null) setLoadingGetUser(false) } } else { - console.error('Invalid mnemonic phrase.'); + showToast('error', 'Invalid mnemonic phrase.') setLoadingGetUser(false) + setClient(null) + } + }, [setClient, setLoadingGetUser]); + + const getNewClient = useCallback(async (mnemonic) => { + const mnemonicTrim = mnemonic.trim(); + setLoadingGetUser(true); + + // Validate the mnemonic phrase + if (!validateMnemonic(mnemonicTrim)) { + showToast('error', 'Invalid mnemonic phrase.'); + setLoadingGetUser(false); + setClient(null); + return; + } + + let client; + try { + client = new Dash.Client({ + network: 'testnet', + wallet: { + mnemonic: mnemonicTrim, + unsafeOptions: { + skipSynchronizationBeforeHeight: 1000000, + }, + }, + }); + + // Check if the client was created successfully + if (!client) { + throw new Error('Client creation failed'); + } + + const account = await client.getWalletAccount(); + const identityIds = account.identities.getIdentityIds(); + + if (identityIds.length > 0) { + const identitiesData = await Promise.all(identityIds.map(async (id) => { + const identity = await client.platform.identities.get(id); + const identityIdentifier = identity.getId().toString(); + const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); + + const firstPart = identityIdentifier.slice(0, 5); + const lastPart = identityIdentifier.slice(-5); + + let name = `${firstPart}...${lastPart}`; + if (document.length > 0) { + document.forEach(doc => { + const data = doc.getData(); + if (data.records.identity === identityIdentifier) { + name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; + } + }); + } + return { name, identityIdentifier }; + })); + + if (identitiesData) { + showToast('success', 'Wallet imported successfully'); + setClient({ + identities: identitiesData, + identityIds + }); + setLoadingGetUser(false); + setOpenImportWalletWindow(false); + } + } else { + throw new Error('No identities found for the account'); + } + } catch (error) { + console.error('Error:', error); // Log the error for debugging + showToast('error', error.message || 'Error retrieving account'); + setClient(null); + setLoadingGetUser(false); } }, [setClient, setLoadingGetUser]); diff --git a/src/components/Registration/ImportWalletWindow.scss b/src/components/Registration/ImportWalletWindow.scss index c91c26b..bd56027 100644 --- a/src/components/Registration/ImportWalletWindow.scss +++ b/src/components/Registration/ImportWalletWindow.scss @@ -126,6 +126,7 @@ display: flex; align-items: center; justify-content: center; + line-height: 120%; width: 50%; cursor: pointer; background-color: transparent; @@ -133,6 +134,32 @@ transition: color .3s ease-in-out; } } + + @media screen and ( max-width: 1100px) { + width: 100vw; + + &__CloseButton { + width: 100%; + height: 64px; + left: 100%; + padding-top: 0; + justify-content: flex-end; + align-items: center; + padding-right: 20px; + z-index: 2; + } + + &__Wrapper { + padding: 40px; + padding-top: 80px; + } + } + + @media screen and ( max-width: 520px) { + &__Wrapper { + gap: 30px; + } + } } .Active { diff --git a/src/components/Registration/RegistrationForm.js b/src/components/Registration/RegistrationForm.js index cc1026d..217b203 100644 --- a/src/components/Registration/RegistrationForm.js +++ b/src/components/Registration/RegistrationForm.js @@ -4,7 +4,6 @@ import './RegistrationForm.scss' import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' import { useSpring, animated } from '@react-spring/web' import { useEffect, useRef, useState } from 'react' -import { showToast } from '@/lib/showToast' // type: // data: { description: string, inputDescription: string, placeholder: string, buttonText: string } @@ -16,7 +15,6 @@ export default function RegistrationForm({ data, handleFunction, type }) { const validationSeedPhrase = (value) => { const words = value.trim().split(/\s+/) if (words.length > 12) { - showToast('warn', '12 words max!') return false } return true diff --git a/src/components/Registration/RegistrationForm.scss b/src/components/Registration/RegistrationForm.scss index f562885..8c07e3c 100644 --- a/src/components/Registration/RegistrationForm.scss +++ b/src/components/Registration/RegistrationForm.scss @@ -73,4 +73,23 @@ transition: .5s; } } + + @media screen and ( max-width: 520px) { + gap: 30px; + + &__Description { + padding: 20px; + } + + &__InputWrapper { + &__Arrow { + left: -14px; + font-size: 12px; + } + + > textarea { + font-size: 16px; + } + } + } } \ No newline at end of file diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index d5e616c..10f755a 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -1,6 +1,7 @@ 'use client' import './RegistrationWindow.scss' +import Loading from '../UI/Loading/Loading'; import Link from 'next/link' import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' import useGlobalStore from '@/store/store'; @@ -9,33 +10,33 @@ import SvgIcons from '../UI/SvgIcons/SvgIcons'; import { useEffect, useRef, useState } from 'react'; import { easings, useTransition, animated } from '@react-spring/web'; import { useLocalstorageState } from 'rooks'; -import Loading from '../UI/Loading/Loading'; export default function RegistrationWindow() { const [client, setClient] = useLocalstorageState('userDash', ''); + const { setOpenImportWalletWindow, indexWallet } = useGlobalStore(); const [data, setData] = useState(null) const statusTextRef = useRef(null) const statusStyleRef = useRef({}) - console.log(client) + useEffect(() => { if (!client) { - setData(); + setData(); statusTextRef.current.innerText = 'LOG IN'; statusStyleRef.current = { backgroundColor: '#2e3845' }; } else { const listAdmin = process.env.NEXT_PUBLIC_LIST_ADMIN; const listAdminArray = listAdmin.split(','); - if (listAdminArray.includes(client?.identityIdentifier)) { - setData(); + if (listAdminArray.includes(client?.identities[indexWallet]?.identityIdentifier)) { + setData(); statusTextRef.current.innerText = 'ADMIN'; statusStyleRef.current = { backgroundColor: '#8bcc49' }; - } else if (client.identityIds) { - setData(); + } else if (client?.identities[indexWallet]?.identityIdentifier) { + setData(); statusTextRef.current.innerText = 'USER'; statusStyleRef.current = { backgroundColor: '#0275ff' }; } } - }, [client]) + }, [client, indexWallet]) const transitions = useTransition(data, { from: { opacity: 0 }, @@ -60,8 +61,8 @@ export default function RegistrationWindow() { ) } -function LogInWindow() { - const { setOpenImportWalletWindow, loadingGetUser } = useGlobalStore(); +function LogInWindow({ setOpenImportWalletWindow }) { + const { loadingGetUser } = useGlobalStore(); return (
@@ -78,28 +79,28 @@ function LogInWindow() { disabled={true} /> {loadingGetUser ? - <> +

connecting...

- +
: null}
-
+ {/*

Not using Dash yet?

Generate a new wallet here -
+
*/}
) } -function UserWindow({ data, setClient }) { +function UserWindow({ data, identities, setClient }) { return (
-

{data?.name}

- +

{data?.name || data?.identityIdentifier}

+
diff --git a/src/components/UI/WalletSelection/WalletSelection.scss b/src/components/UI/WalletSelection/WalletSelection.scss index fae3ab2..b644d11 100644 --- a/src/components/UI/WalletSelection/WalletSelection.scss +++ b/src/components/UI/WalletSelection/WalletSelection.scss @@ -28,6 +28,10 @@ color: #97e8fc; font-family: "Press Start 2P"; transition: color 0.3s ease; + word-break: break-all; + line-height: 140%; + text-align: left; + } > svg { @@ -35,11 +39,12 @@ height: 24px; color: #fff; transition: color 0.3s ease; + flex-shrink: 0; } &__Dropdown { position: absolute; - width: 100%; + width: 102%; bottom: calc(100% + 7px); right: 0; display: flex; @@ -48,5 +53,16 @@ padding: 17px; background: #131619; border: 1px solid #565656; + max-height: 375px; + overflow-y: auto; + + > p { + cursor: pointer; + transition: color 0.3s ease; + + &:hover { + color: #5199fc; + } + } } } diff --git a/src/store/store.js b/src/store/store.js index fe8ec61..3bf6d12 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -2,6 +2,9 @@ import { createWithEqualityFn } from 'zustand/traditional' const useGlobalStore = createWithEqualityFn( (set, get) => ({ + indexWallet: 0, + setIndexWallet: (indexWallet) => set({ indexWallet }), + loadingGetUser: false, setLoadingGetUser: (loadingGetUser) => set({ loadingGetUser }), diff --git a/yarn.lock b/yarn.lock index 513a0ff..37d4e1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -375,6 +375,11 @@ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.6.tgz#6b63a7b4ff3b7b410a038e3ee839c951a3136dc9" integrity sha512-NANtw+ead1rSDK1jxmzq3TYkl03UNK2KHqUYf1nIhNci6NkeqBD4s1njSzYGIlSHxCK+wSaL8RXZm4v+NF/pMw== +"@noble/hashes@^1.2.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1056,6 +1061,13 @@ binascii@0.0.2: resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== +bip39@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" + integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== + dependencies: + "@noble/hashes" "^1.2.0" + bloom-filter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bloom-filter/-/bloom-filter-0.2.0.tgz#84d63bbf9172d8303e64c1ff16eb9dbf33a981a3" From 6b66beb4c245a1604f013445a1b89acc675cc9e4 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sat, 7 Dec 2024 13:42:52 +0300 Subject: [PATCH 12/56] Remove unnecessary code --- .../Registration/ImportWalletWindow.js | 74 +------------------ .../Registration/RegistrationWindow.js | 13 +++- 2 files changed, 13 insertions(+), 74 deletions(-) diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index 16ba93a..baf6460 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -4,14 +4,14 @@ import './ImportWalletWindow.scss' import { useCallback, useEffect, useState } from "react"; import { useSpring, animated, useTransition, easings } from "@react-spring/web"; import { useLocalstorageState } from 'rooks'; +import { showToast } from '@/lib/showToast'; +import { validateMnemonic } from 'bip39'; import useGlobalStore from "@/store/store"; import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; import Dash from "dash"; import Loading from '../UI/Loading/Loading'; -import { showToast } from '@/lib/showToast'; -import { validateMnemonic } from 'bip39'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -33,73 +33,6 @@ export default function ImportWalletWindow() { const [form, setForm] = useState(

Off course

) const [client, setClient] = useLocalstorageState('userDash', ''); - const getNewClientd = useCallback(async (mnemonic) => { - const mnemonicTrim = mnemonic.trim(); - setLoadingGetUser(true) - - if (validateMnemonic(mnemonicTrim)) { - const client = new Dash.Client({ - network: 'testnet', - wallet: { - mnemonic: mnemonicTrim, - unsafeOptions: { - skipSynchronizationBeforeHeight: 1000000, - }, - }, - }); - if (!client) { - showToast('error', 'Error retrieving account') - setClient(null) - setLoadingGetUser(false) - return - } - try { - const account = await client.getWalletAccount(); - // const newAccount = await client.platform.identities.register();; - const identityIds = account.identities.getIdentityIds(); - - if (identityIds.length > 0) { - const identitiesData = await Promise.all(identityIds.map(async (id) => { - const identity = await client.platform.identities.get(id); - const identityIdentifier = identity.getId().toString(); - const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); - - const firstPart = identityIdentifier.slice(0, 5); - const lastPart = identityIdentifier.slice(-5); - - let name = `${firstPart}...${lastPart}`; - if (document.length > 0) { - document.forEach(doc => { - const data = doc.getData(); - if (data.records.identity === identityIdentifier) { - name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; - } - }); - } - return { name, identityIdentifier }; - })); - if (identitiesData) { - showToast('success', 'Wallet imported successfully') - setClient({ - identities: identitiesData, - identityIds - }); - setLoadingGetUser(false) - setOpenImportWalletWindow(false) - } - } - } catch (error) { - showToast('error', 'Error retrieving account') - setClient(null) - setLoadingGetUser(false) - } - } else { - showToast('error', 'Invalid mnemonic phrase.') - setLoadingGetUser(false) - setClient(null) - } - }, [setClient, setLoadingGetUser]); - const getNewClient = useCallback(async (mnemonic) => { const mnemonicTrim = mnemonic.trim(); setLoadingGetUser(true); @@ -124,7 +57,6 @@ export default function ImportWalletWindow() { }, }); - // Check if the client was created successfully if (!client) { throw new Error('Client creation failed'); } @@ -166,7 +98,7 @@ export default function ImportWalletWindow() { throw new Error('No identities found for the account'); } } catch (error) { - console.error('Error:', error); // Log the error for debugging + console.error('Error:', error); showToast('error', error.message || 'Error retrieving account'); setClient(null); setLoadingGetUser(false); diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index 10f755a..c51efca 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -2,7 +2,6 @@ import './RegistrationWindow.scss' import Loading from '../UI/Loading/Loading'; -import Link from 'next/link' import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' import useGlobalStore from '@/store/store'; import WalletSelection from '../UI/WalletSelection/WalletSelection'; @@ -27,11 +26,19 @@ export default function RegistrationWindow() { const listAdmin = process.env.NEXT_PUBLIC_LIST_ADMIN; const listAdminArray = listAdmin.split(','); if (listAdminArray.includes(client?.identities[indexWallet]?.identityIdentifier)) { - setData(); + setData(); statusTextRef.current.innerText = 'ADMIN'; statusStyleRef.current = { backgroundColor: '#8bcc49' }; } else if (client?.identities[indexWallet]?.identityIdentifier) { - setData(); + setData(); statusTextRef.current.innerText = 'USER'; statusStyleRef.current = { backgroundColor: '#0275ff' }; } From 0d4add43297e0ac855496e53c195474995f31cba Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sun, 8 Dec 2024 16:14:54 +0300 Subject: [PATCH 13/56] Add hook useDashClient --- src/hooks/useDashClient.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/hooks/useDashClient.js diff --git a/src/hooks/useDashClient.js b/src/hooks/useDashClient.js new file mode 100644 index 0000000..99c24b9 --- /dev/null +++ b/src/hooks/useDashClient.js @@ -0,0 +1,24 @@ +export async function useDashClient ({ dataDashClient = {}, errorCallback }) { + try { + const client = new Dash.Client(dataDashClient); + + if (!client) { + throw new Error('Client creation failed'); + } + + const account = await client.getWalletAccount(); + const identityIds = account.identities.getIdentityIds(); + + if (client && account && identityIds) { + return { client, account, identityIds } + } else { + throw new Error('Failed to retrieve account or identity IDs'); + } + } catch (error) { + console.error('Error:', error); + if (errorCallback) { + errorCallback(); + } + return null; + } +}; \ No newline at end of file From 916fcdcd9cc834ca3329f73fcce0f85f5962b633 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Sun, 8 Dec 2024 17:32:58 +0300 Subject: [PATCH 14/56] Add hook useDashForageClient --- package.json | 1 + .../Registration/ImportWalletWindow.js | 32 ++++++++++++++- src/hooks/useDashForageClient.js | 39 +++++++++++++++++++ yarn.lock | 19 +++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/hooks/useDashForageClient.js diff --git a/package.json b/package.json index 0f3d2c1..0a06516 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "bip39": "^3.1.0", "dash": "^4.5.1", "framer-motion": "^10.16.16", + "localforage": "^1.10.0", "next": "^14.0.0", "react": "^18", "react-dom": "^18", diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index baf6460..d32f4ae 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -33,7 +33,7 @@ export default function ImportWalletWindow() { const [form, setForm] = useState(

Off course

) const [client, setClient] = useLocalstorageState('userDash', ''); - const getNewClient = useCallback(async (mnemonic) => { + const getNewClients = useCallback(async (mnemonic) => { const mnemonicTrim = mnemonic.trim(); setLoadingGetUser(true); @@ -105,6 +105,36 @@ export default function ImportWalletWindow() { } }, [setClient, setLoadingGetUser]); + const getNewClient = useCallback(async (mnemonic) => { + const mnemonicTrim = mnemonic.trim(); + + if (!validateMnemonic(mnemonicTrim)) { + showToast('error', 'Invalid mnemonic phrase.'); + setLoadingGetUser(false); + setClient(null); + return; + } + + await useDashForageClient({ + network: 'testnet', + wallet: { + mnemonic: mnemonicTrim, + unsafeOptions: { + skipSynchronizationBeforeHeight: 1000000, + }, + }, + successCallback: (identitiesData) => { + showToast('success', 'Wallet imported successfully'); + setLoadingGetUser(false); + setOpenImportWalletWindow(false); + }, + errorCallback: () => { + showToast('error', 'Error retrieving account'); + setLoadingGetUser(false); + } + }); + }, [setLoadingGetUser]); + const animation = useSpring({ transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', config: { diff --git a/src/hooks/useDashForageClient.js b/src/hooks/useDashForageClient.js new file mode 100644 index 0000000..4171be8 --- /dev/null +++ b/src/hooks/useDashForageClient.js @@ -0,0 +1,39 @@ +import { useDashClient } from "./useDashClient"; + +export async function useDashForageClient({ dataDashClient = {}, errorCallback, successCallback }) { + const { identityIds, client } = await useDashClient(dataDashClient); + + try { + const identitiesData = await Promise.all(identityIds.map(async (id) => { + const identity = await client.platform.identities.get(id); + const identityIdentifier = identity.getId().toString(); + const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); + + const firstPart = identityIdentifier.slice(0, 5); + const lastPart = identityIdentifier.slice(-5); + + let name = `${firstPart}...${lastPart}`; + if (document.length > 0) { + document.forEach(doc => { + const data = doc.getData(); + if (data.records.identity === identityIdentifier) { + name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; + } + }); + } + return { name, identityIdentifier }; + })); + + await localforage.setItem('identitiesDataDash', identitiesData); + await localforage.setItem('clientDash', client); + + if (successCallback) { + successCallback(identitiesData); + } + } catch (error) { + console.error('Ошибка при получении данных идентичности:', error); + if (errorCallback) { + errorCallback(error); + } + } +}; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 37d4e1a..c627ae9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2410,6 +2410,11 @@ immediate@^3.2.3: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + immediate@~3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" @@ -2863,11 +2868,25 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== + dependencies: + immediate "~3.0.5" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +localforage@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" + integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== + dependencies: + lie "3.1.1" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" From 3ce50169109c7e4a6338a7adb99e5e5094f0eef4 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Mon, 9 Dec 2024 12:57:22 +0300 Subject: [PATCH 15/56] Add dash hooks --- src/app/layout.js | 15 ++- .../Registration/ImportWalletWindow.js | 117 ++++-------------- .../Registration/RegistrationWindow.js | 41 +++--- src/hooks/useDashClient.js | 76 +++++++++--- src/hooks/useDashForageClient.js | 39 ------ src/hooks/useDashStoreClient.js | 62 ++++++++++ src/store/store.js | 3 + 7 files changed, 177 insertions(+), 176 deletions(-) delete mode 100644 src/hooks/useDashForageClient.js create mode 100644 src/hooks/useDashStoreClient.js diff --git a/src/app/layout.js b/src/app/layout.js index 74b4439..1b2d331 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -5,6 +5,7 @@ import ImportWalletWindow from '@/components/Registration/ImportWalletWindow' import dynamic from "next/dynamic" import './globals.css' import 'react-toastify/dist/ReactToastify.css'; +import { DashProvider } from '@/hooks/useDashClient' const ToastContainer = dynamic(() => import('react-toastify').then((mod) => mod.ToastContainer), @@ -18,15 +19,17 @@ export const metadata = { export default function RootLayout ({ children }) { return ( - - - - - - + + + + + + + {children} + ) } diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index d32f4ae..cb2f7f5 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -10,8 +10,8 @@ import useGlobalStore from "@/store/store"; import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; -import Dash from "dash"; import Loading from '../UI/Loading/Loading'; +import { useDashStoreClient } from '@/hooks/useDashStoreClient'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -28,112 +28,43 @@ const dataPrivateKey = { } export default function ImportWalletWindow() { - const { openImportWalletWindow, setOpenImportWalletWindow, setLoadingGetUser, loadingGetUser } = useGlobalStore(); + const { openImportWalletWindow, setOpenImportWalletWindow, setLoadingGetUser, loadingGetUser, userDash, setUserDash } = useGlobalStore(); const [activeButton, setActiveButton] = useState('seedPhrase'); const [form, setForm] = useState(

Off course

) - const [client, setClient] = useLocalstorageState('userDash', ''); + + const { processIdentities } = useDashStoreClient() - const getNewClients = useCallback(async (mnemonic) => { + const errorCallback = () => { + showToast('error', 'Error retrieving account'); + setLoadingGetUser(false); + }; + + const successCallback = () => { + showToast('success', 'Wallet imported successfully'); + setLoadingGetUser(false); + setOpenImportWalletWindow(false); + }; + + const getNewClient = useCallback(async (mnemonic) => { const mnemonicTrim = mnemonic.trim(); setLoadingGetUser(true); - // Validate the mnemonic phrase - if (!validateMnemonic(mnemonicTrim)) { - showToast('error', 'Invalid mnemonic phrase.'); - setLoadingGetUser(false); - setClient(null); - return; - } - - let client; try { - client = new Dash.Client({ - network: 'testnet', - wallet: { - mnemonic: mnemonicTrim, - unsafeOptions: { - skipSynchronizationBeforeHeight: 1000000, - }, - }, - }); - - if (!client) { - throw new Error('Client creation failed'); + if (!validateMnemonic(mnemonicTrim)) { + showToast('error', 'Invalid mnemonic phrase.'); + setUserDash(null); + return; } + await processIdentities(mnemonicTrim, errorCallback, successCallback); - const account = await client.getWalletAccount(); - const identityIds = account.identities.getIdentityIds(); - - if (identityIds.length > 0) { - const identitiesData = await Promise.all(identityIds.map(async (id) => { - const identity = await client.platform.identities.get(id); - const identityIdentifier = identity.getId().toString(); - const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); - - const firstPart = identityIdentifier.slice(0, 5); - const lastPart = identityIdentifier.slice(-5); - - let name = `${firstPart}...${lastPart}`; - if (document.length > 0) { - document.forEach(doc => { - const data = doc.getData(); - if (data.records.identity === identityIdentifier) { - name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; - } - }); - } - return { name, identityIdentifier }; - })); - - if (identitiesData) { - showToast('success', 'Wallet imported successfully'); - setClient({ - identities: identitiesData, - identityIds - }); - setLoadingGetUser(false); - setOpenImportWalletWindow(false); - } - } else { - throw new Error('No identities found for the account'); - } } catch (error) { console.error('Error:', error); - showToast('error', error.message || 'Error retrieving account'); - setClient(null); + showToast('error', 'Client creation failed'); + } finally { setLoadingGetUser(false); } - }, [setClient, setLoadingGetUser]); - - const getNewClient = useCallback(async (mnemonic) => { - const mnemonicTrim = mnemonic.trim(); - if (!validateMnemonic(mnemonicTrim)) { - showToast('error', 'Invalid mnemonic phrase.'); - setLoadingGetUser(false); - setClient(null); - return; - } - - await useDashForageClient({ - network: 'testnet', - wallet: { - mnemonic: mnemonicTrim, - unsafeOptions: { - skipSynchronizationBeforeHeight: 1000000, - }, - }, - successCallback: (identitiesData) => { - showToast('success', 'Wallet imported successfully'); - setLoadingGetUser(false); - setOpenImportWalletWindow(false); - }, - errorCallback: () => { - showToast('error', 'Error retrieving account'); - setLoadingGetUser(false); - } - }); - }, [setLoadingGetUser]); + }, [setLoadingGetUser, setOpenImportWalletWindow, setUserDash, errorCallback, successCallback]); const animation = useSpring({ transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index c51efca..566635c 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -6,44 +6,49 @@ import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButt import useGlobalStore from '@/store/store'; import WalletSelection from '../UI/WalletSelection/WalletSelection'; import SvgIcons from '../UI/SvgIcons/SvgIcons'; -import { useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { easings, useTransition, animated } from '@react-spring/web'; -import { useLocalstorageState } from 'rooks'; +import { useDashClient } from '@/hooks/useDashClient'; export default function RegistrationWindow() { - const [client, setClient] = useLocalstorageState('userDash', ''); - const { setOpenImportWalletWindow, indexWallet } = useGlobalStore(); + const { userDash, setUserDash, setOpenImportWalletWindow, indexWallet } = useGlobalStore(); + const { disconnect } = useDashClient() const [data, setData] = useState(null) const statusTextRef = useRef(null) const statusStyleRef = useRef({}) + const handleLogout = useCallback(async () => { + setUserDash(null); + disconnect() + }, [disconnect]); + useEffect(() => { - if (!client) { + if (!userDash) { setData(); statusTextRef.current.innerText = 'LOG IN'; statusStyleRef.current = { backgroundColor: '#2e3845' }; } else { const listAdmin = process.env.NEXT_PUBLIC_LIST_ADMIN; const listAdminArray = listAdmin.split(','); - if (listAdminArray.includes(client?.identities[indexWallet]?.identityIdentifier)) { + if (listAdminArray.includes(userDash?.[indexWallet]?.identityIdentifier)) { setData( handleLogout()} />); statusTextRef.current.innerText = 'ADMIN'; statusStyleRef.current = { backgroundColor: '#8bcc49' }; - } else if (client?.identities[indexWallet]?.identityIdentifier) { + } else if (userDash?.[indexWallet]?.identityIdentifier) { setData( handleLogout()} />); statusTextRef.current.innerText = 'USER'; statusStyleRef.current = { backgroundColor: '#0275ff' }; } } - }, [client, indexWallet]) + }, [userDash, indexWallet, setUserDash, handleLogout]); const transitions = useTransition(data, { from: { opacity: 0 }, @@ -102,21 +107,21 @@ function LogInWindow({ setOpenImportWalletWindow }) { ) } -function UserWindow({ data, identities, setClient }) { +function UserWindow({ data, identities, handleLogout }) { return (

{data?.name || data?.identityIdentifier}

-
) } -function AdminWindow({ data, identities, setClient }) { +function AdminWindow({ data, identities, handleLogout }) { return (
@@ -139,7 +144,7 @@ function AdminWindow({ data, identities, setClient }) { />
-
diff --git a/src/hooks/useDashClient.js b/src/hooks/useDashClient.js index 99c24b9..93a7d06 100644 --- a/src/hooks/useDashClient.js +++ b/src/hooks/useDashClient.js @@ -1,24 +1,60 @@ -export async function useDashClient ({ dataDashClient = {}, errorCallback }) { - try { - const client = new Dash.Client(dataDashClient); +'use client' - if (!client) { - throw new Error('Client creation failed'); - } +import Dash from "dash"; +import { useState, useRef, createContext, useContext } from "react"; - const account = await client.getWalletAccount(); - const identityIds = account.identities.getIdentityIds(); +export function useDashClient (props) { + const [client, setClient] = useState(null); + const [account, setAccount] = useState(null); + const [identityIds, setIdentityIds] = useState(null); + const methods = useRef({ + disconnect: () => { + setClient(null); + setAccount(null); + setIdentityIds(null); + }, + connect: async (innerProps) => { + methods.current.disconnect(); + try { + const client = new Dash.Client({...props, ...innerProps}); - if (client && account && identityIds) { - return { client, account, identityIds } - } else { - throw new Error('Failed to retrieve account or identity IDs'); - } - } catch (error) { - console.error('Error:', error); - if (errorCallback) { - errorCallback(); + if (!client) { + throw new Error('Client creation failed'); + } + + setClient(client); + + const account = await client.getWalletAccount(); + const identityIds = account.identities.getIdentityIds(); + + if (account && identityIds) { + setAccount(account); + setIdentityIds(identityIds); + } else { + throw new Error('Failed to retrieve account or identity IDs'); + } + + return Promise.resolve({client, identityIds, account}); + } catch (error) { + console.error('Error add client:', error); + return Promise.reject(error); + } } - return null; - } -}; \ No newline at end of file + }) + + return { identityIds, account, client, ...methods.current }; +}; + +const DashContext = createContext(); + +export function DashProvider ({children}) { + const data = useDashClient(); + + return + {children} + +} + +export function useDash () { + return useContext(DashContext); +} \ No newline at end of file diff --git a/src/hooks/useDashForageClient.js b/src/hooks/useDashForageClient.js deleted file mode 100644 index 4171be8..0000000 --- a/src/hooks/useDashForageClient.js +++ /dev/null @@ -1,39 +0,0 @@ -import { useDashClient } from "./useDashClient"; - -export async function useDashForageClient({ dataDashClient = {}, errorCallback, successCallback }) { - const { identityIds, client } = await useDashClient(dataDashClient); - - try { - const identitiesData = await Promise.all(identityIds.map(async (id) => { - const identity = await client.platform.identities.get(id); - const identityIdentifier = identity.getId().toString(); - const document = await client.platform.names.resolveByRecord('identity', identityIdentifier); - - const firstPart = identityIdentifier.slice(0, 5); - const lastPart = identityIdentifier.slice(-5); - - let name = `${firstPart}...${lastPart}`; - if (document.length > 0) { - document.forEach(doc => { - const data = doc.getData(); - if (data.records.identity === identityIdentifier) { - name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; - } - }); - } - return { name, identityIdentifier }; - })); - - await localforage.setItem('identitiesDataDash', identitiesData); - await localforage.setItem('clientDash', client); - - if (successCallback) { - successCallback(identitiesData); - } - } catch (error) { - console.error('Ошибка при получении данных идентичности:', error); - if (errorCallback) { - errorCallback(error); - } - } -}; \ No newline at end of file diff --git a/src/hooks/useDashStoreClient.js b/src/hooks/useDashStoreClient.js new file mode 100644 index 0000000..892f8cd --- /dev/null +++ b/src/hooks/useDashStoreClient.js @@ -0,0 +1,62 @@ +import useGlobalStore from '@/store/store'; +import { useRef } from 'react'; +import { useDash } from './useDashClient'; + +export function useDashStoreClient () { + const { setClientDash, setUserDash } = useGlobalStore(); + console.log(setClientDash, setUserDash) + const { connect } = useDash(); + + const methods = useRef({ + processIdentities: async (mnemonicTrim, errorCallback, successCallback) => { + try { + await connect({ + network: 'testnet', + wallet: { + mnemonic: mnemonicTrim, + unsafeOptions: { + skipSynchronizationBeforeHeight: 1000000, + }, + }, + }).then(async (resolveClient) => { + console.log('resolveClient', resolveClient) + const identitiesData = await Promise.all(resolveClient.identityIds.map(async (id) => { + const identity = await resolveClient.client.platform.identities.get(id); + const identityIdentifier = identity.getId().toString(); + const document = await resolveClient.client.platform.names.resolveByRecord('identity', identityIdentifier); + + const firstPart = identityIdentifier.slice(0, 5); + const lastPart = identityIdentifier.slice(-5); + + let name = `${firstPart}...${lastPart}`; + if (document.length > 0) { + document.forEach(doc => { + const data = doc.getData(); + if (data.records.identity === identityIdentifier) { + name = data.label && data.parentDomainName ? `${data.label}.${data.parentDomainName}` : name; + } + }); + } + return { name, identityIdentifier }; + })); + + console.log('identitiesData', identitiesData) + + setClientDash(resolveClient.client); + setUserDash(identitiesData); + + if (successCallback) { + successCallback(); + } + }) + } catch (error) { + console.error('Error retrieving identity data:', error); + if (errorCallback) { + errorCallback(error); + } + } + }, + }) + + return { ...methods.current } +} \ No newline at end of file diff --git a/src/store/store.js b/src/store/store.js index 3bf6d12..379d2a2 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -2,6 +2,9 @@ import { createWithEqualityFn } from 'zustand/traditional' const useGlobalStore = createWithEqualityFn( (set, get) => ({ + userDash: null, + setUserDash: (userDash) => set({ userDash }), + indexWallet: 0, setIndexWallet: (indexWallet) => set({ indexWallet }), From 2e6a33844ca0329fde0cf55022c3bad797fa86f8 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Mon, 9 Dec 2024 13:40:48 +0300 Subject: [PATCH 16/56] Fix errors --- package.json | 8 +- .../Registration/ImportWalletWindow.js | 23 +++- .../UI/WalletSelection/WalletSelection.js | 5 +- src/hooks/useDashClient.js | 23 +++- src/hooks/useDashStoreClient.js | 62 ---------- yarn.lock | 113 +++++++++--------- 6 files changed, 102 insertions(+), 132 deletions(-) delete mode 100644 src/hooks/useDashStoreClient.js diff --git a/package.json b/package.json index 0a06516..1b62084 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "bip39": "^3.1.0", "dash": "^4.5.1", "framer-motion": "^10.16.16", - "localforage": "^1.10.0", "next": "^14.0.0", "react": "^18", "react-dom": "^18", @@ -22,13 +21,14 @@ "react-router": "^6.21.1", "react-router-dom": "^6.21.1", "react-toastify": "^10.0.6", - "rooks": "^7.14.1", "sass": "^1.69.5", "zustand": "^4.5.5" }, "devDependencies": { "eslint": "^8.57.0", "eslint-config-next": "^14.2.5", - "eslint-config-standard": "^17.1.0" - } + "eslint-config-standard": "^17.1.0", + "eslint-plugin-n": "^17.14.0" + }, + "license": "MIT" } diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index cb2f7f5..843defa 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -3,15 +3,14 @@ import './ImportWalletWindow.scss' import { useCallback, useEffect, useState } from "react"; import { useSpring, animated, useTransition, easings } from "@react-spring/web"; -import { useLocalstorageState } from 'rooks'; import { showToast } from '@/lib/showToast'; import { validateMnemonic } from 'bip39'; +import { useDash } from '@/hooks/useDashClient'; import useGlobalStore from "@/store/store"; import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; import Loading from '../UI/Loading/Loading'; -import { useDashStoreClient } from '@/hooks/useDashStoreClient'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -31,8 +30,7 @@ export default function ImportWalletWindow() { const { openImportWalletWindow, setOpenImportWalletWindow, setLoadingGetUser, loadingGetUser, userDash, setUserDash } = useGlobalStore(); const [activeButton, setActiveButton] = useState('seedPhrase'); const [form, setForm] = useState(

Off course

) - - const { processIdentities } = useDashStoreClient() + const { connect } = useDash(); const errorCallback = () => { showToast('error', 'Error retrieving account'); @@ -46,6 +44,7 @@ export default function ImportWalletWindow() { }; const getNewClient = useCallback(async (mnemonic) => { + if (typeof window === 'undefined') return; const mnemonicTrim = mnemonic.trim(); setLoadingGetUser(true); @@ -55,12 +54,24 @@ export default function ImportWalletWindow() { setUserDash(null); return; } - await processIdentities(mnemonicTrim, errorCallback, successCallback); + connect({network: 'testnet', + wallet: { + mnemonic: mnemonicTrim, + unsafeOptions: { + skipSynchronizationBeforeHeight: 1000000, + }, + }}).then(async (resolveClient) => { + if (resolveClient?.identitiesData) { + setUserDash(resolveClient.identitiesData); + successCallback() + } + }).catch((error) => { + errorCallback() + }) } catch (error) { console.error('Error:', error); showToast('error', 'Client creation failed'); - } finally { setLoadingGetUser(false); } diff --git a/src/components/UI/WalletSelection/WalletSelection.js b/src/components/UI/WalletSelection/WalletSelection.js index bcce912..b193989 100644 --- a/src/components/UI/WalletSelection/WalletSelection.js +++ b/src/components/UI/WalletSelection/WalletSelection.js @@ -4,13 +4,10 @@ import './WalletSelection.scss' import { useCallback, useState } from 'react' import { useSpring, animated } from '@react-spring/web' import SvgIcons from '../SvgIcons/SvgIcons' -import { useLocalstorageState } from 'rooks' import useGlobalStore from '@/store/store' export default function WalletSelection({ identityIds, identityIdentifier }) { const [openWalletSelection, setOpenWalletSelection] = useState(false) - const [clientDash] = useLocalstorageState('clientDash', ''); - const [client] = useLocalstorageState('userDash', ''); const { setIndexWallet } = useGlobalStore(); const animation = useSpring({ @@ -24,7 +21,7 @@ export default function WalletSelection({ identityIds, identityIdentifier }) { const handleClick = useCallback(async (index) => { setOpenWalletSelection(false) setIndexWallet(index) - }, [clientDash, client]) + }, [setOpenWalletSelection, setIndexWallet]) return ( + ) + } + } else { + // Always show first page + pages.push( + + ) + + // Show dots or numbers + if (currentPage > 3) { + pages.push(...) + } + + // Show current page and neighbors + for (let i = Math.max(2, currentPage - 2); i <= Math.min(currentPage + 2, totalPages - 1); i++) { + pages.push( + + ) + } + + // Show dots before last page + if (currentPage < totalPages - 2) { + pages.push(...) + } + + // Always show last page + pages.push( + + ) + } + + return pages + } + + return ( +
+ + + {renderPageNumbers()} + + +
+ ) +} diff --git a/src/components/UI/Pagination/Pagination.scss b/src/components/UI/Pagination/Pagination.scss new file mode 100644 index 0000000..f1d40ec --- /dev/null +++ b/src/components/UI/Pagination/Pagination.scss @@ -0,0 +1,55 @@ +@import '../../../assets/styles/mixins.scss'; + +.Pagination { + display: flex; + justify-content: center; + align-items: center; + gap: 9px; + width: 100%; + + &__Text { + font-weight: 400; + font-size: 10px; + color: #caf6fd; + font-family: "Press Start 2P"; + text-align: center; + } + + &__Arrow { + cursor: pointer; + padding: 13px; + background: #2e3845; + opacity: 1; + transition: background ease .5s, opacity ease .5s; + + &:disabled { + cursor: auto; + opacity: .5; + + &:hover { + background: #2e3845; + } + } + + &:hover { + background: #7f8ea1; + } + } + + &__Button { + padding: 13px; + cursor: pointer; + flex: 1; + background: #2e3845; + transition: background ease .5s; + + &.active { + background: #7f8ea1; + } + + &:hover { + background: #7f8ea1; + } + } + +} \ No newline at end of file From abacd77520d3d1a57d4f9d4965fcf640a69d7f07 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Thu, 26 Dec 2024 13:52:38 +0300 Subject: [PATCH 40/56] Change display projects --- src/app/App.scss | 3 +- src/app/page.js | 52 +++++++--- src/assets/styles/mixins.scss | 83 +++++++++++----- src/components/ContentBlock/ContentBlock.scss | 14 +-- src/components/Projects/ProjectListItem.js | 37 +++++-- src/components/Projects/ProjectsList.js | 96 ++++++++++++++----- src/components/Projects/ProjectsList.scss | 31 +++++- .../Registration/RegistrationWindow.js | 4 +- src/components/UI/Pagination/Pagination.scss | 1 + src/lib/truncateText.js | 6 ++ 10 files changed, 245 insertions(+), 82 deletions(-) create mode 100644 src/lib/truncateText.js diff --git a/src/app/App.scss b/src/app/App.scss index b24f944..99665be 100644 --- a/src/app/App.scss +++ b/src/app/App.scss @@ -15,7 +15,7 @@ body { overflow: hidden; height: 100%; width: 100%; - padding: 40px 20px; + padding-left: 20px; &::before, &:after { background-color: #0075FF; @@ -59,6 +59,7 @@ body { display: flex; flex-direction: column; justify-content: space-between; + padding: 40px 0px; } @media screen and ( max-width: 1700px) { diff --git a/src/app/page.js b/src/app/page.js index aefa442..df4df97 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -9,10 +9,32 @@ import { BrowserRouter as Router } from 'react-router-dom' import ContentBlock from '@/components/ContentBlock/ContentBlock' import { usePathname } from 'next/navigation' import useGlobalStore from '@/store/store' - +import Dash from "dash"; const defaultContent = 'updates' -export default function App () { +export default function App() { + + useEffect(() => { + const addClient = async () => { + const clientOpts = { + network: 'testnet', + apps: { + tutorialContract: { + contractId: '2MfmHqYmAk1jAQNv7SsGJPT22MrfKFcHKZDc7cTu2biX', + }, + }, + }; + const client = new Dash.Client(clientOpts); + console.log('client', client) + // const documents = await client.platform.documents.get('dpns.domain', { + // limit: 100, + // offset: 0, + // }); + // console.log('documents', documents) + } + addClient() + }, []) + const [content, setContent] = useState(defaultContent) const [render, setRender] = useState(false) const path = usePathname() @@ -43,18 +65,18 @@ export default function App () { return render ? -
- -
- - { path.includes('admin') - ? null - : - } -
- -
-
-
+
+ +
+ + {path.includes('admin') + ? null + : + } +
+ +
+
+ : null } diff --git a/src/assets/styles/mixins.scss b/src/assets/styles/mixins.scss index 0ed3534..7587a79 100644 --- a/src/assets/styles/mixins.scss +++ b/src/assets/styles/mixins.scss @@ -2,12 +2,14 @@ $width-tablet: 940px; @mixin listItem { display: flex; - background: rgba(109, 124, 255, 0.07); - margin-bottom: 50px; + background: #1a212a; + margin-bottom: 12px; position: relative; - height: 200px; + gap: 30px; + min-height: 270px; transition: .5s box-shadow; box-shadow: none; + padding: 30px; &:hover { cursor: pointer; @@ -21,8 +23,8 @@ $width-tablet: 940px; } &__ImageContainer { - width: 200px; - height: 200px; + width: 220px; + height: 100%; background: rgba(109, 124, 255, 0.07); flex-shrink: 0; @@ -38,28 +40,63 @@ $width-tablet: 940px; } &__ContentContainer { - padding: 40px; - width: 100%; + width: 440px; + height: 100%; word-wrap: break-word; + padding-top: 20px; + padding-bottom: 10px; + } + + &__Dashmate { + color: #62cff6; + font-family: 'Press Start 2P'; + font-weight: 400; + font-size: 10px; + margin-bottom: 37px; + text-transform: uppercase; } &__Title { - color: #FFF; - font-family: Press Start 2P; - font-size: 18px; - font-style: normal; + font-family: 'Press Start 2P'; font-weight: 400; - line-height: 1.6; - margin-bottom: 10px; + font-size: 16px; + color: #fff; + margin-bottom: 16px; + } + + &__ButtonPendingClaims { + background-color: #ffbd07 !important; + } + + &__ButtonTasks { + + &.disabled { + border: 1px solid #2e3845; + color: #66727d !important; + background-color: transparent !important; + text-transform: capitalize !important; + + &::after { + background: transparent !important; + opacity: 1 !important; + } + } + } + + &__WrapperButtons { + display: flex; + gap: 12px; + align-self: center; + margin-top: 26px; + flex-wrap: wrap; } &__Description { - color: #A7A7A7; - font-family: Press Start 2P; - font-size: 14px; + color: #fff; + font-family: var(--font-mono); + font-size: 18px; font-style: normal; - font-weight: 400; - line-height: 24px; + font-weight: 700; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; @@ -68,10 +105,10 @@ $width-tablet: 940px; } @media screen and ( max-width: 1500px) { - margin-bottom: 30px; - &__ContentContainer { - padding: 32px 44px; + width: 100%; + padding-top: 20px; + padding-bottom: 10px; } &__Description { @@ -146,7 +183,7 @@ $width-tablet: 940px; &__Title { color: #FFF; - font-family: Press Start 2P; + font-family: 'Press Start 2P'; font-size: 18px; font-style: normal; font-weight: 400; @@ -156,7 +193,7 @@ $width-tablet: 940px; &__Description { color: #A7A7A7; - font-family: Press Start 2P; + font-family: 'Press Start 2P'; font-size: 14px; font-style: normal; font-weight: 400; diff --git a/src/components/ContentBlock/ContentBlock.scss b/src/components/ContentBlock/ContentBlock.scss index ce99baf..5f885cf 100644 --- a/src/components/ContentBlock/ContentBlock.scss +++ b/src/components/ContentBlock/ContentBlock.scss @@ -10,14 +10,16 @@ } &__ContentBlock { - padding: 50px; - border: 1px solid rgba(0, 117, 255, 0.35); - background: rgba(0, 117, 255, 0.01); + padding: 50px 40px; + padding-bottom: 36px; + background: #131619; backdrop-filter: blur(15px); height: 100%; - overflow-y: auto; - overflow-x: hidden; - + + > * { + height: 100%; + } + &__Title { font-size: 24px; } diff --git a/src/components/Projects/ProjectListItem.js b/src/components/Projects/ProjectListItem.js index da17d9a..aa2858e 100644 --- a/src/components/Projects/ProjectListItem.js +++ b/src/components/Projects/ProjectListItem.js @@ -1,14 +1,16 @@ import { motion as m } from 'framer-motion' import Image from 'next/image' -import './ProjectListItem.scss' import useGlobalStore from '@/store/store' import EditButton from '../UI/Button/EditButton/EditButton' +import './ProjectListItem.scss' +import { truncateText } from '@/lib/truncateText' +import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' -function ProjectListItem ({ project, openHandler, id, openEditor }) { +function ProjectListItem({ project, openHandler, id, openEditor }) { const admin = useGlobalStore(state => state.admin) return ( - {admin ?
e.stopPropagation()}> - +
- : null } + : null}
- {project.title + {project.title
-
{project.title}
-
{project.description}
+

{project.title}

+

{project.dashmate}

+

{truncateText(project.description, 75)}

+
+ 0 ? `${project.tasts.length} Tasks` : 'No Tasks'} + ariaLabel={'Tasks'} + disabled={project?.tasts?.length === 0} + /> + {project?.pendingClaims?.length > 0 ? + + : null + } +
-
+ ) } diff --git a/src/components/Projects/ProjectsList.js b/src/components/Projects/ProjectsList.js index 2e1fc9f..d62dda3 100644 --- a/src/components/Projects/ProjectsList.js +++ b/src/components/Projects/ProjectsList.js @@ -1,11 +1,11 @@ -import { useCallback, useState } from 'react' +import { useCallback, useMemo, useState } from 'react' +import { motion as m, AnimatePresence } from 'framer-motion' import ProjectListItem from './ProjectListItem' import Project from './Project' -import { motion as m, AnimatePresence } from 'framer-motion' -import './ProjectsList.scss' import useGlobalStore from '@/store/store' -import ActionButtons from '../UI/Button/ActionButtons/ActionButtons' import Pagination from '../UI/Pagination/Pagination' +import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton' +import './ProjectsList.scss' const defaultProjectsList = [ { @@ -13,28 +13,40 @@ const defaultProjectsList = [ description: 'A lightweight wallet for a Desktops & Android allow you to receive and spend Dash anywhere without downloading the blockchain with a PrivateSend support.', imgSrc: '/assets/img/dash-electrum-icon.png', githubLink: '', - projectLink: 'http://dash-electrum.org/' + projectLink: 'http://dash-electrum.org/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Platform Explorer', description: 'Block explorer for a brand new Dash Platform chain. Explore latest Dash Evolution data such as Identities, Data Contracts, and Documents.', imgSrc: '/assets/img/platform-explorer-preview-300x300.jpg', githubLink: 'https://github.com/pshenmic/platform-explorer', - projectLink: 'https://platform-explorer.com/' + projectLink: 'https://platform-explorer.com/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashmate Contribution', description: 'Masternode setup tool that drastically eases node configuration and setup with a nice & easy CLI interface. Built on top of Node.Js and Docker.', imgSrc: '/assets/img/dashmate-preview-300x300.jpg', githubLink: 'https://github.com/dashpay/platform/tree/master/packages/dashmate', - projectLink: 'https://www.dashmate.org/' + projectLink: 'https://www.dashmate.org/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashboards', description: 'Monitoring toolset that keeps track of the current state of the services deployed in the pshenmic cloud. Ensure yourself the SLA and stability of the provided services or be first to notice the fatal issues happening in cloud or blockchain network!', imgSrc: '/assets/img/dashboards-preview-400x400.png', githubLink: '', - projectLink: 'https://dashboards.pshenmic.dev/' + projectLink: 'https://dashboards.pshenmic.dev/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, // @@ -43,59 +55,86 @@ const defaultProjectsList = [ description: 'Masternode setup tool that drastically eases node configuration and setup with a nice & easy CLI interface. Built on top of Node.Js and Docker.', imgSrc: '/assets/img/dashmate-preview-300x300.jpg', githubLink: 'https://github.com/dashpay/platform/tree/master/packages/dashmate', - projectLink: 'https://www.dashmate.org/' + projectLink: 'https://www.dashmate.org/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashboards', description: 'Monitoring toolset that keeps track of the current state of the services deployed in the pshenmic cloud. Ensure yourself the SLA and stability of the provided services or be first to notice the fatal issues happening in cloud or blockchain network!', imgSrc: '/assets/img/dashboards-preview-400x400.png', githubLink: '', - projectLink: 'https://dashboards.pshenmic.dev/' + projectLink: 'https://dashboards.pshenmic.dev/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashmate Contribution', description: 'Masternode setup tool that drastically eases node configuration and setup with a nice & easy CLI interface. Built on top of Node.Js and Docker.', imgSrc: '/assets/img/dashmate-preview-300x300.jpg', githubLink: 'https://github.com/dashpay/platform/tree/master/packages/dashmate', - projectLink: 'https://www.dashmate.org/' + projectLink: 'https://www.dashmate.org/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashboards', description: 'Monitoring toolset that keeps track of the current state of the services deployed in the pshenmic cloud. Ensure yourself the SLA and stability of the provided services or be first to notice the fatal issues happening in cloud or blockchain network!', imgSrc: '/assets/img/dashboards-preview-400x400.png', githubLink: '', - projectLink: 'https://dashboards.pshenmic.dev/' + projectLink: 'https://dashboards.pshenmic.dev/', + dashmate: 'dash-electrum.com', + tasts: [], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashmate Contribution', description: 'Masternode setup tool that drastically eases node configuration and setup with a nice & easy CLI interface. Built on top of Node.Js and Docker.', imgSrc: '/assets/img/dashmate-preview-300x300.jpg', githubLink: 'https://github.com/dashpay/platform/tree/master/packages/dashmate', - projectLink: 'https://www.dashmate.org/' + projectLink: 'https://www.dashmate.org/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], }, { title: 'Dashboards', description: 'Monitoring toolset that keeps track of the current state of the services deployed in the pshenmic cloud. Ensure yourself the SLA and stability of the provided services or be first to notice the fatal issues happening in cloud or blockchain network!', imgSrc: '/assets/img/dashboards-preview-400x400.png', githubLink: '', - projectLink: 'https://dashboards.pshenmic.dev/' + projectLink: 'https://dashboards.pshenmic.dev/', + dashmate: 'dash-electrum.com', + tasts: ['test', 'test2', 'test3'], + pendingClaims: ['test', 'test2', 'test3'], } ] export default function ProjectsList({ projects = defaultProjectsList }) { const [openedItem, setOpenedItem] = useState(null) const admin = useGlobalStore(state => state.admin) + const setAdmin = useGlobalStore(state => state.setAdmin) const setOpenEditingWindow = useGlobalStore(state => state.setOpenEditingWindow) const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 5; + setAdmin(true) const handlePageChange = (pageNumber) => { setCurrentPage(pageNumber); } + const currentProjects = useMemo(() => { + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + return projects.slice(startIndex, endIndex); + }, [projects, currentPage, itemsPerPage]); + const openEditingWindow = useCallback(() => { setOpenEditingWindow(true) }, [setOpenEditingWindow]) - const ListItems = projects.map((project, id) => + const ListItems = currentProjects.map((project, id) => - {ListItems} +
+

Projects

+ {admin && openedItem === null + ? + : null} +
+
    + {ListItems} +
- {admin && openedItem === null - ? - : null} )} diff --git a/src/components/Projects/ProjectsList.scss b/src/components/Projects/ProjectsList.scss index 2b8c8b4..cdd98ca 100644 --- a/src/components/Projects/ProjectsList.scss +++ b/src/components/Projects/ProjectsList.scss @@ -1,11 +1,36 @@ .ProjectsList { display: flex; flex-direction: column; - align-items: center; + align-items: flex-start; + height: 100%; - @media screen and ( min-width: 500px ) and ( max-width: 680px ) { + &__Header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 37px; + gap: 12px; + width: 100%; + + > h2 { + font-weight: 400; + font-size: 16px; + color: #fff; + font-family: "Press Start 2P"; + text-transform: uppercase; + } + } + + > ul { + width: 100%; + overflow-y: auto; + overflow-x: hidden; + height: 100%; + } + + @media screen and (min-width: 500px) and (max-width: 680px) { display: flex; flex-wrap: wrap; justify-content: space-between; } -} +} \ No newline at end of file diff --git a/src/components/Registration/RegistrationWindow.js b/src/components/Registration/RegistrationWindow.js index a44d8b4..a23f9b2 100644 --- a/src/components/Registration/RegistrationWindow.js +++ b/src/components/Registration/RegistrationWindow.js @@ -11,9 +11,9 @@ import { easings, useTransition, animated } from '@react-spring/web'; import { useDash } from '@/hooks/useDashClient'; export default function RegistrationWindow() { + const setAdmin = useGlobalStore(state => state.setAdmin) const { userDash, setUserDash, setOpenImportWalletWindow, indexWallet } = useGlobalStore(); const { disconnect } = useDash(); - const [data, setData] = useState(null) const statusTextRef = useRef(null) const statusStyleRef = useRef({}) @@ -38,6 +38,7 @@ export default function RegistrationWindow() { />); statusTextRef.current.innerText = 'ADMIN'; statusStyleRef.current = { backgroundColor: '#8bcc49' }; + setAdmin(true) } else if (userDash?.[indexWallet]?.identifier) { setData(); statusTextRef.current.innerText = 'USER'; statusStyleRef.current = { backgroundColor: '#0275ff' }; + setAdmin(false) } } }, [userDash, indexWallet, setUserDash, handleLogout]); diff --git a/src/components/UI/Pagination/Pagination.scss b/src/components/UI/Pagination/Pagination.scss index f1d40ec..739666f 100644 --- a/src/components/UI/Pagination/Pagination.scss +++ b/src/components/UI/Pagination/Pagination.scss @@ -6,6 +6,7 @@ align-items: center; gap: 9px; width: 100%; + padding-top: 9px; &__Text { font-weight: 400; diff --git a/src/lib/truncateText.js b/src/lib/truncateText.js new file mode 100644 index 0000000..07d9e12 --- /dev/null +++ b/src/lib/truncateText.js @@ -0,0 +1,6 @@ +export function truncateText(text, maxLength) { + if (text.length > maxLength) { + return text.substring(0, maxLength) + '…' + } + return text; +} \ No newline at end of file From 05d44cffa59b96cff08af25a374d1a89163fed3f Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Thu, 26 Dec 2024 14:13:12 +0300 Subject: [PATCH 41/56] Add WrapperUserInputModal --- src/components/Projects/ProjectsList.js | 6 +- .../Registration/ImportWalletWindow.js | 86 ++++++++----------- .../WrapperUserInputModal.js | 22 +++++ .../WrapperUserInputModal.scss | 11 +++ 4 files changed, 75 insertions(+), 50 deletions(-) create mode 100644 src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js create mode 100644 src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss diff --git a/src/components/Projects/ProjectsList.js b/src/components/Projects/ProjectsList.js index d62dda3..55e24fa 100644 --- a/src/components/Projects/ProjectsList.js +++ b/src/components/Projects/ProjectsList.js @@ -1,4 +1,4 @@ -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { motion as m, AnimatePresence } from 'framer-motion' import ProjectListItem from './ProjectListItem' import Project from './Project' @@ -119,7 +119,9 @@ export default function ProjectsList({ projects = defaultProjectsList }) { const setOpenEditingWindow = useGlobalStore(state => state.setOpenEditingWindow) const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 5; - setAdmin(true) + useEffect(() => { + setAdmin(true) + }, []) const handlePageChange = (pageNumber) => { setCurrentPage(pageNumber); } diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index 76a8047..d44806f 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -7,11 +7,11 @@ import { showToast } from '@/lib/showToast'; import { validateMnemonic } from 'bip39'; import { useDash } from '@/hooks/useDashClient'; import useGlobalStore from "@/store/store"; -import DarkWrapper from "../UI/DarkWrapper/DarkWrapper"; import Image from "next/image"; import RegistrationForm from "./RegistrationForm"; import Loading from '../UI/Loading/Loading'; import localforage from 'localforage'; +import WrapperUserInputModal from '../UI/WrapperUserInputModal/WrapperUserInputModal'; const dataSeedPhrase = { description: 'Make sure your device is safe & no one is watching, don\'t show this info to anyone.', @@ -90,14 +90,6 @@ export default function ImportWalletWindow() { }, [setLoadingGetUser, setOpenImportWalletWindow, setUserDash, errorCallback, successCallback]); - const animation = useSpring({ - transform: openImportWalletWindow ? 'translateX(0%)' : 'translateX(100%)', - config: { - tension: 200, - friction: 30 - } - }); - const animationLoading = useSpring({ opacity: loadingGetUser ? 1 : 0, pointerEvents: loadingGetUser ? 'auto' : 'none', @@ -127,46 +119,44 @@ export default function ImportWalletWindow() { }) return ( - setOpenImportWalletWindow(false)} > - e.stopPropagation()}> - -
- -
-

It usually takes up to 3 minutes to connect to the blockchain. You can continue using the platform, and we will notify you once the process is successful or if it fails.

-
- -
-

IMPORT WALLET

-
- - -
- {transitions((style, item) => - - {item} - - )} + + +
+
+

It usually takes up to 3 minutes to connect to the blockchain. You can continue using the platform, and we will notify you once the process is successful or if it fails.

- + +
+

IMPORT WALLET

+
+ + +
+ {transitions((style, item) => + + {item} + + )} +
+
) } \ No newline at end of file diff --git a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js new file mode 100644 index 0000000..d80895a --- /dev/null +++ b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js @@ -0,0 +1,22 @@ +'use client' + +import { useSpring, animated } from '@react-spring/web'; +import DarkWrapper from '../DarkWrapper/DarkWrapper'; +import './WrapperUserInputModal.scss' + +export default function WrapperUserInputModal({ children, open, setOpen }) { + const animation = useSpring({ + transform: open ? 'translateX(0%)' : 'translateX(100%)', + config: { + tension: 200, + friction: 30 + } + }); + return ( + setOpen(false)} > + e.stopPropagation()}> + {children} + + + ) +} \ No newline at end of file diff --git a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss new file mode 100644 index 0000000..035833c --- /dev/null +++ b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss @@ -0,0 +1,11 @@ +@import '../../../assets/styles/mixins.scss'; + +.WalletWindow { + position: fixed; + top: 0; + right: 0; + width: 800px; + height: 100vh; + background-color: #fff; + z-index: 11; +} \ No newline at end of file From 24dec22ae61a43625d28c55f9d3a9626361e8898 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Fri, 27 Dec 2024 00:41:29 +0300 Subject: [PATCH 42/56] Change FileInput --- public/assets/img/pictureOfaBlindfold.png | Bin 0 -> 531 bytes .../PageEditingWindows/PageEditingWindows.js | 2 +- .../PageEditingWindows.scss | 18 +-- .../ProjectEditingWindow.js | 127 +++--------------- .../Registration/ImportWalletWindow.js | 7 - .../Registration/ImportWalletWindow.scss | 46 ------- .../UI/EditingWindow/EditingWindow.js | 47 ++----- .../UI/EditingWindow/EditingWindow.scss | 108 +-------------- src/components/UI/FileInput/FileInput.js | 37 ++--- src/components/UI/FileInput/FileInput.scss | 76 +++++------ .../WrapperUserInputModal.js | 14 ++ .../WrapperUserInputModal.scss | 38 ++++++ 12 files changed, 140 insertions(+), 380 deletions(-) create mode 100644 public/assets/img/pictureOfaBlindfold.png diff --git a/public/assets/img/pictureOfaBlindfold.png b/public/assets/img/pictureOfaBlindfold.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac5041bfa08e5309bf1e8fca453f0c7669581c4 GIT binary patch literal 531 zcmeAS@N?(olHy`uVBq!ia0vp^DIm``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBxfPx+jv*C{Z|_9=G6#w{T-0=AV6^sdU=Z>s zXkd_;puouJae$A7U7_LU4$t~N;{7z2q;yPcLmdMnV zuif+?L?&M}SA?38R_7OA8Ln_wNW7Z!%dopnyZi=R zZ=2O}yI)oF { path === '/admin' && } { path === '/admin/services' && } - { path === '/admin/projects' && } + { path === '/projects' && } { path === '/admin/team' && } ) diff --git a/src/components/PageEditingWindows/PageEditingWindows.scss b/src/components/PageEditingWindows/PageEditingWindows.scss index ef18659..e4f6139 100644 --- a/src/components/PageEditingWindows/PageEditingWindows.scss +++ b/src/components/PageEditingWindows/PageEditingWindows.scss @@ -1,14 +1,16 @@ @import '../../assets/styles/mixins.scss'; -.WrapperButton { +.ProjectEditingWindow { position: relative; - padding: 0px 64px; + width: 100%; + display: flex; + flex-direction: column; + gap: 50px; - @media screen and ( max-width: 1024px ) { - padding: 0px 32px; - } - - @media screen and ( max-width: 600px ) { - padding: 0px 16px; + > h2 { + font-weight: 400; + font-size: 16px; + color: #000; + font-family: 'Press Start 2P'; } } \ No newline at end of file diff --git a/src/components/PageEditingWindows/ProjectEditingWindow.js b/src/components/PageEditingWindows/ProjectEditingWindow.js index 582953d..aa4a3ce 100644 --- a/src/components/PageEditingWindows/ProjectEditingWindow.js +++ b/src/components/PageEditingWindows/ProjectEditingWindow.js @@ -1,118 +1,25 @@ -import { useCallback, useState } from 'react' -import EditFieldWrapper from '../UI/EditFieldWrapper/EditFieldWrapper' -import FileInput from '../UI/FileInput/FileInput' -import TextField from '../UI/TextField/TextField' -import ActionButtons from '../UI/Button/ActionButtons/ActionButtons' +import Image from 'next/image' import './PageEditingWindows.scss' +import FileInput from '../UI/FileInput/FileInput' function ProjectEditingWindow ({ errors, register, setValue, clearErrors }) { - const [link, setLink] = useState([]) - - const addField = useCallback(() => { - setLink([...link, { id: Date.now() }]) - }, [link]) - - const removeField = useCallback((id) => { - setLink(link.filter(field => field.id !== id)) - }, [link]) return ( - <> - - - - - - - - - - - {link.map((field, i) => ( - - - - - - removeField(field.id)} - ariaLabel={'Delete project'} - typeButton={'dangerous'} - /> - - ))} -
- -
- +
+

CREATE A NEW PROJECT

+
+
+ {'Project +
+
+

Project name...

+

project link....

+

+
+
+ +
) } diff --git a/src/components/Registration/ImportWalletWindow.js b/src/components/Registration/ImportWalletWindow.js index d44806f..9918d50 100644 --- a/src/components/Registration/ImportWalletWindow.js +++ b/src/components/Registration/ImportWalletWindow.js @@ -126,13 +126,6 @@ export default function ImportWalletWindow() {

It usually takes up to 3 minutes to connect to the blockchain. You can continue using the platform, and we will notify you once the process is successful or if it fails.

-

IMPORT WALLET

diff --git a/src/components/Registration/ImportWalletWindow.scss b/src/components/Registration/ImportWalletWindow.scss index bd56027..7cbf219 100644 --- a/src/components/Registration/ImportWalletWindow.scss +++ b/src/components/Registration/ImportWalletWindow.scss @@ -1,12 +1,4 @@ .ImportWalletWindow { - position: fixed; - top: 0; - right: 0; - width: 800px; - height: 100vh; - background-color: #fff; - z-index: 11; - &__ContainerLoading { position: absolute; left: 0; @@ -46,44 +38,6 @@ gap: 50px; } - &__CloseButton { - position: absolute; - top: 0; - left: 0; - transform: translate(-100%, 0%); - cursor: pointer; - height: 100%; - width: 64px; - background: rgba(45, 59, 75, 0.71); - font-family: "Press Start 2P"; - display: flex; - justify-content: center; - padding-top: 24px; - - &__Icon { - width: 16px; - height: 16px; - } - - &::before { - content: ''; - position: absolute; - height: 100%; - width: 0; - top: 0; - left: 0; - background: rgba(0, 117, 255, 0.10); - transition: .5s; - } - - &:hover { - &:before { - animation-duration: .5s; - animation-name: slidein; - } - } - } - &__Title { font-family: "Press Start 2P"; font-weight: 400; diff --git a/src/components/UI/EditingWindow/EditingWindow.js b/src/components/UI/EditingWindow/EditingWindow.js index 80742b5..c22c0a7 100644 --- a/src/components/UI/EditingWindow/EditingWindow.js +++ b/src/components/UI/EditingWindow/EditingWindow.js @@ -8,8 +8,9 @@ import ActionButtons from '../Button/ActionButtons/ActionButtons' import Image from 'next/image' import PageEditingWindows from '@/components/PageEditingWindows/PageEditingWindows' import './EditingWindow.scss' +import WrapperUserInputModal from '../WrapperUserInputModal/WrapperUserInputModal' -function EditingWindow () { +function EditingWindow() { const openEditingWindow = useGlobalStore(state => state.openEditingWindow) const setOpenEditingWindow = useGlobalStore(state => state.setOpenEditingWindow) const admin = useGlobalStore(state => state.admin) @@ -34,40 +35,16 @@ function EditingWindow () { return ( <> {admin - ? -
- - -
- -
-
- - -
- -
-
+ ? +
+ + +
: null} ) diff --git a/src/components/UI/EditingWindow/EditingWindow.scss b/src/components/UI/EditingWindow/EditingWindow.scss index 5d8c1c0..117b2eb 100644 --- a/src/components/UI/EditingWindow/EditingWindow.scss +++ b/src/components/UI/EditingWindow/EditingWindow.scss @@ -1,107 +1 @@ -@import '../../../assets/styles/mixins.scss'; - -.EditingWindow { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - padding: 64px 0px; - display: flex; - justify-content: center; - - @media screen and ( max-width: 1024px ) { - padding: 40px; - } - - @media screen and ( max-width: 600px ) { - padding: 40px 16px; - } - - &__Close { - position: absolute; - top: 20px; - right: 20px; - width: 24px; - height: 24px; - cursor: pointer; - opacity: 1; - transform: scale(1); - transition: transform ease 0.5s, opacity ease 0.5s; - background-color: transparent; - - > img { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100% - } - - &:hover { - transform: scale(1.1); - opacity: 0.8; - } - } - - &__Window { - position: relative; - padding: 64px 0px; - background: #050505; - height: 100%; - width: 900px; - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: flex-start; - gap: 64px; - border: 1px solid #2c2c2c; - - @media screen and ( max-width: 1024px ) { - gap: 32px; - padding: 32px 0px; - padding-top: 60px; - } - - @media screen and ( max-width: 600px ) { - gap: 32px; - padding: 16px 0px; - padding-top: 60px; - } - } - - &__WrapperEditableFields { - position: relative; - display: flex; - flex-direction: column; - gap: 32px; - width: 100%; - overflow: auto; - - > :nth-child(2n) { - background-color: #202020; - } - - @media screen and ( max-width: 600px ) { - gap: 10px; - } - } - - &__WrapperButton { - position: relative; - display: flex; - align-items: center; - gap: 32px; - flex-wrap: wrap; - padding: 0px 64px; - - @media screen and ( max-width: 1024px ) { - padding: 0px 32px; - } - - @media screen and ( max-width: 600px ) { - gap: 16px; - padding: 0px 16px; - } - } -} \ No newline at end of file +@import '../../../assets/styles/mixins.scss'; \ No newline at end of file diff --git a/src/components/UI/FileInput/FileInput.js b/src/components/UI/FileInput/FileInput.js index 6447bc1..7369888 100644 --- a/src/components/UI/FileInput/FileInput.js +++ b/src/components/UI/FileInput/FileInput.js @@ -5,7 +5,7 @@ import { useEffect, useState } from 'react' import Image from 'next/image' import './FileInput.scss' -function FileInput ({ clearErrors, setValue, error, text, mountedPicture, name, required = true, register }) { +function FileInput({ clearErrors, setValue, error, textName, textLink, textDescription, mountedPicture, name, register }) { const [files, setFiles] = useState([]) const { hasOwnProperty } = Object.prototype // TODO sending a picture to the server (filesserv) @@ -62,39 +62,28 @@ function FileInput ({ clearErrors, setValue, error, text, mountedPicture, name, return (
- {text - ?

{text}{required && *}

- : null} - -
- {files.length > 0 - ? - : null - } +
{files.length !== 0 ? thumbs : {'avatar'} + src={mountedPicture || '/assets/img/pictureOfaBlindfold.png'} + width={100} + height={100} + alt={'Preview Image'} + /> }
+
+

{textName || 'Project name...'}

+

{textLink || 'project link....'}

+ { textDescription &&

{textDescription}

} +
) } diff --git a/src/components/UI/FileInput/FileInput.scss b/src/components/UI/FileInput/FileInput.scss index 2490fff..034a3ee 100644 --- a/src/components/UI/FileInput/FileInput.scss +++ b/src/components/UI/FileInput/FileInput.scss @@ -1,59 +1,22 @@ @import '../../../assets/styles/mixins.scss'; .FileInput { - position: relative; width: 100%; + background-color: #d2e8fe; display: flex; - flex-direction: column; - gap: 8px; - - > p { - font-size: 18px; - color: #8F8F8F; - - @media screen and ( max-width: 1024px ) { - font-size: 14px; - } - - @media screen and ( max-width: 600px ) { - font-size: 10px; - } - - > span { - color: #7D0000; - } - } + align-items: center; &__Error { border: 2px solid #fe5858 !important; } - &__Delete { - position: absolute; - z-index: 10; - padding: 3px; - border: 1px solid #fe5858; - color: #fe5858; - opacity: 1; - transition: opacity ease 0.5s; - cursor: pointer; - font-size: 12; - top: 5px; - right: 5px; - - &:hover { - opacity: 0.7; - } - } - &__Avatar { position: relative; - width: 200px; - height: 200px; + width: 100px; + height: 100px; overflow: hidden; cursor: pointer; flex-shrink: 0; - border: 1px solid #a09d9d; @media screen and ( max-width: 1024px ) { width: 150px; @@ -76,4 +39,33 @@ } } } -} + + &__Info { + display: flex; + flex-direction: column; + gap: 10px; + width: 100%; + padding: 20px 16px 20px 30px; + + &__Name { + font-weight: 400; + font-size: 16px; + color: #000; + font-family: 'Press Start 2P'; + } + + &__Link { + font-weight: 400; + font-size: 10px; + color: #008de4; + font-family: 'Press Start 2P'; + } + + &__Description { + font-weight: 400; + font-size: 12px; + color: #000; + font-family: 'Press Start 2P'; + } + } +} \ No newline at end of file diff --git a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js index d80895a..8879808 100644 --- a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js +++ b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.js @@ -2,6 +2,7 @@ import { useSpring, animated } from '@react-spring/web'; import DarkWrapper from '../DarkWrapper/DarkWrapper'; +import Image from 'next/image'; import './WrapperUserInputModal.scss' export default function WrapperUserInputModal({ children, open, setOpen }) { @@ -15,6 +16,19 @@ export default function WrapperUserInputModal({ children, open, setOpen }) { return ( setOpen(false)} > e.stopPropagation()}> + {children} diff --git a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss index 035833c..72ba826 100644 --- a/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss +++ b/src/components/UI/WrapperUserInputModal/WrapperUserInputModal.scss @@ -8,4 +8,42 @@ height: 100vh; background-color: #fff; z-index: 11; + + &__CloseButton { + position: absolute; + top: 0; + left: 0; + transform: translate(-100%, 0%); + cursor: pointer; + height: 100%; + width: 64px; + background: rgba(45, 59, 75, 0.71); + font-family: "Press Start 2P"; + display: flex; + justify-content: center; + padding-top: 24px; + + &__Icon { + width: 16px; + height: 16px; + } + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 0; + top: 0; + left: 0; + background: rgba(0, 117, 255, 0.10); + transition: .5s; + } + + &:hover { + &:before { + animation-duration: .5s; + animation-name: slidein; + } + } + } } \ No newline at end of file From 025eeeb6b5d5a4481124f4490175452478b750c0 Mon Sep 17 00:00:00 2001 From: Den Kravchu Date: Fri, 27 Dec 2024 13:51:00 +0300 Subject: [PATCH 43/56] Changed form of content editing --- .../HasAdminAccess/HasAdminAccess.js | 4 +- .../PageEditingWindows/PageEditingWindows.js | 10 +-- .../PageEditingWindows.scss | 6 ++ .../ProjectEditingWindow.js | 68 +++++++++++++---- .../UI/EditingWindow/EditingWindow.js | 29 ++++--- src/components/UI/FileInput/FileInput.js | 10 ++- src/components/UI/TextField/TextField.js | 65 ++++++++++------ src/components/UI/TextField/TextField.scss | 76 ++++++++++--------- 8 files changed, 169 insertions(+), 99 deletions(-) diff --git a/src/components/HasAdminAccess/HasAdminAccess.js b/src/components/HasAdminAccess/HasAdminAccess.js index c4529cd..7062fde 100644 --- a/src/components/HasAdminAccess/HasAdminAccess.js +++ b/src/components/HasAdminAccess/HasAdminAccess.js @@ -29,13 +29,13 @@ function HasAdminAccess () {

pshenmic.admin

- + /> */}
diff --git a/src/components/PageEditingWindows/PageEditingWindows.js b/src/components/PageEditingWindows/PageEditingWindows.js index 778b7b5..561a7e8 100644 --- a/src/components/PageEditingWindows/PageEditingWindows.js +++ b/src/components/PageEditingWindows/PageEditingWindows.js @@ -7,15 +7,15 @@ import ProjectEditingWindow from './ProjectEditingWindow' import { usePathname } from 'next/navigation' import './PageEditingWindows.scss' -function PageEditingWindows ({ clearErrors, errors, register, setValue }) { +function PageEditingWindows () { const path = usePathname() return ( <> - { path === '/admin' && } - { path === '/admin/services' && } - { path === '/projects' && } - { path === '/admin/team' && } + {/* { path === '/admin' && } */} + {/* { path === '/admin/services' && } */} + { path === '/projects' && } + {/* { path === '/admin/team' && } */} ) } diff --git a/src/components/PageEditingWindows/PageEditingWindows.scss b/src/components/PageEditingWindows/PageEditingWindows.scss index e4f6139..fa4b02f 100644 --- a/src/components/PageEditingWindows/PageEditingWindows.scss +++ b/src/components/PageEditingWindows/PageEditingWindows.scss @@ -6,6 +6,7 @@ display: flex; flex-direction: column; gap: 50px; + padding: 60px 100px; > h2 { font-weight: 400; @@ -13,4 +14,9 @@ color: #000; font-family: 'Press Start 2P'; } + + &__Button { + width: 100% !important; + background-color: #0275ff !important; + } } \ No newline at end of file diff --git a/src/components/PageEditingWindows/ProjectEditingWindow.js b/src/components/PageEditingWindows/ProjectEditingWindow.js index aa4a3ce..f3ce680 100644 --- a/src/components/PageEditingWindows/ProjectEditingWindow.js +++ b/src/components/PageEditingWindows/ProjectEditingWindow.js @@ -1,24 +1,60 @@ -import Image from 'next/image' +'use client' + import './PageEditingWindows.scss' import FileInput from '../UI/FileInput/FileInput' +import TextField from '../UI/TextField/TextField' +import { useFormContext, useWatch } from 'react-hook-form'; +import RegistrationButton from '../UI/Button/RegistrationButton/RegistrationButton'; -function ProjectEditingWindow ({ errors, register, setValue, clearErrors }) { - +function ProjectEditingWindow() { + const { control } = useFormContext(); + const inputValueName = control ? useWatch({ control, name: 'name_ProjectEditingWindow' }) : ''; + const inputValueDescription = control ? useWatch({ control, name: 'description_ProjectEditingWindow' }) : ''; + const inputValueUrl = control ? useWatch({ control, name: 'url_ProjectEditingWindow' }) : ''; + const image = control ? useWatch({ control, name: 'projectEditingWindow__ImageCard__Image' }) : ''; + console.log(image) return (
-

CREATE A NEW PROJECT

-
-
- {'Project -
-
-

Project name...

-

project link....

-

-
-
- +

CREATE A NEW PROJECT

+ + + + + + + + +
) } diff --git a/src/components/UI/EditingWindow/EditingWindow.js b/src/components/UI/EditingWindow/EditingWindow.js index c22c0a7..ae5ab3e 100644 --- a/src/components/UI/EditingWindow/EditingWindow.js +++ b/src/components/UI/EditingWindow/EditingWindow.js @@ -1,20 +1,19 @@ 'use client' -import { useForm } from 'react-hook-form' +import { FormProvider, useForm } from 'react-hook-form' import { useEffect } from 'react' import useGlobalStore from '@/store/store' -import DarkWrapper from '../DarkWrapper/DarkWrapper' -import ActionButtons from '../Button/ActionButtons/ActionButtons' -import Image from 'next/image' import PageEditingWindows from '@/components/PageEditingWindows/PageEditingWindows' -import './EditingWindow.scss' import WrapperUserInputModal from '../WrapperUserInputModal/WrapperUserInputModal' +import './EditingWindow.scss' function EditingWindow() { const openEditingWindow = useGlobalStore(state => state.openEditingWindow) const setOpenEditingWindow = useGlobalStore(state => state.setOpenEditingWindow) const admin = useGlobalStore(state => state.admin) - const { register, handleSubmit, formState: { errors }, setValue, clearErrors } = useForm() + + const methods = useForm() + const { register, handleSubmit, formState: { errors }, setValue, clearErrors, control } = methods const onSubmit = (data) => { console.log(data) @@ -35,16 +34,14 @@ function EditingWindow() { return ( <> {admin - ? -
- - -
+ ? + + +
+ + +
+
: null} ) diff --git a/src/components/UI/FileInput/FileInput.js b/src/components/UI/FileInput/FileInput.js index 7369888..8c0bedf 100644 --- a/src/components/UI/FileInput/FileInput.js +++ b/src/components/UI/FileInput/FileInput.js @@ -2,11 +2,13 @@ import { useDropzone } from 'react-dropzone' import { useEffect, useState } from 'react' +import { useFormContext } from 'react-hook-form' import Image from 'next/image' import './FileInput.scss' -function FileInput({ clearErrors, setValue, error, textName, textLink, textDescription, mountedPicture, name, register }) { +function FileInput({ textName, textLink, textDescription, mountedPicture, name, }) { const [files, setFiles] = useState([]) + const { control, clearErrors, setValue, formState: { errors }, register } = useFormContext(); const { hasOwnProperty } = Object.prototype // TODO sending a picture to the server (filesserv) // const [serverFiles, setServerFiles] = useState() @@ -50,8 +52,8 @@ function FileInput({ clearErrors, setValue, error, textName, textLink, textDescr {''}
)) @@ -62,7 +64,7 @@ function FileInput({ clearErrors, setValue, error, textName, textLink, textDescr return (
-
+
{files.length !== 0 ? thumbs : { + if (textareaRef?.current) { + textareaRef.current.style.minHeight = `auto` + textareaRef.current.style.minHeight = `${textareaRef.current.scrollHeight}px` + } + }, [inputValue]); return ( -
- {text ?

{text}{required && *}

: null} - {richText - ?