# M-TEER Learning Platform

**User Manual — Admin Panel & System Flow**

This manual explains what the M-TEER platform is, how its three parts work together, and how the content team uses the admin panel day to day. It is written for two audiences: clients who want to understand what the system does, and the internal team who operate it.


---


## 1. What this platform is

M-TEER is a content-driven learning platform for mitral valve transcatheter edge-to-edge repair education. It teaches through interactive activities — drawing, colouring, annotation, quizzes, decision trees and case studies — rather than static pages.


### The governing principle

The admin panel owns the content. The mobile app owns the experience.

This is the single most important idea in the system. New sections, modules, activities, quizzes, decision trees and drawing templates are created by the medical and content team in the admin panel, and they appear in the mobile app automatically — with no source code change and no new app release.

> **Note:** No educational or clinical content is compiled into any of the three applications. Even the legal disclaimer text is served from settings, so the medical team controls its wording without involving a developer.


### What this means in practice

| You want to... | Do you need a developer? | Do learners need to update the app? |
|---|---|---|
| Add a new module or lesson | No | No |
| Fix a typo in published content | No | No |
| Add a quiz or decision tree | No | No |
| Upload new diagrams or videos | No | No |
| Change the disclaimer text | No | No |
| Add a brand new type of activity widget | Yes | Yes |


---


## 2. How the system fits together

The platform has three parts plus a database. They talk to each other only through the API — no part reaches into another's data directly.

```
Admin Panel  (React)   ─┐
                        ├──►  API (NestJS)  ──►  MySQL database
Mobile App   (Flutter) ─┘                        + file storage
```

| Part | Who uses it | What it does |
|---|---|---|
| Admin Panel | Content team, administrators | Creates and publishes all learning content. Runs in a web browser. |
| API | Nobody directly | The engine. Stores everything, enforces all security rules, decides what learners are allowed to see. |
| Mobile App | Learners (doctors) | Displays published content and records progress. No login required. |
| Database | Nobody directly | Holds all content, users, media references and learner progress. |


### The two doors into the API

The API deliberately exposes two separate entrances, with very different rules:

| Entrance | Address | Login required | What it serves |
|---|---|---|---|
| Admin API | /api/v1/admin | Yes — every request | Everything: drafts, published content, users, settings, audit trail. |
| Public API | /api/v1/public | No | Published content only. Draft content is invisible. Quiz answer keys are stripped out. |

> **Note:** Learners never log in. They are identified by an anonymous device session, so no personal accounts or patient-identifiable data are held for learners.


---


## 3. Key concepts you must understand


### 3.1 The content ladder

All learning content is organised in one five-level tree. You always work from the top down.

```
Section        e.g.  "SECTION A — KNOW IT"
  └─ Module    e.g.  "A1 The Mitral Valve Apparatus"
      └─ Lesson      e.g.  "Build It from Scratch"
          └─ Activity      e.g.  "Draw the annulus"
              └─ Content Block   e.g.  a heading, an image, a drawing canvas
```

| Level | What it is | Everyday comparison |
|---|---|---|
| Section | The largest grouping, a theme of the course | A part of a textbook |
| Module | A complete topic within a section | A chapter |
| Lesson | A stage within a module | A section of a chapter |
| Activity | One thing the learner does | An exercise |
| Content Block | One piece of that exercise | A paragraph, picture or question on the page |


### 3.2 The content block — the heart of the system

A content block is the smallest unit of content. Every block is simply a **type** plus a **payload** — the type says what kind of thing it is, and the payload holds the actual content.

The admin panel knows 22 block types, arranged in five families. When you choose a type, the correct form appears automatically; you never edit raw code.

| Family | Block types | Used for |
|---|---|---|
| Text | Heading, Text, Instruction, Info box, Clinical insight, Quote, Checklist | Reading material and teaching points |
| Media | Image, Video, Audio | Diagrams, clips and narration |
| Interactive | Drawing canvas, Colouring canvas, Annotation canvas, Measurement table, Form, Reflection, Decision tree, Case scenario, Procedure step | Everything the learner actively does |
| Assessment | Quiz, MCQ | Testing knowledge |
| Reference | Reference | Citations and external links |

> **Note:** A block type the mobile app does not recognise (for example an older app version meeting a brand new type) displays a readable placeholder instead of crashing. Content is always safe to publish.


### 3.3 The four states of content

Every section, module, lesson, activity, case, decision tree and reference card carries a status. This is how the platform keeps unfinished work away from learners.

