Skip to main content

Overview

The Production Inspection Form is a Next.js-based technical inspection system designed for manufacturing environments. It provides a comprehensive digital solution for conducting equipment inspections, tracking technician assessments, and maintaining detailed inspection records.

User Authentication

Secure login system with user session management and credential storage

Dynamic Forms

Auto-populated inspection forms based on equipment category

Equipment Management

Hierarchical organization of divisions, areas, zones, and equipment

Real-time API Integration

Seamless backend connectivity for data retrieval and submission

Authentication System

The application implements a robust authentication mechanism with persistent sessions.

Key Features

  • LocalStorage-based Session Management: User credentials are stored securely in browser storage
  • Protected Routes: Automatic redirection to login for unauthenticated users
  • Session Persistence: Users remain logged in across page refreshes
  • Logout Functionality: Clean session termination with storage cleanup

Implementation Details

// Authentication check on page load
useEffect(() => {
  let usuario = localStorage.getItem("usuario_inspeccion");
  let nombre = localStorage.getItem("usuario_nombre");
  
  if (usuario) {
    setUsuarioActual(nombre || usuario);
  } else {
    let currentUrl = window.location.href;
    localStorage.setItem("redirect_after_login", currentUrl);
    router.push("/login");
  }
}, []);
The system automatically saves the current URL before redirecting to login, enabling seamless return to the intended page after authentication.

Login Flow

The login page (/login) provides a simple, clean interface:
  • Username and password input fields
  • Form validation with required field checking
  • Credential submission to backend API
  • Automatic redirection upon successful authentication

Dynamic Inspection Forms

The core functionality centers around intelligent, context-aware inspection forms that adapt based on equipment selection.

Hierarchical Data Structure

The form utilizes a four-level organizational hierarchy:

Division

Top-level organizational unit

Area

Subdivision within a division

Zone

Specific location within an area

Equipment

Individual machinery or asset

Auto-Population Logic

// Equipment selection triggers automatic field population
useEffect(() => {
  if (!apiUrl) return;
  
  // Fetch all hierarchical data
  Promise.all([
    fetch(`${apiUrl}/api/divisiones/`).then(res => res.json()).catch(() => []),
    fetch(`${apiUrl}/api/areas/`).then(res => res.json()).catch(() => []),
    fetch(`${apiUrl}/api/zonas/`).then(res => res.json()).catch(() => []),
    fetch(`${apiUrl}/api/equipos/`).then(res => res.json()).catch(() => [])
  ]).then(([divs, areas, zonas, equipos]) => {
    setDivisiones(divs);
    setAreas(areas);
    setZonas(zonas);
    setEquipos(equipos);
  });
  
  // Pre-populate from URL parameter
  let equipoId = searchParams.get("equipo");
  if (equipoId) {
    // Fetch equipment details and auto-fill form
    fetch(`${apiUrl}/api/equipos/`)
      .then(res => res.json())
      .then(equipos => {
        let equipo = equipos.find(e => String(e.id) === String(equipoId));
        if (equipo) {
          setFormData(prev => ({
            ...prev,
            division: equipo.division_id,
            area: equipo.area_id,
            zona: equipo.zona_id
          }));
          setUbicacionFisica(equipo.ubicacion);
          setCategoria(equipo.categoria);
        }
      });
  }
}, [apiUrl]);
Equipment can be pre-selected via URL query parameter (?equipo=123), enabling QR code scanning workflows where equipment IDs are embedded in scannable codes.

Category-Based Question Loading

One of the most powerful features is the dynamic loading of inspection questions based on equipment category.

How It Works

  1. Equipment Selection: User selects or scans equipment
  2. Category Identification: System retrieves equipment category from API
  3. Question Fetch: Relevant questions loaded dynamically
  4. Table Generation: Inspection checklist rendered automatically

Question Table Interface

// Dynamic question loading based on category
if (equipo.categoria) {
  fetch(`${apiUrl}/api/preguntas/${equipo.categoria}/`)
    .then(res => res.json())
    .then(setPreguntas)
    .catch(err => console.error("Error cargando preguntas", err));
}
The inspection table displays:
  • Inspection Item: Description of what needs to be checked
  • OK: Radio button for passing inspection
  • NOK: Radio button for failing inspection
  • No aplica (N/A): Radio button for non-applicable items
