diff --git a/apps/main/src/components/TabloFilesSection.tsx b/apps/main/src/components/TabloFilesSection.tsx
index 476c8e1..82aba48 100644
--- a/apps/main/src/components/TabloFilesSection.tsx
+++ b/apps/main/src/components/TabloFilesSection.tsx
@@ -10,6 +10,7 @@ import {
useTabloFileNames,
} from "../hooks/tablo_data";
import { useIsReadOnlyUser } from "../providers/UserStoreProvider";
+import { TypographyH3, TypographyMuted } from "@xtablo/ui/components/typography";
interface TabloFilesSectionProps {
tablo: UserTablo;
@@ -154,8 +155,10 @@ export const TabloFilesSection = ({ tablo, isAdmin }: TabloFilesSectionProps) =>
return (
-
Fichiers
-
Gérez les fichiers attachés à ce tablo
+
Fichiers
+
+ Gérez les fichiers attachés à ce tablo
+
{/* Error Banner */}
diff --git a/apps/main/src/components/TabloOverviewSection.tsx b/apps/main/src/components/TabloOverviewSection.tsx
index e16069b..33ad86c 100644
--- a/apps/main/src/components/TabloOverviewSection.tsx
+++ b/apps/main/src/components/TabloOverviewSection.tsx
@@ -1,38 +1,29 @@
import { useCallback, useMemo, useState } from "react";
import { Button } from "@xtablo/ui/components/button";
import { Input } from "@xtablo/ui/components/input";
-import {
- ArrowDown,
- ArrowUp,
- Check,
- Edit2,
- Loader2,
- Plus,
- Trash2,
- X,
-} from "lucide-react";
+import { Progress } from "@xtablo/ui/components/progress";
+import { ArrowDown, ArrowUp, Check, Edit2, Loader2, Trash2, X } from "lucide-react";
import type { UserTablo } from "@xtablo/shared/types/tablos.types";
-import { TabloFilesSection } from "./TabloFilesSection";
import {
useCreateEtape,
useDeleteEtape,
useReorderEtapes,
useTabloEtapes,
+ useTasksByTablo,
useUpdateEtape,
} from "../hooks/tasks";
-import { useTablo } from "../hooks/tablos";
-import { useUser } from "../providers/UserStoreProvider";
-
+import { TypographyH3, TypographyMuted, TypographyP } from "@xtablo/ui/components/typography";
+import { useTranslation } from "react-i18next";
+import { pluralize, toast } from "@xtablo/shared";
interface TabloOverviewSectionProps {
tablo: UserTablo;
isAdmin: boolean;
}
export const TabloOverviewSection = ({ tablo, isAdmin }: TabloOverviewSectionProps) => {
- const { data: detailedTablo } = useTablo(tablo.id);
- const { id: currentUserId } = useUser();
-
+ const { t } = useTranslation();
const { data: etapes = [], isLoading: isLoadingEtapes } = useTabloEtapes(tablo.id);
+ const { data: tasks = [] } = useTasksByTablo(tablo.id);
const createEtape = useCreateEtape();
const updateEtape = useUpdateEtape();
const deleteEtape = useDeleteEtape();
@@ -42,17 +33,42 @@ export const TabloOverviewSection = ({ tablo, isAdmin }: TabloOverviewSectionPro
const [editingEtapeId, setEditingEtapeId] = useState
(null);
const [editingTitle, setEditingTitle] = useState("");
- const isOwner = detailedTablo?.owner_id === currentUserId;
- const canManageEtapes = isOwner;
+ const canManageEtapes = isAdmin;
- const sortedEtapes = useMemo(
- () => [...etapes].sort((a, b) => a.position - b.position),
- [etapes]
+ const sortedEtapes = useMemo(() => [...etapes].sort((a, b) => a.position - b.position), [etapes]);
+
+ // Calculate overall tablo progress
+ const overallProgress = useMemo(() => {
+ const totalTasks = tasks.length;
+ const doneTasks = tasks.filter((task) => task.status === "done").length;
+ const percentage = totalTasks > 0 ? Math.round((doneTasks / totalTasks) * 100) : 0;
+ return { total: totalTasks, done: doneTasks, percentage };
+ }, [tasks]);
+
+ // Calculate task counts per etape
+ const getEtapeTaskCounts = useCallback(
+ (etapeId: string) => {
+ const etapeTasks = tasks.filter((task) => task.parent_task_id === etapeId);
+ const total = etapeTasks.length;
+ const done = etapeTasks.filter((task) => task.status === "done").length;
+ const ongoing = etapeTasks.filter(
+ (task) => task.status === "in_progress" || task.status === "in_review"
+ ).length;
+ return { total, done, ongoing };
+ },
+ [tasks]
);
const handleCreateEtape = async () => {
const title = newEtapeTitle.trim();
- if (!title) return;
+ if (!title) {
+ toast.add({
+ title: "Erreur",
+ description: "Le nom de l'Étape est requis",
+ type: "error",
+ });
+ return;
+ }
await createEtape.mutateAsync({
tabloId: tablo.id,
@@ -126,17 +142,17 @@ export const TabloOverviewSection = ({ tablo, isAdmin }: TabloOverviewSectionPro
if (!sortedEtapes.length) {
return (
-
+
Aucune Étape n'a encore été définie pour ce tablo.
-
+
{canManageEtapes ? (
-
+
Créez votre première Étape pour structurer les tâches du tablo.
-
+
) : (
-
+
Seul le propriétaire du tablo peut ajouter des Étapes.
-
+
)}
);
@@ -207,10 +223,34 @@ export const TabloOverviewSection = ({ tablo, isAdmin }: TabloOverviewSectionPro
) : (
<>
-