Skip to content

Commit

Permalink
refactor(infrastructure): removes cra boilerplate, introduces Vite (#15)
Browse files Browse the repository at this point in the history
Co-authored-by: Asman Umbetov <[email protected]>
  • Loading branch information
fastndead and Asman Umbetov authored Nov 25, 2023
1 parent a8a9841 commit 0fb57ff
Show file tree
Hide file tree
Showing 58 changed files with 1,081 additions and 6,409 deletions.
11 changes: 5 additions & 6 deletions src/App.tsx → client/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ import SocketIoErrorCatcher from 'components/SocketIoErrorCatcher'
import { useTransition, a, config } from '@react-spring/web'
import { useLocation, Routes, Route } from 'react-router-dom'

function App() {
function App() {
const location = useLocation()
const transitions = useTransition(location.pathname, {
from: { opacity: 0 },
enter: { opacity: 1, position: 'fixed', top: 0 },
leave: { opacity: 0 },
config:{
config: {
...config.gentle,
duration: 400
} ,
trail: 400
duration: 400,
},
trail: 400,
})

return (
Expand Down Expand Up @@ -47,7 +47,6 @@ function App() {
</a.div>
))}
</SocketIoErrorCatcher>

</NotificationContextProvider>
)
}
Expand Down
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,50 @@ type Props = {

export default function EnterNameModal({ isVisible, onClose }: Props) {
const [name, setName] = useState<string>('')
const [validationError, setValidationError] = useState<string| null>(null)
const [validationError, setValidationError] = useState<string | null>(null)
const { addNotification } = useNotifications()

const handleChangeName = useCallback<ReactEventHandler<HTMLInputElement>>((e) => {
setName(e.currentTarget.value)
}, [])

const handleSubmit = useCallback<ReactEventHandler<HTMLFormElement>>(async (e) => {
e.preventDefault()
if (!name) {
setValidationError('Name cannot be empty')
return
}

if (name.length > 13) {
setValidationError('Name cannot be longer than 13 characters')
return
}
try {
const response = await fetch(`${apiBaseUrl}/mynameis`, {
method: 'POST',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name }), // body data type must match "Content-Type" header
})
const handleSubmit = useCallback<ReactEventHandler<HTMLFormElement>>(
async (e) => {
e.preventDefault()
if (!name) {
setValidationError('Name cannot be empty')
return
}

if (!response.ok) {
throw new Error('Server error')
if (name.length > 13) {
setValidationError('Name cannot be longer than 13 characters')
return
}
try {
const response = await fetch(`${apiBaseUrl}/mynameis`, {
method: 'POST',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name }), // body data type must match "Content-Type" header
})

if (!response.ok) {
throw new Error('Server error')
}

onClose(name)
} catch {
addNotification({ type: 'error', text: 'Something is wrong on the server, refresh the page or try again later' })
}

}, [name, onClose, addNotification])
onClose(name)
} catch {
addNotification({
type: 'error',
text: 'Something is wrong on the server, refresh the page or try again later',
})
}
},
[name, onClose, addNotification]
)

