Skip to content

Commit

Permalink
Merge pull request #26 from Quest-Protocol/feat/frontend
Browse files Browse the repository at this point in the history
front end and app
  • Loading branch information
elliotBraem authored Dec 8, 2023
2 parents a28536a + da6bcd9 commit 56bea73
Show file tree
Hide file tree
Showing 18 changed files with 2,461 additions and 242 deletions.
77 changes: 76 additions & 1 deletion questverse-widgets/apps/QuestVerse/widget/app.jsx
Original file line number Diff line number Diff line change
@@ -1 +1,76 @@
return <Widget src="/*__@appAccount__*//widget/pages.Dashboard"></Widget>;
const { page, ...passProps } = props;

const { AppLayout } = VM.require(
"/*__@appAccount__*//widget/components.Layout"
);

if (!AppLayout) {
return <p>Loading modules...</p>;
}

// CSS styles to be used across the app.
// Define fonts here, as well as any other global styles.
const Theme = styled.div`
a {
color: inherit;
}
width: 100%;
height: 100vh;
`;

if (!page) {
// If no page is specified, we default to the feed page TEMP
page = "dashboard";
}

// This is our navigation, rendering the page based on the page parameter
function Page() {
const routes = page.split(".");
switch (routes[0]) {
case "dashboard": {
return (
<Widget
src="/*__@appAccount__*//widget/pages.Dashboard"
props={passProps}
/>
);
}
case "discover": {
return (
<Widget
src="/*__@appAccount__*//widget/pages.Discover"
props={passProps}
/>
);
}
case "create": {
return (
<Widget
src="/*__@appAccount__*//widget/pages.Create"
props={passProps}
/>
);
}
case "quest": {
return (
<Widget
src="/*__@appAccount__*//widget/pages.Quest"
props={passProps}
/>
);
}
default: {
// TODO: 404 page
return <p>404</p>;
}
}
}

return (
<Theme>
<AppLayout page={page}>
<Page />
</AppLayout>
</Theme>
);
46 changes: 46 additions & 0 deletions questverse-widgets/apps/QuestVerse/widget/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const Toolbar = styled.div`
margin-left: 20px;
@media only screen and (max-width: 1061px) {
margin: 10px 0 0 0;
}
`;

const registryContract = "registry.i-am-human.near";
const issuer = "fractal.i-am-human.near";

// SBT verification
let isVerified = false;
const userSBTs = Near.view("registry.i-am-human.near", "sbt_tokens_by_owner", {
account: context.accountId,
});

for (let i = 0; i < userSBTs.length; i++) {
if ("fractal.i-am-human.near" == userSBTs[i][0]) {
isVerified = true;
}
}

return (
<div className="d-flex p-3 px-4 align-items-center rounded justify-content-between bg-black">
<h3 className="mt-2" style={{ fontFamily: "Courier", color: "white" }}>
<Link to="//*__@appAccount__*//widget/app">
<b>QuestVerse</b>
</Link>
</h3>
<Toolbar>
{!isVerified ? (
<Widget
src="hack.near/widget/n.style"
props={{
Link: {
text: "Get Verified",
href: "https://i-am-human.app/",
},
}}
/>
) : (
<Widget src="hack.near/widget/start" />
)}
</Toolbar>
</div>
);
60 changes: 60 additions & 0 deletions questverse-widgets/apps/QuestVerse/widget/components/Layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const Container = styled.div`
display: flex;
flex-direction: column;
width: 100%;
height: auto;
min-height: 100vh;
background: #f4f4f4;
margin-top: calc(-1 * var(--body-top-padding));
`;

const ContentContainer = styled.div`
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
`;

const Header = styled.div`
background: black;
`;

const registryContract = "registry.i-am-human.near";
const issuer = "fractal.i-am-human.near";

// SBT verification
let isVerified = false;
const userSBTs = Near.view("registry.i-am-human.near", "sbt_tokens_by_owner", {
account: props.accountId ?? context.accountId,
});

for (let i = 0; i < userSBTs.length; i++) {
if ("fractal.i-am-human.near" == userSBTs[i][0]) {
isVerified = true;
}
}

const AppHeader = ({ page }) => (
<Widget src="/*__@appAccount__*//widget/components.Header" props={{ page }} />
);

const Footer = ({ page }) => {
return <></>;
};

