diff --git a/.babelrc.json b/.babelrc.json new file mode 100644 index 0000000..854cb73 --- /dev/null +++ b/.babelrc.json @@ -0,0 +1,4 @@ +{ + "presets": ["next/babel"], + "plugins": [["styled-components", { "ssr": true }]] +} diff --git a/.gitignore b/.gitignore index 91f01f1..f66867a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ # production /build -/temp # misc .DS_Store diff --git a/package.json b/package.json index 0e89934..d62a951 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,9 @@ "license": "MIT", "scripts": { "prisma": "yarn prisma:push && yarn prisma:seed", - "initialdata": "ts-node scripts/initialdata.ts", - "predev": "yarn prisma && yarn initialdata", + "predev": "yarn prisma", "dev": "next dev", - "prebuild": "yarn prisma && yarn initialdata", + "prebuild": "yarn prisma", "build": "next build", "start": "next start", "lint": "next lint --fix", @@ -21,20 +20,23 @@ }, "dependencies": { "@prisma/client": "^3.6.0", - "@stitches/react": "^1.2.6", "axios": "^0.24.0", "bcryptjs": "^2.4.3", + "cuid": "^2.1.8", "dotenv": "^10.0.0", "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", "next": "12.0.7", "next-connect": "^0.11.0", "nookies": "^2.5.2", - "react": "17.0.2", - "react-dom": "17.0.2", + "polished": "^4.1.3", + "react": "^17.0.2", + "react-collapsible": "^2.8.4", + "react-color": "^2.19.3", + "react-dom": "^17.0.2", "react-icons": "^4.3.1", "sharp": "^0.29.3", - "swr": "^1.1.1" + "styled-components": "^5.3.3" }, "devDependencies": { "@commitlint/cli": "15.0.0", @@ -44,6 +46,9 @@ "@types/lodash": "^4.14.178", "@types/node": "^16.11.12", "@types/react": "17.0.37", + "@types/react-color": "^3.0.6", + "@types/styled-components": "^5.1.18", + "babel-plugin-styled-components": "^2.0.2", "eslint": "8.4.1", "eslint-config-next": "12.0.7", "eslint-config-prettier": "8.3.0", @@ -54,6 +59,7 @@ "prettier": "2.5.0", "pretty-quick": "3.1.2", "prisma": "^3.6.0", + "react-is": "^17.0.2", "ts-node": "^10.4.0", "typescript": "^4.5.3" }, diff --git a/prisma/seed.ts b/prisma/seed.ts index 27a886c..00c13eb 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,5 +1,6 @@ import { PrismaClient } from '@prisma/client' import { hashSync } from 'bcryptjs' +import cuid from 'cuid' import dotenv from 'dotenv' const prisma = new PrismaClient() @@ -53,16 +54,19 @@ async function main() { ], buttonLinks: [ { + id: cuid(), label: 'Home', href: '#' }, { + id: cuid(), label: 'About', - href: '/about' + href: '#' }, { + id: cuid(), label: 'Contact', - href: '/contact' + href: '#' } ] } diff --git a/scripts/initialdata.ts b/scripts/initialdata.ts deleted file mode 100644 index d92f65c..0000000 --- a/scripts/initialdata.ts +++ /dev/null @@ -1,19 +0,0 @@ -import fs from 'fs' - -import { fetchData } from '../src/services/fetchData' - -async function initialdata() { - const dataDir = './temp' - const data = await fetchData() - - if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir) - } - - fs.writeFileSync(`${dataDir}/data.json`, JSON.stringify(data, null, 2)) -} - -initialdata().catch(e => { - console.error(e) - process.exit(1) -}) diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json deleted file mode 100644 index 0e7afc6..0000000 --- a/scripts/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "module": "commonjs" - } -} diff --git a/src/components/Avatar/styles.ts b/src/components/Avatar/styles.ts index 1f92376..95ae7b7 100644 --- a/src/components/Avatar/styles.ts +++ b/src/components/Avatar/styles.ts @@ -1,10 +1,9 @@ import Image from 'next/image' +import styled from 'styled-components' -import { styled } from '../../styles/stitches.config' - -export const Wrapper = styled(Image, { - borderRadius: '9999px', - objectFit: 'cover', - width: '84px', - height: '84px' -}) +export const Wrapper = styled(Image)` + border-radius: 9999px; + object-fit: cover; + width: 84px; + height: 84px; +` diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index cc18572..4a15367 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -1,19 +1 @@ -import type { ButtonHTMLAttributes, ReactNode } from 'react' - -import type { ButtonVariantProps } from './styles' -import { Wrapper } from './styles' - -type ButtonProps = ButtonHTMLAttributes & { - children: ReactNode - colorSchema?: ButtonVariantProps['colorSchema'] - styleSchema?: ButtonVariantProps['styleSchema'] - size?: ButtonVariantProps['size'] - font?: ButtonVariantProps['font'] - outline?: boolean -} - -export function Button({ children, ...rest }: ButtonProps) { - return {children} -} - -export type { ButtonVariantProps } +export { Button } from './styles' diff --git a/src/components/Button/styles.ts b/src/components/Button/styles.ts index 3bb751d..a306c2a 100644 --- a/src/components/Button/styles.ts +++ b/src/components/Button/styles.ts @@ -1,218 +1,72 @@ -import { Colors, styled, theme, VariantProps } from '../../styles/stitches.config' +import { darken } from 'polished' +import styled from 'styled-components' -const colorSchemaFn = ( - lightColor: Colors, - regularColor: Colors, - darkColor: Colors, - darkerColor: Colors -) => ({ - background: theme.colors[regularColor], - borderColor: theme.colors[regularColor], - color: theme.colors[lightColor], +type ButtonProps = { + color?: string + background?: string + variant?: 'square' | 'rounded' | 'pill' + outlined?: boolean + font?: string + size?: 'small' | 'medium' +} - '&:hover': { - background: theme.colors[darkColor], - borderColor: theme.colors[darkColor] - }, +export const Button = styled.button.attrs((props: ButtonProps) => ({ + color: props.color || '#f8fafc', + background: props.background || '#e11d48', + variant: props.variant || 'rounded', + outlined: props.outlined || false, + font: props.font || 'inherit', + size: props.size || 'medium' +}))` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + padding: 0 1rem; + font-family: ${({ font }) => font}; + color: ${({ color }) => color}; + background: ${({ background }) => background}; + border-width: 2.5px; + border-style: solid; + font-weight: 500; + cursor: pointer; + text-decoration: none; + transition: all 0.25s ease; - '&:active': { - background: theme.colors[darkerColor], - borderColor: theme.colors[darkerColor] + &:hover { + background: ${({ background }) => darken(0.1, background)}; + transform: translateY(-0.15rem); } -}) -const outlineVariantFn = (color: Colors) => ({ - color: theme.colors[color], - - '&:hover': { - background: 'rgba(0, 0, 0, 0.05)' - }, - - '&:active': { - background: 'rgba(0, 0, 0, 0.1)' + &:active { + background: ${({ background }) => darken(0.2, background)}; } -}) -export const Wrapper = styled('button', { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - width: '100%', - padding: '0 1rem', - borderWidth: '2.5px', - borderStyle: 'solid', - fontWeight: 500, - cursor: 'pointer', - transition: 'all 0.25s ease-in-out', + ${({ variant }) => variant === 'square' && `border-radius: 0;`} - '&:hover': { - transform: 'translateY(-0.15rem)' - }, + ${({ variant }) => variant === 'rounded' && `border-radius: 0.5rem;`} - variants: { - colorSchema: { - slate: colorSchemaFn('slate50', 'slate600', 'slate700', 'slate800'), - red: colorSchemaFn('red50', 'red600', 'red700', 'red800'), - orange: colorSchemaFn('orange50', 'orange600', 'orange700', 'orange800'), - amber: colorSchemaFn('amber50', 'amber600', 'amber700', 'amber800'), - yellow: colorSchemaFn('yellow50', 'yellow600', 'yellow700', 'yellow800'), - lime: colorSchemaFn('lime50', 'lime600', 'lime700', 'lime800'), - green: colorSchemaFn('green50', 'green600', 'green700', 'green800'), - emerald: colorSchemaFn('emerald50', 'emerald600', 'emerald700', 'emerald800'), - teal: colorSchemaFn('teal50', 'teal600', 'teal700', 'teal800'), - cyan: colorSchemaFn('cyan50', 'cyan600', 'cyan700', 'cyan800'), - sky: colorSchemaFn('sky50', 'sky600', 'sky700', 'sky800'), - blue: colorSchemaFn('blue50', 'blue600', 'blue700', 'blue800'), - indigo: colorSchemaFn('indigo50', 'indigo600', 'indigo700', 'indigo800'), - violet: colorSchemaFn('violet50', 'violet600', 'violet700', 'violet800'), - purple: colorSchemaFn('purple50', 'purple600', 'purple700', 'purple800'), - fuchsia: colorSchemaFn('fuchsia50', 'fuchsia600', 'fuchsia700', 'fuchsia800'), - pink: colorSchemaFn('pink50', 'pink600', 'pink700', 'pink800'), - rose: colorSchemaFn('rose50', 'rose600', 'rose700', 'rose800') - }, + ${({ variant }) => variant === 'pill' && `border-radius: 9999px;`} - styleSchema: { - square: { - borderRadius: '0' - }, - rounded: { - borderRadius: '0.5rem' - }, - pill: { - borderRadius: '9999px' - } - }, + ${({ size }) => + size === 'small' && + ` + height: 2rem; + font-size: 0.875rem; + `} - size: { - small: { - height: '2rem', - fontSize: '0.875rem' - }, - medium: { - height: '3rem', - fontSize: '1rem' - } - }, + ${({ size }) => + size === 'medium' && + ` + height: 3rem; + font-size: 1rem; + `} - font: { - baloo: { - fontFamily: theme.fonts.baloo - }, - montserrat: { - fontFamily: theme.fonts.montserrat - }, - roboto: { - fontFamily: theme.fonts.roboto - } - }, - - outline: { - true: { - background: 'transparent' - } - } - }, - - compoundVariants: [ - { - colorSchema: 'slate', - outline: true, - css: outlineVariantFn('slate600') - }, - { - colorSchema: 'red', - outline: true, - css: outlineVariantFn('red600') - }, - { - colorSchema: 'orange', - outline: true, - css: outlineVariantFn('orange600') - }, - { - colorSchema: 'amber', - outline: true, - css: outlineVariantFn('amber600') - }, - { - colorSchema: 'yellow', - outline: true, - css: outlineVariantFn('yellow600') - }, - { - colorSchema: 'lime', - outline: true, - css: outlineVariantFn('lime600') - }, - { - colorSchema: 'green', - outline: true, - css: outlineVariantFn('green600') - }, - { - colorSchema: 'emerald', - outline: true, - css: outlineVariantFn('emerald600') - }, - { - colorSchema: 'teal', - outline: true, - css: outlineVariantFn('teal600') - }, - { - colorSchema: 'cyan', - outline: true, - css: outlineVariantFn('cyan600') - }, - { - colorSchema: 'sky', - outline: true, - css: outlineVariantFn('sky600') - }, - { - colorSchema: 'blue', - outline: true, - css: outlineVariantFn('blue600') - }, - { - colorSchema: 'indigo', - outline: true, - css: outlineVariantFn('indigo600') - }, - { - colorSchema: 'violet', - outline: true, - css: outlineVariantFn('violet600') - }, - { - colorSchema: 'purple', - outline: true, - css: outlineVariantFn('purple600') - }, - { - colorSchema: 'fuchsia', - outline: true, - css: outlineVariantFn('fuchsia600') - }, - { - colorSchema: 'pink', - outline: true, - css: outlineVariantFn('pink600') - }, - { - colorSchema: 'rose', - outline: true, - css: outlineVariantFn('rose600') - } - ], - - defaultVariants: { - colorSchema: 'teal', - styleSchema: 'pill', - size: 'medium', - font: 'roboto', - outline: false - } -}) - -export type ButtonVariantProps = VariantProps + ${({ outlined, color }) => + outlined && + ` + background: transparent; + color: ${color}; + border-color: ${color}; + `} +` diff --git a/src/components/Dash/ButtonsStyleSelect/index.tsx b/src/components/Dash/ButtonsStyleSelect/index.tsx index 81c89e8..b630054 100644 --- a/src/components/Dash/ButtonsStyleSelect/index.tsx +++ b/src/components/Dash/ButtonsStyleSelect/index.tsx @@ -1,18 +1,17 @@ import { useData } from '../../../hooks/useData' -import type { ButtonVariantProps } from '../../Button' export function ButtonsStyleSelect() { const { data, setData } = useData() return ( ) } diff --git a/src/components/Dash/SaveChangesAlert/index.tsx b/src/components/Dash/SaveChangesAlert/index.tsx index 8696e86..66de158 100644 --- a/src/components/Dash/SaveChangesAlert/index.tsx +++ b/src/components/Dash/SaveChangesAlert/index.tsx @@ -40,23 +40,17 @@ export function SaveChangesAlert({ setData(initialData) } - return ( - + return hasUnsavedChanges ? ( + You have unsaved changes. - - - ) + ) : null } diff --git a/src/components/Dash/SaveChangesAlert/styles.ts b/src/components/Dash/SaveChangesAlert/styles.ts index c9d1bbd..2b018b1 100644 --- a/src/components/Dash/SaveChangesAlert/styles.ts +++ b/src/components/Dash/SaveChangesAlert/styles.ts @@ -1,38 +1,19 @@ -import { styled, theme } from '../../../styles/stitches.config' +import styled from 'styled-components' -export const Wrapper = styled('div', { - position: 'fixed', - top: 0, - left: 0, - width: '50%', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '1rem', - background: theme.colors.sky200, - color: theme.colors.slate700, - fontFamily: theme.fonts.roboto, - fontSize: '0.875rem', - lineHeight: 1, - transition: 'all 0.25s ease-in-out', +export const Wrapper = styled.div` + position: fixed; + top: 0; + left: 0; + width: 50%; + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + font-size: 0.875rem; + line-height: 1; +` - variants: { - show: { - true: { - opacity: 1 - }, - false: { - opacity: 0 - } - } - }, - - defaultVariant: { - show: false - } -}) - -export const ButtonsGroup = styled('div', { - display: 'flex', - gap: '1rem' -}) +export const ButtonsGroup = styled.div` + display: flex; + gap: 1rem; +` diff --git a/src/components/Dash/index.tsx b/src/components/Dash/index.tsx index 7a808ee..5ad0359 100644 --- a/src/components/Dash/index.tsx +++ b/src/components/Dash/index.tsx @@ -1,8 +1,8 @@ import { isEqual } from 'lodash' import { useEffect, useState } from 'react' +import Collapsible from 'react-collapsible' import { useData } from '../../hooks/useData' -import type { Data } from '../../types/Data' import { getLocalStorageData, setLocalStorageData } from '../../utils/localStorage' import { Home } from '../Home' import { ColorsSettings } from './ColorsSettings' @@ -10,15 +10,12 @@ import { DataSettings } from './DataSettings' import { SaveChangesAlert } from './SaveChangesAlert' import { Content, Preview, Wrapper } from './styles' -type DashProps = { - initialData: Data -} - -export function Dash({ initialData }: DashProps) { +export function Dash() { const { data, setData } = useData() const [isLoading, setIsLoading] = useState(true) const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false) const [activeTab, setActiveTab] = useState<'data' | 'colors'>('data') + const initialData = data useEffect(() => { if (isLoading) { @@ -53,13 +50,18 @@ export function Dash({ initialData }: DashProps) { />