return (
<Modal
Expand Down
File renamed without changes.
59 changes: 59 additions & 0 deletions client/components/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { ReactNode, useCallback, useEffect } from 'react'
import CloseModalSvg from 'assets/closeModal.svg'
import { animated, useSpring, useTransition } from '@react-spring/web'
import classNames from 'classnames'

type Props = {
isVisible: boolean
children: ReactNode
title?: string
className?: string
onClose?(): void
}

export default function Modal({ className, isVisible, children, title, onClose }: Props) {
const overlayTransition = useTransition(isVisible ? true : [], {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
})

const modalTransition = useTransition(isVisible, {
from: { opacity: 0, y: -30 },
enter: { opacity: 1, y: 0 },
leave: { opacity: 0 },
config: {
tension: 310,
friction: 20,
mass: 2,
},
})

return overlayTransition((modalOverlaySpring) => (
<animated.div
style={{
...modalOverlaySpring,
}}
className={classNames(
'fixed top-0 left-0 w-screen h-screen flex justify-center items-center'
)}
>
{modalTransition((springs) => (
<animated.div
className={classNames('absolute bg-white z-50 rounded-3xl p-6 shadow-modal', className)}
style={{
...springs,
}}
>
<div className='w-full h-11 flex justify-between'>
<h3 className='font-normal text-2xl'>{title || ''}</h3>
{onClose && <CloseModalSvg onClick={onClose} className='cursor-pointer' />}
</div>
{children}
</animated.div>
))}

<animated.div className='fixed top-0 left-0 opacity-70 w-screen h-screen bg-modal-grey z-40 ' />
</animated.div>
))
}
45 changes: 45 additions & 0 deletions client/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import IconButton from 'components/IconButton'
import React, { useCallback } from 'react'
import HomeIcon from 'assets/home.svg'
import HomeHoverIcon from 'assets/homeHover.svg'
import LinkIcon from 'assets/copyLink.svg'
import LinkHoverIcon from 'assets/copyLinkHover.svg'
import SettingsIcon from 'assets/settings.svg'
import SettingsHoverIcon from 'assets/settingsHover.svg'
import { Link } from 'react-router-dom'
import { useNotifications } from 'hooks/useNotifications'

export default function Sidebar() {
const { addNotification } = useNotifications()
const copyToClipboard = useCallback(() => {
navigator.clipboard.writeText(window.location.href)
addNotification({ type: 'success', text: 'Link has been successfuly copied' })
}, [addNotification])

const areSettingsImplemented = false

return (
<div className='fixed top-0 left-0 z-50 h-screen w-20 inset-0 bg-primary-idle overflow-hidden'>
<div className='mt-20 w-full flex flex-col items-center'>
<Link to='/'>
<IconButton icon={<HomeIcon />} hoverIcon={<HomeHoverIcon />} label='home' />
</Link>
{areSettingsImplemented && (
<IconButton
icon={<SettingsIcon />}
hoverIcon={<SettingsHoverIcon />}
className='mt-3.5'
label='settings'
/>
)}
<IconButton
icon={<LinkIcon />}
onClick={copyToClipboard}
hoverIcon={<LinkHoverIcon />}
className='mt-3.5'
label='copy link'
/>
</div>
</div>
)
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions client/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
declare module '*.svg' {
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>
export default content
}

/// <reference types="vite/client" />
/// <reference types="vite/client" />
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { CSSProperties, useState } from 'react'
import { animated, useSpring } from '@react-spring/web'
import classNames from 'classnames'
import { ReactComponent as ArrowSvg } from 'assets/arrow.svg'
import ArrowSvg from 'assets/arrow.svg'

type Props = {
value?: string | null
isRevealed?: boolean
animationProp: CSSProperties
animationProp: CSSProperties
}

export default function Card({ isRevealed, animationProp, value }: Props) {
Expand All @@ -22,28 +22,20 @@ export default function Card({ isRevealed, animationProp, value }: Props) {
style={{
height: 80,
width: 50,
...animationProp
...animationProp,
}}
>
{
value && !isRevealed && (
<ArrowSvg
className='absolute -top-6 left-1/2 -translate-x-2/4'
/>
)
}
<animated.div
{value && !isRevealed && <ArrowSvg className='absolute -top-6 left-1/2 -translate-x-2/4' />}
<animated.div
className={classNames('absolute card', {
'bg-primary-emphasis': value
'bg-primary-emphasis': value,
})}
style={{
style={{
perspective: 400,
opacity: opacity.to(o => 1 - o),
rotateY
opacity: opacity.to((o) => 1 - o),
rotateY,
}}
>

</animated.div>
></animated.div>

<animated.div
className='absolute border cursor-pointer bg-white border-primary-emphasis rounded-lg shadow-card z-1'
Expand All @@ -53,17 +45,14 @@ export default function Card({ isRevealed, animationProp, value }: Props) {
perspective: 400,
height: 80,
width: 50,
opacity: opacity.to(o => o > 0.5 ? o : 0),
opacity: opacity.to((o) => (o > 0.5 ? o : 0)),
rotateY,
}}
>
<div
className='absolute inset-2/4 w-6 h-6 flex items-center justify-center font-normal -translate-x-1/2 -translate-y-1/2 text-2xl'
>
<div className='absolute inset-2/4 w-6 h-6 flex items-center justify-center font-normal -translate-x-1/2 -translate-y-1/2 text-2xl'>
{value}
</div>
</animated.div>

</animated.div>
)
}
Loading

0 comments on commit 0fb57ff

Please sign in to comment.