-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
614 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Navbar from 'components/common/Navbar'; | ||
import Image from 'next/image'; | ||
import { useRouter } from 'next/router'; | ||
import errorImage from 'public/img/error.png'; | ||
|
||
function Error() { | ||
const router = useRouter(); | ||
|
||
return ( | ||
<div className="h-full w-full bg-body-mask bg-cover"> | ||
<Navbar theme="dark" /> | ||
<main className="w-full flex justify-center"> | ||
<div className="container flex flex-col mt-[100px] items-center"> | ||
<div className="w-full relative"> | ||
<div className="w-full pt-1/4 opacity-75"> | ||
<Image | ||
src={errorImage} | ||
className="w-1/2 md:w-auto mx-auto" | ||
alt="error" | ||
/> | ||
</div> | ||
</div> | ||
<div className="text-16 md:text-45 pt-[45px] md:pt-[100px] text-primary-500 font-semibold"> | ||
Sorry, something went wrong | ||
</div> | ||
<div className="text-14 md:text-20 w-[80%] text-center mt-10 md:mt-5 text-neutral-800"> | ||
An unexpected error has occurred. If reloading the page does not fix | ||
it, please contact Rango support. | ||
</div> | ||
<button | ||
onClick={() => router.reload()} | ||
className="text-baseForeground bg-primary-600 py-10 md:py-15 px-20 mt-50 text-center rounded-full w-[224px] text-14 md:text-18 font-medium"> | ||
Reload | ||
</button> | ||
</div> | ||
</main> | ||
</div> | ||
); | ||
} | ||
|
||
export default Error; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { SvgIconPropsWithChildren } from '../SvgIcon'; | ||
|
||
export type RefreshButtonProps = { | ||
onClick: (() => void) | undefined; | ||
refreshTime: number; | ||
}; | ||
|
||
export type RefreshProgressButtonProps = SvgIconPropsWithChildren & { | ||
progress: number; | ||
}; | ||
|
||
export type EllipseProps = { | ||
fill?: string; | ||
progress?: number; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React, { createElement } from 'react'; | ||
|
||
import { SvgIcon } from '../SvgIcon'; | ||
import { EllipseProps, RefreshProgressButtonProps } from './RefreshButton.type'; | ||
|
||
const DEFAULT_STROKE_DASHOFFSET = 59; | ||
const MAX_PERCENTAGE = 100; | ||
const MAX_PROGRESS = 41; | ||
const MIN_PROGRESS = 0; | ||
const NORMALIZE_FACTOR = 10; | ||
const OPACITY_THRESHOLD = 82; | ||
const DIVISION_FACTOR = 2; | ||
|
||
const Ellipse = (props: EllipseProps) => { | ||
const type = props.progress ? 'in-progress' : 'basic'; | ||
return ( | ||
<ellipse | ||
cx="12.5" | ||
cy="12.5" | ||
rx="7.7" | ||
ry="7.7" | ||
stroke="currentColor" | ||
strokeDashoffset={props.progress || DEFAULT_STROKE_DASHOFFSET} | ||
style={{ | ||
strokeLinecap: 'round', | ||
fill: 'none', | ||
strokeDasharray: 100, | ||
transform: `rotate(20deg)`, | ||
transformOrigin: 'center', | ||
...(type === 'in-progress' && { stroke: '#5BABFF', strokeWidth: 2 }), | ||
...(type === 'basic' && { strokeWidth: 1.8 }), | ||
}} | ||
/> | ||
); | ||
}; | ||
|
||
function RefreshProgressButton(props: RefreshProgressButtonProps) { | ||
const normalizeValue = (value: number) => { | ||
return (value - OPACITY_THRESHOLD) / NORMALIZE_FACTOR; | ||
}; | ||
const normalizedProgress = Math.min( | ||
props.progress / DIVISION_FACTOR, | ||
MAX_PROGRESS, | ||
); | ||
const opacity = | ||
normalizedProgress !== MAX_PROGRESS | ||
? MIN_PROGRESS | ||
: normalizeValue(props.progress); | ||
|
||
return createElement( | ||
SvgIcon, | ||
props, | ||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> | ||
<Ellipse /> | ||
<Ellipse progress={MAX_PERCENTAGE - normalizedProgress} /> | ||
|
||
<path | ||
d="M19.2696 9.6089C19.1207 9.49207 19.0218 9.31141 19.01 9.10738L18.807 5.14476C18.788 4.77467 19.0763 4.45089 19.4464 4.43183C19.8165 4.41278 20.1402 4.70108 20.1593 5.07117L20.3622 9.0338C20.3813 9.40389 20.093 9.72767 19.7229 9.74672C19.5584 9.76661 19.3973 9.70903 19.2696 9.6089Z" | ||
fill="currentColor" | ||
/> | ||
<path | ||
d="M19.2696 9.6089C19.1207 9.49207 19.0218 9.31141 19.01 9.10738L18.807 5.14476C18.788 4.77467 19.0763 4.45089 19.4464 4.43183C19.8165 4.41278 20.1402 4.70108 20.1593 5.07117L20.3622 9.0338C20.3813 9.40389 20.093 9.72767 19.7229 9.74672C19.5584 9.76661 19.3973 9.70903 19.2696 9.6089Z" | ||
fillOpacity={opacity} | ||
className="fill-running" | ||
/> | ||
<path | ||
d="M15.5108 9.47903C15.3476 9.35108 15.2457 9.14511 15.2505 8.9198C15.2639 8.55221 15.575 8.25778 15.9482 8.26404L19.707 8.3939C20.0802 8.40016 20.3691 8.71837 20.3628 9.09152C20.3565 9.46466 20.0383 9.75353 19.6652 9.74728L15.9007 9.62451C15.7529 9.62312 15.6243 9.56804 15.5108 9.47903Z" | ||
fill="currentColor" | ||
/> | ||
<path | ||
d="M15.5108 9.47903C15.3476 9.35108 15.2457 9.14511 15.2505 8.9198C15.2639 8.55221 15.575 8.25778 15.9482 8.26404L19.707 8.3939C20.0802 8.40016 20.3691 8.71837 20.3628 9.09152C20.3565 9.46466 20.0383 9.75353 19.6652 9.74728L15.9007 9.62451C15.7529 9.62312 15.6243 9.56804 15.5108 9.47903Z" | ||
fillOpacity={opacity} | ||
className="fill-running" | ||
/> | ||
</svg>, | ||
); | ||
} | ||
|
||
export default RefreshProgressButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import RefreshProgressButton from './RefreshProgressButton'; | ||
import { RefreshButtonProps } from './RefreshButton.type'; | ||
|
||
const REFRESH_INTERVAL = 1000; | ||
const MAX_PERCENTAGE = 100; | ||
|
||
export default function RefreshButton(props: RefreshButtonProps) { | ||
const { onClick, refreshTime } = props; | ||
const [elapsedTime, setElapsedTime] = useState(0); | ||
const [isRefetch, setIsRefetch] = useState(false); | ||
|
||
const handleVisibilityChange = (interval?: number) => { | ||
if (document.hidden && interval) { | ||
clearTimeout(interval); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
let interval: number | undefined; | ||
if (onClick) { | ||
interval = window.setInterval(() => { | ||
setElapsedTime((prevTime) => prevTime + 1); | ||
|
||
if (elapsedTime === refreshTime) { | ||
handleRefreshClick(); | ||
} | ||
}, REFRESH_INTERVAL); | ||
} else { | ||
clearTimeout(interval); | ||
} | ||
|
||
document.addEventListener('visibilitychange', () => | ||
handleVisibilityChange(interval), | ||
); | ||
|
||
return () => { | ||
document.removeEventListener('visibilitychange', () => | ||
handleVisibilityChange(interval), | ||
); | ||
if (interval) { | ||
clearInterval(interval); | ||
} | ||
}; | ||
}, [elapsedTime, onClick]); | ||
|
||
const clearTimeout = (interval?: number) => { | ||
if (interval) { | ||
clearInterval(interval); | ||
} | ||
setElapsedTime(0); | ||
}; | ||
|
||
const handleRefreshClick = () => { | ||
if (onClick) onClick(); | ||
setElapsedTime(0); | ||
setIsRefetch(true); | ||
}; | ||
|
||
return ( | ||
<button onClick={handleRefreshClick} disabled={!onClick}> | ||
<div | ||
className="p-[2px]" | ||
style={{ | ||
...(isRefetch && { | ||
transform: `rotate(360deg)`, | ||
transition: 'transform 1s ease-in-out', | ||
}), | ||
}} | ||
onTransitionEnd={() => setIsRefetch(false)}> | ||
<RefreshProgressButton | ||
size="24" | ||
className="text-neutral-400" | ||
progress={(elapsedTime / refreshTime) * MAX_PERCENTAGE} | ||
/> | ||
</div> | ||
</button> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type PropTypes = { | ||
width?: number; | ||
height?: number; | ||
variant?: 'circular' | 'rectangular'; | ||
className?: string; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { PropTypes } from './Skeleton.types'; | ||
|
||
export function Skeleton(props: PropTypes) { | ||
const { height, width, variant = 'rectangular', className = '' } = props; | ||
return ( | ||
<div | ||
style={{ | ||
background: | ||
'linear-gradient(90deg, #C8E2FF 0%, rgba(200, 226, 255, 0.20) 70%, #C8E2FF 100%)', | ||
backgroundSize: '800px 100px', | ||
...(width && { width: `${width}px` }), | ||
...(height && { height: `${height}px` }), | ||
}} | ||
className={`animate-wave ${ | ||
variant === 'rectangular' ? 'rounded-soft' : 'rounded-full' | ||
} ${className} `}></div> | ||
); | ||
} |
Oops, something went wrong.