NUXT PRACTICAL 4: MONGODB CRUD OPERATIONS WITH EXPRESS
=================================================================

================================================

AIM:
Create a simple Express backend that performs Create, Read, Update and
Delete operations on MongoDB.

This practical has two folders:
- backend: Express and MongoDB API
- frontend: optional Nuxt page that calls the API

PROJECT STRUCTURE:
mongodb-crud/
|
|-- backend/
|   |-- server.js
|   |-- .env
|   |-- package.json
|
|-- frontend/
    |-- (Nuxt project files)
    |-- pages/
        |-- index.vue

PART A: BACKEND
---------------

STEP 1: Create backend folder and install packages
---------------------------------------------------
mkdir mongodb-crud
cd mongodb-crud
mkdir backend
cd backend
npm init -y
npm install express mongoose cors dotenv

STEP 2: backend/package.json
----------------------------
After running npm init -y, open package.json and make sure it contains
the following start script. Keep the installed dependencies too.

{
  "scripts": {
    "start": "node server.js"
  }
}

STEP 3: backend/.env
--------------------
For local MongoDB:

MONGO_URI=mongodb://127.0.0.1:27017/studentDB
PORT=5000

For MongoDB Atlas, use your own Atlas connection string instead:

MONGO_URI=mongodb+srv://USERNAME:PASSWORD@YOUR_CLUSTER.mongodb.net/studentDB
PORT=5000

IMPORTANT:
- Use only one MONGO_URI line.
- Do not write mongodb:mongodb+srv://.
- Replace the Atlas placeholders with your own details.
- Do not share your database password or upload .env to GitHub.
- Make sure local MongoDB is running, or your Atlas cluster is accessible.

STEP 4: backend/server.js
-------------------------
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
require('dotenv').config()

const app = express()

app.use(cors())
app.use(express.json())

// Connect to MongoDB
mongoose.connect(process.env.MONGO_URI)
  .then(() => console.log('MongoDB connected'))
  .catch(error => console.log('MongoDB error:', error.message))

// Create Student Schema and Model
const Student = mongoose.model('Student', {
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  course: {
    type: String,
    required: true
  }
})

// CREATE - Add a student
app.post('/students', async (req, res) => {
  try {
    const student = await Student.create(req.body)
    res.status(201).json(student)
  } catch (error) {
    res.status(400).json({ error: error.message })
  }
})

// READ - Get all students
app.get('/students', async (req, res) => {
  try {
    const students = await Student.find()
    res.json(students)
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
})

// UPDATE - Update a student by ID
app.put('/students/:id', async (req, res) => {
  try {
    const student = await Student.findByIdAndUpdate(
      req.params.id,
      req.body,
      { new: true, runValidators: true }
    )

    if (!student) {
      return res.status(404).json({ message: 'Student not found' })
    }

    res.json(student)
  } catch (error) {
    res.status(400).json({ error: error.message })
  }
})

// DELETE - Delete a student by ID
app.delete('/students/:id', async (req, res) => {
  try {
    const student = await Student.findByIdAndDelete(req.params.id)

    if (!student) {
      return res.status(404).json({ message: 'Student not found' })
    }

    res.json({ message: 'Student deleted successfully' })
  } catch (error) {
    res.status(400).json({ error: error.message })
  }
})

// Start server after MongoDB connects
mongoose.connection.once('open', () => {
  const PORT = process.env.PORT || 5000

  app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`)
  })
})

RUN BACKEND:
Open terminal inside backend folder and run:

npm start

API ENDPOINTS:
GET     http://localhost:5000/students
POST    http://localhost:5000/students
PUT     http://localhost:5000/students/STUDENT_ID
DELETE  http://localhost:5000/students/STUDENT_ID

Use Postman or Thunder Client to test POST, PUT and DELETE.

Example POST JSON:
{
  "name": "Amit",
  "email": "amit@example.com",
  "course": "Computer Science"
}

PART B: SIMPLE NUXT FRONTEND
----------------------------

Create a Nuxt project inside the mongodb-crud folder and name it frontend.
Run the Nuxt project on port 3000. Keep the Express backend on port 5000.

Example frontend/pages/index.vue:

<script setup>
const name = ref('')
const email = ref('')
const course = ref('')
const message = ref('')

const { data: students, refresh } = await useFetch(
  'http://localhost:5000/students'
)

async function addStudent() {
  message.value = ''

  try {
    await $fetch('http://localhost:5000/students', {
      method: 'POST',
      body: {
        name: name.value,
        email: email.value,
        course: course.value
      }
    })

    name.value = ''
    email.value = ''
    course.value = ''
    message.value = 'Student added successfully!'
    await refresh()
  } catch (error) {
    message.value = 'Could not add student.'
  }
}
</script>

<template>
  <div>
    <h1>Student CRUD App</h1>

    <form @submit.prevent="addStudent">
      <input v-model="name" placeholder="Name" required />
      <input v-model="email" type="email" placeholder="Email" required />
      <input v-model="course" placeholder="Course" required />
      <button type="submit">Add Student</button>
    </form>

    <p>{{ message }}</p>

    <h2>Students</h2>
    <div v-for="student in students" :key="student._id">
      <p>{{ student.name }} - {{ student.email }} - {{ student.course }}</p>
    </div>
  </div>
</template>

NOTE:
This frontend example demonstrates adding and listing students. The Express
backend contains all four CRUD endpoints. For a production app, keep API
addresses in runtime configuration and add authentication and validation.

CORS is enabled in the Express backend so the Nuxt page on port 3000 can
request the API on port 5000.


================================================
