First Commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import H2 from "@/components/lib/layout/H2";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
|
||||
export default function AboutSection() {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full max-w-full xl:max-w-[50vw]">
|
||||
<H2 className="leading-snug">About Me</H2>
|
||||
<Span>
|
||||
I'm passionate and dedicated to solving problems using the
|
||||
best technologies available.
|
||||
</Span>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import Card from "@/components/lib/elements/Card";
|
||||
import H2 from "@/components/lib/layout/H2";
|
||||
import H3 from "@/components/lib/layout/H3";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { skills } from "../(data)/skills";
|
||||
import React from "react";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
|
||||
type Props = {
|
||||
noTitle?: boolean;
|
||||
expand?: boolean;
|
||||
};
|
||||
|
||||
export default function MySkillsSection({ noTitle, expand }: Props) {
|
||||
const [category, setCategory] =
|
||||
React.useState<keyof typeof skills>("Devops");
|
||||
const categories = Object.keys(skills) as (keyof typeof skills)[];
|
||||
|
||||
if (expand) {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full">
|
||||
{!noTitle && (
|
||||
<React.Fragment>
|
||||
<H2 className="leading-snug m-0">My Skills</H2>
|
||||
<Span>
|
||||
A summary of the vast array of tools I've
|
||||
mastered over the years
|
||||
</Span>
|
||||
<Divider className="opacity-0 my-2" />
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
<Stack className="items-stretch gap-20 flex-row xl:flex-col flex-wrap md:flex-nowrap">
|
||||
{categories.map((ctgr, i) => {
|
||||
return (
|
||||
<Stack key={i}>
|
||||
<Stack className="gap-6">
|
||||
<Stack className="gap-2">
|
||||
<H3 className="m-0 text-lg">
|
||||
{ctgr}
|
||||
</H3>
|
||||
<Span className="text-sm !leading-5">
|
||||
{skills[ctgr].description}
|
||||
</Span>
|
||||
</Stack>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 w-full">
|
||||
{skills[ctgr].portfolio.map(
|
||||
(portfolio, index) => {
|
||||
return (
|
||||
<MySkillsCard
|
||||
portfolio={
|
||||
portfolio
|
||||
}
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full">
|
||||
{!noTitle && (
|
||||
<React.Fragment>
|
||||
<H2 className="leading-snug m-0">My Skills</H2>
|
||||
<Span>
|
||||
A summary of the vast array of tools I've mastered
|
||||
over the years
|
||||
</Span>
|
||||
<Divider className="opacity-0 my-2" />
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
<Row className="flex-nowrap items-start gap-x-10 flex-col xl:flex-row gap-y-10">
|
||||
<Stack className="xl:max-w-[200px] items-stretch gap-10 flex-row xl:flex-col flex-wrap md:flex-nowrap">
|
||||
{categories.map((ctgr, i) => {
|
||||
const isActive = category === ctgr;
|
||||
return (
|
||||
<Stack
|
||||
key={i}
|
||||
className={twMerge(
|
||||
"cursor-pointer",
|
||||
isActive
|
||||
? ""
|
||||
: "opacity-40 hover:opacity-70"
|
||||
)}
|
||||
onClick={() => setCategory(ctgr)}
|
||||
>
|
||||
<Stack className="gap-1">
|
||||
<H3 className="m-0 text-lg">{ctgr}</H3>
|
||||
<Span className="text-sm !leading-5">
|
||||
{skills[ctgr].description}
|
||||
</Span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 w-full">
|
||||
{skills[category].portfolio.map((portfolio, index) => {
|
||||
return (
|
||||
<MySkillsCard
|
||||
portfolio={portfolio}
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Row>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
export function MySkillsCard({
|
||||
portfolio,
|
||||
}: {
|
||||
portfolio: (typeof skills.Devops.portfolio)[number];
|
||||
}) {
|
||||
return (
|
||||
<Card className="grow w-full items-start">
|
||||
<Stack className="gap-4">
|
||||
<H3 className="m-0">{portfolio.title}</H3>
|
||||
<Span>{portfolio.description}</Span>
|
||||
{portfolio.technologies?.[0] && (
|
||||
<Row className="gap-4">
|
||||
{portfolio.technologies.map((tch, _i) => (
|
||||
<React.Fragment key={_i}>
|
||||
<Span className="text-sm dark:text-white/40">
|
||||
{tch}
|
||||
</Span>
|
||||
{_i < portfolio.technologies.length - 1 && (
|
||||
<Divider vertical />
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import Card from "@/components/lib/elements/Card";
|
||||
import H2 from "@/components/lib/layout/H2";
|
||||
import H3 from "@/components/lib/layout/H3";
|
||||
import Section from "@/components/lib/layout/Section";
|
||||
import Span from "@/components/lib/layout/Span";
|
||||
import Stack from "@/components/lib/layout/Stack";
|
||||
import { work } from "../(data)/work";
|
||||
import Link from "@/components/lib/layout/Link";
|
||||
import React from "react";
|
||||
import Row from "@/components/lib/layout/Row";
|
||||
import Divider from "@/components/lib/layout/Divider";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
type Props = {
|
||||
noTitle?: boolean;
|
||||
expand?: boolean;
|
||||
};
|
||||
|
||||
export default function MyWorkSection({ noTitle, expand }: Props) {
|
||||
const categories = Object.keys(work) as (keyof typeof work)[];
|
||||
const [category, setCategory] = React.useState<keyof typeof work>(
|
||||
categories[0]
|
||||
);
|
||||
|
||||
if (expand) {
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full">
|
||||
{!noTitle && (
|
||||
<React.Fragment>
|
||||
<H2 className="leading-snug m-0">My Work</H2>
|
||||
<Span>Some work I've done in the past</Span>
|
||||
<Divider className="opacity-0 my-2" />
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
<Stack className="items-stretch gap-20 flex-row xl:flex-col flex-wrap md:flex-nowrap">
|
||||
{categories.map((ctgr, i) => {
|
||||
const isActive = category === ctgr;
|
||||
return (
|
||||
<Stack key={i}>
|
||||
<Stack className="gap-6">
|
||||
<H3 className="m-0 text-lg">{ctgr}</H3>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 w-full">
|
||||
{work[ctgr].portfolio.map(
|
||||
(portfolio, index) => {
|
||||
return (
|
||||
<MyWorkPortfolioCard
|
||||
portfolio={
|
||||
portfolio
|
||||
}
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<Stack className="w-full">
|
||||
{!noTitle && (
|
||||
<React.Fragment>
|
||||
<H2 className="leading-snug m-0">My Work</H2>
|
||||
<Span>Some work I've done in the past</Span>
|
||||
<Divider className="opacity-0 my-2" />
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
<Row className="flex-nowrap items-start gap-x-14 flex-col xl:flex-row gap-y-10">
|
||||
<Stack className="xl:max-w-[200px] items-stretch gap-6 flex-row xl:flex-col flex-wrap md:flex-nowrap">
|
||||
{categories.map((ctgr, i) => {
|
||||
const isActive = category === ctgr;
|
||||
return (
|
||||
<Stack
|
||||
key={i}
|
||||
className={twMerge(
|
||||
"cursor-pointer",
|
||||
isActive
|
||||
? ""
|
||||
: "opacity-40 hover:opacity-70"
|
||||
)}
|
||||
onClick={() => setCategory(ctgr)}
|
||||
>
|
||||
<Stack className="gap-1">
|
||||
<H3 className="m-0 text-lg">{ctgr}</H3>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 w-full">
|
||||
{work[category].portfolio.map((portfolio, index) => {
|
||||
return (
|
||||
<MyWorkPortfolioCard
|
||||
portfolio={portfolio}
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Row>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
export function MyWorkPortfolioCard({
|
||||
portfolio,
|
||||
}: {
|
||||
portfolio: (typeof work.Devops.portfolio)[number];
|
||||
}) {
|
||||
return (
|
||||
<Card className="grow w-full items-start">
|
||||
<Stack className="gap-4">
|
||||
<H3 className="m-0">{portfolio.title}</H3>
|
||||
|
||||
<Link
|
||||
target="_blank"
|
||||
href={portfolio.href}
|
||||
className="text-sm text-wrap break-all border-none"
|
||||
>
|
||||
{portfolio.href}
|
||||
</Link>
|
||||
<Span>{portfolio.description}</Span>
|
||||
{portfolio.technologies?.[0] && (
|
||||
<Row className="gap-4">
|
||||
{portfolio.technologies.map((tch, _i) => (
|
||||
<React.Fragment key={_i}>
|
||||
<Span className="text-sm dark:text-white/40">
|
||||
{tch}
|
||||
</Span>
|
||||
{_i < portfolio.technologies.length - 1 && (
|
||||
<Divider vertical />
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user