Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improving profile section #247

Merged
merged 6 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions components/UI/iconsComponents/icons/shareIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { FunctionComponent } from "react";

const ShareIcon: FunctionComponent<IconProps> = ({ color, width }) => {
return (
<>
<svg
width={width}
height={width}
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g id="ShareIcon">
<path
id="Vector"
d="M14.5656 7.51074L9.95942 2.77048C9.91111 2.72082 9.84958 2.68701 9.7826 2.67332C9.71563 2.65963 9.64621 2.66667 9.58313 2.69355C9.52004 2.72043 9.46611 2.76595 9.42814 2.82436C9.39018 2.88277 9.36988 2.95144 9.36982 3.02171V5.5222C6.23299 5.73492 2.43805 8.78114 2.00391 12.6717C1.98981 12.7956 2.01406 12.9209 2.0732 13.0298C2.13235 13.1386 2.22337 13.2255 2.3333 13.2781C2.44324 13.3306 2.56647 13.3461 2.68546 13.3223C2.80444 13.2986 2.91311 13.2368 2.99597 13.1457C3.6443 12.4341 5.97274 10.1677 9.36982 10.0213V12.5022C9.36988 12.5725 9.39018 12.6412 9.42814 12.6996C9.46611 12.758 9.52004 12.8035 9.58313 12.8304C9.64621 12.8573 9.71563 12.8643 9.7826 12.8506C9.84958 12.8369 9.91111 12.8031 9.95942 12.7535L14.5656 8.01321C14.6303 7.94655 14.6667 7.85619 14.6667 7.76198C14.6667 7.66777 14.6303 7.5774 14.5656 7.51074ZM10.0608 11.6443V9.65808C10.0608 9.5638 10.0244 9.47337 9.95957 9.40669C9.89478 9.34002 9.80691 9.30257 9.71529 9.30257C8.11866 9.30257 6.56234 9.73215 5.09065 10.5795C4.23287 11.0754 3.44274 11.686 2.7409 12.3956C3.01152 10.8218 3.90167 9.31442 5.27432 8.11335C6.63316 6.92888 8.29255 6.22139 9.71529 6.22139C9.80691 6.22139 9.89478 6.18393 9.95957 6.11726C10.0244 6.05059 10.0608 5.96016 10.0608 5.86587V3.88029L13.8327 7.76198L10.0608 11.6443Z"
fill={color}
/>
</g>
</svg>
</>
);
};

export default ShareIcon;
54 changes: 54 additions & 0 deletions components/UI/menus/bannerPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { FunctionComponent } from "react";
import styles from "../../../styles/components/popup.module.css";
import Button from "../button";
import CloseIcon from "../iconsComponents/icons/closeIcon";
import { Modal } from "@mui/material";

type BannerPopupProps = {
title: string;
banner: string;
description: string;
buttonName: string;
onClick: () => void;
onClose?: () => void;
};

