Skip to content

Commit

Permalink
Merge pull request #10 from martapanc/feat/home
Browse files Browse the repository at this point in the history
Feat/home
  • Loading branch information
martapanc committed Aug 15, 2023
2 parents 743bdfa + 8cdbf1d commit c3ce299
Show file tree
Hide file tree
Showing 18 changed files with 471 additions and 5 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@
"react-dom": "^18.2.0",
"react-headroom": "^3.2.1",
"react-icons": "^4.10.1",
"react-syntax-highlighter": "^15.5.0",
"react-tippy": "^1.4.0",
"sanity": "^3.0.0",
"sanity-plugin-internationalized-array": "^1.7.0",
"sanity-plugin-media": "^2.2.1",
"styled-components": "^5.2.0",
"tailwind-merge": "^1.12.0"
"tailwind-merge": "^1.12.0",
"typed.js": "^2.0.16"
},
"devDependencies": {
"@commitlint/cli": "^16.3.0",
Expand All @@ -72,6 +74,7 @@
"@testing-library/react": "^13.4.0",
"@types/react": "^18.2.7",
"@types/react-headroom": "^3.2.0",
"@types/react-syntax-highlighter": "^15.5.7",
"@typescript-eslint/eslint-plugin": "^5.59.7",
"@typescript-eslint/parser": "^5.59.7",
"autoprefixer": "^10.4.14",
Expand Down
10 changes: 9 additions & 1 deletion sanity/deskStructure.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const freeTimeSection = [
'tvSeries',
'videoGame',
];
const sharedSection = ['shortText', 'skillIcon'];
const sharedSection = ['codeSnippet', 'shortText', 'skillIcon'];

export const customStructure = (S) =>
S.list()
Expand Down Expand Up @@ -39,4 +39,12 @@ export const customStructure = (S) =>
sharedSection.map((section) => S.documentTypeListItem(section))
)
),
S.listItem()
.title('Single Pages')
.child(
S.editor()
.id('homeContent')
.schemaType('homeContent')
.documentId('homeContent')
),
]);
4 changes: 4 additions & 0 deletions sanity/schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { type SchemaTypeDefinition } from 'sanity';

import codeSnippet from '@/schemas/codeSnippet';
import homeContent from '@/schemas/homeContent';
import randomFact from '@/schemas/randomFact';

import book from '../src/schemas/book';
Expand All @@ -17,6 +19,8 @@ import videoGame from '../src/schemas/videoGame';
export const schema: { types: SchemaTypeDefinition[] } = {
types: [
book,
codeSnippet,
homeContent,
job,
language,
podcast,
Expand Down
28 changes: 26 additions & 2 deletions src/app/(public)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
import * as React from 'react';

import Intro from '@/components/organisms/home/Intro';
import Summary from '@/components/organisms/home/Summary';
import Seo from '@/components/Seo';

import { codeSnippetsQuery } from '@/queries/codeSnippets';

import { sanityClient } from '../../../sanity/lib/client';

import { CodeSnippet } from '@/types/CodeSnippet';

const getData = async () => {
// const homeData: HomeContent[] = await sanityClient.fetch(homeContentQuery);
const codeSnippets: CodeSnippet[] = await sanityClient.fetch(
codeSnippetsQuery
);

return {
codeSnippets,
// homeContent: homeData[0],
};
};

const HomePage = async () => {
const { codeSnippets } = await getData();

return (
<main className='min-h-main'>
<Seo templateTitle='Home' />

<section className='dark:bg-dark bg-white'>
<div className='layout relative flex flex-col items-center justify-center py-12 text-center'>
Homepage :)
<div className='layout relative flex flex-col py-16 md:py-24'>
<Intro codeSnippets={codeSnippets} />

<Summary />
</div>
</section>
</main>
Expand Down
81 changes: 81 additions & 0 deletions src/components/organisms/home/Code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use client';

import { useTheme } from 'next-themes';
import React, { useEffect, useState } from 'react';
import SyntaxHighlighter from 'react-syntax-highlighter';
import {
atomOneLight,
darcula,
} from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import Typed, { TypedOptions } from 'typed.js';

import { CodeSnippet } from '@/types/CodeSnippet';

export interface CodeSnippetsProps {
codeSnippets: CodeSnippet[];
}

const Code = ({ codeSnippets }: CodeSnippetsProps) => {
const [loading, setLoading] = useState(true);

const { theme } = useTheme();

const ideStyle = theme === 'dark' ? darcula : atomOneLight;

useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 2000);
}, []);

useEffect(() => {
if (!loading) {
const typedStringsElement = document.getElementById('typed-strings');
const typedElement = document.getElementById('typed');

if (typedStringsElement && typedElement) {
const typedOptions: TypedOptions = {
stringsElement: '#typed-strings',
typeSpeed: 40,
backSpeed: 10,
backDelay: 5000,
loop: true,
loopCount: 0,
smartBackspace: true,
showCursor: true,
cursorChar: '_',
};

const typed = new Typed(typedElement, typedOptions);

// Clean up the Typed.js instance when the component unmounts
return () => {
typed.destroy();
};
}
}
}, [loading]);

return (
<div className='me-4 h-56 w-full rounded border-double bg-slate-200 px-4 py-6 dark:bg-slate-800 md:h-[280px] md:w-1/2'>
<div id='typed-strings'>
{loading ? <span className='cursor-blink'>_</span> : null}
{!loading &&
codeSnippets.map((snippet) => (
<SyntaxHighlighter
className='text-xs md:text-base'
key={snippet._id}
language={snippet.language}
style={ideStyle}
wrapLongLines={true}
>
{snippet.code}
</SyntaxHighlighter>
))}
</div>
<span id='typed'></span>
</div>
);
};

