diff --git a/.github/workflows/deploy-mainnet.yml b/.github/workflows/deploy-mainnet.yml new file mode 100644 index 00000000..77a00d0b --- /dev/null +++ b/.github/workflows/deploy-mainnet.yml @@ -0,0 +1,13 @@ +name: Deploy Components to Mainnet +on: + push: + branches: [main] +jobs: + deploy-mainnet: + uses: FroVolod/bos-cli-rs/.github/workflows/deploy-mainnet.yml@master + with: + deploy-account-address: potlock.near + signer-account-address: potlock.near + signer-public-key: ed25519:3iWoL6haUT3FGd9KJjwpAS8fLqk7hAdyBX8trD3vSh6C + secrets: + SIGNER_PRIVATE_KEY: ${{ secrets.SIGNER_PRIVATE_KEY }} diff --git a/apps/potlock/widget/Buttons/ActionButton.jsx b/apps/potlock/widget/Buttons/ActionButton.jsx index 381f7aff..c1716529 100644 --- a/apps/potlock/widget/Buttons/ActionButton.jsx +++ b/apps/potlock/widget/Buttons/ActionButton.jsx @@ -40,6 +40,7 @@ const Button = styled.button` text-align: center; color: ${getButtonTextColor()}; font-size: 14px; + line-height: 16px; font-weight: 600; &:hover { diff --git a/apps/potlock/widget/Components/Header.jsx b/apps/potlock/widget/Components/Header.jsx index b821f94a..4aed28af 100644 --- a/apps/potlock/widget/Components/Header.jsx +++ b/apps/potlock/widget/Components/Header.jsx @@ -1,10 +1,13 @@ const ownerId = "potlock.near"; +const loraCss = fetch("https://fonts.googleapis.com/css2?family=Lora&display=swap").body; + const headerTitleFontSizePx = 88; const HeaderContainer = styled.div` width: 100%; - background: #fffaf4; + // background: #fffaf4; + background: white; padding: 80px 64px; `; @@ -17,15 +20,17 @@ const HeaderContent = styled.div` const HeaderTitle = styled.div` color: #2e2e2e; font-size: ${headerTitleFontSizePx}px; - font-weight: 600; + font-weight: 500; word-wrap: break-word; position: relative; + text-align: center; + font-family: "Lora"; + ${loraCss} `; const HeaderDescription = styled.div` color: #2e2e2e; font-size: 32px; - font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; max-width: 866px; @@ -43,6 +48,7 @@ const ButtonsContainer = styled.div` `; return ( + // @@ -78,4 +84,5 @@ return ( {props.buttonSecondary && props.buttonSecondary} + // ); diff --git a/apps/potlock/widget/Index.jsx b/apps/potlock/widget/Index.jsx index 554af8a2..56ea1018 100644 --- a/apps/potlock/widget/Index.jsx +++ b/apps/potlock/widget/Index.jsx @@ -3,81 +3,31 @@ const ownerId = "potlock.near"; const CREATE_PROJECT_TAB = "createproject"; const PROJECT_DETAIL_TAB = "project"; +const monaSansCss = fetch("https://fonts.cdnfonts.com/css/mona-sans").body; + +if (!monaSansCss) return ""; + +const Theme = styled.div` + * { + font-family: "Mona-Sans"; + } + ${monaSansCss} +`; + State.init({ tnc: true, tncIsFetched: false, tosAccept: true, }); -// if (context.accountId && !state.tncIsFetched) { -// Near.asyncView( -// "social.near", -// "get", -// { -// keys: [ -// `${context.accountId}/profile/horizon_tnc`, -// `${context.accountId}/index/tosAccept`, -// ], -// }, -// "final", -// false -// ).then((data) => -// State.update({ -// tnc: data[context.accountId]?.profile?.horizon_tnc === "true", -// tosAccept: -// data[context.accountId]?.index?.tosAccept && -// data[context.accountId]?.index?.tosAccept.length > 0, -// tncIsFetched: true, -// }) -// ); -// } - const tabContentWidget = { - // home: "Dashboard", - // inbox: "Inbox", - // manage: "Manage", - // project: "Project.Page", - // request: "Request.Page", - // vendor: "Vendor.Page", - // backer: "Investor.Page", - // contribution: "Contribution.Page", [CREATE_PROJECT_TAB]: "Project.Create", - // createrequest: "Request.Form", - // createvendor: "Vendor.Form", - // createbacker: "Investor.Form", - // permissions: "Inputs.SetUpPermissions", - // learn: "Learn.Page", - // faq: "FAQ.Page", - // help: "Help.Page", - // legal: "TNCPage", - // admin: "Admin.Page", projects: "Project.ListPage", [PROJECT_DETAIL_TAB]: "Project.Detail", - // investors: "Investor.ListPage", - // backers: "Investor.ListPage", - // vendors: "Vendor.ListPage", - // contributors: "Vendor.ListPage", - // requests: "Request.ListPage", - // partners: "Application.Page", - // partner: "Application.DetailPage", - // "my-projects": "Manage.Projects", - // "my-requests": "Manage.Requests", - // "my-contracts": "Manage.Contracts", - // "my-applications": "Manage.Applications", - // events: "Events.Page", - // perks: "Perks.Page", - // profile: "Profile.Page", }; -const successfulRegistration = props.tab == CREATE_PROJECT_TAB && props.transactionHashes; - const getWidget = (props) => { - if (successfulRegistration) { - // user just successfully registered their project - // navigate to the project page - // get the project ID (do this in getWidgetProps) - return tabContentWidget[PROJECT_DETAIL_TAB]; - } else if (props.tab in tabContentWidget) { + if (props.tab in tabContentWidget) { return tabContentWidget[props.tab]; } // backup (TODO: review) @@ -92,51 +42,19 @@ const getTabWidget = (tab) => { return "Project.ListPage"; }; -const getWidgetProps = () => { - const props = { - ...props, - urlProps: props, - }; - if (successfulRegistration) { - props.successfulRegistration = true; - // get the project ID - // get list of all registered projects - // find the one that matches context.accountId - // pass this project in props to the project page - } - return { - ...props, - urlProps: props, - successfulRegistration, - }; -}; // TODO: IMPLEMENT - -console.log("Index props: ", props); - const tabContent = ( ); -console.log("tab content: ", tabContent); - -// const Page = styled.div` -// width: 100%; -// border-radius: 0.5rem; -// border: 1px solid #eaeaea; -// `; - const Content = styled.div` - padding-top: 110px; width: 100%; + height: 100%; background: #ffffff; // padding: 3em; border-radius: 0rem 0rem 1.5rem 1.5rem; @@ -149,35 +67,11 @@ const Content = styled.div` } `; -// const showSidebar = ![ -// "createproject", -// "createrequest", -// "createvendor", -// "createbacker", -// "permissions", -// "legal", -// ].includes(props.tab); -const isForm = [ - CREATE_PROJECT_TAB, - // "createrequest", - // "createvendor", - // "createbacker", -].includes(props.tab); - -// const showTncDialog = !state.tnc && state.tosAccept && props.tab !== "legal"; +const isForm = [CREATE_PROJECT_TAB].includes(props.tab); return ( - <> + - {/* */} - {/* */} {tabContent} - + ); diff --git a/apps/potlock/widget/Nav.jsx b/apps/potlock/widget/Nav.jsx index 28a99289..8e233c1d 100644 --- a/apps/potlock/widget/Nav.jsx +++ b/apps/potlock/widget/Nav.jsx @@ -1,155 +1,10 @@ const ownerId = "potlock.near"; -// const apiUrl = "https://api-op3o.onrender.com"; - -// State.init({ -// exists: false, -// project: false, -// balance: 0, -// profileIsFetched: false, -// }); - -// if (!state.profileIsFetched) { -// if (!context.accountId) { -// State.update({ -// profileIsFetched: true, -// }); -// } else { -// Near.asyncView( -// ownerId, -// "check_is_project", -// { account_id: context.accountId }, -// "final", -// false -// ).then((profileExists) => { -// if (profileExists) { -// Near.asyncView( -// ownerId, -// "get_project", -// { account_id: context.accountId }, -// "final", -// false -// ).then((project) => { -// State.update({ -// balance: project.credit_balance, -// project: true, -// exists: true, -// profileIsFetched: true, -// }); -// }); -// } else { -// Near.asyncView( -// ownerId, -// "check_is_vendor", -// { account_id: context.accountId }, -// "final", -// false -// ).then((contributorExists) => { -// if (contributorExists) { -// asyncFetch( -// `${apiUrl}/data/credits/vendors/${context.accountId}/balance` -// ).then(({ body, ok }) => { -// State.update({ -// balance: ok ? body : 0, -// project: false, -// exists: true, -// profileIsFetched: true, -// }); -// }); -// } else { -// State.update({ -// exists: false, -// profileIsFetched: true, -// }); -// } -// }); -// } -// }); -// } -// } - -// const Actions = styled.div` -// display: flex; -// justify-content: flex-end; -// align-items: flex-start; -// gap: 1rem; -// `; - -// const GreyButton = styled.div` -// display: flex; -// align-items: center; -// justify-content: center; -// gap: 0.5rem; -// align-self: stretch; -// `; - -// const GreyContent = styled.div` -// display: flex; -// padding: 0.4375rem 1rem 0.4375rem 1rem; -// align-items: center; -// width: 100%; -// gap: 0.5rem; -// align-self: stretch; -// border-radius: 3.125rem; -// border: 1px solid var(--ui-elements-light, #eceef0); -// background: var(--background-light, #fafafa); -// color: var(--ui-elements-black, #000); -// text-align: center; -// font-family: Inter; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 600; -// line-height: 142%; /* 1.2425rem */ -// letter-spacing: 0.00875rem; - -// & > span { -// color: var(--ui-elements-black, #000); -// leading-trim: both; -// text-edge: cap; -// font-family: "Mona Sans"; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 500; -// line-height: 142%; /* 1.2425rem */ -// letter-spacing: 0.00875rem; -// } - -// & > b { -// color: var(--ui-elements-black, #000); -// leading-trim: both; -// text-edge: cap; -// font-family: "Mona Sans"; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 700; -// line-height: 142%; -// letter-spacing: 0.00875rem; -// } - -// & > svg { -// transform: translateY(-1px); -// } - -// & > a { -// color: var(--ui-elements-black, #000); -// text-decoration: none; -// cursor: pointer; -// display: flex; -// align-items: center; -// gap: 0.5rem; - -// &:hover, -// &:focus, -// &:active { -// text-decoration: none; -// color: var(--ui-elements-black, #000); -// } -// } -// `; const Nav = styled.div` - position: fixed; - top: 0; - left: 0; + // commenting out stickiness for now + // position: fixed; + // top: 0; + // left: 0; width: 100%; display: flex; padding: 0 64px 0 64px; @@ -176,7 +31,14 @@ const NavLeft = styled.div` justify-content: center; `; -const NavIcon = styled.div` +const NavRight = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +`; + +const NavLogo = styled.a` text-align: center; color: #2e2e2e; font-size: 23.95px; @@ -184,6 +46,11 @@ const NavIcon = styled.div` line-height: 23.95px; word-wrap: break-word; margin-right: 48px; + text-decoration: none; + + :hover { + text-decoration: none; + } `; const NavTabs = styled.div` @@ -194,24 +61,23 @@ const NavTabs = styled.div` `; const NavTab = styled.a` - :not(:last-child) { - margin-right: 32px; - } - cursor: pointer; + cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")}; color: #7b7b7b; fontsize: 14; fontfamily: Mona-Sans; fontweight: 500; lineheight: 16; wordwrap: break-word; -`; + text-decoration: none; -// const profileIcon = ( -// -// ); + :not(:last-child) { + margin-right: 32px; + } + + :hover { + text-decoration: none; + } +`; const tabOptions = [ { text: "Projects", link: "projects", disabled: false }, @@ -222,17 +88,24 @@ const tabOptions = [ return ( ); diff --git a/apps/potlock/widget/Project/About.jsx b/apps/potlock/widget/Project/About.jsx index 8d357cc1..64a38b96 100644 --- a/apps/potlock/widget/Project/About.jsx +++ b/apps/potlock/widget/Project/About.jsx @@ -16,14 +16,12 @@ const About = () => ( props={{ ...props, title: "Overview", - text: description.repeat(100), + text: description, }} /> ); -console.log("Props in About: ", props); - const Team = () => ( diff --git a/apps/potlock/widget/Project/BannerHeader.jsx b/apps/potlock/widget/Project/BannerHeader.jsx index 864d1f49..7d92bd57 100644 --- a/apps/potlock/widget/Project/BannerHeader.jsx +++ b/apps/potlock/widget/Project/BannerHeader.jsx @@ -19,6 +19,9 @@ const name = profile.name || "No-name profile"; const image = profile.image; const backgroundImage = profile.backgroundImage; const tags = Object.keys(profile.tags ?? {}); +const imageStyle = props.imageStyle ?? {}; +const backgroundStyle = props.backgroundStyle ?? {}; +const containerStyle = props.containerStyle ?? {}; const Wrapper = styled.div` overflow: hidden; @@ -26,32 +29,36 @@ const Wrapper = styled.div` `; return ( -
+
{backgroundImage && ( )} -
+
+ {props.children && props.children}
); diff --git a/apps/potlock/widget/Project/Body.jsx b/apps/potlock/widget/Project/Body.jsx index e54056d6..925c3a4c 100644 --- a/apps/potlock/widget/Project/Body.jsx +++ b/apps/potlock/widget/Project/Body.jsx @@ -1,15 +1,9 @@ -console.log("props in Body: ", props); - const ownerId = "potlock.near"; const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; -// const linktree = props.linktree; - -// if (!linktree) return "Loading..."; - const profile = props.profile; -if (!profile) return "Loading..."; +if (!profile) return "Loading PROFILE..."; const tags = Object.keys(profile.tags ?? {}); diff --git a/apps/potlock/widget/Project/Card.jsx b/apps/potlock/widget/Project/Card.jsx index 654b71c6..37d9e74a 100644 --- a/apps/potlock/widget/Project/Card.jsx +++ b/apps/potlock/widget/Project/Card.jsx @@ -4,40 +4,44 @@ const Card = styled.a` display: flex; flex-direction: column; width: 100%; - border-radius: 6px; - background-color: white; + max-width: 30%; + border-radius: 7px; + background: white; + box-shadow: 0px -2px 0px #dbdbdb inset; + border: 1px solid #dbdbdb; &:hover { text-decoration: none; cursor: pointer; } `; -const Banner = styled.div` - position: relative; - width: 100%; - height: 168; - margin-bottom: 30px; -`; +// const Banner = styled.div` +// position: relative; +// width: 100%; +// height: 168; +// margin-bottom: 30px; +// `; -const BannerImage = styled.img` - width: 100%; - height: 100%; - // border-radius: 6px; -`; +// const BannerImage = styled.img` +// width: 100%; +// height: 100%; +// // border-radius: 6px; +// `; -const ProfileImage = styled.img` - width: 40px; - height: 40px; - border-radius: 50%; - border: 3px solid white; - position: absolute; - bottom: -20px; - left: 60px; -`; +// const ProfileImage = styled.img` +// width: 40px; +// height: 40px; +// border-radius: 50%; +// border: 3px solid white; +// position: absolute; +// bottom: -20px; +// left: 60px; +// `; const Info = styled.div` display: flex; flex-direction: column; + margin-top: 160px; padding: 16px 24px; gap: 16px; `; @@ -72,10 +76,32 @@ const { id, bannerImageUrl, profileImageUrl, name, description, tags } = props.p return ( - - - - + {name} {description} @@ -83,7 +109,7 @@ return ( src={`${ownerId}/widget/Project.Tags`} props={{ ...props, - tags: Object.keys(tags), + tags, }} /> diff --git a/apps/potlock/widget/Project/CreateForm.jsx b/apps/potlock/widget/Project/CreateForm.jsx index 61874121..4a26c4ea 100644 --- a/apps/potlock/widget/Project/CreateForm.jsx +++ b/apps/potlock/widget/Project/CreateForm.jsx @@ -1,11 +1,11 @@ const ownerId = "potlock.near"; -const registryId = "registry1.tests.potlock.near"; // TODO: update when registry is deployed +const registryId = "registry.potlock.near"; // TODO: update when registry is deployed const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; -const DEFAULT_BANNER_IMAGE_URL = - IPFS_BASE_URL + "bafkreih4i6kftb34wpdzcuvgafozxz6tk6u4f5kcr2gwvtvxikvwriteci"; -const DEFAULT_PROFILE_IMAGE_URL = - IPFS_BASE_URL + "bafkreifel4bfm6hxmklcsqjilk3bhvi3acf2rxqepcgglluhginbttkyqm"; +// const DEFAULT_BANNER_IMAGE_URL = +// IPFS_BASE_URL + "bafkreih4i6kftb34wpdzcuvgafozxz6tk6u4f5kcr2gwvtvxikvwriteci"; +// const DEFAULT_PROFILE_IMAGE_URL = +// IPFS_BASE_URL + "bafkreifel4bfm6hxmklcsqjilk3bhvi3acf2rxqepcgglluhginbttkyqm"; const ADD_TEAM_MEMBERS_ICON_URL = IPFS_BASE_URL + "bafkreig6c7m2z2lupreu2br4pm3xx575mv6uvmuy2qkij4kzzfpt7tipcq"; const CLOSE_ICON_URL = @@ -27,46 +27,23 @@ if (!context.accountId) { ); } +const imageHeightPx = 120; +const profileImageTranslateYPx = 220; + const Container = styled.div` display: flex; flex-direction: column; - align-items: center; - justify-content: center; width: 100%; padding: 72px 64px 72px 64px; `; -const ProfileImgContainer = styled.div` - width: 120px; - height: 120px; - position: absolute; - bottom: 0px; - left: 113px; - // background-color: pink; -`; - -const Banner = styled.div` - position: relative; - width: 100%; - height: 280px; - margin-bottom: 132px; -`; - -const BannerImage = styled.img` - width: 100%; - height: 100%; - object-fit: cover; - border-radius: 6px; -`; - const LowerBannerContainer = styled.div` position: absolute; - bottom: -60px; + bottom: -210px; left: 0px; display: flex; align-items: stretch; /* Ensuring child elements stretch to full height */ justify-content: space-between; - // background: pink; width: 100%; `; @@ -74,7 +51,7 @@ const LowerBannerContainerLeft = styled.div` display: flex; flex-direction: row; align-items: flex-end; - margin-left: 113px; + margin-left: 190px; `; const LowerBannerContainerRight = styled.div` @@ -96,19 +73,6 @@ const TeamContainer = styled.div` // gap: -40px; `; -const ProfileImage = styled.img` - width: ${(props) => props.width}px; - height: ${(props) => props.height}px; - border-radius: 50%; - border: ${(props) => props.borderWidth ?? 5}px solid white; - margin: ${(props) => props.margin ?? "0px"}; - z-index: ${(props) => props.zIndex ?? 0}; - position: relative; - // position: absolute; - // bottom: -60px; - // left: 113px; -`; - const AddTeamMembers = styled.a` margin: 0px 0px 16px 36px; cursor: pointer; @@ -159,7 +123,6 @@ const FormSectionRightDiv = styled.div` const FormSectionTitle = styled.div` color: #2e2e2e; font-size: 16; - // font-family: Mona-Sans; font-weight: 600; word-wrap: break-word; `; @@ -167,14 +130,12 @@ const FormSectionTitle = styled.div` const FormSectionDescription = styled.div` color: #2e2e2e; font-size: 16; - // font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; `; const FormSectionIsRequired = styled.div` font-size: 16px; - // font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; position: relative; @@ -259,15 +220,13 @@ const ModalTitle = styled.div` font-color: #2e2e2e; font-size: 16px; font-weight: 600; - // font-family: Mona-Sans; `; const ModalDescription = styled.p` font-color: #2e2e2e; font-size: 16px; font-weight: 400; - // font-family: Mona-Sans; -`; +=`; const MembersCount = styled.span` color: #2e2e2e; @@ -280,6 +239,69 @@ const MembersText = styled.div` font-weight: 400; `; +const MembersListItem = styled.div` + padding: 16px 0px; + border-top: 1px #f0f0f0 solid; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +`; + +const RemoveMember = styled.a` + color: #2e2e2e; + font-size: 14px; + font-weight: 600; + visibility: hidden; + cursor: pointer; + opacity: 0; + transition: opacity 0.2s ease-in-out; + + &:hover { + text-decoration: none; + } + + ${MembersListItem}:hover & { + visibility: visible; + opacity: 1; + } +`; + +const MembersListItemLeft = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 16px; +`; + +const MembersListItemText = styled.div` + font-size: 16px; + font-weight: 400; + color: #2e2e2e; +`; + +const MoreTeamMembersContainer = styled.div` + width: 28px; + height: 28px; + border: 2px solid white; + border-radius: 50%; + background: #dd3345; + position: relative; + display: flex; + justify-content: center; + align-items: center; + z-index: ${(props) => props.zIndex}; + margin-right: -8px; +`; + +const MoreTeamMembersText = styled.div` + color: white; + font-size: 12px; + font-weight: 600; + text-align: center; +`; + State.init({ name: "", nameError: "", @@ -295,10 +317,6 @@ State.init({ telegramError: "", github: "", githubError: "", - profileImageUrl: "", - profileImageError: "", - bannerImageCid: "", - bannerImageError: "", socialDataFetched: false, socialDataIsFetching: false, registeredProjects: null, @@ -328,26 +346,11 @@ const Modal = ({ isOpen, onClose, children }) => { }; if (context.accountId && !state.socialDataFetched) { - // State.update({ socialDataIsFetching: true }); - // const socialData = Social.get(`${context.accountId}/profile/**`); Near.asyncView("social.near", "get", { keys: [`${context.accountId}/profile/**`] }) .then((socialData) => { if (!socialData) return; - console.log("social data for current user: ", socialData); const profileData = socialData[context.accountId].profile; if (!profileData) return; - // get profile image URL - let profileImageUrl = DEFAULT_PROFILE_IMAGE_URL; - if (profileData.image) { - const imageUrl = getImageUrlFromSocialImage(profileData.image); - if (imageUrl) profileImageUrl = imageUrl; - } - // get banner image URL - let bannerImageUrl = DEFAULT_BANNER_IMAGE_URL; - if (profileData.backgroundImage) { - const imageUrl = getImageUrlFromSocialImage(profileData.backgroundImage); - if (imageUrl) bannerImageUrl = imageUrl; - } // description let description = profileData.description || ""; // linktree @@ -366,14 +369,11 @@ if (context.accountId && !state.socialDataFetched) { telegram, github, website, - profileImageUrl, - bannerImageUrl, socialDataFetched: true, teamMembers: Object.keys(team).map((accountId) => ({ accountId, imageUrl: DEFAULT_PROFILE_IMAGE_URL, // TODO: fetch actual image from near social. or better, move ProfileImage to its own component that handles the social data fetching })), - // socialDataIsFetching: false, }); }) .catch((e) => { @@ -393,61 +393,6 @@ if (context.accountId && !state.registeredProjects) { }); } -const FormSectionLeft = (title, description, isRequired) => { - return ( - - {title} - {description} - - {isRequired ? "Required" : "Optional"} - {isRequired && ( - - - - - - )} - - - ); -}; - -const BannerImageWithFallback = (props) => { - const [bannerImageUrl, setBannerImageUrl] = useState(props.src); - const handleBannerImageError = (event) => { - event.stopPropagation(); - event.target.onerror = null; - setBannerImageUrl(DEFAULT_BANNER_IMAGE_URL); - }; - return ; -}; - -// _NB: commenting this out for now; for some reason profileImageUrl inherits bannerImageUrl's value and is NOT set to props.src. this seems to be a bug with useState implementation_ -// const ProfileImageWithFallback = (props) => { -// const [profileImageUrl, setProfileImageUrl] = useState(props.src); -// const handleError = (event) => { -// event.stopPropagation(); -// event.target.onerror = null; -// setProfileImageUrl(DEFAULT_PROFILE_IMAGE_URL); -// }; -// return ; -// }; - const isCreateProjectDisabled = !state.name || state.nameError || @@ -496,79 +441,12 @@ const handleCreateProject = (e) => { const res = Near.call(transactions); }; -console.log("state: ", state); - const registeredProject = state.registeredProjects ? state.registeredProjects?.find( (project) => project.id == context.accountId && project.status == "Approved" ) : null; -// TODO: Move these elsewhere -const MembersListItem = styled.div` - padding: 16px 0px; - border-top: 1px #f0f0f0 solid; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -`; - -const RemoveMember = styled.a` - color: #2e2e2e; - font-size: 14px; - font-weight: 600; - visibility: hidden; - cursor: pointer; - opacity: 0; - transition: opacity 0.2s ease-in-out; - - &:hover { - text-decoration: none; - } - - ${MembersListItem}:hover & { - visibility: visible; - opacity: 1; - } -`; - -const MembersListItemLeft = styled.div` - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - gap: 16px; -`; - -const MembersListItemText = styled.div` - font-size: 16px; - font-weight: 400; - color: #2e2e2e; -`; - -const MoreTeamMembersContainer = styled.div` - width: 28px; - height: 28px; - border: 2px solid white; - border-radius: 50%; - background: #dd3345; - position: relative; - display: flex; - justify-content: center; - align-items: center; - z-index: ${(props) => props.zIndex}; - margin-right: -8px; -`; - -const MoreTeamMembersText = styled.div` - color: white; - font-size: 12px; - font-weight: 600; - text-align: center; - // font-family: Mona-Sans; -`; - const handleAddTeamMember = () => { let isValid = NEAR_ACCOUNT_ID_REGEX.test(state.teamMember); // Additional ".near" check for IDs less than 64 characters @@ -591,7 +469,6 @@ const handleAddTeamMember = () => { }; Near.asyncView("social.near", "get", { keys: [`${state.teamMember}/profile/**`] }) .then((socialData) => { - console.log("social data line 554: ", socialData); if (socialData) { const profileData = socialData[state.teamMember].profile; if (!profileData) return; @@ -599,7 +476,6 @@ const handleAddTeamMember = () => { if (profileData.image) { const imageUrl = getImageUrlFromSocialImage(profileData.image); if (imageUrl) fullTeamMember.imageUrl = imageUrl; - console.log("fullTeamMember.imageUrl line 562: ", fullTeamMember.imageUrl); } } }) @@ -607,7 +483,6 @@ const handleAddTeamMember = () => { console.log("error getting social data: ", e); }) .finally(() => { - console.log("fullTeamMember.imageUrl line 570: ", fullTeamMember.imageUrl); State.update({ teamMembers: [...state.teamMembers, fullTeamMember], teamMember: "", @@ -617,13 +492,47 @@ const handleAddTeamMember = () => { } }; +const FormSectionLeft = (title, description, isRequired) => { + return ( + + {title} + {description} + + {isRequired ? "Required" : "Optional"} + {isRequired && ( + + + + + + )} + + + ); +}; + return ( {!state.socialDataFetched ? ( -
Loading...
+
) : registeredProject ? ( - <> -

You've successfully registered!

+ +

You've successfully registered!

- +
) : ( <> - - - - - - State.update({ isModalOpen: true })}> - Add team members - - - - - {state.teamMembers.length > MAX_TEAM_MEMBERS_DISPLAY_COUNT && ( - - {MAX_TEAM_MEMBERS_DISPLAY_COUNT}+ - - )} - {state.teamMembers - .slice(0, MAX_TEAM_MEMBERS_DISPLAY_COUNT) - .map((teamMember, idx) => { - return ( - - ); - })} - - - - - + + + State.update({ isModalOpen: true })}> + Add team members + + + + + {state.teamMembers.length > MAX_TEAM_MEMBERS_DISPLAY_COUNT && ( + + {MAX_TEAM_MEMBERS_DISPLAY_COUNT}+ + + )} + {state.teamMembers + .slice(0, MAX_TEAM_MEMBERS_DISPLAY_COUNT) + .map((teamMember, idx) => { + return ( + + ); + })} + + + + ), + }} + /> + - - {/* */} - {FormSectionLeft( "Project details", @@ -899,7 +835,22 @@ return ( return ( - + @{teamMember.accountId} -
+
(props.disabled ? "not-allowed" : "pointer")}; &:hover { text-decoration: none; @@ -48,6 +47,12 @@ const itemIconUrls = { NEAR: IPFS_BASE_URL + "bafkreigogi7iyonbdjsxi3n6seplll7at6e4jsrxwpgke5b5uk5obxkdpe", }; +const fullUrls = { + twitter: (handle) => `https://twitter.com/${handle}`, + github: (username) => `https://github.com/${username}`, + website: (url) => url, +}; + return ( {Object.entries(linktree).map(([k, v], idx) => { @@ -55,8 +60,14 @@ return ( { + if (!v) { + e.preventDefault(); + } + }} > {k[0].toUpperCase() + k.slice(1)} @@ -67,7 +78,7 @@ return ( NEAR diff --git a/apps/potlock/widget/Project/ListPage.jsx b/apps/potlock/widget/Project/ListPage.jsx index faa1f022..dd56b39f 100644 --- a/apps/potlock/widget/Project/ListPage.jsx +++ b/apps/potlock/widget/Project/ListPage.jsx @@ -1,5 +1,5 @@ const ownerId = "potlock.near"; -const registryId = "registry1.tests.potlock.near"; // TODO: update when registry is deployed +const registryId = "registry.potlock.near"; // TODO: update when registry is deployed const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; const DEFAULT_BANNER_IMAGE_URL = @@ -15,6 +15,15 @@ const getImageUrlFromSocialImage = (image) => { } }; +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +`; + const HeroOuter = styled.div` padding: 136px 64px; `; @@ -26,18 +35,13 @@ const HeroInner = styled.div` justify-content: space-between; `; -const Separator = styled.div` - width: 100%; - height: 96px; - background-color: #f8f8f8; -`; - const SectionHeader = styled.div` display: flex; flex-direction: row; width: 100%; align-items: center; margin-bottom: 24px; + padding: 96px 64px 24px 64px; `; const SectionTitle = styled.div` @@ -58,7 +62,8 @@ const ProjectsContainer = styled.div` display: flex; flex-direction: column; align-items: center; - padding: 96px 64px; + // padding: 0px 64px 96px 64px; + // background: #fafafa; `; State.init({ @@ -80,11 +85,8 @@ if (context.accountId && !state.registeredProjects) { Near.asyncView("social.near", "get", { keys: projects.map((project) => `${project.id}/profile/**`), }).then((socialData) => { - console.log("social data: ", socialData); const formattedProjects = projects.map((project) => { - console.log("project line 153: ", project); const profileData = socialData[project.id]?.profile; - console.log("profileData line 154: ", profileData); let profileImageUrl = DEFAULT_PROFILE_IMAGE_URL; if (profileData.image) { const imageUrl = getImageUrlFromSocialImage(profileData.image); @@ -104,10 +106,8 @@ if (context.accountId && !state.registeredProjects) { profileImageUrl, tags: [profileData.category.text ?? ""], // TODO: change this to get tags from horizon/social }; - console.log("formatted: ", formatted); return formatted; }); - console.log("formatted projects: ", formattedProjects); State.update({ registeredProjects: formattedProjects }); }); }) @@ -117,9 +117,7 @@ if (context.accountId && !state.registeredProjects) { }); } -console.log("state: ", state); - -if (!state.registeredProjects) return <>Loading...; +if (!state.registeredProjects) return ""; return ( <> @@ -154,14 +152,6 @@ return ( ), }} /> - - {/* Featured projects */} - {/* */} All projects diff --git a/apps/potlock/widget/Project/ListSection.jsx b/apps/potlock/widget/Project/ListSection.jsx index 8c9ca50d..8aef394a 100644 --- a/apps/potlock/widget/Project/ListSection.jsx +++ b/apps/potlock/widget/Project/ListSection.jsx @@ -5,10 +5,11 @@ const Container = styled.div` display: flex; flex-direction: column; align-items: flex-start; - padding: 48px 0px; + padding: 48px 64px; gap: 40px; width: 100%; border-top: 2px #dbdbdb solid; + background: #fafafa; `; const List = styled.div` @@ -38,8 +39,6 @@ const List = styled.div` } `; -console.log("props.projects: ", props.projects); - return ( {props.projects.map((project) => renderItem(project))} diff --git a/apps/potlock/widget/Project/NavOptions.jsx b/apps/potlock/widget/Project/NavOptions.jsx index e1929db3..3e842f62 100644 --- a/apps/potlock/widget/Project/NavOptions.jsx +++ b/apps/potlock/widget/Project/NavOptions.jsx @@ -1,5 +1,3 @@ -console.log("props in NavOptions: ", props); - const navOptions = [ { label: "Home", @@ -23,8 +21,6 @@ const navOptions = [ }, ]; -console.log("props.nav: ", props.nav); - const getSelectedNavOption = () => { const navOption = navOptions.find((option) => option.label == props.nav); return navOption ?? navOptions[0]; diff --git a/apps/potlock/widget/Project/Team.jsx b/apps/potlock/widget/Project/Team.jsx index 60eb4e84..0520b566 100644 --- a/apps/potlock/widget/Project/Team.jsx +++ b/apps/potlock/widget/Project/Team.jsx @@ -44,8 +44,6 @@ const TeamMemberAccountId = styled.div` const team = props.team ?? {}; -console.log("team in Team: ", team); - const imageWidthPx = 129; const ImageContainer = styled.div` @@ -63,11 +61,6 @@ return ( {props.team.map((teamMember) => { - console.log("teammember: ", teamMember); - console.log( - "state.teamMembersProfiles[teamMember]: ", - state.teamMembersProfiles[teamMember] - ); return ( @{teamMember} diff --git a/build/potlock/src/Buttons/ActionButton.jsx b/build/potlock/src/Buttons/ActionButton.jsx index 381f7aff..c1716529 100644 --- a/build/potlock/src/Buttons/ActionButton.jsx +++ b/build/potlock/src/Buttons/ActionButton.jsx @@ -40,6 +40,7 @@ const Button = styled.button` text-align: center; color: ${getButtonTextColor()}; font-size: 14px; + line-height: 16px; font-weight: 600; &:hover { diff --git a/build/potlock/src/Components/Header.jsx b/build/potlock/src/Components/Header.jsx index b821f94a..4aed28af 100644 --- a/build/potlock/src/Components/Header.jsx +++ b/build/potlock/src/Components/Header.jsx @@ -1,10 +1,13 @@ const ownerId = "potlock.near"; +const loraCss = fetch("https://fonts.googleapis.com/css2?family=Lora&display=swap").body; + const headerTitleFontSizePx = 88; const HeaderContainer = styled.div` width: 100%; - background: #fffaf4; + // background: #fffaf4; + background: white; padding: 80px 64px; `; @@ -17,15 +20,17 @@ const HeaderContent = styled.div` const HeaderTitle = styled.div` color: #2e2e2e; font-size: ${headerTitleFontSizePx}px; - font-weight: 600; + font-weight: 500; word-wrap: break-word; position: relative; + text-align: center; + font-family: "Lora"; + ${loraCss} `; const HeaderDescription = styled.div` color: #2e2e2e; font-size: 32px; - font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; max-width: 866px; @@ -43,6 +48,7 @@ const ButtonsContainer = styled.div` `; return ( + // @@ -78,4 +84,5 @@ return ( {props.buttonSecondary && props.buttonSecondary} + // ); diff --git a/build/potlock/src/Index.jsx b/build/potlock/src/Index.jsx index 554af8a2..56ea1018 100644 --- a/build/potlock/src/Index.jsx +++ b/build/potlock/src/Index.jsx @@ -3,81 +3,31 @@ const ownerId = "potlock.near"; const CREATE_PROJECT_TAB = "createproject"; const PROJECT_DETAIL_TAB = "project"; +const monaSansCss = fetch("https://fonts.cdnfonts.com/css/mona-sans").body; + +if (!monaSansCss) return ""; + +const Theme = styled.div` + * { + font-family: "Mona-Sans"; + } + ${monaSansCss} +`; + State.init({ tnc: true, tncIsFetched: false, tosAccept: true, }); -// if (context.accountId && !state.tncIsFetched) { -// Near.asyncView( -// "social.near", -// "get", -// { -// keys: [ -// `${context.accountId}/profile/horizon_tnc`, -// `${context.accountId}/index/tosAccept`, -// ], -// }, -// "final", -// false -// ).then((data) => -// State.update({ -// tnc: data[context.accountId]?.profile?.horizon_tnc === "true", -// tosAccept: -// data[context.accountId]?.index?.tosAccept && -// data[context.accountId]?.index?.tosAccept.length > 0, -// tncIsFetched: true, -// }) -// ); -// } - const tabContentWidget = { - // home: "Dashboard", - // inbox: "Inbox", - // manage: "Manage", - // project: "Project.Page", - // request: "Request.Page", - // vendor: "Vendor.Page", - // backer: "Investor.Page", - // contribution: "Contribution.Page", [CREATE_PROJECT_TAB]: "Project.Create", - // createrequest: "Request.Form", - // createvendor: "Vendor.Form", - // createbacker: "Investor.Form", - // permissions: "Inputs.SetUpPermissions", - // learn: "Learn.Page", - // faq: "FAQ.Page", - // help: "Help.Page", - // legal: "TNCPage", - // admin: "Admin.Page", projects: "Project.ListPage", [PROJECT_DETAIL_TAB]: "Project.Detail", - // investors: "Investor.ListPage", - // backers: "Investor.ListPage", - // vendors: "Vendor.ListPage", - // contributors: "Vendor.ListPage", - // requests: "Request.ListPage", - // partners: "Application.Page", - // partner: "Application.DetailPage", - // "my-projects": "Manage.Projects", - // "my-requests": "Manage.Requests", - // "my-contracts": "Manage.Contracts", - // "my-applications": "Manage.Applications", - // events: "Events.Page", - // perks: "Perks.Page", - // profile: "Profile.Page", }; -const successfulRegistration = props.tab == CREATE_PROJECT_TAB && props.transactionHashes; - const getWidget = (props) => { - if (successfulRegistration) { - // user just successfully registered their project - // navigate to the project page - // get the project ID (do this in getWidgetProps) - return tabContentWidget[PROJECT_DETAIL_TAB]; - } else if (props.tab in tabContentWidget) { + if (props.tab in tabContentWidget) { return tabContentWidget[props.tab]; } // backup (TODO: review) @@ -92,51 +42,19 @@ const getTabWidget = (tab) => { return "Project.ListPage"; }; -const getWidgetProps = () => { - const props = { - ...props, - urlProps: props, - }; - if (successfulRegistration) { - props.successfulRegistration = true; - // get the project ID - // get list of all registered projects - // find the one that matches context.accountId - // pass this project in props to the project page - } - return { - ...props, - urlProps: props, - successfulRegistration, - }; -}; // TODO: IMPLEMENT - -console.log("Index props: ", props); - const tabContent = ( ); -console.log("tab content: ", tabContent); - -// const Page = styled.div` -// width: 100%; -// border-radius: 0.5rem; -// border: 1px solid #eaeaea; -// `; - const Content = styled.div` - padding-top: 110px; width: 100%; + height: 100%; background: #ffffff; // padding: 3em; border-radius: 0rem 0rem 1.5rem 1.5rem; @@ -149,35 +67,11 @@ const Content = styled.div` } `; -// const showSidebar = ![ -// "createproject", -// "createrequest", -// "createvendor", -// "createbacker", -// "permissions", -// "legal", -// ].includes(props.tab); -const isForm = [ - CREATE_PROJECT_TAB, - // "createrequest", - // "createvendor", - // "createbacker", -].includes(props.tab); - -// const showTncDialog = !state.tnc && state.tosAccept && props.tab !== "legal"; +const isForm = [CREATE_PROJECT_TAB].includes(props.tab); return ( - <> + - {/* */} - {/* */} {tabContent} - + ); diff --git a/build/potlock/src/Nav.jsx b/build/potlock/src/Nav.jsx index 28a99289..8e233c1d 100644 --- a/build/potlock/src/Nav.jsx +++ b/build/potlock/src/Nav.jsx @@ -1,155 +1,10 @@ const ownerId = "potlock.near"; -// const apiUrl = "https://api-op3o.onrender.com"; - -// State.init({ -// exists: false, -// project: false, -// balance: 0, -// profileIsFetched: false, -// }); - -// if (!state.profileIsFetched) { -// if (!context.accountId) { -// State.update({ -// profileIsFetched: true, -// }); -// } else { -// Near.asyncView( -// ownerId, -// "check_is_project", -// { account_id: context.accountId }, -// "final", -// false -// ).then((profileExists) => { -// if (profileExists) { -// Near.asyncView( -// ownerId, -// "get_project", -// { account_id: context.accountId }, -// "final", -// false -// ).then((project) => { -// State.update({ -// balance: project.credit_balance, -// project: true, -// exists: true, -// profileIsFetched: true, -// }); -// }); -// } else { -// Near.asyncView( -// ownerId, -// "check_is_vendor", -// { account_id: context.accountId }, -// "final", -// false -// ).then((contributorExists) => { -// if (contributorExists) { -// asyncFetch( -// `${apiUrl}/data/credits/vendors/${context.accountId}/balance` -// ).then(({ body, ok }) => { -// State.update({ -// balance: ok ? body : 0, -// project: false, -// exists: true, -// profileIsFetched: true, -// }); -// }); -// } else { -// State.update({ -// exists: false, -// profileIsFetched: true, -// }); -// } -// }); -// } -// }); -// } -// } - -// const Actions = styled.div` -// display: flex; -// justify-content: flex-end; -// align-items: flex-start; -// gap: 1rem; -// `; - -// const GreyButton = styled.div` -// display: flex; -// align-items: center; -// justify-content: center; -// gap: 0.5rem; -// align-self: stretch; -// `; - -// const GreyContent = styled.div` -// display: flex; -// padding: 0.4375rem 1rem 0.4375rem 1rem; -// align-items: center; -// width: 100%; -// gap: 0.5rem; -// align-self: stretch; -// border-radius: 3.125rem; -// border: 1px solid var(--ui-elements-light, #eceef0); -// background: var(--background-light, #fafafa); -// color: var(--ui-elements-black, #000); -// text-align: center; -// font-family: Inter; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 600; -// line-height: 142%; /* 1.2425rem */ -// letter-spacing: 0.00875rem; - -// & > span { -// color: var(--ui-elements-black, #000); -// leading-trim: both; -// text-edge: cap; -// font-family: "Mona Sans"; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 500; -// line-height: 142%; /* 1.2425rem */ -// letter-spacing: 0.00875rem; -// } - -// & > b { -// color: var(--ui-elements-black, #000); -// leading-trim: both; -// text-edge: cap; -// font-family: "Mona Sans"; -// font-size: 0.875rem; -// font-style: normal; -// font-weight: 700; -// line-height: 142%; -// letter-spacing: 0.00875rem; -// } - -// & > svg { -// transform: translateY(-1px); -// } - -// & > a { -// color: var(--ui-elements-black, #000); -// text-decoration: none; -// cursor: pointer; -// display: flex; -// align-items: center; -// gap: 0.5rem; - -// &:hover, -// &:focus, -// &:active { -// text-decoration: none; -// color: var(--ui-elements-black, #000); -// } -// } -// `; const Nav = styled.div` - position: fixed; - top: 0; - left: 0; + // commenting out stickiness for now + // position: fixed; + // top: 0; + // left: 0; width: 100%; display: flex; padding: 0 64px 0 64px; @@ -176,7 +31,14 @@ const NavLeft = styled.div` justify-content: center; `; -const NavIcon = styled.div` +const NavRight = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +`; + +const NavLogo = styled.a` text-align: center; color: #2e2e2e; font-size: 23.95px; @@ -184,6 +46,11 @@ const NavIcon = styled.div` line-height: 23.95px; word-wrap: break-word; margin-right: 48px; + text-decoration: none; + + :hover { + text-decoration: none; + } `; const NavTabs = styled.div` @@ -194,24 +61,23 @@ const NavTabs = styled.div` `; const NavTab = styled.a` - :not(:last-child) { - margin-right: 32px; - } - cursor: pointer; + cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")}; color: #7b7b7b; fontsize: 14; fontfamily: Mona-Sans; fontweight: 500; lineheight: 16; wordwrap: break-word; -`; + text-decoration: none; -// const profileIcon = ( -// -// ); + :not(:last-child) { + margin-right: 32px; + } + + :hover { + text-decoration: none; + } +`; const tabOptions = [ { text: "Projects", link: "projects", disabled: false }, @@ -222,17 +88,24 @@ const tabOptions = [ return ( ); diff --git a/build/potlock/src/Project/About.jsx b/build/potlock/src/Project/About.jsx index 8d357cc1..64a38b96 100644 --- a/build/potlock/src/Project/About.jsx +++ b/build/potlock/src/Project/About.jsx @@ -16,14 +16,12 @@ const About = () => ( props={{ ...props, title: "Overview", - text: description.repeat(100), + text: description, }} /> ); -console.log("Props in About: ", props); - const Team = () => ( diff --git a/build/potlock/src/Project/BannerHeader.jsx b/build/potlock/src/Project/BannerHeader.jsx index 864d1f49..7d92bd57 100644 --- a/build/potlock/src/Project/BannerHeader.jsx +++ b/build/potlock/src/Project/BannerHeader.jsx @@ -19,6 +19,9 @@ const name = profile.name || "No-name profile"; const image = profile.image; const backgroundImage = profile.backgroundImage; const tags = Object.keys(profile.tags ?? {}); +const imageStyle = props.imageStyle ?? {}; +const backgroundStyle = props.backgroundStyle ?? {}; +const containerStyle = props.containerStyle ?? {}; const Wrapper = styled.div` overflow: hidden; @@ -26,32 +29,36 @@ const Wrapper = styled.div` `; return ( -
+
{backgroundImage && ( )} -
+
+ {props.children && props.children}
); diff --git a/build/potlock/src/Project/Body.jsx b/build/potlock/src/Project/Body.jsx index e54056d6..925c3a4c 100644 --- a/build/potlock/src/Project/Body.jsx +++ b/build/potlock/src/Project/Body.jsx @@ -1,15 +1,9 @@ -console.log("props in Body: ", props); - const ownerId = "potlock.near"; const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; -// const linktree = props.linktree; - -// if (!linktree) return "Loading..."; - const profile = props.profile; -if (!profile) return "Loading..."; +if (!profile) return "Loading PROFILE..."; const tags = Object.keys(profile.tags ?? {}); diff --git a/build/potlock/src/Project/Card.jsx b/build/potlock/src/Project/Card.jsx index 654b71c6..37d9e74a 100644 --- a/build/potlock/src/Project/Card.jsx +++ b/build/potlock/src/Project/Card.jsx @@ -4,40 +4,44 @@ const Card = styled.a` display: flex; flex-direction: column; width: 100%; - border-radius: 6px; - background-color: white; + max-width: 30%; + border-radius: 7px; + background: white; + box-shadow: 0px -2px 0px #dbdbdb inset; + border: 1px solid #dbdbdb; &:hover { text-decoration: none; cursor: pointer; } `; -const Banner = styled.div` - position: relative; - width: 100%; - height: 168; - margin-bottom: 30px; -`; +// const Banner = styled.div` +// position: relative; +// width: 100%; +// height: 168; +// margin-bottom: 30px; +// `; -const BannerImage = styled.img` - width: 100%; - height: 100%; - // border-radius: 6px; -`; +// const BannerImage = styled.img` +// width: 100%; +// height: 100%; +// // border-radius: 6px; +// `; -const ProfileImage = styled.img` - width: 40px; - height: 40px; - border-radius: 50%; - border: 3px solid white; - position: absolute; - bottom: -20px; - left: 60px; -`; +// const ProfileImage = styled.img` +// width: 40px; +// height: 40px; +// border-radius: 50%; +// border: 3px solid white; +// position: absolute; +// bottom: -20px; +// left: 60px; +// `; const Info = styled.div` display: flex; flex-direction: column; + margin-top: 160px; padding: 16px 24px; gap: 16px; `; @@ -72,10 +76,32 @@ const { id, bannerImageUrl, profileImageUrl, name, description, tags } = props.p return ( - - - - + {name} {description} @@ -83,7 +109,7 @@ return ( src={`${ownerId}/widget/Project.Tags`} props={{ ...props, - tags: Object.keys(tags), + tags, }} /> diff --git a/build/potlock/src/Project/CreateForm.jsx b/build/potlock/src/Project/CreateForm.jsx index 61874121..4a26c4ea 100644 --- a/build/potlock/src/Project/CreateForm.jsx +++ b/build/potlock/src/Project/CreateForm.jsx @@ -1,11 +1,11 @@ const ownerId = "potlock.near"; -const registryId = "registry1.tests.potlock.near"; // TODO: update when registry is deployed +const registryId = "registry.potlock.near"; // TODO: update when registry is deployed const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; -const DEFAULT_BANNER_IMAGE_URL = - IPFS_BASE_URL + "bafkreih4i6kftb34wpdzcuvgafozxz6tk6u4f5kcr2gwvtvxikvwriteci"; -const DEFAULT_PROFILE_IMAGE_URL = - IPFS_BASE_URL + "bafkreifel4bfm6hxmklcsqjilk3bhvi3acf2rxqepcgglluhginbttkyqm"; +// const DEFAULT_BANNER_IMAGE_URL = +// IPFS_BASE_URL + "bafkreih4i6kftb34wpdzcuvgafozxz6tk6u4f5kcr2gwvtvxikvwriteci"; +// const DEFAULT_PROFILE_IMAGE_URL = +// IPFS_BASE_URL + "bafkreifel4bfm6hxmklcsqjilk3bhvi3acf2rxqepcgglluhginbttkyqm"; const ADD_TEAM_MEMBERS_ICON_URL = IPFS_BASE_URL + "bafkreig6c7m2z2lupreu2br4pm3xx575mv6uvmuy2qkij4kzzfpt7tipcq"; const CLOSE_ICON_URL = @@ -27,46 +27,23 @@ if (!context.accountId) { ); } +const imageHeightPx = 120; +const profileImageTranslateYPx = 220; + const Container = styled.div` display: flex; flex-direction: column; - align-items: center; - justify-content: center; width: 100%; padding: 72px 64px 72px 64px; `; -const ProfileImgContainer = styled.div` - width: 120px; - height: 120px; - position: absolute; - bottom: 0px; - left: 113px; - // background-color: pink; -`; - -const Banner = styled.div` - position: relative; - width: 100%; - height: 280px; - margin-bottom: 132px; -`; - -const BannerImage = styled.img` - width: 100%; - height: 100%; - object-fit: cover; - border-radius: 6px; -`; - const LowerBannerContainer = styled.div` position: absolute; - bottom: -60px; + bottom: -210px; left: 0px; display: flex; align-items: stretch; /* Ensuring child elements stretch to full height */ justify-content: space-between; - // background: pink; width: 100%; `; @@ -74,7 +51,7 @@ const LowerBannerContainerLeft = styled.div` display: flex; flex-direction: row; align-items: flex-end; - margin-left: 113px; + margin-left: 190px; `; const LowerBannerContainerRight = styled.div` @@ -96,19 +73,6 @@ const TeamContainer = styled.div` // gap: -40px; `; -const ProfileImage = styled.img` - width: ${(props) => props.width}px; - height: ${(props) => props.height}px; - border-radius: 50%; - border: ${(props) => props.borderWidth ?? 5}px solid white; - margin: ${(props) => props.margin ?? "0px"}; - z-index: ${(props) => props.zIndex ?? 0}; - position: relative; - // position: absolute; - // bottom: -60px; - // left: 113px; -`; - const AddTeamMembers = styled.a` margin: 0px 0px 16px 36px; cursor: pointer; @@ -159,7 +123,6 @@ const FormSectionRightDiv = styled.div` const FormSectionTitle = styled.div` color: #2e2e2e; font-size: 16; - // font-family: Mona-Sans; font-weight: 600; word-wrap: break-word; `; @@ -167,14 +130,12 @@ const FormSectionTitle = styled.div` const FormSectionDescription = styled.div` color: #2e2e2e; font-size: 16; - // font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; `; const FormSectionIsRequired = styled.div` font-size: 16px; - // font-family: Mona-Sans; font-weight: 400; word-wrap: break-word; position: relative; @@ -259,15 +220,13 @@ const ModalTitle = styled.div` font-color: #2e2e2e; font-size: 16px; font-weight: 600; - // font-family: Mona-Sans; `; const ModalDescription = styled.p` font-color: #2e2e2e; font-size: 16px; font-weight: 400; - // font-family: Mona-Sans; -`; +=`; const MembersCount = styled.span` color: #2e2e2e; @@ -280,6 +239,69 @@ const MembersText = styled.div` font-weight: 400; `; +const MembersListItem = styled.div` + padding: 16px 0px; + border-top: 1px #f0f0f0 solid; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +`; + +const RemoveMember = styled.a` + color: #2e2e2e; + font-size: 14px; + font-weight: 600; + visibility: hidden; + cursor: pointer; + opacity: 0; + transition: opacity 0.2s ease-in-out; + + &:hover { + text-decoration: none; + } + + ${MembersListItem}:hover & { + visibility: visible; + opacity: 1; + } +`; + +const MembersListItemLeft = styled.div` + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + gap: 16px; +`; + +const MembersListItemText = styled.div` + font-size: 16px; + font-weight: 400; + color: #2e2e2e; +`; + +const MoreTeamMembersContainer = styled.div` + width: 28px; + height: 28px; + border: 2px solid white; + border-radius: 50%; + background: #dd3345; + position: relative; + display: flex; + justify-content: center; + align-items: center; + z-index: ${(props) => props.zIndex}; + margin-right: -8px; +`; + +const MoreTeamMembersText = styled.div` + color: white; + font-size: 12px; + font-weight: 600; + text-align: center; +`; + State.init({ name: "", nameError: "", @@ -295,10 +317,6 @@ State.init({ telegramError: "", github: "", githubError: "", - profileImageUrl: "", - profileImageError: "", - bannerImageCid: "", - bannerImageError: "", socialDataFetched: false, socialDataIsFetching: false, registeredProjects: null, @@ -328,26 +346,11 @@ const Modal = ({ isOpen, onClose, children }) => { }; if (context.accountId && !state.socialDataFetched) { - // State.update({ socialDataIsFetching: true }); - // const socialData = Social.get(`${context.accountId}/profile/**`); Near.asyncView("social.near", "get", { keys: [`${context.accountId}/profile/**`] }) .then((socialData) => { if (!socialData) return; - console.log("social data for current user: ", socialData); const profileData = socialData[context.accountId].profile; if (!profileData) return; - // get profile image URL - let profileImageUrl = DEFAULT_PROFILE_IMAGE_URL; - if (profileData.image) { - const imageUrl = getImageUrlFromSocialImage(profileData.image); - if (imageUrl) profileImageUrl = imageUrl; - } - // get banner image URL - let bannerImageUrl = DEFAULT_BANNER_IMAGE_URL; - if (profileData.backgroundImage) { - const imageUrl = getImageUrlFromSocialImage(profileData.backgroundImage); - if (imageUrl) bannerImageUrl = imageUrl; - } // description let description = profileData.description || ""; // linktree @@ -366,14 +369,11 @@ if (context.accountId && !state.socialDataFetched) { telegram, github, website, - profileImageUrl, - bannerImageUrl, socialDataFetched: true, teamMembers: Object.keys(team).map((accountId) => ({ accountId, imageUrl: DEFAULT_PROFILE_IMAGE_URL, // TODO: fetch actual image from near social. or better, move ProfileImage to its own component that handles the social data fetching })), - // socialDataIsFetching: false, }); }) .catch((e) => { @@ -393,61 +393,6 @@ if (context.accountId && !state.registeredProjects) { }); } -const FormSectionLeft = (title, description, isRequired) => { - return ( - - {title} - {description} - - {isRequired ? "Required" : "Optional"} - {isRequired && ( - - - - - - )} - - - ); -}; - -const BannerImageWithFallback = (props) => { - const [bannerImageUrl, setBannerImageUrl] = useState(props.src); - const handleBannerImageError = (event) => { - event.stopPropagation(); - event.target.onerror = null; - setBannerImageUrl(DEFAULT_BANNER_IMAGE_URL); - }; - return ; -}; - -// _NB: commenting this out for now; for some reason profileImageUrl inherits bannerImageUrl's value and is NOT set to props.src. this seems to be a bug with useState implementation_ -// const ProfileImageWithFallback = (props) => { -// const [profileImageUrl, setProfileImageUrl] = useState(props.src); -// const handleError = (event) => { -// event.stopPropagation(); -// event.target.onerror = null; -// setProfileImageUrl(DEFAULT_PROFILE_IMAGE_URL); -// }; -// return ; -// }; - const isCreateProjectDisabled = !state.name || state.nameError || @@ -496,79 +441,12 @@ const handleCreateProject = (e) => { const res = Near.call(transactions); }; -console.log("state: ", state); - const registeredProject = state.registeredProjects ? state.registeredProjects?.find( (project) => project.id == context.accountId && project.status == "Approved" ) : null; -// TODO: Move these elsewhere -const MembersListItem = styled.div` - padding: 16px 0px; - border-top: 1px #f0f0f0 solid; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -`; - -const RemoveMember = styled.a` - color: #2e2e2e; - font-size: 14px; - font-weight: 600; - visibility: hidden; - cursor: pointer; - opacity: 0; - transition: opacity 0.2s ease-in-out; - - &:hover { - text-decoration: none; - } - - ${MembersListItem}:hover & { - visibility: visible; - opacity: 1; - } -`; - -const MembersListItemLeft = styled.div` - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - gap: 16px; -`; - -const MembersListItemText = styled.div` - font-size: 16px; - font-weight: 400; - color: #2e2e2e; -`; - -const MoreTeamMembersContainer = styled.div` - width: 28px; - height: 28px; - border: 2px solid white; - border-radius: 50%; - background: #dd3345; - position: relative; - display: flex; - justify-content: center; - align-items: center; - z-index: ${(props) => props.zIndex}; - margin-right: -8px; -`; - -const MoreTeamMembersText = styled.div` - color: white; - font-size: 12px; - font-weight: 600; - text-align: center; - // font-family: Mona-Sans; -`; - const handleAddTeamMember = () => { let isValid = NEAR_ACCOUNT_ID_REGEX.test(state.teamMember); // Additional ".near" check for IDs less than 64 characters @@ -591,7 +469,6 @@ const handleAddTeamMember = () => { }; Near.asyncView("social.near", "get", { keys: [`${state.teamMember}/profile/**`] }) .then((socialData) => { - console.log("social data line 554: ", socialData); if (socialData) { const profileData = socialData[state.teamMember].profile; if (!profileData) return; @@ -599,7 +476,6 @@ const handleAddTeamMember = () => { if (profileData.image) { const imageUrl = getImageUrlFromSocialImage(profileData.image); if (imageUrl) fullTeamMember.imageUrl = imageUrl; - console.log("fullTeamMember.imageUrl line 562: ", fullTeamMember.imageUrl); } } }) @@ -607,7 +483,6 @@ const handleAddTeamMember = () => { console.log("error getting social data: ", e); }) .finally(() => { - console.log("fullTeamMember.imageUrl line 570: ", fullTeamMember.imageUrl); State.update({ teamMembers: [...state.teamMembers, fullTeamMember], teamMember: "", @@ -617,13 +492,47 @@ const handleAddTeamMember = () => { } }; +const FormSectionLeft = (title, description, isRequired) => { + return ( + + {title} + {description} + + {isRequired ? "Required" : "Optional"} + {isRequired && ( + + + + + + )} + + + ); +}; + return ( {!state.socialDataFetched ? ( -
Loading...
+
) : registeredProject ? ( - <> -

You've successfully registered!

+ +

You've successfully registered!

- +
) : ( <> - - - - - - State.update({ isModalOpen: true })}> - Add team members - - - - - {state.teamMembers.length > MAX_TEAM_MEMBERS_DISPLAY_COUNT && ( - - {MAX_TEAM_MEMBERS_DISPLAY_COUNT}+ - - )} - {state.teamMembers - .slice(0, MAX_TEAM_MEMBERS_DISPLAY_COUNT) - .map((teamMember, idx) => { - return ( - - ); - })} - - - - - + + + State.update({ isModalOpen: true })}> + Add team members + + + + + {state.teamMembers.length > MAX_TEAM_MEMBERS_DISPLAY_COUNT && ( + + {MAX_TEAM_MEMBERS_DISPLAY_COUNT}+ + + )} + {state.teamMembers + .slice(0, MAX_TEAM_MEMBERS_DISPLAY_COUNT) + .map((teamMember, idx) => { + return ( + + ); + })} + + + + ), + }} + /> + - - {/* */} - {FormSectionLeft( "Project details", @@ -899,7 +835,22 @@ return ( return ( - + @{teamMember.accountId} -
+
(props.disabled ? "not-allowed" : "pointer")}; &:hover { text-decoration: none; @@ -48,6 +47,12 @@ const itemIconUrls = { NEAR: IPFS_BASE_URL + "bafkreigogi7iyonbdjsxi3n6seplll7at6e4jsrxwpgke5b5uk5obxkdpe", }; +const fullUrls = { + twitter: (handle) => `https://twitter.com/${handle}`, + github: (username) => `https://github.com/${username}`, + website: (url) => url, +}; + return ( {Object.entries(linktree).map(([k, v], idx) => { @@ -55,8 +60,14 @@ return ( { + if (!v) { + e.preventDefault(); + } + }} > {k[0].toUpperCase() + k.slice(1)} @@ -67,7 +78,7 @@ return ( NEAR diff --git a/build/potlock/src/Project/ListPage.jsx b/build/potlock/src/Project/ListPage.jsx index faa1f022..dd56b39f 100644 --- a/build/potlock/src/Project/ListPage.jsx +++ b/build/potlock/src/Project/ListPage.jsx @@ -1,5 +1,5 @@ const ownerId = "potlock.near"; -const registryId = "registry1.tests.potlock.near"; // TODO: update when registry is deployed +const registryId = "registry.potlock.near"; // TODO: update when registry is deployed const IPFS_BASE_URL = "https://nftstorage.link/ipfs/"; const DEFAULT_BANNER_IMAGE_URL = @@ -15,6 +15,15 @@ const getImageUrlFromSocialImage = (image) => { } }; +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +`; + const HeroOuter = styled.div` padding: 136px 64px; `; @@ -26,18 +35,13 @@ const HeroInner = styled.div` justify-content: space-between; `; -const Separator = styled.div` - width: 100%; - height: 96px; - background-color: #f8f8f8; -`; - const SectionHeader = styled.div` display: flex; flex-direction: row; width: 100%; align-items: center; margin-bottom: 24px; + padding: 96px 64px 24px 64px; `; const SectionTitle = styled.div` @@ -58,7 +62,8 @@ const ProjectsContainer = styled.div` display: flex; flex-direction: column; align-items: center; - padding: 96px 64px; + // padding: 0px 64px 96px 64px; + // background: #fafafa; `; State.init({ @@ -80,11 +85,8 @@ if (context.accountId && !state.registeredProjects) { Near.asyncView("social.near", "get", { keys: projects.map((project) => `${project.id}/profile/**`), }).then((socialData) => { - console.log("social data: ", socialData); const formattedProjects = projects.map((project) => { - console.log("project line 153: ", project); const profileData = socialData[project.id]?.profile; - console.log("profileData line 154: ", profileData); let profileImageUrl = DEFAULT_PROFILE_IMAGE_URL; if (profileData.image) { const imageUrl = getImageUrlFromSocialImage(profileData.image); @@ -104,10 +106,8 @@ if (context.accountId && !state.registeredProjects) { profileImageUrl, tags: [profileData.category.text ?? ""], // TODO: change this to get tags from horizon/social }; - console.log("formatted: ", formatted); return formatted; }); - console.log("formatted projects: ", formattedProjects); State.update({ registeredProjects: formattedProjects }); }); }) @@ -117,9 +117,7 @@ if (context.accountId && !state.registeredProjects) { }); } -console.log("state: ", state); - -if (!state.registeredProjects) return <>Loading...; +if (!state.registeredProjects) return ""; return ( <> @@ -154,14 +152,6 @@ return ( ), }} /> - - {/* Featured projects */} - {/* */} All projects diff --git a/build/potlock/src/Project/ListSection.jsx b/build/potlock/src/Project/ListSection.jsx index 8c9ca50d..8aef394a 100644 --- a/build/potlock/src/Project/ListSection.jsx +++ b/build/potlock/src/Project/ListSection.jsx @@ -5,10 +5,11 @@ const Container = styled.div` display: flex; flex-direction: column; align-items: flex-start; - padding: 48px 0px; + padding: 48px 64px; gap: 40px; width: 100%; border-top: 2px #dbdbdb solid; + background: #fafafa; `; const List = styled.div` @@ -38,8 +39,6 @@ const List = styled.div` } `; -console.log("props.projects: ", props.projects); - return ( {props.projects.map((project) => renderItem(project))} diff --git a/build/potlock/src/Project/NavOptions.jsx b/build/potlock/src/Project/NavOptions.jsx index e1929db3..3e842f62 100644 --- a/build/potlock/src/Project/NavOptions.jsx +++ b/build/potlock/src/Project/NavOptions.jsx @@ -1,5 +1,3 @@ -console.log("props in NavOptions: ", props); - const navOptions = [ { label: "Home", @@ -23,8 +21,6 @@ const navOptions = [ }, ]; -console.log("props.nav: ", props.nav); - const getSelectedNavOption = () => { const navOption = navOptions.find((option) => option.label == props.nav); return navOption ?? navOptions[0]; diff --git a/build/potlock/src/Project/Team.jsx b/build/potlock/src/Project/Team.jsx index 60eb4e84..0520b566 100644 --- a/build/potlock/src/Project/Team.jsx +++ b/build/potlock/src/Project/Team.jsx @@ -44,8 +44,6 @@ const TeamMemberAccountId = styled.div` const team = props.team ?? {}; -console.log("team in Team: ", team); - const imageWidthPx = 129; const ImageContainer = styled.div` @@ -63,11 +61,6 @@ return ( {props.team.map((teamMember) => { - console.log("teammember: ", teamMember); - console.log( - "state.teamMembersProfiles[teamMember]: ", - state.teamMembersProfiles[teamMember] - ); return ( @{teamMember}