const BannerPopup: FunctionComponent<BannerPopupProps> = ({
fricoben marked this conversation as resolved.
Show resolved Hide resolved
title,
banner,
description,
buttonName,
onClick,
onClose,
}) => {
return (
<Modal
disableAutoFocus
onClose={onClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
open={true}
>
<div className={styles.bannerPopup}>
<div className={styles.titleSide}>
<h1 className={styles.title}>{title}</h1>
<img className={styles.banner} src={banner} alt="banner" />
</div>
<div className={styles.contentSide}>
<button className={styles.close} onClick={onClose}></button>
<p className={styles.description}>{description}</p>
<div className={styles.button}>
<Button onClick={onClick}>{buttonName}</Button>
</div>
</div>
{onClose && (
<button onClick={onClose} className={styles.close}>
<CloseIcon width="16" />
</button>
)}
</div>
</Modal>
);
};

export default BannerPopup;
43 changes: 18 additions & 25 deletions components/UI/menus/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
import React, { FunctionComponent } from "react";
import React, { FunctionComponent, ReactNode } from "react";
import styles from "../../../styles/components/popup.module.css";
import Button from "../button";
import CloseIcon from "../iconsComponents/icons/closeIcon";
import { Modal } from "@mui/material";

type PopupProps = {
title: string;
banner: string;
description: string;
buttonName: string;
onClick: () => void;
children: ReactNode;
bottomContent?: ReactNode;
onClose?: () => void;
};

const Popup: FunctionComponent<PopupProps> = ({
title,
banner,
description,
buttonName,
onClick,
children,
bottomContent = null,
onClose,
}) => {
return (
<div className={styles.popupContainer}>
<Modal
disableAutoFocus
onClose={onClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
open={true}
>
<div className={styles.popup}>
<div className={styles.titleSide}>
<h1 className={styles.title}>{title}</h1>
<img className={styles.banner} src={banner} alt="banner" />
</div>
<div className={styles.contentSide}>
<button className={styles.close} onClick={onClose}></button>
<p className={styles.description}>{description}</p>
<div className={styles.button}>
<Button onClick={onClick}>{buttonName}</Button>
</div>
</div>
<div className={styles.popupContent}>{children}</div>
{bottomContent && (
<div className={styles.bottomContent}>{bottomContent}</div>
)}
{onClose && (
<button onClick={onClose} className={styles.close}>
<CloseIcon width="16" />
</button>
)}
</div>
</div>
</Modal>
);
};

Expand Down
70 changes: 70 additions & 0 deletions components/UI/menus/sharePopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { FunctionComponent } from "react";
import Popup from "./popup";
import TwitterIcon from "../iconsComponents/icons/twitterIcon";
import DiscordIcon from "../iconsComponents/icons/discordIcon";
import iconsStyles from "../../../styles/components/icons.module.css";
import Button from "../button";
import styles from "../../../styles/components/popup.module.css";

type SharePopupProps = {
close: () => void;
toCopy: string;
};

const SharePopup: FunctionComponent<SharePopupProps> = ({ close, toCopy }) => {
const [copied, setCopied] = React.useState(false);
const handleCopy = () => {
navigator.clipboard.writeText(toCopy);
setCopied(true);
setTimeout(() => setCopied(false), 1500);
};

return (
<Popup
onClose={close}
bottomContent={
<div className="flex w-full gap-4 items-center">
<input
type="text"
className="w-full text-black px-4 py-3 rounded-lg"
value={toCopy}
/>
<div className={styles.lilButton}>
<Button onClick={handleCopy}>{copied ? "Copied" : "Copy"}</Button>
</div>
</div>
}
>
<>
<h3 className="text-center font-bold text-3xl">Share</h3>
<div className="flex gap-8">
<a
href={`
https://twitter.com/intent/tweet?url=Check%20out%20my%20Starknet%20Quest%20land%20at%20${toCopy}🏞️%20%23Starknet%20%23StarknetID`}
target="_blank"
rel="noreferrer"
className="flex flex-col items-center gap-2"
>
<div className={iconsStyles.clickableIconTwitter}>
<TwitterIcon width="32" color={"white"} />
</div>
<p>Twitter</p>
</a>
<a
href="https://discord.com/"
target="_blank"
rel="noreferrer"
className="flex flex-col items-center gap-2"
>
<div className={iconsStyles.clickableIconDiscord}>
<DiscordIcon width="32" color={"white"} />
</div>
<p>Discord</p>
</a>
</div>
</>
</Popup>
);
};

export default SharePopup;
109 changes: 67 additions & 42 deletions pages/[addressOrDomain].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useLayoutEffect, useState } from "react";
import type { NextPage } from "next";
import styles from "../styles/profile.module.css";
import { useRouter } from "next/router";
import { isHexString, minifyAddressWithChars } from "../utils/stringService";
import { isHexString, minifyAddressFromStrings } from "../utils/stringService";
import { Connector, useAccount, useConnectors } from "@starknet-react/core";
import SocialMediaActions from "../components/UI/actions/socialmediaActions";
import { StarknetIdJsContext } from "../context/StarknetIdJsProvider";
Expand All @@ -17,6 +17,9 @@ import { hasVerifiedSocials } from "../utils/profile";
import { useMediaQuery } from "@mui/material";
import VerifiedIcon from "../components/UI/iconsComponents/icons/verifiedIcon";
import CopyIcon from "../components/UI/iconsComponents/icons/copyIcon";
import ShareIcon from "../components/UI/iconsComponents/icons/shareIcon";
import theme from "../styles/theme";
import SharePopup from "../components/UI/menus/sharePopup";

const AddressOrDomain: NextPage = () => {
const router = useRouter();
Expand All @@ -35,6 +38,7 @@ const AddressOrDomain: NextPage = () => {
const [achievements, setAchievements] = useState<BuildingsInfo[]>([]);
const [soloBuildings, setSoloBuildings] = useState<BuildingsInfo[]>([]);
const [selectedTab, setSelectedTab] = useState<LandTabs>("nfts");
const [showSharePopup, setShowSharePopup] = useState(false);

useEffect(() => setNotFound(false), [dynamicRoute]);

Expand Down Expand Up @@ -235,59 +239,74 @@ const AddressOrDomain: NextPage = () => {
title={identity?.domain ?? minifyAddress(identity.addr)}
isUppercase={true}
content={
<div className={styles.nameCard}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we put all the content in the ProfileCard component directly? Will we use this profile elsewhere? if not I think we can put it directly in because it's cleaner imo

<div className={styles.profilePicture}>
<img
width={"350px"}
src={`https://www.starknet.id/api/identicons/${identity?.starknet_id}`}
alt="starknet.id avatar"
style={{ maxWidth: "150%" }}
/>
{/* We do not enable the profile pic change atm */}
{/* <Tooltip title="Change profile picture" arrow>
<>
<div className={styles.nameCard}>
<div className={styles.profilePicture}>
<img
width={"350px"}
src={`https://www.starknet.id/api/identicons/${identity?.starknet_id}`}
alt="starknet.id avatar"
style={{ maxWidth: "150%" }}
/>
{/* We do not enable the profile pic change atm */}
{/* <Tooltip title="Change profile picture" arrow>
<div className={styles.cameraIcon}>
<CameraAlt
className={styles.cameraAlt}
onClick={() => console.log("changing pfp")}
/>
</div>
</Tooltip> */}
</div>
<div>
<div className={styles.starknetInfo}>
<div className="cursor-pointer absolute">
{!copied ? (
<Tooltip title="Copy" arrow>
<div onClick={() => copyToClipboard()}>
<CopyIcon width={"18"} color="#F4FAFF" />
</div>
</Tooltip>
) : (
<VerifiedIcon width={"18"} />
)}
</div>
<div className={styles.address}>
{typeof addressOrDomain === "string" &&
isHexString(addressOrDomain)
? minifyAddressWithChars(addressOrDomain, 8)
: minifyAddressWithChars(identity?.addr, 8)}
</div>
</div>
{sinceDate ? (
<div className={styles.memberSince}>
<p>{sinceDate}</p>
<div>
<div className={styles.starknetInfo}>
<div className="cursor-pointer absolute">
{!copied ? (
<Tooltip title="Copy" arrow>
<div onClick={() => copyToClipboard()}>
<CopyIcon width={"18"} color="#F4FAFF" />
</div>
</Tooltip>
) : (
<VerifiedIcon width={"18"} />
)}
</div>
<div className={styles.address}>
{typeof addressOrDomain === "string" &&
minifyAddressFromStrings(
[addressOrDomain, identity?.addr || ""],
8
)}
</div>
</div>
) : null}
{sinceDate ? (
<div className={styles.memberSince}>
<p>{sinceDate}</p>
</div>
) : null}
</div>
</div>
</div>
{hasVerifiedSocials(identity) ? (
<>
<div className={styles.divider} />
<div className="flex items-center w-full my-1">
<SocialMediaActions identity={identity} />
<button
onClick={() => setShowSharePopup(true)}
className={styles.shareButton}
>
<ShareIcon
color={theme.palette.secondary.dark}
width="16px"
/>
<p className="ml-2">Share</p>
</button>
</div>
</>
) : null}
</>
}
/>
{hasVerifiedSocials(identity) ? (
<ProfileCard
title="Social network"
content={<SocialMediaActions identity={identity} />}
/>
) : null}
<ProfileCard
title="Progress"
content={
Expand Down Expand Up @@ -363,6 +382,12 @@ const AddressOrDomain: NextPage = () => {
<h2>Loading</h2>
</div>
)}
{showSharePopup ? (
<SharePopup
close={() => setShowSharePopup(false)}
toCopy={window.location.href}
/>
) : null}
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions pages/quest/[questPage].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import useHasRootDomain from "../../hooks/useHasRootDomain";
import useHasRootOrBraavosDomain from "../../hooks/useHasRootOrBraavosDomain";
import { useAccount } from "@starknet-react/core";
import { starknetIdAppLink } from "../../utils/links";
import Popup from "../../components/UI/menus/popup";
import BannerPopup from "../../components/UI/menus/bannerPopup";

const QuestPage: NextPage = () => {
const router = useRouter();
Expand Down Expand Up @@ -79,7 +79,7 @@ const QuestPage: NextPage = () => {
) : (
<div className={homeStyles.screen}>
{showDomainPopup && (
<Popup
<BannerPopup
title="Mandatory Starknet Domain"
banner="/visuals/profile.webp"
description="To access Starknet Quest, you must own a Starknet domain. It's your passport to the Starknet ecosystem. Get yours now."
Expand Down
Loading