Dash

- {tabs.map(tab => ( - ))} {body[activeTab]} + + +

This is the collapsible content. It can be any element or React component you like.

+

It can even be another Collapsible component. Check out the next section!

+
diff --git a/src/components/Dash/styles.ts b/src/components/Dash/styles.ts index 4a2714c..2499eb3 100644 --- a/src/components/Dash/styles.ts +++ b/src/components/Dash/styles.ts @@ -1,30 +1,28 @@ -import { styled, theme } from '../../styles/stitches.config' +import styled from 'styled-components' -export const Wrapper = styled('main', { - display: 'grid', - gridTemplateColumns: '1fr 1fr', - position: 'fixed', - inset: 0 -}) +export const Wrapper = styled.main` + display: grid; + grid-template-columns: 1fr 1fr; + position: fixed; + inset: 0; +` -export const Content = styled('div', { - display: 'flex', - flexDirection: 'column', - gap: '1rem', - padding: '5rem 1rem 1rem', - fontFamily: theme.fonts.roboto, - color: theme.colors.slate900, - background: theme.colors.slate50, - overflowY: 'scroll' -}) +export const Content = styled.div` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 5rem 1rem 1rem; + font-family: 'Roboto', sans-serif; + overflow-y: scroll; +` -export const Preview = styled('div', { - position: 'relative', - overflowY: 'scroll', +export const Preview = styled.div` + position: relative; + overflow-y: scroll; - '&::after': { - content: '', - position: 'absolute', - inset: 0 + &::after { + content: ''; + position: absolute; + inset: 0; } -}) +` diff --git a/src/components/Home/index.tsx b/src/components/Home/index.tsx index b92117d..89c1ff6 100644 --- a/src/components/Home/index.tsx +++ b/src/components/Home/index.tsx @@ -1,7 +1,4 @@ -import Head from 'next/head' - import { useData } from '../../hooks/useData' -import { theme } from '../../styles/stitches.config' import { Avatar } from '../Avatar' import { Button } from '../Button' import { SocialLinks } from '../SocialLinks' @@ -9,34 +6,24 @@ import { Content, Description, Name, Wrapper } from './styles' export const Home = () => { const { data } = useData() - const { colors, buttonsSchema, outline, font, name, description } = data.settings + const { colors, buttonsSchema, font, name, description } = data.settings return ( - - -