Here's what you need to install on the command line to run the frontend part of the IMSP project:
Windows:
# Download from nodejs.org or use chocolatey
choco install nodejs
# Or use winget
winget install OpenJS.NodeJSmacOS:
# Using Homebrew (recommended)
brew install node
# Or download from nodejs.orgLinux (Ubuntu/Debian):
# Update package index
sudo apt update
# Install Node.js and npm
sudo apt install nodejs npm
# Or install latest version via NodeSource
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejsVerify Installation:
node --version # Should show v16+
npm --version # Should show 8+Windows:
# Download from git-scm.com or use chocolatey
choco install gitmacOS:
# Usually pre-installed, or use Homebrew
brew install gitLinux:
sudo apt install git# Install globally (optional)
npm install -g create-react-app# If you have the project structure
cd frontend
# Or create new React app (if starting fresh)
npx create-react-app imsp-frontend
cd imsp-frontend# Install all required packages
npm install
# Or install specific packages for IMSP
npm install react react-dom react-router-dom
npm install axios react-query
npm install react-hook-form
npm install react-hot-toast
npm install recharts
npm install lucide-react
npm install date-fns
npm install tailwindcss autoprefixer postcssnpm install --save-dev tailwindcss autoprefixer postcss# Initialize Tailwind config
npx tailwindcss init -p
# This creates tailwind.config.js and postcss.config.js# Create .env file
touch .env
# Or on Windows
echo. > .envAdd to .env:
REACT_APP_API_URL=http://localhost:5000
REACT_APP_CLOUDINARY_CLOUD_NAME=your_cloud_name
REACT_APP_CLOUDINARY_UPLOAD_PRESET=your_upload_presetHere's the complete package.json for the frontend:
{
"name": "imsp-frontend",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"react-router-dom": "^6.15.0",
"axios": "^1.5.0",
"react-query": "^3.39.3",
"react-hook-form": "^7.45.4",
"react-hot-toast": "^2.4.1",
"recharts": "^2.8.0",
"react-calendar": "^4.6.0",
"react-modal": "^3.16.1",
"lucide-react": "^0.279.0",
"date-fns": "^2.30.0",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"tailwindcss": "^3.3.3",
"autoprefixer": "^10.4.15",
"postcss": "^8.4.29"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:5000"
}Create this script to install everything at once:
install-frontend.sh (Linux/macOS):
#!/bin/bash
echo "🚀 Installing IMSP Frontend Dependencies..."
# Check if Node.js is installed
if ! command -v node &> /dev/null; then
echo "❌ Node.js is not installed. Please install Node.js first."
exit 1
fi
# Install dependencies
echo "📦 Installing npm packages..."
npm install
# Install additional packages
echo "🔧 Installing additional packages..."
npm install react-router-dom axios react-query react-hook-form react-hot-toast recharts lucide-react date-fns
# Install dev dependencies
echo "🛠️ Installing dev dependencies..."
npm install --save-dev tailwindcss autoprefixer postcss
# Initialize Tailwind
echo "🎨 Initializing Tailwind CSS..."
npx tailwindcss init -p
# Create .env file
echo "📝 Creating environment file..."
cat > .env << EOL
REACT_APP_API_URL=http://localhost:5000
REACT_APP_CLOUDINARY_CLOUD_NAME=your_cloud_name
REACT_APP_CLOUDINARY_UPLOAD_PRESET=your_upload_preset
EOL
echo "✅ Frontend setup complete!"
echo "🚀 Run 'npm start' to start the development server"install-frontend.bat (Windows):
@echo off
echo 🚀 Installing IMSP Frontend Dependencies...
REM Check if Node.js is installed
node --version >nul 2>&1
if %errorlevel% neq 0 (
echo ❌ Node.js is not installed. Please install Node.js first.
exit /b 1
)
REM Install dependencies
echo 📦 Installing npm packages...
npm install
REM Install additional packages
echo 🔧 Installing additional packages...
npm install react-router-dom axios react-query react-hook-form react-hot-toast recharts lucide-react date-fns
REM Install dev dependencies
echo 🛠️ Installing dev dependencies...
npm install --save-dev tailwindcss autoprefixer postcss
REM Initialize Tailwind
echo 🎨 Initializing Tailwind CSS...
npx tailwindcss init -p
REM Create .env file
echo 📝 Creating environment file...
echo REACT_APP_API_URL=http://localhost:5000 > .env
echo REACT_APP_CLOUDINARY_CLOUD_NAME=your_cloud_name >> .env
echo REACT_APP_CLOUDINARY_UPLOAD_PRESET=your_upload_preset >> .env
echo ✅ Frontend setup complete!
echo 🚀 Run 'npm start' to start the development serverAfter installation:
# Start development server
npm start
# The app will open at http://localhost:3000Check if everything is working:
# Check Node.js version
node --version
# Check npm version
npm --version
# List installed packages
npm list --depth=0
# Check if React scripts work
npm run buildPermission Errors (Linux/macOS):
# Fix npm permissions
sudo chown -R $(whoami) ~/.npmPort 3000 Already in Use:
# Kill process on port 3000
sudo lsof -ti:3000 | xargs kill -9
# Or use different port
PORT=3001 npm startModule Not Found Errors:
# Clear npm cache and reinstall
npm cache clean --force
rm -rf node_modules package-lock.json
npm installNow you're ready to paste the frontend code and run the IMSP application! 🎉
The Industrial Maintenance & Safety Portal (IMSP) Backend API is a RESTful service built with Node.js, Express.js, and MongoDB. It provides comprehensive endpoints for managing industrial maintenance operations, safety incidents, machine monitoring, and user management.
Development: http://localhost:5000
Production: https://your-domain.comThe API uses JWT-based authentication with Bearer tokens.
Authorization: Bearer <jwt_token>{
name: {
type: String,
required: true,
trim: true
},
email: {
type: String,
required: true,
unique: true,
lowercase: true
},
password: {
type: String,
required: true,
minlength: 6
},
role: {
type: String,
enum: ["admin", "maintenance_engineer", "operator", "safety_officer"],
default: "operator"
},
department: {
type: String,
enum: ["Rolling Mill", "Smelting", "Casting", "Quality Control", "Maintenance"],
required: true
},
phone: {
type: String,
trim: true
},
isActive: {
type: Boolean,
default: true
},
createdAt: Date,
updatedAt: Date
}Role Permissions:
{
name: {
type: String,
required: true,
trim: true
},
machineId: {
type: String,
required: true,
unique: true
},
department: {
type: String,
enum: ["Rolling Mill", "Smelting", "Casting", "Quality Control"],
required: true
},
status: {
type: String,
enum: ["Running", "Down", "Maintenance", "Idle"],
default: "Idle"
},
location: {
type: String,
required: true
},
model: {
type: String,
required: true
},
manufacturer: {
type: String,
required: true
},
installationDate: {
type: Date,
required: true
},
lastMaintenanceDate: Date,
nextMaintenanceDate: Date,
operatingHours: {
type: Number,
default: 0
},
specifications: {
capacity: String,
power: String,
dimensions: String,
weight: String
},
qrCode: {
type: String,
unique: true
},
isActive: {
type: Boolean,
default: true
},
createdAt: Date,
updatedAt: Date
}{
ticketNumber: {
type: String,
required: true,
unique: true,
auto-generated: "TKT-XXXXXX"
},
title: {
type: String,
required: true,
trim: true
},
description: {
type: String,
required: true
},
machine: {
type: ObjectId,
ref: "Machine",
required: true
},
reportedBy: {
type: ObjectId,
ref: "User",
required: true
},
assignedTo: {
type: ObjectId,
ref: "User"
},
priority: {
type: String,
enum: ["Low", "Medium", "High", "Critical"],
default: "Medium"
},
status: {
type: String,
enum: ["Pending", "In Progress", "Resolved", "Closed"],
default: "Pending"
},
category: {
type: String,
enum: ["Electrical", "Mechanical", "Hydraulic", "Pneumatic", "Software", "Other"],
required: true
},
estimatedHours: Number,
actualHours: Number,
comments: [{
user: { type: ObjectId, ref: "User" },
comment: String,
timestamp: { type: Date, default: Date.now }
}],
attachments: [{
filename: String,
originalName: String,
path: String,
uploadedBy: { type: ObjectId, ref: "User" },
uploadedAt: { type: Date, default: Date.now }
}],
resolvedAt: Date,
closedAt: Date,
createdAt: Date,
updatedAt: Date
}{
incidentNumber: {
type: String,
required: true,
unique: true,
auto-generated: "INC-XXXXXX"
},
title: {
type: String,
required: true,
trim: true
},
description: {
type: String,
required: true
},
type: {
type: String,
enum: ["Near Miss", "Injury", "Property Damage", "Environmental", "Security"],
required: true
},
severity: {
type: String,
enum: ["Low", "Medium", "High", "Critical"],
required: true
},
location: {
type: String,
required: true
},
department: {
type: String,
enum: ["Rolling Mill", "Smelting", "Casting", "Quality Control", "Maintenance"],
required: true
},
reportedBy: {
type: ObjectId,
ref: "User",
required: true
},
involvedPersons: [{
name: String,
role: String,
department: String
}],
witnesses: [{
name: String,
contact: String
}],
immediateActions: String,
rootCause: String,
correctiveActions: [{
action: String,
assignedTo: { type: ObjectId, ref: "User" },
dueDate: Date,
status: {
type: String,
enum: ["Pending", "In Progress", "Completed"],
default: "Pending"
}
}],
status: {
type: String,
enum: ["Open", "Under Investigation", "Closed"],
default: "Open"
},
attachments: [{
filename: String,
originalName: String,
path: String,
uploadedBy: { type: ObjectId, ref: "User" },
uploadedAt: { type: Date, default: Date.now }
}],
incidentDate: {
type: Date,
required: true
},
closedAt: Date,
createdAt: Date,
updatedAt: Date
}{
machine: {
type: ObjectId,
ref: "Machine",
required: true
},
title: {
type: String,
required: true
},
description: String,
type: {
type: String,
enum: ["Preventive", "Predictive", "Corrective", "Emergency"],
default: "Preventive"
},
frequency: {
type: String,
enum: ["Daily", "Weekly", "Monthly", "Quarterly", "Semi-Annual", "Annual", "Custom"],
required: true
},
scheduledDate: {
type: Date,
required: true
},
estimatedDuration: {
type: Number, // in hours
required: true
},
assignedTo: {
type: ObjectId,
ref: "User"
},
status: {
type: String,
enum: ["Scheduled", "In Progress", "Completed", "Overdue", "Cancelled"],
default: "Scheduled"
},
priority: {
type: String,
enum: ["Low", "Medium", "High", "Critical"],
default: "Medium"
},
checklist: [{
task: String,
completed: { type: Boolean, default: false },
notes: String
}],
actualStartTime: Date,
actualEndTime: Date,
notes: String,
nextScheduledDate: Date,
reminderSent: { type: Boolean, default: false },
attachments: [{
filename: String,
originalName: String,
path: String,
uploadedBy: { type: ObjectId, ref: "User" },
uploadedAt: { type: Date, default: Date.now }
}],
completedBy: { type: ObjectId, ref: "User" },
completedAt: Date,
partsUsed: [{
partName: String,
quantity: Number,
cost: Number
}],
totalCost: { type: Number, default: 0 },
createdAt: Date,
updatedAt: Date
}Register a new user.
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"role": "maintenance_engineer",
"department": "Maintenance",
"phone": "+1234567890"
}Response:
{
"token": "jwt_token_here",
"user": {
"id": "user_id",
"name": "John Doe",
"email": "john@example.com",
"role": "maintenance_engineer",
"department": "Maintenance"
}
}Authenticate user and get token.
Request Body:
{
"email": "john@example.com",
"password": "password123"
}Response:
{
"token": "jwt_token_here",
"user": {
"id": "user_id",
"name": "John Doe",
"email": "john@example.com",
"role": "maintenance_engineer",
"department": "Maintenance"
}
}Get current user information.
Headers:
Authorization: Bearer <token>Response:
{
"user": {
"id": "user_id",
"name": "John Doe",
"email": "john@example.com",
"role": "maintenance_engineer",
"department": "Maintenance"
}
}Get all machines with optional filtering.
Query Parameters:
department: Filter by departmentstatus: Filter by statussearch: Search by name, machineId, or locationHeaders:
Authorization: Bearer <token>Response:
[
{
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
"department": "Rolling Mill",
"status": "Running",
"location": "Building A - Floor 1",
"model": "RM-2000X",
"manufacturer": "SteelTech Industries",
"installationDate": "2020-01-15T00:00:00.000Z",
"operatingHours": 8760,
"specifications": {
"capacity": "500 tons/hour",
"power": "2000 kW",
"dimensions": "15m x 8m x 6m",
"weight": "150 tons"
},
"qrCode": "QR-RM-001",
"isActive": true,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
]Get machine by ID.
Headers:
Authorization: Bearer <token>Response:
{
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
// ... other machine fields
}Create a new machine.
Required Role: admin, maintenance_engineer
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"name": "New Machine",
"machineId": "NM-001",
"department": "Rolling Mill",
"location": "Building A - Floor 2",
"model": "NM-1000",
"manufacturer": "TechCorp",
"installationDate": "2024-01-01",
"specifications": {
"capacity": "100 tons/hour",
"power": "500 kW",
"dimensions": "10m x 5m x 3m",
"weight": "50 tons"
}
}Update machine information.
Required Role: admin, maintenance_engineer
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonUpdate machine status only.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"status": "Maintenance"
}Soft delete machine (sets isActive to false).
Required Role: admin
Headers:
Authorization: Bearer <token>Get all tickets with pagination and filtering.
Query Parameters:
status: Filter by statuspriority: Filter by priorityassignedTo: Filter by assigned userdepartment: Filter by departmentpage: Page number (default: 1)limit: Items per page (default: 10)Headers:
Authorization: Bearer <token>Response:
{
"tickets": [
{
"_id": "ticket_id",
"ticketNumber": "TKT-000001",
"title": "Hydraulic leak in Rolling Mill #1",
"description": "Small hydraulic leak detected...",
"machine": {
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
"department": "Rolling Mill"
},
"reportedBy": {
"_id": "user_id",
"name": "Jane Operator",
"email": "jane@example.com",
"department": "Rolling Mill"
},
"assignedTo": {
"_id": "user_id",
"name": "John Engineer",
"email": "john@example.com"
},
"priority": "High",
"status": "In Progress",
"category": "Hydraulic",
"estimatedHours": 6,
"comments": [],
"attachments": [],
"createdAt": "2024-01-25T09:00:00.000Z",
"updatedAt": "2024-01-25T10:30:00.000Z"
}
],
"totalPages": 5,
"currentPage": 1,
"total": 50
}Get ticket by ID with full details.
Headers:
Authorization: Bearer <token>Response:
{
"_id": "ticket_id",
"ticketNumber": "TKT-000001",
"title": "Hydraulic leak in Rolling Mill #1",
"description": "Small hydraulic leak detected...",
"machine": {
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
"department": "Rolling Mill",
"location": "Building A - Floor 1"
},
"reportedBy": {
"_id": "user_id",
"name": "Jane Operator",
"email": "jane@example.com",
"department": "Rolling Mill"
},
"assignedTo": {
"_id": "user_id",
"name": "John Engineer",
"email": "john@example.com",
"department": "Maintenance"
},
"priority": "High",
"status": "In Progress",
"category": "Hydraulic",
"estimatedHours": 6,
"comments": [
{
"user": {
"_id": "user_id",
"name": "Jane Operator",
"email": "jane@example.com"
},
"comment": "Leak first noticed during morning shift. Getting worse.",
"timestamp": "2024-01-25T09:00:00.000Z"
}
],
"attachments": [],
"createdAt": "2024-01-25T09:00:00.000Z",
"updatedAt": "2024-01-25T10:30:00.000Z"
}Create a new maintenance ticket.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"title": "Machine malfunction",
"description": "Detailed description of the issue",
"machine": "machine_id",
"priority": "High",
"category": "Mechanical",
"estimatedHours": 4
}Response:
{
"_id": "ticket_id",
"ticketNumber": "TKT-000002",
"title": "Machine malfunction",
"description": "Detailed description of the issue",
"machine": {
"_id": "machine_id",
"name": "Machine Name",
"machineId": "M-001",
"department": "Department"
},
"reportedBy": {
"_id": "user_id",
"name": "Current User",
"email": "user@example.com",
"department": "Department"
},
"priority": "High",
"status": "Pending",
"category": "Mechanical",
"estimatedHours": 4,
"createdAt": "2024-01-25T12:00:00.000Z",
"updatedAt": "2024-01-25T12:00:00.000Z"
}Update ticket information.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"status": "Resolved",
"assignedTo": "user_id",
"actualHours": 5,
"resolvedAt": "2024-01-25T16:00:00.000Z"
}Add comment to ticket.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"comment": "Work in progress. Ordered replacement parts."
}Upload attachment to ticket.
Headers:
Authorization: Bearer <token>
Content-Type: multipart/form-dataForm Data:
file: File to upload (max 10MB)Get all incidents with pagination and filtering.
Query Parameters:
type: Filter by incident typeseverity: Filter by severitystatus: Filter by statusdepartment: Filter by departmentpage: Page number (default: 1)limit: Items per page (default: 10)Headers:
Authorization: Bearer <token>Response:
{
"incidents": [
{
"_id": "incident_id",
"incidentNumber": "INC-000001",
"title": "Near miss - Falling object",
"description": "A loose bolt fell from overhead equipment...",
"type": "Near Miss",
"severity": "Medium",
"location": "Building A - Rolling Mill Section",
"department": "Rolling Mill",
"reportedBy": {
"_id": "user_id",
"name": "Jane Operator",
"email": "jane@example.com",
"department": "Rolling Mill"
},
"status": "Under Investigation",
"incidentDate": "2024-01-20T14:30:00.000Z",
"createdAt": "2024-01-20T15:00:00.000Z",
"updatedAt": "2024-01-20T15:00:00.000Z"
}
],
"totalPages": 3,
"currentPage": 1,
"total": 25
}Get incident by ID with full details.
Headers:
Authorization: Bearer <token>Create a new safety incident.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"title": "Safety incident title",
"description": "Detailed description of what happened",
"type": "Near Miss",
"severity": "Medium",
"location": "Specific location",
"department": "Rolling Mill",
"incidentDate": "2024-01-20T14:30:00.000Z",
"involvedPersons": [
{
"name": "Person Name",
"role": "Operator",
"department": "Rolling Mill"
}
],
"witnesses": [
{
"name": "Witness Name",
"contact": "+1234567890"
}
],
"immediateActions": "Actions taken immediately after the incident"
}Update incident information.
Required Role: admin, safety_officer
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonUpload attachment to incident.
Headers:
Authorization: Bearer <token>
Content-Type: multipart/form-dataGet all maintenance schedules with filtering.
Query Parameters:
status: Filter by statusmachine: Filter by machine IDassignedTo: Filter by assigned userstartDate: Filter by start date (YYYY-MM-DD)endDate: Filter by end date (YYYY-MM-DD)Headers:
Authorization: Bearer <token>Response:
[
{
"_id": "schedule_id",
"machine": {
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
"department": "Rolling Mill",
"location": "Building A - Floor 1"
},
"title": "Monthly Hydraulic System Check",
"description": "Check hydraulic fluid levels...",
"type": "Preventive",
"frequency": "Monthly",
"scheduledDate": "2024-02-10T00:00:00.000Z",
"estimatedDuration": 4,
"assignedTo": {
"_id": "user_id",
"name": "John Engineer",
"email": "john@example.com",
"department": "Maintenance"
},
"status": "Scheduled",
"priority": "Medium",
"checklist": [
{
"task": "Check hydraulic fluid level",
"completed": false,
"notes": ""
}
],
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
]Get maintenance schedule by ID.
Headers:
Authorization: Bearer <token>Create new maintenance schedule.
Required Role: admin, maintenance_engineer
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"machine": "machine_id",
"title": "Maintenance task title",
"description": "Detailed description",
"type": "Preventive",
"frequency": "Monthly",
"scheduledDate": "2024-02-10",
"estimatedDuration": 4,
"assignedTo": "user_id",
"priority": "Medium",
"checklist": [
{
"task": "Task description",
"completed": false
}
]
}Update maintenance schedule.
Required Role: admin, maintenance_engineer
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonUpdate specific checklist item.
Headers:
Authorization: Bearer <token>
Content-Type: application/jsonRequest Body:
{
"completed": true,
"notes": "Task completed successfully"
}Get maintenance schedules for specific month.
Headers:
Authorization: Bearer <token>Response:
[
{
"_id": "schedule_id",
"machine": {
"_id": "machine_id",
"name": "Rolling Mill #1",
"machineId": "RM-001",
"department": "Rolling Mill"
},
"title": "Monthly Hydraulic System Check",
"scheduledDate": "2024-02-10T00:00:00.000Z",
"estimatedDuration": 4,
"assignedTo": {
"_id": "user_id",
"name": "John Engineer",
"email": "john@example.com"
},
"status": "Scheduled",
"priority": "Medium"
}
]Get dashboard overview statistics.
Headers:
Authorization: Bearer <token>Response:
{
"machines": {
"total": 8,
"running": 5,
"down": 1,
"maintenance": 2
},
"tickets": {
"open": 12
},
"maintenance": {
"pending": 5
},
"incidents": {
"open": 3,
"critical": 1
}
}Get machine status distribution.
Headers:
Authorization: Bearer <token>Response:
[
{
"_id": "Running",
"count": 5
},
{
"_id": "Down",
"count": 1
},
{
"_id": "Maintenance",
"count": 2
}
]Get machines by department.
Headers:
Authorization: Bearer <token>Response:
[
{
"_id": "Rolling Mill",
"count": 3
},
{
"_id": "Smelting",
"count": 2
},
{
"_id": "Casting",
"count": 2
},
{
"_id": "Quality Control",
"count": 1
}
]Get ticket trends for last 6 months.
Headers:
Authorization: Bearer <token>Response:
[
{
"_id": {
"year": 2024,
"month": 1
},
"count": 15
},
{
"_id": {
"year": 2024,
"month": 2
},
"count": 12
}
]Get Mean Time to Repair statistics.
Headers:
Authorization: Bearer <token>Response:
{
"mttr": 4.5,
"totalResolvedTickets": 25
}Get incidents by type.
Headers:
Authorization: Bearer <token>Response:
[
{
"_id": "Near Miss",
"count": 8
},
{
"_id": "Injury",
"count": 3
},
{
"_id": "Property Damage",
"count": 2
}
]Get monthly incident trends for last 12 months.
Headers:
Authorization: Bearer <token>Get maintenance completion rate.
Headers:
Authorization: Bearer <token>Response:
{
"completionRate": 85.5,
"completed": 34,
"total": 40
}Upload single file to Cloudinary.
Headers:
Authorization: Bearer <token>
Content-Type: multipart/form-dataForm Data:
file: File to upload (max 10MB)Response:
{
"message": "File uploaded successfully",
"file": {
"url": "https://res.cloudinary.com/...",
"public_id": "imsp/1234567890",
"original_name": "document.pdf",
"size": 1024000
}
}Upload multiple files (max 5).
Headers:
Authorization: Bearer <token>
Content-Type: multipart/form-dataForm Data:
files: Array of files to uploadDelete file from Cloudinary.
Headers:
Authorization: Bearer <token>{
"message": "Error description",
"error": "Detailed error information (development only)"
}| Code | Description |
|---|---|
| 200 | OK - Request successful |
| 201 | Created - Resource created successfully |
| 400 | Bad Request - Invalid request data |
| 401 | Unauthorized - Authentication required |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Resource not found |
| 409 | Conflict - Resource already exists |
| 422 | Unprocessable Entity - Validation error |
| 500 | Internal Server Error - Server error |
Authentication Error:
{
"message": "No token, authorization denied"
}Validation Error:
{
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Email is required"
}
]
}Permission Error:
{
"message": "Access denied. Insufficient permissions."
}Resource Not Found:
{
"message": "Machine not found"
}const storage = new CloudinaryStorage({
cloudinary: cloudinary,
params: {
folder: "imsp",
allowed_formats: ["jpg", "jpeg", "png", "pdf", "doc", "docx"],
resource_type: "auto",
public_id: (req, file) => {
return `${Date.now()}-${Math.round(Math.random() * 1e9)}`
}
}
})https://res.cloudinary.com/{cloud_name}/image/upload/v{version}/{public_id}.{format}NODE_ENV=development|production
PORT=5000
MONGODB_URI=mongodb://localhost:27017/imsp
JWT_SECRET=your-super-secret-jwt-key-here
CORS_ORIGIN=http://localhost:3000# Cloudinary Configuration
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Email Configuration
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
# SMS Configuration (Twilio)
TWILIO_ACCOUNT_SID=your-twilio-sid
TWILIO_AUTH_TOKEN=your-twilio-token
TWILIO_PHONE_NUMBER=your-twilio-phoneEnvironment Variables
NODE_ENV=productionJWT_SECRETDatabase
Security
Monitoring
Railway:
# Install Railway CLI
npm install -g @railway/cli
# Login and deploy
railway login
railway init
railway upHeroku:
# Install Heroku CLI
npm install -g heroku
# Create app and deploy
heroku create your-app-name
git push heroku mainRender:
GET /api/healthResponse:
{
"message": "IMSP API is running!",
"timestamp": "2024-01-25T12:00:00.000Z",
"environment": "production"
}const rateLimit = require("express-rate-limit")
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 requests per windowMs
message: "Too many authentication attempts, please try again later."
})
app.use("/api/auth", authLimiter)// Users
db.users.createIndex({ email: 1 }, { unique: true })
db.users.createIndex({ role: 1 })
db.users.createIndex({ department: 1 })
// Machines
db.machines.createIndex({ machineId: 1 }, { unique: true })
db.machines.createIndex({ department: 1 })
db.machines.createIndex({ status: 1 })
db.machines.createIndex({ isActive: 1 })
// Tickets
db.tickets.createIndex({ ticketNumber: 1 }, { unique: true })
db.tickets.createIndex({ machine: 1 })
db.tickets.createIndex({ reportedBy: 1 })
db.tickets.createIndex({ assignedTo: 1 })
db.tickets.createIndex({ status: 1 })
db.tickets.createIndex({ priority: 1 })
db.tickets.createIndex({ createdAt: -1 })
// Incidents
db.incidents.createIndex({ incidentNumber: 1 }, { unique: true })
db.incidents.createIndex({ reportedBy: 1 })
db.incidents.createIndex({ department: 1 })
db.incidents.createIndex({ type: 1 })
db.incidents.createIndex({ severity: 1 })
db.incidents.createIndex({ status: 1 })
db.incidents.createIndex({ incidentDate: -1 })
// Maintenance Schedules
db.maintenanceschedules.createIndex({ machine: 1 })
db.maintenanceschedules.createIndex({ assignedTo: 1 })
db.maintenanceschedules.createIndex({ scheduledDate: 1 })
db.maintenanceschedules.createIndex({ status: 1 })This documentation provides a comprehensive overview of the IMSP Backend API. For additional support or questions, please refer to the project repository or contact the development team.
To configure the generation, complete these steps: