diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 9948720..5336914 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,9 +4,32 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -24,10 +47,23 @@
+
+
+
+
+
@@ -40,198 +76,217 @@
},
{
"state": "OPEN"
+ },
+ {
+ "searchQuery": "filter",
+ "state": "OPEN"
}
],
"lastFilter": {
+ "searchQuery": "filter",
"state": "OPEN"
}
}
- {
+ "prStates": [
{
- "id": {
- "id": "PR_kwDOMJIfts51PkS9",
- "number": 22
+ "id": {
+ "id": "PR_kwDOMJIfts51PkS9",
+ "number": 22
},
- "lastSeen": 1741207144695
+ "lastSeen": 1741207144695
},
{
- "id": {
- "id": "PR_kwDOMJIfts6NiNYl",
- "number": 32
+ "id": {
+ "id": "PR_kwDOMJIfts6NiNYl",
+ "number": 32
},
- "lastSeen": 1741209723869
+ "lastSeen": 1741209723869
},
{
- "id": {
- "id": "PR_kwDOMJIfts6Nheyd",
- "number": 31
+ "id": {
+ "id": "PR_kwDOMJIfts6Nheyd",
+ "number": 31
},
- "lastSeen": 1741213371410
+ "lastSeen": 1741213371410
},
{
- "id": {
- "id": "PR_kwDOMJIfts6NmRBs",
- "number": 33
+ "id": {
+ "id": "PR_kwDOMJIfts6NmRBs",
+ "number": 33
},
- "lastSeen": 1741282429036
+ "lastSeen": 1741282429036
},
{
- "id": {
- "id": "PR_kwDOMJIfts5zyFTs",
- "number": 15
+ "id": {
+ "id": "PR_kwDOMJIfts5zyFTs",
+ "number": 15
},
- "lastSeen": 1741535540953
+ "lastSeen": 1741535540953
},
{
- "id": {
- "id": "PR_kwDOMJIfts6QQB3c",
- "number": 59
+ "id": {
+ "id": "PR_kwDOMJIfts6QQB3c",
+ "number": 59
},
- "lastSeen": 1743018960900
+ "lastSeen": 1743018960900
},
{
- "id": {
- "id": "PR_kwDOMJIfts6QMPEg",
- "number": 58
+ "id": {
+ "id": "PR_kwDOMJIfts6QMPEg",
+ "number": 58
},
- "lastSeen": 1743019452983
+ "lastSeen": 1743019452983
},
{
- "id": {
- "id": "PR_kwDOMJIfts6QZvRI",
- "number": 61
+ "id": {
+ "id": "PR_kwDOMJIfts6QZvRI",
+ "number": 61
},
- "lastSeen": 1743103196866
+ "lastSeen": 1743103196866
},
{
- "id": {
- "id": "PR_kwDOMJIfts6QqPrQ",
- "number": 73
+ "id": {
+ "id": "PR_kwDOMJIfts6QqPrQ",
+ "number": 73
},
- "lastSeen": 1743265865001
+ "lastSeen": 1743265865001
},
{
- "id": {
- "id": "PR_kwDOMJIfts6Qp5nI",
- "number": 72
+ "id": {
+ "id": "PR_kwDOMJIfts6Qp5nI",
+ "number": 72
},
- "lastSeen": 1743338472110
+ "lastSeen": 1743338472110
},
{
- "id": {
- "id": "PR_kwDOMJIfts6QsjlS",
- "number": 76
+ "id": {
+ "id": "PR_kwDOMJIfts6QsjlS",
+ "number": 76
},
- "lastSeen": 1743352150953
+ "lastSeen": 1743352150953
},
{
- "id": {
- "id": "PR_kwDOMJIfts6Q0JBe",
- "number": 82
+ "id": {
+ "id": "PR_kwDOMJIfts6Q0JBe",
+ "number": 82
},
- "lastSeen": 1743470267269
+ "lastSeen": 1743470267269
},
{
- "id": {
- "id": "PR_kwDOMJIfts6UE9-x",
- "number": 102
+ "id": {
+ "id": "PR_kwDOMJIfts6UE9-x",
+ "number": 102
},
- "lastSeen": 1747171977348
+ "lastSeen": 1747171977348
},
{
- "id": {
- "id": "PR_kwDOMJIfts6XPua_",
- "number": 117
+ "id": {
+ "id": "PR_kwDOMJIfts6XPua_",
+ "number": 117
},
- "lastSeen": 1747929835864
+ "lastSeen": 1747929835864
},
{
- "id": {
- "id": "PR_kwDOMJIfts6XY-mZ",
- "number": 119
+ "id": {
+ "id": "PR_kwDOMJIfts6XY-mZ",
+ "number": 119
},
- "lastSeen": 1748028108508
+ "lastSeen": 1748028108508
},
{
- "id": {
- "id": "PR_kwDOMJIfts6Xdz4n",
- "number": 120
+ "id": {
+ "id": "PR_kwDOMJIfts6Xdz4n",
+ "number": 120
},
- "lastSeen": 1748282672214
+ "lastSeen": 1748282672214
},
{
- "id": {
- "id": "PR_kwDOMJIfts6X_zxl",
- "number": 131
+ "id": {
+ "id": "PR_kwDOMJIfts6X_zxl",
+ "number": 131
},
- "lastSeen": 1748881279494
+ "lastSeen": 1748881279494
},
{
- "id": {
- "id": "PR_kwDOMJIfts6bhieT",
- "number": 152
+ "id": {
+ "id": "PR_kwDOMJIfts6bhieT",
+ "number": 152
},
- "lastSeen": 1751848489082
+ "lastSeen": 1751848489082
},
{
- "id": {
- "id": "PR_kwDOMJIfts6dOyRk",
- "number": 154
+ "id": {
+ "id": "PR_kwDOMJIfts6dOyRk",
+ "number": 154
},
- "lastSeen": 1751849436454
+ "lastSeen": 1751849436454
},
{
- "id": {
- "id": "PR_kwDOMJIfts6cHjNi",
- "number": 153
+ "id": {
+ "id": "PR_kwDOMJIfts6cHjNi",
+ "number": 153
},
- "lastSeen": 1751849501498
+ "lastSeen": 1751849501498
},
{
- "id": {
- "id": "PR_kwDOMJIfts6Zs1FN",
- "number": 145
+ "id": {
+ "id": "PR_kwDOMJIfts6Zs1FN",
+ "number": 145
},
- "lastSeen": 1751849770308
+ "lastSeen": 1751849770308
},
{
- "id": {
- "id": "PR_kwDOMJIfts6bgKi9",
- "number": 150
+ "id": {
+ "id": "PR_kwDOMJIfts6bgKi9",
+ "number": 150
},
- "lastSeen": 1751850367300
+ "lastSeen": 1751850367300
},
{
- "id": {
- "id": "PR_kwDOMJIfts6eUKC-",
- "number": 176
+ "id": {
+ "id": "PR_kwDOMJIfts6eUKC-",
+ "number": 176
},
- "lastSeen": 1752158748013
+ "lastSeen": 1752158748013
},
{
- "id": {
- "id": "PR_kwDOMJIfts6eqzP7",
- "number": 190
+ "id": {
+ "id": "PR_kwDOMJIfts6eqzP7",
+ "number": 190
},
- "lastSeen": 1752404173008
+ "lastSeen": 1752404173008
},
{
- "id": {
- "id": "PR_kwDOMJIfts6et6vx",
- "number": 192
+ "id": {
+ "id": "PR_kwDOMJIfts6et6vx",
+ "number": 192
},
- "lastSeen": 1752585709582
+ "lastSeen": 1752585709582
},
{
- "id": {
- "id": "PR_kwDOMJIfts6d36mi",
- "number": 168
+ "id": {
+ "id": "PR_kwDOMJIfts6d36mi",
+ "number": 168
},
- "lastSeen": 1752805763664
+ "lastSeen": 1752805763664
+ },
+ {
+ "id": {
+ "id": "PR_kwDOMJIfts6fnXKf",
+ "number": 208
+ },
+ "lastSeen": 1752862212326
+ },
+ {
+ "id": {
+ "id": "PR_kwDOMJIfts6fo_ig",
+ "number": 209
+ },
+ "lastSeen": 1753201966322
}
]
-}]]>
+}
{
"selectedUrlAndAccountId": {
"url": "https://github.com/iib0011/omni-tools.git",
@@ -291,7 +346,7 @@
"Vitest.replaceText function (regexp mode).should return the original text when passed an invalid regexp.executor": "Run",
"Vitest.replaceText function.executor": "Run",
"Vitest.timeBetweenDates.executor": "Run",
- "git-widget-placeholder": "main",
+ "git-widget-placeholder": "#209 on fork/AshAnand34/tools-filtering",
"ignore.virus.scanning.warn.message": "true",
"kotlin-language-version-configured": "true",
"last_opened_file_path": "C:/Users/Ibrahima/IdeaProjects/omni-tools",
@@ -316,8 +371,9 @@
"project.structure.last.edited": "Problems",
"project.structure.proportion": "0.0",
"project.structure.side.proportion": "0.2",
- "settings.editor.selected.configurable": "refactai_advanced_settings",
+ "settings.editor.selected.configurable": "preferences.pluginManager",
"ts.external.directory.path": "C:\\Users\\Ibrahima\\IdeaProjects\\omni-tools\\node_modules\\typescript\\lib",
+ "ts.rename.search.for.js.occurrences": "false",
"vue.rearranger.settings.migration": "true"
}
}]]>
@@ -346,7 +402,7 @@
-
+
@@ -420,11 +476,11 @@
-
+
+
-
@@ -538,46 +594,12 @@
-
-
-
- 1748027090253
-
-
-
- 1748027090253
-
-
-
- 1748027889103
-
-
-
- 1748027889103
-
-
-
- 1748028055669
-
-
-
- 1748028055669
-
-
-
- 1748881153433
-
-
-
- 1748881153433
-
-
-
- 1749147227565
-
-
-
- 1749147227565
+
+
+
+
+
+
@@ -931,7 +953,47 @@
1752805853344
-
+
+
+ 1753124389709
+
+
+
+ 1753124389709
+
+
+
+ 1753206794968
+
+
+
+ 1753206794968
+
+
+
+ 1753207817041
+
+
+
+ 1753207817041
+
+
+
+ 1753209484099
+
+
+
+ 1753209484099
+
+
+
+ 1753210033390
+
+
+
+ 1753210033390
+
+
@@ -978,11 +1040,6 @@
-
-
-
-
-
@@ -1003,7 +1060,12 @@
-
+
+
+
+
+
+
false
diff --git a/public/locales/en/pdf.json b/public/locales/en/pdf.json
index eb4b98d..d6b2860 100644
--- a/public/locales/en/pdf.json
+++ b/public/locales/en/pdf.json
@@ -11,6 +11,7 @@
"highCompression": "High Compression",
"highCompressionDescription": "Maximum file size reduction with some quality loss",
"inputTitle": "Input PDF",
+ "longDescription": "Compress PDF files securely in your browser using Ghostscript. Your files never leave your device, ensuring complete privacy while reducing file sizes for email sharing, uploading to websites, or saving storage space. Powered by WebAssembly technology.",
"lowCompression": "Low Compression",
"lowCompressionDescription": "Slightly reduce file size with minimal quality loss",
"mediumCompression": "Medium Compression",
diff --git a/public/locales/en/string.json b/public/locales/en/string.json
index 2994890..5e0387b 100644
--- a/public/locales/en/string.json
+++ b/public/locales/en/string.json
@@ -258,30 +258,29 @@
"shortDescription": "Convert text to uppercase",
"title": "Convert to Uppercase"
},
- "urlEncode": {
- "toolInfo": {
- "description": "Load your string and it will automatically get URL-escaped.",
- "shortDescription": "Quickly URL-escape a string.",
- "longDescription": "This tool URL-encodes a string. Special URL characters get converted to percent-sign encoding. This encoding is called percent-encoding because each character's numeric value gets converted to a percent sign followed by a two-digit hexadecimal value. The hex values are determined based on the character's codepoint value. For example, a space gets escaped to %20, a colon to %3a, a slash to %2f. Characters that are not special stay unchanged. In case you also need to convert non-special characters to percent-encoding, then we've also added an extra option that lets you do that. Select the encode-non-special-chars option to enable this behavior.",
- "title": "String URL encoder"
- },
- "encodingOption": {
- "title": "Encoding Options",
- "nonSpecialCharPlaceholder": "Encode non-special characters",
- "nonSpecialCharDescription": "If selected, then all characters in the input string will be converted to URL-encoding (not just special)."
- },
- "inputTitle": "Input String",
- "resultTitle": "Url-escaped String"
- },
"urlDecode": {
+ "inputTitle": "Input String(URL-escaped)",
+ "resultTitle": "Output string",
"toolInfo": {
"description": "Load your string and it will automatically get URL-unescaped.",
- "shortDescription": "Quickly URL-unescape a string.",
"longDescription": "This tool URL-decodes a previously URL-encoded string. URL-decoding is the inverse operation of URL-encoding. All percent-encoded characters get decoded to characters that you can understand. Some of the most well known percent-encoded values are %20 for a space, %3a for a colon, %2f for a slash, and %3f for a question mark. The two digits following the percent sign are character's char code values in hex.",
+ "shortDescription": "Quickly URL-unescape a string.",
"title": "String URL decoder"
+ }
+ },
+ "urlEncode": {
+ "encodingOption": {
+ "nonSpecialCharDescription": "If selected, then all characters in the input string will be converted to URL-encoding (not just special).",
+ "nonSpecialCharPlaceholder": "Encode non-special characters",
+ "title": "Encoding Options"
},
-
- "inputTitle": "Input String(URL-escaped)",
- "resultTitle": "Output string"
+ "inputTitle": "Input String",
+ "resultTitle": "Url-escaped String",
+ "toolInfo": {
+ "description": "Load your string and it will automatically get URL-escaped.",
+ "longDescription": "This tool URL-encodes a string. Special URL characters get converted to percent-sign encoding. This encoding is called percent-encoding because each character's numeric value gets converted to a percent sign followed by a two-digit hexadecimal value. The hex values are determined based on the character's codepoint value. For example, a space gets escaped to %20, a colon to %3a, a slash to %2f. Characters that are not special stay unchanged. In case you also need to convert non-special characters to percent-encoding, then we've also added an extra option that lets you do that. Select the encode-non-special-chars option to enable this behavior.",
+ "shortDescription": "Quickly URL-escape a string.",
+ "title": "String URL encoder"
+ }
}
}
diff --git a/public/locales/en/time.json b/public/locales/en/time.json
index 1eb65bd..6bfb88e 100644
--- a/public/locales/en/time.json
+++ b/public/locales/en/time.json
@@ -58,6 +58,21 @@
"title": "Convert Time to Seconds"
}
},
+ "convertUnixToDate": {
+ "addUtcLabel": "Add 'UTC' suffix",
+ "addUtcLabelDescription": "Display 'UTC' after the converted date (only for UTC mode)",
+ "description": "Convert a Unix timestamp to a human-readable date.",
+ "outputOptions": "Output Options",
+ "shortDescription": "Convert Unix timestamp to date",
+ "title": "Convert Unix to Date",
+ "toolInfo": {
+ "description": "This tool converts a Unix timestamp (in seconds) into a human-readable date format (e.g., YYYY-MM-DD HH:MM:SS). It supports both local and UTC output, making it useful for quickly interpreting timestamps from logs, APIs, or systems that use Unix time.",
+ "title": "Convert Unix to Date"
+ },
+ "useLocalTime": "Use Local Time",
+ "useLocalTimeDescription": "Show converted date in your local timezone instead of UTC",
+ "withLabel": "Options"
+ },
"crontabGuru": {
"description": "Generate and understand cron expressions. Create cron schedules for automated tasks and system jobs.",
"shortDescription": "Generate and understand cron expressions",
@@ -98,21 +113,5 @@
"zeroPaddingDescription": "Make all time components always be two digits wide.",
"zeroPrintDescription": "Display the dropped parts as zero values \"00\".",
"zeroPrintTruncatedParts": "Zero-print Truncated Parts"
- },
- "convertUnixToDate": {
- "title": "Convert Unix to Date",
- "description": "Convert a Unix timestamp to a human-readable date.",
- "shortDescription": "Convert Unix timestamp to date",
- "longDescription": "",
- "withLabel": "Options",
- "outputOptions": "Output Options",
- "addUtcLabel": "Add 'UTC' suffix",
- "addUtcLabelDescription": "Display 'UTC' after the converted date (only for UTC mode)",
- "useLocalTime": "Use Local Time",
- "useLocalTimeDescription": "Show converted date in your local timezone instead of UTC",
- "toolInfo": {
- "title": "Convert Unix to Date",
- "description": "This tool converts a Unix timestamp (in seconds) into a human-readable date format (e.g., YYYY-MM-DD HH:MM:SS). It supports both local and UTC output, making it useful for quickly interpreting timestamps from logs, APIs, or systems that use Unix time."
- }
}
}
diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json
index 789e161..00f7878 100644
--- a/public/locales/en/translation.json
+++ b/public/locales/en/translation.json
@@ -246,5 +246,9 @@
"copyFailed": "Failed to copy: {{error}}",
"loading": "Loading... This may take a moment.",
"result": "Result"
+ },
+ "userTypes": {
+ "developers": "Developers",
+ "generalUsers": "General users"
}
}
diff --git a/public/locales/en/video.json b/public/locales/en/video.json
index 397df0e..cb9d961 100644
--- a/public/locales/en/video.json
+++ b/public/locales/en/video.json
@@ -38,6 +38,7 @@
"height": "Height",
"inputTitle": "Input Video",
"loadVideoForDimensions": "Load a video to see dimensions",
+ "longDescription": "This tool allows you to crop video files to remove unwanted areas or focus on specific parts of the video. Useful for removing black bars, adjusting aspect ratios, or focusing on important content. Supports various video formats including MP4, MOV, and AVI.",
"resultTitle": "Cropped Video",
"shortDescription": "Crop video to remove unwanted areas",
"title": "Crop Video",
diff --git a/public/locales/es/translation.json b/public/locales/es/translation.json
index 3bec9ef..1b3ca06 100644
--- a/public/locales/es/translation.json
+++ b/public/locales/es/translation.json
@@ -246,5 +246,9 @@
"copyFailed": "No se pudo copiar: {{error}}",
"loading": "Cargando... Esto puede tardar un momento.",
"result": "Resultado"
+ },
+ "userTypes": {
+ "developers": "Desarrolladores",
+ "generalUsers": "Usuarios generales"
}
}
diff --git a/public/locales/fr/time.json b/public/locales/fr/time.json
index c8f6fbb..2ccf157 100644
--- a/public/locales/fr/time.json
+++ b/public/locales/fr/time.json
@@ -56,6 +56,22 @@
"title": "Convertir le temps en secondes"
}
},
+ "convertUnixToDate": {
+ "addUtcLabel": "Ajouter le suffixe 'UTC'",
+ "addUtcLabelDescription": "Affiche 'UTC' après la date convertie (uniquement en mode UTC)",
+ "description": "Convertit un timestamp Unix en une date lisible par un humain.",
+ "longDescription": "Cet outil permet de convertir un timestamp Unix (en secondes) en une date lisible au format AAAA-MM-JJ HH:MM:SS. Il prend en charge l'affichage en UTC ou dans le fuseau horaire local, ce qui est pratique pour interpréter rapidement des horodatages issus de journaux, d'API ou de systèmes utilisant le temps Unix.",
+ "outputOptions": "Options de sortie",
+ "shortDescription": "Conversion de timestamp Unix en date",
+ "title": "Convertir un timestamp Unix en date",
+ "toolInfo": {
+ "description": "Cet outil convertit un timestamp Unix (en secondes) en une date lisible (par ex. AAAA-MM-JJ HH:MM:SS). Il prend en charge l'affichage en heure locale ou en UTC, ce qui le rend utile pour analyser rapidement des données issues de journaux ou d’APIs.",
+ "title": "Convertir un timestamp Unix en date"
+ },
+ "useLocalTime": "Utiliser l’heure locale",
+ "useLocalTimeDescription": "Affiche la date convertie dans votre fuseau horaire local au lieu de l’heure UTC",
+ "withLabel": "Options"
+ },
"crontabGuru": {
"description": "Générez et comprenez les expressions Cron. Créez des planifications Cron pour les tâches automatisées et les tâches système.",
"shortDescription": "Générer et comprendre les expressions cron",
@@ -96,21 +112,5 @@
"zeroPaddingDescription": "Faites en sorte que tous les composants de temps aient toujours une largeur de deux chiffres.",
"zeroPrintDescription": "Afficher les parties supprimées sous forme de valeurs nulles « 00 ».",
"zeroPrintTruncatedParts": "Parties tronquées sans impression"
- },
- "convertUnixToDate": {
- "title": "Convertir un timestamp Unix en date",
- "description": "Convertit un timestamp Unix en une date lisible par un humain.",
- "shortDescription": "Conversion de timestamp Unix en date",
- "longDescription": "Cet outil permet de convertir un timestamp Unix (en secondes) en une date lisible au format AAAA-MM-JJ HH:MM:SS. Il prend en charge l'affichage en UTC ou dans le fuseau horaire local, ce qui est pratique pour interpréter rapidement des horodatages issus de journaux, d'API ou de systèmes utilisant le temps Unix.",
- "withLabel": "Options",
- "outputOptions": "Options de sortie",
- "addUtcLabel": "Ajouter le suffixe 'UTC'",
- "addUtcLabelDescription": "Affiche 'UTC' après la date convertie (uniquement en mode UTC)",
- "useLocalTime": "Utiliser l’heure locale",
- "useLocalTimeDescription": "Affiche la date convertie dans votre fuseau horaire local au lieu de l’heure UTC",
- "toolInfo": {
- "title": "Convertir un timestamp Unix en date",
- "description": "Cet outil convertit un timestamp Unix (en secondes) en une date lisible (par ex. AAAA-MM-JJ HH:MM:SS). Il prend en charge l'affichage en heure locale ou en UTC, ce qui le rend utile pour analyser rapidement des données issues de journaux ou d’APIs."
- }
}
}
diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json
index 3257c16..15fa9bb 100644
--- a/public/locales/fr/translation.json
+++ b/public/locales/fr/translation.json
@@ -246,5 +246,9 @@
"copyFailed": "Échec de la copie : {{error}}",
"loading": "Chargement... Cela peut prendre un moment.",
"result": "Résultat"
+ },
+ "userTypes": {
+ "developers": "Développeurs",
+ "generalUsers": "Grand public"
}
}
diff --git a/src/components/App.tsx b/src/components/App.tsx
index b71abd8..a578cc8 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -12,6 +12,7 @@ import { darkTheme, lightTheme } from '../config/muiConfig';
import ScrollToTopButton from './ScrollToTopButton';
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18n';
+import { UserTypeFilterProvider } from 'providers/UserTypeFilterProvider';
export type Mode = 'dark' | 'light' | 'system';
@@ -57,18 +58,20 @@ function App() {
}}
>
-
- {
- setMode((prev) => nextMode(prev));
- localStorage.setItem('theme', nextMode(mode));
- }}
- />
- }>
-
-
-
+
+
+ {
+ setMode((prev) => nextMode(prev));
+ localStorage.setItem('theme', nextMode(mode));
+ }}
+ />
+ }>
+
+
+
+
diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx
index 91143d6..0404216 100644
--- a/src/components/Hero.tsx
+++ b/src/components/Hero.tsx
@@ -25,6 +25,7 @@ import {
toggleBookmarked
} from '@utils/bookmark';
import IconButton from '@mui/material/IconButton';
+import { useUserTypeFilter } from '../providers/UserTypeFilterProvider';
const GroupHeader = styled('div')(({ theme }) => ({
position: 'sticky',
@@ -50,6 +51,7 @@ export default function Hero() {
const { t } = useTranslation(validNamespaces);
const [inputValue, setInputValue] = useState('');
const theme = useTheme();
+ const { selectedUserTypes } = useUserTypeFilter();
const [filteredTools, setFilteredTools] = useState(tools);
const [bookmarkedToolPaths, setBookmarkedToolPaths] = useState(
getBookmarkedToolPaths()
@@ -96,12 +98,13 @@ export default function Hero() {
];
const handleInputChange = (
- event: React.ChangeEvent<{}>,
+ _event: React.ChangeEvent<{}>,
newInputValue: string
) => {
setInputValue(newInputValue);
- setFilteredTools(filterTools(tools, newInputValue, t));
+ setFilteredTools(filterTools(tools, newInputValue, selectedUserTypes, t));
};
+
const toolsMap = new Map();
for (const tool of filteredTools) {
toolsMap.set(tool.path, {
diff --git a/src/components/ToolHeader.tsx b/src/components/ToolHeader.tsx
index a39c0db..8388274 100644
--- a/src/components/ToolHeader.tsx
+++ b/src/components/ToolHeader.tsx
@@ -103,7 +103,7 @@ export default function ToolHeader({
items={[
{ title: 'All tools', link: '/' },
{
- title: getToolsByCategory(t).find(
+ title: getToolsByCategory([], t).find(
(category) => category.type === type
)!.rawTitle,
link: '/categories/' + type
diff --git a/src/components/ToolLayout.tsx b/src/components/ToolLayout.tsx
index 5559d49..40ad761 100644
--- a/src/components/ToolLayout.tsx
+++ b/src/components/ToolLayout.tsx
@@ -43,7 +43,7 @@ export default function ToolLayout({
const toolDescription: string = t(i18n.description);
const otherCategoryTools =
- getToolsByCategory(t)
+ getToolsByCategory([], t)
.find((category) => category.type === type)
?.tools.filter((tool) => t(tool.name) !== toolTitle)
.map((tool) => ({
@@ -77,8 +77,9 @@ export default function ToolLayout({
category.type === type)!
- .title
+ getToolsByCategory([], t).find(
+ (category) => category.type === type
+ )!.title
)
})}
toolCards={otherCategoryTools}
diff --git a/src/components/UserTypeFilter.tsx b/src/components/UserTypeFilter.tsx
new file mode 100644
index 0000000..7ca45cc
--- /dev/null
+++ b/src/components/UserTypeFilter.tsx
@@ -0,0 +1,47 @@
+import React from 'react';
+import { Box, Chip } from '@mui/material';
+import { UserType } from '@tools/defineTool';
+import { useTranslation } from 'react-i18next';
+
+interface UserTypeFilterProps {
+ selectedUserTypes: UserType[];
+ userTypes?: UserType[];
+ onUserTypesChange: (userTypes: UserType[]) => void;
+}
+
+export default function UserTypeFilter({
+ selectedUserTypes,
+ onUserTypesChange,
+ userTypes = ['generalUsers', 'developers']
+}: UserTypeFilterProps) {
+ const { t } = useTranslation('translation');
+ if (userTypes.length <= 1) return null;
+ return (
+
+ {userTypes.map((userType) => (
+ {
+ const isSelected = selectedUserTypes.includes(userType);
+ const newUserTypes = isSelected
+ ? selectedUserTypes.filter((ut) => ut !== userType)
+ : [...selectedUserTypes, userType];
+ onUserTypesChange(newUserTypes);
+ }}
+ sx={{ cursor: 'pointer' }}
+ />
+ ))}
+
+ );
+}
diff --git a/src/pages/home/Categories.tsx b/src/pages/home/Categories.tsx
index 81bf1b6..9ec1546 100644
--- a/src/pages/home/Categories.tsx
+++ b/src/pages/home/Categories.tsx
@@ -9,7 +9,7 @@ import { categoriesColors } from 'config/uiConfig';
import { Icon } from '@iconify/react';
import { useTranslation } from 'react-i18next';
import { getI18nNamespaceFromToolCategory } from '@utils/string';
-import { validNamespaces } from '../../i18n';
+import { useUserTypeFilter } from '../../providers/UserTypeFilterProvider';
type ArrayElement =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
@@ -84,10 +84,11 @@ const SingleCategory = function ({
{categoryDescription}
-
+
);
};
+
export default function Categories() {
+ const { selectedUserTypes } = useUserTypeFilter();
const { t } = useTranslation();
+ const categories = getToolsByCategory(selectedUserTypes, t);
+
return (
-
- {getToolsByCategory(t).map((category, index) => (
+
+ {categories.map((category, index) => (
))}
diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx
index bf891d8..c65d24f 100644
--- a/src/pages/home/index.tsx
+++ b/src/pages/home/index.tsx
@@ -2,9 +2,12 @@ import { Box, useTheme } from '@mui/material';
import Hero from 'components/Hero';
import Categories from './Categories';
import { Helmet } from 'react-helmet';
+import { useUserTypeFilter } from 'providers/UserTypeFilterProvider';
+import UserTypeFilter from '@components/UserTypeFilter';
export default function Home() {
const theme = useTheme();
+ const { selectedUserTypes, setSelectedUserTypes } = useUserTypeFilter();
return (
+
+
+
);
diff --git a/src/pages/tools-by-category/index.tsx b/src/pages/tools-by-category/index.tsx
index 2129bfe..436311c 100644
--- a/src/pages/tools-by-category/index.tsx
+++ b/src/pages/tools-by-category/index.tsx
@@ -22,28 +22,38 @@ import IconButton from '@mui/material/IconButton';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import SearchIcon from '@mui/icons-material/Search';
import { Helmet } from 'react-helmet';
+import UserTypeFilter from '@components/UserTypeFilter';
import { useTranslation } from 'react-i18next';
import { I18nNamespaces, validNamespaces } from '../../i18n';
+import { useUserTypeFilter } from '../../providers/UserTypeFilterProvider';
const StyledLink = styled(Link)(({ theme }) => ({
'&:hover': {
color: theme.palette.mode === 'dark' ? 'white' : theme.palette.primary.light
}
}));
+
export default function ToolsByCategory() {
const navigate = useNavigate();
const theme = useTheme();
const mainContentRef = React.useRef(null);
const { categoryName } = useParams();
const [searchTerm, setSearchTerm] = React.useState('');
+ const { selectedUserTypes, setSelectedUserTypes } = useUserTypeFilter();
const { t } = useTranslation(validNamespaces);
const rawTitle = getToolCategoryTitle(categoryName as string, t);
// First get tools by category without filtering
- const toolsByCategory =
- getToolsByCategory(t).find(({ type }) => type === categoryName)?.tools ??
- [];
+ const toolsByCategory = getToolsByCategory(selectedUserTypes, t).find(
+ ({ type }) => type === categoryName
+ );
+ const categoryDefinedTools = toolsByCategory?.tools ?? [];
- const categoryTools = filterTools(toolsByCategory, searchTerm, t);
+ const categoryTools = filterTools(
+ categoryDefinedTools,
+ searchTerm,
+ selectedUserTypes,
+ t
+ );
useEffect(() => {
if (mainContentRef.current) {
@@ -90,7 +100,20 @@ export default function ToolsByCategory() {
onChange={(event) => setSearchTerm(event.target.value)}
/>
-
+
+
+
+
{categoryTools.map((tool, index) => (
import('./index'))
});
diff --git a/src/pages/tools/audio/trim/meta.ts b/src/pages/tools/audio/trim/meta.ts
index 5509d79..1ad9e91 100644
--- a/src/pages/tools/audio/trim/meta.ts
+++ b/src/pages/tools/audio/trim/meta.ts
@@ -6,7 +6,8 @@ export const tool = defineTool('audio', {
name: 'audio:trim.title',
description: 'audio:trim.description',
shortDescription: 'audio:trim.shortDescription',
- longDescription: 'audio:trim.longDescription'
+ longDescription: 'audio:trim.longDescription',
+ userTypes: ['generalUsers', 'developers']
},
path: 'trim',
@@ -24,6 +25,5 @@ export const tool = defineTool('audio', {
'audio editing',
'time'
],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/csv/csv-to-yaml/meta.ts b/src/pages/tools/csv/csv-to-yaml/meta.ts
index 7623c7a..67b7f9a 100644
--- a/src/pages/tools/csv/csv-to-yaml/meta.ts
+++ b/src/pages/tools/csv/csv-to-yaml/meta.ts
@@ -12,6 +12,5 @@ export const tool = defineTool('csv', {
path: 'csv-to-yaml',
icon: 'nonicons:yaml-16',
keywords: ['csv', 'to', 'yaml'],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/csv/insert-csv-columns/meta.ts b/src/pages/tools/csv/insert-csv-columns/meta.ts
index 66c4cf6..97c6608 100644
--- a/src/pages/tools/csv/insert-csv-columns/meta.ts
+++ b/src/pages/tools/csv/insert-csv-columns/meta.ts
@@ -12,6 +12,5 @@ export const tool = defineTool('csv', {
icon: 'hugeicons:column-insert',
keywords: ['insert', 'csv', 'columns', 'append', 'prepend'],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/csv/transpose-csv/meta.ts b/src/pages/tools/csv/transpose-csv/meta.ts
index ddda470..76920bc 100644
--- a/src/pages/tools/csv/transpose-csv/meta.ts
+++ b/src/pages/tools/csv/transpose-csv/meta.ts
@@ -13,6 +13,5 @@ export const tool = defineTool('csv', {
icon: 'carbon:transpose',
keywords: ['transpose', 'csv'],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/image/generic/compress/meta.ts b/src/pages/tools/image/generic/compress/meta.ts
index 7cd8c6c..9116b29 100644
--- a/src/pages/tools/image/generic/compress/meta.ts
+++ b/src/pages/tools/image/generic/compress/meta.ts
@@ -5,12 +5,13 @@ export const tool = defineTool('image-generic', {
i18n: {
name: 'image:compress.title',
description: 'image:compress.description',
- shortDescription: 'image:compress.shortDescription'
+ shortDescription: 'image:compress.shortDescription',
+ userTypes: ['generalUsers']
},
path: 'compress',
- component: lazy(() => import('./index')),
icon: 'material-symbols-light:compress-rounded',
- keywords: ['image', 'compress', 'reduce', 'quality']
+ keywords: ['image', 'compress', 'reduce', 'quality'],
+ component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/image/generic/resize/meta.ts b/src/pages/tools/image/generic/resize/meta.ts
index fbc4d1f..dac23a6 100644
--- a/src/pages/tools/image/generic/resize/meta.ts
+++ b/src/pages/tools/image/generic/resize/meta.ts
@@ -5,7 +5,8 @@ export const tool = defineTool('image-generic', {
i18n: {
name: 'image:resize.title',
description: 'image:resize.description',
- shortDescription: 'image:resize.shortDescription'
+ shortDescription: 'image:resize.shortDescription',
+ userTypes: ['generalUsers']
},
path: 'resize',
diff --git a/src/pages/tools/json/validateJson/meta.ts b/src/pages/tools/json/validateJson/meta.ts
index c18b58b..1f91bb4 100644
--- a/src/pages/tools/json/validateJson/meta.ts
+++ b/src/pages/tools/json/validateJson/meta.ts
@@ -1,15 +1,15 @@
-import { defineTool } from '@tools/defineTool';
-import { lazy } from 'react';
-
-export const tool = defineTool('json', {
- path: 'validate-json',
- icon: 'material-symbols:check-circle',
-
- keywords: ['json', 'validate', 'check', 'syntax', 'errors'],
- component: lazy(() => import('./index')),
- i18n: {
- name: 'json:validateJson.title',
- description: 'json:validateJson.description',
- shortDescription: 'json:validateJson.shortDescription'
- }
-});
+import { defineTool } from '@tools/defineTool';
+import { lazy } from 'react';
+
+export const tool = defineTool('json', {
+ path: 'validateJson',
+ icon: 'material-symbols:check-circle',
+
+ keywords: ['json', 'validate', 'check', 'syntax', 'errors'],
+ component: lazy(() => import('./index')),
+ i18n: {
+ name: 'json:validateJson.title',
+ description: 'json:validateJson.description',
+ shortDescription: 'json:validateJson.shortDescription'
+ }
+});
diff --git a/src/pages/tools/list/duplicate/meta.ts b/src/pages/tools/list/duplicate/meta.ts
index e9d2dbd..e594c67 100644
--- a/src/pages/tools/list/duplicate/meta.ts
+++ b/src/pages/tools/list/duplicate/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:duplicate.title',
description: 'list:duplicate.description',
- shortDescription: 'list:duplicate.shortDescription'
+ shortDescription: 'list:duplicate.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/find-most-popular/meta.ts b/src/pages/tools/list/find-most-popular/meta.ts
index 20a8258..c1f732f 100644
--- a/src/pages/tools/list/find-most-popular/meta.ts
+++ b/src/pages/tools/list/find-most-popular/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:findMostPopular.title',
description: 'list:findMostPopular.description',
- shortDescription: 'list:findMostPopular.shortDescription'
+ shortDescription: 'list:findMostPopular.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/find-unique/meta.ts b/src/pages/tools/list/find-unique/meta.ts
index d9828a3..ea09c2b 100644
--- a/src/pages/tools/list/find-unique/meta.ts
+++ b/src/pages/tools/list/find-unique/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:findUnique.title',
description: 'list:findUnique.description',
- shortDescription: 'list:findUnique.shortDescription'
+ shortDescription: 'list:findUnique.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/group/meta.ts b/src/pages/tools/list/group/meta.ts
index 394b61c..d6fb646 100644
--- a/src/pages/tools/list/group/meta.ts
+++ b/src/pages/tools/list/group/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:group.title',
description: 'list:group.description',
- shortDescription: 'list:group.shortDescription'
+ shortDescription: 'list:group.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/reverse/meta.ts b/src/pages/tools/list/reverse/meta.ts
index ff500fa..4ea7e53 100644
--- a/src/pages/tools/list/reverse/meta.ts
+++ b/src/pages/tools/list/reverse/meta.ts
@@ -5,12 +5,12 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
path: 'reverse',
icon: 'proicons:reverse',
-
keywords: ['reverse'],
- component: lazy(() => import('./index')),
i18n: {
name: 'list:reverse.title',
description: 'list:reverse.description',
- shortDescription: 'list:reverse.shortDescription'
- }
+ shortDescription: 'list:reverse.shortDescription',
+ userTypes: ['generalUsers']
+ },
+ component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/list/rotate/meta.ts b/src/pages/tools/list/rotate/meta.ts
index 70a0691..f046133 100644
--- a/src/pages/tools/list/rotate/meta.ts
+++ b/src/pages/tools/list/rotate/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:rotate.title',
description: 'list:rotate.description',
- shortDescription: 'list:rotate.shortDescription'
+ shortDescription: 'list:rotate.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/list/shuffle/meta.ts b/src/pages/tools/list/shuffle/meta.ts
index bb01cd7..704db7a 100644
--- a/src/pages/tools/list/shuffle/meta.ts
+++ b/src/pages/tools/list/shuffle/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:shuffle.title',
description: 'list:shuffle.description',
- shortDescription: 'list:shuffle.shortDescription'
+ shortDescription: 'list:shuffle.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/list/sort/meta.ts b/src/pages/tools/list/sort/meta.ts
index 6b7fac3..a77eb3d 100644
--- a/src/pages/tools/list/sort/meta.ts
+++ b/src/pages/tools/list/sort/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:sort.title',
description: 'list:sort.description',
- shortDescription: 'list:sort.shortDescription'
+ shortDescription: 'list:sort.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/truncate/meta.ts b/src/pages/tools/list/truncate/meta.ts
index 8e42e91..6ba3158 100644
--- a/src/pages/tools/list/truncate/meta.ts
+++ b/src/pages/tools/list/truncate/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:truncate.title',
description: 'list:truncate.description',
- shortDescription: 'list:truncate.shortDescription'
+ shortDescription: 'list:truncate.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/list/unwrap/meta.ts b/src/pages/tools/list/unwrap/meta.ts
index 9f52494..d0c2b03 100644
--- a/src/pages/tools/list/unwrap/meta.ts
+++ b/src/pages/tools/list/unwrap/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:unwrap.title',
description: 'list:unwrap.description',
- shortDescription: 'list:unwrap.shortDescription'
+ shortDescription: 'list:unwrap.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/list/wrap/meta.ts b/src/pages/tools/list/wrap/meta.ts
index de7783a..f4e00bd 100644
--- a/src/pages/tools/list/wrap/meta.ts
+++ b/src/pages/tools/list/wrap/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('list', {
i18n: {
name: 'list:wrap.title',
description: 'list:wrap.description',
- shortDescription: 'list:wrap.shortDescription'
+ shortDescription: 'list:wrap.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/number/arithmetic-sequence/meta.ts b/src/pages/tools/number/arithmetic-sequence/meta.ts
index 20a14b6..5a29578 100644
--- a/src/pages/tools/number/arithmetic-sequence/meta.ts
+++ b/src/pages/tools/number/arithmetic-sequence/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('number', {
i18n: {
name: 'number:arithmeticSequence.title',
description: 'number:arithmeticSequence.description',
- shortDescription: 'number:arithmeticSequence.shortDescription'
+ shortDescription: 'number:arithmeticSequence.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/number/sum/meta.ts b/src/pages/tools/number/sum/meta.ts
index 4b7b9b9..7023d61 100644
--- a/src/pages/tools/number/sum/meta.ts
+++ b/src/pages/tools/number/sum/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('number', {
i18n: {
name: 'number:sum.title',
description: 'number:sum.description',
- shortDescription: 'number:sum.shortDescription'
+ shortDescription: 'number:sum.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/pdf/compress-pdf/meta.ts b/src/pages/tools/pdf/compress-pdf/meta.ts
index bbe0990..f0a414c 100644
--- a/src/pages/tools/pdf/compress-pdf/meta.ts
+++ b/src/pages/tools/pdf/compress-pdf/meta.ts
@@ -19,11 +19,11 @@ export const tool = defineTool('pdf', {
'browser',
'webassembly'
],
-
component: lazy(() => import('./index')),
i18n: {
name: 'pdf:compressPdf.title',
description: 'pdf:compressPdf.description',
- shortDescription: 'pdf:compressPdf.shortDescription'
+ shortDescription: 'pdf:compressPdf.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/pdf/editor/meta.ts b/src/pages/tools/pdf/editor/meta.ts
index 9d9901f..e55694a 100644
--- a/src/pages/tools/pdf/editor/meta.ts
+++ b/src/pages/tools/pdf/editor/meta.ts
@@ -5,7 +5,8 @@ export const tool = defineTool('pdf', {
i18n: {
name: 'pdf:editor.title',
description: 'pdf:editor.description',
- shortDescription: 'pdf:editor.shortDescription'
+ shortDescription: 'pdf:editor.shortDescription',
+ userTypes: ['generalUsers']
},
path: 'editor',
diff --git a/src/pages/tools/pdf/merge-pdf/meta.ts b/src/pages/tools/pdf/merge-pdf/meta.ts
index b393bf2..33ba46c 100644
--- a/src/pages/tools/pdf/merge-pdf/meta.ts
+++ b/src/pages/tools/pdf/merge-pdf/meta.ts
@@ -9,6 +9,7 @@ export const meta = defineTool('pdf', {
i18n: {
name: 'pdf:mergePdf.title',
description: 'pdf:mergePdf.description',
- shortDescription: 'pdf:mergePdf.shortDescription'
+ shortDescription: 'pdf:mergePdf.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/pdf/pdf-to-epub/meta.ts b/src/pages/tools/pdf/pdf-to-epub/meta.ts
index 411814f..8aada08 100644
--- a/src/pages/tools/pdf/pdf-to-epub/meta.ts
+++ b/src/pages/tools/pdf/pdf-to-epub/meta.ts
@@ -9,6 +9,7 @@ export const meta = defineTool('pdf', {
i18n: {
name: 'pdf:pdfToEpub.title',
description: 'pdf:pdfToEpub.description',
- shortDescription: 'pdf:pdfToEpub.shortDescription'
+ shortDescription: 'pdf:pdfToEpub.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/pdf/pdf-to-png/meta.ts b/src/pages/tools/pdf/pdf-to-png/meta.ts
index dc3efb5..919de1f 100644
--- a/src/pages/tools/pdf/pdf-to-png/meta.ts
+++ b/src/pages/tools/pdf/pdf-to-png/meta.ts
@@ -6,13 +6,13 @@ export const tool = defineTool('pdf', {
name: 'pdf:pdfToPng.title',
description: 'pdf:pdfToPng.description',
shortDescription: 'pdf:pdfToPng.shortDescription',
- longDescription: 'pdf:pdfToPng.longDescription'
+ longDescription: 'pdf:pdfToPng.longDescription',
+ userTypes: ['generalUsers']
},
path: 'pdf-to-png',
icon: 'mdi:image-multiple', // Iconify icon ID
keywords: ['pdf', 'png', 'convert', 'image', 'extract', 'pages'],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/pdf/protect-pdf/meta.ts b/src/pages/tools/pdf/protect-pdf/meta.ts
index e3b8a14..7876f1d 100644
--- a/src/pages/tools/pdf/protect-pdf/meta.ts
+++ b/src/pages/tools/pdf/protect-pdf/meta.ts
@@ -18,11 +18,11 @@ export const tool = defineTool('pdf', {
'browser',
'encryption'
],
-
component: lazy(() => import('./index')),
i18n: {
name: 'pdf:protectPdf.title',
description: 'pdf:protectPdf.description',
- shortDescription: 'pdf:protectPdf.shortDescription'
+ shortDescription: 'pdf:protectPdf.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/pdf/rotate-pdf/meta.ts b/src/pages/tools/pdf/rotate-pdf/meta.ts
index f0ab83f..e037ff4 100644
--- a/src/pages/tools/pdf/rotate-pdf/meta.ts
+++ b/src/pages/tools/pdf/rotate-pdf/meta.ts
@@ -6,13 +6,13 @@ export const tool = defineTool('pdf', {
name: 'pdf:rotatePdf.title',
description: 'pdf:rotatePdf.description',
shortDescription: 'pdf:rotatePdf.shortDescription',
- longDescription: 'pdf:rotatePdf.longDescription'
+ longDescription: 'pdf:rotatePdf.longDescription',
+ userTypes: ['generalUsers']
},
path: 'rotate-pdf',
icon: 'carbon:rotate',
keywords: ['pdf', 'rotate', 'rotation', 'document', 'pages', 'orientation'],
-
component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/pdf/split-pdf/meta.ts b/src/pages/tools/pdf/split-pdf/meta.ts
index 04d8ac2..0352c5b 100644
--- a/src/pages/tools/pdf/split-pdf/meta.ts
+++ b/src/pages/tools/pdf/split-pdf/meta.ts
@@ -9,6 +9,7 @@ export const meta = defineTool('pdf', {
i18n: {
name: 'pdf:splitPdf.title',
description: 'pdf:splitPdf.description',
- shortDescription: 'pdf:splitPdf.shortDescription'
+ shortDescription: 'pdf:splitPdf.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/base64/meta.ts b/src/pages/tools/string/base64/meta.ts
index a334e77..d51eb7f 100644
--- a/src/pages/tools/string/base64/meta.ts
+++ b/src/pages/tools/string/base64/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:base64.title',
description: 'string:base64.description',
- shortDescription: 'string:base64.shortDescription'
+ shortDescription: 'string:base64.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/censor/meta.ts b/src/pages/tools/string/censor/meta.ts
index bda557b..12d8af8 100644
--- a/src/pages/tools/string/censor/meta.ts
+++ b/src/pages/tools/string/censor/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:censor.title',
description: 'string:censor.description',
- shortDescription: 'string:censor.shortDescription'
+ shortDescription: 'string:censor.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/create-palindrome/meta.ts b/src/pages/tools/string/create-palindrome/meta.ts
index cadd578..b523ced 100644
--- a/src/pages/tools/string/create-palindrome/meta.ts
+++ b/src/pages/tools/string/create-palindrome/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:createPalindrome.title',
description: 'string:createPalindrome.description',
- shortDescription: 'string:createPalindrome.shortDescription'
+ shortDescription: 'string:createPalindrome.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/extract-substring/meta.ts b/src/pages/tools/string/extract-substring/meta.ts
index 7a7a361..01cfb69 100644
--- a/src/pages/tools/string/extract-substring/meta.ts
+++ b/src/pages/tools/string/extract-substring/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:extractSubstring.title',
description: 'string:extractSubstring.description',
- shortDescription: 'string:extractSubstring.shortDescription'
+ shortDescription: 'string:extractSubstring.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/join/meta.ts b/src/pages/tools/string/join/meta.ts
index 5fcc936..e0c0e03 100644
--- a/src/pages/tools/string/join/meta.ts
+++ b/src/pages/tools/string/join/meta.ts
@@ -3,13 +3,15 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
path: 'join',
+
icon: 'material-symbols-light:join',
- keywords: ['join'],
+ keywords: ['text', 'join'],
component: lazy(() => import('./index')),
i18n: {
name: 'string:join.title',
description: 'string:join.description',
- shortDescription: 'string:join.shortDescription'
+ shortDescription: 'string:join.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/palindrome/meta.ts b/src/pages/tools/string/palindrome/meta.ts
index 5c56ba0..fd16fe9 100644
--- a/src/pages/tools/string/palindrome/meta.ts
+++ b/src/pages/tools/string/palindrome/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:palindrome.title',
description: 'string:palindrome.description',
- shortDescription: 'string:palindrome.shortDescription'
+ shortDescription: 'string:palindrome.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/quote/meta.ts b/src/pages/tools/string/quote/meta.ts
index 7bb86e9..fb88052 100644
--- a/src/pages/tools/string/quote/meta.ts
+++ b/src/pages/tools/string/quote/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:quote.title',
description: 'string:quote.description',
- shortDescription: 'string:quote.shortDescription'
+ shortDescription: 'string:quote.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/randomize-case/meta.ts b/src/pages/tools/string/randomize-case/meta.ts
index 4eb3af1..92100a2 100644
--- a/src/pages/tools/string/randomize-case/meta.ts
+++ b/src/pages/tools/string/randomize-case/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:randomizeCase.title',
description: 'string:randomizeCase.description',
- shortDescription: 'string:randomizeCase.shortDescription'
+ shortDescription: 'string:randomizeCase.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/string/remove-duplicate-lines/meta.ts b/src/pages/tools/string/remove-duplicate-lines/meta.ts
index debe033..5f4facc 100644
--- a/src/pages/tools/string/remove-duplicate-lines/meta.ts
+++ b/src/pages/tools/string/remove-duplicate-lines/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:removeDuplicateLines.title',
description: 'string:removeDuplicateLines.description',
- shortDescription: 'string:removeDuplicateLines.shortDescription'
+ shortDescription: 'string:removeDuplicateLines.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/repeat/meta.ts b/src/pages/tools/string/repeat/meta.ts
index 02c2910..2ac9fc7 100644
--- a/src/pages/tools/string/repeat/meta.ts
+++ b/src/pages/tools/string/repeat/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:repeat.title',
description: 'string:repeat.description',
- shortDescription: 'string:repeat.shortDescription'
+ shortDescription: 'string:repeat.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/reverse/meta.ts b/src/pages/tools/string/reverse/meta.ts
index 1f30e9b..865199c 100644
--- a/src/pages/tools/string/reverse/meta.ts
+++ b/src/pages/tools/string/reverse/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:reverse.title',
description: 'string:reverse.description',
- shortDescription: 'string:reverse.shortDescription'
+ shortDescription: 'string:reverse.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/rot13/meta.ts b/src/pages/tools/string/rot13/meta.ts
index 8e6be8c..76d3c65 100644
--- a/src/pages/tools/string/rot13/meta.ts
+++ b/src/pages/tools/string/rot13/meta.ts
@@ -6,7 +6,8 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:rot13.title',
description: 'string:rot13.description',
- shortDescription: 'string:rot13.shortDescription'
+ shortDescription: 'string:rot13.shortDescription',
+ userTypes: ['generalUsers', 'developers']
},
path: 'rot13',
diff --git a/src/pages/tools/string/rotate/meta.ts b/src/pages/tools/string/rotate/meta.ts
index 66c4117..468d806 100644
--- a/src/pages/tools/string/rotate/meta.ts
+++ b/src/pages/tools/string/rotate/meta.ts
@@ -6,7 +6,8 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:rotate.title',
description: 'string:rotate.description',
- shortDescription: 'string:rotate.shortDescription'
+ shortDescription: 'string:rotate.shortDescription',
+ userTypes: ['generalUsers', 'developers']
},
path: 'rotate',
diff --git a/src/pages/tools/string/split/meta.ts b/src/pages/tools/string/split/meta.ts
index 8b7b6a9..4d8ac4b 100644
--- a/src/pages/tools/string/split/meta.ts
+++ b/src/pages/tools/string/split/meta.ts
@@ -3,6 +3,7 @@ import { lazy } from 'react';
export const tool = defineTool('string', {
path: 'split',
+
icon: 'material-symbols-light:call-split',
keywords: ['split'],
@@ -10,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:split.title',
description: 'string:split.description',
- shortDescription: 'string:split.shortDescription'
+ shortDescription: 'string:split.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/statistic/meta.ts b/src/pages/tools/string/statistic/meta.ts
index f56b7d4..7aba6da 100644
--- a/src/pages/tools/string/statistic/meta.ts
+++ b/src/pages/tools/string/statistic/meta.ts
@@ -11,6 +11,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:statistic.title',
description: 'string:statistic.description',
- shortDescription: 'string:statistic.shortDescription'
+ shortDescription: 'string:statistic.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/text-replacer/meta.ts b/src/pages/tools/string/text-replacer/meta.ts
index d02502b..4d48b07 100644
--- a/src/pages/tools/string/text-replacer/meta.ts
+++ b/src/pages/tools/string/text-replacer/meta.ts
@@ -5,7 +5,8 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:textReplacer.title',
description: 'string:textReplacer.description',
- shortDescription: 'string:textReplacer.shortDescription'
+ shortDescription: 'string:textReplacer.shortDescription',
+ userTypes: ['generalUsers', 'developers']
},
path: 'replacer',
diff --git a/src/pages/tools/string/to-morse/meta.ts b/src/pages/tools/string/to-morse/meta.ts
index 5244c3a..b15a757 100644
--- a/src/pages/tools/string/to-morse/meta.ts
+++ b/src/pages/tools/string/to-morse/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:toMorse.title',
description: 'string:toMorse.description',
- shortDescription: 'string:toMorse.shortDescription'
+ shortDescription: 'string:toMorse.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/truncate/meta.ts b/src/pages/tools/string/truncate/meta.ts
index a62eebc..256c92c 100644
--- a/src/pages/tools/string/truncate/meta.ts
+++ b/src/pages/tools/string/truncate/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:truncate.title',
description: 'string:truncate.description',
- shortDescription: 'string:truncate.shortDescription'
+ shortDescription: 'string:truncate.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/string/uppercase/meta.ts b/src/pages/tools/string/uppercase/meta.ts
index 9c2e25c..4b221a6 100644
--- a/src/pages/tools/string/uppercase/meta.ts
+++ b/src/pages/tools/string/uppercase/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('string', {
i18n: {
name: 'string:uppercase.title',
description: 'string:uppercase.description',
- shortDescription: 'string:uppercase.shortDescription'
+ shortDescription: 'string:uppercase.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/time/check-leap-years/meta.ts b/src/pages/tools/time/check-leap-years/meta.ts
index 661f4a6..b275f97 100644
--- a/src/pages/tools/time/check-leap-years/meta.ts
+++ b/src/pages/tools/time/check-leap-years/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:checkLeapYears.title',
description: 'time:checkLeapYears.description',
- shortDescription: 'time:checkLeapYears.shortDescription'
+ shortDescription: 'time:checkLeapYears.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/time/convert-days-to-hours/meta.ts b/src/pages/tools/time/convert-days-to-hours/meta.ts
index a94823b..938ed56 100644
--- a/src/pages/tools/time/convert-days-to-hours/meta.ts
+++ b/src/pages/tools/time/convert-days-to-hours/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:convertDaysToHours.title',
description: 'time:convertDaysToHours.description',
- shortDescription: 'time:convertDaysToHours.shortDescription'
+ shortDescription: 'time:convertDaysToHours.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/time/convert-hours-to-days/meta.ts b/src/pages/tools/time/convert-hours-to-days/meta.ts
index fd49c3f..c9c505e 100644
--- a/src/pages/tools/time/convert-hours-to-days/meta.ts
+++ b/src/pages/tools/time/convert-hours-to-days/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:convertHoursToDays.title',
description: 'time:convertHoursToDays.description',
- shortDescription: 'time:convertHoursToDays.shortDescription'
+ shortDescription: 'time:convertHoursToDays.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/time/convert-seconds-to-time/meta.ts b/src/pages/tools/time/convert-seconds-to-time/meta.ts
index 574623d..91ce4ab 100644
--- a/src/pages/tools/time/convert-seconds-to-time/meta.ts
+++ b/src/pages/tools/time/convert-seconds-to-time/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:convertSecondsToTime.title',
description: 'time:convertSecondsToTime.description',
- shortDescription: 'time:convertSecondsToTime.shortDescription'
+ shortDescription: 'time:convertSecondsToTime.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/time/convert-time-to-seconds/meta.ts b/src/pages/tools/time/convert-time-to-seconds/meta.ts
index 988e6c0..c71988f 100644
--- a/src/pages/tools/time/convert-time-to-seconds/meta.ts
+++ b/src/pages/tools/time/convert-time-to-seconds/meta.ts
@@ -5,11 +5,12 @@ export const tool = defineTool('time', {
path: 'convert-time-to-seconds',
icon: 'material-symbols:schedule',
- keywords: ['time', 'seconds', 'convert', 'format'],
+ keywords: ['time', 'seconds', 'convert', 'format', 'HH:MM:SS'],
component: lazy(() => import('./index')),
i18n: {
name: 'time:convertTimeToSeconds.title',
description: 'time:convertTimeToSeconds.description',
- shortDescription: 'time:convertTimeToSeconds.shortDescription'
+ shortDescription: 'time:convertTimeToSeconds.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/time/crontab-guru/meta.ts b/src/pages/tools/time/crontab-guru/meta.ts
index 2c5d2e0..2ca4304 100644
--- a/src/pages/tools/time/crontab-guru/meta.ts
+++ b/src/pages/tools/time/crontab-guru/meta.ts
@@ -4,12 +4,21 @@ import { lazy } from 'react';
export const tool = defineTool('time', {
path: 'crontab-guru',
icon: 'material-symbols:schedule',
-
- keywords: ['cron', 'schedule', 'automation', 'expression'],
+ keywords: [
+ 'crontab',
+ 'cron',
+ 'schedule',
+ 'guru',
+ 'time',
+ 'expression',
+ 'parser',
+ 'explain'
+ ],
component: lazy(() => import('./index')),
i18n: {
name: 'time:crontabGuru.title',
description: 'time:crontabGuru.description',
- shortDescription: 'time:crontabGuru.shortDescription'
+ shortDescription: 'time:crontabGuru.shortDescription',
+ userTypes: ['developers']
}
});
diff --git a/src/pages/tools/time/time-between-dates/meta.ts b/src/pages/tools/time/time-between-dates/meta.ts
index 028617b..34f18a5 100644
--- a/src/pages/tools/time/time-between-dates/meta.ts
+++ b/src/pages/tools/time/time-between-dates/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:timeBetweenDates.title',
description: 'time:timeBetweenDates.description',
- shortDescription: 'time:timeBetweenDates.shortDescription'
+ shortDescription: 'time:timeBetweenDates.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/time/truncate-clock-time/meta.ts b/src/pages/tools/time/truncate-clock-time/meta.ts
index 9a9498a..b64ea67 100644
--- a/src/pages/tools/time/truncate-clock-time/meta.ts
+++ b/src/pages/tools/time/truncate-clock-time/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('time', {
i18n: {
name: 'time:truncateClockTime.title',
description: 'time:truncateClockTime.description',
- shortDescription: 'time:truncateClockTime.shortDescription'
+ shortDescription: 'time:truncateClockTime.shortDescription',
+ userTypes: ['generalUsers', 'developers']
}
});
diff --git a/src/pages/tools/video/change-speed/meta.ts b/src/pages/tools/video/change-speed/meta.ts
index c881cb6..da97073 100644
--- a/src/pages/tools/video/change-speed/meta.ts
+++ b/src/pages/tools/video/change-speed/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:changeSpeed.title',
description: 'video:changeSpeed.description',
- shortDescription: 'video:changeSpeed.shortDescription'
+ shortDescription: 'video:changeSpeed.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/compress/meta.ts b/src/pages/tools/video/compress/meta.ts
index fb9a09d..bab6d6f 100644
--- a/src/pages/tools/video/compress/meta.ts
+++ b/src/pages/tools/video/compress/meta.ts
@@ -8,15 +8,20 @@ export const tool = defineTool('video', {
keywords: [
'compress',
'video',
- 'resize',
- 'scale',
- 'resolution',
- 'reduce size'
+ 'reduce',
+ 'size',
+ 'optimize',
+ 'mp4',
+ 'mov',
+ 'avi',
+ 'video editing',
+ 'shrink'
],
component: lazy(() => import('./index')),
i18n: {
name: 'video:compress.title',
description: 'video:compress.description',
- shortDescription: 'video:compress.shortDescription'
+ shortDescription: 'video:compress.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/crop-video/meta.ts b/src/pages/tools/video/crop-video/meta.ts
index 22a23e3..0026022 100644
--- a/src/pages/tools/video/crop-video/meta.ts
+++ b/src/pages/tools/video/crop-video/meta.ts
@@ -4,12 +4,22 @@ import { lazy } from 'react';
export const tool = defineTool('video', {
path: 'crop-video',
icon: 'material-symbols:crop',
-
- keywords: ['video', 'crop', 'trim', 'edit', 'resize'],
- component: lazy(() => import('./index')),
+ keywords: [
+ 'crop',
+ 'video',
+ 'trim',
+ 'aspect ratio',
+ 'mp4',
+ 'mov',
+ 'avi',
+ 'video editing',
+ 'resize'
+ ],
i18n: {
name: 'video:cropVideo.title',
description: 'video:cropVideo.description',
- shortDescription: 'video:cropVideo.shortDescription'
- }
+ shortDescription: 'video:cropVideo.shortDescription',
+ userTypes: ['generalUsers']
+ },
+ component: lazy(() => import('./index'))
});
diff --git a/src/pages/tools/video/flip/meta.ts b/src/pages/tools/video/flip/meta.ts
index 24d4e96..f15ed8e 100644
--- a/src/pages/tools/video/flip/meta.ts
+++ b/src/pages/tools/video/flip/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:flip.title',
description: 'video:flip.description',
- shortDescription: 'video:flip.shortDescription'
+ shortDescription: 'video:flip.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/loop/meta.ts b/src/pages/tools/video/loop/meta.ts
index 1176b2f..5484ed3 100644
--- a/src/pages/tools/video/loop/meta.ts
+++ b/src/pages/tools/video/loop/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:loop.title',
description: 'video:loop.description',
- shortDescription: 'video:loop.shortDescription'
+ shortDescription: 'video:loop.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/rotate/meta.ts b/src/pages/tools/video/rotate/meta.ts
index d49d001..0489519 100644
--- a/src/pages/tools/video/rotate/meta.ts
+++ b/src/pages/tools/video/rotate/meta.ts
@@ -10,6 +10,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:rotate.title',
description: 'video:rotate.description',
- shortDescription: 'video:rotate.shortDescription'
+ shortDescription: 'video:rotate.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/trim/meta.ts b/src/pages/tools/video/trim/meta.ts
index 98d7e97..bfcfc80 100644
--- a/src/pages/tools/video/trim/meta.ts
+++ b/src/pages/tools/video/trim/meta.ts
@@ -9,6 +9,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:trim.title',
description: 'video:trim.description',
- shortDescription: 'video:trim.shortDescription'
+ shortDescription: 'video:trim.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/pages/tools/video/video-to-gif/meta.ts b/src/pages/tools/video/video-to-gif/meta.ts
index 9cec755..b323686 100644
--- a/src/pages/tools/video/video-to-gif/meta.ts
+++ b/src/pages/tools/video/video-to-gif/meta.ts
@@ -9,6 +9,7 @@ export const tool = defineTool('video', {
i18n: {
name: 'video:videoToGif.title',
description: 'video:videoToGif.description',
- shortDescription: 'video:videoToGif.shortDescription'
+ shortDescription: 'video:videoToGif.shortDescription',
+ userTypes: ['generalUsers']
}
});
diff --git a/src/providers/UserTypeFilterProvider.tsx b/src/providers/UserTypeFilterProvider.tsx
new file mode 100644
index 0000000..b989ba7
--- /dev/null
+++ b/src/providers/UserTypeFilterProvider.tsx
@@ -0,0 +1,77 @@
+import React, {
+ createContext,
+ useContext,
+ useState,
+ useEffect,
+ ReactNode,
+ useMemo
+} from 'react';
+import { UserType } from '@tools/defineTool';
+
+interface UserTypeFilterContextType {
+ selectedUserTypes: UserType[];
+ setSelectedUserTypes: (userTypes: UserType[]) => void;
+}
+
+const UserTypeFilterContext = createContext(
+ null
+);
+
+interface UserTypeFilterProviderProps {
+ children: ReactNode;
+}
+
+export function UserTypeFilterProvider({
+ children
+}: UserTypeFilterProviderProps) {
+ const [selectedUserTypes, setSelectedUserTypes] = useState(() => {
+ try {
+ const saved = localStorage.getItem('selectedUserTypes');
+ return saved ? JSON.parse(saved) : [];
+ } catch (error) {
+ console.error(
+ 'Error loading selectedUserTypes from localStorage:',
+ error
+ );
+ return [];
+ }
+ });
+
+ useEffect(() => {
+ try {
+ localStorage.setItem(
+ 'selectedUserTypes',
+ JSON.stringify(selectedUserTypes)
+ );
+ } catch (error) {
+ console.error('Error saving selectedUserTypes to localStorage:', error);
+ }
+ }, [selectedUserTypes]);
+
+ const contextValue = useMemo(
+ () => ({
+ selectedUserTypes,
+ setSelectedUserTypes
+ }),
+ [selectedUserTypes]
+ );
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useUserTypeFilter(): UserTypeFilterContextType {
+ const context = useContext(UserTypeFilterContext);
+
+ if (!context) {
+ throw new Error(
+ 'useUserTypeFilter must be used within a UserTypeFilterProvider. ' +
+ 'Make sure your component is wrapped with .'
+ );
+ }
+
+ return context;
+}
diff --git a/src/tools/defineTool.tsx b/src/tools/defineTool.tsx
index ed19326..104c83b 100644
--- a/src/tools/defineTool.tsx
+++ b/src/tools/defineTool.tsx
@@ -4,6 +4,8 @@ import { IconifyIcon } from '@iconify/react';
import { FullI18nKey, validNamespaces } from '../i18n';
import { useTranslation } from 'react-i18next';
+export type UserType = 'generalUsers' | 'developers';
+
export interface ToolMeta {
path: string;
component: LazyExoticComponent>;
@@ -14,21 +16,22 @@ export interface ToolMeta {
description: FullI18nKey;
shortDescription: FullI18nKey;
longDescription?: FullI18nKey;
+ userTypes?: UserType[];
};
}
export type ToolCategory =
| 'string'
+ | 'image-generic'
| 'png'
| 'number'
| 'gif'
- | 'video'
| 'list'
| 'json'
| 'time'
| 'csv'
+ | 'video'
| 'pdf'
- | 'image-generic'
| 'audio'
| 'xml';
@@ -41,6 +44,7 @@ export interface DefinedTool {
icon: IconifyIcon | string;
keywords: string[];
component: () => JSX.Element;
+ userTypes?: UserType[];
}
export interface ToolComponentProps {
@@ -62,6 +66,7 @@ export const defineTool = (
description: i18n.description,
shortDescription: i18n.shortDescription,
keywords,
+ userTypes: i18n.userTypes,
component: function ToolComponent() {
const { t } = useTranslation(validNamespaces);
return (
diff --git a/src/tools/index.ts b/src/tools/index.ts
index dd1b723..e13d3fc 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -1,6 +1,6 @@
import { stringTools } from '../pages/tools/string';
import { imageTools } from '../pages/tools/image';
-import { DefinedTool, ToolCategory } from './defineTool';
+import { DefinedTool, ToolCategory, UserType } from './defineTool';
import { capitalizeFirstLetter } from '@utils/string';
import { numberTools } from '../pages/tools/number';
import { videoTools } from '../pages/tools/video';
@@ -136,6 +136,36 @@ const categoriesConfig: {
title: 'translation:categories.xml.title'
}
];
+const CATEGORIES_USER_TYPES_MAPPINGS: Partial> =
+ {
+ xml: 'developers',
+ csv: 'developers',
+ json: 'developers',
+ gif: 'generalUsers',
+ png: 'generalUsers',
+ 'image-generic': 'generalUsers',
+ video: 'generalUsers',
+ audio: 'generalUsers'
+ };
+// Filter tools by user types
+export const filterToolsByUserTypes = (
+ tools: DefinedTool[],
+ userTypes: UserType[]
+): DefinedTool[] => {
+ if (userTypes.length === 0) return tools;
+
+ return tools.filter((tool) => {
+ if (CATEGORIES_USER_TYPES_MAPPINGS[tool.type]) {
+ return userTypes.includes(CATEGORIES_USER_TYPES_MAPPINGS[tool.type]!);
+ }
+ // If tool has no userTypes defined, show it to all users
+ if (!tool.userTypes || tool.userTypes.length === 0) return true;
+
+ // Check if tool has any of the selected user types
+ return tool.userTypes.some((userType) => userTypes.includes(userType));
+ });
+};
+
// use for changelogs
// console.log(
// 'tools',
@@ -144,12 +174,22 @@ const categoriesConfig: {
export const filterTools = (
tools: DefinedTool[],
query: string,
+ userTypes: UserType[] = [],
t: TFunction
): DefinedTool[] => {
- if (!query) return tools;
+ let filteredTools = tools;
+
+ // First filter by user types
+ if (userTypes.length > 0) {
+ filteredTools = filterToolsByUserTypes(tools, userTypes);
+ }
+
+ // Then filter by search query
+ if (!query) return filteredTools;
const lowerCaseQuery = query.toLowerCase();
- return tools.filter(
+
+ return filteredTools.filter(
(tool) =>
t(tool.name).toLowerCase().includes(lowerCaseQuery) ||
t(tool.description).toLowerCase().includes(lowerCaseQuery) ||
@@ -161,6 +201,7 @@ export const filterTools = (
};
export const getToolsByCategory = (
+ userTypes: UserType[] = [],
t: TFunction
): {
title: string;
@@ -170,14 +211,28 @@ export const getToolsByCategory = (
type: ToolCategory;
example: { title: string; path: string };
tools: DefinedTool[];
+ userTypes: UserType[]; // <-- Add this line
}[] => {
const groupedByType: Partial> =
Object.groupBy(tools, ({ type }) => type);
+
return (Object.entries(groupedByType) as Entries)
.map(([type, tools]) => {
const categoryConfig = categoriesConfig.find(
(config) => config.type === type
);
+
+ // Filter tools by user types if specified
+ const filteredTools =
+ userTypes.length > 0
+ ? filterToolsByUserTypes(tools ?? [], userTypes)
+ : tools ?? [];
+
+ // Aggregate unique userTypes from all tools in this category
+ const aggregatedUserTypes = Array.from(
+ new Set((filteredTools ?? []).flatMap((tool) => tool.userTypes ?? []))
+ );
+
return {
rawTitle: categoryConfig?.title
? t(categoryConfig.title)
@@ -188,12 +243,22 @@ export const getToolsByCategory = (
description: categoryConfig?.value ? t(categoryConfig.value) : '',
type,
icon: categoryConfig!.icon,
- tools: tools ?? [],
- example: tools
- ? { title: tools[0].name, path: tools[0].path }
- : { title: '', path: '' }
+ tools: filteredTools,
+ example:
+ filteredTools.length > 0
+ ? { title: filteredTools[0].name, path: filteredTools[0].path }
+ : { title: '', path: '' },
+ userTypes: aggregatedUserTypes // <-- Add this line
};
})
+ .filter((category) => category.tools.length > 0)
+ .filter((category) =>
+ userTypes.length > 0
+ ? [...category.userTypes, CATEGORIES_USER_TYPES_MAPPINGS[category.type]]
+ .filter(Boolean)
+ .some((categoryUserType) => userTypes.includes(categoryUserType!))
+ : true
+ ) // Only show categories with tools
.sort(
(a, b) =>
toolCategoriesOrder.indexOf(a.type) -
diff --git a/src/utils/string.ts b/src/utils/string.ts
index 4207348..b5a4cc0 100644
--- a/src/utils/string.ts
+++ b/src/utils/string.ts
@@ -114,7 +114,7 @@ export const getToolCategoryTitle = (
categoryName: string,
t: TFunction
): string =>
- getToolsByCategory(t).find((category) => category.type === categoryName)!
+ getToolsByCategory([], t).find((category) => category.type === categoryName)!
.rawTitle;
// Type guard to check if a value is a valid I18nNamespaces