mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-20 14:56:17 -04:00
feat(favorites) drag-and-drop favorites section (#1360)
This commit is contained in:
parent
ea8c4ed077
commit
0b1b98f93e
13 changed files with 72 additions and 4 deletions
|
@ -10,6 +10,7 @@ home:
|
||||||
newestTools: Neueste Tools
|
newestTools: Neueste Tools
|
||||||
favoriteTools: Deine Lieblingstools
|
favoriteTools: Deine Lieblingstools
|
||||||
allTools: Alle Tools
|
allTools: Alle Tools
|
||||||
|
favoritesDndToolTip: 'Ziehen und Ablegen, um Favoriten neu zu ordnen'
|
||||||
subtitle: Praktische Tools für Entwickler
|
subtitle: Praktische Tools für Entwickler
|
||||||
toggleMenu: Menü umschalten
|
toggleMenu: Menü umschalten
|
||||||
home: Startseite
|
home: Startseite
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: Newest tools
|
newestTools: Newest tools
|
||||||
favoriteTools: 'Your favorite tools'
|
favoriteTools: 'Your favorite tools'
|
||||||
allTools: 'All the tools'
|
allTools: 'All the tools'
|
||||||
|
favoritesDndToolTip: 'Drag and drop to reorder favorites'
|
||||||
subtitle: 'Handy tools for developers'
|
subtitle: 'Handy tools for developers'
|
||||||
toggleMenu: 'Toggle menu'
|
toggleMenu: 'Toggle menu'
|
||||||
home: Home
|
home: Home
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: Nuevas herramientas
|
newestTools: Nuevas herramientas
|
||||||
favoriteTools: 'Tus herramientas favoritas'
|
favoriteTools: 'Tus herramientas favoritas'
|
||||||
allTools: 'Todas las herramientas'
|
allTools: 'Todas las herramientas'
|
||||||
|
favoritesDndToolTip: 'Arrastra y suelta para reordenar favoritos'
|
||||||
subtitle: 'Herramientas practicas para desarrolladores'
|
subtitle: 'Herramientas practicas para desarrolladores'
|
||||||
toggleMenu: 'Toggle menu'
|
toggleMenu: 'Toggle menu'
|
||||||
home: Home
|
home: Home
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: 'Les nouveaux outils'
|
newestTools: 'Les nouveaux outils'
|
||||||
favoriteTools: 'Vos outils favoris'
|
favoriteTools: 'Vos outils favoris'
|
||||||
allTools: 'Tous les outils'
|
allTools: 'Tous les outils'
|
||||||
|
favoritesDndToolTip: 'Faites glisser et déposez pour réordonner vos favoris'
|
||||||
subtitle: 'Outils pour les développeurs'
|
subtitle: 'Outils pour les développeurs'
|
||||||
toggleMenu: 'Menu'
|
toggleMenu: 'Menu'
|
||||||
home: Accueil
|
home: Accueil
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: Nyeste verktøy
|
newestTools: Nyeste verktøy
|
||||||
favoriteTools: 'Dine favoritt verktøy'
|
favoriteTools: 'Dine favoritt verktøy'
|
||||||
allTools: 'Alle verktøyene'
|
allTools: 'Alle verktøyene'
|
||||||
|
favoritesDndToolTip: 'Dra og slipp for å omordne favoritter'
|
||||||
subtitle: 'Nyttige verktøy for utviklere'
|
subtitle: 'Nyttige verktøy for utviklere'
|
||||||
toggleMenu: 'Vekslemenmy'
|
toggleMenu: 'Vekslemenmy'
|
||||||
home: Hjem
|
home: Hjem
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: 'Novas ferramentas'
|
newestTools: 'Novas ferramentas'
|
||||||
favoriteTools: 'Suas ferramentas favoritas'
|
favoriteTools: 'Suas ferramentas favoritas'
|
||||||
allTools: 'Todas as ferramentas'
|
allTools: 'Todas as ferramentas'
|
||||||
|
favoritesDndToolTip: 'Arraste e solte para reordenar favoritos'
|
||||||
subtitle: 'Ferraentas úteis para desenvolvedores'
|
subtitle: 'Ferraentas úteis para desenvolvedores'
|
||||||
toggleMenu: 'Menu'
|
toggleMenu: 'Menu'
|
||||||
home: 'Início'
|
home: 'Início'
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: Найновіші інструменти
|
newestTools: Найновіші інструменти
|
||||||
favoriteTools: 'Ваші улюблені інструменти'
|
favoriteTools: 'Ваші улюблені інструменти'
|
||||||
allTools: 'Усі інструменти'
|
allTools: 'Усі інструменти'
|
||||||
|
favoritesDndToolTip: 'Перетягніть і відпустіть, щоб змінити порядок улюблених'
|
||||||
subtitle: 'Зручні інструменти для розробників'
|
subtitle: 'Зручні інструменти для розробників'
|
||||||
toggleMenu: 'Перемикання меню'
|
toggleMenu: 'Перемикання меню'
|
||||||
home: Головна
|
home: Головна
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: Công cụ mới nhất
|
newestTools: Công cụ mới nhất
|
||||||
favoriteTools: 'Công cụ yêu thích của bạn'
|
favoriteTools: 'Công cụ yêu thích của bạn'
|
||||||
allTools: 'Tất cả công cụ'
|
allTools: 'Tất cả công cụ'
|
||||||
|
favoritesDndToolTip: 'Kéo thả để sắp xếp lại yêu thích'
|
||||||
subtitle: 'Công cụ cho nhà phát triển.'
|
subtitle: 'Công cụ cho nhà phát triển.'
|
||||||
toggleMenu: 'Chuyển đổi menu'
|
toggleMenu: 'Chuyển đổi menu'
|
||||||
home: Trang chủ
|
home: Trang chủ
|
||||||
|
|
|
@ -3,6 +3,7 @@ home:
|
||||||
newestTools: '最新工具'
|
newestTools: '最新工具'
|
||||||
favoriteTools: '我的收藏'
|
favoriteTools: '我的收藏'
|
||||||
allTools: '全部工具'
|
allTools: '全部工具'
|
||||||
|
favoritesDndToolTip: '拖放重新排列收藏夹'
|
||||||
subtitle: '助力开发人员和 IT 工作者'
|
subtitle: '助力开发人员和 IT 工作者'
|
||||||
toggleMenu: '切换菜单'
|
toggleMenu: '切换菜单'
|
||||||
home: '主页'
|
home: '主页'
|
||||||
|
|
|
@ -99,6 +99,7 @@
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue-shadow-dom": "^4.2.0",
|
"vue-shadow-dom": "^4.2.0",
|
||||||
"vue-tsc": "^1.8.1",
|
"vue-tsc": "^1.8.1",
|
||||||
|
"vuedraggable": "^4.1.0",
|
||||||
"xml-formatter": "^3.3.2",
|
"xml-formatter": "^3.3.2",
|
||||||
"xml-js": "^1.6.11",
|
"xml-js": "^1.6.11",
|
||||||
"yaml": "^2.2.1"
|
"yaml": "^2.2.1"
|
||||||
|
|
14
pnpm-lock.yaml
generated
14
pnpm-lock.yaml
generated
|
@ -194,6 +194,9 @@ dependencies:
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^1.8.1
|
specifier: ^1.8.1
|
||||||
version: 1.8.1(typescript@5.2.2)
|
version: 1.8.1(typescript@5.2.2)
|
||||||
|
vuedraggable:
|
||||||
|
specifier: ^4.1.0
|
||||||
|
version: 4.1.0(vue@3.3.4)
|
||||||
xml-formatter:
|
xml-formatter:
|
||||||
specifier: ^3.3.2
|
specifier: ^3.3.2
|
||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
|
@ -8231,6 +8234,9 @@ packages:
|
||||||
tslib: 2.5.0
|
tslib: 2.5.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/sortablejs@1.14.0:
|
||||||
|
resolution: {integrity: sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==}
|
||||||
|
|
||||||
/source-map-js@1.0.2:
|
/source-map-js@1.0.2:
|
||||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
@ -9356,6 +9362,14 @@ packages:
|
||||||
'@vue/server-renderer': 3.3.4(vue@3.3.4)
|
'@vue/server-renderer': 3.3.4(vue@3.3.4)
|
||||||
'@vue/shared': 3.3.4
|
'@vue/shared': 3.3.4
|
||||||
|
|
||||||
|
/vuedraggable@4.1.0(vue@3.3.4):
|
||||||
|
resolution: {integrity: sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.1
|
||||||
|
dependencies:
|
||||||
|
sortablejs: 1.14.0
|
||||||
|
vue: 3.3.4
|
||||||
|
|
||||||
/vueuc@0.4.51(vue@3.3.4):
|
/vueuc@0.4.51(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-pLiMChM4f+W8czlIClGvGBYo656lc2Y0/mXFSCydcSmnCR1izlKPGMgiYBGjbY9FDkFG8a2HEVz7t0DNzBWbDw==}
|
resolution: {integrity: sha512-pLiMChM4f+W8czlIClGvGBYo656lc2Y0/mXFSCydcSmnCR1izlKPGMgiYBGjbY9FDkFG8a2HEVz7t0DNzBWbDw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { IconHeart } from '@tabler/icons-vue';
|
import { IconDragDrop, IconHeart } from '@tabler/icons-vue';
|
||||||
import { useHead } from '@vueuse/head';
|
import { useHead } from '@vueuse/head';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import Draggable from 'vuedraggable';
|
||||||
import ColoredCard from '../components/ColoredCard.vue';
|
import ColoredCard from '../components/ColoredCard.vue';
|
||||||
import ToolCard from '../components/ToolCard.vue';
|
import ToolCard from '../components/ToolCard.vue';
|
||||||
import { useToolStore } from '@/tools/tools.store';
|
import { useToolStore } from '@/tools/tools.store';
|
||||||
|
@ -10,6 +12,13 @@ const toolStore = useToolStore();
|
||||||
|
|
||||||
useHead({ title: 'IT Tools - Handy online tools for developers' });
|
useHead({ title: 'IT Tools - Handy online tools for developers' });
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const favoriteTools = computed(() => toolStore.favoriteTools);
|
||||||
|
|
||||||
|
// Update favorite tools order when drag is finished
|
||||||
|
function onUpdateFavoriteTools() {
|
||||||
|
toolStore.updateFavoriteTools(favoriteTools.value); // Update the store with the new order
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -66,10 +75,21 @@ const { t } = useI18n();
|
||||||
<div v-if="toolStore.favoriteTools.length > 0">
|
<div v-if="toolStore.favoriteTools.length > 0">
|
||||||
<h3 class="mb-5px mt-25px font-500 text-neutral-400">
|
<h3 class="mb-5px mt-25px font-500 text-neutral-400">
|
||||||
{{ $t('home.categories.favoriteTools') }}
|
{{ $t('home.categories.favoriteTools') }}
|
||||||
|
<c-tooltip :tooltip="$t('home.categories.favoritesDndToolTip')">
|
||||||
|
<n-icon :component="IconDragDrop" size="18" />
|
||||||
|
</c-tooltip>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="grid grid-cols-1 gap-12px lg:grid-cols-3 md:grid-cols-3 sm:grid-cols-2 xl:grid-cols-4">
|
<Draggable
|
||||||
<ToolCard v-for="tool in toolStore.favoriteTools" :key="tool.name" :tool="tool" />
|
:list="favoriteTools"
|
||||||
</div>
|
class="grid grid-cols-1 gap-12px lg:grid-cols-3 md:grid-cols-3 sm:grid-cols-2 xl:grid-cols-4"
|
||||||
|
ghost-class="ghost-favorites-draggable"
|
||||||
|
item-key="name"
|
||||||
|
@end="onUpdateFavoriteTools"
|
||||||
|
>
|
||||||
|
<template #item="{ element: tool }">
|
||||||
|
<ToolCard :tool="tool" />
|
||||||
|
</template>
|
||||||
|
</Draggable>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
@ -107,4 +127,24 @@ const { t } = useI18n();
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ghost-favorites-draggable {
|
||||||
|
opacity: 0.4;
|
||||||
|
background-color: #ccc;
|
||||||
|
border: 2px dashed #666;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||||
|
transform: scale(1.1);
|
||||||
|
animation: ghost-favorites-draggable-animation 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes ghost-favorites-draggable-animation {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.4;
|
||||||
|
transform: scale(1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -59,5 +59,9 @@ export const useToolStore = defineStore('tools', () => {
|
||||||
return favoriteToolsName.value.includes(get(tool).name)
|
return favoriteToolsName.value.includes(get(tool).name)
|
||||||
|| favoriteToolsName.value.includes(get(tool).path);
|
|| favoriteToolsName.value.includes(get(tool).path);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateFavoriteTools(newOrder: ToolWithCategory[]) {
|
||||||
|
favoriteToolsName.value = newOrder.map(tool => tool.path);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue