diff --git a/next.config.js b/next.config.js deleted file mode 100644 index c681179..0000000 --- a/next.config.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - pageExtensions: ["page.ts", "page.tsx"], - reactStrictMode: true, - swcMinify: true, -}; - -module.exports = nextConfig; diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..4678774 --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/src/app/api/linear/[teamId]/[property]/comparisons/route.ts b/src/app/api/linear/[teamId]/[property]/comparisons/route.ts new file mode 100644 index 0000000..66e740f --- /dev/null +++ b/src/app/api/linear/[teamId]/[property]/comparisons/route.ts @@ -0,0 +1,24 @@ +import { NextResponse } from "next/server"; +import getComparisons from "../../../../../../core/getComparisons"; +import postComparisons from "../../../../../../core/postComparisons"; + +type Params = { + property: "effort"; + teamId: string; +}; + +export const GET = async (_: Request, { params }: { params: Params }) => { + const data = await getComparisons("linear", params.teamId, params.property); + return NextResponse.json(data); +}; + +export const POST = async (req: Request, { params }: { params: Params }) => { + const body = await req.json(); + const data = await postComparisons( + "linear", + params.teamId, + params.property, + body + ); + return NextResponse.json(data); +}; diff --git a/src/pages/effort/[id].page.tsx b/src/app/effort/[id]/page.tsx similarity index 71% rename from src/pages/effort/[id].page.tsx rename to src/app/effort/[id]/page.tsx index f87b112..b353c0a 100644 --- a/src/pages/effort/[id].page.tsx +++ b/src/app/effort/[id]/page.tsx @@ -1,21 +1,16 @@ -import type { NextPage } from "next"; -import { useRouter } from "next/router"; -import Layout from "../../components/Layout"; -import IssueComparison from "../../core/IssueComparison"; +"use client"; -const EffortPage: NextPage = () => { - const { push, query } = useRouter(); - const id = Array.isArray(query.id) ? query.id[0] : query.id; +import IssueComparison from "../../../core/IssueComparison"; - if (!id) { - push("/effort"); - return null; - } +type Params = { + id: string; +}; +const EffortPage = ({ params }: { params: Params }) => { return ( - + <> @@ -41,7 +36,7 @@ const EffortPage: NextPage = () => { firstButtonLabel="Quickest" successiveButtonLabel="Next quickest" /> - + ); }; diff --git a/src/pages/effort/index.page.tsx b/src/app/effort/page.tsx similarity index 86% rename from src/pages/effort/index.page.tsx rename to src/app/effort/page.tsx index 90bad32..5edf6ef 100644 --- a/src/pages/effort/index.page.tsx +++ b/src/app/effort/page.tsx @@ -1,5 +1,7 @@ +"use client"; + import type { NextPage } from "next"; -import { useRouter } from "next/router"; +import { useRouter } from "next/navigation"; import { useContext, useEffect } from "react"; import { v4 as uuid } from "uuid"; import Layout from "../../components/Layout"; @@ -22,7 +24,7 @@ const EffortIndexPage: NextPage = () => { } }, [createTournament, issueSummaries.length, router]); - return Generating tournament...; + return <>Generating tournament...; }; export default EffortIndexPage; diff --git a/src/pages/app.css b/src/app/layout.css similarity index 100% rename from src/pages/app.css rename to src/app/layout.css diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..30e17ef --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,20 @@ +import Layout from "@/components/Layout"; +import LinearApp from "@/linear/LinearApp"; +import type { ReactNode } from "react"; +import "./layout.css"; + +type Props = { + children: ReactNode; +}; + +const RootLayout = ({ children }: Props) => ( + + + + {children} + + + +); + +export default RootLayout; diff --git a/src/pages/index.page.tsx b/src/app/page.tsx similarity index 98% rename from src/pages/index.page.tsx rename to src/app/page.tsx index 110f9e2..d2546ae 100644 --- a/src/pages/index.page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,8 @@ +"use client"; + import type { NextPage } from "next"; import { useContext, useState } from "react"; import ComparisonValue from "../components/ComparisonValue"; -import Layout from "../components/Layout"; import ProjectName from "../components/ProjectName"; import RelationshipGraph from "../components/RelationshipGraph"; import CoreContext from "../core/CoreContext"; @@ -49,7 +50,7 @@ const IndexPage: NextPage = () => { ); return ( - + <>
{ })} - + ); }; diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx new file mode 100644 index 0000000..9f961a3 --- /dev/null +++ b/src/app/settings/page.tsx @@ -0,0 +1,21 @@ +"use client"; + +import CredentialsForm from "../../linear/CredentialsForm"; +import { useLocalStorage } from "../../utils/useLocalStorage"; + +const SettingsPage = () => { + const [apiKey, setApiKey] = useLocalStorage("linear_api_key"); + const [teamId, setTeamId] = useLocalStorage("linear_team_id"); + + return ( + { + setApiKey(apiKey); + setTeamId(teamId); + }} + /> + ); +}; + +export default SettingsPage; diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index e3fd580..6a1c570 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,3 +1,5 @@ +"use client"; + import styles from "./Layout.module.css"; import Link from "next/link"; diff --git a/src/core/IssueComparison.tsx b/src/core/IssueComparison.tsx index 039bdad..5913f22 100644 --- a/src/core/IssueComparison.tsx +++ b/src/core/IssueComparison.tsx @@ -1,6 +1,6 @@ import styles from "./IssueComparison.module.css"; -import { useRouter } from "next/router"; +import { useRouter } from "next/navigation"; import { type ReactNode, useContext, useState } from "react"; import IssueCard from "../components/IssueCard"; import CoreContext from "./CoreContext"; diff --git a/src/core/getComparisons.ts b/src/core/getComparisons.ts index ed2ff36..544c385 100644 --- a/src/core/getComparisons.ts +++ b/src/core/getComparisons.ts @@ -22,7 +22,7 @@ const getRedisResponseSchema = z.union([ const getComparisons = async ( app: "linear", teamId: string, - property: "effort" | "value", + property: "effort", start: string = "-" ): Promise> => { const response = await fetch( diff --git a/src/core/postComparisons.ts b/src/core/postComparisons.ts index 8858ba6..39a204b 100644 --- a/src/core/postComparisons.ts +++ b/src/core/postComparisons.ts @@ -1,6 +1,5 @@ import { formatISO, fromUnixTime } from "date-fns"; import gql from "dedent"; -import type { NextApiRequest } from "next"; import { z } from "zod"; import { postBodySchema, postLinearResponseSchema } from "../linear/_schema"; import type { Comparison } from "./_types"; @@ -31,7 +30,7 @@ const postComparisons = async ( app: "linear", teamId: string, property: "effort" | "value", - body: NextApiRequest["body"] + body: unknown ): Promise> => { const { apiKey, comparisons, highWaterMark } = postBodySchema.parse(body); diff --git a/src/linear/CredentialsForm.tsx b/src/linear/CredentialsForm.tsx index 0737ddf..e3eb9c8 100644 --- a/src/linear/CredentialsForm.tsx +++ b/src/linear/CredentialsForm.tsx @@ -3,7 +3,6 @@ import styles from "./CredentialsForm.module.css"; import { useEffect, useState } from "react"; import { z } from "zod"; import credentialsSchema from "./credentialsSchema"; -import { useLocalStorage } from "../utils/useLocalStorage"; type Props = { value: z.infer | null; @@ -13,7 +12,6 @@ type Props = { const CredentialsForm = ({ value, onSubmit }: Props) => { const [apiKey, setApiKey] = useState(value?.apiKey ?? ""); const [teamId, setTeamId] = useState(value?.teamId ?? ""); - const [_, setAppId] = useLocalStorage("app"); useEffect(() => { setApiKey((current) => @@ -54,14 +52,6 @@ const CredentialsForm = ({ value, onSubmit }: Props) => { />
diff --git a/src/linear/LinearApp.tsx b/src/linear/LinearApp.tsx index 4baf051..17d84e0 100644 --- a/src/linear/LinearApp.tsx +++ b/src/linear/LinearApp.tsx @@ -1,3 +1,5 @@ +"use client"; + import gql from "dedent"; import { type ReactNode, useCallback } from "react"; import Core from "../core/Core"; diff --git a/src/pages/_app.page.tsx b/src/pages/_app.page.tsx deleted file mode 100644 index 7bacc85..0000000 --- a/src/pages/_app.page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import "./app.css"; - -import type { AppProps } from "next/app"; -import LinearApp from "../linear/LinearApp"; - -const App = ({ Component, pageProps }: AppProps) => ( - - - -); - -export default App; diff --git a/src/pages/api/linear/[teamId]/[property]/comparisons.page.ts b/src/pages/api/linear/[teamId]/[property]/comparisons.page.ts deleted file mode 100644 index 371aaa1..0000000 --- a/src/pages/api/linear/[teamId]/[property]/comparisons.page.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from "next"; -import getComparisons from "../../../../../core/getComparisons"; -import postComparisons from "../../../../../core/postComparisons"; -import { queryParamsSchema } from "../../../../../linear/_schema"; - -const LinearComparisonsEndpoint = async ( - req: NextApiRequest, - res: NextApiResponse -) => { - try { - const query = queryParamsSchema.parse(req.query); - - switch (req.method) { - case "GET": { - const data = await getComparisons( - "linear", - query.teamId, - query.property - ); - res.status(200).json(data); - return; - } - case "POST": - const data = await postComparisons( - "linear", - query.teamId, - query.property, - req.body - ); - res.status(200).json(data); - return; - default: - throw Error("Only GET and POST requests are supported."); - } - } catch (error) { - res - .status(500) - .send(error instanceof Error ? error.message : "Unknown error."); - } -}; - -export default LinearComparisonsEndpoint; diff --git a/src/pages/settings.page.tsx b/src/pages/settings.page.tsx deleted file mode 100644 index 1f67f40..0000000 --- a/src/pages/settings.page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Layout from "../components/Layout"; -import CredentialsForm from "../linear/CredentialsForm"; -import { useLocalStorage } from "../utils/useLocalStorage"; - -const SettingsPage = () => { - const [apiKey, setApiKey] = useLocalStorage("linear_api_key"); - const [teamId, setTeamId] = useLocalStorage("linear_team_id"); - - return ( - - { - setApiKey(apiKey); - setTeamId(teamId); - }} - /> - - ); -}; - -export default SettingsPage;