1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2024-10-05 13:06:10 +02:00

Compare commits

...

4 Commits

26 changed files with 63 additions and 34 deletions

View File

@ -25,7 +25,7 @@ const BlogPage = async (): Promise<JSX.Element> => {
return ( return (
<main className="flex flex-1 flex-col flex-wrap items-center"> <main className="flex flex-1 flex-col flex-wrap items-center">
<div className="mt-10 flex flex-col items-center"> <div className="mt-10 flex flex-col items-center">
<h1 className="text-4xl font-semibold text-yellow dark:text-yellow-dark"> <h1 className="text-4xl font-semibold text-primary dark:text-primary-dark">
Blog Blog
</h1> </h1>
<p className="mt-6 text-center" data-cy="blog-post-date"> <p className="mt-6 text-center" data-cy="blog-post-date">

View File

@ -18,7 +18,7 @@ const ErrorHandling = (props: ErrorHandlingProps): JSX.Element => {
<h1 className="my-6 text-4xl font-semibold"> <h1 className="my-6 text-4xl font-semibold">
Error{" "} Error{" "}
<span <span
className="text-yellow dark:text-yellow-dark" className="text-primary dark:text-primary-dark"
data-cy="status-code" data-cy="status-code"
> >
500 500

View File

@ -29,7 +29,7 @@
.prose a, .prose a,
.prose strong { .prose strong {
@apply !font-semibold text-yellow dark:text-yellow-dark; @apply !font-semibold text-primary dark:text-primary-dark;
} }
strong, strong,

View File

@ -10,7 +10,7 @@ const NotFound = (): JSX.Element => {
<h1 className="my-6 text-4xl font-semibold"> <h1 className="my-6 text-4xl font-semibold">
{i18n.translate("errors.error")}{" "} {i18n.translate("errors.error")}{" "}
<span <span
className="text-yellow dark:text-yellow-dark" className="text-primary dark:text-primary-dark"
data-cy="status-code" data-cy="status-code"
> >
404 404
@ -20,7 +20,7 @@ const NotFound = (): JSX.Element => {
{i18n.translate("errors.not-found")}{" "} {i18n.translate("errors.not-found")}{" "}
<Link <Link
href="/" href="/"
className="text-yellow hover:underline dark:text-yellow-dark" className="text-primary hover:underline dark:text-primary-dark"
> >
{i18n.translate("errors.return-to-home-page")} {i18n.translate("errors.return-to-home-page")}
</Link> </Link>

View File

@ -21,7 +21,7 @@ export const BlogPost = async (props: BlogPostProps): Promise<JSX.Element> => {
return ( return (
<main className="break-wrap-words flex flex-1 flex-col flex-wrap items-center justify-center"> <main className="break-wrap-words flex flex-1 flex-col flex-wrap items-center justify-center">
<div className="my-10 flex flex-col items-center text-center"> <div className="my-10 flex flex-col items-center text-center">
<h1 className="text-3xl font-semibold text-yellow dark:text-yellow-dark"> <h1 className="text-3xl font-semibold text-primary dark:text-primary-dark">
{blogPost.frontmatter.title} {blogPost.frontmatter.title}
</h1> </h1>
<p className="mt-2" data-cy="blog-post-date"> <p className="mt-2" data-cy="blog-post-date">

View File

@ -25,7 +25,7 @@ export const BlogPosts = async (): Promise<JSX.Element> => {
<ShadowContainer className="cursor-pointer p-6 transition duration-200 ease-in-out hover:-translate-y-2"> <ShadowContainer className="cursor-pointer p-6 transition duration-200 ease-in-out hover:-translate-y-2">
<h2 <h2
data-cy="blog-post-title" data-cy="blog-post-title"
className="text-xl font-semibold text-yellow dark:text-yellow-dark" className="text-xl font-semibold text-primary dark:text-primary-dark"
> >
{post.frontmatter.title} {post.frontmatter.title}
</h2> </h2>

View File

@ -9,7 +9,7 @@ export const FooterText = (): JSX.Element => {
<p> <p>
<Link <Link
href="/" href="/"
className="font-semibold text-yellow hover:underline dark:text-yellow-dark" className="font-semibold text-primary hover:underline dark:text-primary-dark"
> >
Théo LUDWIG Théo LUDWIG
</Link>{" "} </Link>{" "}

View File

@ -16,7 +16,7 @@ export const FooterVersion = (props: FooterVersionProps): JSX.Element => {
Version{" "} Version{" "}
<a <a
data-cy="version-link" data-cy="version-link"
className="font-semibold text-yellow hover:underline dark:text-yellow-dark" className="font-semibold text-primary hover:underline dark:text-primary-dark"
href={versionLink} href={versionLink}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"

View File

@ -1,9 +1,10 @@
import { getVersion } from "@/utils/getVersion"
import { FooterText } from "./FooterText" import { FooterText } from "./FooterText"
import { FooterVersion } from "./FooterVersion" import { FooterVersion } from "./FooterVersion"
export const Footer = async (): Promise<JSX.Element> => { export const Footer = async (): Promise<JSX.Element> => {
const { readPackage } = await import("read-pkg") const version = await getVersion()
const { version } = await readPackage()
return ( return (
<footer className="flex flex-col items-center justify-center border-t-2 border-gray-600 bg-white py-6 text-lg dark:border-gray-400 dark:bg-black"> <footer className="flex flex-col items-center justify-center border-t-2 border-gray-600 bg-white py-6 text-lg dark:border-gray-400 dark:bg-black">

View File

@ -23,7 +23,7 @@ export const Header = (): JSX.Element => {
alt="Théo LUDWIG" alt="Théo LUDWIG"
priority priority
/> />
<strong className="ml-1 hidden font-headline font-semibold text-yellow dark:text-yellow-dark sm:block sm:text-xl"> <strong className="ml-1 hidden font-headline font-semibold text-primary dark:text-primary-dark sm:block sm:text-xl">
Théo LUDWIG Théo LUDWIG
</strong> </strong>
</h1> </h1>
@ -33,7 +33,7 @@ export const Header = (): JSX.Element => {
<Link <Link
href="/blog" href="/blog"
data-cy="header-blog-link" data-cy="header-blog-link"
className="font-semibold text-yellow hover:underline dark:text-yellow-dark" className="font-semibold text-primary hover:underline dark:text-primary-dark"
> >
Blog Blog
</Link> </Link>

View File

@ -22,7 +22,7 @@ export const InterestParagraph = (
return ( return (
<> <>
<p className="my-6 text-center text-gray dark:text-gray-dark"> <p className="my-6 text-center text-gray dark:text-gray-dark">
<strong className="text-lg font-semibold text-yellow dark:text-yellow-dark"> <strong className="text-lg font-semibold text-primary dark:text-primary-dark">
{title} {title}
</strong> </strong>
<br /> <br />

View File

@ -12,7 +12,7 @@ export const InterestItem = (props: InterestItemProps): JSX.Element => {
return ( return (
<li className="m-2 size-8" title={title}> <li className="m-2 size-8" title={title}>
<FontAwesomeIcon <FontAwesomeIcon
className="block size-full text-yellow dark:text-yellow-dark" className="block size-full text-primary dark:text-primary-dark"
icon={fontAwesomeIcon} icon={fontAwesomeIcon}
/> />
</li> </li>

View File

@ -15,7 +15,7 @@ export const Repository = (props: RepositoryProps): JSX.Element => {
<a href={href} target="_blank" rel="noopener noreferrer"> <a href={href} target="_blank" rel="noopener noreferrer">
<div className="flex"> <div className="flex">
<GitHubIcon className="mr-2 h-6" /> <GitHubIcon className="mr-2 h-6" />
<span className="font-semibold text-yellow dark:text-yellow-dark"> <span className="font-semibold text-primary dark:text-primary-dark">
{name} {name}
</span> </span>
</div> </div>

View File

@ -32,7 +32,7 @@ export const PortfolioItem = (props: PortfolioItemProps): JSX.Element => {
/> />
</div> </div>
<div className="absolute bottom-0 h-auto overflow-hidden text-center opacity-0 transition-opacity duration-500 group-hover:opacity-100"> <div className="absolute bottom-0 h-auto overflow-hidden text-center opacity-0 transition-opacity duration-500 group-hover:opacity-100">
<h3 className="my-6 text-2xl font-semibold text-yellow dark:text-yellow-dark"> <h3 className="my-6 text-2xl font-semibold text-primary dark:text-primary-dark">
{title} {title}
</h3> </h3>
<p className="mx-4 my-6 font-semibold">{description}</p> <p className="mx-4 my-6 font-semibold">{description}</p>

View File

@ -12,7 +12,7 @@ export const ProfileDescriptionBottom = (): JSX.Element => {
<br /> <br />
<a <a
href="/curriculum-vitae/index.html" href="/curriculum-vitae/index.html"
className="font-semibold text-yellow hover:underline dark:text-yellow-dark" className="font-semibold text-primary hover:underline dark:text-primary-dark"
> >
Curriculum vitæ ({i18n.translate("common.fr-FR")}) Curriculum vitæ ({i18n.translate("common.fr-FR")})
</a> </a>

View File

@ -5,7 +5,7 @@ export const ProfileInformation = (): JSX.Element => {
return ( return (
<div className="mb-6 border-b-2 border-gray-600 pb-2 font-headline dark:border-gray-400"> <div className="mb-6 border-b-2 border-gray-600 pb-2 font-headline dark:border-gray-400">
<h1 className="mb-2 text-4xl font-semibold text-yellow dark:text-yellow-dark"> <h1 className="mb-2 text-4xl font-semibold text-primary dark:text-primary-dark">
Théo LUDWIG Théo LUDWIG
</h1> </h1>
<h2 className="mb-3 text-base"> <h2 className="mb-3 text-base">

View File

@ -5,6 +5,7 @@ import { useMemo } from "react"
import { useI18n } from "@/i18n/i18n.client" import { useI18n } from "@/i18n/i18n.client"
import { BIRTH_DATE, BIRTH_DATE_STRING, getAge } from "@/utils/getAge" import { BIRTH_DATE, BIRTH_DATE_STRING, getAge } from "@/utils/getAge"
import type { CookiesStore } from "@/utils/constants" import type { CookiesStore } from "@/utils/constants"
import { useIsMounted } from "@/hooks/useIsMounted"
import { ProfileItem } from "./ProfileItem" import { ProfileItem } from "./ProfileItem"
@ -21,18 +22,22 @@ export const ProfileList = (props: ProfileListProps): JSX.Element => {
return getAge(BIRTH_DATE) return getAge(BIRTH_DATE)
}, []) }, [])
const { isMounted } = useIsMounted()
return ( return (
<ul className="m-0 list-none p-0"> <ul className="m-0 list-none p-0">
<ProfileItem <ProfileItem
title={i18n.translate("home.about.pronouns")} title={i18n.translate("home.about.pronouns")}
value={i18n.translate("home.about.pronouns-value")} value={i18n.translate("home.about.pronouns-value")}
/> />
<ProfileItem {isMounted ? (
title={i18n.translate("home.about.birth-date")} <ProfileItem
value={`${BIRTH_DATE_STRING} (${age} ${i18n.translate( title={i18n.translate("home.about.birth-date")}
"home.about.years-old", value={`${BIRTH_DATE_STRING} (${age} ${i18n.translate(
)})`} "home.about.years-old",
/> )})`}
/>
) : null}
<ProfileItem <ProfileItem
title={i18n.translate("home.about.nationality")} title={i18n.translate("home.about.nationality")}
value="Alsace, France" value="Alsace, France"

View File

@ -29,7 +29,7 @@ export const SkillComponent = (props: SkillComponentProps): JSX.Element => {
return ( return (
<a <a
href={skillProperties.link} href={skillProperties.link}
className="mx-2 max-w-xl text-yellow hover:underline dark:text-yellow-dark" className="mx-2 max-w-xl text-primary hover:underline dark:text-primary-dark"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >

View File

@ -14,7 +14,7 @@ export const SkillsSection = (props: SkillsSectionProps): JSX.Element => {
<div className="flex flex-wrap px-4 py-6"> <div className="flex flex-wrap px-4 py-6">
<div className="flex-1"> <div className="flex-1">
<div className="mb-8 border-b border-gray-600 dark:border-white/10"> <div className="mb-8 border-b border-gray-600 dark:border-white/10">
<h3 className="my-3 text-xl font-semibold text-yellow dark:text-yellow-dark"> <h3 className="my-3 text-xl font-semibold text-primary dark:text-primary-dark">
{title} {title}
</h3> </h3>
</div> </div>

View File

@ -16,7 +16,7 @@ export const Loader = (props: LoaderProps): JSX.Element => {
height, height,
}} }}
className={classNames( className={classNames(
"inline-block animate-spin rounded-full border-[3px] border-current border-t-transparent text-yellow dark:text-yellow-dark", "inline-block animate-spin rounded-full border-[3px] border-current border-t-transparent text-primary dark:text-primary-dark",
className, className,
)} )}
role="status" role="status"

View File

@ -6,7 +6,7 @@ export const SectionHeading = (props: SectionHeadingProps): JSX.Element => {
return ( return (
<h2 <h2
{...rest} {...rest}
className="mb-3 mt-1 text-center text-4xl font-semibold text-yellow dark:text-yellow-dark" className="mb-3 mt-1 text-center text-4xl font-semibold text-primary dark:text-primary-dark"
> >
{children} {children}
</h2> </h2>

15
hooks/useIsMounted.ts Normal file
View File

@ -0,0 +1,15 @@
import { useEffect, useState } from "react"
export interface UseIsMountedResult {
isMounted: boolean
}
export const useIsMounted = (): UseIsMountedResult => {
const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
}, [])
return { isMounted }
}

View File

@ -18,7 +18,7 @@
}, },
{ {
"title": "Open-Source Enthusiast", "title": "Open-Source Enthusiast",
"description": "I value the <strong>sharing of knowledge and collaboration</strong> to collectively resolve problems. <br /> The source code of the website is available on <a class='text-yellow dark:text-yellow-dark hover:underline font-semibold' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>.", "description": "I value the <strong>sharing of knowledge and collaboration</strong> to collectively resolve problems. <br /> The source code of the website is available on <a class='text-primary dark:text-primary-dark hover:underline font-semibold' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>.",
"id": "open-source" "id": "open-source"
} }
] ]
@ -34,7 +34,7 @@
{ {
"title": "Carolo", "title": "Carolo",
"description": "Strategy board game similar to chess which allows grandiose moves (only available in French).", "description": "Strategy board game similar to chess which allows grandiose moves (only available in French).",
"link": "https://carolo.org/", "link": "https://carolo.theoludwig.fr/",
"image": "/images/portfolio/Carolo.png" "image": "/images/portfolio/Carolo.png"
}, },
{ {

View File

@ -18,7 +18,7 @@
}, },
{ {
"title": "Enthousiaste de l'Open-Source", "title": "Enthousiaste de l'Open-Source",
"description": "J'apprécie le <strong>partage des connaissances et la collaboration</strong> pour résoudre des défis collectivement. <br /> Le code source du site est accessible sur <a class='text-yellow dark:text-yellow-dark hover:underline font-semibold' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>.", "description": "J'apprécie le <strong>partage des connaissances et la collaboration</strong> pour résoudre des défis collectivement. <br /> Le code source du site est accessible sur <a class='text-primary dark:text-primary-dark hover:underline font-semibold' href='https://github.com/theoludwig/theoludwig' target='_blank' rel='noopener noreferrer'>GitHub</a>.",
"id": "open-source" "id": "open-source"
} }
] ]
@ -34,7 +34,7 @@
{ {
"title": "Carolo", "title": "Carolo",
"description": "Jeu de plateau stratégique similaire aux échecs qui permet des coups grandioses, reposant sur des enchaînements remarquables.", "description": "Jeu de plateau stratégique similaire aux échecs qui permet des coups grandioses, reposant sur des enchaînements remarquables.",
"link": "https://carolo.org/", "link": "https://carolo.theoludwig.fr/",
"image": "/images/portfolio/Carolo.png" "image": "/images/portfolio/Carolo.png"
}, },
{ {

View File

@ -14,7 +14,7 @@ const tailwindConfig = {
DEFAULT: "#333333", DEFAULT: "#333333",
dark: "#b7c0c9", dark: "#b7c0c9",
}, },
yellow: { primary: {
DEFAULT: "#006cff", DEFAULT: "#006cff",
dark: "#00aeff", dark: "#00aeff",
}, },

8
utils/getVersion.ts Normal file
View File

@ -0,0 +1,8 @@
export const getVersion = async (): Promise<string> => {
if (process.env.NODE_ENV === "development") {
return "0.0.0-development"
}
const { readPackage } = await import("read-pkg")
const { version } = await readPackage()
return version
}