Each inspection point is rendered as a radio button group, ensuring only one status can be selected per item.

Response Handling

// Store technician responses
const handleTecnicoChange = (pregunta, valor) => {
  setFormData(prev => ({
    ...prev,
    tecnicos: {
      ...prev.tecnicos,
      [pregunta]: valor
    }
  }));
};

// Usage in the table
<input
  type="radio"
  name={`pregunta-${pregunta.id}`}
  value="OK"
  checked={formData.tecnicos[pregunta.descripcion] === "OK"}
  onChange={() => handleTecnicoChange(pregunta.descripcion, "OK")}
/>

Time Tracking

The system automatically captures inspection timing for audit and performance analysis.

Automatic Timestamp Generation

// Set start time on form load
useEffect(() => {
  if (!apiUrl) return;
  
  const now = new Date();
  const horaInicio = now.toTimeString().split(" ")[0];
  
  setFormData(prev => ({
    ...prev,
    fecha: now.toISOString().split("T")[0],
    horaInicio: horaInicio
  }));
}, [apiUrl]);

// Set end time on form submission
const handleSubmit = async (e) => {
  e.preventDefault();
  
  const horaFin = new Date().toTimeString().split(" ")[0];
  const payload = {
    ...formData,
    horaFin: horaFin,
    usuario: usuarioActual
  };
  
  // Submit to API
  await fetch(`${apiUrl}/api/guardar/`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload)
  });
};
Tracked Timestamps:
  • Fecha (Date): Auto-filled with current date
  • Hora de Inicio (Start Time): Captured when form loads
  • Hora de Fin (End Time): Captured when form is submitted

Equipment Information Display

The form provides comprehensive equipment context to technicians during inspection.

Displayed Information

FieldDescriptionSource
DivisiónOrganizational divisionAPI - divisions endpoint
ÁreaFunctional areaAPI - areas endpoint
ZonaPhysical zoneAPI - zones endpoint
EquipoEquipment name/IDAPI - equipment endpoint
Ubicación FísicaPhysical location detailsEquipment record
Categoría del EquipoEquipment category typeEquipment record

Read-Only Context Fields

// All hierarchy fields are disabled (read-only) after auto-population
<select value={formData.division} disabled>
  {divisiones.map(div => (
    <option key={div.id} value={div.id}>
      {div.nombre}
    </option>
  ))}
</select>
Hierarchy fields (division, area, zone, equipment) are automatically populated and locked to prevent accidental modification during inspection.

Observations and Notes

Technicians can document additional findings, anomalies, or recommendations.

Observations Field

<label>Observaciones:</label>
<textarea
  value={formData.observaciones}
  onChange={(e) => setFormData({
    ...formData,
    observaciones: e.target.value
  })}
  rows={4}
/>
Use Cases:
  • Documenting visual defects not covered by checklist
  • Recording unusual noises or behaviors
  • Noting required follow-up actions
  • Adding maintenance recommendations

Form Submission

The submission process includes validation, payload construction, and backend synchronization.

Submission Workflow

const handleSubmit = async (e) => {
  e.preventDefault();
  if (!apiUrl) return;
  
  // Capture end time
  const horaFin = new Date().toTimeString().split(" ")[0];
  
  // Construct complete payload
  const payload = {
    ...formData,
    horaFin: horaFin,
    usuario: usuarioActual
  };
  
  try {
    // POST to backend API
    const response = await fetch(`${apiUrl}/api/guardar/`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload)
    });
    
    const data = await response.json();
    
    // Display success message
    setMensaje(data.message || "Formulario enviado correctamente");
    
    // Reset form for next inspection
    setFormData({
      fecha: "", horaInicio: "", horaFin: "",
      division: "", area: "", zona: "", equipo: "",
      observaciones: "", tecnicos: {}
    });
    setCategoria("");
    setUbicacionFisica("");
    setPreguntas([]);
    
  } catch (error) {
    console.error(error);
    setMensaje("Error al enviar");
  }
};

Payload Structure

