Skip to content

Commit e738830

Browse files
authored
flatten file structure (#120)
* Rename Home to home * Center the app layout * Add a space there * Move some pages around * Move some components around * Fix happy load more accident * Flatten the tos page * Make the green greener * Flatten the tree history * Don't use unnecessary FCs * Normalize props * Move those along as well * Flatten that file as well * Save that file
1 parent 107a1ca commit e738830

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+487
-459
lines changed

src/App.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import React, { Suspense } from "react";
33
import { BrowserRouter, Routes, Route } from "react-router-dom";
44

55
const AppLayout = React.lazy(() => import("./components/layout/AppLayout"));
6-
const Tos = React.lazy(() => import("./components/upload/Tos"));
7-
const New = React.lazy(() => import("./components/upload/Tos/New"));
6+
const Tos = React.lazy(() => import("./components/pages/tos"));
7+
const New = React.lazy(() => import("./components/pages/tos/New"));
88
const Result = React.lazy(() => import("./components/tree/Result"));
99
const NotFound = React.lazy(() => import("./components/NotFound"));
10-
const History = React.lazy(() => import("./components/pages/trees/History"));
10+
const History = React.lazy(() => import("./components/pages/history"));
1111
const LogIn = React.lazy(() => import("./components/pages/account/LogIn"));
1212
const SignUp = React.lazy(() => import("./components/pages/account/SignUp"));
1313
const VerifyEmail = React.lazy(
@@ -16,7 +16,7 @@ const VerifyEmail = React.lazy(
1616
const PasswordReset = React.lazy(
1717
() => import("./components/pages/account/PasswordReset"),
1818
);
19-
const Plans = React.lazy(() => import("./components/pricing/Plans"));
19+
const Plans = React.lazy(() => import("./components/pages/pricing"));
2020
const FilesProvider = React.lazy(
2121
() => import("./components/providers/FilesProvider"),
2222
);
@@ -29,7 +29,7 @@ const About = React.lazy(() => import("./components/pages/docs/About"));
2929
const PressRelease = React.lazy(
3030
() => import("./components/pages/docs/PressRelease"),
3131
);
32-
const Home = React.lazy(() => import("./components/pages/Home"));
32+
const Home = React.lazy(() => import("./components/pages/home"));
3333
const ProBuyflow = React.lazy(
3434
() => import("./components/pages/buyflow/ProBuyflow"),
3535
);

src/components/tree/Download/FloatingButtonMenuItems/hooks/useFloatingButton/index.ts renamed to src/components/common/FloatingButtonMenuItems/hooks/useFloatingButton/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { DownloadPropsType } from "../../../types";
1+
import { Analysis } from "../../../../../types/Analysis";
2+
import { TreeResult } from "../../../../../types/result";
23
import { downloadFile } from "./utils/downloadFile";
34
import { fileAsUri } from "./utils/fileAsUri";
45
import Papa from "papaparse";
@@ -7,7 +8,10 @@ import { useCallback, useState } from "react";
78
export const useFloatingButton = ({
89
treeSections,
910
analysis,
10-
}: DownloadPropsType) => {
11+
}: {
12+
treeSections: TreeResult;
13+
analysis?: Analysis;
14+
}) => {
1115
const [isDownloading, setIsDownloading] = useState<boolean>(false);
1216

1317
const downloadArticles = useCallback(() => {

src/components/tree/Download/FloatingButtonMenuItems/hooks/useFloatingButton/utils/downloadFile.ts renamed to src/components/common/FloatingButtonMenuItems/hooks/useFloatingButton/utils/downloadFile.ts

File renamed without changes.

src/components/tree/Download/FloatingButtonMenuItems/hooks/useFloatingButton/utils/fileAsUri.ts renamed to src/components/common/FloatingButtonMenuItems/hooks/useFloatingButton/utils/fileAsUri.ts

File renamed without changes.

src/components/tree/Download/FloatingButtonMenuItems/index.tsx renamed to src/components/common/FloatingButtonMenuItems/index.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import FloatingButtonMenuItem from "../../../common/FloatingButtonMenuItem";
2-
import AnalysisIcon from "../../../vectors/AnalysisIcon";
3-
import DownloadIcon from "../../../vectors/Download";
4-
import { DownloadPropsType } from "../types";
1+
import { Analysis } from "../../../types/Analysis";
2+
import { TreeResult } from "../../../types/result";
3+
import FloatingButtonMenuItem from "../../common/FloatingButtonMenuItem";
4+
import AnalysisIcon from "../../vectors/AnalysisIcon";
5+
import DownloadIcon from "../../vectors/Download";
56
import { useFloatingButton } from "./hooks/useFloatingButton";
6-
import React from "react";
7+
import React, { FC } from "react";
78

8-
const FloatingButtonMenuItems: React.FC<DownloadPropsType> = ({
9+
type FloatingButtonMenuItemsProps = {
10+
treeSections: TreeResult;
11+
analysis: Analysis | undefined;
12+
};
13+
14+
const FloatingButtonMenuItems: FC<FloatingButtonMenuItemsProps> = ({
915
treeSections,
1016
analysis,
1117
}) => {

src/components/common/Message.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { FC } from "react";
22

3-
export const Message: FC<{
3+
type MessageProps = {
44
message: string | undefined;
55
type: "info" | "error";
6-
}> = ({ message, type }) => {
7-
if (!message) return null;
6+
};
87

8+
export const Message: FC<MessageProps> = ({ message, type }) => {
9+
if (!message) return null;
910
if (type === "error") return <span className="text-red-500">{message}</span>;
10-
1111
if (type === "info") return <span className="text-leaf">{message}</span>;
12-
1312
return null;
1413
};

src/components/common/TableOfContents.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Button from "../ui/Button";
2-
import { FC } from "react";
32

43
type Heading = {
54
text: string;
@@ -29,7 +28,7 @@ const headingData: Heading[] = [
2928
},
3029
];
3130

32-
const TableOfContents: FC = () => {
31+
const TableOfContents = () => {
3332
return (
3433
<div className="prose prose-stone">
3534
<ul>
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import useFirebase from "../../hooks/useFirebase";
2+
import { TreeMetadata } from "../../types/treeMetadata";
3+
import { UserContextType } from "../../types/userContextType";
4+
import { mostCommon } from "../../utils/arrays";
5+
import Button from "../ui/Button";
6+
import TreeHistoryItems from "./TreeHistoryItems";
7+
import { useQuery } from "@tanstack/react-query";
8+
import {
9+
Firestore,
10+
collection,
11+
getDocs,
12+
limit,
13+
orderBy,
14+
query,
15+
where,
16+
} from "firebase/firestore";
17+
import { flatten, sortBy } from "lodash";
18+
import { useMemo, useState } from "react";
19+
20+
const TREES_PER_PAGE = 500;
21+
22+
type TreeHistoryProps = {
23+
user: UserContextType;
24+
};
25+
26+
const summarize = (tree: TreeMetadata) => {
27+
if (!tree.result) {
28+
return null;
29+
}
30+
const { root, trunk, leaf } = tree.result;
31+
const allKeywords = flatten([
32+
...root.map((node) => node.keywords),
33+
...trunk.map((node) => node.keywords),
34+
...leaf.map((node) => node.keywords),
35+
]);
36+
return {
37+
keywords: mostCommon(
38+
allKeywords
39+
.filter((kw) => kw !== undefined)
40+
.map((kw) => (kw as string).toLowerCase()),
41+
4,
42+
),
43+
createdDate: new Date(tree.createdDate),
44+
};
45+
};
46+
47+
const getTrees = async (
48+
firestore: Firestore,
49+
userId: string,
50+
count: number,
51+
) => {
52+
const treesQuery = query(
53+
collection(firestore, `users/${userId}/trees`),
54+
where("result", "!=", null),
55+
orderBy("result", "desc"),
56+
orderBy("finishedDate", "desc"),
57+
limit(count),
58+
);
59+
const result = await getDocs(treesQuery);
60+
return result.docs;
61+
};
62+
63+
const TreeHistory = ({ user }: TreeHistoryProps) => {
64+
const firebase = useFirebase();
65+
const [limit, setLimit] = useState(25);
66+
67+
const {
68+
data: trees,
69+
isError,
70+
isLoading,
71+
} = useQuery({
72+
queryKey: ["trees", user.uid, limit],
73+
queryFn: async () => {
74+
return getTrees(firebase.firestore, user.uid, limit);
75+
},
76+
});
77+
78+
const hasNext = useMemo(
79+
() => !trees || (trees.length === limit && trees.length < TREES_PER_PAGE),
80+
[trees, limit],
81+
);
82+
83+
const data = useMemo(
84+
() =>
85+
trees &&
86+
sortBy(
87+
trees.map((doc) => {
88+
const datum = doc.data() as TreeMetadata;
89+
return {
90+
treeId: doc.id,
91+
summary: summarize(datum),
92+
createdDate: datum.createdDate,
93+
planId: datum.planId,
94+
};
95+
}),
96+
(datum) => -datum.createdDate,
97+
),
98+
[trees],
99+
);
100+
101+
if (isLoading) return "Loading...";
102+
if (isError) return "There was an error loading your trees";
103+
if (!data) return "No trees found";
104+
105+
return (
106+
<div className="flex flex-col gap-3">
107+
{user.plan === "basic" ? (
108+
<ul className="flex flex-col gap-2">
109+
<TreeHistoryItems user={user} trees={data.slice(0, 3)} />
110+
</ul>
111+
) : (
112+
<div className="flex flex-col gap-8">
113+
<ul className="flex flex-col gap-2">
114+
<TreeHistoryItems user={user} trees={data} />
115+
</ul>
116+
{hasNext && (
117+
<div>
118+
<Button
119+
onClick={() =>
120+
setLimit((prev) => Math.min(TREES_PER_PAGE, prev * 2))
121+
}
122+
disabled={isLoading}
123+
className="uppercase"
124+
>
125+
Load More
126+
</Button>
127+
</div>
128+
)}
129+
</div>
130+
)}
131+
</div>
132+
);
133+
};
134+
135+
export default TreeHistory;

src/components/upload/TreeHistory/Items.tsx renamed to src/components/history/TreeHistoryItems.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
1-
import useUser from "../../../hooks/useUser";
2-
import { TreeSummary } from "../../../types/treeSummary";
3-
import Button from "../../ui/Button";
1+
import { TreeSummary } from "../../types/treeSummary";
2+
import { UserContextType } from "../../types/userContextType";
3+
import Button from "../ui/Button";
44
import moment from "moment";
55
import { FC } from "react";
66
import { Link } from "react-router-dom";
77

8-
type Props = {
8+
type TreeHistoryItemsProps = {
99
trees: TreeSummary[];
10+
user: UserContextType;
1011
};
1112

12-
const Items: FC<Props> = ({ trees }) => {
13-
const user = useUser();
14-
15-
if (!user) return null;
16-
13+
const TreeHistoryItems: FC<TreeHistoryItemsProps> = ({ trees, user }) => {
1714
return (
1815
<>
1916
{trees.map(({ treeId, summary, planId, createdDate }) => {
@@ -40,4 +37,4 @@ const Items: FC<Props> = ({ trees }) => {
4037
);
4138
};
4239

43-
export default Items;
40+
export default TreeHistoryItems;

src/components/layout/AppLayout.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1+
import cn from "../../utils/cn";
12
import Footer from "./Footer";
23
import Header from "./Header";
34
import { FC, ReactNode } from "react";
45
import { useLocation } from "react-router-dom";
56

6-
interface Props {
7+
type AppLayoutProps = {
78
children?: ReactNode;
8-
}
9+
};
910

10-
const AppLayout: FC<Props> = ({ children }: Props) => {
11+
const AppLayout: FC<AppLayoutProps> = ({ children }) => {
1112
const location = useLocation();
1213
return (
13-
<div className="grid-rows-[auto 1fr auto] mt-4 grid h-full gap-4 md:mt-16 md:gap-16">
14+
<div className="grid-rows-[auto_1fr_auto] mt-4 grid min-h-dvh gap-4 md:mt-16 md:gap-16">
1415
<header>
1516
<div className="container">
1617
<Header />
1718
</div>
1819
</header>
19-
<main>
20-
<div className={location.pathname !== "/" ? "container" : ""}>
20+
<main className="grid place-items-center">
21+
<div className={cn("w-full", { container: location.pathname !== "/" })}>
2122
{children}
2223
</div>
2324
</main>

0 commit comments

Comments
 (0)