feat: improve TaskCard and TagList components, enhance task loading logic
- Updated TaskCard to conditionally render footer elements based on available data (due date, source, completion status). - Enhanced TagList to visually indicate deleting tags and improved button styles for better UX. - Modified useTasks hook to refresh tasks only if no initial data is present, optimizing loading behavior. - Updated TagsPageClient to manage local tags and handle optimistic UI updates during tag deletion.
This commit is contained in:
@@ -4,7 +4,7 @@ import { HomePageClient } from '@/components/HomePageClient';
|
||||
export default async function HomePage() {
|
||||
// SSR - Récupération des données côté serveur
|
||||
const [initialTasks, initialStats] = await Promise.all([
|
||||
tasksService.getTasks({ limit: 20 }),
|
||||
tasksService.getTasks(),
|
||||
tasksService.getTaskStats()
|
||||
]);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Tag } from '@/lib/types';
|
||||
import { useTags } from '@/hooks/useTags';
|
||||
import { CreateTagData, UpdateTagData } from '@/clients/tags-client';
|
||||
@@ -32,11 +33,20 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
const [editingTag, setEditingTag] = useState<Tag | null>(null);
|
||||
const [showPopular, setShowPopular] = useState(false);
|
||||
const [deletingTagId, setDeletingTagId] = useState<string | null>(null);
|
||||
const [localTags, setLocalTags] = useState<Tag[]>(initialTags);
|
||||
|
||||
// Utiliser les tags initiaux si pas encore chargés
|
||||
const displayTags = tags.length > 0 ? tags : initialTags;
|
||||
// Utiliser les tags du hook s'ils sont chargés, sinon les tags locaux
|
||||
const displayTags = tags.length > 0 ? tags : localTags;
|
||||
const filteredTags = searchQuery ? searchResults : displayTags;
|
||||
|
||||
// Synchroniser les tags locaux avec les tags du hook une seule fois
|
||||
React.useEffect(() => {
|
||||
if (tags.length > 0 && localTags === initialTags) {
|
||||
setLocalTags(tags);
|
||||
}
|
||||
}, [tags, localTags, initialTags]);
|
||||
|
||||
const handleSearch = async (query: string) => {
|
||||
setSearchQuery(query);
|
||||
if (query.trim()) {
|
||||
@@ -67,13 +77,22 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
};
|
||||
|
||||
const handleDeleteTag = async (tag: Tag) => {
|
||||
if (confirm(`Êtes-vous sûr de vouloir supprimer le tag "${tag.name}" ?`)) {
|
||||
try {
|
||||
await deleteTag(tag.id);
|
||||
} catch (error) {
|
||||
// L'erreur est déjà gérée dans le hook
|
||||
console.error('Erreur lors de la suppression:', error);
|
||||
}
|
||||
// Suppression optimiste : retirer immédiatement de l'affichage
|
||||
setDeletingTagId(tag.id);
|
||||
|
||||
// Mettre à jour les tags locaux pour suppression immédiate
|
||||
const updatedTags = displayTags.filter(t => t.id !== tag.id);
|
||||
setLocalTags(updatedTags);
|
||||
|
||||
try {
|
||||
await deleteTag(tag.id);
|
||||
// Succès : les tags seront mis à jour par le hook
|
||||
} catch (error) {
|
||||
// En cas d'erreur, restaurer le tag dans l'affichage
|
||||
setLocalTags(prev => [...prev, tag].sort((a, b) => a.name.localeCompare(b.name)));
|
||||
console.error('Erreur lors de la suppression:', error);
|
||||
} finally {
|
||||
setDeletingTagId(null);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,14 +141,14 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleShowPopular}
|
||||
disabled={loading}
|
||||
disabled={false}
|
||||
>
|
||||
{showPopular ? 'Tous les tags' : 'Tags populaires'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => setIsCreateModalOpen(true)}
|
||||
disabled={loading}
|
||||
disabled={false}
|
||||
>
|
||||
+ Nouveau tag
|
||||
</Button>
|
||||
@@ -194,7 +213,7 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loading && (
|
||||
{loading && displayTags.length === 0 && (
|
||||
<div className="text-center py-8">
|
||||
<div className="text-slate-400">Chargement...</div>
|
||||
</div>
|
||||
@@ -215,6 +234,7 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
onTagEdit={handleEditTag}
|
||||
onTagDelete={handleDeleteTag}
|
||||
showUsage={true}
|
||||
deletingTagId={deletingTagId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -225,7 +245,7 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
isOpen={isCreateModalOpen}
|
||||
onClose={() => setIsCreateModalOpen(false)}
|
||||
onSubmit={handleCreateTag}
|
||||
loading={loading}
|
||||
loading={false}
|
||||
/>
|
||||
|
||||
<TagForm
|
||||
@@ -233,7 +253,7 @@ export function TagsPageClient({ initialTags }: TagsPageClientProps) {
|
||||
onClose={() => setEditingTag(null)}
|
||||
onSubmit={handleUpdateTag}
|
||||
tag={editingTag}
|
||||
loading={loading}
|
||||
loading={false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user