{
  "fecha": "2026-03-06",
  "horaInicio": "09:15:30",
  "horaFin": "09:28:45",
  "division": "1",
  "area": "2",
  "zona": "3",
  "equipo": "45",
  "observaciones": "Equipment running normally, minor oil leak detected on seal",
  "usuario": "john.smith",
  "tecnicos": {
    "Check oil level": "OK",
    "Inspect belts for wear": "NOK",
    "Verify pressure gauges": "OK",
    "Check for leaks": "NOK",
    "Test emergency stop": "OK"
  }
}
The tecnicos object contains all inspection responses, with question descriptions as keys and status values (OK/NOK/NA) as values.

User Interface Features

Responsive Design

The application uses responsive CSS with mobile-first approach:
.container {
  max-width: 850px;
  margin: 1rem auto;
  background: #fff;
  padding: 1.2rem;
  border-radius: 12px;
  font-family: "Segoe UI", sans-serif;
  color: #1a1a1a;
  border: 3px solid #FFD200;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
}

Branding Elements

  • Logo Display: Goodyear logo prominently featured
  • Brand Colors: #003399 (blue) and #FFD200 (yellow)
  • Custom Styling: Consistent color scheme throughout interface

Top Bar Components

<div className="top-bar">
  <div className="usuario-label">
    Usuario: {usuarioActual}
  </div>
  <button onClick={handleLogout} className="logout-button">
    Cerrar Sesión
  </button>
</div>
Features:
  • Current user display
  • Logout button with hover effects
  • Aligned to the right for easy access

API Integration

Endpoints

The application integrates with the following API endpoints:
EndpointMethodPurpose
/api/divisiones/GETFetch all divisions
/api/areas/GETFetch all areas
/api/zonas/GETFetch all zones
/api/equipos/GETFetch all equipment
/api/preguntas/{categoria}/GETFetch questions for category
/api/guardar/POSTSubmit inspection form

Error Handling

// Graceful degradation with empty arrays
Promise.all([
  fetch(`${apiUrl}/api/divisiones/`)
    .then(res => res.json())
    .catch(() => []),  // Return empty array on failure
  // ... other endpoints
]).then(([divs, areas, zonas, equipos]) => {
  setDivisiones(divs);
  setAreas(areas);
  setZonas(zonas);
  setEquipos(equipos);
});
The application implements graceful error handling, returning empty arrays when API calls fail to prevent UI crashes.

Loading States

The application uses React Suspense for loading state management:
export default function InspeccionPage() {
  return (
    <Suspense fallback={
      <div style={{
        textAlign: "center",
        paddingTop: "2rem",
        color: "#003399"
      }}>
        Cargando formulario...
      </div>
    }>
      <FormularioInspeccion />
    </Suspense>
  );
}

Client-Side Rendering

The form uses client-side rendering with a loading placeholder:
<div style="text-align:center;padding-top:2rem;color:#003399">
  Cargando formulario...
</div>

Internationalization

The application is built in Spanish (language: “es”):
  • All UI text in Spanish
  • Field labels in Spanish
  • Status messages in Spanish
  • Button text in Spanish
The codebase is currently monolingual (Spanish). Internationalization would require implementing i18n libraries like next-intl or react-i18next.

Technical Stack

Next.js

React framework with App Router

React Hooks

useState, useEffect, Suspense

Styled JSX

Component-scoped CSS styling

Fetch API

RESTful API communication

LocalStorage

Client-side session persistence

URL Search Params

Query parameter handling

Key Benefits

For Technicians

  • ✅ Streamlined inspection workflow
  • ✅ No manual equipment lookup required
  • ✅ Clear checklist format prevents missed items
  • ✅ Quick form submission with minimal typing

For Management

  • ✅ Standardized inspection data format
  • ✅ Automatic timestamp capture for compliance
  • ✅ User accountability through login system
  • ✅ Comprehensive audit trail

For Operations

  • ✅ Real-time data submission
  • ✅ Equipment-specific question sets
  • ✅ Reduced training time (intuitive interface)
  • ✅ Mobile-friendly for shop floor use

Next Steps

Getting Started

Learn how to deploy and configure the application

Technical Reference

Explore the backend API endpoints and data models

User Guide

Step-by-step instructions for conducting inspections

Troubleshooting

Common issues and solutions

Build docs developers (and LLMs) love