diff --git a/apps/main/src/pages/tablo-details.layout.test.tsx b/apps/main/src/pages/tablo-details.layout.test.tsx index 76bfe34..e591c75 100644 --- a/apps/main/src/pages/tablo-details.layout.test.tsx +++ b/apps/main/src/pages/tablo-details.layout.test.tsx @@ -1,4 +1,5 @@ import { screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi } from "vitest"; import { renderWithProviders } from "../utils/testHelpers"; import { TabloDetailsPage } from "./tablo-details"; @@ -195,4 +196,20 @@ describe("TabloDetailsPage overview layout", () => { expect(screen.getByRole("button", { name: "Modifier la mise en page" })).toBeInTheDocument(); }); + + it("uses the standard email invite UI in the share dialog", async () => { + const user = userEvent.setup(); + + renderWithProviders(, { + route: "/tablos/tablo-1", + path: "/tablos/:tabloId", + }); + + await user.click(screen.getByRole("button", { name: "Inviter" })); + + expect(screen.getByText("Inviter un utilisateur")).toBeInTheDocument(); + expect(screen.getByPlaceholderText("Email de l'utilisateur à inviter")).toBeInTheDocument(); + expect(screen.queryByText("Accès client")).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Envoyer le lien" })).not.toBeInTheDocument(); + }); }); diff --git a/apps/main/src/pages/tablo-details.tsx b/apps/main/src/pages/tablo-details.tsx index df06def..a9cd3e5 100644 --- a/apps/main/src/pages/tablo-details.tsx +++ b/apps/main/src/pages/tablo-details.tsx @@ -186,6 +186,9 @@ const TABS: { { id: "roadmap", label: "Roadmap", icon: MapIcon }, ]; +// Temporary rollback until the client portal invite flow is ready to be used again. +const USE_CLIENT_MAGIC_LINK_INVITES = false; + // ─── Page ───────────────────────────────────────────────────────────────────── export const TabloDetailsPage = () => { @@ -202,6 +205,7 @@ export const TabloDetailsPage = () => { ); const [showAllOverviewTasks, setShowAllOverviewTasks] = useState(false); const [isShareDialogOpen, setIsShareDialogOpen] = useState(false); + const [inviteEmail, setInviteEmail] = useState(""); const [clientInviteEmail, setClientInviteEmail] = useState(""); const [isLayoutEditMode, setIsLayoutEditMode] = useState(false); const [draggedOverviewBlock, setDraggedOverviewBlock] = useState<{ @@ -255,6 +259,13 @@ export const TabloDetailsPage = () => { (member) => !pendingInvites?.some((invite) => invite.invited_email === member.email) ); + const handleSendInvite = () => { + if (!tabloId || !inviteEmail.trim()) return; + + inviteUser({ email: inviteEmail, tablo_id: tabloId }); + setInviteEmail(""); + }; + const openTaskModal = (dueDate?: Date) => { setTaskModalInitialDueDate(dueDate ? new Date(dueDate) : undefined); setIsTaskModalOpen(true); @@ -1002,117 +1013,205 @@ export const TabloDetailsPage = () => { {/* Separator */}
- {/* Client Access Section */} -
-

Accès client

-

- Invitez des clients externes via un lien magique -

-
- - {/* Client Invite Input */} -
- setClientInviteEmail(e.target.value)} - placeholder="Email du client" - className="flex-1 min-h-[44px]" - /> - {isCreatingClientInvite ? ( -
-
+ {USE_CLIENT_MAGIC_LINK_INVITES ? ( + <> +
+

Accès client

+

+ Invitez des clients externes via un lien magique +

- ) : ( - - )} -
- {/* Pending Client Invites */} - {pendingClientInvites && pendingClientInvites.length > 0 && ( -
-

- Invitations client en attente ({pendingClientInvites.length}) -

-
- {pendingClientInvites.map((invite) => { - const daysUntilExpiry = Math.ceil( - (new Date(invite.expires_at).getTime() - Date.now()) / (1000 * 60 * 60 * 24) - ); - const isExpiringSoon = daysUntilExpiry < 5; - return ( -
-
- +
+
+
+ ) : ( + + )} +
+ + {pendingClientInvites && pendingClientInvites.length > 0 && ( +
+

+ Invitations client en attente ({pendingClientInvites.length}) +

+
+ {pendingClientInvites.map((invite) => { + const daysUntilExpiry = Math.ceil( + (new Date(invite.expires_at).getTime() - Date.now()) / + (1000 * 60 * 60 * 24) + ); + const isExpiringSoon = daysUntilExpiry < 5; + return ( +
- - -
-
- - {invite.invited_email} - - - {isExpiringSoon && "⚠ "} - Expire dans {daysUntilExpiry} jour{daysUntilExpiry !== 1 ? "s" : ""} - -
- {isExpiringSoon && ( - - Bientôt expiré - - )} - +
+ ); + })} +
+
+ )} + + ) : ( + <> +
+

Inviter un utilisateur

+

+ Utilisez le système d'invitation standard par email pour le moment +

+
+ +
+ setInviteEmail(e.target.value)} + placeholder="Email de l'utilisateur à inviter" + className="flex-1 min-h-[44px]" + /> + {isInvitingUser ? ( +
+
+
+ ) : ( + + )} +
+ + {pendingInvites && pendingInvites.length > 0 && ( +
+

+ Invitations en attente ({pendingInvites.length}) +

+
+ {pendingInvites.map((invite) => ( +
- - -
- ); - })} -
-
+
+ + + +
+
+ + {invite.invited_email} + + (En attente) +
+ +
+ ))} +
+
+ )} + )}