Frontend JavaScript (app.js)
Relevant source files
The following files were used as context for generating this wiki page:- src/main/resources/static/js/app.js
- src/main/resources/templates/contracts/form.html
- src/main/resources/templates/customers/form.html
- src/main/resources/templates/fragments/layout.html
- src/main/resources/templates/customers/list.html
- src/main/resources/templates/contracts/list.html
- src/main/resources/templates/reports/index.html
- src/main/resources/static/css/style.css
- src/main/resources/templates/installments/list.html
- src/main/resources/templates/error.html
- pom.xml
The app.js file is the core of the PayMaster application's client-side functionality. It is responsible for enhancing user experience through dynamic interactions, form validation, API communication, and UI component management. The script is structured into a series of modular objects, encapsulated within an Immediately Invoked Function Expression (IIFE) to avoid polluting the global scope.
The script initializes various modules upon the DOMContentLoaded event, including form validators, a contract calculator, data table enhancements, and general UI components. It also handles the display of flash messages passed from the server and exposes a global PayMaster object for specific functionalities to be accessed from inline scripts in HTML templates.
Sources: src/main/resources/static/js/app.js:5-10, src/main/resources/static/js/app.js:1018-1057
Architecture and Initialization
The script follows a modular pattern where different functionalities are grouped into distinct objects (Utils, ApiService, FormValidator, etc.). The main App object orchestrates the initialization of these modules.
The initialization flow is triggered once the DOM is fully loaded. The App.init() method calls the init() method of each submodule, setting up event listeners and activating dynamic features across the application.
Sources: src/main/resources/static/js/app.js:1018-1037
This diagram shows the modular architecture and the initialization sequence.
Global Configuration
A CONFIG object at the top of the file centralizes key settings used throughout the script.
| Property | Value | Description |
|---|---|---|
apiBaseUrl | '/api' | The base path for all backend API calls. |
debounceDelay | 300 | The delay in milliseconds for debouncing functions (e.g., input validation). |
animationDuration | 300 | Standard duration for animations in milliseconds. |
toastDuration | 5000 | Duration for which toast notifications are displayed, in milliseconds. |
dateFormat | 'YYYY/MM/DD' | The standard date format used in the application. |
currency | 'ریال' | The currency symbol or name. |
locale | 'fa-IR' | The locale used for number and date formatting. |
Sources: src/main/resources/static/js/app.js:11-20
Utility Functions (Utils)
The Utils object provides a collection of helper functions for common tasks.
| Function | Description |
|---|---|
formatNumber(num) | Formats a number with thousand separators according to the fa-IR locale. |
formatCurrency(amount) | Formats a number as currency, appending the "ریال" symbol. |
validateNationalCode(code) | Performs local validation of a 10-digit Iranian national ID. |
validateMobile(mobile) | Validates a mobile number to match the 09\d{9} pattern. |
validatePersianDate(dateStr) | Validates a Persian date string in YYYY/MM/DD format. |
debounce(func, wait) | A standard debounce implementation to limit the rate at which a function gets called. |
showToast(message, type) | Displays a Bootstrap toast notification. It dynamically creates the toast container if it doesn't exist. |
copyToClipboard(text) | Copies the given text to the user's clipboard using the navigator.clipboard API. |
Sources: src/main/resources/static/js/app.js:25-212
API Service (ApiService)
The ApiService object is a wrapper around the fetch API, simplifying communication with the backend. It provides methods for GET and POST requests and defines specific functions for application endpoints.
| Method | Endpoint | Description |
|---|---|---|
checkNationalCode(nationalCode, excludeId) | GET /api/check-national-code | Checks if a national code is unique, optionally excluding a specific customer ID. |
checkMobile(mobile, excludeId) | GET /api/check-mobile | Checks if a mobile number is unique, optionally excluding a specific customer ID. |
calculateInstallments(principal, rate, months) | GET /api/calculate-installments | Calculates installment details based on principal, interest rate, and duration. |
convertDate(persianDate) | GET /api/convert-date | Converts a Persian date to another format (presumably Gregorian) on the server. |
searchCustomers(query) | GET /api/search-customers | Searches for customers based on a query string. |
Sources: src/main/resources/static/js/app.js:217-287
The following sequence diagram illustrates the flow for checking a national code.
Form Validation (FormValidator)
The FormValidator module enhances standard HTML5 form validation with real-time, server-side checks for specific fields.
Initialization
The init() method attaches a submit event listener to all forms with the .needs-validation class. It also sets up specific validation for national code, mobile number, and Persian date inputs.
Sources: src/main/resources/static/js/app.js:292-315, src/main/resources/templates/customers/form.html:26
Real-time Validation
- National Code (
#nationalCode): Oninputandblur, the script first performs a local format check usingUtils.validateNationalCode. If it passes, it makes a debounced API call toApiService.checkNationalCodeto verify its uniqueness in the database. The input field's class is updated tois-validoris-invalidbased on the result. - Mobile Number (
#mobile): Similar to the national code, it validates the format locally and then callsApiService.checkMobileto check for uniqueness. - Persian Dates: Inputs with names containing "Persian" or "Date" are validated on
bluragainst theYYYY/MM/DDformat usingUtils.validatePersianDate.
This flowchart shows the logic for national code validation.
Contract Calculator (ContractCalculator)
This module provides an interactive calculator on the contract creation form (contracts/form.html). It listens for changes to the principal amount, interest rate, and installment count, then automatically recalculates and updates the summary.
Flow
- Event listeners are attached to
#principalAmount,#interestRate, and#installmentCount. - When a value changes, the
calculate()function is called (with a debounce for inputs). - It reads the values from the form. If valid, it calls
ApiService.calculateInstallments. - The results from the API (principal, interest, total, installment amount) are displayed in the "پیشنمایش محاسبات" (Calculation Preview) section.
- A Chart.js doughnut chart (
#pieChart) is updated to visually represent the ratio of principal to interest. - If the API call fails, a local fallback calculation (
calculateLocally) is performed.
Sources: src/main/resources/static/js/app.js:425-555, src/main/resources/templates/contracts/form.html:112-140
This sequence diagram illustrates the contract calculation process.
UI Components (UIComponents)
This module initializes and manages various UI elements to improve usability.
- Tooltips & Popovers: Initializes all Bootstrap tooltips and popovers found on the page.
- Modals: Sets focus to the first input field when a modal is shown.
- Alerts: Automatically dismisses non-permanent alerts after the duration specified in
CONFIG.toastDuration. This is used for flash messages from the server. - Loading Buttons: Disables submit buttons and shows a spinner on form submission to prevent double-clicks.
- Scroll to Top: Dynamically creates and manages a "scroll to top" button that appears when the user scrolls down the page.
Sources: src/main/resources/static/js/app.js:630-749, src/main/resources/templates/fragments/layout.html:81-93
Other Modules
DataTable: Provides simple client-side enhancements for tables, including a live search filter.KeyboardShortcuts: Implements shortcuts likeCtrl+Kfor search andCtrl+Nfor creating a new customer.NumberInput: Adds formatting and digit-only restrictions to number inputs.PrintManager: Contains functions to print a specific section of a page or the entire page.StorageManager: A wrapper forlocalStorageto persist simple data on the client, prefixing all keys withpm_.
Sources: src/main/resources/static/js/app.js:559-628, src/main/resources/static/js/app.js:754-867
Conclusion
app.js is a well-structured and essential part of the PayMaster application. It effectively separates concerns into logical modules, providing a rich, responsive, and user-friendly interface. By handling client-side validation, API communication, and dynamic UI updates, it offloads work from the server and creates a modern web application experience. The use of a central configuration, utility functions, and a dedicated API service makes the code maintainable and easy to extend.