diff --git a/app/[username]/page.tsx b/app/[username]/page.tsx
index 03d5613..d45ce66 100644
--- a/app/[username]/page.tsx
+++ b/app/[username]/page.tsx
@@ -11,6 +11,7 @@ export default function UserProfile() {
const params = useParams();
const {
handleConnectWallet,
+ signer,
isConnecting,
isConnected,
} = useBlockchain();
@@ -41,7 +42,7 @@ export default function UserProfile() {
}, [isConnected, isConnecting, handleConnectWallet]);
useEffect(() => {
- if (isConnected && username.length > 0 && !isFetching) {
+ if (isConnected && signer && username.length > 0 && !isFetching) {
setIsFetching(true);
getProfileByUsername(username).then(res => {
const cleanedData = parseResult(res);
@@ -55,13 +56,12 @@ export default function UserProfile() {
)
})
.catch(err => {
- debugger
console.log(err);
}).finally(() => {
setIsFetching(false);
})
}
- }, [isFetching, isConnected, username, getProfileByUsername, setUserProfile]);
+ }, [isConnected, signer, username, getProfileByUsername, setUserProfile]);
function parseResult(result: string[]) {
// Initialize arrays for Web2 and Web3 items
@@ -103,8 +103,11 @@ export default function UserProfile() {
// set the profile data into the global state
return (
- {isConnecting ? <>Connecting ...> : ''}
- {isConnected && isFetching ? <>Reading Blockchain Data ...> : ''}
+
+ {isConnecting ? Connecting ... : ''}
+ {isConnected && isFetching ? Reading Blockchain Data ... : ''}
+
+
{isConnected && !isFetching ?
: ''}
diff --git a/app/layout.tsx b/app/layout.tsx
index 6c4aed7..db31111 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -38,32 +38,15 @@ export default function RootLayout({
+
+ LinkTrueJoin now!
+
-
-
+ {children}
diff --git a/app/page.tsx b/app/page.tsx
index 84cccba..4e19028 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,56 +1,93 @@
-"use client"
-// import Image from "next/image";
-import { useSteps, Steps } from '../context/StepsContext';
+"use client";
+import Image from "next/image";
+import { useSteps, Steps } from "../context/StepsContext";
-import Step1 from '../components/steps/S1Main';
-import Step2 from '../components/steps/S2Username';
-import Step3 from '../components/steps/S3Web2Items';
-import Step4 from '../components/steps/S4Web3Items';
-import Step5 from '../components/steps/S5Preview';
+import Step1 from "../components/steps/S1Main";
+import Step2 from "../components/steps/S2Username";
+import Step3 from "../components/steps/S3Web2Items";
+import Step4 from "../components/steps/S4Web3Items";
+import Step5 from "../components/steps/S5Preview";
export default function Home() {
const { currentStep } = useSteps();
return (
-
-
+ {/* Use flex and set minimum height to screen height */}
+
{currentStep} */}
+ >
+ {currentStep === Steps.Main && }
+ {currentStep === Steps.Username && }
+ {currentStep === Steps.Web2Addresses && }
+ {currentStep === Steps.Web3Addresses && }
+ {currentStep === Steps.Preview && }
+
- {currentStep === Steps.Main && (
-
- )}
-
- {currentStep === Steps.Username && (
-
- )}
- {currentStep === Steps.Web2Addresses && (
-
- )}
-
- {currentStep === Steps.Web3Addresses && (
-
- )}
-
- {currentStep === Steps.Preview &&
-
- }
+
-
-
-
+
);
}
diff --git a/components/ChainsComboBox.jsx b/components/ChainsComboBox.jsx
index 7f31d21..4373e7f 100644
--- a/components/ChainsComboBox.jsx
+++ b/components/ChainsComboBox.jsx
@@ -53,11 +53,13 @@ const ChainsComboBox = forwardRef(({ onSelect }, ref) => {
src={option.value}
alt={option.label}
style={{ width: 20, marginRight: 10 }}
+ width={20}
+ height={20}
/>
{option.label}
)}
- placeholder="Search the Native coin name..."
+ placeholder="Select the coin name..."
isClearable
/>
diff --git a/components/ConnectWallet.tsx b/components/ConnectWallet.tsx
index 129f1f3..5fc031c 100644
--- a/components/ConnectWallet.tsx
+++ b/components/ConnectWallet.tsx
@@ -22,7 +22,9 @@ const BlockchainComponent: React.FC = () => {
"
onClick={() => handleConnectWallet(true)}
>
- {isConnecting ? 'Waiting for MetaMask to connect...' : 'Connect Wallet'}
+ {isConnecting ? (
+ ()
+ ) : 'Connect Wallet'}
)}
diff --git a/components/EllipsifiedAddress.tsx b/components/EllipsifiedAddress.tsx
index 3c53013..019cb17 100644
--- a/components/EllipsifiedAddress.tsx
+++ b/components/EllipsifiedAddress.tsx
@@ -28,7 +28,7 @@ const EllipsifiedAddress = ({ walletAddress }: { walletAddress: string }) => {
}
}
>
-
+
{ellipsify(walletAddress)} {" "}
diff --git a/components/Preview.tsx b/components/Preview.tsx
index 23f6610..1378b27 100644
--- a/components/Preview.tsx
+++ b/components/Preview.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { QRCodeSVG } from 'qrcode.react';
import { Button } from "@/components/ui/button"
import { Web3Item } from "@/context/GlobalStateContext";
@@ -7,11 +7,12 @@ import { copyToClipboard } from '@/lib/utils'
import Web3ItemsComboBox from '@/components/Web3ItemsComboBox';
import { useGlobalState } from '@/context/GlobalStateContext';
import Image from "next/image";
+import { toast } from "sonner";
const Preview = () => {
+ const [pageUrl, setPageUrl] = useState('');
const { userProfile } = useGlobalState();
const [selectedWeb3Item, setSelectedWeb3Item] = useState({
- title: '',
icon: '',
walletAddress: ''
});
@@ -20,78 +21,99 @@ const Preview = () => {
setSelectedWeb3Item(option);
};
+ const shareOnTwitter = () => {
+ const twitterUrl = `https://twitter.com/share?url=${encodeURIComponent(pageUrl)}`;
+ window.open(twitterUrl, '_blank');
+ };
+
+ const shareOnFacebook = () => {
+ const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(pageUrl)}`;
+ window.open(facebookUrl, '_blank');
+ };
+
+ const shareOnWhatsApp = () => {
+ const whatsappUrl = `https://api.whatsapp.com/send?text=${encodeURIComponent(pageUrl)}`;
+ window.open(whatsappUrl, '_blank');
+ };
+
+ useEffect(() => {
+ if (userProfile.username)
+ setPageUrl(`https://miladtsx.github.io/linktrue_client/${userProfile.username}`);
+ }, [userProfile.username])
+
+
return (
-
-
- {/*
- TODO find a reliable service allowing uploading files.
- IPFS?
-
*/}
-
-
@ {userProfile.username}
-
-
- {userProfile.web2Items.map((item, index) => (
-
-
-
-
-
- ))}
-
-
-
- {userProfile.web3Items.length > 0 && (
-
-
-
- )}
-
- {selectedWeb3Item.walletAddress && (
- <>
-
-
-
-
or Scan the QR Code
-
+
+
+
@ {userProfile.username}
+
+
+
+
);
};
diff --git a/components/SocialMediaComboBox.jsx b/components/SocialMediaComboBox.jsx
index 57be7b0..2e14a9d 100644
--- a/components/SocialMediaComboBox.jsx
+++ b/components/SocialMediaComboBox.jsx
@@ -41,6 +41,7 @@ const SocialMediaComboBox = forwardRef(({ onSelect, autoFocus = false }, ref) =>
return (
)}
- placeholder="Search social media icons..."
+ placeholder="Search for icon..."
isClearable
autoFocus={autoFocus}
/>
diff --git a/components/Web3ItemsComboBox.jsx b/components/Web3ItemsComboBox.jsx
index f86f290..f638510 100644
--- a/components/Web3ItemsComboBox.jsx
+++ b/components/Web3ItemsComboBox.jsx
@@ -63,11 +63,13 @@ const Web3ItemsComboBox = forwardRef(({ onSelect }, ref) => {
src={option.value}
alt={option.label}
style={{ width: 20, marginRight: 10 }}
+ width={20}
+ height={20}
/>
{option.label}
)}
- placeholder={`Choose wallet address`}
+ placeholder={`Select a wallet address`}
isClearable
/>
diff --git a/components/steps/S1Main.tsx b/components/steps/S1Main.tsx
index 7e6e718..a2678d4 100644
--- a/components/steps/S1Main.tsx
+++ b/components/steps/S1Main.tsx
@@ -4,56 +4,100 @@ import { useSteps } from '@/context/StepsContext'
import { useBlockchain } from "@/context/BlockchainProvider";
import BlockchainComponent from '../ConnectWallet';
import Link from 'next/link';
+import Typed from 'typed.js';
+import { useEffect, useRef } from 'react';
const S1Main = () => {
const { nextStep } = useSteps();
const { signer } = useBlockchain();
+ // Create a reference to attach the Typed.js animation
+ const typedElement = useRef(null);
+
+ useEffect(() => {
+ const typed = new Typed(typedElement.current, {
+ strings: [
+ 'Influencers',
+ 'Entrepreneurs',
+ 'Creators',
+ "Solo Builders",
+
+ ],
+ typeSpeed: 50,
+ backSpeed: 50,
+ loop: true,
+ fadeOut: false,
+ });
+
+ return () => {
+ typed.destroy(); // Destroy Typed.js instance on unmount
+ };
+ }, []);
+
+ console.log(signer?.address);
+
+
return (
- <>
-
- Securely Share Your Crypto Addresses with Full Control
-
-
-
- -
- Full Ownership: Only {signer ?
- <>
- {"owns"}
- >
- : "YOU own"} all data
-
- -
- Exclusive Access: Only {" "}
- {signer ? : "YOU "} can modify data
-
-
-
-
- Explore a sample profile to see how it looks {" "}
+
+
+
+ For
+
+
+
+ Share a single link in your bio: containing your wallet addresses and any www website.
+
+
+
LinkTrue
+
+
+ Unlike Linktr.ee, LinkTrue is fully decentralized and open-source, giving you complete ownership of your data without relying on third parties.
+
+
+
+ Own your data. Share with confidence.
+
+ Try now
+
+
+
+
+ {signer &&
+
+ }
+
+
+
+ View a sample profile{' '}
-
-
+
- < BlockchainComponent />
-
- {
- signer &&
+
+ {signer && (
- }
-
-
- >
- )
+ )}
+
+
+
+ );
};
export default S1Main;
diff --git a/components/steps/S2Username.tsx b/components/steps/S2Username.tsx
index dcf5718..9445891 100644
--- a/components/steps/S2Username.tsx
+++ b/components/steps/S2Username.tsx
@@ -2,8 +2,10 @@
import { useSteps } from '@/context/StepsContext'
import { useGlobalState } from "@/context/GlobalStateContext";
import { useContractMethods } from '@/hooks/useContractMethods';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
import { useLogger } from '@/context/LoggerContext';
+import { Input } from '@/components/ui/input';
+import { toast } from 'sonner';
const S2Username = () => {
const { logException } = useLogger();
@@ -22,6 +24,7 @@ const S2Username = () => {
const { isUsernameAvailable } = useContractMethods();
const [isChecking, setIsChecking] = useState(false);
+ const [isUsernameError, setIsUsernameError] = useState(false);
// Handle input change for user information (step 1)
function handleUserInfoChange(e: React.ChangeEvent) {
@@ -46,40 +49,46 @@ const S2Username = () => {
}
updateUsername(_usernameValue);
setUserNameCheckOK(false);
+ setIsUsernameError(false);
}
};
const handleUsernameCheck = async () => {
if (isChecking) return;
setIsChecking(true);
-
- try {
- isUsernameAvailable(userProfile.username).then(() => {
+ isUsernameAvailable(userProfile.username).then((res) => {
+ if (!!res) {
setUserNameCheckOK(true);
- }).finally(() => {
- setIsChecking(false);
- })
- } catch (err: unknown) {
- logException(err);
- }
+ nextStep();
+ } else {
+ console.debug(res);
+ }
+ }).catch(err => {
+ setIsUsernameError(true);
+ toast.error(err.message)
+ }).finally(() => {
+ setIsChecking(false);
+ })
};
+ useEffect(() => { });
+
return (
-
-
Choose a unique username for your brand
-
-
+
Choose your unique brand name
+
+
{
};
return (
-
-
Add your social media links
-
-
-
-
-
-
+
@{userProfile.username}
+
Guide your fans with thoughtful hand-picked destinations you want!
+
(any www address, social media, Ecommerce, shop, etc.):
+
+
+
+
+
-
-
-
-
-
-
- Summary:
-
- {userProfile.web2Items.length > 0 ? (
-
+ {web2Item.iconUrl ?
+
+ : <>>
+ }
+
+ {userProfile.web2Items.length > 0 ? (
+
+
Summary:
+
+
Icon |
URL |
- Actions |
+ Remove |
{userProfile.web2Items.map((item, index) => (
-
+
|
{
))}
|
- ) : (
-
No items added yet.
- )}
-
+
-
-
-
+ ) : (
+ <>>
+ )}
+