Merge remote-tracking branch 'origin/main' into feat/wallet
12
app/src/components/Button.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import styled from "styled-components";
|
||||
import { Button } from "@radix-ui/themes";
|
||||
|
||||
export default styled(Button)`
|
||||
display: inline-flex;
|
||||
padding: 4px 25px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
`;
|
||||
@@ -1,29 +1,45 @@
|
||||
/// <reference types="vite-plugin-svgr/client" />
|
||||
import styled from "styled-components";
|
||||
import {FC} from "react";
|
||||
import LogonIcon from './_/logo.svg?react'
|
||||
import { FC, ReactNode } from "react";
|
||||
|
||||
export const StyledHeader = styled.div`
|
||||
//display: flex;
|
||||
width: 100vw;
|
||||
background: #A9F868;;
|
||||
const StyledHeaderName = styled.a`
|
||||
color: #000;
|
||||
font-size: 20px;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 30px; /* 150% */
|
||||
letter-spacing: 3px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
padding: 29px 34px;
|
||||
`
|
||||
top: 40px;
|
||||
left: 66px;
|
||||
`;
|
||||
|
||||
export const Header: FC = () => {
|
||||
return (
|
||||
<StyledHeader>
|
||||
<LogonIcon/>
|
||||
</StyledHeader>
|
||||
)
|
||||
}
|
||||
|
||||
return <StyledHeaderName href={"/"}>STORYTIME</StyledHeaderName>;
|
||||
};
|
||||
|
||||
export const PageContainer = styled.div`
|
||||
background: #A9F868;
|
||||
background: #a9f868;
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
`
|
||||
padding: 39px 66px;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const StyledContentContainer = styled.div`
|
||||
flex: 1;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
`;
|
||||
|
||||
export const ContentContainer: FC<{
|
||||
children: ReactNode;
|
||||
className?: string;
|
||||
}> = ({ children, className }) => {
|
||||
return (
|
||||
<StyledContentContainer className={className}>
|
||||
<Header />
|
||||
{children}
|
||||
</StyledContentContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ export function protectedRoute<T extends { user: User }>(component: FC<T>) {
|
||||
return auth.onAuthStateChanged((user) => setUser(user));
|
||||
}, []);
|
||||
if (user === undefined) {
|
||||
return <div>Loading...</div>;
|
||||
return null;
|
||||
}
|
||||
if (user == null) {
|
||||
return <Navigate to="/login" />;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: black;
|
||||
@@ -6,14 +10,8 @@ a {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
body, div, dl, dt, dd, ul, ol, li, tr, td, th,
|
||||
h1, h2, h3, h4, h5, h6, hr, br, img, table,
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Container, Heading, Button } from "@radix-ui/themes";
|
||||
import { createCharacterType } from "../modules/character/actions";
|
||||
|
||||
const CHARACTER_BASE = ["cat", "human", "bear"];
|
||||
|
||||
const CharacterBase = () => {
|
||||
const [characterBase, setCharacterBase] = useState("human");
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Heading>Select Character Base</Heading>
|
||||
<ul>
|
||||
{CHARACTER_BASE.map((c) => (
|
||||
<li key={c} onClick={() => setCharacterBase(c)}>
|
||||
<img src="" alt={c} />
|
||||
<Heading as="h4">{c}</Heading>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Button
|
||||
onClick={() => {
|
||||
// update default character type
|
||||
dispatch(createCharacterType({ characterType: characterBase }));
|
||||
navigate("/canvas");
|
||||
}}
|
||||
>
|
||||
Select Character
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default CharacterBase;
|
||||
BIN
app/src/pages/characterBase/_/1.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
app/src/pages/characterBase/_/2.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
app/src/pages/characterBase/_/3.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
app/src/pages/characterBase/_/bear.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
app/src/pages/characterBase/_/dog.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
app/src/pages/characterBase/_/human.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
134
app/src/pages/characterBase/index.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import { useState } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { createCharacterType } from "../../modules/character/actions";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import Button from "../../components/Button";
|
||||
import character1 from "./_/1.png";
|
||||
import character2 from "./_/2.png";
|
||||
import character3 from "./_/3.png";
|
||||
|
||||
const CHARACTER_BASE = [
|
||||
{
|
||||
title: "Bear",
|
||||
image: character1,
|
||||
},
|
||||
{
|
||||
title: "Human",
|
||||
image: character2,
|
||||
},
|
||||
{
|
||||
title: "Dog",
|
||||
image: character3,
|
||||
},
|
||||
];
|
||||
|
||||
const ContentContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.h1`
|
||||
color: #000;
|
||||
font-family: Inter Tight;
|
||||
font-size: 50px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 60px; /* 120% */
|
||||
letter-spacing: -1px;
|
||||
margin-bottom: 76px;
|
||||
`;
|
||||
|
||||
const StyledBaseContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 64px;
|
||||
padding: 0 20px;
|
||||
margin-bottom: 64px;
|
||||
`;
|
||||
|
||||
const StyledBaseItem = styled.div<{ $selected: boolean }>`
|
||||
display: flex;
|
||||
padding: 6px;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
${(props) =>
|
||||
props.$selected &&
|
||||
`
|
||||
border-radius: 5px;
|
||||
background: #C9E7B0;
|
||||
box-shadow: 0px 0px 25px 0px rgba(0, 0, 0, 0.50);
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledBaseItemTitle = styled.div`
|
||||
color: #000;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
line-height: 60px;
|
||||
`;
|
||||
|
||||
const StyledBaseItemImage = styled.img`
|
||||
max-width: 300px;
|
||||
border-radius: 5px;
|
||||
`;
|
||||
|
||||
const BaseItem: React.FC<{
|
||||
selected: boolean;
|
||||
title: string;
|
||||
image: string;
|
||||
onClick: () => void;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<div>
|
||||
<StyledBaseItem $selected={props.selected} onClick={props.onClick}>
|
||||
<StyledBaseItemImage src={props.image} alt="" />
|
||||
</StyledBaseItem>
|
||||
<StyledBaseItemTitle>{props.title}</StyledBaseItemTitle>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CharacterBase = () => {
|
||||
const [characterBase, setCharacterBase] = useState("Human");
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<Header />
|
||||
<ContentContainer>
|
||||
<StyledTitle>Select Character Base</StyledTitle>
|
||||
<StyledBaseContainer>
|
||||
{CHARACTER_BASE.map((c) => (
|
||||
<BaseItem
|
||||
selected={characterBase === c.title}
|
||||
key={c.title}
|
||||
title={c.title}
|
||||
image={c.image}
|
||||
onClick={() => setCharacterBase(c.title)}
|
||||
/>
|
||||
))}
|
||||
</StyledBaseContainer>
|
||||
<Button
|
||||
onClick={() => {
|
||||
// update default character type
|
||||
dispatch(createCharacterType({ characterType: characterBase }));
|
||||
navigate("/canvas");
|
||||
}}
|
||||
>
|
||||
Select Character
|
||||
</Button>
|
||||
</ContentContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default CharacterBase;
|
||||
@@ -1,55 +0,0 @@
|
||||
import { db } from "../firebase.ts";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Project } from "model";
|
||||
import {
|
||||
collection,
|
||||
onSnapshot,
|
||||
QueryDocumentSnapshot,
|
||||
} from "firebase/firestore";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { User } from "firebase/auth";
|
||||
import { Container, Button } from "@radix-ui/themes";
|
||||
import { protectedRoute } from "../components/protectedRoute.tsx";
|
||||
|
||||
const DashboardPage = protectedRoute(({ user }: { user: User }) => {
|
||||
const [projects, setProjects] = useState<QueryDocumentSnapshot<Project>[]>();
|
||||
const navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
onSnapshot(collection(db, `users/${user.uid}/projects`), (snapshot) => {
|
||||
setProjects(
|
||||
snapshot.docs.map((x) => x as QueryDocumentSnapshot<Project>)
|
||||
);
|
||||
});
|
||||
}, [user.uid]);
|
||||
if (projects == null) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
if (projects.length === 0) {
|
||||
return (
|
||||
<Container>
|
||||
Create Your own Adventure
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate("/name");
|
||||
}}
|
||||
>
|
||||
Get Started
|
||||
</Button>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h1>Dashboard</h1>
|
||||
{projects.map((project) => (
|
||||
<Link to={`/projects/${project.id}`}>
|
||||
<h2>{project.data().name}</h2>
|
||||
<p>{project.data().title}</p>
|
||||
</Link>
|
||||
))}
|
||||
{projects.length === 0 && <Link to="/canvas">New Project</Link>}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export default DashboardPage;
|
||||
BIN
app/src/pages/dashboard/_/demo.png
Normal file
|
After Width: | Height: | Size: 250 KiB |
243
app/src/pages/dashboard/index.tsx
Normal file
@@ -0,0 +1,243 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Project } from "model";
|
||||
import {
|
||||
collection,
|
||||
onSnapshot,
|
||||
QueryDocumentSnapshot,
|
||||
} from "firebase/firestore";
|
||||
import { User } from "firebase/auth";
|
||||
import { protectedRoute } from "../../components/protectedRoute";
|
||||
import { db } from "../../firebase";
|
||||
import {
|
||||
ContentContainer,
|
||||
PageContainer,
|
||||
} from "../../components/Layout/Layout";
|
||||
import styled from "styled-components";
|
||||
import demoImage from "./_/demo.png";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Button } from "@radix-ui/themes";
|
||||
|
||||
export const StyledContentContainer = styled(ContentContainer)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
`;
|
||||
|
||||
const StyledEmptyCard = styled.div`
|
||||
width: 774px;
|
||||
height: 420px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 15px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 40px;
|
||||
`;
|
||||
|
||||
const StyledEmptyText = styled.div`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-size: 50px;
|
||||
font-weight: 600;
|
||||
line-height: 60px;
|
||||
letter-spacing: -1px;
|
||||
`;
|
||||
|
||||
export const StyledCreateButton = styled(Button)`
|
||||
color: #fff;
|
||||
width: 149px;
|
||||
height: 48px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #363636;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledSubButton = styled(Button)`
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
cursor: pointer;
|
||||
padding: 4px 25px;
|
||||
&:hover {
|
||||
background: #363636;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledTitleContainer = styled.div`
|
||||
width: 774px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
export const StyledStoryTitle = styled.p`
|
||||
text-align: left;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
line-height: 29px;
|
||||
`;
|
||||
|
||||
export const StyledStoryContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 48px;
|
||||
flex-direction: column;
|
||||
`;
|
||||
export const StyledStoryItem = styled.div`
|
||||
padding: 26px;
|
||||
display: flex;
|
||||
gap: 34px;
|
||||
border-radius: 15px;
|
||||
background: #fff;
|
||||
width: 774px;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
export const StyledStoryImage = styled.img`
|
||||
width: 365.5px;
|
||||
height: 365.5px;
|
||||
`;
|
||||
|
||||
const StyledInfo = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 42px;
|
||||
`;
|
||||
|
||||
const StyledMintTag = styled.div`
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border-radius: 7.11px;
|
||||
background: #a9f868;
|
||||
padding: 7px 11px;
|
||||
`;
|
||||
|
||||
const DateText = styled.span`
|
||||
color: #000;
|
||||
font-size: 12.012px;
|
||||
font-weight: 600;
|
||||
line-height: 16.18px;
|
||||
`;
|
||||
|
||||
export const StyledStoryItemTitle = styled.p`
|
||||
color: #000;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
line-height: 29px;
|
||||
width: 186px;
|
||||
`;
|
||||
|
||||
export const StyledDescription = styled.p`
|
||||
margin-top: 25px;
|
||||
color: #000;
|
||||
font-size: 12.012px;
|
||||
font-weight: 500;
|
||||
line-height: 16.18px;
|
||||
`;
|
||||
//TODO: check margin-top
|
||||
const StyledLink = styled(Link)`
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 14.93px;
|
||||
text-decoration-line: underline;
|
||||
margin-top: 80px;
|
||||
`;
|
||||
|
||||
const StyledIndexTag = styled.div`
|
||||
position: absolute;
|
||||
padding: 14px 16px;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
left: -78px;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
line-height: 16.18px;
|
||||
`;
|
||||
|
||||
const DashboardPage = protectedRoute(({ user }: { user: User }) => {
|
||||
const [projects, setProjects] = useState<QueryDocumentSnapshot<Project>[]>();
|
||||
useEffect(() => {
|
||||
onSnapshot(collection(db, `users/${user.uid}/projects`), (snapshot) => {
|
||||
setProjects(
|
||||
snapshot.docs.map((x) => x as QueryDocumentSnapshot<Project>),
|
||||
);
|
||||
});
|
||||
}, [user.uid]);
|
||||
if (projects == null) {
|
||||
return null;
|
||||
}
|
||||
if (projects.length === 0) {
|
||||
return (
|
||||
<PageContainer>
|
||||
<StyledContentContainer>
|
||||
<StyledTitleContainer>
|
||||
<StyledStoryTitle>Your Stories</StyledStoryTitle>
|
||||
</StyledTitleContainer>
|
||||
<StyledEmptyCard>
|
||||
<StyledEmptyText>Create your first story</StyledEmptyText>
|
||||
<Link to="/name">
|
||||
<StyledCreateButton>Create</StyledCreateButton>
|
||||
</Link>
|
||||
</StyledEmptyCard>
|
||||
</StyledContentContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<PageContainer>
|
||||
<StyledContentContainer>
|
||||
<StyledTitleContainer>
|
||||
<StyledStoryTitle>Your Stories</StyledStoryTitle>
|
||||
<StyledSubButton>Create New Story</StyledSubButton>
|
||||
</StyledTitleContainer>
|
||||
<StyledStoryContainer>
|
||||
{[
|
||||
{
|
||||
name: "The Journey to Dragon’s Keep",
|
||||
image: demoImage,
|
||||
},
|
||||
{
|
||||
name: "The Journey to Dragon’s Keep",
|
||||
image: demoImage,
|
||||
},
|
||||
].map((story, idx) => (
|
||||
<StyledStoryItem>
|
||||
<StyledStoryImage src={story.image} alt="" />
|
||||
<div>
|
||||
<StyledInfo>
|
||||
<StyledMintTag>Minted</StyledMintTag>
|
||||
<DateText>12/12/2023</DateText>
|
||||
</StyledInfo>
|
||||
<StyledStoryItemTitle>{story.name}</StyledStoryItemTitle>
|
||||
<StyledDescription>
|
||||
A playful and bold collage of colors and shapes, blending a
|
||||
retro feel with modern design principles to evoke creativity
|
||||
and the joy of building something unique and impactful.
|
||||
</StyledDescription>
|
||||
<StyledLink>Read Story</StyledLink>
|
||||
</div>
|
||||
<StyledIndexTag>#{idx + 1}</StyledIndexTag>
|
||||
</StyledStoryItem>
|
||||
))}
|
||||
</StyledStoryContainer>
|
||||
</StyledContentContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
});
|
||||
|
||||
export default DashboardPage;
|
||||
BIN
app/src/pages/home/_/poster.png
Normal file
|
After Width: | Height: | Size: 681 KiB |
|
Before Width: | Height: | Size: 168 KiB |
|
Before Width: | Height: | Size: 162 KiB |
|
Before Width: | Height: | Size: 168 KiB |
@@ -1,85 +1,62 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import {
|
||||
ContentContainer,
|
||||
PageContainer,
|
||||
} from "../../components/Layout/Layout";
|
||||
import styled from "styled-components";
|
||||
import step1 from "./_/step1.png";
|
||||
import step2 from "./_/step2.png";
|
||||
import step3 from "./_/step3.png";
|
||||
import posterImage from "./_/poster.png";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useLocation } from "react-router";
|
||||
import { upsertSalt, ZKLoginStore } from "../../components/zklogin.store.tsx";
|
||||
import queryString from "query-string";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { auth } from "../../firebase.ts";
|
||||
|
||||
const StyledTitle = styled.h1`
|
||||
export const StyledContentContainer = styled(ContentContainer)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
color: #000;
|
||||
font-size: 50px;
|
||||
font-weight: 600;
|
||||
line-height: 60px;
|
||||
width: 604px;
|
||||
letter-spacing: -1px;
|
||||
margin-left: 34px;
|
||||
margin-top: 72px;
|
||||
`;
|
||||
|
||||
const StyledStepContainer = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
padding: 0 20px;
|
||||
`;
|
||||
|
||||
const StyledStepItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
`;
|
||||
|
||||
const StyledStepItemTitle = styled.div`
|
||||
color: #000;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
line-height: 60px;
|
||||
`;
|
||||
|
||||
const StyledStepItemImage = styled.img`
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
`;
|
||||
|
||||
const StyledStepItemDescription = styled.div`
|
||||
color: #000;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
`;
|
||||
|
||||
const StepItem: FC<{
|
||||
title: string;
|
||||
description: string;
|
||||
image: string;
|
||||
}> = (props) => {
|
||||
return (
|
||||
<StyledStepItem>
|
||||
<StyledStepItemTitle>{props.title}</StyledStepItemTitle>
|
||||
<StyledStepItemImage src={props.image} alt="" />
|
||||
<StyledStepItemDescription>{props.description}</StyledStepItemDescription>
|
||||
</StyledStepItem>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledStartButton = styled.button`
|
||||
padding: 4px 25px;
|
||||
color: #fff;
|
||||
width: 188px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
width: fit-content;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
|
||||
&:hover {
|
||||
background: #363636;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledStartButtonContainer = styled.div`
|
||||
height: 416px;
|
||||
display: flex;
|
||||
margin-top: 140px;
|
||||
justify-content: center;
|
||||
background-image: url(${posterImage});
|
||||
background-repeat: no-repeat;
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const StyledBox = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
`;
|
||||
|
||||
const LoginButton: FC = () => {
|
||||
@@ -88,6 +65,8 @@ const LoginButton: FC = () => {
|
||||
|
||||
const [store, setStore] = useState<ZKLoginStore>(new ZKLoginStore());
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const oauthParams = queryString.parse(location.hash);
|
||||
@@ -103,6 +82,7 @@ const LoginButton: FC = () => {
|
||||
id_token: oauthParams.id_token as string,
|
||||
}),
|
||||
);
|
||||
setLoading(true);
|
||||
const listener = auth.onAuthStateChanged((x) => {
|
||||
if (x != null) {
|
||||
listener();
|
||||
@@ -123,7 +103,7 @@ const LoginButton: FC = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
Get started
|
||||
{loading ? "Loading..." : "Continue with Google"}
|
||||
</StyledStartButton>
|
||||
);
|
||||
};
|
||||
@@ -131,28 +111,17 @@ const LoginButton: FC = () => {
|
||||
const HomePage: FC = () => {
|
||||
return (
|
||||
<PageContainer>
|
||||
<Header />
|
||||
<StyledTitle>Create your own Adventure</StyledTitle>
|
||||
<StyledStepContainer>
|
||||
<StepItem
|
||||
title={"1.Create Character"}
|
||||
image={step1}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
<StepItem
|
||||
title={"2.Generate Story"}
|
||||
image={step2}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
<StepItem
|
||||
title={"3.Mint Your Story"}
|
||||
image={step3}
|
||||
description="You’ve got two images, you need two words.Start working out that big brain"
|
||||
/>
|
||||
</StyledStepContainer>
|
||||
<StyledStartButtonContainer>
|
||||
<LoginButton />
|
||||
</StyledStartButtonContainer>
|
||||
<StyledContentContainer>
|
||||
<StyledBox>
|
||||
<StyledTitle>
|
||||
Mint Your Story <br />
|
||||
Create Your Own Adventure
|
||||
</StyledTitle>
|
||||
<StyledStartButtonContainer>
|
||||
<LoginButton />
|
||||
</StyledStartButtonContainer>
|
||||
</StyledBox>
|
||||
</StyledContentContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
GoogleAuthProvider,
|
||||
onAuthStateChanged,
|
||||
signInWithPopup,
|
||||
User,
|
||||
} from "firebase/auth";
|
||||
import { auth } from "../../firebase.ts";
|
||||
import { Navigate } from "react-router";
|
||||
|
||||
export const StyledPageContainer = styled(PageContainer)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
`;
|
||||
|
||||
const StyledCard = styled.div`
|
||||
width: 353px;
|
||||
height: 433px;
|
||||
border-radius: 10px;
|
||||
background: #ddffc2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 59px 35px;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const StyledCardTitle = styled.div`
|
||||
color: #000;
|
||||
font-family: N27;
|
||||
font-size: 20px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledDescritionTitle = styled.p`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter Tight;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
line-height: 60px;
|
||||
margin-top: 74px;
|
||||
`;
|
||||
|
||||
const StyledDescription = styled.p`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter Tight;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
width: 237px;
|
||||
`;
|
||||
|
||||
const StyleSubButton = styled.button`
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
width: 283px;
|
||||
padding: 10px 25px;
|
||||
gap: 10px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
margin-top: 80px;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const LoginPage: FC = () => {
|
||||
const [user, setUser] = useState<User | null>();
|
||||
useEffect(() => {
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
setUser(user);
|
||||
});
|
||||
}, []);
|
||||
if (user === undefined) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
if (user != null) {
|
||||
return <Navigate to="/dashboard" />;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<StyledPageContainer>
|
||||
<StyledCard>
|
||||
<StyledCardTitle>STORYTIME</StyledCardTitle>
|
||||
<StyledDescritionTitle>Start Creating!</StyledDescritionTitle>
|
||||
<StyledDescription>
|
||||
You’ve got two images, you need two words. Start working out that
|
||||
big brain
|
||||
</StyledDescription>
|
||||
<StyleSubButton
|
||||
onClick={async () => {
|
||||
const provider = new GoogleAuthProvider();
|
||||
await signInWithPopup(auth, provider);
|
||||
}}
|
||||
>
|
||||
Continue with google
|
||||
</StyleSubButton>
|
||||
</StyledCard>
|
||||
</StyledPageContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
@@ -1,59 +1,65 @@
|
||||
import { FC } from "react";
|
||||
import { Header, PageContainer } from "../../components/Layout/Layout";
|
||||
import { PageContainer } from "../../components/Layout/Layout";
|
||||
import storyImg from "./_/story.png";
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
StyledContentContainer,
|
||||
StyledDescription,
|
||||
StyledStoryContainer,
|
||||
StyledStoryImage,
|
||||
StyledStoryItem,
|
||||
StyledStoryItemTitle,
|
||||
StyledStoryTitle,
|
||||
StyledTitleContainer,
|
||||
} from "../dashboard";
|
||||
import { Button } from "@radix-ui/themes";
|
||||
|
||||
export const StyledPageContainer = styled(PageContainer)`
|
||||
const StyledInfoContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 32px;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
`;
|
||||
|
||||
const StyledMintTitle = styled.div`
|
||||
color: #000;
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 60px;
|
||||
font-weight: 600;
|
||||
line-height: 60px;
|
||||
letter-spacing: -1px;
|
||||
`;
|
||||
|
||||
const StyledMintSubTitle = styled.div`
|
||||
color: #000;
|
||||
font-family: Inter;
|
||||
font-size: 25px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
`
|
||||
|
||||
const StyledMintImg = styled.img`
|
||||
margin-top: 47px;
|
||||
margin-bottom: 29px;
|
||||
`
|
||||
const StyledMintButton = styled.div`
|
||||
padding: 4px 25px;
|
||||
const StyledCreateButton = styled(Button)`
|
||||
color: #fff;
|
||||
width: 149px;
|
||||
height: 32px;
|
||||
border-radius: 10px;
|
||||
background: #000;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
margin-top: 29px;
|
||||
`
|
||||
|
||||
&:hover {
|
||||
background: #363636;
|
||||
}
|
||||
`;
|
||||
|
||||
const MinStoryPage: FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<Header />
|
||||
<StyledPageContainer>
|
||||
<StyledMintTitle>Mint your story</StyledMintTitle>
|
||||
<StyledMintImg src={storyImg} alt="" />
|
||||
<StyledMintSubTitle>The Journey to Dragon’s Keep</StyledMintSubTitle>
|
||||
<StyledMintButton>MINT STORY</StyledMintButton>
|
||||
</StyledPageContainer>
|
||||
</div>
|
||||
<PageContainer>
|
||||
<StyledContentContainer>
|
||||
<StyledTitleContainer>
|
||||
<StyledStoryTitle>Mint your story</StyledStoryTitle>
|
||||
</StyledTitleContainer>
|
||||
<StyledStoryContainer>
|
||||
<StyledStoryItem>
|
||||
<StyledStoryImage src={storyImg} alt="" />
|
||||
<StyledInfoContainer>
|
||||
<StyledStoryItemTitle>
|
||||
The Journey to Dragon’s Keep
|
||||
</StyledStoryItemTitle>
|
||||
<StyledDescription>
|
||||
A playful and bold collage of colors and shapes, blending a
|
||||
retro feel with modern design principles to evoke creativity and
|
||||
the joy of building something unique and impactful.
|
||||
</StyledDescription>
|
||||
<StyledCreateButton>Mint Story</StyledCreateButton>
|
||||
</StyledInfoContainer>
|
||||
</StyledStoryItem>
|
||||
</StyledStoryContainer>
|
||||
</StyledContentContainer>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import { Heading, TextField, Button } from "@radix-ui/themes";
|
||||
import { TextField } from "@radix-ui/themes";
|
||||
import { createCharacterName } from "../modules/character/actions";
|
||||
import { Header, PageContainer } from "../components/Layout/Layout";
|
||||
import Button from "../components/Button";
|
||||
|
||||
const ContentContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -70,7 +71,7 @@ const Name = () => {
|
||||
<StyledInputRoot>
|
||||
<StyledInput
|
||||
value={characterName}
|
||||
onChange={(e) => setCharacterName(e.target.value)}
|
||||
onChange={(e: any) => setCharacterName(e.target.value)}
|
||||
placeholder="ENTER CHARACTER NAME"
|
||||
/>
|
||||
</StyledInputRoot>
|
||||
|
||||