| Status | Meaning | Can learners see it? |
|---|---|---|
| DRAFT | Being written. The starting state for everything. | No |
| IN REVIEW | Finished and waiting for a reviewer to check it. | No |
| PUBLISHED | Approved and live. | Yes |
| ARCHIVED | Retired — kept for the record but withdrawn. | No |

The system enforces which moves are legal. You cannot skip from ARCHIVED straight back to PUBLISHED, for example — it must return to DRAFT first.

| From | Allowed next states |
|---|---|
| DRAFT | IN REVIEW, PUBLISHED, ARCHIVED |
| IN REVIEW | DRAFT, PUBLISHED, ARCHIVED |
| PUBLISHED | DRAFT, ARCHIVED |
| ARCHIVED | DRAFT |

> **Note:** Publishing is a deliberate, separate action with its own permission. It is impossible to publish something accidentally while editing it — the edit screens cannot change status at all.


---


## 4. Getting started


### 4.1 Logging in

1. Open the admin panel in your browser (by default http://localhost:5173).
2. Enter your email address and password.
3. You land on the first screen your role permits — usually the Dashboard.

If your login fails, see section 11, Troubleshooting.


### 4.2 The screen layout

Every screen shares the same three areas:

| Area | Location | Contains |
|---|---|---|
| Sidebar | Left | The main menu, grouped into Content, Learning, Media and Administration. Collapsible. |
| Header | Top right | Your role, your name, and the Log out button. |
| Work area | Centre | The page you are working on. |

> **Note:** You will only see menu items your role allows. If a colleague has options you do not, that is their role, not a fault. Ask an administrator to review your permissions.


### 4.3 The menu at a glance

| Menu group | Screens | Purpose |
|---|---|---|
| Dashboard | Dashboard | Overview of content and learner engagement |
| Content | Sections, Modules, Quick Reference | The main course material |
| Learning | Cases, Decision Trees | Clinical scenarios and branching pathways |
| Media | Media Library, Drawing Templates | Images, video, audio and drawing backgrounds |
| Administration | Users, Roles & Permissions, Audit Logs, Settings | Running the platform |


---


## 5. The complete content workflow

This is the core process — how a piece of learning material goes from nothing to live on a learner's device. Follow it in order.


### Step 1 — Upload your media first

Go to **Media → Media Library** and upload every image, video and audio file the new content will use. Doing this first means the files are ready to pick when you build the activities.

1. Click **Upload** and select one or more files.
2. For each image, click **Edit** and fill in the caption and the alt text.

> **Note:** Alt text describes the image for learners using a screen reader. Treat it as required, not optional.


### Step 2 — Create the Section

Go to **Content → Sections**. A section is the top-level theme, such as "KNOW IT" or "SEE IT". You will usually reuse an existing one rather than create a new one.

1. Click **New section**.
2. Enter a title. Leave the slug blank and it is generated for you.
3. Add a description, then save.
4. Use the up and down arrows to place it in the right order.

> **Note:** The slug is a permanent identifier used by the API. Avoid changing it once content is live.


### Step 3 — Create the Module

Go to **Content → Modules** — or simply click a section name, which opens the module list already filtered to it.

1. Click **New module**.
2. Choose the section it belongs to.
3. Enter the title and description, then save.


### Step 4 — Add Lessons

Click the module title to open the **Module Builder**. This is where the module's internal structure is built.

1. Click **Add lesson**.
2. Give it a title and description, then save.
3. Repeat for each stage of the module, then order them with the arrows.


### Step 5 — Add Activities

Inside each lesson panel, click **Add activity**.

1. Choose the activity type — this decides which widget the mobile app uses.
2. Enter the title and the instructions the learner will read.
3. Save. You are taken straight into the Activity Builder.


### Step 6 — Add Content Blocks

The **Activity Builder** is where the real content is written. It has up to three tabs.

| Tab | Purpose | When it appears |
|---|---|---|
| Content blocks | The content the learner sees, in order | Always |
| Questions | Quiz questions and answers | Only for Quiz and MCQ activities |
| Settings | Title, description, instructions and advanced configuration | Always |

To add a block:

1. Click **Add block**.
2. Choose the block type from the grouped list.
3. Fill in the form — the fields change to match the type you picked.
4. Give it an internal title if you wish. This is a label for your team only; learners never see it.
5. Save, then use the arrows to order the blocks as the learner should meet them.

> **Note:** The block type cannot be changed after saving, because the content you entered belongs to that type. To switch type, delete the block and add a new one.


### Step 7 — Add Questions (assessment activities only)

If the activity is a Quiz or MCQ, open the **Questions** tab.

1. Click **Add question**.
2. Type the question, choose its type and set a score.
3. Add the options and switch the correct one or ones to **Correct**.
4. Optionally add an explanation, shown after the learner answers.

| Question type | Use it for |
|---|---|
| MCQ_SINGLE | One correct answer only |
| MCQ_MULTIPLE | Several correct answers |
| TRUE_FALSE | A simple true or false statement |
| IMAGE_BASED | A question about a picture |
| MATCHING | Pairing items together |

> **Note:** Correct answers never leave the server. The mobile app receives the questions and options only — the answer key and explanations are stripped out, and marking is done by the API. A learner cannot inspect the app to find the answers.


### Step 8 — Preview

Return to the Module Builder and click **Preview**. This renders the module exactly as the mobile app will, including draft content, so a reviewer can check it properly before anyone sees it.


### Step 9 — Review and publish

1. From the module list, click **Submit for review**. The status becomes IN REVIEW.
2. A reviewer opens the preview and checks the content.
3. When satisfied, they click **Publish** and type a short change reason describing what changed.
4. The status becomes PUBLISHED and learners receive it on their next sync.

> **Note:** The change reason is stored permanently against that version. Write something meaningful — "Corrected chordae terminology in lesson 2" is useful; "update" is not.


---


## 6. Publishing and version history

Publishing does more than flip a switch. Understanding this protects you from an expensive mistake.


### What happens when you press Publish

1. The system checks you hold the publish permission. This is checked freshly against the database on every request, never taken on trust from the browser.
2. It checks the status move is legal.
3. It takes a complete snapshot of the module — every lesson, activity and content block — and stores it as a new numbered version, together with your change reason, your name and the timestamp.
4. The module is marked PUBLISHED and pointed at that version.
5. The action is written to the audit log.
6. The mobile app sees the content fingerprint change and downloads only what is new.


### Why the snapshot matters

Because publishing photographs the whole module, editing the module afterwards does **not** alter what was published. Your edits accumulate quietly in the working copy until you publish again. This gives you two guarantees:

- Learners never see half-finished edits appearing in live content.
- You keep a permanent, readable record of exactly what was taught at any point in time — important for medical education.

To see the history, open the Module Builder and click **Versions**. You get every version number, its status, its change reason and when it was published.


---


## 7. Screen-by-screen reference


### Dashboard

The opening overview. Eight tiles count your sections, modules, draft modules, activities, media assets, cases, saved drawings and active learners over the last thirty days. Two tables below show the most engaged modules and which activity types are being used most.


### Content → Sections

Manage the top-level themes. Create, edit, reorder with the arrows, publish, archive and delete.

> **Note:** Deleting a section deletes every module, lesson and activity inside it. There is no undo. Archive instead unless you are certain.


### Content → Modules

The full module list with filters for section, status and a text search. The filters are stored in the address bar, so a filtered view can be copied and shared with a colleague as a link. Row actions cover the whole workflow: open the builder, edit details, submit for review, publish, archive and delete.


### Content → Module Builder

The inside of one module. Lessons appear as expandable panels, each listing its activities with type and status. From here you add lessons and activities, reorder them, and reach the two header tools: **Preview** and **Versions**.


### Content → Activity Builder

Where content is actually written, using the three tabs described in Step 6. The Settings tab also holds a Configuration field for advanced, type-specific options passed straight to the mobile widget.

> **Note:** Leave the Configuration field alone unless you have been given specific values to enter. It must be valid JSON or the page will refuse to save.


### Content → Quick Reference

The pocket reference cards learners consult during a procedure — quick maps and checklists rather than full lessons. The category is free text with suggestions, so inventing a new category makes it appear in the mobile app automatically.

> **Note:** Quick reference content is entered as a structured list rather than through the guided block forms. Ask a developer for help the first time, then copy the pattern.


### Learning → Cases

Teaching case scenarios. Alongside the title and description you can record patient code, age, sex and clinical details — MR etiology, NYHA class, EF, STS score, an anatomy image and expert teaching notes. Cases are published and archived like any other content.

> **Note:** Use patient codes such as PT-001, never patient names. Do not enter anything that could identify a real person. This is a medical safety and privacy requirement, not a preference.


### Learning → Decision Trees

Branching clinical pathways — for example "Is this patient TEER-able?". The list creates the tree; clicking it opens the graph builder, where you build the pathway from nodes and branches.

| Node type | Purpose |
|---|---|
| START | The entry point. Every tree needs exactly one. |
| QUESTION | A decision point that offers the learner choices. |
| RESULT | An end point with a conclusion. |
| INFO | An explanatory step along the way. |

To build a tree:

1. Add your nodes. Give each a short key such as q-anatomy-suitable — this is how branches refer to it.
2. Add branches connecting one node to another, each with the option label the learner will tap.
3. Watch the warnings: the page tells you if there is no START node, more than one, or nodes nothing links to.
4. Click **Save graph**, then publish.

> **Note:** The whole tree is saved in one action, so a half-connected tree is never stored. Your changes are held in the browser until you press Save graph — leaving the page first loses them.


### Media → Media Library

All images, video, audio and documents. Upload several files at once, search by name or caption, and filter by type. You can edit a file's name, caption and alt text after upload.

> **Note:** Removing a file from the library does not break content already published that referenced it.


### Media → Drawing Templates

The background plates learners draw, trace and colour on — for example a mitral valve outline. Each template has a name, an image chosen from the media library, a canvas size and optionally a restricted colour palette.

> **Note:** Deleting a template does not destroy drawings learners already made on it; their work is preserved.


### Administration → Users

Administrator accounts for this panel. Create users, edit their details, assign roles, set a password and activate or deactivate accounts.

| Action | Effect |
|---|---|
| Assign roles | Changes what the user can see and do |
| Set password | Replaces the password and signs the user out of every session |
| Deactivate | Blocks login immediately without deleting anything |

> **Note:** You cannot deactivate your own account or change your own roles. This prevents an administrator locking themselves out, and it is enforced by the server, not just hidden in the screen.


### Administration → Roles & Permissions

Roles are built from permissions rather than written into the software, so access can be reshaped without a developer. Create a role, tick the permissions it should carry — grouped by area with All and None shortcuts — and save. Expand any role in the list to see everything it grants.

Permissions are named by area and action, such as module.view, module.update and module.publish. A typical arrangement:

| Role | Typically holds |
|---|---|
| SUPER_ADMIN | Everything, including user and role management |
| Content author | View, create and update content — but not publish |
| Reviewer / publisher | The above plus the publish permissions |
| Read only | View permissions alone |

> **Note:** Hiding a button in this panel is a convenience only. Every request is independently re-checked by the server against the user's current permissions, so access cannot be gained by tampering with the browser.


### Administration → Audit Logs

A permanent record of every change made through the admin panel: what happened, to which item, by whom, from which address and when. Filter by action or item type, and click any row to see the full detail of the change.

This is your first stop for questions such as "who published this?" or "when did this text change?".


### Administration → Settings

Platform-wide values delivered to every learner's device:

| Setting | Purpose |
|---|---|
| Educational disclaimer | The legal and safety notice shown in the mobile app |
| Support email | Where learners are told to ask for help |
| Minimum supported app version | Older app versions can be asked to update |
| Content cache duration | How long the app may use stored content before checking for changes |

> **Note:** These values reach every learner. The disclaimer in particular is medical safety wording — change it only with the approval of whoever is responsible for it.


---


## 8. How content reaches the learner

Once you publish, the process is automatic. Nothing is sent by hand and no app release is needed.

1. You publish a module in the admin panel.
2. The API records the new version and the overall content fingerprint changes.
3. The mobile app checks that fingerprint when it next opens or refreshes.
4. Seeing a change, it downloads only the modules that actually changed — not the whole course.
5. The content is stored on the device so it works offline afterwards.


### What learners can and cannot see

| Item | Reaches the device? |
|---|---|
| Published sections, modules, lessons and activities | Yes |
| Draft or in-review content | No |
| Archived content | No |
| Quiz questions and options | Yes |
| Quiz correct answers and explanations | No — marking happens on the server |
| Another learner's drawings, notes or progress | No |


### How learners are identified

Learners do not log in. Each device is given an anonymous session identifier, and progress, drawings, annotations, notes, favourites and case logs are stored against it. Work is saved on the device first and synchronised when a connection is available, so the app remains usable without network access.


---


## 9. Roles and responsibilities

A suggested division of duties for a content team:

| Person | Responsibilities | Needs permission to |
|---|---|---|
| Content author | Writes modules, lessons, activities and blocks. Uploads media. | View, create and update content; upload media |
| Medical reviewer | Checks clinical accuracy in preview, then publishes. | The above plus publish |
| Administrator | Manages users, roles and platform settings. Monitors the audit log. | Everything |

> **Note:** Separating "can write" from "can publish" is the main safeguard against unreviewed clinical content reaching learners. Grant publish permissions sparingly.


---


## 10. Good practice

- Upload media before you build the activity that uses it.
- Write meaningful change reasons when publishing — they become your permanent history.
- Always preview before publishing, and have someone other than the author do the review.
- Archive rather than delete. Deleting a section or module destroys everything inside it.
- Fill in alt text for every image so learners using a screen reader are not excluded.
- Use patient codes in cases, never names or identifying detail.
- Keep slugs stable once content is live.
- Give each person the narrowest role that lets them do their job.


---


## 11. Troubleshooting

| Symptom | Likely cause | What to do |
|---|---|---|
| Login says the details are wrong | Incorrect password, or the account was deactivated | Check the email, then ask an administrator to reset your password or reactivate you |
| Login is refused after several tries | The system limits repeated login attempts | Wait about a minute and try again |
| Login reports an internal error | The API cannot reach the database | Check the API is running and the database is reachable, then try again |
| A menu item is missing | Your role does not include it | Ask an administrator to review your permissions |
| "Not authorised" on a page | Same as above | Ask an administrator |
| Publish is refused | The status move is not allowed from the current state | Check the current status; archived content must return to draft first |
| A decision tree will not publish | It has no START node, or more than one | Open the graph builder and read the warnings at the top |
| Changes are not visible in the mobile app | The content was saved but not published | Check the status is PUBLISHED, then refresh the app |
| Edits after publishing are not reaching learners | Working as designed — publishing takes a snapshot | Publish again to release the new version |
| A form will not save | A required field is empty, or a configuration field is not valid | Look for the red validation message on the field |


---


## 12. Glossary

| Term | Meaning |
|---|---|
| Activity | One thing a learner does inside a lesson |
| Alt text | A written description of an image for screen reader users |
| Anonymous session | The identifier that represents a learner's device, used instead of a login |
| API | The engine behind both apps; stores data and enforces the rules |
| Archive | Withdraw content from learners while keeping it on record |
| Audit log | The permanent record of who changed what and when |
| Change reason | The note recorded against a published version explaining what changed |
| Content block | The smallest piece of content — a heading, image, canvas or question set |
| Decision tree | A branching pathway of questions leading to conclusions |
| Draft | Content being written; not visible to learners |
| Drawing template | A background image learners draw or colour on |
| Lesson | A stage within a module |
| Module | A complete topic within a section |
| Permission | A single right, such as publishing a module |
| Publish | Make content live and take a permanent snapshot of it |
| Quick reference | Fast-access reference cards in the mobile app |
| Role | A named bundle of permissions given to a user |
| Section | The top level of the content structure |
| Slug | A short permanent identifier used by the system |
| Snapshot | The frozen copy of a module taken at publish time |
| Status | Where content sits in its lifecycle: draft, in review, published or archived |


---


## Appendix A — Running the system

For the technical team. The platform needs two processes running, each in its own terminal window.


### Start the API

```
cd c:\xampp\htdocs\mteer-doctor-app\backend-api
npm run start:dev
```

Wait for the message confirming it is listening on port 3000.


### Start the admin panel

```
cd c:\xampp\htdocs\mteer-doctor-app\adminpanel
npm run dev
```

Then open http://localhost:5173 in a browser.

> **Note:** Start the API first. If the admin panel loads before the API is ready, login will fail until you refresh. Both processes reload automatically when code changes; restart them only after changing configuration or installing packages.


### First-time setup

On a fresh installation, run these once from the backend-api folder:

| Command | What it does |
|---|---|
| npm install | Installs the required packages |
| npm run migrate | Creates the database tables |
| npm run seed | Creates roles, permissions, settings and the first administrator |
| npm run seed:content | Loads the M-TEER workbook content as draft |

> **Note:** The seed command prints the generated administrator password once. Record it and change it after the first login.


### Addresses

| Service | Address |
|---|---|
| Admin panel | http://localhost:5173 |
| API | http://localhost:3000 |
| Content for the mobile app | http://localhost:3000/api/v1/public |
| Admin API | http://localhost:3000/api/v1/admin |
