update payment flow

This commit is contained in:
AykutSarac 2023-05-23 15:35:03 +03:00
parent f820d59542
commit 21150a21c4
No known key found for this signature in database
14 changed files with 37 additions and 45 deletions

View File

@ -1,3 +1,4 @@
NEXT_PUBLIC_BASE_URL=http://localhost:3000
NEXT_PUBLIC_ALTOGIC_ENV_URL=https://jsoncrack.c5-na.altogic.com
NEXT_PUBLIC_ALTOGIC_CLIENT_KEY=f1e92022789f4ccf91273a345ab2bdf8
NEXT_PUBLIC_PAYMENT_URL=https://herowand.lemonsqueezy.com/checkout/buy/ce30521f-c7cc-44f3-9435-995d3260ba22

View File

@ -1,3 +1,4 @@
NEXT_PUBLIC_BASE_URL=https://jsoncrack.com
NEXT_PUBLIC_ALTOGIC_ENV_URL=https://jsoncrack.c5-na.altogic.com
NEXT_PUBLIC_ALTOGIC_CLIENT_KEY=f1e92022789f4ccf91273a345ab2bdf8
NEXT_PUBLIC_PAYMENT_URL=https://herowand.lemonsqueezy.com/checkout/buy/ce30521f-c7cc-44f3-9435-995d3260ba22

View File

