Files
fs-onboarding/.cursor/plans/einab_interaction_edit_79be74e0.plan.md
T

156 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.