1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-12-22 09:13:19 +01:00
This commit is contained in:
Matthias Kretschmann 2024-02-05 09:29:00 +00:00
parent a5cd4aebda
commit 934ed0fff5
Signed by: m
GPG Key ID: 606EEEF3C479A91F
24 changed files with 47 additions and 37 deletions

View File

@ -9,6 +9,9 @@
"^(react/(.*)$)|^(react$)", "^(react/(.*)$)|^(react$)",
"^(next/(.*)$)|^(next$)", "^(next/(.*)$)|^(next$)",
"<THIRD_PARTY_MODULES>", "<THIRD_PARTY_MODULES>",
"^(@/(.*)$)|^(@$)",
"^(@content/(.*)$)|^(@content$)",
"^(@generated/(.*)$)|^(@generated$)",
"^[./]" "^[./]"
], ],
"importOrderSeparation": false, "importOrderSeparation": false,

View File

@ -44,9 +44,10 @@ If you are looking for the former Gatsby-based app, it is archived in the [`gats
All displayed project content is powered by one YAML file where all the portfolio's projects are defined. The project description itself is transformed from Markdown written inside the YAML file into HTML on build time. All displayed project content is powered by one YAML file where all the portfolio's projects are defined. The project description itself is transformed from Markdown written inside the YAML file into HTML on build time.
Next.js automatically creates pages from each item in that file utilizing the [`[slug]/page.tsx`](src/app/[slug]/page.tsx) template. Next.js automatically creates pages from each item in that file utilizing the [`scripts/prebuild.ts`](scripts/prebuild.ts) script and the [`[slug]/page.tsx`](src/app/[slug]/page.tsx) template.
- [`_content/projects.yml`](_content/projects.yml) - [`_content/projects.yml`](_content/projects.yml)
- [`scripts/prebuild.ts`](scripts/prebuild.ts)
- [`src/app/[slug]/page.tsx`](src/app/[slug]/page.tsx) - [`src/app/[slug]/page.tsx`](src/app/[slug]/page.tsx)
### 🖼 Project images ### 🖼 Project images
@ -56,7 +57,7 @@ All project images live under `public/images` and are automatically attached to
Next.js with `next/image` generates all required image sizes for delivering responsible, responsive images to visitors, including lazy loading of all images. For this to work, images are analyzed on build time and various image metadata is passed down as props. Next.js with `next/image` generates all required image sizes for delivering responsible, responsive images to visitors, including lazy loading of all images. For this to work, images are analyzed on build time and various image metadata is passed down as props.
- [`src/components/ProjectImage/index.tsx`](src/components/ProjectImage/index.tsx) - [`src/components/ProjectImage/index.tsx`](src/components/ProjectImage/index.tsx)
- [`src/lib/content.ts`](src/lib/content.ts) - [`script/content/images.ts`](script/content/images.ts)
### 🐱 GitHub repositories ### 🐱 GitHub repositories

View File

@ -1,4 +1,4 @@
import projects from '@/generated/projects.json' import projects from '@generated/projects.json'
export function getAllSlugs() { export function getAllSlugs() {
const slugs = projects.map(({ slug }: { slug: string }) => slug) const slugs = projects.map(({ slug }: { slug: string }) => slug)

View File

@ -1,4 +1,4 @@
import projects from '@/generated/projects.json' import projects from '@generated/projects.json'
export function getProjectBySlug(slug: string) { export function getProjectBySlug(slug: string) {
return projects.find((item) => item.slug === slug) return projects.find((item) => item.slug === slug)

View File

@ -1,10 +1,10 @@
import { Metadata } from 'next' import { Metadata } from 'next'
import { notFound } from 'next/navigation' import { notFound } from 'next/navigation'
import meta from '@/_content/meta.json' import Header from '@/components/Header/Header'
import projects from '@/generated/projects.json' import Project from '@/components/Project'
import Header from '@/src/components/Header/Header' import ProjectNav from '@/components/ProjectNav'
import Project from '@/src/components/Project' import meta from '@content/meta.json'
import ProjectNav from '@/src/components/ProjectNav' import projects from '@generated/projects.json'
import { getAllSlugs } from './getAllSlugs' import { getAllSlugs } from './getAllSlugs'
import { getProjectBySlug } from './getProjectBySlug' import { getProjectBySlug } from './getProjectBySlug'

View File

@ -1,4 +1,4 @@
import meta from '../../../_content/meta.json' import meta from '@content/meta.json'
import styles from './index.module.css' import styles from './index.module.css'
export default function Availability() { export default function Availability() {

View File

@ -1,4 +1,4 @@
import meta from '../../../_content/meta.json' import meta from '@content/meta.json'
import LogoUnit from '../LogoUnit' import LogoUnit from '../LogoUnit'
import Networks from '../Networks' import Networks from '../Networks'
import Vcard from '../Vcard' import Vcard from '../Vcard'

View File

@ -16,7 +16,7 @@ import {
Star, Star,
Sun Sun
} from 'lucide-react' } from 'lucide-react'
import Mastodon from '../../images/mastodon.svg' import Mastodon from '@/images/mastodon.svg'
import styles from './index.module.css' import styles from './index.module.css'
export default function Icon({ name, ...props }: { name: string }) { export default function Icon({ name, ...props }: { name: string }) {

View File

@ -1,9 +1,9 @@
'use client' 'use client'
import { useEffect, useState } from 'react' import { useEffect, useState, useTransition } from 'react'
import { getLocation } from '@/src/app/actions'
import RelativeTime from '@yaireo/relative-time' import RelativeTime from '@yaireo/relative-time'
import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion' import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion'
import { getLocation } from '@/app/actions'
import { fadeIn, getAnimationProps } from '../Transitions' import { fadeIn, getAnimationProps } from '../Transitions'
import { Flag } from './Flag' import { Flag } from './Flag'
import styles from './Location.module.css' import styles from './Location.module.css'
@ -11,22 +11,22 @@ import { UseLocation } from './types'
export default function Location() { export default function Location() {
const shouldReduceMotion = useReducedMotion() const shouldReduceMotion = useReducedMotion()
const [isPending, startTransition] = useTransition()
const [location, setLocation] = useState<UseLocation | null>(null) const [location, setLocation] = useState<UseLocation | null>(null)
const isDifferentCountry = location?.now?.country !== location?.next?.country const isDifferentCountry = location?.now?.country !== location?.next?.country
const relativeTime = new RelativeTime({ locale: 'en' }) const relativeTime = new RelativeTime({ locale: 'en' })
useEffect(() => { useEffect(() => {
const updateLocation = async () => { startTransition(async () => {
const location = await getLocation() const location = await getLocation()
setLocation(location) setLocation(location)
} })
updateLocation()
}, []) }, [])
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
{location?.now?.city ? ( {!isPending && location?.now?.city ? (
<LazyMotion features={domAnimation}> <LazyMotion features={domAnimation}>
<m.section <m.section
aria-label="Location" aria-label="Location"

View File

@ -1,6 +1,6 @@
import Link from 'next/link' import Link from 'next/link'
import meta from '../../../_content/meta.json' import Logo from '@/images/logo.svg'
import Logo from '../../images/logo.svg' import meta from '@content/meta.json'
import styles from './index.module.css' import styles from './index.module.css'
type Props = { type Props = {

View File

@ -1,7 +1,7 @@
'use client' 'use client'
import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion' import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion'
import meta from '../../../_content/meta.json' import meta from '@content/meta.json'
import { getAnimationProps } from '../Transitions' import { getAnimationProps } from '../Transitions'
import { NetworkLink } from './NetworkLink' import { NetworkLink } from './NetworkLink'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,5 +1,5 @@
import Button from '../../Button' import Button from '@/components/Button'
import Icon from '../../Icon' import Icon from '@/components/Icon'
import styles from './index.module.css' import styles from './index.module.css'
export default function ProjectLinks({ export default function ProjectLinks({

View File

@ -1,8 +1,8 @@
'use client' 'use client'
import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion' import { LazyMotion, domAnimation, m, useReducedMotion } from 'framer-motion'
import type ImageType from '../../types/image' import type ImageType from '@/types/image'
import type ProjectType from '../../types/project' import type ProjectType from '@/types/project'
import ProjectImage from '../ProjectImage' import ProjectImage from '../ProjectImage'
import { getAnimationProps, moveInBottom } from '../Transitions' import { getAnimationProps, moveInBottom } from '../Transitions'
import ProjectLinks from './Links' import ProjectLinks from './Links'

View File

@ -1,5 +1,5 @@
import Image from 'next/image' import Image from 'next/image'
import ImageType from '../../types/image' import ImageType from '@/types/image'
import styles from './index.module.css' import styles from './index.module.css'
export default function ProjectImage({ export default function ProjectImage({

View File

@ -1,7 +1,7 @@
'use client' 'use client'
import { createRef, useEffect } from 'react' import { createRef, useEffect } from 'react'
import ProjectType from '../../types/project' import ProjectType from '@/types/project'
import { Project } from './Project' import { Project } from './Project'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,4 +1,4 @@
import ProjectType from '../../types/project' import ProjectType from '@/types/project'
import ProjectPreview from '../ProjectPreview' import ProjectPreview from '../ProjectPreview'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,7 +1,7 @@
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import Repo from '@/types/repo'
import Repositories from '.' import Repositories from '.'
import repos from '../../../tests/__fixtures__/repos.json' import repos from '../../../tests/__fixtures__/repos.json'
import Repo from '../../types/repo'
describe('Repositories', () => { describe('Repositories', () => {
it('renders correctly', () => { it('renders correctly', () => {

View File

@ -1,4 +1,4 @@
import Repo from '../../types/repo' import Repo from '@/types/repo'
import Repository from '../Repository' import Repository from '../Repository'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,6 +1,6 @@
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import Repo from '@/types/repo'
import repos from '../../../tests/__fixtures__/repos.json' import repos from '../../../tests/__fixtures__/repos.json'
import Repo from '../../types/repo'
import Repository from '../Repository' import Repository from '../Repository'
describe('Repository', () => { describe('Repository', () => {

View File

@ -1,4 +1,4 @@
import Repo from '../../types/repo' import Repo from '@/types/repo'
import Icon from '../Icon' import Icon from '../Icon'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,7 +1,7 @@
'use client' 'use client'
import { MouseEvent } from 'react' import { MouseEvent } from 'react'
import meta from '../../../_content/meta.json' import meta from '@content/meta.json'
export default function Vcard() { export default function Vcard() {
const { name, label, email } = meta.author const { name, label, email } = meta.author

View File

@ -1,5 +1,5 @@
import data from '../../_content/repos.json' import type Repo from '@/types/repo'
import Repo from '../types/repo' import filter from '@content/repos.json'
// //
// Get GitHub repos // Get GitHub repos
@ -18,7 +18,7 @@ const gitHubConfig = {
export async function getGithubRepos() { export async function getGithubRepos() {
let repos: Repo[] = [] let repos: Repo[] = []
for (let item of data) { for (let item of filter) {
const user = item.split('/')[0] const user = item.split('/')[0]
const repoName = item.split('/')[1] const repoName = item.split('/')[1]
const data = await fetch( const data = await fetch(

View File

@ -16,6 +16,8 @@ const customJestConfig: Config = {
testEnvironment: 'jsdom', testEnvironment: 'jsdom',
moduleNameMapper: { moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1', '^@/(.*)$': '<rootDir>/$1',
'^@content/(.*)$': '<rootDir>/_content/$1',
'^@generated/(.*)$': '<rootDir>/generated/$1',
'^.+\\.(svg)$': '<rootDir>/tests/__mocks__/svgr-mock.tsx' '^.+\\.(svg)$': '<rootDir>/tests/__mocks__/svgr-mock.tsx'
}, },
collectCoverage: true, collectCoverage: true,

View File

@ -15,7 +15,11 @@
"jsx": "preserve", "jsx": "preserve",
"incremental": true, "incremental": true,
"plugins": [{ "name": "next" }], "plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] } "paths": {
"@/*": ["./src/*"],
"@content/*": ["./_content/*"],
"@generated/*": ["./generated/*"]
}
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]