This commit is contained in:
Bpr3 2025-10-29 21:07:43 +01:00 committed by GitHub
commit fe2172cd08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 735 additions and 2 deletions

40
@types/units-converter.d.ts vendored Normal file
View file

@ -0,0 +1,40 @@
declare module 'units-converter' {
export type UnitDescription = {
unit: string;
system: string;
singular: string;
plural: string;
};
export type Converter = (value?: number) => {
from: (unit: string) => {
to: (unit: string) => {
value: number;
unit: string;
system: string;
singular: string;
plural: string;
};
toBest: (opts?: { exclude?: string[] }) => {
value: number;
unit: string;
system: string;
singular: string;
plural: string;
};
possibilities: () => string[];
};
list: () => UnitDescription[];
describe: (unit: string) => UnitDescription;
};
export const length: Converter;
export const mass: Converter;
export const volume: Converter;
export const area: Converter;
export const current: Converter;
export const power: Converter;
export const energy: Converter;
export const digital: Converter;
export const temperature: Converter;
export const speed: Converter;
export const voltage: Converter;
}

14
package-lock.json generated
View file

@ -20,6 +20,7 @@
"@mui/material": "^5.15.20",
"@playwright/test": "^1.45.0",
"@simplepdf/react-embed-pdf": "^1.9.0",
"@types/convert-units": "^2.3.12",
"@types/ffmpeg": "^1.0.7",
"@types/js-quantities": "^1.6.6",
"@types/lodash": "^4.17.5",
@ -67,6 +68,7 @@
"styled-components": "^6.1.19",
"tesseract.js": "^6.0.0",
"type-fest": "^4.35.0",
"units-converter": "^1.0.3",
"use-deep-compare-effect": "^1.8.1",
"yup": "^1.4.0"
},
@ -3408,6 +3410,12 @@
"@types/node": "*"
}
},
"node_modules/@types/convert-units": {
"version": "2.3.12",
"resolved": "https://registry.npmjs.org/@types/convert-units/-/convert-units-2.3.12.tgz",
"integrity": "sha512-4EaowCOJMy8Cb2nB8XSN61U82VV4qFsFYY2WhKIwXy936aBTp2yWKvMpTCt1g76MDmd+DmVi9YxKSYVrfCQ/yw==",
"license": "MIT"
},
"node_modules/@types/estree": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
@ -13271,6 +13279,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/units-converter": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/units-converter/-/units-converter-1.0.3.tgz",
"integrity": "sha512-tcAwnZxH8NUx0T/eltQ2CUZ21jJxLRHF7dkPoYDFdX+W+VHxbvb/aH5xXBa0Cdp1tpyFI6rju+Jnpj9seuudqg==",
"license": "MIT"
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",

View file

@ -39,6 +39,7 @@
"@mui/material": "^5.15.20",
"@playwright/test": "^1.45.0",
"@simplepdf/react-embed-pdf": "^1.9.0",
"@types/convert-units": "^2.3.12",
"@types/ffmpeg": "^1.0.7",
"@types/js-quantities": "^1.6.6",
"@types/lodash": "^4.17.5",
@ -86,6 +87,7 @@
"styled-components": "^6.1.19",
"tesseract.js": "^6.0.0",
"type-fest": "^4.35.0",
"units-converter": "^1.0.3",
"use-deep-compare-effect": "^1.8.1",
"yup": "^1.4.0"
},

View file

View file

View file

