> ## Documentation Index
> Fetch the complete documentation index at: https://docs.criar.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Engagement Module

> SKOLE-ENGG — Engagement Module

# SKOLE-ENGG — Engagement Module (Comments & Reactions)

**Module ID:** `SKOLE-ENGG` | **Version:** 1.0 | **Status:** Active\
**Products:** Parent App (comment + react) · Teacher App (implicitly via engagement endpoints)

***

## 1. Overview

| Field              | Value                                                                                                                                                                              |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Module Name**    | Engagement                                                                                                                                                                         |
| **Module Code**    | ENGG                                                                                                                                                                               |
| **Business Value** | Increases parent-school interaction quality. Parents can acknowledge, praise, or ask clarifying questions on activities, diary entries, and notices — all without leaving the app. |

### Scope In

* Comments on any entity (activity, diary, write\_to, noticeboard)
* Reactions (like, love) on any entity
* Reaction toggle (add if not exists, remove if already reacted)
* Comment listing per entity

### Scope Out

* Moderating/flagging comments
* Teacher commenting (API available but UI not yet built in teacher app)

***

## 2. Requirements

### Functional Requirements (FR)

*What the module must DO — actions, behaviors, and outcomes.*

* **SKOLE-ENGG-FR001:** The module shall allow parents to post comments on activities, diary entries, notices, and requests.
* **SKOLE-ENGG-FR002:** The module shall enable parents to list all comments associated with a specific entity.
* **SKOLE-ENGG-FR003:** The module shall allow parents to toggle reactions (like, love) on any supported entity.
* **SKOLE-ENGG-FR004:** The module shall behave as a toggle when a parent reacts with the same type again, removing the previous reaction.
* **SKOLE-ENGG-FR005:** The module shall show real-time reaction counts and the current user's reaction state per entity.

### Non-Functional Requirements (NFR)

*How well the module must do it — performance, security, and reliability.*

* **SKOLE-ENGG-NFR001:** The module shall perform secure data scoping by ensuring all engagement records are partitioned by `skole_id`.
* **SKOLE-ENGG-NFR002:** The module shall behave strictly by enforcing a unique constraint on the parent+entity+reaction type combination.
* **SKOLE-ENGG-NFR003:** The module shall ensure that engagement queries (comments/reactions) are performant even for high-activity entities.

### Constraints

*Rules and boundaries — tech choices and platform restrictions.*

* **C001:** We must implement a generic entity-linking schema (`entity_type` + `entity_id`) to allow the engagement module to support new modules without schema changes.
* **C002:** We must use a `@@unique` constraint on `[entity_type, entity_id, parent_id, staff_id]` to prevent duplicate engagement records.

***

## 3. Sub-modules / Backlog

| ID                 | Sub-module      | Priority | Status | Estimate | Linked FR   |
| ------------------ | --------------- | -------- | ------ | -------- | ----------- |
| `SKOLE-ENGG-SM001` | Comment system  | P1       | Done   | 2d       | FR001–FR002 |
| `SKOLE-ENGG-SM002` | Reaction system | P1       | Done   | 2d       | FR003–FR005 |

***

## 4. Logical Implementation

### Comment Flow

```text theme={null}
POST /parent-app/engagement/comment
  { entity_type, entity_id, content }
  -- INSERT comments (skole_id from JWT, parent_id from JWT sub)

GET /parent-app/engagement/comments/:type/:id
  -- SELECT * FROM comments WHERE entity_type = ? AND entity_id = ?
     AND deleted_status = 0 ORDER BY created_at ASC
```

### Reaction Toggle Flow

```text theme={null}
POST /parent-app/engagement/react
  { entity_type, entity_id, reaction_type }
  ├─ Try UPSERT into reactions (unique on entity_type+entity_id+parent_id+staff_id)
  ├─ If existing record matches reaction_type → DELETE (toggle off)
  └─ If new or different type → INSERT/UPDATE
```

***

## 5. UI Requirements

> Engagement components are embedded within Activity, Diary, Noticeboard, and Write-To screens.

**Components:**

| ID                 | Component       | Props                                           |
| ------------------ | --------------- | ----------------------------------------------- |
| `SKOLE-ENGG-UC001` | `CommentInput`  | `entityType`, `entityId`, `onSubmit`, `loading` |
| `SKOLE-ENGG-UC002` | `CommentFeed`   | `comments[]`, `currentParentId`                 |
| `SKOLE-ENGG-UC003` | `CommentBubble` | `comment`, `isOwn`                              |
| `SKOLE-ENGG-UC004` | `ReactionBar`   | `reactions`, `onReact`, `myReaction`            |
| `SKOLE-ENGG-UC005` | `ReactionCount` | `likeCount`, `loveCount`                        |

***

## 6. Conditional Expressions

| ID                 | Expression                                   | Trigger            | True Action                  | False Action      |
| ------------------ | -------------------------------------------- | ------------------ | ---------------------------- | ----------------- |
| `SKOLE-ENGG-CE001` | `existingReaction && reaction_type === same` | POST react         | Delete reaction (toggle off) | Upsert reaction   |
| `SKOLE-ENGG-CE002` | `myReaction === 'like'`                      | ReactionBar render | Filled like icon             | Outline like icon |
| `SKOLE-ENGG-CE003` | `myReaction === 'love'`                      | ReactionBar render | Filled love icon             | Outline love icon |
| `SKOLE-ENGG-CE004` | `comment.parent_id === jwt.sub`              | CommentBubble      | Align right, own color       | Align left        |
| `SKOLE-ENGG-CE005` | `comment.deleted_status === 1`               | Comment query      | Exclude                      | Include           |

***

## 7. Internal Module Connections

| Direction   | Module      | Data / Event                                          | Condition |
| ----------- | ----------- | ----------------------------------------------------- | --------- |
| ENGG → ACTV | Activities  | Comments/reactions attach via entity\_type='activity' | On engage |
| ENGG → DIRY | Diary       | Comments/reactions via entity\_type='diary'           | On engage |
| ENGG → WRIT | Write-To    | Comments via entity\_type='write\_to'                 | On engage |
| ENGG → NOTB | Noticeboard | Reactions via entity\_type='noticeboard'              | On react  |

***

## 8. Database Tables

| ID                 | Table       | Role                           |
| ------------------ | ----------- | ------------------------------ |
| `SKOLE-ENGG-TB001` | `comments`  | Comments on any entity         |
| `SKOLE-ENGG-TB002` | `reactions` | Like/love reactions per entity |

### `reactions` Unique Constraint

```text theme={null}
@@unique([entity_type, entity_id, parent_id, staff_id])
```

This ensures one reaction per user+entity. Toggle is handled at service layer.

***

## 9. API Endpoints

| ID                 | Method | Route                                        | Auth         | Description                 |
| ------------------ | ------ | -------------------------------------------- | ------------ | --------------------------- |
| `SKOLE-ENGG-EP001` | POST   | `/parent-app/engagement/comment`             | JWT (parent) | Post comment                |
| `SKOLE-ENGG-EP002` | GET    | `/parent-app/engagement/comments/:type/:id`  | JWT (parent) | List comments               |
| `SKOLE-ENGG-EP003` | POST   | `/parent-app/engagement/react`               | JWT (parent) | Toggle reaction             |
| `SKOLE-ENGG-EP004` | GET    | `/parent-app/engagement/reactions/:type/:id` | JWT (parent) | Reaction counts + own state |
