Skip to content

Commit

Permalink
refactor: add routes to demo apps
Browse files Browse the repository at this point in the history
  • Loading branch information
abelflopes committed Jun 11, 2024
1 parent 03d5f65 commit c6347fc
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 48 deletions.
4 changes: 3 additions & 1 deletion packages/apps/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"main": "src/index.tsx",
"dependencies": {
"react": "^18.2.0",
"react-ck": "*"
"react-ck": "*",
"react-router": "^6.23.1",
"react-router-dom": "^6.23.1"
},
"devDependencies": {
"@react-ck/typescript-config": "^1.0.0",
Expand Down
13 changes: 13 additions & 0 deletions packages/apps/common/src/context/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createContext, useContext } from "react";

export interface AppContextProps {
title: string;
}

export const AppContext = createContext<AppContextProps>({
title: "-",
});

export const AppContextProvider = AppContext.Provider;

export const useAppContext = (): AppContextProps => useContext(AppContext);
55 changes: 8 additions & 47 deletions packages/apps/common/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,18 @@
import React from "react";
import { Button, Container, Manager, Text, DataTable, Modal } from "react-ck";
import { Manager } from "react-ck";
import { DefaultRouter } from "./routes/Default";
import { type AppContextProps, AppContextProvider } from "./context/app";

const el = document.querySelector("#root");

if (!el) throw new Error("Missing root element");

export interface CommonAppProps {
title: string;
}
export type CommonAppProps = AppContextProps;

export const CommonApp = ({ title }: Readonly<CommonAppProps>): React.ReactElement => (
export const CommonApp = (props: Readonly<CommonAppProps>): React.ReactElement => (
<Manager>
<Container spacingY>
<Text variation="h1">{title}</Text>
<Text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam voluptate a assumenda nulla
minus corporis nisi commodi dolores, minima facilis quis, maxime perspiciatis non facere
quod aperiam placeat repudiandae ex id quae. Quisquam repellat cum incidunt atque aut
dolores modi laborum dolorem sapiente, esse dignissimos pariatur optio quibusdam vitae quas
fugiat officia harum. Sint cumque voluptatem nemo aperiam reprehenderit consequuntur
molestias, labore corporis, magnam fugit facilis laudantium corrupti similique ad quidem. A
facilis accusantium sequi ab saepe fuga qui architecto error debitis, tempore suscipit quo
quae nesciunt voluptas ipsam vel odit minima, nemo modi dolorem aut. Blanditiis rerum modi
magnam.
</Text>
<Button>Ok</Button>

<Text variation="h2">Multiples</Text>

<DataTable
autoHeaders
sortable
scrollable
skin="bordered"
data={Object.keys(Array.from(Array(10))).map((key) => ({
"": (
<Text skin="bold" as="span">
N{key}
</Text>
),
...Object.fromEntries(
Object.keys(Array.from(Array(100))).map((k) => {
const n = Number(k) * Number(key);
return [`N${k}`, n];
}),
),
}))}
/>
</Container>

<Modal>
<Modal.Header heading="Header" />
Modal content
</Modal>
<AppContextProvider value={props}>
<DefaultRouter />
</AppContextProvider>
</Manager>
);
9 changes: 9 additions & 0 deletions packages/apps/common/src/pages/Error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from "react";
import { Container, Text } from "react-ck";

export const ErrorPage = (): React.ReactElement => (
<Container spacingY>
<Text variation="h1">Oops, something happened</Text>
<Text>We are currently experiencing some issues. Please try again later.</Text>
</Container>
);
79 changes: 79 additions & 0 deletions packages/apps/common/src/pages/Home.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useState } from "react";
import { Button, Container, Text, DataTable, Modal } from "react-ck";
import { useAppContext } from "../context/app";

