-
-
-
Create new post
-
Logged in as {user.name}
-
-
+
);
};
diff --git a/src/pages/link/[location].tsx b/src/pages/link/[location].tsx
new file mode 100644
index 0000000..805994c
--- /dev/null
+++ b/src/pages/link/[location].tsx
@@ -0,0 +1,22 @@
+import { GetServerSideProps, NextPage } from "next";
+
+import prisma from "@utils/prisma";
+
+const LinkRedirectPage: NextPage = () => {
+ return <>>;
+};
+
+export const getServerSideProps: GetServerSideProps = async ({ params }) => {
+ const location = params?.location;
+
+ if (location === undefined || typeof location !== "string")
+ return { notFound: true };
+
+ const link = await prisma.link.findFirst({ where: { location } });
+
+ if (link === null) return { notFound: true };
+
+ return { redirect: { destination: link.remoteAddress, permanent: false } };
+};
+
+export default LinkRedirectPage;
diff --git a/src/pages/link/index.tsx b/src/pages/link/index.tsx
new file mode 100644
index 0000000..549fb29
--- /dev/null
+++ b/src/pages/link/index.tsx
@@ -0,0 +1,62 @@
+import { GetStaticProps, NextPage } from "next";
+import { NextSeo } from "next-seo";
+import Link from "next/link";
+
+import { Link as LinkType } from "@prisma/client";
+
+import useUser from "@utils/hooks/useUser";
+import prisma from "@utils/prisma";
+
+import EmptyPage from "@components/EmptyPage";
+import Layout from "@components/Layout";
+import LinkComponent from "@components/LinkComponent";
+
+const LinksPage: NextPage<{ links: LinkType[] }> = ({ links }) => {
+ const user = useUser();
+
+ return (
+
+
+
+
+
+
Links
+
+
+
+
This is a collection of quick usefull links
+
+ {user !== null && (
+
+ )}
+
+
+
+
+ {links.length < 1 &&
No links yet
}
+ {links.map((link) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+export const getStaticProps: GetStaticProps = async () => {
+ const links = await prisma.link
+ .findMany({
+ orderBy: { id: "desc" },
+ take: 5
+ })
+ .catch(() => []);
+
+ return { props: { links }, revalidate: 1 * 60 };
+};
+
+export default LinksPage;
diff --git a/src/pages/link/new.tsx b/src/pages/link/new.tsx
new file mode 100644
index 0000000..6993ee7
--- /dev/null
+++ b/src/pages/link/new.tsx
@@ -0,0 +1,132 @@
+import { GetServerSideProps, NextPage } from "next";
+import { NextSeo } from "next-seo";
+import { useRouter } from "next/router";
+
+import { FormEvent, useCallback, useState } from "react";
+
+import axios from "axios";
+
+import { User } from "@prisma/client";
+
+import Link from "@models/link";
+
+import { parseAxiosError, parseAxiosResponse } from "@utils/fetch";
+import { withSessionSsr } from "@utils/session";
+
+import EmptyPage from "@components/EmptyPage";
+import Layout from "@components/Layout";
+
+const NewLinkPage: NextPage<{ user: User }> = ({ user }) => {
+ const [remoteAddress, setRemoteAddress] = useState("");
+ const [localAddress, setLocalAddress] = useState("");
+ const [error, setError] = useState
(null);
+
+ const router = useRouter();
+
+ const host =
+ typeof window !== "undefined" && "location" in window
+ ? location.host
+ : "guusvanmeerveld.dev";
+
+ const createLink = useCallback(
+ async (e: FormEvent) => {
+ e.preventDefault();
+
+ const parsedLinkResult = Link.safeParse({
+ remoteAddress,
+ location: localAddress
+ });
+
+ if (!parsedLinkResult.success) {
+ setError(parsedLinkResult.error.message);
+ return;
+ }
+
+ const response = await axios
+ .post("/api/link/new", parsedLinkResult.data)
+ .then(parseAxiosResponse)
+ .catch(parseAxiosError);
+
+ if (!response.ok) {
+ setError(JSON.stringify(response.error));
+ return;
+ }
+
+ router.push("/link");
+ },
+ [remoteAddress, localAddress, router]
+ );
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export const getServerSideProps: GetServerSideProps = withSessionSsr(
+ async ({ req }) => {
+ const user = req.session.user;
+
+ if (user === undefined)
+ return {
+ notFound: true
+ };
+
+ return { props: { user } };
+ }
+);
+
+export default NewLinkPage;
diff --git a/src/styles/_dark.scss b/src/styles/_dark.scss
index 0e5245b..6b249bc 100644
--- a/src/styles/_dark.scss
+++ b/src/styles/_dark.scss
@@ -34,8 +34,10 @@
background-color: $bg-dark-secondary !important;
}
- .chip {
+ .chip,
+ .input-group .input-group-addon {
background-color: lighten($bg-dark-secondary, 10%);
+ border-color: lighten($bg-dark-secondary, 20%)
}
.divider {
@@ -43,6 +45,7 @@
}
.table {
+
td,
th {
border-color: lighten($bg-dark-secondary, 10%);
@@ -101,4 +104,4 @@
border-color: $primary-color-dark;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/utils/hooks/useUser.ts b/src/utils/hooks/useUser.ts
new file mode 100644
index 0000000..5603b92
--- /dev/null
+++ b/src/utils/hooks/useUser.ts
@@ -0,0 +1,35 @@
+import { useQuery } from "@tanstack/react-query";
+
+import axios from "axios";
+
+import { User } from "@prisma/client";
+
+import { User as UserModel } from "@models/user";
+
+import { parseAxiosError, parseAxiosResponse } from "@utils/fetch";
+
+const useUser = (): User | null => {
+ const { data } = useQuery(
+ ["user"],
+ async () => {
+ const response = await axios
+ .get("/api/user")
+ .then(parseAxiosResponse)
+ .catch(parseAxiosError);
+
+ if (response.ok) return response.data;
+ else throw response.error;
+ },
+ { retry: () => false, enabled: typeof window !== "undefined" }
+ );
+
+ if (typeof window === "undefined") return null;
+
+ const parseUserResult = UserModel.safeParse(data);
+
+ if (parseUserResult.success) {
+ return parseUserResult.data;
+ } else return null;
+};
+
+export default useUser;