Skip to content

Commit

Permalink
Character page + mint flow mobile UI (#109)
Browse files Browse the repository at this point in the history
## Description

Adjusts routes based on `useIsMobile()` hook, if mobile is detected all
paths except `onboarding, connectWallet, character, createCharacter`
will redirect to `<MobileNotAvailable />`. This pr includes UI
components for the `character` and `createCharacter` routes.

## Related Issues
#108

## Screenshots (if applicable)


https://github.com/Kryha/KREAd/assets/97608823/ad674348-7cf8-4a1c-b191-44ffba25cfe3

## Checklist

Make sure all items are checked before submitting the pull request.
Remove any items that are not applicable.

- [x] The PR title is clear and concise.
- [x] Are there changes in the /fronted folder? Make sure `cd frontend
&& yarn build` runs successfully.;

## Additional Comments

Currently having issues connecting the Keplr app to Emerynet, so this PR
is purely UI and routing changes
  • Loading branch information
carlos-kryha authored Dec 15, 2023
1 parent 09a7050 commit 064b281
Show file tree
Hide file tree
Showing 19 changed files with 134 additions and 215 deletions.
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"workbox-streams": "^6.5.3"
},
"scripts": {
"dev": "NODE_ENV=development vite",
"dev": "NODE_ENV=development vite --host",
"build": "tsc && vite build",
"preview": "vite preview",
"lint": "eslint src",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/atoms/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface ButtonProps {
borderColor?: string;
visible?: boolean;
disabled?: boolean;
mobileWidth?: string;
}

export const KeplerIconWrapper = styled.div``;
Expand Down Expand Up @@ -88,6 +89,7 @@ export const PrimaryButton = styled.button<ButtonProps>`
@media (max-width: ${breakpoints.mobile}) {
font-size: 12px;
max-width: ${(props): string => props.mobileWidth || "none"};
}
`;

Expand Down
51 changes: 8 additions & 43 deletions frontend/src/components/base-route-mobile/base-route-mobile.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import React, { FC, useMemo } from "react";

import { text } from "../../assets";
import React, { FC } from "react";
import { routes } from "../../navigation";
import { Footer } from "../footer";
import { NavigationSection, NavigationTab } from "../navigation-tab";
import { Box, ChildrenContainer, FooterContainer, RightBox, TopbarContainer } from "./styles";
import { ChildrenContainer, FooterContainer, TopbarContainer } from "./styles";
import { useCharacterBuilder } from "../../context/character-builder-context";
import { MAIN_MODE, Section } from "../../constants";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { SwitchSelector } from "../switch-selector";
import { KreadContainer } from "../../pages/shop/styles";
import { MAIN_MODE } from "../../constants";
import { useNavigate } from "react-router-dom";
import { KreadContainerMobile } from "../../pages/shop/styles";
import { KreadIcon } from "../logo/styles";
import { ButtonText, PrimaryButton } from "../atoms";
import { color } from "../../design";
import { useKadoWidget } from "../../context/filter-context";
import styled from "@emotion/styled";
import { BuyCryptoButton } from "../base-route/base-route";

interface BaseRouteProps {
sideNavigation: React.ReactNode;
Expand All @@ -25,46 +16,20 @@ interface BaseRouteProps {
isShop?: boolean;
}

export const BaseRouteMobile: FC<BaseRouteProps> = ({ children, sideNavigation, onboarding = false, isLanding = false, isShop = false }) => {
const isOnboarding = onboarding ? routes.onboarding : routes.character;
export const BaseRouteMobile: FC<BaseRouteProps> = ({ children, isLanding = false}) => {
const { interactionMode } = useCharacterBuilder();

const { pathname } = useLocation();
const { section } = useParams<{ section: Section }>();
const navigate = useNavigate();
const home = () => {
navigate(routes.character);
};

const pageSelector = useMemo(
() => (
<SwitchSelector
buttonOneText={text.character.items}
buttonTwoText={text.character.characters}
selectedSection={section || "items"}
path={pathname}
/>
),
[section, pathname],
);

return (
<>
{interactionMode === MAIN_MODE && (
<TopbarContainer isLanding={isLanding}>
<Box>
<NavigationSection route={isOnboarding}>
<NavigationTab title={text.navigation.character} route={isOnboarding} />
</NavigationSection>
</Box>
<KreadContainer onClick={home}>
<KreadContainerMobile onClick={home}>
<KreadIcon />
</KreadContainer>
<RightBox>
{isShop && <BuyCryptoButton />}
{!isLanding && <>{pageSelector}</>}
{sideNavigation}
</RightBox>
</KreadContainerMobile>
</TopbarContainer>
)}
<ChildrenContainer isLanding={isLanding}>{children}</ChildrenContainer>
Expand Down
11 changes: 5 additions & 6 deletions frontend/src/components/base-route-mobile/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,19 @@ export const NavBarDivider = styled.div`
`;

export const TopbarContainer = styled.header<AnimationProps>`
width: 100vw;
display: flex;
flex-direction: row;
justify-content: space-between;
justify-content: flex-start;
margin-top: 12px;
align-items: flex-end;
z-index: 100;
top: 0;
margin-left: ${margins.medium};
margin-right: ${margins.medium};
padding-top: ${margins.medium};
padding-bottom: ${margins.medium};
padding: ${margins.medium};
background: transparent;
@media screen and (max-width: ${breakpoints.tablet}) {
padding: ${margins.mini};
padding: ${margins.medium};
}
`;

Expand Down
12 changes: 11 additions & 1 deletion frontend/src/components/content-loader/content-loader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { FC } from "react";
import { AnimatedLoading } from "./animated-loading";
import { LoadingPageContainer, Spinner } from "./styles";
import { LoadingPageContainer, LoadingPageContainerMobile, Spinner } from "./styles";
import { useIsMobile } from "../../hooks";
import { breakpoints } from "../../design";

interface ContentLoaderProps {
loading: boolean;
Expand All @@ -12,6 +14,14 @@ interface LoadingPageProps {
}

export const LoadingPage: FC<LoadingPageProps> = ({ spinner = true }) => {
const isMobile = useIsMobile(breakpoints.tablet);
if(isMobile) {
return (
<>
<LoadingPageContainerMobile isSpinner={spinner}>{spinner ? <Spinner /> : <AnimatedLoading />}</LoadingPageContainerMobile>
</>
);
}
return (
<>
<LoadingPageContainer isSpinner={spinner}>{spinner ? <Spinner /> : <AnimatedLoading />}</LoadingPageContainer>
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/components/content-loader/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,33 @@ export const LoadingPageContainer = styled.div<SpinnerProps>`
`;
}};
`;

export const LoadingPageContainerMobile = styled.div<SpinnerProps>`
width: fit-content;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 30vw;
${({ isSpinner }): string => {
return isSpinner
? `
width: fit-content;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 46vh 46vw;
`
: `
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
`;
}};
`;

interface AnimationProps {
iteration?: number;
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

body {
font-family: 'aktiv-grotesk', -apple-system, BlinkMacSystemFont, sans-serif;
max-width: 100vw;
overflow-x: hidden;
}

4 changes: 3 additions & 1 deletion frontend/src/pages/content-mobile/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const Title = styled(FormText)``;

export const InfoContainer = styled.div`
padding-left: 20px;
padding-right: 20px;
padding-top: 4%;
${TitleText} {
margin-top: ${margins.mini};
Expand All @@ -34,7 +35,8 @@ export const GeneralInfo = styled.div`
export const KreadContainer = styled.div`
display: flex;
flex: 1;
justify-content: center;
justify-content: start;
padding-left: 30px;
margin-top: 30px;
${KreadIcon} {
width: 100px;
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/pages/create-character-mobile/confirmation.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FC } from "react";
import { text } from "../../assets";
import { ButtonText, ErrorView, MenuItemName, PrimaryButton, TitleText } from "../../components";
import { ButtonText, ErrorView, MenuItemName, TitleText } from "../../components";
import { color } from "../../design";
import { Character } from "../../interfaces";
import { getDatefromEpoch } from "../../util";
import { ArrowUp, ButtonContainer, ContentWrapper, InfoContainer, Tick, TickContainer } from "./styles";
import { ArrowUp, ButtonContainer, ContentWrapper, InfoContainer, PrimaryButtonMobile, Tick, TickContainer } from "./styles";
import { useUserStateDispatch } from "../../context/user";
import { useNavigate } from "react-router-dom";
import { routes } from "../../navigation";
Expand Down Expand Up @@ -42,10 +42,10 @@ export const Confirmation: FC<ConfirmationProps> = ({ character }) => {
<MenuItemName>{getDatefromEpoch(Date.now())}</MenuItemName>
</InfoContainer>
<ButtonContainer>
<PrimaryButton onClick={handleConfirm}>
<PrimaryButtonMobile onClick={handleConfirm} mobileWidth="100px">
<ButtonText customColor={color.white}>{text.mint.goToCharacter}</ButtonText>
<ArrowUp />
</PrimaryButton>
</PrimaryButtonMobile>
</ButtonContainer>
</ContentWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import React, { FC, useEffect, useMemo, useState } from "react";
import { ElephiaCitizen, text } from "../../assets";
import { text } from "../../assets";
import { ErrorView, FadeInOut, FormHeader, LoadingPage, NotificationDetail, Overlay } from "../../components";
import { PageContainer } from "../../components/page-container";
import { MINTING_COST, MINT_CHARACTER_FLOW_STEPS, WALLET_INTERACTION_STEP } from "../../constants";
import { useIsMobile, useViewport } from "../../hooks";
import { Character, CharacterCreation, MakeOfferCallback } from "../../interfaces";
import { routes } from "../../navigation";
import { useCreateCharacter } from "../../service";
import { Confirmation } from "./confirmation";
import { Information } from "./information";
import { Payment } from "./payment";
import { DefaultImage, FormCard } from "./styles";
import { breakpoints } from "../../design";
import { FormCard } from "./styles";
import { useUserState } from "../../context/user";
import { useWalletState } from "../../context/wallet";
import { NotificationWrapper } from "../../components/notification-detail/styles";

export const CreateCharacterMobile: FC = () => {
const createCharacter = useCreateCharacter();
const { width, height } = useViewport();
const [currentStep, setCurrentStep] = useState<number>(0);
const [mintedCharacter, setMintedCharacter] = useState<Character>();
const [error, setError] = useState<string>();
Expand All @@ -30,7 +27,6 @@ export const CreateCharacterMobile: FC = () => {
const isLoadingCharacters = !fetched;
const [isLoading, setIsLoading] = useState<boolean>(false);
const [isOfferAccepted, setIsOfferAccepted] = useState<boolean>(false);
const mobile = useIsMobile(breakpoints.desktop);
const { ist } = useWalletState();

const notEnoughIST = useMemo(() => {
Expand All @@ -47,6 +43,8 @@ export const CreateCharacterMobile: FC = () => {
setMintedCharacter(newCharacter.nft);
setIsLoading(false);
}
if(error) console.error(`Error in create-character-mobile: ${error}`);

}, [characters, characterData, notEnoughIST]);

const changeStep = async (step: number): Promise<void> => {
Expand Down Expand Up @@ -119,7 +117,6 @@ export const CreateCharacterMobile: FC = () => {
/>
</NotificationWrapper>
</FadeInOut>
{!mobile && <DefaultImage src={ElephiaCitizen} alt={text.character.defaultCharacter} height={height} width={width} />}
</PageContainer>
);
};
9 changes: 5 additions & 4 deletions frontend/src/pages/create-character-mobile/information.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CharacterCreation } from "../../interfaces";
import { FC, useEffect, useMemo } from "react";
import { FC, useMemo } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import {
ArrowUp,
Expand All @@ -10,10 +10,11 @@ import {
FormContainer,
FormFields,
InputWrapper,
PrimaryButtonMobile,
Tick,
Warning,
} from "./styles";
import { ButtonText, FormText, Input, Label, PrimaryButton } from "../../components";
import { ButtonText, FormText, Input, Label } from "../../components";
import { text } from "../../assets";
import { MAX_CHARACTER_LENGTH, MINTING_COST } from "../../constants";
import { ButtonInfo } from "../../components/button-info";
Expand Down Expand Up @@ -103,10 +104,10 @@ export const Information: FC<InformationProps> = ({ setData, disabled }) => {
<FormText>{text.mint.theCostsOfMinting}</FormText>
<ButtonWrapper>
<ButtonContainer>
<PrimaryButton type="submit" disabled={!isValid || disabled || notEnoughIST || nameTaken}>
<PrimaryButtonMobile mobileWidth="100px" type="submit" disabled={!isValid || disabled || notEnoughIST || nameTaken}>
<ButtonText customColor={color.white}>{text.mint.next}</ButtonText>
<ArrowUp />
</PrimaryButton>
</PrimaryButtonMobile>
</ButtonContainer>
</ButtonWrapper>
</FormContainer>
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/pages/create-character-mobile/payment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import {
NumberContainer,
PreviousButtonContainer,
PricingContainer,
PrimaryButtonMobile,
Step,
StepContainer,
StepText,
StepWrapper,
Tick,
} from "./styles";
import { Badge, ButtonText, FormText, LoadingPage, PriceInIst, PrimaryButton, SecondaryButton } from "../../components";
import { Badge, ButtonText, FormText, LoadingPage, PriceInIst, SecondaryButton } from "../../components";
import { text } from "../../assets";
import { CONFIRMATION_STEP, INFORMATION_STEP, MINTING_COST } from "../../constants";
import { color } from "../../design";
Expand All @@ -31,7 +32,6 @@ export const Payment: FC<PaymentProps> = ({ submit, sendOfferHandler, isOfferAcc
const [disable, setDisable] = useState(false);
const sendOfferToWallet = async () => {
setDisable(true);
console.info("SENDING OFFER TO WALLET");
await sendOfferHandler();
setSendOffer(true);
};
Expand All @@ -49,9 +49,9 @@ export const Payment: FC<PaymentProps> = ({ submit, sendOfferHandler, isOfferAcc
{!sendOffer && (
<>
<PriceInIst price={MINTING_COST} />
<PrimaryButton onClick={sendOfferToWallet} disabled={disable}>
<PrimaryButtonMobile mobileWidth="100px" onClick={sendOfferToWallet} disabled={disable}>
<ButtonText customColor={color.white}>{text.mint.sendOffer}</ButtonText>
</PrimaryButton>
</PrimaryButtonMobile>
</>
)}
</PricingContainer>
Expand Down Expand Up @@ -80,10 +80,10 @@ export const Payment: FC<PaymentProps> = ({ submit, sendOfferHandler, isOfferAcc
</PreviousButtonContainer>
)}
<ButtonContainer>
<PrimaryButton onClick={() => submit(CONFIRMATION_STEP)} disabled={!isOfferAccepted}>
<PrimaryButtonMobile mobileWidth="100px" onClick={() => submit(CONFIRMATION_STEP)} disabled={!isOfferAccepted}>
<ButtonText customColor={color.white}>{text.mint.confirm}</ButtonText>
{isLoading ? <LoadingPage /> : <ArrowUp />}
</PrimaryButton>
</PrimaryButtonMobile>
</ButtonContainer>
</ButtonWrapper>
</ContentWrapper>
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/pages/create-character-mobile/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const FormCard = styled.div`
margin: auto;
height: 100%;
border-radius: 0;
max-width: 100vw;
}
animation: ${fadeUp} 1.2s ease-out 0s forwards;
Expand Down Expand Up @@ -290,6 +291,7 @@ export const ButtonWrapper = styled.div`
flex-direction: row;
justify-content: space-between;
height: 100%;
max-width: 100vw;
align-items: flex-end;
align-content: flex-end;
`;
Expand All @@ -302,4 +304,8 @@ export const Step = styled.div`

export const RedButtonText = styled(ButtonText)`
color: red;
`
`;

export const PrimaryButtonMobile = styled(PrimaryButton)`
max-width: 100px;
`;
Loading

0 comments on commit 064b281

Please sign in to comment.