# MetaCourse API — Frontend Integration Guide > Target stack: Angular + Capacitor > Base URL (local): `http://localhost:8080` > Base URL (production): `http://romaric-thibault.fr` --- ## Deployment ### Requirements - Docker + Docker Compose installed on the server ### Start the stack ```bash docker compose up -d --build ``` The API will be available on port **8080**. SQL Server runs on port **1433** (internal). Migrations run automatically on startup. ### Swagger UI ``` http://:8080/swagger ``` --- ## Authentication There is **no JWT** currently. Login returns user info directly. Store `UserId` in local storage / Capacitor Preferences to identify the current user across requests. --- ## Data Models (TypeScript interfaces) ```typescript // Enums type CourseStatus = 'Draft' | 'Published'; type ResourceType = 'Url' | 'Video' | 'Text' | 'File'; interface User { id: string; // Guid name: string; email: string; createdAt: string; // ISO date } interface LoginResponse { userId: string; name: string; email: string; } interface Course { id: string; title: string; description: string; status: CourseStatus; creatorId: string; creatorName: string; topicCount: number; createdAt: string; updatedAt: string; } interface CourseDetails extends Course { topics: Topic[]; } interface Topic { id: string; title: string; description?: string; position: number; courseId: string; resources: Resource[]; } interface Resource { id: string; type: ResourceType; title: string; content: string; // URL, video URL, text body, or file path createdAt: string; } interface Enrollment { userId: string; courseId: string; courseTitle: string; enrolledAt: string; completedAt?: string; } interface CourseProgress { courseId: string; userId: string; totalTopics: number; completedTopics: number; totalResources: number; completedResources: number; progressPercentage: number; // 0.0 - 100.0 } ``` --- ## API Endpoints ### Users #### Register ``` POST /api/users/register ``` **Body:** ```json { "name": "Alice", "email": "alice@example.com", "password": "Password1" } ``` **Validation:** name 2–100 chars, valid email, password ≥8 chars + 1 uppercase + 1 digit **Response:** `201` → `User` **Errors:** `400` validation | `409` email already taken --- #### Login ``` POST /api/users/login ``` **Body:** ```json { "email": "alice@example.com", "password": "Password1" } ``` **Response:** `200` → `LoginResponse` **Errors:** `401` wrong credentials --- #### Get User Profile ``` GET /api/users/{id} ``` **Response:** `200` → `User` | `404` --- ### Courses #### List Published Courses ``` GET /api/courses ``` Optional query param: `?search=angular` **Response:** `200` → `Course[]` (only Published courses, newest first) --- #### Get Course with Topics & Resources ``` GET /api/courses/{id} ``` **Response:** `200` → `CourseDetails` | `404` --- #### Create Course ``` POST /api/courses ``` **Body:** ```json { "title": "Introduction to Angular", "description": "Learn Angular from scratch", "creatorId": "" } ``` **Response:** `201` → `Course` (status = `Draft`) --- #### Update Course ``` PUT /api/courses/{id} ``` **Body:** ```json { "id": "", "title": "Updated Title", "description": "Updated description" } ``` **Response:** `200` → `Course` | `404` --- #### Publish Course ``` PATCH /api/courses/{id}/publish ``` **Response:** `200` → `Course` | `422` if no topics yet | `404` --- #### Delete Course ``` DELETE /api/courses/{id} ``` **Response:** `204` | `409` if course has enrollments | `404` --- #### Courses Created by a User ``` GET /api/users/{userId}/courses ``` **Response:** `200` → `Course[]` --- ### Topics #### Get Topic ``` GET /api/topics/{id} ``` **Response:** `200` → `Topic` (includes resources ordered by position) | `404` --- #### Create Topic ``` POST /api/topics ``` **Body:** ```json { "courseId": "", "title": "Components", "description": "Optional description", "position": 1 } ``` **Response:** `201` → `Topic` --- #### Update Topic ``` PUT /api/topics/{id} ``` **Body:** ```json { "id": "", "title": "Updated Title", "description": "Updated", "position": 2 } ``` **Response:** `200` → `Topic` | `404` --- #### Delete Topic ``` DELETE /api/topics/{id} ``` **Response:** `204` | `404` --- #### Link Resource to Topic ``` POST /api/topics/{topicId}/resources/{resourceId} ``` **Body:** ```json { "position": 1 } ``` **Response:** `204` --- #### Unlink Resource from Topic ``` DELETE /api/topics/{topicId}/resources/{resourceId} ``` **Response:** `204` --- ### Resources #### List All Resources ``` GET /api/resources ``` **Response:** `200` → `Resource[]` (ordered by creation date desc) --- #### Get Resource ``` GET /api/resources/{id} ``` **Response:** `200` → `Resource` | `404` --- #### Create Resource ``` POST /api/resources ``` **Body:** ```json { "type": "Url", "title": "Angular Docs", "content": "https://angular.io" } ``` **Types & content:** | Type | content field | |------|--------------| | `Url` | Full URL (https required) | | `Video` | Video URL (https required) | | `Text` | Markdown or plain text body | | `File` | File path or download URL | **Response:** `201` → `Resource` --- #### Update Resource ``` PUT /api/resources/{id} ``` **Body:** ```json { "id": "", "type": "Video", "title": "Updated", "content": "https://youtube.com/..." } ``` **Response:** `200` → `Resource` | `404` --- #### Delete Resource ``` DELETE /api/resources/{id} ``` **Response:** `204` | `404` --- ### Enrollments #### Enroll in a Course ``` POST /api/courses/{courseId}/enroll ``` **Body:** ```json { "userId": "", "courseId": "" } ``` **Response:** `201` → `Enrollment` **Errors:** `409` already enrolled | `422` course not Published | `404` --- #### User's Enrollments ``` GET /api/users/{userId}/enrollments ``` **Response:** `200` → `Enrollment[]` --- ### Progress #### Mark Topic Progress ``` POST /api/topics/{topicId}/progress ``` **Body:** ```json { "userId": "", "topicId": "", "completed": true } ``` **Response:** `204` (upsert — safe to call multiple times) --- #### Mark Resource Progress ``` POST /api/resources/{resourceId}/progress ``` **Body:** ```json { "userId": "", "resourceId": "", "completed": true } ``` **Response:** `204` (upsert) --- #### Get Course Progress ``` GET /api/courses/{courseId}/progress?userId={userId} ``` **Response:** `200` → `CourseProgress` ```json { "courseId": "...", "userId": "...", "totalTopics": 5, "completedTopics": 3, "totalResources": 10, "completedResources": 7, "progressPercentage": 66.67 } ``` --- ## Error Response Format All validation and business errors follow this shape: ```json { "statusCode": 400, "errors": { "email": ["'Email' is not a valid email address."], "password": ["Password must be at least 8 characters."] } } ``` --- ## CORS All origins, methods, and headers are allowed (`AllowAll` policy). No special headers needed from Angular/Capacitor. --- ## Typical User Flow (Angular/Capacitor) ``` 1. POST /api/users/register → store userId in Capacitor Preferences 2. POST /api/users/login → verify credentials 3. GET /api/courses → show published course catalog 4. GET /api/courses/{id} → show course detail with topics 5. POST /api/courses/{id}/enroll → enroll user 6. GET /api/users/{id}/enrollments → show My Courses 7. POST /api/topics/{id}/progress → mark topic done 8. POST /api/resources/{id}/progress → mark resource done 9. GET /api/courses/{id}/progress?userId=... → show progress bar ``` --- ## Notes for Angular Service Layer - All IDs are **UUIDs (string)** — no integer IDs. - Dates are **ISO 8601 UTC strings** — use `new Date(dateString)` or a pipe. - `progressPercentage` is a `number` (float 0–100), round for display. - `status` and `type` come back as **strings**, not numbers. - No auth headers needed currently — all endpoints are `AllowAnonymous`.