Spring Boot project specifictions (2 wheeler service)

Two‑Wheeler Service Worksheet Application

Full‑Stack Guide: Spring Boot + MySQL + React + Tailwind


1. Backend – Spring Boot + MySQL

1.1 Entities

Customer.java

import jakarta.persistence.*;

 

@Entity

@Table(name = "customer")

public class Customer {

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

 

    private String name;

    private String phone;

    private String email;

 

    // getters and setters

}

Vehicle.java

import jakarta.persistence.*;

 

@Entity

@Table(name = "vehicle")

public class Vehicle {

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

 

    private String regNumber;

    private String brand;

    private String model;

 

    @ManyToOne

    @JoinColumn(name = "customer_id")

    private Customer customer;

 

    // getters and setters

}

ServiceWorksheet.java

import jakarta.persistence.*;

import java.time.LocalDate;

 

@Entity

@Table(name = "service_worksheet")

public class ServiceWorksheet {

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

 

    @ManyToOne

    @JoinColumn(name = "vehicle_id")

    private Vehicle vehicle;

 

    private LocalDate serviceDate;

    private String issuesReported;

    private String workDone;

    private String partsReplaced;

    private Double cost;

 

    // getters and setters

}


1.2 Repository Layer

public interface CustomerRepository extends JpaRepository<Customer, Long> {}

public interface VehicleRepository extends JpaRepository<Vehicle, Long> {}

public interface ServiceWorksheetRepository extends JpaRepository<ServiceWorksheet, Long> {}

1.3 Service Layer

@Service

public class WorksheetService {

    @Autowired private ServiceWorksheetRepository repo;

 

    public ServiceWorksheet createWorksheet(ServiceWorksheet ws) {

        return repo.save(ws);

    }

    public List<ServiceWorksheet> getAllWorksheets() {

        return repo.findAll();

    }

}

1.4 Controller Layer

@RestController

@RequestMapping("/api/worksheets")

public class WorksheetController {

    @Autowired private WorksheetService service;

 

    @PostMapping

    public ServiceWorksheet addWorksheet(@RequestBody ServiceWorksheet ws) {

        return service.createWorksheet(ws);

    }

 

    @GetMapping

    public List<ServiceWorksheet> getWorksheets() {

        return service.getAllWorksheets();

    }

}


2. Database Configuration

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/two_wheeler_service

spring.datasource.username=root

spring.datasource.password=yourpassword

 

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

spring.jpa.properties.hibernate.format_sql=true

🔑 Key Point

  • spring.jpa.hibernate.ddl-auto=update + @Entity annotations = automatic table creation.
  • You must manually create the database schema once:

·         CREATE DATABASE two_wheeler_service;


3. Sample Data Seeding

Option A: data.sql

INSERT INTO customer (name, phone, email) VALUES ('Ravi Kumar', '9876543210', 'ravi@example.com');

INSERT INTO customer (name, phone, email) VALUES ('Priya Sharma', '9123456780', 'priya@example.com');

 

INSERT INTO vehicle (reg_number, brand, model, customer_id) VALUES ('TN09AB1234', 'Honda', 'Activa', 1);

INSERT INTO vehicle (reg_number, brand, model, customer_id) VALUES ('TN10XY5678', 'Yamaha', 'FZ', 2);

 

INSERT INTO service_worksheet (vehicle_id, service_date, issues_reported, work_done, parts_replaced, cost)

VALUES (1, '2026-06-28', 'Brake noise', 'Brake pad replaced', 'Brake pads', 1200.00);

Option B: CommandLineRunner

@Bean

CommandLineRunner initData(CustomerRepository customerRepo, VehicleRepository vehicleRepo, ServiceWorksheetRepository wsRepo) {

    return args -> {

        Customer c1 = customerRepo.save(new Customer(null, "Ravi Kumar", "9876543210", "ravi@example.com"));

        Vehicle v1 = vehicleRepo.save(new Vehicle(null, "TN09AB1234", "Honda", "Activa", c1));

        wsRepo.save(new ServiceWorksheet(null, v1, LocalDate.now(), "Brake noise", "Brake pad replaced", "Brake pads", 1200.0));

    };

}


4. Frontend – React + Tailwind

4.1 Setup

npm create vite@latest service-worksheet-ui --template react

cd service-worksheet-ui

npm install axios tailwindcss @tailwindcss/vite

vite.config.js

import { defineConfig } from 'vite'

import react from '@vitejs/plugin-react'

import tailwindcss from '@tailwindcss/vite'

 

export default defineConfig({

  plugins: [react(), tailwindcss()],

})

index.css

@import "tailwindcss";


4.2 Components

WorksheetForm.jsx

import { useState } from "react";

import axios from "axios";

 

export default function WorksheetForm({ onAdded }) {

  const [form, setForm] = useState({ vehicleId:"", issuesReported:"", workDone:"", partsReplaced:"", cost:"" });

 

  const handleSubmit = async (e) => {

    e.preventDefault();

    await axios.post("http://localhost:8080/api/worksheets", form);

    onAdded();

  };

 

  return (

    <form onSubmit={handleSubmit} className="p-4 bg-white shadow rounded space-y-3">

      <input className="border p-2 w-full" placeholder="Vehicle ID"

             onChange={e=>setForm({...form, vehicleId:e.target.value})}/>

      <textarea className="border p-2 w-full" placeholder="Issues Reported"

             onChange={e=>setForm({...form, issuesReported:e.target.value})}/>

      <textarea className="border p-2 w-full" placeholder="Work Done"

             onChange={e=>setForm({...form, workDone:e.target.value})}/>

      <input className="border p-2 w-full" placeholder="Parts Replaced"

             onChange={e=>setForm({...form, partsReplaced:e.target.value})}/>

      <input className="border p-2 w-full" placeholder="Cost"

             onChange={e=>setForm({...form, cost:e.target.value})}/>

      <button className="bg-blue-500 text-white px-4 py-2 rounded">Save</button>

    </form>

  );

}

WorksheetList.jsx

import { useEffect, useState } from "react";

import axios from "axios";

 

export default function WorksheetList() {

  const [worksheets, setWorksheets] = useState([]);

 

  useEffect(() => {

    axios.get("http://localhost:8080/api/worksheets")

         .then(res => setWorksheets(res.data));

  }, []);

 

  return (

    <table className="table-auto w-full border-collapse border">

      <thead>

        <tr className="bg-gray-200">

          <th className="border px-2">Vehicle ID</th>

          <th className="border px-2">Issues</th>

          <th className="border px-2">Work Done</th>

          <th className="border px-2">Parts</th>

          <th className="border px-2">Cost</th>

        </tr>

      </thead>

      <tbody>

        {worksheets.map(ws => (

          <tr key={ws.id}>

            <td className="border px-2">{ws.vehicle.id}</td>

            <td className="border px-2">{ws.issuesReported}</td>

            <td className="border px-2">{ws.workDone}</td>

            <td className="border px-2">{ws.partsReplaced}</td>

            <td className="border px-2">{ws.cost}</td>

          </tr>

        ))}

      </tbody>

    </table>

  );

}


5. Integration

  • Backend: http://localhost:8080
  • Frontend: http://localhost:5173
  • Enable CORS in Spring Boot:

@CrossOrigin(origins="http://localhost:5173")


6. Next Steps

  • Add authentication (Spring Security + JWT).
  • Expand worksheet with status (Pending, Completed).
  • Generate PDF invoice from worksheet.
  • Add search/filter for vehicles and customers.

 

Comments

Popular Posts