update pricing styles

This commit is contained in:
AykutSarac 2022-12-30 16:49:41 +03:00
parent 321a13ab37
commit 319abe039b
6 changed files with 196 additions and 105 deletions

View File

@ -53,10 +53,15 @@ const StyledBottomBarItem = styled.button`
font-weight: 400;
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
&:hover {
&:hover:not(&:disabled) {
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
color: ${({ theme }) => theme.INTERACTIVE_HOVER};
}
&:disabled {
opacity: 0.4;
cursor: progress;
}
`;
const StyledImg = styled.img<{ light: boolean }>`
@ -74,6 +79,7 @@ export const BottomBar = () => {
const setVisible = useModal(state => state.setVisible);
const setHasChanges = useJson(state => state.setHasChanges);
const [isPrivate, setIsPrivate] = React.useState(false);
const [isUpdating, setIsUpdating] = React.useState(false);
React.useEffect(() => {
setIsPrivate(data?.private ?? false);
@ -84,6 +90,7 @@ export const BottomBar = () => {
if (hasChanges) {
try {
setIsUpdating(true);
toast.loading("Saving JSON...", { id: "jsonSave" });
const res = await saveJson({ id: query.json as string, data: getJson() });
@ -98,6 +105,8 @@ export const BottomBar = () => {
}
toast.error("Failed to save JSON!", { id: "jsonSave" });
} finally {
setIsUpdating(false);
}
}
}, [getJson, hasChanges, query.json, replace, setHasChanges, setVisible, user]);
@ -107,10 +116,24 @@ export const BottomBar = () => {
else setVisible("login")(true);
};
const setPrivate = () => {
if (!query.json) return handleSaveJson();
setIsPrivate(!isPrivate);
updateJson(query.json as string, { private: !isPrivate });
const setPrivate = async () => {
try {
if (!query.json) return handleSaveJson();
if (!isPrivate && user?.type === 0) {
return window.open("https://jsoncrack.com/pricing", "_blank");
}
setIsUpdating(true);
const res = await updateJson(query.json as string, { private: !isPrivate });
if (!res.errors?.items.length) {
setIsPrivate(res.data.private);
toast.success(`Document set to ${isPrivate ? "public" : "private"}.`);
} else throw res.errors;
} catch (error) {
toast.error("An error occured while updating document!");
} finally {
setIsUpdating(false);
}
};
return (
@ -120,14 +143,14 @@ export const BottomBar = () => {
<VscAccount />
{user ? user.name : "Login"}
</StyledBottomBarItem>
<StyledBottomBarItem onClick={handleSaveJson}>
<StyledBottomBarItem onClick={handleSaveJson} disabled={isUpdating}>
{hasChanges ? <AiOutlineCloudUpload /> : <AiOutlineCloudSync />}
{hasChanges ? "Unsaved Changes" : "Saved"}
</StyledBottomBarItem>
{data && (
<>
{typeof data.private !== "undefined" && (
<StyledBottomBarItem onClick={setPrivate}>
<StyledBottomBarItem onClick={setPrivate} disabled={isUpdating}>
{isPrivate ? <AiOutlineLock /> : <AiOutlineUnlock />}
{isPrivate ? "Private" : "Public"}
</StyledBottomBarItem>

View File

@ -18,6 +18,7 @@ import { Sponsors } from "src/components/Sponsors";
import { SupportButton } from "src/components/SupportButton";
import { baseURL } from "src/constants/data";
import * as Styles from "./styles";
import { PricingCards } from "../PricingCards";
const Navbar = () => (
<Styles.StyledNavbar>
@ -282,6 +283,7 @@ const Home: React.FC = () => {
<FeaturesSection />
<GitHubSection />
<EmbedSection />
<PricingCards />
<SupportSection />
<SponsorSection />
<SupportButton />

View File

@ -80,7 +80,7 @@ const AccountView: React.FC<Pick<ModalProps, "setVisible">> = ({ setVisible }) =
<StyledContainer>
ACCOUNT STATUS
<div>
{isPremium ? "PREMIUM " : "Normal"}
{isPremium ? "PREMIUM " : "Free"}
{isPremium && <MdVerified />}
</div>
</StyledContainer>
@ -93,7 +93,11 @@ const AccountView: React.FC<Pick<ModalProps, "setVisible">> = ({ setVisible }) =
<div>{user?.signUpAt && new Date(user.signUpAt).toDateString()}</div>
</StyledContainer>
{isPremium ? (
<Button status="DANGER" block>
<Button
status="DANGER"
block
onClick={() => window.open("https://patreon.com/jsoncrack", "_blank")}
>
<IoRocketSharp />
Cancel Subscription
</Button>

View File

@ -4,7 +4,13 @@ import { useQuery } from "@tanstack/react-query";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import toast from "react-hot-toast";
import { AiOutlineEdit, AiOutlineLock, AiOutlinePlus, AiOutlineUnlock } from "react-icons/ai";
import {
AiOutlineEdit,
AiOutlineInfoCircle,
AiOutlineLock,
AiOutlinePlus,
AiOutlineUnlock,
} from "react-icons/ai";
import { FaTrash } from "react-icons/fa";
import { IoRocketSharp } from "react-icons/io5";
import { Button } from "src/components/Button";
@ -94,6 +100,16 @@ const StyledNameInput = styled.input`
font-weight: 600;
`;
const StyledInfoText = styled.span`
font-size: 10px;
color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
svg {
vertical-align: text-top;
margin-right: 4px;
}
`;
const GraphCard: React.FC<{ data: Json; refetch: () => void; active: boolean }> = ({
data,
refetch,
@ -241,7 +257,13 @@ export const CloudModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
)}
</StyledModalContent>
</Modal.Content>
<Modal.Controls setVisible={setVisible}></Modal.Controls>
<Modal.Controls setVisible={setVisible}>
<StyledInfoText>
<AiOutlineInfoCircle />
Cloud Save feature is for ease-of-access only and recommended to not store sensitive data.
</StyledInfoText>
</Modal.Controls>
</StyledModal>
);
};

View File

@ -0,0 +1,129 @@
import React from "react";
import { Button } from "src/components/Button";
import styled from "styled-components";
const StyledSectionBody = styled.div`
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
gap: 50px;
align-items: center;
justify-content: space-between;
background: rgba(181, 116, 214, 0.23);
width: 80%;
margin: 5% auto 0;
border-radius: 6px;
padding: 50px;
@media only screen and (max-width: 768px) {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
padding: 20px;
}
`;
const StyledPricingCard = styled.div<{ premium?: boolean }>`
padding: 6px;
padding-bottom: 0;
width: 100%;
height: 100%;
${({ premium }) =>
premium
? `
background: rgba(255, 5, 214, 0.19);
border-radius: 4px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 5, 214, 0.74);`
: `background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.3);`};
`;
const StyledPricingCardTitle = styled.h2`
text-align: center;
font-weight: 800;
font-size: 24px;
`;
const StyledPricingCardPrice = styled.h3`
text-align: center;
font-weight: 600;
font-size: 24px;
color: ${({ theme }) => theme.SILVER};
`;
const StyledPricingCardDetails = styled.ul`
color: ${({ theme }) => theme.TEXT_NORMAL};
line-height: 2.3;
padding: 20px;
`;
const StyledPricingCardDetailsItem = styled.li`
font-weight: 500;
@media only screen and (max-width: 768px) {
font-size: 14px;
}
`;
const StyledButton = styled(Button)`
border: 1px solid white;
`;
const StyledPricingSection = styled.section`
margin: 0 auto;
h1 {
text-align: center;
padding-bottom: 25px;
}
`;
export const PricingCards = () => {
return (
<StyledPricingSection>
<h1>Unlock Full Potential of JSON Crack</h1>
<StyledSectionBody>
<StyledPricingCard>
<StyledPricingCardTitle>Free</StyledPricingCardTitle>
<StyledPricingCardDetails>
<StyledPricingCardDetailsItem>Store up to 15 files</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Create short-links for saved JSON files
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>Embed saved JSON instantly</StyledPricingCardDetailsItem>
</StyledPricingCardDetails>
</StyledPricingCard>
<StyledPricingCard premium>
<StyledPricingCardTitle>Premium</StyledPricingCardTitle>
<StyledPricingCardPrice>$5/mo</StyledPricingCardPrice>
<StyledPricingCardDetails>
<StyledPricingCardDetailsItem>
Create and share up to 200 files
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>Store private JSON</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Get access to JSON Crack API to generate JSON remotely
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>Everything in previous tier</StyledPricingCardDetailsItem>
</StyledPricingCardDetails>
<StyledButton
href="https://www.patreon.com/jsoncrack"
target="_blank"
status="SUCCESS"
block
link
>
GET IT NOW!
</StyledButton>
</StyledPricingCard>
</StyledSectionBody>
</StyledPricingSection>
);
};

View File

@ -1,6 +1,7 @@
import React from "react";
import { Button } from "src/components/Button";
import { Footer } from "src/components/Footer";
import { PricingCards } from "src/containers/PricingCards";
import styled from "styled-components";
const StyledPageWrapper = styled.div`
@ -13,108 +14,18 @@ const StyledHeroSection = styled.section`
flex-direction: column;
align-items: center;
`;
const StyledPricingSection = styled.section`
display: flex;
justify-content: space-evenly;
background: rgba(181, 116, 214, 0.23);
width: 60%;
margin: 5% auto 0;
border-radius: 6px;
padding: 40px 20px;
`;
const StyledPricingCard = styled.div<{ premium?: boolean }>`
padding: 6px;
width: 40%;
${({ premium }) =>
premium
? `
background: rgba(255, 5, 214, 0.19);
border-radius: 4px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 5, 214, 0.74);`
: `background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.3);`};
`;
const StyledPricingCardTitle = styled.h2`
text-align: center;
font-weight: 800;
font-size: 24px;
`;
const StyledPricingCardPrice = styled.h3`
text-align: center;
font-weight: 600;
font-size: 24px;
color: ${({ theme }) => theme.SILVER};
`;
const StyledPricingCardDetails = styled.ul`
color: ${({ theme }) => theme.TEXT_NORMAL};
line-height: 2.3;
`;
const StyledPricingCardDetailsItem = styled.li`
font-weight: 500;
`;
const StyledButton = styled(Button)`
border: 1px solid white;
`;
const Pricing = () => {
return (
<>
<StyledPageWrapper>
<Button href="/" link>
&lt; Go Back
</Button>
<StyledHeroSection>
<img src="assets/icon.png" alt="json crack" width="400" />
<h1>Premium</h1>
</StyledHeroSection>
<StyledPricingSection>
<StyledPricingCard>
<StyledPricingCardTitle>Free</StyledPricingCardTitle>
<StyledPricingCardDetails>
<StyledPricingCardDetailsItem>Store up to 20 files</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Create short-links for saved JSON files
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Embed saved JSON instantly
</StyledPricingCardDetailsItem>
</StyledPricingCardDetails>
</StyledPricingCard>
<StyledPricingCard premium>
<StyledPricingCardTitle>Premium</StyledPricingCardTitle>
<StyledPricingCardPrice>$5/mo</StyledPricingCardPrice>
<StyledPricingCardDetails>
<StyledPricingCardDetailsItem>
Create and share up to 200 files
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>Store private JSON</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Premium role at Discord server
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Get access to JSON Crack API to generate JSON remotely
</StyledPricingCardDetailsItem>
<StyledPricingCardDetailsItem>
Everything in previous tier
</StyledPricingCardDetailsItem>
</StyledPricingCardDetails>
<StyledButton href="https://www.patreon.com/jsoncrack" status="SUCCESS" block link>
GET IT NOW!
</StyledButton>
</StyledPricingCard>
</StyledPricingSection>
<PricingCards />
</StyledPageWrapper>
<Footer />
</>