@ -42,6 +42,10 @@
"description": "Tools for working with lists sort, reverse, randomize lists, find unique and duplicate list items, change list item separators, and much more.",
"title": "List Tools"
},
"conversion": {
"description": "Comprehensive tools for converting between all major and niche units: length, area, volume, mass, temperature, speed, digital storage, energy, voltage, current, power, and more. Instantly switch between metric, imperial, and scientific units for science, engineering, daily life..",
"title": "Conversion Tools"
},
"number": {
"description": "Tools for working with numbers generate number sequences, convert numbers to words and words to numbers, sort, round, factor numbers, and much more.",
"title": "Number Tools"
@ -251,5 +255,60 @@
"userTypes": {
"developers": "Developers",
"generalUsers": "General users"
},
"lengthConverter": {
"title": "Length Converter",
"description": "Convert between metric, imperial, and US customary units of length and distance. Instantly switch between meters, kilometers, miles, yards, feet, inches, and more. Useful for science, engineering, travel, and everyday tasks. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert length and distance units"
},
"areaConverter": {
"title": "Area Converter",
"description": "Easily convert between square meters, acres, hectares, square feet, and other area units. Supports metric and imperial systems. Perfect for land measurement, real estate, and construction projects. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert area units"
},
"volumeConverter": {
"title": "Volume Converter",
"description": "Convert between liters, milliliters, gallons, quarts, pints, cups, and more. Handles both metric and US/UK imperial volume units. Great for cooking, science, and industrial applications. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert volume and capacity units"
},
"massConverter": {
"title": "Mass Converter",
"description": "Switch between grams, kilograms, tons, pounds, ounces, and other mass and weight units. Supports metric, imperial, and US customary systems. Ideal for science, nutrition, and shipping. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert mass and weight units"
},
"temperatureConverter": {
"title": "Temperature Converter",
"description": "Convert between Celsius, Fahrenheit, Kelvin, and Rankine. Instantly switch temperature units for science, cooking, weather, and engineering. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert temperature units"
},
"speedConverter": {
"title": "Speed Converter",
"description": "Convert between meters per second, kilometers per hour, miles per hour, knots, and more. Useful for physics, travel, automotive, and sports. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert speed units"
},
"digitalConverter": {
"title": "Digital Storage Converter",
"description": "Convert between bits, bytes, kilobytes, megabytes, gigabytes, terabytes, and more. Instantly switch digital storage units for computing, IT, and data management. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert digital storage units"
},
"energyConverter": {
"title": "Energy Converter",
"description": "Convert between joules, calories, kilowatt-hours, electronvolts, BTUs, and more. Useful for physics, engineering, nutrition, and energy management. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert energy units"
},
"voltageConverter": {
"title": "Voltage Converter",
"description": "Convert between volts, millivolts, kilovolts, and more. Instantly switch voltage units for electronics, engineering, and physics. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert voltage units"
},
"currentConverter": {
"title": "Current Converter",
"description": "Convert between amperes, milliamperes, kiloamperes, and more. Instantly switch current units for electronics, engineering, and physics. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert electric current units"
},
"powerConverter": {
"title": "Power Converter",
"description": "Convert between watts, kilowatts, megawatts, horsepower, and more. Instantly switch power units for electronics, engineering, and physics. Enable Expert mode to unlock all available units.",
"shortDescription": "Convert power units"
}
}

View file

View file

