started work on page footer
continuous-integration/drone/push Build is passing Details

pull/1/head
Guus van Meerveld 9 months ago
parent 789ddcf00c
commit 946bc5f6e6

@ -1,12 +1,13 @@
{ {
"owner": { "header": {
"fullName": "Guus van Meerveld", "fullName": "Guus van Meerveld",
"name": "guus", "name": "guus",
"description": "AI student at Radboud University. Creating software as a hobby.", "description": "AI student at Radboud University. Creating software as a hobby.",
"contact": { "contact": {
"email": "contact@guusvanmeerveld.dev", "email": "contact@guusvanmeerveld.dev",
"git": "https://github.com/Guusvanmeerveld", "git": "https://github.com/Guusvanmeerveld",
"linkedin": "https://linkedin.com/in/guus-van-meerveld-038357210" "linkedin": "https://linkedin.com/in/guus-van-meerveld-038357210"
} }
} },
"footer": {}
} }

@ -10,45 +10,45 @@ import Link from "next/link";
import { useMemo } from "react"; import { useMemo } from "react";
import { FiGithub, FiMail, FiLinkedin } from "react-icons/fi"; import { FiGithub, FiMail, FiLinkedin } from "react-icons/fi";
import Owner from "@models/owner"; import HeaderProps from "@models/header";
export const Header: Component<{ owner: Owner }> = ({ owner }) => { export const Header: Component<{ header: HeaderProps }> = ({ header }) => {
const socials = useMemo( const socials = useMemo(
() => [ () => [
{ {
link: `mailto:${owner.contact.email}`, link: `mailto:${header.contact.email}`,
name: "Email address", name: "Email address",
icon: <FiMail /> icon: <FiMail />
}, },
{ {
link: owner.contact.git, link: header.contact.git,
name: "Github", name: "Github",
icon: <FiGithub /> icon: <FiGithub />
}, },
{ {
link: owner.contact.linkedin, link: header.contact.linkedin,
name: "LinkedIn", name: "LinkedIn",
icon: <FiLinkedin /> icon: <FiLinkedin />
} }
], ],
[owner.contact] [header.contact]
); );
return ( return (
<div className="container min-h-screen"> <div className="container mx-auto flex items-center min-h-screen">
<div> <div>
{owner.avatar !== undefined && ( {header.avatar !== undefined && (
<Image <Image
src={owner.avatar} src={header.avatar}
width={300} width={300}
alt={`A picture of ${owner.fullName}`} alt={`A picture of ${header.fullName}`}
/> />
)} )}
<h1 className="text-4xl">{owner.fullName}</h1> <h1 className="text-4xl">{header.fullName}</h1>
<Spacer y={4} /> <Spacer y={4} />
<h2 className="text-2xl">{owner.description}</h2> <h2 className="text-2xl">{header.description}</h2>
<Spacer y={4} /> <Spacer y={4} />
{socials.map((social) => ( {socials.map((social) => (

@ -1,3 +1,4 @@
import { Footer } from "../Footer";
import { Header } from "./Header"; import { Header } from "./Header";
import Landing from "@models/landing"; import Landing from "@models/landing";
@ -15,7 +16,8 @@ export default async function Page() {
return ( return (
<> <>
<Header owner={landing.owner} /> <Header header={landing.header} />
<Footer />
</> </>
); );
} }

@ -0,0 +1,12 @@
import { Component } from "@typings/component";
export const Footer: Component = () => {
return (
<div className="container mx-auto columns-4">
<div className="w-full">hi</div>
<div className="w-full">hi</div>
<div className="w-full">hi</div>
<div className="w-full">hi</div>
</div>
);
};

@ -0,0 +1,37 @@
"use client";
import { Switch } from "@nextui-org/react";
import { Component } from "@typings/component";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { FiMoon, FiSun } from "react-icons/fi";
export const ThemeSwitcher: Component = () => {
const [mounted, setMounted] = useState(false);
const { theme, setTheme } = useTheme();
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return null;
return (
<div>
The current theme is: {theme}
<Switch
defaultSelected
size="lg"
color="primary"
onValueChange={(value) => {
value ? setTheme("dark") : setTheme("light");
}}
startContent={<FiSun />}
endContent={<FiMoon />}
>
Dark mode
</Switch>
</div>
);
};

@ -11,13 +11,15 @@ const MainErrorPage: ErrorPage = ({ error, reset }) => {
}, [error]); }, [error]);
return ( return (
<div className="container min-h-screen text-center"> <div className="container mx-auto flex items-center justify-center min-h-screen text-center">
<p className="text-3xl">Something went loading the page!</p>
<p className="text-xl">{error.toString()}</p>
<div> <div>
<Link href="#" onClick={() => reset()}> <p className="text-3xl">Something went loading the page!</p>
Try again <p className="text-xl">{error.toString()}</p>
</Link> <div>
<Link href="#" onClick={() => reset()}>
Try again
</Link>
</div>
</div> </div>
</div> </div>
); );

@ -1,5 +1,6 @@
import { Metadata } from "next"; import { Metadata } from "next";
import { Footer } from "./Footer";
import { Providers } from "./providers"; import { Providers } from "./providers";
import "@styles/global.scss"; import "@styles/global.scss";
@ -10,7 +11,7 @@ export default function RootLayout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<html lang="en" className="dark"> <html lang="en">
<body> <body>
<Providers>{children}</Providers> <Providers>{children}</Providers>
</body> </body>

@ -1,7 +1,15 @@
"use client"; "use client";
import { NextUIProvider } from "@nextui-org/react"; import { NextUIProvider } from "@nextui-org/react";
import { Component } from "@typings/component";
import { ThemeProvider as NextThemesProvider } from "next-themes";
export function Providers({ children }: { children: React.ReactNode }) { export const Providers: Component = ({ children }) => {
return <NextUIProvider>{children}</NextUIProvider>; return (
} <NextUIProvider>
<NextThemesProvider attribute="class" defaultTheme="dark">
{children}
</NextThemesProvider>
</NextUIProvider>
);
};

@ -0,0 +1,7 @@
import z from "zod";
export const FooterPropsModel = z.object({});
export type FooterProps = z.infer<typeof FooterPropsModel>;
export default FooterProps;

@ -1,6 +1,6 @@
import z from "zod"; import z from "zod";
export const OwnerModel = z.object({ export const HeaderPropsModel = z.object({
fullName: z.string(), fullName: z.string(),
name: z.string(), name: z.string(),
avatar: z.string().optional(), avatar: z.string().optional(),
@ -12,6 +12,6 @@ export const OwnerModel = z.object({
}) })
}); });
export type Owner = z.infer<typeof OwnerModel>; export type HeaderProps = z.infer<typeof HeaderPropsModel>;
export default Owner; export default HeaderProps;

@ -1,9 +1,11 @@
import z from "zod"; import z from "zod";
import { OwnerModel } from "./owner"; import { FooterPropsModel } from "./footer";
import { HeaderPropsModel } from "./header";
export const LandingModel = z.object({ export const LandingModel = z.object({
owner: OwnerModel header: HeaderPropsModel,
footer: FooterPropsModel
}); });
export type Landing = z.infer<typeof LandingModel>; export type Landing = z.infer<typeof LandingModel>;

@ -1,23 +1,3 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
.container {
display: flex;
min-width: 100%;
flex-direction: column;
justify-content: center;
padding-right: 1rem;
padding-left: 1rem;
@media screen and (width >=800px) {
padding-right: 4rem;
padding-left: 4rem;
}
@media screen and (width >=1200px) {
padding-right: 16rem;
padding-left: 16rem;
}
}

@ -1,3 +1,3 @@
import { FC, PropsWithChildren } from "react"; import { FC, PropsWithChildren } from "react";
export type Component<P> = FC<PropsWithChildren<P>>; export type Component<P = unknown> = FC<PropsWithChildren<P>>;

@ -1,3 +1 @@
import path from "path";
export const dataDirLocation = process.env.DATA_DIR ?? "/app/data"; export const dataDirLocation = process.env.DATA_DIR ?? "/app/data";

Loading…
Cancel
Save