Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 Basic demo setup for state management #741

Merged
merged 8 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
"git-info": "rm -rf src/generated/ && mkdir src/generated/ && echo export default \"{\\\"commitHash\\\": \\\"$(git rev-parse --short HEAD)\\\", \\\"version\\\": \\\"$(git describe --tags --always)\\\"};\" > src/generated/gitInfo.ts"
},
"dependencies": {
"@stellar/design-system": "^1.1.2",
"@stellar/design-system": "^2.0.0-beta.1",
"immer": "^10.0.3",
"next": "14.0.4",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"zustand": "^4.5.0",
"zustand-querystring": "^0.0.19"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
14 changes: 14 additions & 0 deletions src/app/(sidebar)/account/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use client";

import { useStore } from "@/store/useStore";

export default function CreateAccount() {
const { network } = useStore();

return (
<div>
Create Account
<div>{`Current network: ${network?.id}`}</div>
</div>
);
}
74 changes: 74 additions & 0 deletions src/app/(sidebar)/account/fund/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use client";

import { useStore } from "@/store/useStore";
import { Input, Button, Select } from "@stellar/design-system";
import { useState } from "react";

export default function FundAccount() {
const {
account: { value, update, updateNested, reset },
} = useStore();

const [testValue, setTestValue] = useState(value);

const handleUpdateNested = (event: any) => {
const val = event.target.value;
let submitValue = {
nestedValue1: "AAA",
nestedValue2: 111,
};

if (val === "Two") {
submitValue = {
nestedValue1: "BBB",
nestedValue2: 222,
};
}

updateNested(submitValue);
};

return (
<div>
Fund Account
<div>
<div>{`Test value: ${value}`}</div>

<p>Store value is updated on blur</p>

<Input
id="test-1"
fieldSize="sm"
value={testValue}
onChange={(event) => setTestValue(event.target.value)}
onBlur={(event) => update(event.target.value)}
label="Value"
/>

<p>Testing nested object update</p>

<Select
id="select-1"
fieldSize="sm"
onChange={handleUpdateNested}
label="Nested value"
>
<option></option>
<option value="One">One</option>
<option value="Two">Two</option>
</Select>

<Button
size="sm"
variant="primary"
onClick={() => {
reset();
setTestValue("");
}}
>
Reset
</Button>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions src/app/(sidebar)/account/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use client";

export default function Account() {
return <div>Account content</div>;
}
29 changes: 29 additions & 0 deletions src/app/(sidebar)/account/template.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use client";

import { LayoutSidebarContent } from "@/components/layout/LayoutSidebarContent";
import { Routes } from "@/constants/routes";

export default function AccountTemplate({
children,
}: {
children: React.ReactNode;
}) {
return (
<LayoutSidebarContent
sidebar={{
navItems: [
{
route: Routes.CREATE_ACCOUNT,
label: "Create Account",
},
{
route: Routes.FUND_ACCOUNT,
label: "Fund Account",
},
],
}}
>
{children}
</LayoutSidebarContent>
);
}
5 changes: 5 additions & 0 deletions src/app/(sidebar)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LayoutWithSidebar } from "@/components/layout/LayoutWithSidebar";

export default function Layout({ children }: { children: React.ReactNode }) {
return <LayoutWithSidebar>{children}</LayoutWithSidebar>;
}
1 change: 0 additions & 1 deletion src/app/globals.scss

This file was deleted.

12 changes: 8 additions & 4 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Metadata } from "next";

import { MainLayout } from "./ui/MainLayout";
import { LayoutMain } from "@/components/layout/LayoutMain";
import { StoreProvider } from "@/store/StoreProvider";

import "@stellar/design-system/build/styles.min.css";
import "./globals.scss";
import "@/styles/globals.scss";

// TODO: update metadata
export const metadata: Metadata = {
title: "Laboratory - Stellar",
description: "",
Expand All @@ -18,8 +20,10 @@ export default function RootLayout({
return (
<html lang="en">
<body>
<div id="root">
<MainLayout>{children}</MainLayout>
<div id="root" className="LabLayout">
<StoreProvider>
<LayoutMain>{children}</LayoutMain>
</StoreProvider>
</div>
</body>
</html>
Expand Down
18 changes: 18 additions & 0 deletions src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"use client";

import Link from "next/link";

import { Routes } from "@/constants/routes";
import { LayoutContentContainer } from "@/components/layout/LayoutContentContainer";

// TODO: update 404
// TODO: keep searchParams
export default function NotFound() {
return (
<LayoutContentContainer>
<h2>Not Found</h2>
<p>Could not find requested resource</p>
<Link href={Routes.ROOT}>Return Home</Link>
</LayoutContentContainer>
);
}
10 changes: 7 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
"use client";

import { Layout } from "@stellar/design-system";
import { LayoutContentContainer } from "@/components/layout/LayoutContentContainer";

export default function Home() {
return <Layout.Inset>Page</Layout.Inset>;
export default function Introduction() {
return (
<LayoutContentContainer>
<div>Introduction</div>
</LayoutContentContainer>
);
}
18 changes: 0 additions & 18 deletions src/app/ui/MainLayout.tsx

This file was deleted.

69 changes: 69 additions & 0 deletions src/components/MainNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { usePathname } from "next/navigation";

import { Routes } from "@/constants/routes";
import { NextLink } from "@/components/NextLink";

type NavLink = {
href: Routes | string;
label: string;
};

const primaryNavLinks: NavLink[] = [
{
href: Routes.ROOT,
label: "Introduction",
},
{
href: Routes.CREATE_ACCOUNT,
label: "Account",
},
{
href: Routes.EXPLORE_ENDPOINTS,
label: "Explore Endpoints",
},
];

const secondaryNavLinks: NavLink[] = [
{
href: "https://developers.stellar.org/docs",
label: "View Documentation",
},
];

export const MainNav = () => {
const pathname = usePathname();

const isActiveRoute = (link: string) => {
if (link.startsWith("http")) {
return false;
}

return pathname.split("/")[1] === link.split("/")[1];
};

const NavItem = ({ link }: { link: NavLink }) => (
<NextLink
href={link.href}
className={`NavLink ${isActiveRoute(link.href) ? "NavLink--active" : ""}`}
>
{link.label}
</NextLink>
);

return (
<nav className="LabLayout__header__nav">
{/* Primary nav links */}
<div className="LabLayout__header__nav--primary">
{primaryNavLinks.map((l) => (
<NavItem key={l.href} link={l} />
))}
</div>
{/* Secondary nav links */}
<div className="LabLayout__header__nav--secondary">
{secondaryNavLinks.map((sl) => (
<NavItem key={sl.href} link={sl} />
))}
</div>
</nav>
);
};
52 changes: 52 additions & 0 deletions src/components/NetworkSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client";

// TODO: update Network selector. This is a demo for state/store.

import { useCallback, useEffect } from "react";
import { Select } from "@stellar/design-system";
import { useStore } from "@/store/useStore";

export const NetworkSelector = () => {
const { network, selectNetwork } = useStore();

const setNetwork = useCallback(() => {
if (!network?.id) {
// TODO: get from local storage
selectNetwork({
id: "testnet",
label: "testnet",
url: "",
passphrase: "",
});
}
}, [network?.id, selectNetwork]);

// Set default network on launch
useEffect(() => {
setNetwork();
}, [setNetwork]);

return (
<div>
{`Network: ${network?.id}`}
<Select
id="network"
fieldSize="sm"
onChange={(event) =>
selectNetwork({
id: event.target.value,
label: event.target.value,
url: `url-${event.target.value}`,
passphrase: `passphrase-${event.target.value}`,
})
}
value={network?.id || ""}
>
<option value=""></option>
<option value="testnet">testnet</option>
<option value="mainnet">mainnet</option>
<option value="futurenet">futurenet</option>
</Select>
</div>
);
};
17 changes: 17 additions & 0 deletions src/components/NextLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ComponentProps } from "react";
import Link from "next/link";

type LinkProps = ComponentProps<typeof Link>;

/** `NextLink` is extended `next/link`. */
export const NextLink = (props: LinkProps) => {
const externalLinkProps = (href: string) => {
const isExternalLink = href?.startsWith("http") || href?.startsWith("//");

return isExternalLink
? { rel: "noreferrer noopener", target: "_blank" }
: {};
};

return <Link {...props} {...externalLinkProps(props.href.toString())} />;
};
11 changes: 11 additions & 0 deletions src/components/SdsLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import NextLink from "next/link";
import { Props as LinkProps, Link } from "@stellar/design-system";

/** Use `SdsLink` instead of `Link` from Stellar Design System to support client-side routing. `SdsLink` uses `next/link` internally. */
export const SdsLink = (props: LinkProps) => {
return (
<Link {...props} customAnchor={<NextLink href={props.href || ""} />}>
{props.children}
</Link>
);
};
9 changes: 9 additions & 0 deletions src/components/layout/LayoutContentContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const LayoutContentContainer = ({
children,
}: {
children: React.ReactNode;
}) => (
<div className="LabLayout__container">
<div className="LabLayout__content">{children}</div>
</div>
);
Loading
Loading