Skip to content

Commit

Permalink
add scaleform utility
Browse files Browse the repository at this point in the history
  • Loading branch information
ayan4m1 committed Feb 10, 2024
1 parent 498b3ab commit 1ab21c8
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 32 deletions.
2 changes: 1 addition & 1 deletion jsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"module": "commonjs",
"module": "esnext",
"jsx": "react",
"baseUrl": "./"
},
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@
"classnames": "^2.5.1",
"color-diff": "^1.4.0",
"color-namer": "^1.4.0",
"convert-units": "^3.0.0-beta.6",
"d3-color": "^3.1.0",
"d3-interpolate": "^3.0.1",
"d3-scale-chromatic": "^3.0.0",
"date-fns": "^3.3.1",
"dotenv": "^16.4.1",
"formik": "^2.4.5",
"gatsby": "^5.13.3",
"gatsby-plugin-gtag": "^1.0.13",
"gatsby-plugin-eslint": "^4.0.4",
"gatsby-plugin-gtag": "^1.0.13",
"gatsby-plugin-image": "^3.13.1",
"gatsby-plugin-manifest": "^5.13.1",
"gatsby-plugin-mdx": "^5.13.1",
Expand Down
83 changes: 53 additions & 30 deletions src/components/header.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import PropTypes from 'prop-types';
import { Fragment } from 'react';
import { Link, useStaticQuery, graphql } from 'gatsby';
import { Container, Navbar, Nav, NavDropdown, Button } from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faFileArchive,
Expand All @@ -7,18 +11,34 @@ import {
faNewspaper,
faPaintBrush,
faRectangleList,
faBalanceScale,
faSun,
faTable,
faWrench
} from '@fortawesome/free-solid-svg-icons';
import { Fragment } from 'react';
import { Link, useStaticQuery, graphql } from 'gatsby';
import { Container, Navbar, Nav, NavDropdown, Button } from 'react-bootstrap';

import { useThemeContext } from 'hooks/useThemeContext';

import icon from '../images/gatsby-icon.png';

const NavLink = ({ to, label, icon, topLevel = false, ...props }) => (
<Nav.Link
{...props}
as={Link}
className={topLevel ? null : 'text-dark'}
to={to}
>
<FontAwesomeIcon icon={icon} /> {label}
</Nav.Link>
);

NavLink.propTypes = {
to: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
topLevel: PropTypes.bool,
icon: PropTypes.object
};