@ -0,0 +1,205 @@
import React, { useState, useMemo, useEffect } from 'react';
import {
Box,
TextField,
MenuItem,
Grid,
Typography,
InputAdornment,
IconButton,
Tooltip,
FormControlLabel,
Switch
} from '@mui/material';
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
export interface UnitDescription {
unit: string;
singular: string;
plural: string;
system?: string;
}
interface GenericConverterProps {
converter: (value?: number) => any;
classicUnits: string[];
defaultFrom: string;
defaultTo: string;
title: string;
hasExpert?: boolean;
}
const GenericConverter: React.FC<GenericConverterProps> = ({
converter,
classicUnits,
defaultFrom,
defaultTo,
title,
hasExpert = true
}) => {
const converterInstance = useMemo(() => converter(), [converter]);
const allUnits = useMemo(
() => converterInstance.list() as UnitDescription[],
[converterInstance]
);
const [expert, setExpert] = useState(false);
const showExpert = hasExpert && allUnits.length > 5;
const units = useMemo(
() =>
showExpert && expert
? allUnits
: showExpert
? allUnits.filter((u: UnitDescription) =>
classicUnits.includes(u.unit)
)
: allUnits,
[allUnits, expert, showExpert, classicUnits]
);
const [fromUnit, setFromUnit] = useState<string>(defaultFrom);
const [toUnit, setToUnit] = useState<string>(defaultTo);
const [fromValue, setFromValue] = useState('1');
const [toValue, setToValue] = useState('');
const [inputError, setInputError] = useState('');
const [copied, setCopied] = useState(false);
useEffect(() => {
if (!fromUnit || !units.some((u: UnitDescription) => u.unit === fromUnit)) {
setFromUnit(units[0]?.unit || '');
}
if (
!toUnit ||
!units.some((u: UnitDescription) => u.unit === toUnit) ||
toUnit === fromUnit
) {
const next =
units.find((u: UnitDescription) => u.unit !== fromUnit)?.unit ||
units[0]?.unit ||
'';
setToUnit(next);
}
}, [units, fromUnit, toUnit]);
useEffect(() => {
if (!fromValue || isNaN(Number(fromValue))) {
setToValue('');
setInputError(fromValue ? 'Enter a valid number' : '');
return;
}
if (!fromUnit || !toUnit) {
setToValue('');
setInputError('');
return;
}
try {
const result = converterInstance
.from(fromUnit)
.to(toUnit, Number(fromValue));
setToValue(result.value.toString());
setInputError('');
} catch {
setToValue('');
setInputError('Conversion not possible');
}
}, [fromValue, fromUnit, toUnit, converterInstance]);
const handleCopy = async () => {
if (toValue) {
await navigator.clipboard.writeText(toValue);
setCopied(true);
setTimeout(() => setCopied(false), 1200);
}
};
return (
<Box>
<Typography variant="h5" mb={2}>
{title}
</Typography>
{showExpert && (
<FormControlLabel
control={
<Switch
checked={expert}
onChange={(e) => setExpert(e.target.checked)}
color="primary"
/>
}
label="Expert mode (show all units)"
sx={{ mb: 2 }}
/>
)}
<Grid container spacing={2} alignItems="center">
<Grid item xs={5}>
<TextField
fullWidth
label="Value"
value={fromValue}
onChange={(e) => setFromValue(e.target.value)}
type="number"
error={!!inputError}
helperText={inputError}
/>
</Grid>
<Grid item xs={3}>
<TextField
select
fullWidth
label="From"
value={fromUnit}
onChange={(e) => setFromUnit(e.target.value as string)}
disabled={units.length === 0}
>
{units.map((u: UnitDescription) => (
<MenuItem key={u.unit} value={u.unit}>
{u.singular}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={5}>
<TextField
fullWidth
label="Result"
value={toValue}
InputProps={{
readOnly: true,
endAdornment: (
<InputAdornment position="end">
<Tooltip title={copied ? 'Copied!' : 'Copy'}>
<span>
<IconButton
onClick={handleCopy}
disabled={!toValue}
size="small"
>
<ContentCopyIcon fontSize="small" />
</IconButton>
</span>
</Tooltip>
</InputAdornment>
)
}}
/>
</Grid>
<Grid item xs={3}>
<TextField
select
fullWidth
label="To"
value={toUnit}
onChange={(e) => setToUnit(e.target.value as string)}
disabled={units.length === 0}
>
{units.map((u: UnitDescription) => (
<MenuItem key={u.unit} value={u.unit}>
{u.singular}
</MenuItem>
))}
</TextField>
</Grid>
</Grid>
</Box>
);
};
export default GenericConverter;

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'area-converter',
icon: 'mdi:ruler-square',
keywords: ['area', 'convert', 'square meter', 'acre', 'hectare'],
component: lazy(() => import('./area-converter')),
i18n: {
name: 'translation:areaConverter.title',
description: 'translation:areaConverter.description',
shortDescription: 'translation:areaConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { area } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['m2', 'km2', 'cm2', 'ha', 'ac', 'ft2', 'yd2'];
export default function AreaConverter() {
return (
<GenericConverter
converter={area}
classicUnits={CLASSIC_UNITS}
defaultFrom="m2"
defaultTo="km2"
title="Area Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'current-converter',
icon: 'mdi:current-ac',
keywords: ['current', 'ampere', 'milliampere', 'kiloampere', 'convert'],
component: lazy(() => import('./current-converter')),
i18n: {
name: 'translation:currentConverter.title',
description: 'translation:currentConverter.description',
shortDescription: 'translation:currentConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { current } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['A', 'mA', 'kA'];
export default function CurrentConverter() {
return (
<GenericConverter
converter={current}
classicUnits={CLASSIC_UNITS}
defaultFrom="A"
defaultTo="mA"
title="Current Converter"
/>
);
}

View file

@ -0,0 +1,24 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'digital-converter',
icon: 'mdi:database',
keywords: [
'digital',
'data',
'bit',
'byte',
'kilobyte',
'megabyte',
'gigabyte',
'convert'
],
component: lazy(() => import('./digital-converter')),
i18n: {
name: 'translation:digitalConverter.title',
description: 'translation:digitalConverter.description',
shortDescription: 'translation:digitalConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,27 @@
import { digital } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = [
'B',
'KB',
'MB',
'GB',
'TB',
'b',
'Kb',
'Mb',
'Gb',
'Tb'
];
export default function DigitalConverter() {
return (
<GenericConverter
converter={digital}
classicUnits={CLASSIC_UNITS}
defaultFrom="MB"
defaultTo="GB"
title="Digital Storage Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'energy-converter',
icon: 'mdi:solar-power',
keywords: ['energy', 'joule', 'calorie', 'kilowatt-hour', 'btu', 'convert'],
component: lazy(() => import('./energy-converter')),
i18n: {
name: 'translation:energyConverter.title',
description: 'translation:energyConverter.description',
shortDescription: 'translation:energyConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { energy } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['J', 'Wh', 'kWh', 'cal', 'kcal'];
export default function EnergyConverter() {
return (
<GenericConverter
converter={energy}
classicUnits={CLASSIC_UNITS}
defaultFrom="J"
defaultTo="kWh"
title="Energy Converter"
/>
);
}

View file

@ -0,0 +1,26 @@
import { tool as lengthConverterTool } from './length-converter-meta';
import { tool as areaConverterTool } from './area-converter-meta';
import { tool as volumeConverterTool } from './volume-converter-meta';
import { tool as massConverterTool } from './mass-converter-meta';
import { tool as temperatureConverterTool } from './temperature-converter-meta';
import { tool as speedConverterTool } from './speed-converter-meta';
import { tool as digitalConverterTool } from './digital-converter-meta';
import { tool as energyConverterTool } from './energy-converter-meta';
import { tool as voltageConverterTool } from './voltage-converter-meta';
import { tool as currentConverterTool } from './current-converter-meta';
import { tool as powerConverterTool } from './power-converter-meta';
// Conversion tools section entry point
export const conversionTools = [
lengthConverterTool,
areaConverterTool,
volumeConverterTool,
massConverterTool,
temperatureConverterTool,
speedConverterTool,
digitalConverterTool,
energyConverterTool,
voltageConverterTool,
currentConverterTool,
powerConverterTool
];

View file

@ -0,0 +1,24 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'length-converter',
icon: 'mdi:ruler',
keywords: [
'length',
'distance',
'convert',
'meter',
'mile',
'yard',
'foot',
'inch'
],
component: lazy(() => import('./length-converter')),
i18n: {
name: 'translation:lengthConverter.title',
description: 'translation:lengthConverter.description',
shortDescription: 'translation:lengthConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { length } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['m', 'km', 'cm', 'mm', 'mi', 'yd', 'ft', 'in'];
export default function LengthConverter() {
return (
<GenericConverter
converter={length}
classicUnits={CLASSIC_UNITS}
defaultFrom="m"
defaultTo="km"
title="Length Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'mass-converter',
icon: 'mdi:weight',
keywords: ['mass', 'weight', 'convert', 'gram', 'kilogram', 'pound', 'ounce'],
component: lazy(() => import('./mass-converter')),
i18n: {
name: 'translation:massConverter.title',
description: 'translation:massConverter.description',
shortDescription: 'translation:massConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { mass } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['kg', 'g', 'mg', 'lb', 'oz', 'st', 'ton', 't'];
export default function MassConverter() {
return (
<GenericConverter
converter={mass}
classicUnits={CLASSIC_UNITS}
defaultFrom="kg"
defaultTo="g"
title="Mass Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'power-converter',
icon: 'mdi:power-plug',
keywords: ['power', 'watt', 'kilowatt', 'megawatt', 'horsepower', 'convert'],
component: lazy(() => import('./power-converter')),
i18n: {
name: 'translation:powerConverter.title',
description: 'translation:powerConverter.description',
shortDescription: 'translation:powerConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { power } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['W', 'kW', 'MW', 'GW', 'mW'];
export default function PowerConverter() {
return (
<GenericConverter
converter={power}
classicUnits={CLASSIC_UNITS}
defaultFrom="W"
defaultTo="kW"
title="Power Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'speed-converter',
icon: 'mdi:speedometer',
keywords: ['speed', 'km/h', 'm/s', 'mph', 'knots', 'convert'],
component: lazy(() => import('./speed-converter')),
i18n: {
name: 'translation:speedConverter.title',
description: 'translation:speedConverter.description',
shortDescription: 'translation:speedConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { speed } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['km/h', 'm/s', 'mph', 'knot', 'ft/s'];
export default function SpeedConverter() {
return (
<GenericConverter
converter={speed}
classicUnits={CLASSIC_UNITS}
defaultFrom="km/h"
defaultTo="mph"
title="Speed Converter"
/>
);
}

View file

@ -0,0 +1,22 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'temperature-converter',
icon: 'mdi:thermometer',
keywords: [
'temperature',
'celsius',
'fahrenheit',
'kelvin',
'rankine',
'convert'
],
component: lazy(() => import('./temperature-converter')),
i18n: {
name: 'translation:temperatureConverter.title',
description: 'translation:temperatureConverter.description',
shortDescription: 'translation:temperatureConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { temperature } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['C', 'F', 'K', 'R'];
export default function TemperatureConverter() {
return (
<GenericConverter
converter={temperature}
classicUnits={CLASSIC_UNITS}
defaultFrom="C"
defaultTo="F"
title="Temperature Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'voltage-converter',
icon: 'mdi:flash',
keywords: ['voltage', 'volt', 'millivolt', 'kilovolt', 'convert'],
component: lazy(() => import('./voltage-converter')),
i18n: {
name: 'translation:voltageConverter.title',
description: 'translation:voltageConverter.description',
shortDescription: 'translation:voltageConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { voltage } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['V', 'mV', 'kV'];
export default function VoltageConverter() {
return (
<GenericConverter
converter={voltage}
classicUnits={CLASSIC_UNITS}
defaultFrom="V"
defaultTo="kV"
title="Voltage Converter"
/>
);
}

View file

@ -0,0 +1,15 @@
import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('conversion', {
path: 'volume-converter',
icon: 'mdi:cup-water',
keywords: ['volume', 'capacity', 'convert', 'liter', 'gallon', 'pint', 'cup'],
component: lazy(() => import('./volume-converter')),
i18n: {
name: 'translation:volumeConverter.title',
description: 'translation:volumeConverter.description',
shortDescription: 'translation:volumeConverter.shortDescription',
userTypes: ['generalUsers']
}
});

View file

@ -0,0 +1,16 @@
import { volume } from 'units-converter';
import GenericConverter from './GenericConverter';
const CLASSIC_UNITS = ['L', 'm3', 'mL', 'cL', 'gal', 'qt', 'pt', 'cup', 'floz'];
export default function VolumeConverter() {
return (
<GenericConverter
converter={volume}
classicUnits={CLASSIC_UNITS}
defaultFrom="L"
defaultTo="m3"
title="Volume Converter"
/>
);
}

View file

@ -33,7 +33,8 @@ export type ToolCategory =
| 'video'
| 'pdf'
| 'audio'
| 'xml';
| 'xml'
| 'conversion';
export interface DefinedTool {
type: ToolCategory;

View file

@ -15,6 +15,7 @@ import { pdfTools } from '../pages/tools/pdf';
import { xmlTools } from '../pages/tools/xml';
import { TFunction } from 'i18next';
import { FullI18nKey, I18nNamespaces } from '../i18n';
import { conversionTools } from '../pages/tools/conversion';
const toolCategoriesOrder: ToolCategory[] = [
'image-generic',
@ -27,6 +28,7 @@ const toolCategoriesOrder: ToolCategory[] = [
'list',
'csv',
'number',
'conversion', // <-- Renamed measurement to conversion
'png',
'time',
'xml',
@ -43,7 +45,8 @@ export const tools: DefinedTool[] = [
...numberTools,
...timeTools,
...audioTools,
...xmlTools
...xmlTools,
...conversionTools
];
const categoriesConfig: {
type: ToolCategory;
@ -134,6 +137,12 @@ const categoriesConfig: {
icon: 'mdi-light:xml',
value: 'translation:categories.xml.description',
title: 'translation:categories.xml.title'
},
{
type: 'conversion',
icon: 'material-symbols-light:conversion-path',
value: 'translation:categories.conversion.description',
title: 'translation:categories.conversion.title'
}
];
const CATEGORIES_USER_TYPES_MAPPINGS: Partial<Record<ToolCategory, UserType>> =