From 75d4ace76569a20bf34bb20534d284f4df46661d Mon Sep 17 00:00:00 2001 From: alma Date: Mon, 12 Jan 2026 15:27:08 +0100 Subject: [PATCH] Mission Tab Refactor Big --- app/mission-tab/[missionId]/page.tsx | 137 ++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/app/mission-tab/[missionId]/page.tsx b/app/mission-tab/[missionId]/page.tsx index 3322891..a900bed 100644 --- a/app/mission-tab/[missionId]/page.tsx +++ b/app/mission-tab/[missionId]/page.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; -import { FileIcon, Calendar, Eye, MapPin, Users, Clock, ThumbsUp, Languages, ArrowLeft } from "lucide-react"; +import { FileIcon, Calendar, Eye, MapPin, Users, Clock, ThumbsUp, Languages, ArrowLeft, FileText } from "lucide-react"; import { useToast } from "@/components/ui/use-toast"; import { useParams, useRouter } from "next/navigation"; import Link from "next/link"; @@ -41,6 +41,10 @@ interface Mission { createdAt: string; creator: User; missionUsers: any[]; + rocketChatChannelId?: string | null; + outlineCollectionId?: string | null; + giteaRepositoryUrl?: string | null; + leantimeProjectId?: string | null; } export default function MissionTabDetailPage() { @@ -135,6 +139,23 @@ export default function MissionTabDetailPage() { }; }; + // Function to sanitize mission name (same logic as N8N) + const sanitizeMissionName = (name: string): string => { + if (!name || typeof name !== "string") return "unnamed-mission"; + return name.toLowerCase() + .split("") + .map(c => { + if (c >= "a" && c <= "z") return c; + if (c >= "0" && c <= "9") return c; + if (c === " " || c === "-") return c; + return ""; + }) + .join("") + .split(" ") + .filter(Boolean) + .join("-"); + }; + // Loading state if (loading) { return ( @@ -361,6 +382,120 @@ export default function MissionTabDetailPage() { )} + + {/* Ressources Métiers */} + {(mission.rocketChatChannelId || mission.outlineCollectionId || mission.giteaRepositoryUrl || mission.leantimeProjectId) && ( +
+

Ressources Métiers

+
+ {mission.rocketChatChannelId && (() => { + // Build RocketChat URL: parole.slm-lab.net/channel/[channelId] + // If it's already a full URL, use it; otherwise build from ID + const rocketChatUrl = mission.rocketChatChannelId.startsWith('http') + ? mission.rocketChatChannelId + : `https://parole.slm-lab.net/channel/${mission.rocketChatChannelId}`; + + return ( + +
+ +
+
+

Tenant de Parole

+

Espace de discussion

+
+
+ ); + })()} + + {mission.outlineCollectionId && (() => { + // Build Outline URL: chapitre.slm-lab.net/collection/[collectionId] + // If it's already a full URL, use it; otherwise build from ID + const outlineUrl = mission.outlineCollectionId.startsWith('http') + ? mission.outlineCollectionId + : `https://chapitre.slm-lab.net/collection/${mission.outlineCollectionId}`; + + return ( + +
+ +
+
+

Tenant du Chapitre

+

Espace de documentation

+
+
+ ); + })()} + + {mission.giteaRepositoryUrl && (() => { + // Use mission name (sanitized) as repo name + const repoName = sanitizeMissionName(mission.name); + + // Get Gitea owner from environment variable (default: "alma") + // Note: In Next.js client components, we need NEXT_PUBLIC_ prefix + const giteaOwner = typeof window !== 'undefined' + ? (process.env.NEXT_PUBLIC_GITEA_OWNER || 'alma') + : 'alma'; + + // Build the correct Gitea URL: gite.slm-lab.net/owner/repo-name + const giteaUrl = `https://gite.slm-lab.net/${giteaOwner}/${repoName}`; + + return ( + +
+ +
+
+

Tenant du Code

+

Espace pour les codes sources

+
+
+ ); + })()} + + {mission.leantimeProjectId && (() => { + // Build Leantime URL: agilite.slm-lab.net/projects/showProject/[projectId] + // If it's already a full URL, use it; otherwise build from ID + const leantimeUrl = mission.leantimeProjectId.startsWith('http') + ? mission.leantimeProjectId + : `https://agilite.slm-lab.net/projects/showProject/${mission.leantimeProjectId}`; + + return ( + +
+ +
+
+

Tenant des Devoirs

+

Espace d'organisation

+
+
+ ); + })()} +
+
+ )}