From 8f7179726c8947f9159f7c61aeb87a81472a876a Mon Sep 17 00:00:00 2001 From: ramcharan032785-code Date: Mon, 2 Mar 2026 13:13:27 +0530 Subject: [PATCH] Add e-commerce starter with React and Spring Boot --- .gitignore | 4 + README.md | 33 +++ backend/pom.xml | 47 +++++ .../com/example/ecom/EcomApplication.java | 12 ++ .../main/java/com/example/ecom/Product.java | 3 + .../com/example/ecom/ProductController.java | 20 ++ .../src/main/resources/application.properties | 9 + frontend/index.html | 12 ++ frontend/package.json | 19 ++ frontend/src/App.jsx | 111 ++++++++++ frontend/src/main.jsx | 10 + frontend/src/styles.css | 191 ++++++++++++++++++ frontend/vite.config.js | 12 ++ 13 files changed, 483 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 backend/pom.xml create mode 100644 backend/src/main/java/com/example/ecom/EcomApplication.java create mode 100644 backend/src/main/java/com/example/ecom/Product.java create mode 100644 backend/src/main/java/com/example/ecom/ProductController.java create mode 100644 backend/src/main/resources/application.properties create mode 100644 frontend/index.html create mode 100644 frontend/package.json create mode 100644 frontend/src/App.jsx create mode 100644 frontend/src/main.jsx create mode 100644 frontend/src/styles.css create mode 100644 frontend/vite.config.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca5fb28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +frontend/dist/ +backend/target/ +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c0d089 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# E-Commerce Application + +This repository contains a simple e-commerce application with a React frontend, a Spring Boot backend, and a MySQL database configuration. + +## Frontend (React) + +```bash +cd frontend +npm install +npm run dev +``` + +The frontend expects the backend to run on `http://localhost:8080` and proxies `/api` requests via Vite. + +## Backend (Spring Boot) + +```bash +cd backend +./mvnw spring-boot:run +``` + +Update the MySQL credentials in `backend/src/main/resources/application.properties` before running the backend. + +## Database (MySQL) + +Example database setup: + +```sql +CREATE DATABASE ecom_db; +CREATE USER 'ecom_user'@'localhost' IDENTIFIED BY 'change_me'; +GRANT ALL PRIVILEGES ON ecom_db.* TO 'ecom_user'@'localhost'; +FLUSH PRIVILEGES; +``` diff --git a/backend/pom.xml b/backend/pom.xml new file mode 100644 index 0000000..45723fd --- /dev/null +++ b/backend/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.3 + + + + com.example + ecom-backend + 0.0.1-SNAPSHOT + ecom-backend + E-commerce API with Spring Boot + + + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.mysql + mysql-connector-j + runtime + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/backend/src/main/java/com/example/ecom/EcomApplication.java b/backend/src/main/java/com/example/ecom/EcomApplication.java new file mode 100644 index 0000000..6365711 --- /dev/null +++ b/backend/src/main/java/com/example/ecom/EcomApplication.java @@ -0,0 +1,12 @@ +package com.example.ecom; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class EcomApplication { + + public static void main(String[] args) { + SpringApplication.run(EcomApplication.class, args); + } +} diff --git a/backend/src/main/java/com/example/ecom/Product.java b/backend/src/main/java/com/example/ecom/Product.java new file mode 100644 index 0000000..fbb0ba2 --- /dev/null +++ b/backend/src/main/java/com/example/ecom/Product.java @@ -0,0 +1,3 @@ +package com.example.ecom; + +public record Product(Long id, String name, String description, double price) {} diff --git a/backend/src/main/java/com/example/ecom/ProductController.java b/backend/src/main/java/com/example/ecom/ProductController.java new file mode 100644 index 0000000..ca048da --- /dev/null +++ b/backend/src/main/java/com/example/ecom/ProductController.java @@ -0,0 +1,20 @@ +package com.example.ecom; + +import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/products") +public class ProductController { + + @GetMapping + public List getProducts() { + return List.of( + new Product(1L, "Lunar Running Shoes", "Lightweight sneakers with responsive cushioning.", 129.00), + new Product(2L, "Aurora Smartwatch", "Track workouts, sleep, and notifications in style.", 249.00), + new Product(3L, "Nebula Backpack", "Weather-resistant backpack with laptop sleeve.", 89.00) + ); + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties new file mode 100644 index 0000000..e1a1d82 --- /dev/null +++ b/backend/src/main/resources/application.properties @@ -0,0 +1,9 @@ +server.port=8080 + +spring.datasource.url=jdbc:mysql://localhost:3306/ecom_db +spring.datasource.username=ecom_user +spring.datasource.password=change_me +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..5dcd26d --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + NovaCart + + +
+ + + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..33fb8d0 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,19 @@ +{ + "name": "ecom-frontend", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.2.0", + "vite": "^5.0.0" + } +} diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..e53bb70 --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,111 @@ +import { useEffect, useState } from 'react'; + +const fallbackProducts = [ + { + id: 1, + name: 'Lunar Running Shoes', + price: 129.0, + description: 'Lightweight sneakers with responsive cushioning.' + }, + { + id: 2, + name: 'Aurora Smartwatch', + price: 249.0, + description: 'Track workouts, sleep, and notifications in style.' + }, + { + id: 3, + name: 'Nebula Backpack', + price: 89.0, + description: 'Weather-resistant backpack with laptop sleeve.' + } +]; + +export default function App() { + const [products, setProducts] = useState([]); + const [status, setStatus] = useState('Loading products...'); + + useEffect(() => { + const loadProducts = async () => { + try { + const response = await fetch('/api/products'); + if (!response.ok) { + throw new Error('Failed to load products'); + } + const data = await response.json(); + setProducts(data); + setStatus(''); + } catch (error) { + setProducts(fallbackProducts); + setStatus('Showing demo products. Connect the Spring Boot API for live data.'); + } + }; + + loadProducts(); + }, []); + + return ( +
+
+
+

NovaCart

+

Space-grade gear for everyday adventures.

+

+ Explore curated essentials across tech, travel, and lifestyle. Fast delivery, + flexible returns, and a seamless checkout experience. +

+
+ + +
+
+
+

Weekly spotlight

+

Save 15% on bundles with code ORBIT.

+
    +
  • Free shipping over $75
  • +
  • 2-year warranty included
  • +
  • 24/7 concierge support
  • +
+
+
+ +
+
+

Featured products

+ {status ? {status} : null} +
+
+ {products.map((product) => ( +
+
+ New +

{product.name}

+

{product.description}

+
+
+ ${product.price.toFixed(2)} + +
+
+ ))} +
+
+ +
+
+

Fast checkout, flexible payments.

+

+ Connect with Apple Pay, PayPal, or card-on-file. Keep your favorites in one + place and reorder in seconds. +

+
+
+ 1-click reorder + Live order tracking + Instant support +
+
+
+ ); +} diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx new file mode 100644 index 0000000..d78ecd4 --- /dev/null +++ b/frontend/src/main.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.jsx'; +import './styles.css'; + +ReactDOM.createRoot(document.getElementById('root')).render( + + + +); diff --git a/frontend/src/styles.css b/frontend/src/styles.css new file mode 100644 index 0000000..1e3e000 --- /dev/null +++ b/frontend/src/styles.css @@ -0,0 +1,191 @@ +:root { + font-family: 'Inter', system-ui, sans-serif; + color: #0b1220; + background-color: #f6f8fb; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; +} + +button { + font: inherit; + border: none; + cursor: pointer; +} + +.page { + display: flex; + flex-direction: column; + gap: 48px; + padding: 40px 72px 64px; +} + +.hero { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 32px; + align-items: center; + background: linear-gradient(120deg, #ffffff 0%, #f0f4ff 100%); + padding: 32px; + border-radius: 24px; + box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08); +} + +.eyebrow { + text-transform: uppercase; + letter-spacing: 0.2em; + font-weight: 600; + color: #5465ff; + margin-bottom: 12px; +} + +.hero h1 { + font-size: clamp(2rem, 3vw, 3.1rem); + margin: 0 0 16px; +} + +.subtitle { + font-size: 1.05rem; + color: #4b5563; + max-width: 480px; +} + +.cta-row { + display: flex; + gap: 16px; + margin-top: 24px; + flex-wrap: wrap; +} + +.primary { + background: #5465ff; + color: white; + padding: 12px 20px; + border-radius: 999px; +} + +.ghost { + background: white; + color: #111827; + padding: 12px 20px; + border-radius: 999px; + border: 1px solid #d1d5db; +} + +.hero-card { + background: white; + padding: 24px; + border-radius: 18px; + border: 1px solid #e5e7eb; +} + +.hero-card ul { + padding-left: 18px; + color: #4b5563; +} + +.section { + display: flex; + flex-direction: column; + gap: 24px; +} + +.section-header { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-items: center; + gap: 12px; +} + +.status { + font-size: 0.9rem; + color: #6b7280; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 20px; +} + +.card { + background: white; + padding: 20px; + border-radius: 16px; + border: 1px solid #e5e7eb; + display: flex; + flex-direction: column; + justify-content: space-between; + min-height: 200px; +} + +.card-top h3 { + margin: 12px 0 8px; +} + +.card-top p { + margin: 0; + color: #6b7280; +} + +.badge { + background: #e0e7ff; + color: #4338ca; + padding: 4px 10px; + border-radius: 999px; + font-size: 0.75rem; + font-weight: 600; +} + +.card-bottom { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 24px; +} + +.card-bottom button { + background: #111827; + color: white; + padding: 8px 14px; + border-radius: 10px; +} + +.price { + font-weight: 600; +} + +.section.dark { + background: #111827; + color: white; + padding: 32px; + border-radius: 20px; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 24px; +} + +.pill-row { + display: flex; + gap: 12px; + flex-wrap: wrap; + align-items: center; +} + +.pill-row span { + background: rgba(255, 255, 255, 0.12); + padding: 8px 14px; + border-radius: 999px; +} + +@media (max-width: 720px) { + .page { + padding: 24px; + } +} diff --git a/frontend/vite.config.js b/frontend/vite.config.js new file mode 100644 index 0000000..d1ce38d --- /dev/null +++ b/frontend/vite.config.js @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + server: { + port: 5173, + proxy: { + '/api': 'http://localhost:8080' + } + } +});