export default Code;
22 changes: 22 additions & 0 deletions src/components/organisms/home/Intro.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import { shuffleArray } from '@/lib/helper';

import Code, { CodeSnippetsProps } from '@/components/organisms/home/Code';
import Photo from '@/components/organisms/home/Photo';

const Intro = ({ codeSnippets }: CodeSnippetsProps) => {
return (
<div className='mb-6 flex h-fit flex-col pb-6 md:h-96'>
<h1 className='pb-4 text-5xl antialiased'>Hey there, I'm Marta 👋🏻</h1>

<div className='mt-8 flex flex-col md:flex-row'>
<Code codeSnippets={shuffleArray(codeSnippets)} />

<Photo />
</div>
</div>
);
};

export default Intro;
35 changes: 35 additions & 0 deletions src/components/organisms/home/Photo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Image from 'next/image';
import React from 'react';

const Photo = () => {
return (
<div className='flex h-80 w-full justify-start md:h-[280px] md:w-1/2 md:justify-end'>
<div className='ms-3 flex flex-row-reverse p-3 md:flex-row'>
<div className='me-6 flex flex-col items-end text-lg'>
<div className='mt-10'>Software Engineer</div>
<div className='mt-10'>Lifelong learner</div>
<div className='mt-10'>Remote work enthusiast</div>
</div>
<div className='flex flex-col items-center'>
<Image
className='mb-3 rounded-full'
src='https://cdn.sanity.io/images/lj8a3h3g/production/15c9b3d57800e2f07abb0f6971a9186f9ff54f68-553x553.png'
alt='Avatar'
width={190}
height={0}
style={{ height: '190px' }}
/>
<Image
src='https://cdn.sanity.io/images/lj8a3h3g/production/b1fbe23d8efef11db38fd636e4035db81cfebdf6-941x189.webp'
alt='Avatar'
width={250}
height={0}
style={{ height: '50px' }}
/>
</div>
</div>
</div>
);
};

export default Photo;
74 changes: 74 additions & 0 deletions src/components/organisms/home/Summary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Image from 'next/image';
import React from 'react';

const Summary = () => {
return (
<>
<div className='pb-4 text-base antialiased'>
I'm a software engineer based in Turin, Italy, and I am currently
working at
<a
href='https://resourcify.com/'
target='_blank'
rel='noopener noreferrer'
>
<Image
className='ms-2 inline'
src='https://cdn.sanity.io/images/lj8a3h3g/production/c0f36368549d879ad790c46fd32f7ea10e3e258f-600x115.webp'
alt='Resourcify'
width='110'
height='25'
/>
</a>
.
</div>

<p className='pb-4 text-base antialiased'>
I hold a MSc in Advanced Computer Science from the University of
Manchester, and have four years of experience at
<a href='https://bjss.com/' target='_blank' rel='noopener noreferrer'>
<Image
className='mx-2 inline'
src='https://cdn.sanity.io/images/lj8a3h3g/production/0c8cfb9083cafb314b46b195ab99a27daf2f639d-280x150.webp'
alt='BJSS'
width='45'
height='25'
/>
</a>
and
<a
href='https://booking.com/'
target='_blank'
rel='noopener noreferrer'
>
<Image
className='ms-2 inline'
src='https://cdn.sanity.io/images/lj8a3h3g/production/a9bb3876e39ba378769bcc9b881ad8860dcbb9df-2500x424.svg'
alt='Booking.com'
width='115'
height='25'
/>
</a>
.
</p>

<p className='pb-4 text-base antialiased'>
My skill set embraces a range of programming languages, including Java,
Kotlin, Python, C# and TypeScript, as well as frontend frameworks such
as React and Angular.
</p>

<p className='pb-4 text-base antialiased'>
While I have a solid foundation in backend development, my heart truly
lies in the exciting realm of full-stack engineering.
</p>

<p className='pb-4 text-base antialiased'>
In my free time, I’m a fiction writer, an avid bookworm, an oboist and
alto singer, and a travel photographer.
</p>
</>
);
};

export default Summary;
19 changes: 19 additions & 0 deletions src/pages/api/code-snippets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NextApiRequest, NextApiResponse } from 'next';

import { codeSnippetsQuery } from '@/queries/codeSnippets';

import { sanityClient } from '../../../sanity/lib/client';

import { CodeSnippet } from '@/types/CodeSnippet';

const codeSnippetsApi = async (req: NextApiRequest, res: NextApiResponse) => {
const codeSnippets: CodeSnippet[] = await sanityClient.fetch(
codeSnippetsQuery
);

res.status(200).json({
codeSnippets,
});
};

export default codeSnippetsApi;
17 changes: 17 additions & 0 deletions src/pages/api/home.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { NextApiRequest, NextApiResponse } from 'next';

import { homeContentQuery } from '@/queries/homeContent';

import { sanityClient } from '../../../sanity/lib/client';

import { HomeContent } from '@/types/HomeContent';

const homeApi = async (req: NextApiRequest, res: NextApiResponse) => {
const homeContent: HomeContent = await sanityClient.fetch(homeContentQuery);

res.status(200).json({
home: homeContent,
});
};

export default homeApi;
9 changes: 9 additions & 0 deletions src/queries/codeSnippets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { groq } from 'next-sanity';

export const codeSnippetsQuery = groq`
*[_type == "codeSnippet"] {
_id,
title,
"code": code.code,
"language": code.language,
}`;
13 changes: 13 additions & 0 deletions src/queries/homeContent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { groq } from 'next-sanity';

export const homeContentQuery = groq`
*[_type == "homeContent"] {
_id,
title,
threeLineSummary,
summary0,
summary1,
summary2,
summary3,
summary4,
}`;
Loading

1 comment on commit c3ce299

@vercel
Copy link

@vercel vercel bot commented on c3ce299 Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.