diff --git a/public/jobs.json b/public/jobs.json index 9ceac57..42b2f7c 100644 --- a/public/jobs.json +++ b/public/jobs.json @@ -3,7 +3,7 @@ "name": "Czech Quests", "started": "July 2024", "ended": "today", - "description": "Custom project, where I make an addon for World of Warcraft game, which show Czech translation for in-game quests. The translations are made via AI (DeepL and GPT). Text is formated for player and quest giver gender. Keep original names of other NPCs, items or places. I also create a web application where i am able to manage translations", + "description": "Custom project, where I make an addon, for World of Warcraft game, to show Czech translation for in-game quests. The translations are made via AI (DeepL and GPT). Texts are formated for player and quest giver gender. Also it keeps original names of other NPCs, items or places. I also create a web application where i am able to manage translations", "tags": [ "Typescript", "React", @@ -63,7 +63,7 @@ "tags": [ "Typescript", "React", - "Graphql", + "GraphQL", "REST", "Mui", "Azure DevOps" diff --git a/src/app/components/AboutMe.tsx b/src/app/components/AboutMe.tsx index bc94642..eb8984c 100644 --- a/src/app/components/AboutMe.tsx +++ b/src/app/components/AboutMe.tsx @@ -1,4 +1,4 @@ -import {Card} from "../../components/Card"; +import {Kbd} from "../../components/Kbd"; export const AboutMe = () => { const age = Math.floor( @@ -13,9 +13,9 @@ export const AboutMe = () => { <>

- 👋, my name is Roman Jaroš. I am {age}. {work} years working as software engineer. + Hello, my name is Roman Jaroš. I am {age}. {work} years working as software engineer. I have been programming since I was 15 years old and still love to learn new technologies. - Outside of the programming world, I maintain servers with about 120 docker containers. + Outside of the programming world, I maintain servers with around 80 docker containers. Outside of the IT world, I enjoy reading self improvement books, meditating, alternative medicine and model painting or playing video games.

@@ -24,9 +24,11 @@ export const AboutMe = () => { I am contractor and currently only for full remote jobs.


-
- - +
+ #uidesign + #webdevelopment + #automationtesting + #devops
diff --git a/src/app/components/Contact.tsx b/src/app/components/Contact.tsx index b8087e3..8a5307c 100644 --- a/src/app/components/Contact.tsx +++ b/src/app/components/Contact.tsx @@ -1,4 +1,4 @@ -import {GithubIcon, InfoIcon, LinkedinIcon, MailIcon} from "lucide-react"; +import {GithubIcon, LinkedinIcon, MailIcon, ScrollTextIcon} from "lucide-react"; export const Contact = () => { return ( @@ -8,12 +8,19 @@ export const Contact = () => { - Send e-mail + className="flex gap-2 focus:outline-none font-medium rounded-lg px-5 py-2.5 me-2 mb-2 text-yellow-600 dark:bg-transparent"> + Hire me + + + Download CV

- + = ({jobs}) => { +export const Jobs = () => { + const {jobs, filter} = useJobs() return ( <>

    - {jobs?.filter(notNil).map(({name, started, ended, description, tags, link}, index) => ( -
  1. + {jobs + ?.filter(notNil) + .filter(({tags}) => filter != undefined ? tags.includes(filter) : true) + .map(({name, started, ended, description, tags, link}, index) => ( +
  2. -

    - {name} -

    - -

    - {description} -

    - {link != undefined && -

    - - Visit website - - +

    + {name} +

    + +

    + {description}

    - } -

    - {tags.sort().map((name) => ( - + {link != undefined && +

    + + Visit website + + +

    + } +

    + {tags.sort().map((name) => ( + {name} - ))} -

    -
  3. - ))} + ))} +

    + + ))}
diff --git a/src/app/components/Skills.tsx b/src/app/components/Skills.tsx index e4b8771..8bb5d7e 100644 --- a/src/app/components/Skills.tsx +++ b/src/app/components/Skills.tsx @@ -1,40 +1,53 @@ -import {notNil} from "../../utils"; +"use client" + +import {notNil} from "../../utils/notNil"; import {StarIcon} from "lucide-react"; import {FC} from "react"; -import {Job} from "../type"; +import {useJobs} from "../context/useJobs"; -type SkillsProps = { - jobs: Job[] | undefined -} - -export const Skills: FC = ({jobs}) => { - - const skills = new Set(jobs?.filter(notNil).flatMap(({tags}) => tags).sort()); +export const Skills: FC = () => { + const {jobs, filterJobs, filter} = useJobs() + const skills = new Set(jobs.filter(notNil).flatMap(({tags}) => tags).sort()); return ( <>
-

Czech

+

Czech, native

+ + +
-

English 

+

English, B1

+ + +
-
- {Array.from(skills)?.map((name) => ( - - {name} - - ))} +
+
+ {Array.from(skills)?.map((name) => ( + filterJobs(name)} + className={[ + "cursor-pointer text-xs font-medium me-2 px-2.5 py-0.5 rounded-full select-none", + filter === name + ? "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300" + : "bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-300" + ].join(" ")}> + {name} + + ))} +
+

Psss, you can click on pill to filter.

) diff --git a/src/app/components/Title.tsx b/src/app/components/Title.tsx index b8f4afa..781f042 100644 --- a/src/app/components/Title.tsx +++ b/src/app/components/Title.tsx @@ -1,12 +1,9 @@ export const Title = () => { return ( -
- < +

- Just - Roman + Roman Jaroš

-  />
) } \ No newline at end of file diff --git a/src/app/context/JobsContext.tsx b/src/app/context/JobsContext.tsx new file mode 100644 index 0000000..f974658 --- /dev/null +++ b/src/app/context/JobsContext.tsx @@ -0,0 +1,25 @@ +"use client" + +import {createContext, ReactNode, FC, useState, Dispatch, SetStateAction} from "react"; +import {Job} from "../type"; + +type JobsContextPayload = { + data: Job[] + filter?: string + setFilter: Dispatch> +} | undefined + +export const JobsContext = createContext(undefined); + +type JobsContextProviderProps = { + jobs: Job[] + children: ReactNode[] +} + +export const JobsProvider: FC = ({children, jobs: data}) => { + const [filter, setFilter] = useState() + + return ( + {children} + ) +} \ No newline at end of file diff --git a/src/app/context/useJobs.ts b/src/app/context/useJobs.ts new file mode 100644 index 0000000..c4b27b9 --- /dev/null +++ b/src/app/context/useJobs.ts @@ -0,0 +1,25 @@ +"use client" + +import {useContext} from "react"; +import {JobsContext} from "./JobsContext"; + +export const useJobs = () => { + const context = useContext(JobsContext) + if (!context) { + throw new Error('useJobs must be used within a JobsProvider!'); + } + + const handleFilterJob = (name: string) => { + if (name === context.filter) { + context.setFilter(undefined) + } else { + context.setFilter(name) + } + } + + return { + jobs: context.data, + filter: context?.filter, + filterJobs: handleFilterJob, + } +} \ No newline at end of file diff --git a/src/app/fetch.ts b/src/app/fetch.ts new file mode 100644 index 0000000..b3343d9 --- /dev/null +++ b/src/app/fetch.ts @@ -0,0 +1,6 @@ +import {Job} from "./type"; + +export const fetchJobs = async (): Promise => { + const res = await fetch(`${process.env.NEXT_PUBLIC_SITE_URL}/jobs.json`, {cache: "no-store"}) + return await res?.json(); +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5669178..c744b8a 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -8,13 +8,16 @@ export default function AppLayout({ }) { return ( - - - - - -
{children}
- - - ) + + + Roman Jaroš + + + + +
{children}
+ + + ) } \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 4af9bd5..0282764 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,21 +4,24 @@ import {Contact} from "./components/Contact"; import {Footer} from "./components/Footer"; import {Jobs} from "./components/Jobs"; import {Skills} from "./components/Skills"; -import {Job} from "./type"; +import {fetchJobs} from "./fetch"; +import {JobsProvider} from "./context/JobsContext"; +import {use} from "react"; -export default async function Page() { +export default function Page() { - const res = await fetch(`${process.env.NEXT_PUBLIC_SITE_URL}/jobs.json`, {cache: "no-store"}) - const data: Job[] | undefined = await res?.json(); + const jobs = use(fetchJobs()) return ( <> -
+
<AboutMe /> <Contact /> - <Skills jobs={data} /> - <Jobs jobs={data} /> + <JobsProvider jobs={jobs ?? []}> + <Skills /> + <Jobs /> + </JobsProvider> <Footer /> </div> </> diff --git a/src/components/Card.tsx b/src/components/Card.tsx deleted file mode 100644 index b436f24..0000000 --- a/src/components/Card.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import {FC} from "react"; - -type CardProps = { - title: string; - description: string; -} - -export const Card: FC<CardProps> = ({title, description}) => { - return ( - <div - className="w-full md:w-80 block p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700" - > - <h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">{title}</h5> - <p className="font-normal text-gray-700 dark:text-gray-400">{description}</p> - </div> - ) -} \ No newline at end of file diff --git a/src/components/Kbd.tsx b/src/components/Kbd.tsx new file mode 100644 index 0000000..4a93b45 --- /dev/null +++ b/src/components/Kbd.tsx @@ -0,0 +1,14 @@ +import {FC} from "react"; + +type KbdProps = { + children: string +} + +export const Kbd: FC<KbdProps> = ({children}) => { + return ( + <kbd + className="px-2 py-1.5 text-xs font-semibold text-gray-800 bg-gray-100 border border-gray-200 rounded-lg dark:bg-gray-600 dark:text-gray-100 dark:border-gray-500"> + {children} + </kbd> + ) +} \ No newline at end of file diff --git a/src/utils.ts b/src/utils/notNil.ts similarity index 100% rename from src/utils.ts rename to src/utils/notNil.ts