Compare commits

..

No commits in common. "ff9fdc79829ed480f1c80b4d8d5ff9c957051e39" and "3522448a7f01cab73b2c73f14f4bc7acd7a385e7" have entirely different histories.

4 changed files with 99 additions and 97 deletions

143
README.md
View File

@ -1,40 +1,38 @@
# Learner Management System Frontend # Learner Management System Frontend
This is the frontend for a modular and responsive Learner Management System (LMS), built with Vanilla Typescript, Vite, and Bootstrap v5.3. It utilizes a widget-based system and interacts with a dedicated backend server via a RESTful API using PAKE SRP for authentication. This is the frontend for a modular and responsive Learner Management System (LMS), built with Vanilla Typescript, Vite, and Bootstrap v5.3. It utilizes a widget-based system and a global API structure designed to interact with a backend server.
## Features ## Features
* **Modular Architecture:** Organized into distinct modules (widgets, layouts, pages, API) for maintainability and scalability. * **Modular Architecture:** Organized into modules for easy maintainability and scalability.
* **Responsive Design:** Uses Bootstrap 5.3 for a consistent experience across desktops, tablets, and mobiles. * **Responsive Design:** Built with Bootstrap 5.3 to ensure responsiveness across various devices.
* **Widget System:** Extensible widgets with `default` (full-width) and `icon` (sidebar) sizes. * **Widget System:** Extensible widget system with two size types (default full-width and icon-type for sidebar).
* **API Integration:** Connects to a live backend API (default: `http://localhost:8080/api`) for data fetching and actions. * **Global API System:** Clearly defined API structure for communication with a backend (currently mocked).
* **Secure Authentication:** Implements Password-Authenticated Key Exchange (PAKE SRP) for secure login via the `thin-srp` library. * **Layout Modules:** Pre-built layouts (Centered, Three-Column, Split-Column) for different page structures.
* **Token-Based Sessions:** Manages user sessions using tokens obtained from the backend upon successful login (stored in localStorage by default). * **Page Components:** Includes pre-built pages for Login, Register, Dashboard, Settings, Admin, Profile, and Manage Students.
* **Layout Modules:** Provides pre-built layouts: `CenteredLayout`, `ThreeColumnLayout`, `SplitColumnLayout`. * **Topbar Module:** Navigation and user profile dropdown.
* **Core Pages:** Includes pages for Login, Register (info only), Dashboard, Profile, Account Settings (Modal), Admin Dashboard, Manage Students. * **Modal Module:** (To be implemented) For reusable modal components.
* **Topbar Module:** Features main navigation and a user profile dropdown with account actions. * **Basic Authentication Flow:** Login and logout functionality with token-based session management (localStorage).
* **Modal Module:** Provides a reusable container for modal dialogs (e.g., Account Settings, notifications).
## Technologies Used ## Technologies Used
* **Vanilla Typescript:** For a robust, type-safe, and maintainable codebase without framework overhead. * **Vanilla Typescript:** For a type-safe and maintainable codebase.
* **Vite:** For an extremely fast development server and optimized build process. * **Vite:** For fast and efficient development and build process.
* **Bootstrap v5.3:** For responsive layout, styling components, and utility classes. * **Bootstrap v5.3:** For responsive layout and styling.
* **pnpm:** Efficient package manager for dependency management. * **pnpm:** Package manager for efficient dependency management.
* **thin-srp:** JavaScript client library for Secure Remote Password (SRP) protocol implementation. * **argon2-browser:** (For demonstration purposes - **Backend Hashing Recommended**) For frontend password hashing demonstration (Argon2id). **Important:** In a production environment, password hashing should be performed on the backend for security reasons.
## Prerequisites ## Prerequisites
* **Node.js** (>= 18 recommended) * **Node.js** (>= 18 recommended)
* **pnpm** (Install globally: `npm install -g pnpm`) * **pnpm** (Install globally: `npm install -g pnpm`)
* **Running Backend:** The LMS backend service must be running (see backend README) and accessible (defaults to `http://localhost:8080`).
## Installation and Setup ## Installation and Setup
1. **Clone the repository:** 1. **Clone the repository:**
```bash ```bash
git clone <your-frontend-repository-url> git clone <repository_url>
cd lms-frontend cd lms-frontend
``` ```
@ -44,86 +42,85 @@ This is the frontend for a modular and responsive Learner Management System (LMS
pnpm install pnpm install
``` ```
3. **Configure API Base URL (Optional):** 3. **Start the development server:**
* If your backend runs on a different address or port, update the `API_BASE_URL` constant in `src/api/api.ts`.
4. **Start the development server:**
```bash ```bash
pnpm dev pnpm dev
``` ```
This will start the Vite development server. Open your browser and navigate to the address provided (usually `http://localhost:5173`). This will start the Vite development server. Open your browser and navigate to the address provided in the console (usually `http://localhost:5173/`).
## Project Structure ## Project Structure
```bash ```bash
lms-frontend/ lms-frontend/
├── index.html # Main HTML entry point ├── index.html # Main HTML entry point
├── package.json # Project dependencies and scripts ├── pnpm-lock.yaml # pnpm lock file for dependency management
├── pnpm-lock.yaml # pnpm lock file ├── pnpm-workspace.yaml # pnpm workspace configuration
├── public/ # Static assets served directly ├── public/ # Public assets (images, etc.)
├── README.md # This README file ├── README.md # This README file
├── src/ # Source code directory ├── src/ # Source code directory
│ ├── api/ │ ├── api/ # API interaction functions (mocked in api.ts)
│ │ └── api.ts # Functions for interacting with the backend API (SRP, data fetching) │ ├── assets/ # Static assets (images, icons)
│ ├── assets/ # Static assets processed by Vite (images, icons) │ ├── components/ # Reusable components
│ ├── components/ │ │ ├── layouts/ # Page layout components (CenteredLayout, ThreeColumnLayout, SplitColumnLayout)
│ │ ├── layouts/ # Page layout components │ │ ├── modules/ # Modules (TopbarModule, ModalModule - to be implemented)
│ │ ├── modules/ # Larger UI modules (TopbarModule, ModalModule) │ │ ├── widgets/ # Widget components (LoginWidget, ButtonWidget, etc.)
│ │ └── widgets/ # Reusable UI widgets │ ├── main.ts # Main entry point for the application
│ ├── main.ts # Application entry point, initializes router/app state │ ├── pages/ # Page components (LoginPage, DashboardPage, etc.)
│ ├── pages/ # Page-level components/logic │ ├── styles/ # Global styles and Bootstrap import (index.css)
│ ├── styles/ │ ├── types/ # Typescript interfaces (Widget.ts, User.ts)
│ │ └── index.css # Global styles, Bootstrap import │ ├── utils/ # Utility functions (api.ts, auth.ts)
│ ├── types/ # TypeScript interfaces and type definitions │ ├── vite-env.d.ts # Vite environment declaration
│ ├── utils/ ├── tsconfig.json # Typescript configuration
│ │ └── utils.ts # Utility functions (auth state management, storage) ├── vite.config.ts # Vite configuration
│ └── vite-env.d.ts # Vite environment type declarations
├── tsconfig.json # TypeScript configuration
├── tsconfig.node.json # TypeScript configuration for Node contexts (e.g., Vite config)
└── vite.config.ts # Vite build tool configuration
``` ```
## Widget System ## Widget System
The UI is composed of reusable widgets found in `src/components/widgets/`. Each widget encapsulates specific functionality or displays data. They support different sizes (`default`, `icon`) for adaptability within various layouts. The frontend is built around a widget system. Widgets are independent, reusable components that display specific information or functionality.
* **Widget Sizes:**
* `default`: Full column width, suitable for most widgets.
* `icon`: Smaller size, designed for use in collapsed sidebars or icon-based menus.
* **Widget Components:** Located in `src/components/widgets/`. Examples include:
* `LoginWidget`: Login form.
* `RegisterWidget`: Registration information display.
* `ButtonWidget`: Reusable button component.
* `StudentCountWidget`, `TeacherCountWidget`, `ProfileInfoWidget`, `PostFeedWidget`, `StudentTableWidget`, `TuitionFeeWidget`: Placeholder widgets to be implemented.
## API System ## API System
Defined in `src/api/api.ts`, this module handles all communication with the backend API. The frontend is designed to interact with a backend through a global API system defined in `src/utils/api.ts`.
* **Live Interaction:** Functions use `fetch` to make requests to the running backend (default: `http://localhost:8080/api`). * **Current Implementation:** The `api.ts` file currently contains **mocked API calls** for demonstration purposes. It simulates API responses using timeouts and hardcoded data.
* **SRP Flow:** The `login` function implements the two-step SRP authentication handshake with the backend. * **Backend Integration:** To connect to a real backend, you will need to replace the mocked API calls in `api.ts` with actual `fetch` requests to your backend endpoints.
* **Authenticated Requests:** Other API functions automatically include the stored authentication token in the `Authorization: Bearer <token>` header for protected endpoints. * **Expected Backend Endpoints (Example):**
* **Error Handling:** Includes basic error handling and detection of unauthorized (401) responses. * `POST /api/login`: User login.
* **Key Endpoints Used:** * `GET /api/user`: Get user data (requires authentication).
* `POST /api/auth/srp/start` * `POST /api/logout`: User logout.
* `POST /api/auth/srp/verify` * `/api/students`, `/api/teachers`, `/api/admin/students`, etc.: Endpoints for managing students, teachers, and other LMS data.
* `POST /api/auth/logout`
* `GET /api/profile/{user_id}`
* `PUT /api/profile/settings`
* `GET /api/admin/dashboard`
* `GET /api/admin/students`
* `GET /api/admin/students/{student_id}/financials`
## Backend Interaction Notes ## Backend Considerations
* **Authentication:** The backend handles the secure verification of passwords using SRP. The frontend never stores or hashes the raw password itself after the initial SRP calculation during login. * **Password Hashing (Backend Recommended):** While `argon2-browser` is included for frontend password hashing demonstration, **it is strongly recommended to implement password hashing (using Argon2id or similar) and salting on the backend for enhanced security.** The frontend should send passwords securely (HTTPS) to the backend, and the backend should handle the hashing and verification process.
* **Authorization:** Access to specific API endpoints (e.g., admin routes) is controlled by the backend based on the user's role/permissions associated with their session token. * **Authentication and Authorization:** The backend should implement robust authentication (e.g., JWT or session-based) and authorization mechanisms to secure API endpoints and protect sensitive data.
* **Data Source:** All dynamic data (user info, student lists, etc.) is fetched from the backend, which interacts with the MariaDB database. * **Database:** The database schema outlined in the initial prompt should be implemented on the backend to store user data, course information, enrollments, etc. (Refer to the initial prompt for database schema details).
* **Backend Technology:** You can choose any suitable backend technology (Node.js, Python, Java, PHP, etc.) to build the API endpoints and connect to the database.
## Further Development ## Further Development
* **Complete Widget Functionality:** Ensure all widgets fetch and display real data from the backend API. * **Implement Modal Module:** Create a reusable `ModalModule` component in `src/components/modules/ModalModule.ts` to handle modals for various purposes (e.g., classrooms under construction, account settings).
* **Admin Page Enhancements:** Implement full CRUD operations for student/teacher management, filtering, batch actions, and enrollment assignments. * **Complete Widget Implementations:** Implement the remaining placeholder widgets in `src/components/widgets/` (e.g., `StudentCountWidget`, `TeacherCountWidget`, `ProfileInfoWidget`, `PostFeedWidget`, `StudentTableWidget`, `TuitionFeeWidget`) to display actual data from the backend.
* **Student Table Widget:** Integrate a robust table library (e.g., Tabulator, TanStack Table) for improved sorting, filtering, and pagination. * **Account Settings Modal:** Develop the Account Settings Modal to allow users to edit their profile information and change passwords.
* **Classrooms Module:** Build out the Classrooms feature beyond the placeholder modal. * **Admin Page Functionality:** Implement the functionality for the Admin page, including student and teacher management, using appropriate widgets and API calls.
* **Robust Error Handling:** Implement more comprehensive error handling and user feedback mechanisms throughout the UI. * **Student Table Widget:** Integrate a table library (e.g., Tabulator, DataTables) into the `StudentTableWidget` for enhanced table features like sorting, filtering, and pagination.
* **Client-Side Validation:** Add more input validation for forms (e.g., account settings). * **Classrooms Page/Modal:** Implement the Classrooms feature, potentially starting with a modal indicating "Under Construction" as initially requested, and then expanding to a full Classrooms page with relevant widgets.
* **UI/UX Polish:** Refine styling, transitions, and interactions for a smoother user experience. * **Form Validation:** Add client-side form validation to login, registration (if implemented), and account settings forms for better user experience.
* **Testing:** Implement unit and potentially end-to-end tests. * **Error Handling:** Improve error handling in API calls and display user-friendly error messages.
* **State Management:** For larger applications, consider introducing a dedicated state management library (like Zustand, Pinia, Redux Toolkit) instead of relying solely on `utils.ts`. * **Styling and UI Polish:** Enhance the visual design and user interface with custom CSS and Bootstrap components to create a polished and professional LMS frontend.
* **Backend Integration:** Replace the mocked API calls with real API calls to your backend endpoints to connect the frontend to the backend data and functionality.
## Contributing ## Contributing
@ -131,4 +128,4 @@ Defined in `src/api/api.ts`, this module handles all communication with the back
## License ## License
[View MIT License](./LICENSE) [View the License](./LICENSE)

View File

@ -4,13 +4,11 @@ import { globalAPI, ApiResponse, ProfileResponseData } from '../api/api'; // Imp
export class TopBar { export class TopBar {
private container: HTMLElement; private container: HTMLElement;
private menuItems: Array<HTMLElement>;
private profileDropdownVisible: boolean = false; private profileDropdownVisible: boolean = false;
private profileData: ProfileResponseData | null = null; private profileData: ProfileResponseData | null = null;
constructor() { constructor() {
this.container = createElement('nav'); this.container = createElement('nav');
this.menuItems = [];
this.container.classList.add('top-bar', 'navbar', 'navbar-expand-lg', 'navbar-light', 'bg-darker', 'mb-3', 'px-4'); this.container.classList.add('top-bar', 'navbar', 'navbar-expand-lg', 'navbar-light', 'bg-darker', 'mb-3', 'px-4');
this.fetchProfileData(); this.fetchProfileData();
} }
@ -31,19 +29,6 @@ export class TopBar {
} }
} }
addMenuItem(text: string, href: string) {
const menuItem = createElement('li');
menuItem.classList.add('nav-item');
const itemLink = createElement('a');
itemLink.classList.add('nav-link');
itemLink.href = href;
itemLink.textContent = text;
menuItem.appendChild(itemLink);
this.menuItems.push(menuItem)
}
render(): HTMLElement { render(): HTMLElement {
this.container.innerHTML = ''; this.container.innerHTML = '';
@ -69,9 +54,33 @@ export class TopBar {
const menuPages = createElement('ul'); const menuPages = createElement('ul');
menuPages.classList.add('navbar-nav', 'me-auto', 'mb-2', 'mb-lg-0'); menuPages.classList.add('navbar-nav', 'me-auto', 'mb-2', 'mb-lg-0');
for (const item of this.menuItems) { const dashboardMenuItem = createElement('li');
menuPages.appendChild(item); dashboardMenuItem.classList.add('nav-item');
} const dashboardLink = createElement('a');
dashboardLink.classList.add('nav-link');
dashboardLink.href = '#/dashboard';
dashboardLink.textContent = 'Dashboard';
dashboardMenuItem.appendChild(dashboardLink);
menuPages.appendChild(dashboardMenuItem);
const classroomsMenuItem = createElement('li');
classroomsMenuItem.classList.add('nav-item');
const classroomsLink = createElement('a');
classroomsLink.classList.add('nav-link');
classroomsLink.href = '#/classrooms';
classroomsLink.textContent = 'Classrooms';
classroomsMenuItem.appendChild(classroomsLink);
menuPages.appendChild(classroomsMenuItem);
const adminMenuItem = createElement('li');
adminMenuItem.classList.add('nav-item');
const adminLink = createElement('a');
adminLink.classList.add('nav-link');
adminLink.href = '#/admin';
adminLink.textContent = 'Admin';
adminMenuItem.appendChild(adminLink);
menuPages.appendChild(adminMenuItem);
const profileSection = createElement('div'); const profileSection = createElement('div');
profileSection.classList.add('d-flex', 'align-items-center', 'ms-auto'); profileSection.classList.add('d-flex', 'align-items-center', 'ms-auto');

View File

@ -9,7 +9,7 @@ class WelcomeWidget extends Widget {
const widgetDiv = createElement('div'); const widgetDiv = createElement('div');
widgetDiv.classList.add('widget', 'welcome-widget'); widgetDiv.classList.add('widget', 'welcome-widget');
widgetDiv.innerHTML = ` widgetDiv.innerHTML = `
<div class="widget-header centered-header">Welcome to the Dashboard</div> <div class="widget-header">Welcome to the Dashboard</div>
<div class="widget-body"> <div class="widget-body">
This is your dashboard. More widgets will be added here. This is your dashboard. More widgets will be added here.
</div> </div>

View File

@ -58,12 +58,8 @@ body {
border-radius: 5px; border-radius: 5px;
} }
.centered-header {
font-size: 24px;
text-align: center;
}
.widget-header { .widget-header {
font-size: 24px;
margin-bottom: 10px; margin-bottom: 10px;
font-weight: bold; font-weight: bold;
} }