1
1
mirror of https://github.com/theoludwig/theoludwig.git synced 2025-05-29 22:37:44 +02:00

feat: components structure Curriculum Vitae

This commit is contained in:
2024-07-31 22:27:51 +02:00
parent b4611e4a7f
commit a596d1c443
20 changed files with 891 additions and 38 deletions

View File

@ -4,6 +4,7 @@
"private": true,
"type": "module",
"exports": {
"./CurriculumVitae": "./src/CurriculumVitae/CurriculumVitae.tsx",
"./Design/Button": "./src/Design/Button/Button.tsx",
"./Design/Link": "./src/Design/Link/Link.tsx",
"./Design/Spinner": "./src/Design/Spinner/Spinner.tsx",

View File

@ -0,0 +1,16 @@
import type { Meta, StoryObj } from "@storybook/react"
import { CurriculumVitae as CurriculumVitaeComponent } from "./CurriculumVitae"
const meta = {
title: "Curriculum Vitae/CurriculumVitae",
component: CurriculumVitaeComponent,
} satisfies Meta<typeof CurriculumVitaeComponent>
export default meta
type Story = StoryObj<typeof meta>
export const CurriculumVitae: Story = {
args: {},
}

View File

@ -0,0 +1,40 @@
import { CurriculumVitaeAbout } from "./CurriculumVitaeAbout"
import { CurriculumVitaeEducation } from "./CurriculumVitaeEducation"
import { CurriculumVitaeInterests } from "./CurriculumVitaeInterests"
import { CurriculumVitaeProfile } from "./CurriculumVitaeProfile"
import { CurriculumVitaeSkills } from "./CurriculumVitaeSkills"
import { CurriculumVitaeWork } from "./CurriculumVitaeWork"
export interface CurriculumVitaeProps {}
export const CurriculumVitae: React.FC<CurriculumVitaeProps> = () => {
return (
<main className="curriculum-vitae container-fluid">
<div className="row main clearfix">
<section className="col-md-3 card-wrapper profile-card-wrapper affix">
<CurriculumVitaeProfile />
<div className="card background-card">
<div className="background-details">
<CurriculumVitaeAbout />
<hr />
<section className="section-separated">
<CurriculumVitaeEducation />
<CurriculumVitaeSkills />
</section>
<hr />
<section className="section-separated">
<CurriculumVitaeWork />
<CurriculumVitaeInterests />
</section>
</div>
</div>
</section>
</div>
</main>
)
}

View File

@ -0,0 +1,19 @@
import { useTranslations } from "next-intl"
import { FaUser } from "react-icons/fa"
import { CurriculumVitaeSection } from "./CurriculumVitaeSection"
export interface CurriculumVitaeAboutProps {}
export const CurriculumVitaeAbout: React.FC<CurriculumVitaeAboutProps> = () => {
const t = useTranslations()
return (
<CurriculumVitaeSection
id="about"
title={t("curriculum-vitae.about.title")}
icon={<FaUser size={24} />}
>
<p>{t.rich("curriculum-vitae.about.description")}</p>
</CurriculumVitaeSection>
)
}

View File

@ -0,0 +1,21 @@
import { useTranslations } from "next-intl"
import { FaGraduationCap } from "react-icons/fa"
import { CurriculumVitaeSection } from "./CurriculumVitaeSection"
export interface CurriculumVitaeEducationProps {}
export const CurriculumVitaeEducation: React.FC<
CurriculumVitaeEducationProps
> = () => {
const t = useTranslations()
return (
<CurriculumVitaeSection
id="education"
title={t("curriculum-vitae.education.title")}
icon={<FaGraduationCap size={24} />}
>
<p>Test</p>
</CurriculumVitaeSection>
)
}

View File

@ -0,0 +1,21 @@
import { useTranslations } from "next-intl"
import { FaHeart } from "react-icons/fa"
import { CurriculumVitaeSection } from "./CurriculumVitaeSection"
export interface CurriculumVitaeInterestsProps {}
export const CurriculumVitaeInterests: React.FC<
CurriculumVitaeInterestsProps
> = () => {
const t = useTranslations()
return (
<CurriculumVitaeSection
id="interests"
title={t("home.interests.title")}
icon={<FaHeart size={24} />}
>
<p>Test</p>
</CurriculumVitaeSection>
)
}

View File

@ -0,0 +1,55 @@
import { Link } from "@repo/i18n/navigation"
import { useTranslations } from "next-intl"
import Image from "next/image"
import { BirthDate } from "../Home/About/AboutList/BirthDate"
export interface CurriculumVitaeProfileProps {}
export const CurriculumVitaeProfile: React.FC<
CurriculumVitaeProfileProps
> = () => {
const t = useTranslations()
return (
<div className="card profile-card">
<div className="profile-pic-container">
<div className="profile-pic">
<Image
className="media-object img-circle center-block"
alt={t("meta.title")}
src="/images/logo_background.webp"
width={800}
height={800}
/>
</div>
<div className="name-and-profession text-center">
<h3>
<strong>{t("meta.title")}</strong>
</h3>
<h5 className="text-muted">{t("curriculum-vitae.description")}</h5>
<h5 className="text-muted">
<BirthDate />
</h5>
<h5 className="text-muted">{t("home.about.nationality.value")}</h5>
</div>
</div>
<div className="contact-details clearfix">
<div className="detail">
<span className="info">
<a className="link-disguise" href="mailto:contact@theoludwig.fr">
contact@theoludwig.fr
</a>
</span>
</div>
<div className="detail">
<span className="info">
<Link className="link-disguise" href="/">
https://theoludwig.fr/
</Link>
</span>
</div>
</div>
<hr />
</div>
)
}

View File

@ -0,0 +1,23 @@
export interface CurriculumVitaeSectionProps extends React.PropsWithChildren {
id: string
icon: React.ReactNode
title: string
}
export const CurriculumVitaeSection: React.FC<CurriculumVitaeSectionProps> = (
props,
) => {
const { id, icon, title, children } = props
return (
<section className="detail" id={id}>
<div className="icon">{icon}</div>
<div className="info">
<h4 className="title text-uppercase">{title}</h4>
<div className="content">{children}</div>
</div>
</section>
)
}

View File

@ -0,0 +1,21 @@
import { useTranslations } from "next-intl"
import { FaToolbox } from "react-icons/fa"
import { CurriculumVitaeSection } from "./CurriculumVitaeSection"
export interface CurriculumVitaeSkillsProps {}
export const CurriculumVitaeSkills: React.FC<
CurriculumVitaeSkillsProps
> = () => {
const t = useTranslations()
return (
<CurriculumVitaeSection
id="skills"
title={t("home.skills.title")}
icon={<FaToolbox size={24} />}
>
<p>Test</p>
</CurriculumVitaeSection>
)
}

View File

@ -0,0 +1,19 @@
import { useTranslations } from "next-intl"
import { MdWork } from "react-icons/md"
import { CurriculumVitaeSection } from "./CurriculumVitaeSection"
export interface CurriculumVitaeWorkProps {}
export const CurriculumVitaeWork: React.FC<CurriculumVitaeWorkProps> = () => {
const t = useTranslations()
return (
<CurriculumVitaeSection
id="work-experience"
title={t("curriculum-vitae.work.title")}
icon={<MdWork size={24} />}
>
<p>Test</p>
</CurriculumVitaeSection>
)
}

View File

@ -1,6 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react"
import { expect, fn, userEvent, within } from "@storybook/test"
import { FaCheck } from "react-icons/fa6"
import { FaCheck } from "react-icons/fa"
import type { ButtonLinkProps } from "./Button"
import { Button } from "./Button"

View File

@ -1,6 +1,6 @@
export interface AboutItemProps {
label: string
value: string
value: React.ReactNode
link?: string
}

View File

@ -1,27 +0,0 @@
"use client"
import { BIRTH_DATE } from "@repo/utils/constants"
import { getAge, getISODate } from "@repo/utils/dates"
import { useTranslations } from "next-intl"
import { useMemo } from "react"
import { AboutItem } from "./AboutItem"
export interface AboutItemBirthDateProps {}
export const AboutItemBirthDate: React.FC<AboutItemBirthDateProps> = () => {
const t = useTranslations()
const age = useMemo(() => {
return getAge(BIRTH_DATE)
}, [])
return (
<AboutItem
label={t("home.about.birth-date.label")}
value={t("home.about.birth-date.value", {
age,
birthDate: getISODate(BIRTH_DATE),
})}
/>
)
}

View File

@ -1,6 +1,6 @@
import { useTranslations } from "next-intl"
import { AboutItem } from "./AboutItem"
import { AboutItemBirthDate } from "./AboutItemBirthDate"
import { BirthDate } from "./BirthDate"
export interface AboutListProps {}
@ -13,7 +13,10 @@ export const AboutList: React.FC<AboutListProps> = () => {
label={t("home.about.pronouns.label")}
value={t("home.about.pronouns.value")}
/>
<AboutItemBirthDate />
<AboutItem
label={t("home.about.birth-date.label")}
value={<BirthDate />}
/>
<AboutItem
label={t("home.about.nationality.label")}
value={t("home.about.nationality.value")}

View File

@ -0,0 +1,21 @@
"use client"
import { BIRTH_DATE, BIRTH_DATE_STRING } from "@repo/utils/constants"
import { getAge } from "@repo/utils/dates"
import { useTranslations } from "next-intl"
import { useMemo } from "react"
export interface BirthDateProps {}
export const BirthDate: React.FC<BirthDateProps> = () => {
const t = useTranslations()
const age = useMemo(() => {
return getAge(BIRTH_DATE)
}, [])
return t("home.about.birth-date.value", {
age,
birthDate: BIRTH_DATE_STRING,
})
}