Add edit functionality for EinAb interactions: implement UpdateInteraction method, extend InteractionDialog for edit mode, and add edit button in InteractionRow

This commit is contained in:
troogs
2026-09-14 16:09:13 +02:00
parent fdd7ea5a40
commit 8b298b37c7
11 changed files with 360 additions and 24 deletions
@@ -0,0 +1,155 @@
---
name: EinAb Interaction Edit
overview: Add edit mode for EinAb (Einführung) interactions by extending the existing InteractionDialog with an update path, a new ProspectService.UpdateInteraction method, and an edit button in InteractionRow — scoped to EinAb initially but designed for future interaction types.
todos:
- id: service-update
content: Add ProspectService.UpdateInteraction + AuditType.EditInteraction + AuditHelper case
status: completed
- id: dialog-edit-mode
content: Extend InteractionDialog with IsEditMode, IsEditable helper, and unified SaveAsync
status: completed
- id: row-edit-button
content: Add AllowEdit/EditClick to InteractionRow with pencil icon in item list
status: completed
- id: container-wire
content: Add EditInteraction handler in ProspectContainer and enable AllowEdit on EinAb row
status: completed
isProject: false
---
# EinAb Interaction Edit Mode
## Current State
EinAb interactions ("Einführung") are multi-entry (minimum 3) and support date, business/person fields (`Info1`/`Info2`), and feedback (thumbs up/down/neutral). Users can **add** via [`InteractionDialog`](FoodsharingSiegen.Server/Dialogs/InteractionDialog.razor) and **remove** via the X icon in [`InteractionRow`](FoodsharingSiegen.Server/Controls/InteractionRow.razor). There is no update path at any layer.
```mermaid
flowchart LR
subgraph current [Current Flow]
AddBtn["+ Button"] --> Dialog["InteractionDialog"]
Dialog --> AddSvc["ProspectService.AddInteraction"]
XBtn["X Button"] --> Confirm["ConfirmDialog"]
Confirm --> RemoveSvc["ProspectService.RemoveInteraction"]
end
```
## Target Flow
```mermaid
flowchart LR
subgraph target [New Edit Flow]
EditBtn["Pencil Button"] --> EditDialog["InteractionDialog (edit mode)"]
EditDialog --> UpdateSvc["ProspectService.UpdateInteraction"]
end
AddBtn["+ Button"] --> AddDialog["InteractionDialog (add mode)"]
AddDialog --> AddSvc["ProspectService.AddInteraction"]
XBtn["X Button"] --> RemoveSvc["ProspectService.RemoveInteraction"]
```
Edit and remove will coexist. Only EinAb gets the edit button initially.
---
## 1. Service Layer — `UpdateInteraction`
**File:** [`FoodsharingSiegen.Server/Data/Service/ProspectService.cs`](FoodsharingSiegen.Server/Data/Service/ProspectService.cs)
Add `UpdateInteraction(Interaction interaction)` following the existing `UpdateAsync(Prospect)` pattern:
- Load tracked entity by `interaction.Id`; return error if not found
- Update editable fields only: `Date`, `Info1`, `Info2`, `Feedback`, `FeedbackInfo`, `Alert`
- Do **not** change: `Id`, `Created`, `UserID` (preserves original creator), `Type`, `ProspectID`, `NotNeeded`
- Set parent `Prospect.Modified = DateTime.UtcNow`
- Audit via new `AuditType.EditInteraction` (prospect name + interaction type as data)
- Detach entities after save (consistent with `AddInteraction`)
---
## 2. Audit Support
**Files:**
- [`FoodsharingSiegen.Contracts/Enums/AuditType.cs`](FoodsharingSiegen.Contracts/Enums/AuditType.cs) — add `EditInteraction = 160`
- [`FoodsharingSiegen.Server/Data/AuditHelper.cs`](FoodsharingSiegen.Server/Data/AuditHelper.cs) — add case: `"hat eine Interaktion bei {Data1} bearbeitet: {Data2}"`
---
## 3. InteractionDialog — Add/Edit Mode
**Files:** [`InteractionDialog.razor.cs`](FoodsharingSiegen.Server/Dialogs/InteractionDialog.razor.cs), [`InteractionDialog.razor`](FoodsharingSiegen.Server/Dialogs/InteractionDialog.razor)
Follow the [`EditProspectDialog`](FoodsharingSiegen.Server/Dialogs/EditProspectDialog.razor.cs) pattern (`IsUpdateMode` + conditional save):
- Add `IsEditMode` parameter and a static extensibility helper:
```csharp
public static bool IsEditable(InteractionType type) => type switch
{
InteractionType.EinAb => true,
_ => false
};
```
- Extend `InteractionDialogParameter` with optional `Interaction? ExistingInteraction = null`
- In `ShowAsync`: when `ExistingInteraction` is provided, pass it as the bound `Interaction` and set `IsEditMode = true`; otherwise keep current "new interaction" behavior
- Replace `AddInteractionAsync` with a unified `SaveAsync`:
- **Add mode:** `Interaction.UserID = CurrentUser.Id``ProspectService.AddInteraction`
- **Edit mode:** `ProspectService.UpdateInteraction`
- In the razor template, change OK button label: `"OK"` (add) / `"Speichern"` (edit) — same fields render in both modes (date, Betrieb, Mit wem, feedback)
**Header text** (in `ProspectContainer`): `"Einführung für {Name} bearbeiten"` for edit vs existing `"… eintragen"` for add.
---
## 4. InteractionRow — Edit Button
**Files:** [`InteractionRow.razor`](FoodsharingSiegen.Server/Controls/InteractionRow.razor), [`InteractionRow.razor.cs`](FoodsharingSiegen.Server/Controls/InteractionRow.razor.cs)
- Add parameters:
- `bool AllowEdit { get; set; }` — controls visibility
- `Func<Guid, Task>? EditClick { get; set; }` — callback with interaction Id
- In the per-item loop (lines 4666), show a pencil icon (`fa-solid fa-pen-to-square`) next to the existing X remove icon when `AllowEdit && AllowInteraction`
- Same visibility guard as remove: hidden when prospect is complete (unless Complete-type interaction)
---
## 5. ProspectContainer — Wire Up Edit
**Files:** [`ProspectContainer.razor`](FoodsharingSiegen.Server/Controls/ProspectContainer.razor), [`ProspectContainer.razor.cs`](FoodsharingSiegen.Server/Controls/ProspectContainer.razor.cs)
- Add `EditInteraction(Guid interactionId)`:
- Look up interaction from `Prospect.Interactions`
- Guard: only proceed if `InteractionDialog.IsEditable(interaction.Type)`
- Open dialog with existing interaction and header `"Einführung für {Name} bearbeiten"`
- On success → `OnDataChanged()`
- On the EinAb `InteractionRow`, add:
- `AllowEdit="true"`
- `EditClick="@EditInteraction"`
Other interaction rows remain unchanged (no edit button).
---
## Extensibility Notes
To enable edit for another type later:
1. Add the type to `InteractionDialog.IsEditable()`
2. Set `AllowEdit="true"` on that row in `ProspectContainer.razor`
3. Ensure field labels in `ShowAsync`'s type switch cover that type (already done for several types)
No separate edit dialog component is needed — the same form handles both modes.
---
## Files Changed (summary)
| File | Change |
|------|--------|
| `ProspectService.cs` | New `UpdateInteraction` method |
| `AuditType.cs` | New `EditInteraction` enum value |
| `AuditHelper.cs` | New audit text case |
| `InteractionDialog.razor.cs` | Edit mode, `IsEditable`, unified save |
| `InteractionDialog.razor` | Conditional button label |
| `InteractionRow.razor` / `.cs` | Edit button + parameters |
| `ProspectContainer.razor` / `.cs` | `EditInteraction` handler, EinAb wiring |
No database migration required — all editable fields already exist on the `Interaction` entity.