From 652ea22940c7b78bacfbdc0e6259b44ff2333a85 Mon Sep 17 00:00:00 2001 From: Melvyn Malherbe Date: Tue, 21 Jan 2020 14:08:44 +0100 Subject: [PATCH] Update Base Calculator * add base 8 * add settings for edit textField display * change style switch in dialog setting * edit settings button for is general * full screen for phone size --- .env | 1 + 404.md | 3 + package.json | 5 +- src/App.tsx | 34 ++++--- src/components/Custom/CustomSwitch.tsx | 74 +++++++++++++++ src/components/Custom/CustomTextField.tsx | 41 +++++++++ src/components/baseCalculator/Calculator.tsx | 69 ++++++++++++-- .../baseCalculator/InputBaseCalcul.tsx | 57 +++--------- .../baseCalculator/SettingsDialog.tsx | 69 ++++++++++++++ src/components/function.tsx | 55 ++++++++++-- .../settingsDialog/SettingsButton.tsx | 26 +++--- .../settingsDialog/SettingsContent.tsx | 8 +- .../settingsDialog/SettingsDialog.tsx | 6 +- src/page/BaseCalculator.tsx | 89 +++++++++++++++++-- src/page/RandomSentence.tsx | 38 ++++++-- 15 files changed, 457 insertions(+), 118 deletions(-) create mode 100644 .env create mode 100644 404.md create mode 100644 src/components/Custom/CustomSwitch.tsx create mode 100644 src/components/Custom/CustomTextField.tsx create mode 100644 src/components/baseCalculator/SettingsDialog.tsx diff --git a/.env b/.env new file mode 100644 index 0000000..2b3936e --- /dev/null +++ b/.env @@ -0,0 +1 @@ +PUBLIC_URL=/tools \ No newline at end of file diff --git a/404.md b/404.md new file mode 100644 index 0000000..f21d3a5 --- /dev/null +++ b/404.md @@ -0,0 +1,3 @@ +--- +permalink: /404.html +--- diff --git a/package.json b/package.json index ba65037..ed2be93 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "projetq", "version": "0.1.0", "private": true, + "homepage": "https://melvynx.github.io/tools/", "dependencies": { "@material-ui/core": "^4.8.1", "@material-ui/icons": "^4.5.1", @@ -26,7 +27,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "predeploy": "yarn build", + "deploy": "npx gh-pages -d build" }, "eslintConfig": { "extends": "react-app" diff --git a/src/App.tsx b/src/App.tsx index dda67ae..b8ea26c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { CssBaseline, ThemeProvider, createMuiTheme, Container } from "@material-ui/core"; +import { CssBaseline, ThemeProvider, createMuiTheme } from "@material-ui/core"; import { purple } from "@material-ui/core/colors"; -import { Switch, BrowserRouter as Router, Route } from "react-router-dom"; +import { Switch, HashRouter as Router, Route } from "react-router-dom"; import RandomSentence from "./page/RandomSentence"; import HomePage from "./page/HomePage"; import BaseCalculator from "./page/BaseCalculator"; @@ -44,22 +44,20 @@ export default function App() { return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + ); } diff --git a/src/components/Custom/CustomSwitch.tsx b/src/components/Custom/CustomSwitch.tsx new file mode 100644 index 0000000..4334d9f --- /dev/null +++ b/src/components/Custom/CustomSwitch.tsx @@ -0,0 +1,74 @@ +import React from "react"; +import { withStyles, createStyles, Theme } from "@material-ui/core/styles"; +import Switch, { SwitchClassKey, SwitchProps } from "@material-ui/core/Switch"; + +interface Styles extends Partial> { + focusVisible?: string; +} +interface Props extends SwitchProps { + classes: Styles; +} +export const CustomSwitch = withStyles((theme: Theme) => + createStyles({ + root: { + width: 60, + height: 30, + padding: 0, + margin: theme.spacing(1) + }, + switchBase: { + padding: 1, + color: theme.palette.primary.main, + "&$checked": { + transform: "translateX(35px)", + color: theme.palette.secondary.main, + backgroundColor: "none", + "& + $track": { + backgroundColor: theme.palette.primary.light, + opacity: 1, + border: `1px solid ${theme.palette.primary.main}` + } + }, + "&$focusVisible $thumb": { + color: "orange", + border: "6px solid red", + boxShadow: "none" + } + }, + thumb: { + width: 20, + height: 20, + marginTop: 4, + marginLeft: 2 + }, + track: { + borderRadius: 10 / 2, + border: `1px solid ${theme.palette.secondary.light}`, + backgroundColor: theme.palette.secondary.main, + opacity: 1, + transition: theme.transitions.create(["background-color", "border"]) + }, + checked: { + backgroundColor: "none", + color: "red" + }, + focusVisible: { + color: "red" + } + }) +)(({ classes, ...props }: Props) => { + return ( + + ); +}); diff --git a/src/components/Custom/CustomTextField.tsx b/src/components/Custom/CustomTextField.tsx new file mode 100644 index 0000000..fef7ac6 --- /dev/null +++ b/src/components/Custom/CustomTextField.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { + TextField, + makeStyles, + fade, + TextFieldProps, + OutlinedInputProps, +} from "@material-ui/core"; + +const useStyles = makeStyles(theme => ({ + root: { + border: "1px solid " + theme.palette.primary.dark, + color: theme.palette.primary.light, + padding: 2, + paddingLeft: 6, + fontSize: 18, + overflow: "hidden", + borderRadius: 3, + backgroundColor: theme.palette.secondary.main, + transition: theme.transitions.create(["border-color", "box-shadow"]), + "&:hover": { + backgroundColor: theme.palette.secondary.main + }, + "&$focused": { + backgroundColor: theme.palette.secondary.dark, + boxShadow: `${fade(theme.palette.secondary.main, 0.25)} 2px 0 0 2px`, + borderColor: theme.palette.secondary.main + } + } +})); + +export default function CustomTextField(props: TextFieldProps) { + const classes = useStyles(); + + return ( + } + {...props} + /> + ); +} diff --git a/src/components/baseCalculator/Calculator.tsx b/src/components/baseCalculator/Calculator.tsx index 3b0c57d..c1da39b 100644 --- a/src/components/baseCalculator/Calculator.tsx +++ b/src/components/baseCalculator/Calculator.tsx @@ -10,9 +10,17 @@ import { dec_to_hexa, isHexadecimal, hexa_to_dec, - hexa_to_bin + hexa_to_bin, + isOctal, + oct_to_bin, + oct_to_dec, + oct_to_hexa, + hexa_to_oct, + dec_to_oct, + bin_to_oct } from "../function"; import { Alert } from "@material-ui/lab"; +import { TypeSettings } from "../../page/BaseCalculator"; type TypeValue = { value: string; @@ -26,9 +34,14 @@ export enum Base { base2 = "base 2" } -export default function Calculator() { +type TypeCalculator = { + settings: TypeSettings; +}; + +export default function Calculator({ settings }: TypeCalculator) { const [base2, setBase2] = useState(""); const [base10, setBase10] = useState(""); + const [base8, setBase8] = useState(""); const [base16, setBase16] = useState(""); const [errorMessage, setErrorMessage] = useState(""); @@ -56,10 +69,17 @@ export default function Calculator() { hexadecimalConvertor(event.target.value); }; + const changeBase8 = (event: ChangeEvent) => { + setBase8(event.target.value); + + octalConvertor(event.target.value); + }; + const binaryConvertor = (value: string) => { if (isBinary(value)) { setBase10(String(bin_to_dec(value))); setBase16(bin_to_hexa(value)); + setBase8(bin_to_oct(value)); } else { displayErrorMessage("Binary number is null or invalid (only 0 and 1)."); } @@ -69,6 +89,7 @@ export default function Calculator() { if (isDecimal(value)) { setBase2(dec_to_bin(value)); setBase16(dec_to_hexa(value)); + setBase8(dec_to_oct(value)); } else { displayErrorMessage("Decimal number is null or invalid (only 0 to 9)."); } @@ -78,18 +99,52 @@ export default function Calculator() { if (isHexadecimal(value)) { setBase2(String(hexa_to_bin(value))); setBase10(String(hexa_to_dec(value))); + setBase8(String(hexa_to_oct(value))); } else { displayErrorMessage("Hexadecimal number is null or invalid (only 0 to 9 and A to F)"); } }; + const octalConvertor = (value: string) => { + console.log(isOctal(value)); + if (isOctal(value)) { + setBase2(oct_to_bin(value)); + setBase10(String(oct_to_dec(value))); + setBase16(oct_to_hexa(value)); + } else { + displayErrorMessage("Octal number is null or invalid (only 0 to 7)"); + } + }; + return ( - - - - - + + + + + + + 0}> diff --git a/src/components/baseCalculator/InputBaseCalcul.tsx b/src/components/baseCalculator/InputBaseCalcul.tsx index aa05e94..c9bdcab 100644 --- a/src/components/baseCalculator/InputBaseCalcul.tsx +++ b/src/components/baseCalculator/InputBaseCalcul.tsx @@ -1,54 +1,15 @@ import React from "react"; -import { - Box, - TextField, - makeStyles, - fade, - TextFieldProps, - OutlinedInputProps, - InputLabel -} from "@material-ui/core"; +import { Box, makeStyles, InputLabel } from "@material-ui/core"; +import CustomTextField from "../Custom/CustomTextField"; type TypeInputBaseCalcul = { value: string; base: string; onChange: Function; error?: boolean; + display?: boolean; }; -const useStyles = makeStyles(theme => ({ - root: { - border: "1px solid " + theme.palette.primary.dark, - color: theme.palette.primary.light, - padding: 2, - paddingLeft: 6, - fontSize: 18, - overflow: "hidden", - borderRadius: 3, - backgroundColor: theme.palette.secondary.main, - transition: theme.transitions.create(["border-color", "box-shadow"]), - "&:hover": { - backgroundColor: theme.palette.secondary.main - }, - "&$focused": { - backgroundColor: theme.palette.secondary.dark, - boxShadow: `${fade(theme.palette.secondary.main, 0.25)} 2px 0 0 2px`, - borderColor: theme.palette.secondary.main - } - } -})); - -function CustomTextField(props: TextFieldProps) { - const classes = useStyles(); - - return ( - } - {...props} - /> - ); -} - const useStylesInput = makeStyles(theme => ({ input: { fontSize: 12, @@ -56,13 +17,19 @@ const useStylesInput = makeStyles(theme => ({ } })); -export default function InputBaseCalcul({ value, base, onChange, error }: TypeInputBaseCalcul) { +export default function InputBaseCalcul({ + display, + value, + base, + onChange, + error +}: TypeInputBaseCalcul) { const classes = useStylesInput(); return ( - + {base} onChange(event)} fullWidth diff --git a/src/components/baseCalculator/SettingsDialog.tsx b/src/components/baseCalculator/SettingsDialog.tsx new file mode 100644 index 0000000..c07a8d8 --- /dev/null +++ b/src/components/baseCalculator/SettingsDialog.tsx @@ -0,0 +1,69 @@ +import React from "react"; +import { Dialog, DialogTitle, makeStyles, DialogActions, Button } from "@material-ui/core"; +import SettingsContent from "../randomSentence/settingsDialog/SettingsContent"; +import { TypeSettings } from "../../page/BaseCalculator"; + +type TypeSettingsDialog = { + open: boolean; + onClose: Function; + settings: TypeSettings; + onChange: Function; +}; + +const useStyles = makeStyles(theme => ({ + background: { + backgroundColor: theme.palette.secondary.main + }, + text: { + color: theme.palette.secondary.contrastText + } +})); + +export default function SettingsDialog({ open, onClose, settings, onChange }: TypeSettingsDialog) { + const classes = useStyles(); + + return ( + onClose()} open={open}> + + Settings Random Sentence + + + Affiché la base 2 + + + Affiché la base 8 + + + Affiché la base 10 + + + Affiché la base 16 + + + + + + ); +} diff --git a/src/components/function.tsx b/src/components/function.tsx index 75ca141..82efb9f 100644 --- a/src/components/function.tsx +++ b/src/components/function.tsx @@ -26,6 +26,10 @@ export function bin_to_hexa(bin: string) { .toUpperCase(); } +export function bin_to_oct(bin: string) { + return parseInt(bin, 2).toString(8); +} + export function isBinary(number: string) { let isValide: boolean = true; @@ -44,27 +48,31 @@ export function isBinary(number: string) { return isValide; } -export function dec_to_bin(number: string) { - return (Number(number) - 0).toString(2); +export function dec_to_bin(dec: string) { + return (Number(dec) - 0).toString(2); } -export function dec_to_hexa(number: string) { - return (Number(number) - 0).toString(16).toUpperCase(); +export function dec_to_hexa(dec: string) { + return (Number(dec) - 0).toString(16).toUpperCase(); } -export function isDecimal(number: string) { - if (isNaN(Number(number))) { +export function dec_to_oct(dec: string) { + return (Number(dec) - 0).toString(8); +} + +export function isDecimal(dec: string) { + if (isNaN(Number(dec))) { return false; } else { return true; } } -export function isHexadecimal(number: string) { - if (number === "0" || number === "") { +export function isHexadecimal(hexa: string) { + if (hexa === "0" || hexa === "") { return false; } - const array = number.split(""); + const array = hexa.split(""); const notBinaryLetter = [ "g", "h", @@ -105,3 +113,32 @@ export function hexa_to_dec(hexa: string) { export function hexa_to_bin(hexa: string) { return parseInt(hexa, 16).toString(2); } +export function hexa_to_oct(hexa: string) { + return parseInt(hexa, 16).toString(8); +} + +export function isOctal(oct: string) { + if (oct === "0" || oct === "") { + return false; + } + const arrayOct: Array = oct.split(""); + + for (let i = 0; i < arrayOct.length; i++) { + if (arrayOct[i] === "9" || arrayOct[i] === "8") { + return false; + } + } + return true; +} + +export function oct_to_dec(oct: string) { + return parseInt(oct, 8); +} +export function oct_to_hexa(oct: string) { + return parseInt(oct, 8) + .toString(16) + .toUpperCase(); +} +export function oct_to_bin(oct: string) { + return parseInt(oct, 8).toString(2); +} diff --git a/src/components/randomSentence/settingsDialog/SettingsButton.tsx b/src/components/randomSentence/settingsDialog/SettingsButton.tsx index 8d97b3f..8ddf788 100644 --- a/src/components/randomSentence/settingsDialog/SettingsButton.tsx +++ b/src/components/randomSentence/settingsDialog/SettingsButton.tsx @@ -1,8 +1,7 @@ -import React, { useState } from "react"; +import React from "react"; import { Box, Button, IconButton, makeStyles } from "@material-ui/core"; import SettingsIcon from "@material-ui/icons/Settings"; -import SettingsDialog from "./SettingsDialog"; -import { TypeSettings } from "../../../page/RandomSentence"; + const useStyles = makeStyles({ button: { width: 30, @@ -11,31 +10,26 @@ const useStyles = makeStyles({ }); export type TypeSettingsButton = { - settings: TypeSettings; - onChange: Function; + onClick: Function; }; -export default function SettingsButton({ settings, onChange }: TypeSettingsButton) { - const [open, setOpen] = useState(false); +export default function SettingsButton({ onClick }: TypeSettingsButton) { const classes = useStyles(); - const handleClick = () => { - setOpen(true); - }; - - const handleClose = () => { - setOpen(false); - }; return ( <> - - ); } diff --git a/src/components/randomSentence/settingsDialog/SettingsContent.tsx b/src/components/randomSentence/settingsDialog/SettingsContent.tsx index 1934758..ea1e6c9 100644 --- a/src/components/randomSentence/settingsDialog/SettingsContent.tsx +++ b/src/components/randomSentence/settingsDialog/SettingsContent.tsx @@ -1,8 +1,9 @@ import React from "react"; -import { DialogContent, Box, Typography, Switch } from "@material-ui/core"; +import { DialogContent, Box, Typography } from "@material-ui/core"; +import { CustomSwitch } from "../../Custom/CustomSwitch"; type TypeSettingsContent = { - checked: boolean; + checked?: boolean; onChange: Function; className: Record<"background" | "text", string>; children: string; @@ -30,8 +31,7 @@ export default function SettingsContent({ {children} - onChange(typeSettings)} inputProps={{ "aria-label": "secondary checkbox" }} diff --git a/src/components/randomSentence/settingsDialog/SettingsDialog.tsx b/src/components/randomSentence/settingsDialog/SettingsDialog.tsx index 0377f00..afe6d40 100644 --- a/src/components/randomSentence/settingsDialog/SettingsDialog.tsx +++ b/src/components/randomSentence/settingsDialog/SettingsDialog.tsx @@ -1,11 +1,13 @@ import React from "react"; import { Dialog, DialogTitle, makeStyles, DialogActions, Button } from "@material-ui/core"; +import { TypeSettings } from "../../../page/RandomSentence"; import SettingsContent from "./SettingsContent"; -import { TypeSettingsButton } from "./SettingsButton"; -type TypeSettingsDialog = TypeSettingsButton & { +type TypeSettingsDialog = { open: boolean; onClose: Function; + settings: TypeSettings; + onChange: Function; }; const useStyles = makeStyles(theme => ({ diff --git a/src/page/BaseCalculator.tsx b/src/page/BaseCalculator.tsx index 4cc70c8..a741817 100644 --- a/src/page/BaseCalculator.tsx +++ b/src/page/BaseCalculator.tsx @@ -1,21 +1,94 @@ -import React from "react"; -import { Container, Box, Typography } from "@material-ui/core"; +import React, { useState } from "react"; +import { Box, Typography, makeStyles } from "@material-ui/core"; import Calculator from "../components/baseCalculator/Calculator"; import HomePageLinkButton from "../components/HomePage/HomePageLinkButton"; +import SettingsButton from "../components/randomSentence/settingsDialog/SettingsButton"; +import SettingsDialog from "../components/baseCalculator/SettingsDialog"; + +const useStyles = makeStyles(theme => ({ + title: { + [theme.breakpoints.down("sm")]: { + marginTop: 40 + } + } +})); + +export type TypeSettings = { + displayBase2?: boolean; + displayBase8?: boolean; + displayBase10?: boolean; + displayBase16?: boolean; +}; export default function BaseCalculator() { + const [settings, setSettings] = useState({ + displayBase2: true, + displayBase8: false, + displayBase10: true, + displayBase16: true + }); + const [openSettings, setOpenSettings] = useState(false); + + const handleSettings = () => { + setOpenSettings(!openSettings); + }; + + const handleChangeSettings = (value: string) => { + switch (value) { + case "2": + setSettings(prevState => { + return { ...prevState, displayBase2: !settings.displayBase2 }; + }); + break; + case "8": + setSettings(prevState => { + return { ...prevState, displayBase8: !settings.displayBase8 }; + }); + break; + case "10": + setSettings(prevState => { + return { ...prevState, displayBase10: !settings.displayBase10 }; + }); + break; + case "16": + setSettings(prevState => { + return { ...prevState, displayBase16: !settings.displayBase16 }; + }); + } + }; + + const classes = useStyles(); return ( - - + + - + + + + + + Change base calculator ! - + Enter a number where you want to transform this in all base ! - + - + ); } diff --git a/src/page/RandomSentence.tsx b/src/page/RandomSentence.tsx index b90eb76..f2bc0da 100644 --- a/src/page/RandomSentence.tsx +++ b/src/page/RandomSentence.tsx @@ -1,23 +1,33 @@ import React, { useState } from "react"; -import { Box, Typography, Container, useTheme } from "@material-ui/core"; +import { Box, Typography, makeStyles } from "@material-ui/core"; import MakeSentence from "../components/randomSentence/make/MakeSentence"; import ShuffleSentence from "../components/randomSentence/shuffle/ShuffleSentence"; import SettingsButton from "../components/randomSentence/settingsDialog/SettingsButton"; import HomePageLinkButton from "../components/HomePage/HomePageLinkButton"; +import SettingsDialog from "../components/randomSentence/settingsDialog/SettingsDialog"; export type TypeSettings = { isCountDown: boolean; isOneSentence: boolean; }; +const useStyles = makeStyles(theme => ({ + title: { + [theme.breakpoints.down("sm")]: { + marginTop: 12 + } + } +})); + export default function RandomSentence() { - const theme = useTheme(); + const classes = useStyles(); const [wordList, setWordList] = useState>([]); const [isAdding, setAdding] = useState(true); const [settings, setSettings] = useState({ isCountDown: false, isOneSentence: false }); + const [openSettings, setOpenSettings] = useState(false); const toggleSettings = (value: string) => { switch (value) { @@ -36,6 +46,10 @@ export default function RandomSentence() { } }; + const handleSettings = () => { + setOpenSettings(!openSettings); + }; + const addWord = (sentence: string) => { const list = [...wordList]; list.push(sentence); @@ -57,23 +71,31 @@ export default function RandomSentence() { }; return ( - + - + + + - + Random word or sentence ! @@ -97,6 +119,6 @@ export default function RandomSentence() { /> )} - + ); }