export default function Header() {
const { darkMode, toggleDarkMode } = useThemeContext();
const data = useStaticQuery(graphql`
Expand Down Expand Up @@ -64,38 +84,38 @@ export default function Header() {
}
>
{data.allArticleCategoriesJson.nodes.map((category) => (
<Nav.Link
<NavLink
key={category.name}
as={Link}
className="text-dark"
to={`/${category.name}`}
>
{category.title}
</Nav.Link>
label={category.title}
/>
))}
</NavDropdown>
<Nav.Link as={Link} to="/projects">
<FontAwesomeIcon icon={faFileArchive} /> Projects
</Nav.Link>
<Nav.Link as={Link} to="/love">
<FontAwesomeIcon icon={faHeart} /> Things I Love
</Nav.Link>
<NavLink
to="/projects"
icon={faFileArchive}
label="Projects"
topLevel
/>
<NavLink to="/love" icon={faHeart} label="Things I Love" topLevel />
<NavDropdown
title={
<Fragment>
<FontAwesomeIcon icon={faGamepad} /> Games
</Fragment>
}
>
<Nav.Link as={Link} to="/games/sudoku" className="text-dark">
<FontAwesomeIcon icon={faTable} /> Sudoku
</Nav.Link>
<Nav.Link as={Link} to="/games/mahjong" className="text-dark">
<FontAwesomeIcon icon={faRectangleList} /> Mahjong
</Nav.Link>
<Nav.Link as={Link} to="/games/coloree" className="text-dark">
<FontAwesomeIcon icon={faPaintBrush} /> Coloree
</Nav.Link>
<NavLink to="/games/sudoku" icon={faTable} label="Sudoku" />
<NavLink
to="/games/mahjong"
icon={faRectangleList}
label="Mahjong"
/>
<NavLink
to="/games/coloree"
icon={faPaintBrush}
label="Coloree"
/>
</NavDropdown>
<NavDropdown
title={
Expand All @@ -104,13 +124,16 @@ export default function Header() {
</Fragment>
}
>
<Nav.Link
as={Link}
<NavLink
to="/utilities/bom-sheet-maker"
className="text-dark"
>
<FontAwesomeIcon icon={faTable} /> BOM Sheet Maker
</Nav.Link>
icon={faTable}
label="BOM Sheet Maker"
/>
<NavLink
to="/utilities/scale-converter"
icon={faBalanceScale}
label="Scale Converter"
/>
</NavDropdown>
</Nav>
<Nav
Expand Down
6 changes: 6 additions & 0 deletions src/hooks/useDebounce.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { useRef } from 'react';
import { debounce } from 'lodash-es';

export default function useDebounce(handler) {
return useRef(debounce(handler, 250)).current;
}
67 changes: 67 additions & 0 deletions src/hooks/useScaleForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useFormik } from 'formik';
import { uniqueId } from 'lodash-es';

import { convert } from 'utils/units';

const convertRegex = /([\d.-]+)\s+(\w+)\s+in\s+(\w+)/;

export default function useScaleForm(onHistoryPush) {
return useFormik({
initialValues: {
conversion: ''
},
onSubmit: (vals, { setFieldError }) => {
if (convertRegex.test(vals.conversion)) {
const [, rawValue, unit, targetUnit] =
vals.conversion.match(convertRegex);

if (!rawValue || !unit || !targetUnit) {
return setFieldError('conversion', 'Could not parse input.');
}

if (!convert().from(unit).possibilities().includes(targetUnit)) {
return setFieldError(
'conversion',
`Cannot convert ${unit} to ${targetUnit}`
);
}

const value = parseFloat(rawValue);

if (isNaN(value)) {
return setFieldError('conversion', `Could not parse value.`);
}

onHistoryPush({
id: uniqueId(),
unit,
targetUnit,
value
});
} else {
const [rawValue, unit] = vals.conversion.split(/\s+/);

if (!rawValue || !unit) {
return setFieldError('conversion', 'Could not parse input.');
}

const value = parseFloat(rawValue);

if (isNaN(value)) {
return setFieldError('conversion', `Could not parse value.`);
}

if (!convert().possibilities('length').includes(unit)) {
return setFieldError('conversion', `Unsupported unit ${unit}`);
}

onHistoryPush({
id: uniqueId(),
unit,
targetUnit: unit,
value
});
}
}
});
}
37 changes: 37 additions & 0 deletions src/hooks/useScaleHistory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useCallback } from 'react';
import useLocalStorageState from 'use-local-storage-state';

import { convert } from 'utils/units';

const calculate = (entry, denominator) => ({
...entry,
result:
convert(entry.value).from(entry.unit).to(entry.targetUnit) *
(1 / denominator)
});

export default function useScaleHistory() {
const [denominator, setDenominator] = useLocalStorageState('denominator', {
defaultValue: 1
});
const [entries, setEntries] = useLocalStorageState('entries', {
defaultValue: []
});
const clearEntries = useCallback(() => setEntries([]), [setEntries]);
const pushEntry = useCallback(
(entry) =>
setEntries((original) => [...original, calculate(entry, denominator)]),
[setEntries, denominator]
);
const updateDenominator = useCallback(
(value) => {
setEntries((original) =>
original.map((entry) => calculate(entry, value))
);
setDenominator(value);
},
[setEntries, setDenominator]
);

return { entries, denominator, pushEntry, clearEntries, updateDenominator };
}
Loading

0 comments on commit 1ab21c8

Please sign in to comment.