mirror of
https://github.com/dsoaress/link-free.git
synced 2026-08-18 23:46:04 +01:00
feat: test ISR
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
/data
|
/temp
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"sharp": "^0.29.3"
|
"sharp": "^0.29.3",
|
||||||
|
"swr": "^1.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "15.0.0",
|
"@commitlint/cli": "15.0.0",
|
||||||
|
|||||||
@@ -1,29 +1,19 @@
|
|||||||
import { PrismaClient } from '@prisma/client'
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
const prisma = new PrismaClient()
|
import { fetchData } from '../src/services/fetchData'
|
||||||
|
|
||||||
async function initialdata() {
|
async function initialdata() {
|
||||||
const dataDir = './data'
|
const dataDir = './temp'
|
||||||
const data = await prisma.data.findFirst()
|
const data = await fetchData()
|
||||||
|
|
||||||
if (data) {
|
|
||||||
if (!fs.existsSync(dataDir)) {
|
if (!fs.existsSync(dataDir)) {
|
||||||
fs.mkdirSync(dataDir)
|
fs.mkdirSync(dataDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedData = JSON.parse(data.data)
|
fs.writeFileSync(`${dataDir}/data.json`, JSON.stringify(data, null, 2))
|
||||||
fs.writeFileSync(`${dataDir}/data.json`, JSON.stringify(parsedData, null, 2))
|
|
||||||
} else {
|
|
||||||
throw new Error('No data found')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initialdata()
|
initialdata().catch(e => {
|
||||||
.catch(e => {
|
|
||||||
console.error(e)
|
console.error(e)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
.finally(async () => {
|
|
||||||
await prisma.$disconnect()
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useData } from '../../contexts/DataContext'
|
import { useData } from '../../hooks/useData'
|
||||||
import { Wrapper } from './styles'
|
import { Wrapper } from './styles'
|
||||||
|
|
||||||
export function Avatar() {
|
export function Avatar() {
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import { ButtonHTMLAttributes, ReactNode } from 'react'
|
import type { ButtonHTMLAttributes, ReactNode } from 'react'
|
||||||
|
|
||||||
import { ButtonVariantProps, Wrapper } from './styles'
|
import type { ButtonVariantProps } from './styles'
|
||||||
|
import { Wrapper } from './styles'
|
||||||
|
|
||||||
type ButtonProps = ButtonVariantProps &
|
type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||||
ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
|
theme?: ButtonVariantProps['theme']
|
||||||
|
schema?: ButtonVariantProps['schema']
|
||||||
|
outline?: ButtonVariantProps['outline']
|
||||||
|
font?: ButtonVariantProps['font']
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Button({ children, ...rest }: ButtonProps) {
|
export function Button({ children, ...rest }: ButtonProps) {
|
||||||
return <Wrapper {...rest}>{children}</Wrapper>
|
return <Wrapper {...rest}>{children}</Wrapper>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type { ButtonVariantProps }
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { ColorsType, styled, theme, VariantProps } from '../../styles/stitches.config'
|
import { Colors, styled, theme, VariantProps } from '../../styles/stitches.config'
|
||||||
|
|
||||||
const colorVariantFn = (
|
const themeVariantFn = (
|
||||||
lightColor: ColorsType,
|
lightColor: Colors,
|
||||||
regularColor: ColorsType,
|
regularColor: Colors,
|
||||||
darkColor: ColorsType,
|
darkColor: Colors,
|
||||||
darkerColor: ColorsType
|
darkerColor: Colors
|
||||||
) => ({
|
) => ({
|
||||||
background: theme.colors[regularColor],
|
background: theme.colors[regularColor],
|
||||||
borderColor: theme.colors[regularColor],
|
borderColor: theme.colors[regularColor],
|
||||||
@@ -21,7 +21,7 @@ const colorVariantFn = (
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const outlineVariantFn = (color: ColorsType) => ({
|
const outlineVariantFn = (color: Colors) => ({
|
||||||
color: theme.colors[color],
|
color: theme.colors[color],
|
||||||
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
@@ -51,29 +51,29 @@ export const Wrapper = styled('button', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
color: {
|
theme: {
|
||||||
slate: colorVariantFn('slate50', 'slate600', 'slate700', 'slate800'),
|
slate: themeVariantFn('slate50', 'slate600', 'slate700', 'slate800'),
|
||||||
gray: colorVariantFn('gray50', 'gray600', 'gray700', 'gray800'),
|
gray: themeVariantFn('gray50', 'gray600', 'gray700', 'gray800'),
|
||||||
zinc: colorVariantFn('zinc50', 'zinc600', 'zinc700', 'zinc800'),
|
zinc: themeVariantFn('zinc50', 'zinc600', 'zinc700', 'zinc800'),
|
||||||
neutral: colorVariantFn('neutral50', 'neutral600', 'neutral700', 'neutral800'),
|
neutral: themeVariantFn('neutral50', 'neutral600', 'neutral700', 'neutral800'),
|
||||||
stone: colorVariantFn('stone50', 'stone600', 'stone700', 'stone800'),
|
stone: themeVariantFn('stone50', 'stone600', 'stone700', 'stone800'),
|
||||||
red: colorVariantFn('red50', 'red600', 'red700', 'red800'),
|
red: themeVariantFn('red50', 'red600', 'red700', 'red800'),
|
||||||
orange: colorVariantFn('orange50', 'orange600', 'orange700', 'orange800'),
|
orange: themeVariantFn('orange50', 'orange600', 'orange700', 'orange800'),
|
||||||
amber: colorVariantFn('amber50', 'amber600', 'amber700', 'amber800'),
|
amber: themeVariantFn('amber50', 'amber600', 'amber700', 'amber800'),
|
||||||
yellow: colorVariantFn('yellow50', 'yellow600', 'yellow700', 'yellow800'),
|
yellow: themeVariantFn('yellow50', 'yellow600', 'yellow700', 'yellow800'),
|
||||||
lime: colorVariantFn('lime50', 'lime600', 'lime700', 'lime800'),
|
lime: themeVariantFn('lime50', 'lime600', 'lime700', 'lime800'),
|
||||||
green: colorVariantFn('green50', 'green600', 'green700', 'green800'),
|
green: themeVariantFn('green50', 'green600', 'green700', 'green800'),
|
||||||
emerald: colorVariantFn('emerald50', 'emerald600', 'emerald700', 'emerald800'),
|
emerald: themeVariantFn('emerald50', 'emerald600', 'emerald700', 'emerald800'),
|
||||||
teal: colorVariantFn('teal50', 'teal600', 'teal700', 'teal800'),
|
teal: themeVariantFn('teal50', 'teal600', 'teal700', 'teal800'),
|
||||||
cyan: colorVariantFn('cyan50', 'cyan600', 'cyan700', 'cyan800'),
|
cyan: themeVariantFn('cyan50', 'cyan600', 'cyan700', 'cyan800'),
|
||||||
sky: colorVariantFn('sky50', 'sky600', 'sky700', 'sky800'),
|
sky: themeVariantFn('sky50', 'sky600', 'sky700', 'sky800'),
|
||||||
blue: colorVariantFn('blue50', 'blue600', 'blue700', 'blue800'),
|
blue: themeVariantFn('blue50', 'blue600', 'blue700', 'blue800'),
|
||||||
indigo: colorVariantFn('indigo50', 'indigo600', 'indigo700', 'indigo800'),
|
indigo: themeVariantFn('indigo50', 'indigo600', 'indigo700', 'indigo800'),
|
||||||
violet: colorVariantFn('violet50', 'violet600', 'violet700', 'violet800'),
|
violet: themeVariantFn('violet50', 'violet600', 'violet700', 'violet800'),
|
||||||
purple: colorVariantFn('purple50', 'purple600', 'purple700', 'purple800'),
|
purple: themeVariantFn('purple50', 'purple600', 'purple700', 'purple800'),
|
||||||
fuchsia: colorVariantFn('fuchsia50', 'fuchsia600', 'fuchsia700', 'fuchsia800'),
|
fuchsia: themeVariantFn('fuchsia50', 'fuchsia600', 'fuchsia700', 'fuchsia800'),
|
||||||
pink: colorVariantFn('pink50', 'pink600', 'pink700', 'pink800'),
|
pink: themeVariantFn('pink50', 'pink600', 'pink700', 'pink800'),
|
||||||
rose: colorVariantFn('rose50', 'rose600', 'rose700', 'rose800')
|
rose: themeVariantFn('rose50', 'rose600', 'rose700', 'rose800')
|
||||||
},
|
},
|
||||||
|
|
||||||
schema: {
|
schema: {
|
||||||
@@ -109,119 +109,119 @@ export const Wrapper = styled('button', {
|
|||||||
|
|
||||||
compoundVariants: [
|
compoundVariants: [
|
||||||
{
|
{
|
||||||
color: 'slate',
|
theme: 'slate',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('slate600')
|
css: outlineVariantFn('slate600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'gray',
|
theme: 'gray',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('gray600')
|
css: outlineVariantFn('gray600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'zinc',
|
theme: 'zinc',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('zinc600')
|
css: outlineVariantFn('zinc600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'neutral',
|
theme: 'neutral',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('neutral600')
|
css: outlineVariantFn('neutral600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'stone',
|
theme: 'stone',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('stone600')
|
css: outlineVariantFn('stone600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'red',
|
theme: 'red',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('red600')
|
css: outlineVariantFn('red600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'orange',
|
theme: 'orange',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('orange600')
|
css: outlineVariantFn('orange600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'amber',
|
theme: 'amber',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('amber600')
|
css: outlineVariantFn('amber600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'yellow',
|
theme: 'yellow',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('yellow600')
|
css: outlineVariantFn('yellow600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'lime',
|
theme: 'lime',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('lime600')
|
css: outlineVariantFn('lime600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'green',
|
theme: 'green',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('green600')
|
css: outlineVariantFn('green600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'emerald',
|
theme: 'emerald',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('emerald600')
|
css: outlineVariantFn('emerald600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'teal',
|
theme: 'teal',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('teal600')
|
css: outlineVariantFn('teal600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'cyan',
|
theme: 'cyan',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('cyan600')
|
css: outlineVariantFn('cyan600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'sky',
|
theme: 'sky',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('sky600')
|
css: outlineVariantFn('sky600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'blue',
|
theme: 'blue',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('blue600')
|
css: outlineVariantFn('blue600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'indigo',
|
theme: 'indigo',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('indigo600')
|
css: outlineVariantFn('indigo600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'violet',
|
theme: 'violet',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('violet600')
|
css: outlineVariantFn('violet600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'purple',
|
theme: 'purple',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('purple600')
|
css: outlineVariantFn('purple600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'fuchsia',
|
theme: 'fuchsia',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('fuchsia600')
|
css: outlineVariantFn('fuchsia600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'pink',
|
theme: 'pink',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('pink600')
|
css: outlineVariantFn('pink600')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'rose',
|
theme: 'rose',
|
||||||
outline: true,
|
outline: true,
|
||||||
css: outlineVariantFn('rose600')
|
css: outlineVariantFn('rose600')
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
color: 'teal',
|
theme: 'teal',
|
||||||
schema: 'pill',
|
schema: 'pill',
|
||||||
font: 'roboto',
|
font: 'roboto',
|
||||||
outline: false
|
outline: false
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useData } from '../../../contexts/DataContext'
|
import { useData } from '../../../hooks/useData'
|
||||||
|
|
||||||
export function DescriptionInput() {
|
export function DescriptionInput() {
|
||||||
const { data, setData } = useData()
|
const { data, setData } = useData()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useData } from '../../../contexts/DataContext'
|
import { useData } from '../../../hooks/useData'
|
||||||
|
|
||||||
export function NameInput() {
|
export function NameInput() {
|
||||||
const { data, setData } = useData()
|
const { data, setData } = useData()
|
||||||
|
|||||||
@@ -1,77 +1,80 @@
|
|||||||
import { isEqual } from 'lodash'
|
import { isEqual } from 'lodash'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { useData } from '../../contexts/DataContext'
|
import { useData } from '../../hooks/useData'
|
||||||
import { api } from '../../services/api'
|
import { api } from '../../services/api'
|
||||||
|
import type { Colors, Fonts } from '../../styles/stitches.config'
|
||||||
import { theme } from '../../styles/stitches.config'
|
import { theme } from '../../styles/stitches.config'
|
||||||
|
import type { Data } from '../../types/Data'
|
||||||
import {
|
import {
|
||||||
getLocalStorageData,
|
getLocalStorageData,
|
||||||
removeLocalStorageData,
|
removeLocalStorageData,
|
||||||
setLocalStorageData
|
setLocalStorageData
|
||||||
} from '../../utils/localStorage'
|
} from '../../utils/localStorage'
|
||||||
|
import type { ButtonVariantProps } from '../Button'
|
||||||
import { Home } from '../Home'
|
import { Home } from '../Home'
|
||||||
import { DescriptionInput } from './DescriptionInput'
|
import { DescriptionInput } from './DescriptionInput'
|
||||||
import { NameInput } from './NameInput'
|
import { NameInput } from './NameInput'
|
||||||
import { Content, Preview, Wrapper } from './styles'
|
import { Content, Preview, Wrapper } from './styles'
|
||||||
|
|
||||||
export function Dash() {
|
type DashProps = {
|
||||||
const { initialData, data, setData } = useData()
|
initialData: Data
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Dash({ initialData }: DashProps) {
|
||||||
|
const { push } = useRouter()
|
||||||
|
const { data, setData } = useData()
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (isLoading) {
|
||||||
const storageData = getLocalStorageData()
|
const storageData = getLocalStorageData()
|
||||||
|
if (storageData) setData(storageData)
|
||||||
if (storageData && isLoading) {
|
else setData(initialData)
|
||||||
setData(storageData)
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}, [isLoading, setData])
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
if (!isLoading && !isEqual(initialData, data)) {
|
||||||
if (!isEqual(initialData, data)) {
|
|
||||||
setHasUnsavedChanges(true)
|
setHasUnsavedChanges(true)
|
||||||
setLocalStorageData(data)
|
setLocalStorageData(data)
|
||||||
} else {
|
} else {
|
||||||
setHasUnsavedChanges(false)
|
setHasUnsavedChanges(false)
|
||||||
removeLocalStorageData()
|
|
||||||
}
|
}
|
||||||
}, [data, initialData])
|
}, [data, initialData, isLoading, setData])
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
try {
|
try {
|
||||||
await api.put('data', { data })
|
await api.put('data', { data })
|
||||||
setHasUnsavedChanges(false)
|
|
||||||
removeLocalStorageData()
|
removeLocalStorageData()
|
||||||
|
setHasUnsavedChanges(false)
|
||||||
|
push('/')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeBackground = (background: string) => {
|
const handleChangeBackground = (background: Colors) => {
|
||||||
setData({
|
setData({
|
||||||
...data,
|
...data,
|
||||||
settings: { ...data.settings, colors: { ...data.settings.colors, background } }
|
settings: { ...data.settings, colors: { ...data.settings.colors, background } }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeButtonsSchema = (schema: string) => {
|
const handleChangeButtonsSchema = (schema: ButtonVariantProps['schema']) => {
|
||||||
setData({ ...data, settings: { ...data.settings, buttonsSchema: schema } })
|
setData({ ...data, settings: { ...data.settings, buttonsSchema: schema } })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeOutline = (outline: boolean) => {
|
const handleChangeOutline = (outline: ButtonVariantProps['outline']) => {
|
||||||
setData({ ...data, settings: { ...data.settings, outline } })
|
setData({ ...data, settings: { ...data.settings, outline } })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeFont = (font: string) => {
|
const handleChangeFont = (font: Fonts) => {
|
||||||
setData({ ...data, settings: { ...data.settings, font } })
|
setData({ ...data, settings: { ...data.settings, font } })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoading) {
|
|
||||||
return <div>Loading...</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Content>
|
<Content>
|
||||||
@@ -86,7 +89,10 @@ export function Dash() {
|
|||||||
<NameInput />
|
<NameInput />
|
||||||
<DescriptionInput />
|
<DescriptionInput />
|
||||||
|
|
||||||
<select value={data.settings.font} onChange={e => handleChangeFont(e.target.value)}>
|
<select
|
||||||
|
value={data.settings.font}
|
||||||
|
onChange={e => handleChangeFont(e.target.value as Fonts)}
|
||||||
|
>
|
||||||
<option value="square">Baloo</option>
|
<option value="square">Baloo</option>
|
||||||
<option value="montserrat">Montserrat</option>
|
<option value="montserrat">Montserrat</option>
|
||||||
<option value="roboto">Roboto</option>
|
<option value="roboto">Roboto</option>
|
||||||
@@ -94,7 +100,7 @@ export function Dash() {
|
|||||||
|
|
||||||
<select
|
<select
|
||||||
value={data.settings.colors.background}
|
value={data.settings.colors.background}
|
||||||
onChange={e => handleChangeBackground(e.target.value)}
|
onChange={e => handleChangeBackground(e.target.value as Colors)}
|
||||||
>
|
>
|
||||||
{Object.keys(theme.colors).map(color => (
|
{Object.keys(theme.colors).map(color => (
|
||||||
<option key={color} value={color}>
|
<option key={color} value={color}>
|
||||||
@@ -104,8 +110,8 @@ export function Dash() {
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select
|
<select
|
||||||
value={data.settings.buttonsSchema}
|
value={data.settings.buttonsSchema as string}
|
||||||
onChange={e => handleChangeButtonsSchema(e.target.value)}
|
onChange={e => handleChangeButtonsSchema(e.target.value as ButtonVariantProps['schema'])}
|
||||||
>
|
>
|
||||||
<option value="square">Square</option>
|
<option value="square">Square</option>
|
||||||
<option value="rounded">Rounded</option>
|
<option value="rounded">Rounded</option>
|
||||||
@@ -114,8 +120,10 @@ export function Dash() {
|
|||||||
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
defaultChecked={data.settings.outline}
|
defaultChecked={data.settings.outline as boolean}
|
||||||
onChange={() => handleChangeOutline(!data.settings.outline)}
|
onChange={() =>
|
||||||
|
handleChangeOutline(!data.settings.outline as ButtonVariantProps['outline'])
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Content>
|
</Content>
|
||||||
<Preview>
|
<Preview>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useData } from '../../contexts/DataContext'
|
import { useData } from '../../hooks/useData'
|
||||||
import { theme } from '../../styles/stitches.config'
|
import { theme } from '../../styles/stitches.config'
|
||||||
import { Avatar } from '../Avatar'
|
import { Avatar } from '../Avatar'
|
||||||
import { Button } from '../Button'
|
import { Button } from '../Button'
|
||||||
@@ -22,13 +22,17 @@ export const Home = () => {
|
|||||||
<Name>{name}</Name>
|
<Name>{name}</Name>
|
||||||
<SocialLinks />
|
<SocialLinks />
|
||||||
<Description>{description}</Description>
|
<Description>{description}</Description>
|
||||||
{data.buttonLinks?.map(link =>
|
{data.buttonLinks?.map(link => (
|
||||||
// @ts-ignore
|
<Button
|
||||||
// prettier-ignore
|
theme={colors.buttonLinks}
|
||||||
<Button color={colors.buttonLinks} schema={buttonsSchema} outline={outline} font={font} key={link.href}>
|
schema={buttonsSchema}
|
||||||
|
outline={outline}
|
||||||
|
font={font}
|
||||||
|
key={link.href}
|
||||||
|
>
|
||||||
{link.label}
|
{link.label}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
))}
|
||||||
</Content>
|
</Content>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
import NextLink from 'next/link'
|
import NextLink from 'next/link'
|
||||||
import { AnchorHTMLAttributes } from 'react'
|
import type { AnchorHTMLAttributes } from 'react'
|
||||||
|
|
||||||
import { LinkVariantProps, Wrapper } from './styles'
|
import type { LinkVariantProps } from './styles'
|
||||||
|
import { Wrapper } from './styles'
|
||||||
|
|
||||||
export type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> &
|
export type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||||
LinkVariantProps & {
|
|
||||||
href: string
|
href: string
|
||||||
|
theme?: LinkVariantProps['theme']
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Link({ href, ...rest }: LinkProps) {
|
export function Link({ href, theme, ...rest }: LinkProps) {
|
||||||
return (
|
return (
|
||||||
<NextLink href={href} passHref>
|
<NextLink href={href} passHref>
|
||||||
<Wrapper {...rest} />
|
<Wrapper theme={theme} {...rest} />
|
||||||
</NextLink>
|
</NextLink>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type { LinkVariantProps }
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { ColorsType, styled, theme, VariantProps } from '../../styles/stitches.config'
|
import { Colors, styled, theme, VariantProps } from '../../styles/stitches.config'
|
||||||
|
|
||||||
const colorVariantFn = (
|
const themeVariantFn = (regularColor: Colors, darkColor: Colors, darkerColor: Colors) => ({
|
||||||
regularColor: ColorsType,
|
|
||||||
darkColor: ColorsType,
|
|
||||||
darkerColor: ColorsType
|
|
||||||
) => ({
|
|
||||||
color: theme.colors[regularColor],
|
color: theme.colors[regularColor],
|
||||||
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
@@ -22,34 +18,34 @@ export const Wrapper = styled('a', {
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
color: {
|
theme: {
|
||||||
slate: colorVariantFn('slate600', 'slate700', 'slate800'),
|
slate: themeVariantFn('slate600', 'slate700', 'slate800'),
|
||||||
gray: colorVariantFn('gray600', 'gray700', 'gray800'),
|
gray: themeVariantFn('gray600', 'gray700', 'gray800'),
|
||||||
zinc: colorVariantFn('zinc600', 'zinc700', 'zinc800'),
|
zinc: themeVariantFn('zinc600', 'zinc700', 'zinc800'),
|
||||||
neutral: colorVariantFn('neutral600', 'neutral700', 'neutral800'),
|
neutral: themeVariantFn('neutral600', 'neutral700', 'neutral800'),
|
||||||
stone: colorVariantFn('stone600', 'stone700', 'stone800'),
|
stone: themeVariantFn('stone600', 'stone700', 'stone800'),
|
||||||
red: colorVariantFn('red600', 'red700', 'red800'),
|
red: themeVariantFn('red600', 'red700', 'red800'),
|
||||||
orange: colorVariantFn('orange600', 'orange700', 'orange800'),
|
orange: themeVariantFn('orange600', 'orange700', 'orange800'),
|
||||||
amber: colorVariantFn('amber600', 'amber700', 'amber800'),
|
amber: themeVariantFn('amber600', 'amber700', 'amber800'),
|
||||||
yellow: colorVariantFn('yellow600', 'yellow700', 'yellow800'),
|
yellow: themeVariantFn('yellow600', 'yellow700', 'yellow800'),
|
||||||
lime: colorVariantFn('lime600', 'lime700', 'lime800'),
|
lime: themeVariantFn('lime600', 'lime700', 'lime800'),
|
||||||
green: colorVariantFn('green600', 'green700', 'green800'),
|
green: themeVariantFn('green600', 'green700', 'green800'),
|
||||||
emerald: colorVariantFn('emerald600', 'emerald700', 'emerald800'),
|
emerald: themeVariantFn('emerald600', 'emerald700', 'emerald800'),
|
||||||
teal: colorVariantFn('teal600', 'teal700', 'teal800'),
|
teal: themeVariantFn('teal600', 'teal700', 'teal800'),
|
||||||
cyan: colorVariantFn('cyan600', 'cyan700', 'cyan800'),
|
cyan: themeVariantFn('cyan600', 'cyan700', 'cyan800'),
|
||||||
sky: colorVariantFn('sky600', 'sky700', 'sky800'),
|
sky: themeVariantFn('sky600', 'sky700', 'sky800'),
|
||||||
blue: colorVariantFn('blue600', 'blue700', 'blue800'),
|
blue: themeVariantFn('blue600', 'blue700', 'blue800'),
|
||||||
indigo: colorVariantFn('indigo600', 'indigo700', 'indigo800'),
|
indigo: themeVariantFn('indigo600', 'indigo700', 'indigo800'),
|
||||||
violet: colorVariantFn('violet600', 'violet700', 'violet800'),
|
violet: themeVariantFn('violet600', 'violet700', 'violet800'),
|
||||||
purple: colorVariantFn('purple600', 'purple700', 'purple800'),
|
purple: themeVariantFn('purple600', 'purple700', 'purple800'),
|
||||||
fuchsia: colorVariantFn('fuchsia600', 'fuchsia700', 'fuchsia800'),
|
fuchsia: themeVariantFn('fuchsia600', 'fuchsia700', 'fuchsia800'),
|
||||||
pink: colorVariantFn('pink600', 'pink700', 'pink800'),
|
pink: themeVariantFn('pink600', 'pink700', 'pink800'),
|
||||||
rose: colorVariantFn('rose600', 'rose700', 'rose800')
|
rose: themeVariantFn('rose600', 'rose700', 'rose800')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
color: 'teal'
|
theme: 'teal'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import {
|
|||||||
} from 'react-icons/ai'
|
} from 'react-icons/ai'
|
||||||
import { BsEnvelope as Email } from 'react-icons/bs'
|
import { BsEnvelope as Email } from 'react-icons/bs'
|
||||||
import { FaDev as Dev, FaLinkedinIn as LinkedIn } from 'react-icons/fa'
|
import { FaDev as Dev, FaLinkedinIn as LinkedIn } from 'react-icons/fa'
|
||||||
import { IconType } from 'react-icons/lib'
|
import type { IconType } from 'react-icons/lib'
|
||||||
|
|
||||||
import { useData } from '../../contexts/DataContext'
|
import { useData } from '../../hooks/useData'
|
||||||
import { Link } from '../Link'
|
import { Link } from '../Link'
|
||||||
import { SocialItem, Wrapper } from './styles'
|
import { SocialItem, Wrapper } from './styles'
|
||||||
|
|
||||||
@@ -34,8 +34,7 @@ export function SocialLinks() {
|
|||||||
aria-label={label}
|
aria-label={label}
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
// @ts-ignore
|
theme={data.settings.colors.socialLinks}
|
||||||
color={data.settings.colors.socialLinks}
|
|
||||||
>
|
>
|
||||||
<Icon size={22} />
|
<Icon size={22} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,27 +1,22 @@
|
|||||||
import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useState } from 'react'
|
import type { Dispatch, ReactNode, SetStateAction } from 'React'
|
||||||
|
import { createContext, useState } from 'react'
|
||||||
|
|
||||||
import initialData from '../../data/data.json'
|
import initialData from '../../temp/data.json'
|
||||||
|
import type { Data } from '../types/Data'
|
||||||
type DataType = typeof initialData
|
|
||||||
|
|
||||||
type DataContextType = {
|
type DataContextType = {
|
||||||
initialData: DataType
|
data: Data
|
||||||
data: DataType
|
setData: Dispatch<SetStateAction<Data>>
|
||||||
setData: Dispatch<SetStateAction<DataType>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataProviderProps = {
|
type DataProviderProps = {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const DataContext = createContext({} as DataContextType)
|
export const DataContext = createContext({} as DataContextType)
|
||||||
|
|
||||||
export const DataProvider = ({ children }: DataProviderProps) => {
|
export const DataProvider = ({ children }: DataProviderProps) => {
|
||||||
const [data, setData] = useState<DataType>(initialData)
|
const [data, setData] = useState<Data>(initialData as Data)
|
||||||
|
|
||||||
return (
|
return <DataContext.Provider value={{ data, setData }}>{children}</DataContext.Provider>
|
||||||
<DataContext.Provider value={{ initialData, data, setData }}>{children}</DataContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useData = () => useContext(DataContext)
|
|
||||||
|
|||||||
5
src/hooks/useData.ts
Normal file
5
src/hooks/useData.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { useContext } from 'react'
|
||||||
|
|
||||||
|
import { DataContext } from '../contexts/DataContext'
|
||||||
|
|
||||||
|
export const useData = () => useContext(DataContext)
|
||||||
15
src/hooks/useFetchData.ts
Normal file
15
src/hooks/useFetchData.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
import { fetcher } from '../services/api'
|
||||||
|
import type { Data } from '../types/Data'
|
||||||
|
import { useData } from './useData'
|
||||||
|
|
||||||
|
export function useFetchData(fallbackData: Data) {
|
||||||
|
const { setData } = useData()
|
||||||
|
const { data } = useSWR('data', fetcher, {
|
||||||
|
refreshInterval: 1000,
|
||||||
|
fallbackData
|
||||||
|
})
|
||||||
|
|
||||||
|
setData(data)
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ import { NextApiRequest, NextApiResponse } from 'next'
|
|||||||
import nc from 'next-connect'
|
import nc from 'next-connect'
|
||||||
|
|
||||||
import { prisma } from '../../services/prisma'
|
import { prisma } from '../../services/prisma'
|
||||||
const { RAILWAY_TOKEN } = process.env
|
|
||||||
|
|
||||||
const handler = nc<NextApiRequest, NextApiResponse>()
|
const handler = nc<NextApiRequest, NextApiResponse>()
|
||||||
.get(async (_req, res) => {
|
.get(async (_req, res) => {
|
||||||
@@ -24,10 +23,6 @@ const handler = nc<NextApiRequest, NextApiResponse>()
|
|||||||
data: { data: JSON.stringify(req.body.data) }
|
data: { data: JSON.stringify(req.body.data) }
|
||||||
})
|
})
|
||||||
|
|
||||||
if (RAILWAY_TOKEN) {
|
|
||||||
console.log('railway token', RAILWAY_TOKEN)
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(200).json(response)
|
res.status(200).json(response)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
import { Dash } from '../components/Dash'
|
import { GetServerSideProps } from 'next'
|
||||||
|
|
||||||
export default function DashPage() {
|
import { Dash } from '../components/Dash'
|
||||||
return <Dash />
|
import { fetchData } from '../services/fetchData'
|
||||||
|
import type { Data } from '../types/Data'
|
||||||
|
|
||||||
|
type DashPageProps = {
|
||||||
|
initialData: Data
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DashPage({ initialData }: DashPageProps) {
|
||||||
|
return <Dash initialData={initialData} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps: GetServerSideProps = async () => {
|
||||||
|
const initialData = await fetchData()
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { initialData }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,24 @@
|
|||||||
import { Home } from '../components/Home'
|
import { GetStaticProps } from 'next'
|
||||||
|
|
||||||
export default function HomePage() {
|
import { Home } from '../components/Home'
|
||||||
|
import { useFetchData } from '../hooks/useFetchData'
|
||||||
|
import { fetchData } from '../services/fetchData'
|
||||||
|
import type { Data } from '../types/Data'
|
||||||
|
|
||||||
|
type HomePageProps = {
|
||||||
|
data: Data
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function HomePage({ data }: HomePageProps) {
|
||||||
|
useFetchData(data)
|
||||||
return <Home />
|
return <Home />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getStaticProps: GetStaticProps = async () => {
|
||||||
|
const data = await fetchData()
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: { data },
|
||||||
|
revalidate: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,3 +3,5 @@ import axios from 'axios'
|
|||||||
export const api = axios.create({
|
export const api = axios.create({
|
||||||
baseURL: '/api'
|
baseURL: '/api'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const fetcher = (url: string) => api.get(url).then(({ data }) => data)
|
||||||
|
|||||||
12
src/services/fetchData.ts
Normal file
12
src/services/fetchData.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { Data } from '../types/Data'
|
||||||
|
import { prisma } from './prisma'
|
||||||
|
|
||||||
|
export async function fetchData(): Promise<Data> {
|
||||||
|
const data = await prisma.data.findFirst()
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
return JSON.parse(data.data)
|
||||||
|
} else {
|
||||||
|
throw new Error('No data found')
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import data from '../../data/data.json'
|
import data from '../../temp/data.json'
|
||||||
import { globalCss, theme } from './stitches.config'
|
import { globalCss, theme } from './stitches.config'
|
||||||
|
|
||||||
export const globalStyles = globalCss({
|
export const globalStyles = globalCss({
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createStitches, VariantProps } from '@stitches/react'
|
import type { VariantProps } from '@stitches/react'
|
||||||
|
import { createStitches } from '@stitches/react'
|
||||||
|
|
||||||
export const { css, styled, globalCss, theme, keyframes, getCssText } = createStitches({
|
export const { css, styled, globalCss, theme, keyframes, getCssText } = createStitches({
|
||||||
theme: {
|
theme: {
|
||||||
@@ -253,6 +254,7 @@ export const { css, styled, globalCss, theme, keyframes, getCssText } = createSt
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
type ColorsType = keyof typeof theme.colors
|
type Colors = keyof typeof theme.colors
|
||||||
|
type Fonts = keyof typeof theme.fonts
|
||||||
|
|
||||||
export type { ColorsType, VariantProps }
|
export type { Colors, Fonts, VariantProps }
|
||||||
|
|||||||
28
src/types/Data.ts
Normal file
28
src/types/Data.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import type { ButtonVariantProps } from '../components/Button'
|
||||||
|
import type { LinkVariantProps } from '../components/Link'
|
||||||
|
import type { Colors, Fonts } from '../styles/stitches.config'
|
||||||
|
|
||||||
|
export type Data = {
|
||||||
|
settings: {
|
||||||
|
avatar: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
font: Fonts
|
||||||
|
buttonsSchema: ButtonVariantProps['schema']
|
||||||
|
outline: ButtonVariantProps['outline']
|
||||||
|
colors: {
|
||||||
|
texts: Colors
|
||||||
|
socialLinks: LinkVariantProps['theme']
|
||||||
|
buttonLinks: ButtonVariantProps['theme']
|
||||||
|
background: Colors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
socialLinks: {
|
||||||
|
label: string
|
||||||
|
href: string
|
||||||
|
}[]
|
||||||
|
buttonLinks: {
|
||||||
|
label: string
|
||||||
|
href: string
|
||||||
|
}[]
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import type { Data } from '../types/Data'
|
||||||
|
|
||||||
const KEY = 'link-free-data'
|
const KEY = 'link-free-data'
|
||||||
|
|
||||||
export function getLocalStorageData() {
|
export function getLocalStorageData(): Data | null {
|
||||||
const data = process.browser && localStorage.getItem(KEY)
|
const data = process.browser && localStorage.getItem(KEY)
|
||||||
return data ? JSON.parse(data) : null
|
return data ? JSON.parse(data) : null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4147,6 +4147,11 @@ supports-color@^9.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891"
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891"
|
||||||
integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==
|
integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==
|
||||||
|
|
||||||
|
swr@^1.1.1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/swr/-/swr-1.1.1.tgz#f13346cc830d7950183af57b341bfabb4cc90d43"
|
||||||
|
integrity sha512-ZpUHyU3N3snj2QGFeE2Fd3BXl1CVS6YQIQGb1ttPAkTmvwZqDyV3GRMNPsaeAYCBM74tfn4XbKx28FVQR0mS7Q==
|
||||||
|
|
||||||
tar-fs@^2.0.0, tar-fs@^2.1.1:
|
tar-fs@^2.0.0, tar-fs@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
|
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
|
||||||
|
|||||||
Reference in New Issue
Block a user