This commit is contained in:
geoffsee
2025-05-22 23:14:01 -04:00
commit 33679583af
242 changed files with 15090 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
import React, { useCallback, useMemo } from "react";
import { Box, Flex, useMediaQuery } from "@chakra-ui/react";
import { resumeData } from "../../static-data/resume_data";
import SectionContent from "./SectionContent";
import SectionButton from "./SectionButton";
const sections = ["professionalSummary", "skills", "experience", "education"];
export default function ResumeComponent() {
const [activeSection, setActiveSection] = React.useState(
"professionalSummary",
);
const [isMobile] = useMediaQuery("(max-width: 1243px)");
const handleSectionClick = useCallback((section) => {
setActiveSection(section);
}, []);
const capitalizeFirstLetter = useCallback((word) => {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
}, []);
const sectionButtons = useMemo(
() =>
sections.map((section) => (
<SectionButton
key={section}
onClick={() => handleSectionClick(section)}
activeSection={activeSection}
section={section}
mobile={isMobile}
callbackfn={capitalizeFirstLetter}
/>
)),
[activeSection, isMobile, handleSectionClick, capitalizeFirstLetter],
);
return (
<Box p={"unset"}>
<Flex
direction={isMobile ? "column" : "row"}
mb={8}
wrap="nowrap"
gap={isMobile ? 2 : 4}
minWidth="0"
>
{sectionButtons}
</Flex>
<Box
bg="background.secondary"
color="text.primary"
borderRadius="md"
boxShadow="md"
borderWidth={1}
borderColor="brand.300"
minHeight="300px"
>
<SectionContent activeSection={activeSection} resumeData={resumeData} />
</Box>
</Box>
);
}

View File

@@ -0,0 +1,32 @@
import React from "react";
import { Button } from "@chakra-ui/react";
import { ChevronRight } from "lucide-react";
function SectionButton(props: {
onClick: () => void;
activeSection: string;
section: string;
mobile: boolean;
callbackfn: (word) => string;
}) {
return (
<Button
mt={1}
onClick={props.onClick}
variant={props.activeSection === props.section ? "solid" : "outline"}
colorScheme="brand"
rightIcon={<ChevronRight size={16} />}
size="md"
width={props.mobile ? "100%" : "auto"}
>
{props.section
.replace(/([A-Z])/g, " $1")
.trim()
.split(" ")
.map(props.callbackfn)
.join(" ")}
</Button>
);
}
export default SectionButton;

View File

@@ -0,0 +1,98 @@
import React from "react";
import {
Box,
Grid,
GridItem,
Heading,
ListItem,
Text,
UnorderedList,
VStack,
} from "@chakra-ui/react";
const fontSize = "md";
const ProfessionalSummary = ({ professionalSummary }) => (
<Box>
<Grid
templateColumns="1fr"
gap={4}
maxW={["100%", "100%", "100%"]}
mx="auto"
className="about-container"
>
<GridItem
colSpan={1}
maxW={["100%", "100%", "container.md"]}
justifySelf="center"
minH={"100%"}
>
<Grid templateColumns="1fr" gap={4} overflowY={"auto"}>
<GridItem>
<Text fontSize="md">{professionalSummary}</Text>
</GridItem>
</Grid>
</GridItem>
</Grid>
</Box>
);
const Skills = ({ skills }) => (
<VStack align={"baseline"} spacing={6} mb={4}>
<UnorderedList spacing={2} mb={0}>
<Box>
{skills?.map((skill, index) => (
<ListItem p={1} key={index}>
{skill}
</ListItem>
))}
</Box>
</UnorderedList>
</VStack>
);
const Experience = ({ experience }) => (
<VStack align="start" spacing={6} mb={4}>
{experience?.map((job, index) => (
<Box key={index} width="100%">
<Heading as="h3" size="md" mb={2}>
{job.title}
</Heading>
<Text fontWeight="bold">{job.company}</Text>
<Text color="gray.500" mb={2}>
{job.timeline}
</Text>
<Text>{job.description}</Text>
</Box>
))}
</VStack>
);
const Education = ({ education }) => (
<UnorderedList spacing={2} mb={4}>
{education?.map((edu, index) => <ListItem key={index}>{edu}</ListItem>)}
</UnorderedList>
);
const SectionContent = ({ activeSection, resumeData }) => {
const components = {
professionalSummary: ProfessionalSummary,
skills: Skills,
experience: Experience,
education: Education,
};
const ActiveComponent = components[activeSection];
return (
<Box p={4} minHeight="300px" width="100%">
{ActiveComponent ? (
<ActiveComponent {...resumeData} />
) : (
<Text>Select a section to view details.</Text>
)}
</Box>
);
};
export default SectionContent;