Meal Entry¶
Overview¶
The Meal Entry feature allows staff and carers to log food intake for care recipients, capturing the food item name, portion size, carbohydrates consumed, and carb level category. The primary purpose is bolus calculation support for diabetes management. Each entry can be later edited or deleted. A history view with client-side search provides an audit trail, and Excel export is available for reporting. CareRecipients themselves cannot edit or delete entries — only create them — preserving data accuracy.
Role Access¶
| Role | Create | View | Edit | Delete | Export |
|---|---|---|---|---|---|
| SuperAdmin | ✓ | All | ✓ | ✓ | ✓ |
| Administrator | ✓ | All | ✓ | ✓ | ✓ |
| Carer | ✓ | Linked CRs | ✓ | ✓ | ✓ |
| SupportWorker | ✓ | Linked CRs | ✓ | ✓ | ✓ |
| CareRecipient | ✓ (own) | Own | — | — | ✓ |
| HealthCareProvider | — | Linked CRs | — | — | — |
Backend¶
Controller: MealEntryController — /api/mealentry¶
| Method | Route | Auth | Description |
|---|---|---|---|
| POST | /api/mealentry/entries |
Authorized | Create a meal entry |
| GET | /api/mealentry/entries |
Authorized | List entries (role-scoped) |
| GET | /api/mealentry/entries/{id} |
Anonymous | Get a single entry |
| PUT | /api/mealentry/entries/{id} |
Authorized (non-CR) | Update an entry |
| DELETE | /api/mealentry/entries/{id} |
Authorized (non-CR) | Delete an entry |
| GET | /api/mealentry/export/weekly |
Anonymous | Weekly entries export with optional date range |
Business Logic¶
POST /api/mealentry/entries
- CareRecipient role: CareRecipientId is automatically set to self (from JWT id claim); the request's careRecipientId field is ignored.
- Other roles: CareRecipientId may be specified or null (entry attributed to the user themselves).
PUT / DELETE /api/mealentry/entries/{id}
- CareRecipient role: returns 403 Forbidden. Only Carer/SupportWorker/Admin roles may modify or delete entries.
GET /api/mealentry/entries
- CareRecipient: returns entries where CareRecipientId == self OR UserId == self.
- Other roles: accepts optional ?userId=N query param to filter by user.
GET /api/mealentry/export/weekly
- Returns entries optionally filtered by ?startDate and ?endDate query params.
Key DTOs¶
CreateMealEntryRequest
foodItem string Max 200 characters (required)
portionSize string Max 100 characters (required)
carbsConsumed decimal Min 0 (required)
carbLevel int Corresponds to CarbLevel enum
comments string? Optional free text
careRecipientId int? Omit for CareRecipient self-entry
UpdateMealEntryRequest
MealEntryDto (response)
id int
foodItem string
portionSize string
carbsConsumed decimal
carbLevel string Label from CarbLevel enum
comments string?
timestamp DateTime
userId int
userName string
careRecipientId int?
careRecipientName string?
lastUpdatedById int?
lastUpdatedByName string?
lastUpdatedAt DateTime?
Model: MealEntry¶
| Field | Type | Notes |
|---|---|---|
Id |
int | PK |
FoodItem |
string (200) | |
PortionSize |
string (100) | |
CarbsConsumed |
decimal (7,2) | |
CarbLevel |
CarbLevel enum | Low / Medium / High / VeryHigh |
Comments |
string? | |
Timestamp |
DateTime | Server creation time |
UserId |
int | FK → User (creator) |
CareRecipientId |
int? | FK → User |
LastUpdatedById |
int? | FK → User (last editor) |
LastUpdatedAt |
DateTime? |
MealEntryService¶
File: server/src/Vitara.Api/Services/MealEntryService.cs
Dependencies: ApplicationDbContext
Key methods:
- GetMealEntriesForCareRecipientAsync(userId) — returns entries where CareRecipientId == userId OR UserId == userId (covers both self-entry and staff-entered records for the same person).
- GetWeeklyMealEntriesAsync(startDate?, endDate?) — date-range filter with optional bounds.
- All reads include User, CareRecipient, and LastUpdatedBy navigation properties.
Frontend¶
Routes¶
| Path | Component | Notes |
|---|---|---|
/meal-entry/entry |
MealEntryComponent |
Create or edit a single entry |
/meal-entry/history |
MealEntryHistoryComponent |
View and manage all entries |
MealEntryComponent — /meal-entry/entry¶
File: client/src/app/features/meal-entry/components/meal-entry.component.ts
Modes:
- Create mode (default): form is empty; submission calls MealEntryService.createEntry(dto).
- Edit mode: activated when ?id=N query param is present. On init, loads the entry via MealEntryService.getEntry(id), pre-fills all fields, and submission calls MealEntryService.updateEntry(id, dto).
Form fields:
- foodItem — required text input (max 200).
- portionSize — required text input (max 100).
- carbsConsumed — required decimal input (≥ 0).
- carbLevel — required dropdown: Low / Medium / High / Very High.
- comments — optional textarea.
Offline fallback: MealEntryService.createEntry() enqueues to OfflineQueueService (type 'meal-entry') on network failure.
Navigation: On successful create, navigates to /meal-entry/history. On successful edit, navigates back with a success snackbar.
MealEntryHistoryComponent — /meal-entry/history¶
File: client/src/app/features/meal-entry/components/meal-entry-history.component.ts
On init: Calls MealEntryService.getEntries().
Table columns: Food Item | Portion Size | Carbs (g) | Carb Level | Comments | Last Updated | Actions
Client-side search: Filters across food item, portion size, comments, and user name fields.
Edit action: Navigates to /meal-entry/entry?id=N.
Delete action: Triggers DialogService.confirmDelete(), then calls MealEntryService.deleteEntry(id).
HealthCareProvider: Delete button is hidden; read-only view.
Excel export: MealEntryService.getExportReport() → GET /export/mealentry-report → downloads Bolus_History_Report_YYYY-MM-DD.xlsx blob.
Feature Service: MealEntryService¶
File: client/src/app/features/meal-entry/services/meal-entry.service.ts
| Method | HTTP | Endpoint | Notes |
|---|---|---|---|
createEntry(dto) |
POST | /mealentry/entries |
Offline fallback |
getEntries(userId?) |
GET | /mealentry/entries |
Optional userId filter |
getEntry(id) |
GET | /mealentry/entries/{id} |
For edit pre-fill |
updateEntry(id, dto) |
PUT | /mealentry/entries/{id} |
|
deleteEntry(id) |
DELETE | /mealentry/entries/{id} |
|
getExportReport() |
GET | /export/mealentry-report |
Returns Blob |
Data Validation Rules¶
| Field | Rule |
|---|---|
foodItem |
Required, max 200 characters |
portionSize |
Required, max 100 characters |
carbsConsumed |
Required, minimum 0 |
carbLevel |
Required, must be a valid enum value |
| CareRecipient edit/delete | 403 Forbidden at server; hidden in UI |
End-to-End Data Flow¶
Create Entry¶
Carer Angular API DB
| | | |
| Navigate /meal-entry/entry| | |
| Fill form: Fish, 200g, | | |
| 30g carbs, Medium | | |
| | | |
| Submit |-- POST /mealentry/entries -->| |
| | |-- INSERT MealEntry ->|
| |<-- MealEntryDto --------------| |
|<-- navigate /history | | |
Edit Entry¶
Carer Angular API DB
| | | |
| Click Edit on row | | |
|<-- navigate /entry?id=5 | | |
| |-- GET /mealentry/entries/5 -->| |
| |<-- MealEntryDto --------------| |
|<-- form pre-filled | | |
| Change portion to 250g | | |
| Submit |-- PUT /mealentry/entries/5 -->| |
| |<-- Updated MealEntryDto ------| |
|<-- snackbar + navigate | | |