types: improved component typing

This commit is contained in:
wonderlandpark 2021-05-18 11:16:48 +09:00
parent 74fa828189
commit 3b52e4c386
43 changed files with 236 additions and 235 deletions

View File

@ -1,7 +1,7 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import Logger from '@utils/Logger' import Logger from '@utils/Logger'
const Advertisement = ({ size = 'short' }: AdvertisementProps): JSX.Element => { const Advertisement: React.FC<AdvertisementProps> = ({ size = 'short' }) => {
useEffect(() => { useEffect(() => {
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
window.adsbygoogle = window.adsbygoogle || [] window.adsbygoogle = window.adsbygoogle || []

View File

@ -3,15 +3,14 @@ import Link from 'next/link'
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar')) const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
const Application = ({ type, id, name }: ApplicationProps): JSX.Element => { const Application: React.FC<ApplicationProps> = ({ type, id, name }) => {
return ( return <Link href={`/developers/applications/${type + 's'}/${id}`}>
<Link href={`/developers/applications/${type + 's'}/${id}`}> <div className='relative px-2 py-4 text-center dark:bg-discord-black bg-little-white rounded-lg cursor-pointer transform hover:-translate-y-1 transition duration-100 ease-in'>
<div className='relative px-2 py-4 text-center dark:bg-discord-black bg-little-white rounded-lg cursor-pointer transform hover:-translate-y-1 transition duration-100 ease-in'> <DiscordAvatar userID={id} className='px-2 w-full rounded-xl' />
<DiscordAvatar userID={id} className='px-2 w-full rounded-xl' /> <h2 className='pt-2 whitespace-nowrap text-xl font-medium truncate'>{name}</h2>
<h2 className='pt-2 whitespace-nowrap text-xl font-medium truncate'>{name}</h2> </div>
</div> </Link>
</Link>
)
} }
interface ApplicationProps { interface ApplicationProps {

View File

@ -9,115 +9,114 @@ const Divider = dynamic(() => import('@components/Divider'))
const Tag = dynamic(() => import('@components/Tag')) const Tag = dynamic(() => import('@components/Tag'))
const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar')) const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
const BotCard = ({ manage = false, bot }: BotProps): JSX.Element => { const BotCard: React.FC<BotCardProps> = ({ manage = false, bot }) => {
return ( return <div className='container mb-16 transform hover:-translate-y-1 transition duration-100 ease-in cursor-pointer'>
<div className='container mb-16 transform hover:-translate-y-1 transition duration-100 ease-in cursor-pointer'> <div className='relative'>
<div className='relative'> <div className='container mx-auto'>
<div className='container mx-auto'> <div className='h-full'>
<div className='h-full'> <div
<div className='relative mx-auto h-full text-black dark:text-white dark:bg-discord-black bg-little-white rounded-2xl shadow-xl'
className='relative mx-auto h-full text-black dark:text-white dark:bg-discord-black bg-little-white rounded-2xl shadow-xl' style={
style={ checkBotFlag(bot.flags, 'trusted') && bot.banner
checkBotFlag(bot.flags, 'trusted') && bot.banner ? {
? { background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${bot.banner}") center top / cover no-repeat`,
background: `linear-gradient(to right, rgba(34, 36, 38, 0.68), rgba(34, 36, 38, 0.68)), url("${bot.banner}") center top / cover no-repeat`, color: 'white',
color: 'white', }
} : {}
: {} }
} >
> <Link href={makeBotURL(bot)}>
<Link href={makeBotURL(bot)}> <div>
<div> <div className='flex h-44'>
<div className='flex h-44'> <div className='w-3/5'>
<div className='w-3/5'> <div className='flex justify-start'>
<div className='flex justify-start'> <DiscordAvatar
<DiscordAvatar size={128}
size={128} userID={bot.id}
userID={bot.id} alt='Avatar'
alt='Avatar' className='absolute -left-2 -top-8 mx-auto w-32 h-32 bg-white rounded-full'
className='absolute -left-2 -top-8 mx-auto w-32 h-32 bg-white rounded-full' />
/>
</div>
<div className='mt-28 px-4'>
<h2 className='px-1 text-sm'>
<i className={`fas fa-circle text-${Status[bot.status]?.color}`} />
{Status[bot.status]?.text}
</h2>
<h1 className='mb-3 text-left text-2xl font-bold truncate'>{bot.name}</h1>
</div>
</div> </div>
<div className='grid grid-cols-1 pr-5 py-5 w-2/5 h-0'>
<Tag <div className='mt-28 px-4'>
text={ <h2 className='px-1 text-sm'>
<> <i className={`fas fa-circle text-${Status[bot.status]?.color}`} />
<i className='fas fa-heart text-red-600' /> {formatNumber(bot.votes)} {Status[bot.status]?.text}
</> </h2>
} <h1 className='mb-3 text-left text-2xl font-bold truncate'>{bot.name}</h1>
dark
/>
<Tag
blurple
text={bot.servers ? <>{formatNumber(bot.servers)} </> : 'N/A'}
dark
/>
</div> </div>
</div> </div>
<p className='mb-10 px-4 h-6 text-left text-gray-400 text-sm font-medium'> <div className='grid grid-cols-1 pr-5 py-5 w-2/5 h-0'>
{bot.intro} <Tag
</p> text={
<div> <>
<div className='category flex flex-wrap px-2'> <i className='fas fa-heart text-red-600' /> {formatNumber(bot.votes)}
{bot.category.slice(0, 3).map(el => ( </>
<Tag key={el} text={el} href={`/categories/${el}`} dark /> }
))}{' '} dark
{bot.category.length > 3 && <Tag text={`+${bot.category.length - 3}`} dark />} />
</div> <Tag
blurple
text={bot.servers ? <>{formatNumber(bot.servers)} </> : 'N/A'}
dark
/>
</div> </div>
</div> </div>
</Link> <p className='mb-10 px-4 h-6 text-left text-gray-400 text-sm font-medium'>
<Divider /> {bot.intro}
<div className='w-full'> </p>
<div className='flex justify-evenly'> <div>
<Link href={makeBotURL(bot)}> <div className='category flex flex-wrap px-2'>
<a className='py-3 w-full text-center text-koreanbots-blue hover:text-white text-sm font-bold hover:bg-koreanbots-blue rounded-bl-2xl hover:shadow-lg transition duration-100 ease-in'> {bot.category.slice(0, 3).map(el => (
<Tag key={el} text={el} href={`/categories/${el}`} dark />
))}{' '}
{bot.category.length > 3 && <Tag text={`+${bot.category.length - 3}`} dark />}
</div>
</div>
</div>
</Link>
<Divider />
<div className='w-full'>
<div className='flex justify-evenly'>
<Link href={makeBotURL(bot)}>
<a className='py-3 w-full text-center text-koreanbots-blue hover:text-white text-sm font-bold hover:bg-koreanbots-blue rounded-bl-2xl hover:shadow-lg transition duration-100 ease-in'>
</a>
</Link>
{manage ? (
<Link href={`/manage/${bot.id}`}>
<a className='py-3 w-full text-center text-green-500 hover:text-white text-sm font-bold hover:bg-green-500 rounded-br-2xl hover:shadow-lg transition duration-100 ease-in'>
</a> </a>
</Link> </Link>
{manage ? ( ) : bot.state !== 'ok' ? <a
<Link href={`/manage/${bot.id}`}> className='py-3 w-full text-center text-discord-blurple text-sm font-bold rounded-br-2xl hover:shadow-lg transition duration-100 ease-in opacity-50 cursor-default select-none'
<a className='py-3 w-full text-center text-green-500 hover:text-white text-sm font-bold hover:bg-green-500 rounded-br-2xl hover:shadow-lg transition duration-100 ease-in'> >
</a>
</Link>
) : bot.state !== 'ok' ? <a
className='py-3 w-full text-center text-discord-blurple text-sm font-bold rounded-br-2xl hover:shadow-lg transition duration-100 ease-in opacity-50 cursor-default select-none'
>
</a> : </a> :
<a <a
href={ href={
bot.url || bot.url ||
`https://discordapp.com/oauth2/authorize?client_id=${bot.id}&scope=bot&permissions=0` `https://discordapp.com/oauth2/authorize?client_id=${bot.id}&scope=bot&permissions=0`
} }
rel='noopener noreferrer' rel='noopener noreferrer'
target='_blank' target='_blank'
className='py-3 w-full text-center text-discord-blurple hover:text-white text-sm font-bold hover:bg-discord-blurple rounded-br-2xl hover:shadow-lg transition duration-100 ease-in' className='py-3 w-full text-center text-discord-blurple hover:text-white text-sm font-bold hover:bg-discord-blurple rounded-br-2xl hover:shadow-lg transition duration-100 ease-in'
> >
</a> </a>
} }
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
) </div>
} }
interface BotProps { interface BotCardProps {
manage?: boolean manage?: boolean
bot: Bot bot: Bot
} }

View File

@ -1,25 +1,23 @@
import Link from 'next/link' import Link from 'next/link'
import { ReactNode } from 'react' import { ReactNode } from 'react'
const Button = ({ const Button: React.FC<ButtonProps> = ({
type = 'button', type = 'button',
className, className,
children, children,
href, href,
disabled=false, disabled=false,
onClick, onClick,
}: ButtonProps): JSX.Element => { }) => {
return href ? ( return href ? <Link href={!disabled && href}>
<Link href={!disabled && href}> <a
<a className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ??
className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ??
'bg-discord-blurple hover:opacity-80 dark:bg-very-black dark:hover:bg-discord-dark-hover text-white'}`} 'bg-discord-blurple hover:opacity-80 dark:bg-very-black dark:hover:bg-discord-dark-hover text-white'}`}
> >
{children} {children}
</a> </a>
</Link> </Link>
) : onClick ? ( : onClick ? <button
<button
type={disabled ? 'button' : type} type={disabled ? 'button' : type}
onClick={disabled ? null : onClick} onClick={disabled ? null : onClick}
className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ?? className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ??
@ -27,15 +25,14 @@ const Button = ({
> >
{children} {children}
</button> </button>
) : ( :
<button <button
type={disabled ? 'button' : type} type={disabled ? 'button' : type}
className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ?? className={`cursor-pointer rounded-md px-4 py-2 transition duration-300 ease select-none outline-none foucs:outline-none mr-1.5 ${className ??
'bg-discord-blurple hover:opacity-80 dark:bg-very-black dark:hover:bg-discord-dark-hover text-white'}`} 'bg-discord-blurple hover:opacity-80 dark:bg-very-black dark:hover:bg-discord-dark-hover text-white'}`}
> >
{children} {children}
</button> </button>
)
} }
interface ButtonProps { interface ButtonProps {

View File

@ -2,7 +2,7 @@ import { Ref } from 'react'
import HCaptcha from '@hcaptcha/react-hcaptcha' import HCaptcha from '@hcaptcha/react-hcaptcha'
const Captcha = ({ dark, onVerify }:CaptchaProps):JSX.Element => { const Captcha: React.FC<CaptchaProps> = ({ dark, onVerify }) => {
return <HCaptcha sitekey='43e556b4-cc90-494f-b100-378b906bb736' theme={dark ? 'dark' : 'light'} onVerify={onVerify}/> return <HCaptcha sitekey='43e556b4-cc90-494f-b100-378b906bb736' theme={dark ? 'dark' : 'light'} onVerify={onVerify}/>
} }

View File

@ -1,4 +1,4 @@
const ColorCard = ({ header, first, second, className }: ColorCardProps): JSX.Element => { const ColorCard: React.FC<ColorCardProps> = ({ header, first, second, className }) => {
return ( return (
<div className={`rounded-lg p-10 ${className} shadow-lg`}> <div className={`rounded-lg p-10 ${className} shadow-lg`}>
<h2 className='text-2xl font-bold'>{header}</h2> <h2 className='text-2xl font-bold'>{header}</h2>

View File

@ -1,11 +1,11 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
const Container = ({ const Container: React.FC<ContainerProps> = ({
ignoreColor, ignoreColor,
className, className,
paddingTop = false, paddingTop = false,
children, children,
}: ContainerProps): JSX.Element => { }) => {
return ( return (
<div <div
className={`${ignoreColor ? '' : 'text-black dark:text-gray-100'} ${ className={`${ignoreColor ? '' : 'text-black dark:text-gray-100'} ${

View File

@ -9,7 +9,7 @@ const Container = dynamic(() => import('@components/Container'))
const Divider = dynamic(() => import('@components/Divider')) const Divider = dynamic(() => import('@components/Divider'))
const SEO = dynamic(() => import('@components/SEO')) const SEO = dynamic(() => import('@components/SEO'))
const DeveloperLayout = ({ children, enabled, docs, currentDoc }:DeveloperLayout):JSX.Element => { const DeveloperLayout: React.FC<DeveloperLayout> = ({ children, enabled, docs, currentDoc }:DeveloperLayout) => {
const [ navbarEnabled, setNavbarOpen ] = useState(false) const [ navbarEnabled, setNavbarOpen ] = useState(false)
return <div className='flex min-h-screen'> return <div className='flex min-h-screen'>

View File

@ -3,12 +3,7 @@ import { KoreanbotsEndPoints } from '@utils/Constants'
import { supportsWebP } from '@utils/Tools' import { supportsWebP } from '@utils/Tools'
import Logger from '@utils/Logger' import Logger from '@utils/Logger'
const DiscordAvatar = (props: { const DiscordAvatar: React.FC<DiscordAvatarProps> = props => {
alt?: string
userID: string
className?: string
size? : 128 | 256 | 512
}) => {
const fallback = '/img/default.png' const fallback = '/img/default.png'
const [ webpUnavailable, setWebpUnavailable ] = useState<boolean>() const [ webpUnavailable, setWebpUnavailable ] = useState<boolean>()
@ -46,7 +41,12 @@ const DiscordAvatar = (props: {
/> />
} }
export default DiscordAvatar interface DiscordAvatarProps {
alt?: string
userID: string
className?: string
size? : 128 | 256 | 512
}
interface ImageEvent extends Event { interface ImageEvent extends Event {
target: ImageTarget target: ImageTarget
@ -55,4 +55,6 @@ interface ImageEvent extends Event {
interface ImageTarget extends EventTarget { interface ImageTarget extends EventTarget {
src: string src: string
onerror: (event: SyntheticEvent<HTMLImageElement, ImageEvent>) => void onerror: (event: SyntheticEvent<HTMLImageElement, ImageEvent>) => void
} }
export default DiscordAvatar

View File

@ -1,4 +1,4 @@
const Divider = ({ className }: { className?: string }) => { const Divider: React.FC<DividerProps> = ({ className }) => {
return ( return (
<div <div
className={`my-2 px-5 ${className || ''}`} className={`my-2 px-5 ${className || ''}`}
@ -10,4 +10,8 @@ const Divider = ({ className }: { className?: string }) => {
) )
} }
interface DividerProps {
className?: string
}
export default Divider export default Divider

View File

@ -2,7 +2,8 @@ import dynamic from 'next/dynamic'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const SEO = dynamic(() => import('@components/SEO')) const SEO = dynamic(() => import('@components/SEO'))
const Docs = ({ title, header, description, subheader, children }: DocsProps): JSX.Element => {
const Docs: React.FC<DocsProps> = ({ title, header, description, subheader, children }) => {
return ( return (
<> <>
<SEO <SEO
@ -32,9 +33,9 @@ const Docs = ({ title, header, description, subheader, children }: DocsProps): J
export default Docs export default Docs
interface DocsProps { interface DocsProps {
header: string | JSX.Element header: string | React.ReactNode
title?: string title?: string
description?: string description?: string
subheader?: string subheader?: string
children: JSX.Element | JSX.Element[] children: React.ReactNode
} }

View File

@ -6,7 +6,7 @@ import { Theme } from '@types'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const Toggle = dynamic(() => import('@components/Toggle')) const Toggle = dynamic(() => import('@components/Toggle'))
const Footer = ({ theme, setTheme }: FooterProps): JSX.Element => { const Footer: React.FC<FooterProps> = ({ theme, setTheme }) => {
return ( return (
<div className='releative z-30'> <div className='releative z-30'>
<div className='bottom-0 text-white bg-discord-black py-24'> <div className='bottom-0 text-white bg-discord-black py-24'>

View File

@ -6,7 +6,7 @@ import { ErrorText } from '@utils/Constants'
const SEO = dynamic(() => import('@components/SEO')) const SEO = dynamic(() => import('@components/SEO'))
const Button = dynamic(() => import('@components/Button')) const Button = dynamic(() => import('@components/Button'))
const Forbidden = ():JSX.Element => { const Forbidden:React.FC = () => {
const router = useRouter() const router = useRouter()
return <> return <>
<SEO title='권한이 없습니다' /> <SEO title='권한이 없습니다' />

View File

@ -1,6 +1,6 @@
import { Field } from 'formik' import { Field } from 'formik'
const CheckBox = ({ name, ...props }: CheckBoxProps): JSX.Element => { const CheckBox: React.FC<CheckBoxProps> = ({ name, ...props }) => {
return <Field type='checkbox' name={name} className='form-checkbox text-koreanbots-blue bg-gray-300 h-4 w-4 rounded' {...props} /> return <Field type='checkbox' name={name} className='form-checkbox text-koreanbots-blue bg-gray-300 h-4 w-4 rounded' {...props} />
} }

View File

@ -1,6 +1,6 @@
import { Field } from 'formik' import { Field } from 'formik'
const CsrfToken = ({ token }: CsrfTokenProps): JSX.Element => { const CsrfToken: React.FC<CsrfTokenProps> = ({ token }) => {
return <Field name='_csrf' hidden value={token} readOnly /> return <Field name='_csrf' hidden value={token} readOnly />
} }

View File

@ -1,18 +1,18 @@
import { Field } from 'formik' import { Field } from 'formik'
const Input = ({ name, placeholder }: InputProps): JSX.Element => { const Input: React.FC<InputProps> = ({ name, placeholder, ...props }) => {
return ( return <Field
<Field {...props}
name={name} name={name}
className='border-grey-light relative px-3 w-full h-10 text-black dark:text-white dark:bg-very-black border dark:border-transparent rounded outline-none' className='border-grey-light relative px-3 w-full h-10 text-black dark:text-white dark:bg-very-black border dark:border-transparent rounded outline-none'
placeholder={placeholder} placeholder={placeholder}
/> />
)
} }
interface InputProps { interface InputProps {
name: string name: string
placeholder?: string placeholder?: string
[key: string]: unknown
} }
export default Input export default Input

View File

@ -1,4 +1,4 @@
const Label = ({ const Label: React.FC<LabelProps> = ({
For, For,
children, children,
label, label,
@ -7,31 +7,27 @@ const Label = ({
grid = true, grid = true,
short = false, short = false,
required = false, required = false,
}: LabelProps): JSX.Element => { }) => {
return ( return <label
<> className={grid ? 'grid grid-cols-1 xl:grid-cols-4 gap-2 my-4' : 'inline-flex items-center'}
<label htmlFor={For}
className={grid ? 'grid grid-cols-1 xl:grid-cols-4 gap-2 my-4' : 'inline-flex items-center'} >
htmlFor={For} {label && (
> <div className='col-span-1 text-sm'>
{label && ( <h3 className='text-koreanbots-blue text-lg font-bold'>
<div className='col-span-1 text-sm'> {label}
<h3 className='text-koreanbots-blue text-lg font-bold'> {required && (
{label} <span className='align-text-top text-red-500 text-base font-semibold'> *</span>
{required && ( )}
<span className='align-text-top text-red-500 text-base font-semibold'> *</span> </h3>
)} {labelDesc}
</h3> </div>
{labelDesc} )}
</div> <div className={short ? 'col-span-1' : 'col-span-3'}>
)} {children}
<div className={short ? 'col-span-1' : 'col-span-3'}> <div className='mt-1 text-red-500 text-xs font-light'>{error}</div>
{children} </div>
<div className='mt-1 text-red-500 text-xs font-light'>{error}</div> </label>
</div>
</label>
</>
)
} }
interface LabelProps { interface LabelProps {

View File

@ -1,32 +1,30 @@
import ReactSelect from 'react-select' import ReactSelect from 'react-select'
const Select = ({ placeholder, options, handleChange, handleTouch, value }: SelectProps): JSX.Element => { const Select: React.FC<SelectProps> = ({ placeholder, options, handleChange, handleTouch, value }) => {
return ( return <ReactSelect
<ReactSelect styles={{
styles={{ control: provided => {
control: provided => { return { ...provided, border: 'none' }
return { ...provided, border: 'none' } },
}, option: provided => {
option: provided => { return {
return { ...provided,
...provided, cursor: 'pointer',
cursor: 'pointer', ':hover': {
':hover': { opacity: '0.7',
opacity: '0.7', },
}, }
} },
}, }}
}} className='border-grey-light border dark:border-transparent rounded'
className='border-grey-light border dark:border-transparent rounded' classNamePrefix='outline-none text-black dark:bg-very-black dark:text-white '
classNamePrefix='outline-none text-black dark:bg-very-black dark:text-white ' placeholder={placeholder || '선택해주세요.'}
placeholder={placeholder || '선택해주세요.'} options={options}
options={options} onChange={handleChange}
onChange={handleChange} onBlur={handleTouch}
onBlur={handleTouch} noOptionsMessage={() => '검색 결과가 없습니다.'}
noOptionsMessage={() => '검색 결과가 없습니다.'} defaultValue={value}
defaultValue={value} />
/>
)
} }
interface SelectProps { interface SelectProps {

View File

@ -31,7 +31,7 @@ const SortableMultiValueLabel = SortableHandle(props => (
const SortableSelect = SortableContainer(ReactSelect) const SortableSelect = SortableContainer(ReactSelect)
const Select = ({ placeholder, options, values, setValues, handleChange, handleTouch }:SelectProps):JSX.Element => { const Select: React.FC<SelectProps> = ({ placeholder, options, values, setValues, handleChange, handleTouch }) => {
const onSortEnd = ({ oldIndex, newIndex }) => { const onSortEnd = ({ oldIndex, newIndex }) => {
const newValue = arrayMove(values, oldIndex, newIndex) const newValue = arrayMove(values, oldIndex, newIndex)
setValues(newValue) setValues(newValue)

View File

@ -10,7 +10,7 @@ import 'emoji-mart/css/emoji-mart.css'
const TextArea = ({ name, placeholder, theme='auto', setValue, value }:TextAreaProps):JSX.Element => { const TextArea: React.FC<TextAreaProps> = ({ name, placeholder, theme='auto', setValue, value }) => {
const ref = useRef() const ref = useRef()
const [ emojiPickerHidden, setEmojiPickerHidden ] = useState(true) const [ emojiPickerHidden, setEmojiPickerHidden ] = useState(true)
useOutsideClick(ref, () => { useOutsideClick(ref, () => {

View File

@ -6,7 +6,7 @@ const Container = dynamic(()=> import('@components/Container'))
const Tag = dynamic(()=> import('@components/Tag')) const Tag = dynamic(()=> import('@components/Tag'))
const Search = dynamic(()=> import('@components/Search')) const Search = dynamic(()=> import('@components/Search'))
const Hero = ({ header, description }:HeroProps):JSX.Element => { const Hero:React.FC<HeroProps> = ({ header, description }) => {
return <> return <>
<div className='dark:bg-discord-black bg-discord-blurple text-gray-100 md:p-0 mb-8'> <div className='dark:bg-discord-black bg-discord-blurple text-gray-100 md:p-0 mb-8'>
<Container className='pt-24 pb-16 md:pb-20' ignoreColor> <Container className='pt-24 pb-16 md:pb-20' ignoreColor>

View File

@ -1,4 +1,4 @@
const Loader = ({ text, visible = true }: LoaderProps): JSX.Element => { const Loader: React.FC<LoaderProps> = ({ text, visible = true }) => {
return ( return (
<div <div
className={`${ className={`${
@ -13,7 +13,7 @@ const Loader = ({ text, visible = true }: LoaderProps): JSX.Element => {
} }
interface LoaderProps { interface LoaderProps {
text: string | JSX.Element text: string | React.ReactNode
visible?: boolean visible?: boolean
} }

View File

@ -1,6 +1,7 @@
import { redirectTo } from '@utils/Tools'
import { useRouter } from 'next/router'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useRouter } from 'next/router'
import { redirectTo } from '@utils/Tools'
const Login: React.FC = ({ children }) => { const Login: React.FC = ({ children }) => {
const router = useRouter() const router = useRouter()

View File

@ -1,7 +1,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/no-static-element-interactions */
import Link from 'next/link' import Link from 'next/link'
const LongButton = ({ children, newTab=false, href, onClick, center=false }:LongButtonProps):JSX.Element => { const LongButton: React.FC<LongButtonProps> = ({ children, newTab=false, href, onClick, center=false }) => {
if(href) { if(href) {
if(newTab) return <a href={href} rel='noopener noreferrer' if(newTab) return <a href={href} rel='noopener noreferrer'
target='_blank'> target='_blank'>

View File

@ -5,7 +5,7 @@ import { FunctionComponent } from 'react'
import { anchorHeader, customEmoji, twemoji } from '@utils/Tools' import { anchorHeader, customEmoji, twemoji } from '@utils/Tools'
const Markdown = ({ text, options={}, allowedTag=[], components={} }: MarkdownProps): JSX.Element => { const Markdown: React.FC<MarkdownProps> = ({ text, options={}, allowedTag=[], components={} }) => {
return ( return (
<div className='markdown-body w-full'> <div className='markdown-body w-full'>
<MarkdownView <MarkdownView

View File

@ -1,7 +1,7 @@
import { MessageColor } from '@utils/Constants' import { MessageColor } from '@utils/Constants'
import Markdown from './Markdown' import Markdown from './Markdown'
const Message = ({ type, children }: MessageProps): JSX.Element => { const Message: React.FC<MessageProps> = ({ type, children }) => {
return ( return (
<div <div
className={`${MessageColor[type]} px-6 py-4 rounded-md text-base mx-auto w-full text-left`} className={`${MessageColor[type]} px-6 py-4 rounded-md text-base mx-auto w-full text-left`}

View File

@ -2,7 +2,7 @@ import { ReactNode } from 'react'
import { Modal as ReactModal } from 'react-responsive-modal' import { Modal as ReactModal } from 'react-responsive-modal'
import 'react-responsive-modal/styles.css' import 'react-responsive-modal/styles.css'
const Modal = ({ children, isOpen, onClose, closeIcon=false, dark, header, full=false }: ModalProps): JSX.Element => { const Modal: React.FC<ModalProps> = ({ children, isOpen, onClose, closeIcon=false, dark, header, full=false }) => {
return ( return (
<ReactModal <ReactModal
open={isOpen} open={isOpen}

View File

@ -3,7 +3,7 @@ import dynamic from 'next/dynamic'
const Button = dynamic(() => import('@components/Button')) const Button = dynamic(() => import('@components/Button'))
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const NSFW = ({ onClick, onDisableClick }:NSFWProps): JSX.Element => { const NSFW: React.FC<NSFWProps> = ({ onClick, onDisableClick }) => {
return <Container> return <Container>
<div className='flex items-center h-screen select-none'> <div className='flex items-center h-screen select-none'>
<div className='px-10'> <div className='px-10'>

View File

@ -3,15 +3,16 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/no-static-element-interactions */
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import dynamic from 'next/dynamic'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { redirectTo } from '@utils/Tools' import { redirectTo } from '@utils/Tools'
import Fetch from '@utils/Fetch'
import { User, UserCache } from '@types' import { User, UserCache } from '@types'
import DiscordAvatar from '@components/DiscordAvatar' const DiscordAvatar = dynamic(() => import('@components/DiscordAvatar'))
import Fetch from '@utils/Fetch'
const Navbar = ({ token, pwa }:{ token: string, pwa: boolean }): JSX.Element => { const Navbar: React.FC<NavbarProps> = ({ token, pwa }) => {
const [userCache, setUserCache] = useState<UserCache>() const [userCache, setUserCache] = useState<UserCache>()
const [navbarOpen, setNavbarOpen] = useState<boolean>(false) const [navbarOpen, setNavbarOpen] = useState<boolean>(false)
const [dropdownOpen, setDropdownOpen] = useState<boolean>(false) const [dropdownOpen, setDropdownOpen] = useState<boolean>(false)
@ -213,4 +214,9 @@ const Navbar = ({ token, pwa }:{ token: string, pwa: boolean }): JSX.Element =>
) )
} }
interface NavbarProps {
token: string
pwa: boolean
}
export default Navbar export default Navbar

View File

@ -1,4 +1,4 @@
const Notice = ({ header, desc }: NoticeProps) => { const Notice: React.FC<NoticeProps> = ({ header, desc }) => {
return ( return (
<div className='mx-auto my-auto px-10 py-48 h-screen text-center'> <div className='mx-auto my-auto px-10 py-48 h-screen text-center'>
<h1 className='text-4xl font-bold'>KOREANBOTS</h1> <h1 className='text-4xl font-bold'>KOREANBOTS</h1>

View File

@ -1,7 +1,7 @@
import Link from 'next/link' import Link from 'next/link'
import DiscordAvatar from '@components/DiscordAvatar' import DiscordAvatar from '@components/DiscordAvatar'
const Owner = ({ id, username, tag }: OwnerProps): JSX.Element => { const Owner: React.FC<OwnerProps> = ({ id, username, tag }) => {
return ( return (
<Link href={`/users/${id}`}> <Link href={`/users/${id}`}>
<a className='dark:hover:bg-discord-dark-hover flex mb-1 px-4 py-4 text-black dark:text-gray-400 text-base dark:bg-discord-black bg-little-white hover:bg-little-white-hover rounded cursor-pointer'> <a className='dark:hover:bg-discord-dark-hover flex mb-1 px-4 py-4 text-black dark:text-gray-400 text-base dark:bg-discord-black bg-little-white hover:bg-little-white-hover rounded cursor-pointer'>

View File

@ -1,5 +1,5 @@
import Link from 'next/link' import Link from 'next/link'
const Paginator = ({ currentPage, totalPage, pathname, searchParams }: PaginatorProps): JSX.Element => { const Paginator: React.FC<PaginatorProps> = ({ currentPage, totalPage, pathname, searchParams }) => {
let pages = [] let pages = []
if (currentPage < 4) if (currentPage < 4)
pages = [ pages = [

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
const PlatformDisplay = ({ osx, children }:PlatformDisplayProps): JSX.Element => { const PlatformDisplay: React.FC<PlatformDisplayProps> = ({ osx, children }:PlatformDisplayProps) => {
const isOSX = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform) const isOSX = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)
return <>{isOSX ? osx ?? children : children}</> return <>{isOSX ? osx ?? children : children}</>
} }

View File

@ -6,7 +6,7 @@ import { redirectTo } from '@utils/Tools'
const Container = dynamic(() => import('@components/Container')) const Container = dynamic(() => import('@components/Container'))
const Redirect = ({ to, text=true, children }:RedirectProps):JSX.Element => { const Redirect: React.FC<RedirectProps> = ({ to, text=true, children }) => {
const router = useRouter() const router = useRouter()
if(!to) throw new Error('No Link') if(!to) throw new Error('No Link')
useEffect(() => { useEffect(() => {

View File

@ -1,6 +1,4 @@
import { ReactNode } from 'react' const ResponsiveGrid: React.FC = ({ children }) => {
const ResponsiveGrid = ({ children }:{ children: ReactNode }):JSX.Element => {
return <div className='grid gap-x-4 grid-rows-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-10 -mb-10'> return <div className='grid gap-x-4 grid-rows-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 mt-10 -mb-10'>
{children} {children}
</div> </div>

View File

@ -1,6 +1,6 @@
import Head from 'next/head' import Head from 'next/head'
const SEO = ({ title, description, image }: SEOProps): JSX.Element => { const SEO: React.FC<SEOProps> = ({ title, description, image }: SEOProps) => {
return ( return (
<Head> <Head>
<title>{title} - </title> <title>{title} - </title>

View File

@ -11,7 +11,7 @@ import DiscordAvatar from '@components/DiscordAvatar'
import Day from '@utils/Day' import Day from '@utils/Day'
import useOutsideClick from '@utils/useOutsideClick' import useOutsideClick from '@utils/useOutsideClick'
const Search = (): JSX.Element => { const Search: React.FC = () => {
const router = useRouter() const router = useRouter()
const ref = useRef() const ref = useRef()
const [query, setQuery] = useState('') const [query, setQuery] = useState('')

View File

@ -1,6 +1,6 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
const Segment = ({ children, className = '' }: SegmentProps): JSX.Element => { const Segment: React.FC<SegmentProps> = ({ children, className = '' }) => {
return ( return (
<div <div
className={`py-3 px-7 text-black dark:text-white dark:bg-discord-black bg-little-white rounded ${className}`} className={`py-3 px-7 text-black dark:text-white dark:bg-discord-black bg-little-white rounded ${className}`}

View File

@ -5,7 +5,7 @@ import Tag from '@components/Tag'
import { SubmittedBot } from '@types' import { SubmittedBot } from '@types'
import Link from 'next/link' import Link from 'next/link'
const SubmittedBotCard = ({ href, submit }: SubmittedBotProps): JSX.Element => { const SubmittedBotCard: React.FC<SubmittedBotProps> = ({ href, submit }) => {
return ( return (
<Link href={href}> <Link href={href}>
<a className='relative mx-auto px-4 py-5 w-full h-full text-black dark:text-white dark:bg-discord-black bg-little-white rounded-2xl shadow-xl transform hover:-translate-y-1 transition duration-100 ease-in'> <a className='relative mx-auto px-4 py-5 w-full h-full text-black dark:text-white dark:bg-discord-black bg-little-white rounded-2xl shadow-xl transform hover:-translate-y-1 transition duration-100 ease-in'>

View File

@ -1,7 +1,7 @@
import Link from 'next/link' import Link from 'next/link'
import { ReactNode } from 'react' import { ReactNode } from 'react'
const Tag = ({ const Tag: React.FC<LabelProps> = ({
blurple = false, blurple = false,
github = false, github = false,
href, href,
@ -13,7 +13,7 @@ const Tag = ({
newTab = false, newTab = false,
bigger = false, bigger = false,
...props ...props
}: LabelProps): JSX.Element => { }) => {
return href ? ( return href ? (
newTab ? ( newTab ? (
<a <a

View File

@ -1,4 +1,4 @@
const Toggle = ({ checked, onChange }: ToggleProps): JSX.Element => { const Toggle: React.FC<ToggleProps> = ({ checked, onChange }: ToggleProps) => {
return ( return (
<button <button
className='relative inline-block align-middle mr-2 w-10 outline-none select-none' className='relative inline-block align-middle mr-2 w-10 outline-none select-none'

View File

@ -1,12 +1,12 @@
import Link from 'next/link' import Link from 'next/link'
const Tooltip = ({ const Tooltip: React.FC<TooltipProps> = ({
href, href,
size = 'small', size = 'small',
children, children,
direction = 'center', direction = 'center',
text, text,
}: TooltipProps): JSX.Element => { }) => {
return href ? ( return href ? (
<Link href={href}> <Link href={href}>
<a className='inline'> <a className='inline'>

View File

@ -1,4 +1,4 @@
const Wave = ({ color, className }: WaveProps): JSX.Element => { const Wave: React.FC<WaveProps> = ({ color, className }) => {
return ( return (
<svg viewBox='0 0 1440 320' className={className}> <svg viewBox='0 0 1440 320' className={className}>
<path <path