-
+
+
+
+
+ Your favorite tools
+
+
+
+
+
+
+
+
+
+ Newest tools
+
+
+
+
+
+
+
+ All the tools
+
+
+
+
+
@@ -43,4 +71,23 @@ useHead({ title: 'IT Tools - Handy online tools for developers' });
.home-page {
padding-top: 50px;
}
+
+::v-deep(.n-grid) {
+ margin-bottom: 12px;
+}
+
+.height-enter-active,
+.height-leave-active {
+ transition: all 0.5s ease-in-out;
+ overflow: hidden;
+ max-height: 500px;
+}
+
+.height-enter-from,
+.height-leave-to {
+ max-height: 42px;
+ overflow: hidden;
+ opacity: 0;
+ margin-bottom: 0;
+}
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 60ad21d0..38975f61 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -1,5 +1,4 @@
import { LockOpen } from '@vicons/tabler';
-import type { ToolCategory } from './tool';
import { tool as chmodCalculator } from './chmod-calculator';
import { tool as mimeTypes } from './mime-types';
@@ -36,16 +35,15 @@ import { tool as tokenGenerator } from './token-generator';
import { tool as urlEncoder } from './url-encoder';
import { tool as urlParser } from './url-parser';
import { tool as uuidGenerator } from './uuid-generator';
+import type { ToolCategory } from './tools.types';
export const toolsByCategory: ToolCategory[] = [
{
name: 'Crypto',
- icon: LockOpen,
components: [tokenGenerator, hashText, bcrypt, uuidGenerator, cypher, bip39, hmacGenerator],
},
{
name: 'Converter',
- icon: LockOpen,
components: [
dateTimeConverter,
baseConverter,
@@ -58,7 +56,6 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Web',
- icon: LockOpen,
components: [
urlEncoder,
htmlEntities,
@@ -72,27 +69,22 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Images',
- icon: LockOpen,
components: [qrCodeGenerator, svgPlaceholderGenerator],
},
{
name: 'Development',
- icon: LockOpen,
components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer, sqlPrettify, chmodCalculator],
},
{
name: 'Math',
- icon: LockOpen,
components: [mathEvaluator, etaCalculator],
},
{
name: 'Measurement',
- icon: LockOpen,
components: [chronometer],
},
{
name: 'Text',
- icon: LockOpen,
components: [loremIpsumGenerator, textStatistics],
},
];
diff --git a/src/tools/tool.ts b/src/tools/tool.ts
index b2ebf497..8289aa33 100644
--- a/src/tools/tool.ts
+++ b/src/tools/tool.ts
@@ -1,27 +1,10 @@
import { config } from '@/config';
-import type { Component } from 'vue';
-
-export interface ITool {
- name: string;
- path: string;
- description: string;
- keywords: string[];
- component: () => Promise;
- icon: Component;
- redirectFrom?: string[];
- isNew: boolean;
-}
-
-export interface ToolCategory {
- name: string;
- icon: Component;
- components: ITool[];
-}
+import type { Tool } from './tools.types';
type WithOptional = Omit & Partial>;
export function defineTool(
- tool: WithOptional,
+ tool: WithOptional,
{ newTools }: { newTools: string[] } = { newTools: config.tools.newTools },
) {
const isNew = newTools.includes(tool.name);
diff --git a/src/tools/tools.store.ts b/src/tools/tools.store.ts
new file mode 100644
index 00000000..2b0826c1
--- /dev/null
+++ b/src/tools/tools.store.ts
@@ -0,0 +1,44 @@
+import { get, useStorage, type MaybeRef } from '@vueuse/core';
+import { defineStore } from 'pinia';
+import type { Ref } from 'vue';
+import { toolsWithCategory } from './index';
+import type { Tool, ToolWithCategory } from './tools.types';
+
+export const useToolStore = defineStore('tools', {
+ state: () => ({
+ favoriteToolsName: useStorage('favoriteToolsName', []) as Ref,
+ }),
+ getters: {
+ favoriteTools(state) {
+ return state.favoriteToolsName
+ .map((favoriteName) => toolsWithCategory.find(({ name }) => name === favoriteName))
+ .filter(Boolean) as ToolWithCategory[]; // cast because .filter(Boolean) does not remove undefined from type
+ },
+
+ notFavoriteTools(state): ToolWithCategory[] {
+ return toolsWithCategory.filter((tool) => !state.favoriteToolsName.includes(tool.name));
+ },
+
+ tools(): ToolWithCategory[] {
+ return toolsWithCategory;
+ },
+
+ newTools(): ToolWithCategory[] {
+ return this.tools.filter(({ isNew }) => isNew);
+ },
+ },
+
+ actions: {
+ addToolToFavorites({ tool }: { tool: MaybeRef }) {
+ this.favoriteToolsName.push(get(tool).name);
+ },
+
+ removeToolFromFavorites({ tool }: { tool: MaybeRef }) {
+ this.favoriteToolsName = this.favoriteToolsName.filter((name) => get(tool).name !== name);
+ },
+
+ isToolFavorite({ tool }: { tool: MaybeRef }) {
+ return this.favoriteToolsName.includes(get(tool).name);
+ },
+ },
+});
diff --git a/src/tools/tools.types.ts b/src/tools/tools.types.ts
new file mode 100644
index 00000000..5630a12e
--- /dev/null
+++ b/src/tools/tools.types.ts
@@ -0,0 +1,19 @@
+import type { Component } from 'vue';
+
+export type Tool = {
+ name: string;
+ path: string;
+ description: string;
+ keywords: string[];
+ component: () => Promise;
+ icon: Component;
+ redirectFrom?: string[];
+ isNew: boolean;
+};
+
+export type ToolCategory = {
+ name: string;
+ components: Tool[];
+};
+
+export type ToolWithCategory = Tool & { category: string };