mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-22 09:13:19 +01:00
refactor
This commit is contained in:
parent
a5cd4aebda
commit
934ed0fff5
@ -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,
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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() {
|
||||||
|
@ -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'
|
||||||
|
@ -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 }) {
|
||||||
|
@ -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"
|
||||||
|
@ -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 = {
|
||||||
|
@ -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'
|
||||||
|
@ -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({
|
||||||
|
@ -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'
|
||||||
|
@ -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({
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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', () => {
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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', () => {
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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"]
|
||||||
|
Loading…
Reference in New Issue
Block a user