function AppLayout({ page, children }) {
return (
<>
<Container>
<AppHeader page={page} />
<ContentContainer>{children}</ContentContainer>
<Footer page={page} />
</Container>
</>
);
}

return { AppLayout };
71 changes: 35 additions & 36 deletions questverse-widgets/apps/QuestVerse/widget/components/quest/card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ if (!quest) {
return "quest data missing";
}

const questUrl = `//*__@appAccount__*//widget/pages.QuestDetailsPage?questId=${questId}`;

const isEligible = props.isEligible ?? true;

const Card = styled.div`
Expand Down Expand Up @@ -78,11 +76,11 @@ const Tag = styled.a`

return (
<Card>
<CardLeft>
<div className="d-flex flex-column me-3">
<div className="d-flex flex-row me-3">
<div className="me-3">
<a href={questUrl}>
<Link to={`//*__@appAccount__*//widget/app?page=quest&id=${questId}`}>
<CardLeft>
<div className="d-flex flex-column me-3">
<div className="d-flex flex-row me-3">
<div className="me-3">
<Widget
src="mob.near/widget/ProfileImage"
props={{
Expand All @@ -94,48 +92,49 @@ return (
imageClassName: "w-100 h-100",
}}
/>
</a>
</div>
<div className="text-truncate">
<div className="text-truncate mb-1">
<a href={questUrl} style={{ textDecoration: "none" }}>
</div>
<div className="text-truncate">
<div className="text-truncate mb-1">
<span className="fw-bold" style={{ color: "black" }}>
{quest.title}
</span>
</a>
</div>
<div className="text-truncate text-muted">
{quest.tags.length > 0 && (
<>
{quest.tags.map((tag, i) => (
<span
key={i}
className="me-1 fw-light badge border border-secondary text-bg-light"
>
<a
href={`//*__@appAccount__*//widget/quests?tag=${tag}`}
style={{ textDecoration: "none" }}
className="no-text-decoration"
</div>
<div className="text-truncate text-muted">
{quest.tags.length > 0 && (
<>
{quest.tags.map((tag, i) => (
<span
key={i}
className="me-1 fw-light badge border border-secondary text-bg-light"
>
<Tag>#{tag}</Tag>
</a>
</span>
))}
</>
)}
<a
href={`//*__@appAccount__*//widget/quests?tag=${tag}`}
style={{ textDecoration: "none" }}
className="no-text-decoration"
>
<Tag>#{tag}</Tag>
</a>
</span>
))}
</>
)}
</div>
</div>
</div>
<p className="mt-3 m-1">{quest.description}</p>
</div>
<p className="mt-3 m-1">{quest.description}</p>
</div>
</CardLeft>
</CardLeft>
</Link>
{!isVerified && context.accountId && (
<div className="d-flex flex-column m-3">
<p>
<b>{JSON.stringify(quest.reward_amount)} NEAR</b>
</p>

<Widget src="/*__@appAccount__*//widget/components.quest.claim" props={{ questId }} />
<Widget
src="/*__@appAccount__*//widget/components.quest.claim"
props={{ questId }}
/>
<p className="text-center mt-1">
<i>{JSON.stringify(quest.total_participants_allowed)} left</i>
</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const nextChildren = props.isLast ? (
<>
Create Quest <i className="bi bi-check2" />
</>
) : (
<>
Next step <i className="bi bi-chevron-right" />
</>
);
const hasPrevious = props.hasPrevious;
const onReset = props.onReset ?? (() => {});
const onNext = props.onNext ?? (() => {});
const onPrevious = props.onPrevious ?? (() => {});

return (
<div className="d-flex align-items-center gap-2 mt-5">
<Widget
src="nearui.near/widget/Input.Button"
props={{
children: "Reset steps",
variant: "danger outline",
size: "lg",
className: "me-auto",
onClick: onReset,
}}
/>
<Widget
src="nearui.near/widget/Input.Button"
props={{
children: (
<>
<i className="bi bi-chevron-left" /> Previous step
</>
),
variant: "info outline",
size: "lg",
onClick: onPrevious,
className: hasPrevious ? undefined : "d-none",
}}
/>
<Widget
src="nearui.near/widget/Input.Button"
props={{
children: nextChildren,
variant: "info",
size: "lg",
onClick: onNext,
buttonProps: {
type: "submit",
},
}}
/>
</div>
);
Loading

0 comments on commit 56bea73

Please sign in to comment.