JSON과 React에 이력서를 직접 써요.

69595 단어 ReactJSON이력서tech

요약


이력서용 데이터를 JSON 형식으로 기술하고 리액트로 페이지를 만든다.나는 PDF 형식으로 그것을 저장했다.
데이터는 Giithub에서 관리하므로 손실에 대한 걱정은 없습니다.

성과물


이름과 주소는 모두 마스크지만 이런 이력서를 작성했다.

기술을 사용하다

  • React
  • Chakra UI
  • TypeScript
  • 계기.


    이력서의 데이터 관리, 일본어에 대응하는 예쁜 디자인 이력서가 부족하고 개인 정보 전달의 불안이 자신이 창작한 계기이다.
    자세히 보면 우선 이력서를 쓰려던 곳은 과거 이력서의 데이터를 찾지 못했다.
    그리고 예쁜 이력서 템플릿을 찾으려면 영어 요약만 찾았어요.문제는 다음과 같습니다.
  • 프로젝트 이름은 영어로 고정되며 일본어로 변경할 수 없음
  • 많은 항목이 고정되어 있어 끈에 짧고 긴 인상을 준다
  • 양식만 작성하면 이력서를 예쁘게 쓸 수 있는 서비스가 있지만 이력서에 개인정보를 제공하는 것은 어색하다
  • 한편, 일본어로 살짝 검색해보면 의무교육 이력이 많이 적혀 있어 눈길을 끈다.
    종목과 스킬 세트를 강조하는 형식과는 반대로 이번 요구와는 다르다.
    따라서 Giithub을 통해 비공식적으로 데이터를 쉽게 관리하여 보기와 데이터를 분리하여 디자인의 자유를 변경하고 프로젝트 등에서도 유연하게 조정할 수 있도록 하는 자제개요를 가지게 한다.
    실제로 고민하며 찾기보다는 스스로 손을 써서 (반나절 정도) 더 빨리 완성하는 것이 낫다.

    코드


    설계는 2열의 A4를 통해 1장의 양으로 조정한다.
    다른 파일 정의 유형을 읽고 Chakra UI의 구성 요소를 사용하며 사용자 정의 구성 요소의 일부를 정의하여 설계를 조정하여 중복 설명량을 줄입니다.이렇게 되면 코드의 전망은 일목요연하게 된다.
    그렇긴 하지만 원래 코드량이 적어서 기본적으로 앱이다.tsx에 집중하다.
    데이터는 로컬 json 파일에서 읽습니다.
    코드 전체 텍스트
    App.tsx
    import {WorkType, EducationType, NaturalLanguageType, ProjectType } from './types/index';
    import { Box, Divider, Flex, Tag, Text, Heading, VStack, ListItem, UnorderedList } from "@chakra-ui/react"
    import { AtSignIcon, CalendarIcon, EmailIcon, PhoneIcon, LinkIcon } from '@chakra-ui/icons'
    import StarRating from 'react-svg-star-rating'
    import data from './data/resume.json'
    import {H3, H4, TimeSpan } from './components/index';
    
    function App() {
      const {name, label, email, phone, website, address} = data.basics;
    
      const summary:string = data.summary;
      const works:WorkType[] = data.work;
      const educations:EducationType[] = data.education;
      const programingLanguages:string[] = data.programming_language;
      const naturalLanguages:NaturalLanguageType[] = data.natural_language;
      const techStacks:string[] = data.skill_stack;
      const personalProjects:ProjectType[] = data.project;
      const qualifications:string[] = data.qualification;
    
      return (
        <Box margin="5">
          <header>
            <Heading as="h2" fontSize="4xl" letterSpacing="wider">{name}</Heading>
            <Flex flexWrap="wrap" alignItems="center" spacing={3} marginY="3" justifyContent="space-between">
              <Box flex="1 1 auto">
              <Text fontWeight="semibold">
               <EmailIcon color="#992214" /> {email}
              </Text>
              </Box>
              <Box flex="1 1 auto">
              <Text fontWeight="semibold">
               <PhoneIcon color="#992214" /> { phone }
              </Text>
              </Box>
              <Box flex="1 1 auto">
              <Text fontWeight="semibold">
               <LinkIcon color="#992214" /> {website}
              </Text>
              </Box>
              <Box flex="1 1 auto">
              <Text fontWeight="semibold">
                <AtSignIcon color="#992214" />{address}
              </Text>
              </Box>
            </Flex>
          </header>
          <Box marginY="7">
            <H3 content="サマリー"></H3>
            <Text>{summary}</Text>
          </Box>
          <Flex>
            <VStack>
              <Box>
                <H3 content="職歴"></H3>
                <Divider />
                { works.map(({company, position, website, startDate, endDate, summary, highlights}) => (
                  <>
                    <H4 content={company}></H4>
                    <Text fontSize="md">{position}</Text>
                    <TimeSpan startDate={startDate} endDate={endDate} />
                    <Text marginY="3">{summary}</Text>
                    <UnorderedList>
                      {highlights.map((highlight) => (
                        <ListItem fontSize="sm">{highlight}</ListItem>
                      ))}
                    </UnorderedList>
                  </>
                ))}
              </Box>
              <Box>
                <H3 content="学歴"></H3>
                <Divider />
                { educations.map(({institution, area, startDate, endDate}) => (
                  <>
                    <H4 content={institution}></H4>
                    <Text fontSize="md">{area}</Text>
                    <TimeSpan startDate={startDate} endDate={endDate} />
                  </>
                ))}
              </Box>
              <Box>
                <H3 content="プログラミング言語"></H3>
                <Divider />
                { programingLanguages.map((language) => (
                  <Tag margin="0.5" >
                    { language }
                  </Tag>
                ))}
              </Box>
              <Box>
                <H3 content="資格"></H3>
                <Divider />
                { qualifications.map((qualification) => (
                  <Tag margin="0.5" >
                    { qualification }
                  </Tag>
                ))}
              </Box>
            </VStack>
            <Box w="3rem"></Box>
            <VStack>
              <Box>
                <H3 content="プロジェクト"></H3>
                <Divider />
                { personalProjects.map(({heading, summary, highlights}) => (
                  <>
                    <H4 content={heading}></H4>
                    <Text fontSize="md" marginBottom="3">{summary}</Text>
                    <UnorderedList>
                      {highlights.map((highlight) => (
                        <ListItem fontSize="sm">{highlight}</ListItem>
                      ))}
                    </UnorderedList>
                  </>
                ))}
              </Box>
              <Box>
                <H3 content="技術スタック"></H3>
                <Divider />
                { techStacks.map((stack) => (
                  <Tag margin="0.5" >
                    { stack }
                  </Tag>
                ))}
              </Box>
              <Box w="100%">
                <H3 content="言語"></H3>
                <Divider />
                { naturalLanguages.map(({language, fluency, points}) => (
                  <Flex justifyContent="space-between">
                    <Text fontSize="md">{language}</Text>
                    <Text>{fluency} <StarRating
                      unit="float"
                      activeColor={"#9AE6B4"}
                      initialRating={points}
                      size={15}
                    /></Text>
                  </Flex>
                ))}
              </Box>
            </VStack>
          </Flex>
        </Box>
      );
    }
    
    export default App;
    
    components.tsx
    import { Text, Heading } from "@chakra-ui/react"
    import { CalendarIcon } from '@chakra-ui/icons'
    
    export const H3 = ({content}: any) => {
        return <Heading as="h3" fontSize="3xl">{content}</Heading>
    }
    
    export const H4 = ({content}: any) => {
        return <Heading as="h4" fontSize="xl" fontWeight="semibold" marginTop="4" marginBottom="1">{content}</Heading>
    }
    
    
    type TimeSpanProps = {
        startDate: string,
        endDate: string
    }
    
    export const TimeSpan: React.VFC<TimeSpanProps> = ({startDate, endDate}) => {
        return <Text fontSize="sm"><CalendarIcon color="#992214" /> {startDate}~{endDate}</Text>
    }
    
    index.tsx
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { ChakraProvider } from "@chakra-ui/react"
    import { extendTheme } from "@chakra-ui/react"
    
    const theme = extendTheme({
      styles: {
        global: {
          svg: {
            display: "unset",
          }
        },
      },
      components: {
        Heading: {
          baseStyle: {
            color: "#159957"
          },
        },
        Text: {
          baseStyle: {
            color: "#384347"
          }
        }
      },
    })
    
    ReactDOM.render(
      <ChakraProvider theme={theme}>
        <App />
      </ChakraProvider>,
      document.getElementById('root')
    );
    
    types.ts
    export type WorkType = {
      company: string,
      position: string,
      website: string,
      startDate: string,
      endDate: string,
      summary: string,
      highlights: string[]
    }
    
    export type EducationType = {
      institution: string,
      area: string,
      startDate: string,
      endDate: string,
    }
    
    export type ProjectType = {
      heading: string,
      summary: string,
      highlights: string[]
    }
    
    export type NaturalLanguageType = {
      language: string,
      fluency: string,
      points: number,
    }
    

    겸사겸사 말씀드리겠습니다.


    리액트로 PDF를 만들 수 있는 프로그램 라이브러리와 리액트 파일을 PDF로 변환할 수 있는 프로그램 라이브러리가 있지만 이번에는 채택되지 않았다.
    전자는 일반적으로 React로 페이지를 만들고 PDF로 출력하면 되기 때문에 이번에는 학습 비용을 들일 가치가 없다고 판단했다.
    후자는 명령행에서 PDF로 전환할 수 있는 것은 매력적이지만 이력서를 PDF로 전환할 기회가 잦지 않기 때문에 페이지에서 수동으로 PDF로 전환하면 충분하다고 본다.

    최후


    이력서에 부족한 항목과 경험이 있다면 지적해 주시기 바랍니다.

    좋은 웹페이지 즐겨찾기