@ -3,7 +3,7 @@ import useUser from "src/store/useUser";
export const CarbonAds = () => {
const ref = React.useRef<HTMLDivElement>(null!);
const premium = useUser(state => state.isPremium());
const premium = useUser(state => state.premium);
React.useEffect(() => {
if (!premium) {

View File

@ -2,6 +2,7 @@ import React from "react";
import styled from "styled-components";
import { Badge, Button, Image, List, ThemeIcon, Title } from "@mantine/core";
import { BsCheck } from "react-icons/bs";
import { paymentURL } from "src/constants/data";
const StyledPremiumView = styled.div`
position: relative;
@ -185,7 +186,7 @@ export const PremiumView = () => (
component="a"
variant="gradient"
gradient={{ from: "blue", to: "teal" }}
href="https://www.patreon.com/join/herowand/checkout?rid=8549056"
href={paymentURL}
target="_blank"
>
UPGRADE TO PREMIUM $5.00

View File

@ -59,7 +59,7 @@ const StyledEditorWrapper = styled.div<{ widget: boolean }>`
export const Graph = ({ isWidget = false }: GraphProps) => {
const { validateHiddenNodes } = useToggleHide();
const isPremium = useUser(state => state.isPremium());
const isPremium = useUser(state => state.premium);
const setLoading = useGraph(state => state.setLoading);
const setZoomPanPinch = useGraph(state => state.setZoomPanPinch);
const centerView = useGraph(state => state.centerView);

View File

@ -1,4 +1,5 @@
export const baseURL = process.env.NEXT_PUBLIC_BASE_URL;
export const baseURL = process.env.NEXT_PUBLIC_BASE_URL as string;
export const paymentURL = process.env.NEXT_PUBLIC_PAYMENT_URL as string;
// Example taken from https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json
const sampleJson = Object.freeze({

View File

@ -84,7 +84,7 @@ export const BottomBar = () => {
const { query } = useRouter();
const data = useFile(state => state.fileData);
const user = useUser(state => state.user);
const premium = useUser(state => state.isPremium());
const premium = useUser(state => state.premium);
const lightmode = useStored(state => state.lightmode);
const hasChanges = useFile(state => state.hasChanges);
const hasErrors = useFile(state => state.hasError);

View File

@ -103,7 +103,7 @@ export const Tools: React.FC<{ isWidget?: boolean }> = ({ isWidget = false }) =>
const expandGraph = useGraph(state => state.expandGraph);
const collapseGraph = useGraph(state => state.collapseGraph);
const lightmode = useStored(state => state.lightmode);
const premium = useUser(state => state.isPremium());
const premium = useUser(state => state.premium);
const CoreKey = navigator.userAgent.indexOf("Mac OS X") ? "⌘" : "CTRL";

View File

@ -2,6 +2,7 @@ import React from "react";
import styled from "styled-components";
import { Modal, Group, Button, Badge, Avatar, Grid, Divider, ModalProps } from "@mantine/core";
import { IoRocketSharp } from "react-icons/io5";
import { paymentURL } from "src/constants/data";
import useModal from "src/store/useModal";
import useUser from "src/store/useUser";
@ -45,7 +46,7 @@ const StyledContainer = styled.div`
export const AccountModal: React.FC<ModalProps> = ({ opened, onClose }) => {
const setVisible = useModal(state => state.setVisible);
const user = useUser(state => state.user);
const isPremium = useUser(state => state.isPremium());
const isPremium = useUser(state => state.premium);
const logout = useUser(state => state.logout);
return (
@ -93,11 +94,7 @@ export const AccountModal: React.FC<ModalProps> = ({ opened, onClose }) => {
<Divider py="xs" />
<Group position="right">
{isPremium ? (
<Button
variant="light"
color="red"
onClick={() => window.open("https://patreon.com/herowand", "_blank")}
>
<Button variant="light" color="red" onClick={() => window.open(paymentURL, "_blank")}>
Cancel Subscription
</Button>
) : (

View File

@ -165,7 +165,7 @@ const GraphCard: React.FC<{ data: File; refetch: () => void; active: boolean }>
const CreateCard: React.FC<{ reachedLimit: boolean }> = ({ reachedLimit }) => {
const { replace } = useRouter();
const isPremium = useUser(state => state.isPremium());
const isPremium = useUser(state => state.premium);
const getContents = useFile(state => state.getContents);
const setHasChanges = useFile(state => state.setHasChanges);
const setVisible = useModal(state => state.setVisible);

View File

@ -47,7 +47,7 @@ const CodeBlock: React.FC<{ children: any; [key: string]: any }> = ({
};
export const NodeModal: React.FC<ModalProps> = ({ opened, onClose }) => {
const isPremium = useUser(state => state.isPremium());
const isPremium = useUser(state => state.premium);
const editContents = useFile(state => state.editContents);
const setVisible = useModal(state => state.setVisible);
const lightmode = useStored(state => (state.lightmode ? "light" : "vs-dark"));

View File

@ -13,6 +13,7 @@ import {
Badge,
} from "@mantine/core";
import { BsCheck } from "react-icons/bs";
import { paymentURL } from "src/constants/data";
export const PremiumModal: React.FC<ModalProps> = ({ opened, onClose }) => {
return (
@ -52,7 +53,7 @@ export const PremiumModal: React.FC<ModalProps> = ({ opened, onClose }) => {
</Title>
<Button
component="a"
href="https://www.patreon.com/join/herowand/checkout?rid=8549056"
href={paymentURL}
variant="filled"
color="teal"
size="md"

View File

@ -13,6 +13,7 @@ import {
} from "@mantine/core";
import { CgChevronDown } from "react-icons/cg";
import { VscStarEmpty } from "react-icons/vsc";
import { paymentURL } from "src/constants/data";
import { JSONCrackLogo } from "../JsonCrackLogo";
const links: HeaderActionProps[] = [
@ -36,12 +37,12 @@ const links: HeaderActionProps[] = [
{ link: "/oss", label: "Open Source" },
{ link: "https://github.com/sponsors/AykutSarac", label: "Sponsor" },
{
link: "https://www.patreon.com/herowand",
link: paymentURL,
label: "Become Backer",
},
],
},
{ link: "https://www.patreon.com/join/herowand", label: "Plus" },
{ link: paymentURL, label: "Plus" },
{ link: "/docs", label: "Docs" },
];

View File

@ -6,20 +6,11 @@ import useModal from "./useModal";
const isDevelopment = process.env.NODE_ENV === "development";
interface CustomUser extends User {
premium: {
status: boolean;
end_date: string;
};
type: 0 | 1;
}
interface UserActions {
login: (response: AltogicAuth) => void;
logout: () => void;
setUser: (key: keyof typeof initialStates, value: any) => void;
checkSession: () => void;
isPremium: () => boolean;
}
const devUser = {
@ -32,28 +23,23 @@ const devUser = {
signUpAt: "2022-12-04T11:07:32.000Z",
lastLoginAt: "2023-05-13T09:56:02.915Z",
updatedAt: "2023-05-06T16:19:47.486Z",
type: 1,
} as CustomUser;
} as User;
interface UserStates {
user: CustomUser | null;
user: User | null;
isAuthenticated: boolean;
premium: boolean;
}
const initialStates: UserStates = {
isAuthenticated: false,
user: null,
isAuthenticated: false,
premium: false,
};
const useUser = create<UserStates & UserActions>()((set, get) => ({
const useUser = create<UserStates & UserActions>()(set => ({
...initialStates,
setUser: (key, value) => set({ [key]: value }),
isPremium: () => {
const user = get().user;
if (user) return user.type > 0;
return false;
},
logout: async () => {
const session = altogic.auth.getSession();
if (!session) return;
@ -66,14 +52,15 @@ const useUser = create<UserStates & UserActions>()((set, get) => ({
toast.success("Logged out.");
useModal.setState({ account: false });
},
login: user => set({ user: user as unknown as CustomUser, isAuthenticated: true }),
login: user => set({ user: user as unknown as User, isAuthenticated: true }),
checkSession: async () => {
if (isDevelopment) {
return set({ user: devUser as User, isAuthenticated: true, premium: true });
}
const currentSession = altogic.auth.getSession();
if (currentSession) {
if (isDevelopment) {
return set({ user: devUser as CustomUser, isAuthenticated: true });
}
const { user, errors } = await altogic.auth.getUserFromDB();
if (errors?.items || !user) {
altogic.auth.clearLocalData();
@ -82,8 +69,9 @@ const useUser = create<UserStates & UserActions>()((set, get) => ({
altogic.auth.setUser(user);
altogic.auth.setSession(currentSession);
const { data: premiumData } = await altogic.endpoint.get("/isPremium");
set({ user: user as CustomUser, isAuthenticated: true });
set({ user: user as User, isAuthenticated: true, premium: premiumData.premium });
} else if (new URLSearchParams(window.location.search).get("access_token")) {
const { errors, user } = await altogic.auth.getAuthGrant();
if (errors?.items) {
@ -91,7 +79,8 @@ const useUser = create<UserStates & UserActions>()((set, get) => ({
return;
}
set({ user: user as CustomUser, isAuthenticated: true });
const { data: premiumData } = await altogic.endpoint.get("/isPremium");
set({ user: user as User, isAuthenticated: true, premium: premiumData.data.premium });
}
},
}));