-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from WeFoxTech/feature/byteunit-conversion-tool
add byte unit conversion tool 💯
- Loading branch information
Showing
6 changed files
with
261 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { SvgIcon } from '@material-ui/core'; | ||
|
||
export const SdcardIcon: React.FC = props => { | ||
return ( | ||
<SvgIcon viewBox="0 0 1549 1024" {...props}> | ||
<path d="M768 0H384L128 256v640c0 70.6 57.4 128 128 128h512c70.6 0 128-57.4 128-128V128C896 57.4 838.6 0 768 0zM448 320h-96V128h96v192zm160 0h-96V128h96v192zm160 0h-96V128h96v192z" /> | ||
</SvgIcon> | ||
); | ||
}; |
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,180 @@ | ||
import React from 'react'; | ||
import useTranslation from '~/src/hooks/useTranslation'; | ||
import TimeUnitSvg from '~/components/svgs/TimeUnit'; | ||
import { | ||
Box, | ||
TextField, | ||
Typography, | ||
TextareaAutosize, | ||
Divider, | ||
Button, | ||
Grid, | ||
IconButton, | ||
CircularProgress, | ||
Snackbar, | ||
InputLabel, | ||
Select, | ||
MenuItem, | ||
Hidden, | ||
InputAdornment, | ||
FormControl, | ||
Input, | ||
} from '@material-ui/core'; | ||
import BigNumber from 'bignumber.js'; | ||
import { TranslationKey, InlineLocale } from '~/src/translations/types'; | ||
import copy from 'copy-to-clipboard'; | ||
import FileCopyIcon from '@material-ui/icons/FileCopy'; | ||
import Alert from '@material-ui/lab/Alert'; | ||
|
||
const title: InlineLocale = { | ||
zh: '字节单位换算工具', | ||
en: 'Byte Unit Conversion Tool', | ||
}; | ||
|
||
const units = { | ||
bit: 1, | ||
Byte: 8, | ||
KiB: 2 ** 10 * 8, | ||
MiB: 2 ** 20 * 8, | ||
GiB: 2 ** 30 * 8, | ||
TiB: 2 ** 40 * 8, | ||
PiB: 2 ** 50 * 8, | ||
EiB: 2 ** 60 * 8, | ||
ZiB: 2 ** 70 * 8, | ||
YiB: 2 ** 80 * 8, | ||
}; | ||
|
||
type Units = typeof units; | ||
|
||
type UnitKey = keyof Units; | ||
|
||
export const ByteConverter: React.FC = () => { | ||
const { t, locale } = useTranslation(); | ||
const [ns, setNs] = React.useState<null | BigNumber>(null); | ||
const [fixedType, setFixedType] = React.useState< | ||
Partial<{ [key: string]: string | null | undefined }> | ||
>({}); | ||
|
||
const textArea = React.useRef<HTMLTextAreaElement>(null); | ||
|
||
const [error, setError] = React.useState<null | string>(null); | ||
const [success, setSuccess] = React.useState<null | string>(null); | ||
|
||
const checkAndSetNs = (name: string, value: string, calc: (input: BigNumber) => BigNumber) => { | ||
if (value) { | ||
const dotTimes = (value.match(/\./g) || []).length; | ||
if (dotTimes > 1) { | ||
setError(`. appear ${dotTimes} times`); | ||
} else { | ||
if (/\.0*$/.test(value) || /^\d*\.$/.test(value)) { | ||
setFixedType({ [name]: value }); | ||
} else if (/^[\d\.]+$/.test(value)) { | ||
setNs(calc(new BigNumber(value, 10))); | ||
setFixedType({ [name]: null }); | ||
} else { | ||
const charArr = value.split(''); | ||
const lastChar = charArr.pop(); | ||
setError(`${lastChar} is not a number`); | ||
} | ||
} | ||
} else { | ||
setNs(null); | ||
} | ||
}; | ||
|
||
const copyText = (name: UnitKey, text: string) => { | ||
const result = copy(text); | ||
if (result) { | ||
setSuccess(t('copySuccess')); | ||
} else { | ||
setError(t('copyFailure')); | ||
} | ||
}; | ||
|
||
const data: Array<[ | ||
UnitKey, | ||
string, | ||
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void | ||
]> = Object.keys(units).map(ele => { | ||
const key = ele as UnitKey; | ||
return [ | ||
key, | ||
fixedType[key] ?? ns?.dividedBy(units[key]).toString(10) ?? '', | ||
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => | ||
checkAndSetNs(key, e.currentTarget.value, bn => bn.multipliedBy(units[key])), | ||
]; | ||
}); | ||
|
||
return ( | ||
<Box> | ||
<Snackbar | ||
open={!!error || !!success} | ||
autoHideDuration={2000} | ||
onClose={e => { | ||
setError(null); | ||
setSuccess(null); | ||
}} | ||
> | ||
<Alert | ||
onClose={e => { | ||
setError(null); | ||
setSuccess(null); | ||
}} | ||
severity={error ? 'error' : success ? 'success' : 'info'} | ||
> | ||
{error || success} | ||
</Alert> | ||
</Snackbar> | ||
<Box textAlign="center" justifyContent="center"> | ||
<Typography variant="h3">{title[locale]}</Typography> | ||
<Box pt={4}> | ||
<Button | ||
color="primary" | ||
variant="contained" | ||
onClick={e => { | ||
setNs(null); | ||
setFixedType({}); | ||
}} | ||
> | ||
{t('reset')} | ||
</Button> | ||
</Box> | ||
</Box> | ||
<Box pt={2} pb={16} justifyContent="center" alignItems="center" textAlign="center"> | ||
<form> | ||
<Grid container spacing={1} justify="center"> | ||
{data.map((e, i) => { | ||
const [k, v, h] = e; | ||
return ( | ||
<Grid key={i} item xs={12} md={6}> | ||
<Box> | ||
<FormControl> | ||
<InputLabel htmlFor={`byte-unit-${k}`}>{k}</InputLabel> | ||
<Input | ||
id={`byte-unit-${k}`} | ||
value={v} | ||
onChange={h} | ||
fullWidth | ||
type="number" | ||
multiline | ||
endAdornment={ | ||
<InputAdornment position="end"> | ||
{v && ( | ||
<Button startIcon={<FileCopyIcon />} onClick={e => copyText(k, v)}> | ||
{t('copy')} | ||
</Button> | ||
)} | ||
</InputAdornment> | ||
} | ||
></Input> | ||
</FormControl> | ||
</Box> | ||
</Grid> | ||
); | ||
})} | ||
</Grid> | ||
</form> | ||
</Box> | ||
</Box> | ||
); | ||
}; |
60 changes: 60 additions & 0 deletions
60
packages/website/pages/[lang]/tool/byte-unit-converter.tsx
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,60 @@ | ||
import * as React from 'react'; | ||
import Layout from '~/components/Layout'; | ||
import withLocale from '~/src/hocs/withLocale'; | ||
import { GetstaticProps } from '~/src/types/next'; | ||
import locales from '~/src/translations/locales'; | ||
import useTranslation from '~/src/hooks/useTranslation'; | ||
import { PageMeta } from '~/src/PageMeta'; | ||
import { ByteConverter } from '~/components/tool/ByteConverter'; | ||
|
||
const commonKeyworks = ['wefox', 'Byte unit']; | ||
const meta: PageMeta = { | ||
title: 'byte unit converter', | ||
keywords: [...commonKeyworks, 'technical consulting', 'Technical Adviser'], | ||
description: 'Tools to convert various byte units', | ||
author: 'fox, [email protected]', | ||
zh: { | ||
title: '字节单位转换工具', | ||
keywords: [ | ||
...commonKeyworks, | ||
'字节单位转换', | ||
'字节单位', | ||
'文件单位', | ||
'存储单位', | ||
'带宽单位', | ||
'技术咨询', | ||
'技术顾问', | ||
], | ||
description: '转换字节单位的工具', | ||
}, | ||
}; | ||
|
||
const ByteUnitConvertPage = () => { | ||
const { t, locale } = useTranslation(); | ||
|
||
return ( | ||
<Layout meta={meta}> | ||
<ByteConverter /> | ||
</Layout> | ||
); | ||
}; | ||
|
||
export default withLocale(ByteUnitConvertPage); | ||
|
||
export async function getStaticPaths() { | ||
return { | ||
paths: ['en', 'zh'].map(l => ({ params: { lang: l } })), | ||
fallback: false, | ||
}; | ||
} | ||
|
||
export const getStaticProps: GetstaticProps = async ({ params }) => { | ||
const { lang } = params; | ||
const currentLocales = locales[lang]; | ||
return { | ||
props: { | ||
locale: lang, | ||
translations: currentLocales['common'], | ||
}, | ||
}; | ||
}; |
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
17865a3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deploy preview for website ready!
Built with commit 17865a3
https://home-website-1ru5n89hk.now.sh