export const HomePage = (): React.ReactElement => {
const { title } = useAppContext();
const [modalOpen, setModalOpen] = useState(false);

return (
<>
<Container spacingY>
<Text variation="h1">{title} - Home</Text>
<Text>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsam voluptate a assumenda nulla
minus corporis nisi commodi dolores, minima facilis quis, maxime perspiciatis non facere
quod aperiam placeat repudiandae ex id quae. Quisquam repellat cum incidunt atque aut
dolores modi laborum dolorem sapiente, esse dignissimos pariatur optio quibusdam vitae
quas fugiat officia harum. Sint cumque voluptatem nemo aperiam reprehenderit consequuntur
molestias, labore corporis, magnam fugit facilis laudantium corrupti similique ad quidem.
A facilis accusantium sequi ab saepe fuga qui architecto error debitis, tempore suscipit
quo quae nesciunt voluptas ipsam vel odit minima, nemo modi dolorem aut. Blanditiis rerum
modi magnam.
</Text>
<Button
onClick={() => {
console.log("click");
setModalOpen(true);
}}>
Open {String(modalOpen)}
</Button>

<Text variation="h2">Multiples</Text>

<DataTable
autoHeaders
sortable
scrollable
skin="bordered"
data={Object.keys(Array.from(Array(10))).map((key) => ({
"": (
<Text skin="bold" as="span">
N{key}
</Text>
),
...Object.fromEntries(
Object.keys(Array.from(Array(100))).map((k) => {
const n = Number(k) * Number(key);
return [`N${k}`, n];
}),
),
}))}
/>
</Container>
<Button
onClick={() => {
setModalOpen(false);
}}>
Close
</Button>

<Modal
open={modalOpen}
onDismiss={() => {
setModalOpen(false);
}}>
<Modal.Header heading="Header" />
Lorem ipsum dolor sit amet consectetur adipisicing elit. Enim, voluptate!
<Modal.Footer>
<Button
onClick={() => {
setModalOpen(false);
}}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
};
19 changes: 19 additions & 0 deletions packages/apps/common/src/routes/Default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { type RouteIndex, routesList } from "./routes-list";
import { viewsMap } from "./view-mapping";

const router = createBrowserRouter(
Object.keys(routesList).map((i) => ({
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- to match expected types
path: routesList[i as RouteIndex] as unknown as string,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- to match expected types
Component: viewsMap[i as RouteIndex],
})),
);

/**
* Main / global router component
*/

export const DefaultRouter = (): React.ReactElement => <RouterProvider router={router} />;
50 changes: 50 additions & 0 deletions packages/apps/common/src/routes/Redirect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect, useMemo, type default as React } from "react";
import { generatePath, useLocation, useParams, useSearchParams } from "react-router-dom";
import { useNavigate, type PathParam } from "react-router";
import { type RouteIndex, routesList } from "./routes-list";

/**
* Route redirection component
* This component tries to preserve params by merging search and pat params
* and injecting them on the target path, also allows overriding with "params prop"
* It also preserves search params
*/

interface RedirectViewProps<T extends RouteIndex> {
to: T;
params?: Partial<PathParam<(typeof routesList)[T]>>;
}

export const RedirectView = <T extends RouteIndex>({
to,
params: additionalParams,
}: Readonly<RedirectViewProps<T>>): React.ReactNode => {
const navigate = useNavigate();
const pathParams = useParams();
const location = useLocation();
const [searchParams] = useSearchParams();
const path = String(routesList[to]);

const params = useMemo(
() => ({
...searchParams,
...pathParams,
...additionalParams,
}),
[additionalParams, pathParams, searchParams],
);

useEffect(() => {
navigate(
{
pathname: generatePath<string>(path, params),
search: location.search,
},
{
replace: true,
},
);
}, [location.search, navigate, params, path]);

return null;
};
14 changes: 14 additions & 0 deletions packages/apps/common/src/routes/routes-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* NOTE: sorting affects router behavior
* NOTE: do not use numeric keys to prevent JS auto sorting
*/

export const routesList = {
root: "/",
home: "/home",
error: "*",
} as const;

export type RouteIndex = keyof typeof routesList;

export type AppRoute = (typeof routesList)[RouteIndex];
15 changes: 15 additions & 0 deletions packages/apps/common/src/routes/view-mapping.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";
import { type RouteProps } from "react-router-dom";
import { type RouteIndex } from "./routes-list";
import { RedirectView } from "./Redirect";

import { ErrorPage } from "../pages/Error";
import { HomePage } from "../pages/Home";

type ViewsMap = { [key in RouteIndex]: NonNullable<RouteProps["Component"]> };

export const viewsMap: ViewsMap = {
root: () => <RedirectView to="home" />,
home: () => <HomePage />,
error: () => <ErrorPage />,
};

0 comments on commit c6347fc

Please sign in to comment.