From 9ce2b62bc67bfb3eca9f0050ad9479ddfdf5615a Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Thu, 27 Nov 2025 13:22:57 +0100 Subject: [PATCH] feat: add duplicate functionality for SWOT items, enhance ActionPanel layout, and update SwotCard with duplicate action --- dev.db | Bin 81920 -> 81920 bytes src/actions/swot.ts | 16 ++++ src/components/swot/ActionPanel.tsx | 109 +++++++++++++++------------- src/components/swot/SwotCard.tsx | 27 ++++++- src/services/sessions.ts | 25 +++++++ 5 files changed, 124 insertions(+), 53 deletions(-) diff --git a/dev.db b/dev.db index 580e910bd32c090b08715feaedb706436b1bfa4c..44e532a92bf0b6eb004fbd5967ef6328a558ea16 100644 GIT binary patch delta 1545 zcma)5OKcNI7~YAK?0WIe)FKw$rj8-Kw1uqq;q}^9)rBGm7ZU{{w_IraOk5|9iSw{G zi5g#8RpL=J2MaC;4j@h_GEy#86^Z5$Q7M;Hxgiy#Ld6LoA#ov{S;wKlChcWcyZ`+E z_kWLBT}Yz-QdL=&_1O!BiE*tknM@_7haTL`$CKHq2Y1g7ojGy3 zf9O;v9^4Xf&m2suYD5c4;ZX3fEJtKnl~uh@QTkM4NKqs26f3N-8>?K%5v%~kO3!2i zMn<=qu{s)9N9yBrZ4a!SB92)<0w;cC<(#TQ7Lin4#%Ja(u?)wV9xsRgn)?)s3x{!J zUhF0(6kU>op*jhfVVECG(H5mT=m%ow$+7hKcp6`vKOHn8nl7n^Qej<$Oa+jq=U?)b z)Dc2Sqm&XedQd4?lc~6sBCWDP_YX(`c^jrltAHVCjbf#Z<;V&g@nzQv?gb66%!`zi z5|nf$RC~VA+2$vodRQ_V40se}c(}}JMK54enSCNJ*PUW3 zzoFM*0z7Pqc;j;U3nE5OJsK_S66n!-wFPrmHRlIjeEZ6I-T`9_8ikuMMzBx8&%bx@ z<^jg(VH&~9s#6)FoJ^IQ%I9aT5v`Dlr>r=3-#EgBZPm2^Hs?LvjgPup71+j`-UHkx zbX0ZF2gDCamldb7lb4mve_NQG7@15Li*}MEdmKqbNDJY_ja$3}-PsnZ=0120QCU2# zwsBOWKEmelz1}WPC^6_BI*$bS3(Ucfgf*c=cnu4o0j}LNOL7b?|VC^mDDWuU-4GI^MmVM96ZLLb7&1+g@3~(bO@H=F*55j*kceo>er=Jz-R`- R+}>y2Yc;#P^d%So{{Rav)&l?l delta 729 zcmZo@U~On%ogmF9J5k1&QFdd(!hBf<1_o}fFb4i|zHfY`ydQaUcwX=%ao^*P;JVHg zwpmcXf@^YERXZcc5~O&4JPlYk(<1?hR?8(k&VM%T$U54COJ1VBQ?pS z!qC9Lz^pi*I z6PLX#1E=WZ2lG@XH_X$SY&%~Ti1{XG%%8)-#D5g*yv>3NJNc*k$^(sfv|dSojZcb! ze?5O3KQG@NzHB}zpiyjmZ2oL4_V)IZ1J6rtw%m7`QGku#7sYQtRhImlea~-E04ELn zKA$}EpX}r-|0*X7{+DHB1Cy*Ea`LkOKrbLW3#{_df1szOdmwX%f6@k)o`L=JgWAtYP0GQz31^@s6 diff --git a/src/actions/swot.ts b/src/actions/swot.ts index a075cbf..997348d 100644 --- a/src/actions/swot.ts +++ b/src/actions/swot.ts @@ -64,6 +64,22 @@ export async function deleteSwotItem(itemId: string, sessionId: string) { } } +export async function duplicateSwotItem(itemId: string, sessionId: string) { + const session = await auth(); + if (!session?.user?.id) { + return { success: false, error: 'Non autorisé' }; + } + + try { + const item = await sessionsService.duplicateSwotItem(itemId); + revalidatePath(`/sessions/${sessionId}`); + return { success: true, data: item }; + } catch (error) { + console.error('Error duplicating SWOT item:', error); + return { success: false, error: 'Erreur lors de la duplication' }; + } +} + export async function moveSwotItem( itemId: string, sessionId: string, diff --git a/src/components/swot/ActionPanel.tsx b/src/components/swot/ActionPanel.tsx index 95d7e55..417abc9 100644 --- a/src/components/swot/ActionPanel.tsx +++ b/src/components/swot/ActionPanel.tsx @@ -172,64 +172,24 @@ export function ActionPanel({ Créez des actions en sélectionnant plusieurs items SWOT.

) : ( -
+
{actions.map((action) => (
onActionHover(action.links.map((l) => l.swotItemId))} onMouseLeave={onActionLeave} > -
-
-
-

{action.title}

- - {priorityLabels[action.priority]} - -
- {action.description && ( -

{action.description}

- )} -
- {action.links.map((link) => ( - - {categoryShort[link.swotItem.category]} - - ))} -
-
- -
- - + {/* Header with title & actions */} +
+

{action.title}

+
-
+ + {/* Description */} + {action.description && ( +

{action.description}

+ )} + + {/* Linked Items */} +
+ {action.links.map((link) => ( + + + {link.swotItem.content.length > 25 + ? link.swotItem.content.slice(0, 25) + '...' + : link.swotItem.content} + + + ))} +
+ + {/* Footer with status & priority */} +
+ + {priorityLabels[action.priority]} + + +
))}
diff --git a/src/components/swot/SwotCard.tsx b/src/components/swot/SwotCard.tsx index 29f60fa..7f1e1dc 100644 --- a/src/components/swot/SwotCard.tsx +++ b/src/components/swot/SwotCard.tsx @@ -2,7 +2,7 @@ import { forwardRef, useState, useTransition } from 'react'; import type { SwotItem, SwotCategory } from '@prisma/client'; -import { updateSwotItem, deleteSwotItem } from '@/actions/swot'; +import { updateSwotItem, deleteSwotItem, duplicateSwotItem } from '@/actions/swot'; interface SwotCardProps { item: SwotItem; @@ -58,6 +58,12 @@ export const SwotCard = forwardRef( }); } + async function handleDuplicate() { + startTransition(async () => { + await duplicateSwotItem(item.id, sessionId); + }); + } + function handleKeyDown(e: React.KeyboardEvent) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); @@ -105,7 +111,7 @@ export const SwotCard = forwardRef( {/* Actions (visible on hover) */} {!linkMode && ( -
+
+