feat: add linked item management to action updates in SWOT analysis
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 5s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 5s
This commit is contained in:
@@ -183,6 +183,7 @@ export async function updateAction(
|
|||||||
description?: string;
|
description?: string;
|
||||||
priority?: number;
|
priority?: number;
|
||||||
status?: string;
|
status?: string;
|
||||||
|
linkedItemIds?: string[];
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export function ActionPanel({
|
|||||||
const [title, setTitle] = useState('');
|
const [title, setTitle] = useState('');
|
||||||
const [description, setDescription] = useState('');
|
const [description, setDescription] = useState('');
|
||||||
const [priority, setPriority] = useState(1);
|
const [priority, setPriority] = useState(1);
|
||||||
|
const [editingSelectedItems, setEditingSelectedItems] = useState<string[]>([]);
|
||||||
|
|
||||||
function openCreateModal() {
|
function openCreateModal() {
|
||||||
if (selectedItems.length < 2) {
|
if (selectedItems.length < 2) {
|
||||||
@@ -75,6 +76,7 @@ export function ActionPanel({
|
|||||||
setTitle('');
|
setTitle('');
|
||||||
setDescription('');
|
setDescription('');
|
||||||
setPriority(1);
|
setPriority(1);
|
||||||
|
setEditingSelectedItems([]);
|
||||||
setEditingAction(null);
|
setEditingAction(null);
|
||||||
setShowModal(true);
|
setShowModal(true);
|
||||||
}
|
}
|
||||||
@@ -83,6 +85,7 @@ export function ActionPanel({
|
|||||||
setTitle(action.title);
|
setTitle(action.title);
|
||||||
setDescription(action.description || '');
|
setDescription(action.description || '');
|
||||||
setPriority(action.priority);
|
setPriority(action.priority);
|
||||||
|
setEditingSelectedItems(action.links.map((link) => link.swotItemId));
|
||||||
setEditingAction(action);
|
setEditingAction(action);
|
||||||
setShowModal(true);
|
setShowModal(true);
|
||||||
}
|
}
|
||||||
@@ -90,9 +93,16 @@ export function ActionPanel({
|
|||||||
function closeModal() {
|
function closeModal() {
|
||||||
setShowModal(false);
|
setShowModal(false);
|
||||||
setEditingAction(null);
|
setEditingAction(null);
|
||||||
|
setEditingSelectedItems([]);
|
||||||
onExitLinkMode();
|
onExitLinkMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleEditingItem(itemId: string) {
|
||||||
|
setEditingSelectedItems((prev) =>
|
||||||
|
prev.includes(itemId) ? prev.filter((id) => id !== itemId) : [...prev, itemId]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function handleSubmit(e: React.FormEvent) {
|
async function handleSubmit(e: React.FormEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
@@ -100,10 +110,15 @@ export function ActionPanel({
|
|||||||
|
|
||||||
startTransition(async () => {
|
startTransition(async () => {
|
||||||
if (editingAction) {
|
if (editingAction) {
|
||||||
|
if (editingSelectedItems.length < 2) {
|
||||||
|
alert('Une action doit être liée à au moins 2 items SWOT');
|
||||||
|
return;
|
||||||
|
}
|
||||||
await updateAction(editingAction.id, sessionId, {
|
await updateAction(editingAction.id, sessionId, {
|
||||||
title: title.trim(),
|
title: title.trim(),
|
||||||
description: description.trim() || undefined,
|
description: description.trim() || undefined,
|
||||||
priority,
|
priority,
|
||||||
|
linkedItemIds: editingSelectedItems,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await createAction(sessionId, {
|
await createAction(sessionId, {
|
||||||
@@ -302,6 +317,48 @@ export function ActionPanel({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{editingAction && (
|
||||||
|
<div className="mb-4">
|
||||||
|
<p className="mb-2 text-sm font-medium text-foreground">
|
||||||
|
Items liés ({editingSelectedItems.length}) :
|
||||||
|
</p>
|
||||||
|
<div className="max-h-48 space-y-2 overflow-y-auto rounded-lg border border-border bg-background p-3">
|
||||||
|
{allItems.map((item) => {
|
||||||
|
const isSelected = editingSelectedItems.includes(item.id);
|
||||||
|
return (
|
||||||
|
<label
|
||||||
|
key={item.id}
|
||||||
|
className={`
|
||||||
|
flex cursor-pointer items-center gap-2 rounded-lg border p-2 transition-colors
|
||||||
|
${
|
||||||
|
isSelected
|
||||||
|
? 'border-primary bg-primary/10'
|
||||||
|
: 'border-border bg-card hover:bg-card-hover'
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={isSelected}
|
||||||
|
onChange={() => toggleEditingItem(item.id)}
|
||||||
|
className="h-4 w-4 rounded border-border text-primary focus:ring-primary"
|
||||||
|
/>
|
||||||
|
<Badge variant={categoryBadgeVariant[item.category]} className="shrink-0">
|
||||||
|
{categoryShort[item.category]}
|
||||||
|
</Badge>
|
||||||
|
<span className="text-sm text-foreground">{item.content}</span>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{editingSelectedItems.length < 2 && (
|
||||||
|
<p className="mt-2 text-xs text-destructive">
|
||||||
|
Sélectionnez au moins 2 items SWOT
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<Input
|
||||||
label="Titre de l'action"
|
label="Titre de l'action"
|
||||||
|
|||||||
@@ -305,11 +305,39 @@ export async function updateAction(
|
|||||||
priority?: number;
|
priority?: number;
|
||||||
status?: string;
|
status?: string;
|
||||||
dueDate?: Date | null;
|
dueDate?: Date | null;
|
||||||
|
linkedItemIds?: string[];
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
const { linkedItemIds, ...updateData } = data;
|
||||||
|
|
||||||
|
// If linkedItemIds is provided, update the links
|
||||||
|
if (linkedItemIds !== undefined) {
|
||||||
|
// Delete all existing links
|
||||||
|
await prisma.actionLink.deleteMany({
|
||||||
|
where: { actionId },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create new links
|
||||||
|
if (linkedItemIds.length > 0) {
|
||||||
|
await prisma.actionLink.createMany({
|
||||||
|
data: linkedItemIds.map((swotItemId) => ({
|
||||||
|
actionId,
|
||||||
|
swotItemId,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return prisma.action.update({
|
return prisma.action.update({
|
||||||
where: { id: actionId },
|
where: { id: actionId },
|
||||||
data,
|
data: updateData,
|
||||||
|
include: {
|
||||||
|
links: {
|
||||||
|
include: {
|
||||||
|
swotItem: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user