https://pastein.ru/t/H1s

  скопируйте уникальную ссылку для отправки

Загрузка данных


CONTROLLERS
const db = require('../db.js');

class CarController{
    async createCar(req, res){
        const {name, description, price, img} = req.body;
        const newCar = await db.query(`INSERT INTO cars (name, description, price, img)
            VALUES ($1, $2, $3, $4) RETURNING *`, [name, description, price, img]);
        res.json(newCar.rows[0]);
    }
    async getCars(req, res){
        const cars = await db.query(`SELECT id, name, description, price, img FROM cars`);
        res.json(cars.rows);
    }
    async getCar(req, res){
        const id = req.params.id;
        const car = await db.query(`SELECT id, name, description, price, img FROM cars 
                                    WHERE id = $1`, [id]);
        res.json(car.rows[0]);
    }
    async updateCar(req, res){
        const {id, name, description, price, img} = req.body;
        const car = await db.query(`UPDATE cars SET name=$1, description=$2, price=$3, img=$4 
                                    WHERE id = $5 RETURNING *`, [name, description, price, img, id]);
        res.json(car.rows[0]);
    }
    async deleteCar(req, res){
        const id = req.params.id;
        await db.query(`DELETE FROM cars WHERE id = $1`, [id]);
    }
}
module.exports = new CarController();

components
car.model
export function createItem(name, description, price, img){
    let item = document.createElement('div');
    let image = document.createElement('img');
    let body = document.createElement('div');
    let h5 = document.createElement('h5');
    let pDescription = document.createElement('p');
    let pPrice = document.createElement('p');

    let btnGroup = document.createElement('div');
    let btnDetail = document.createElement('button');
    let btnDelete = document.createElement('button');

    //зададим стили
    item.classList.add('card', 'm-3');
    item.style.width = '18rem';
    item.style.float = 'left';

    image.classList.add('card-img-top');
    image.src = img;

    body.classList.add('card-body');

    h5.classList.add('card-title');
    h5.innerText = name;

    pDescription.classList.add('card-text');
    pDescription.innerText = description;

    pPrice.innerText = price;

    btnGroup.classList.add('btn-group', 'float-end');

    btnDetail.classList.add('btn', 'btn-primary');
    btnDetail.textContent = 'Подробнее';

    btnDelete.classList.add('btn', 'btn-danger');
    btnDelete.textContent = 'Удалить';

    //вложим элемемнты друг в друга
    btnGroup.append(btnDetail, btnDelete);
    body.append(h5, pDescription, pPrice, btnGroup);
    item.append(image, body);

    //вернем результат
    return {item, btnDetail, btnDelete};
}

main
import { getAllCars, addCar, deleteCar } from "../requests/car.requests.js";
import { createItem } from "./components/item.js";

let list = document.getElementById('car-list');

async function elementsGenerator() {
    const cars = await getAllCars();
    for (let car of cars){
        let listItem = createItem(car.name, car.description, car.price, car.img);
        listItem.btnDetail.addEventListener('click', ()=>{
            window.location.href = '/car/' + car.id;
        });
        listItem.btnDelete.addEventListener('click', ()=>{
            if(confirm('Вы действительно хотите удалить?')){
                deleteCar(car.id);
                listItem.item.remove();
            }
        })
        list.appendChild(listItem.item);
    }
}

document.addEventListener('DOMContentLoaded', async ()=>{
    await elementsGenerator();

    let form = document.getElementById('add-form');
    form.addEventListener('submit', async (e)=>{
        e.preventDefault();

        let carName = document.getElementById('car-name');
        let carDescription = document.getElementById('car-description');
        let carPrice = document.getElementById('car-price');
        let carImg = document.getElementById('car-img');

        let listItem = createItem(carName.value, carDescription.value, carPrice.value, carImg.value);
        await addCar(carName.value, carDescription.value, carPrice.value, carImg.value);
        list.appendChild(listItem.item);
    })
});

singecar
import { getOneCar } from "../requests/car.requests.js";

document.addEventListener('DOMContentLoaded', async ()=>{
    let carId =  window.location.pathname.split('/').pop();
    console.log(carId);

    let car = await getOneCar(carId);

    console.log(car.name);
    document.getElementById('car-img').src = car.img;
    document.getElementById('car-name').innerText = car.name;
    document.getElementById('car-description').innerText = car.description;
    document.getElementById('car-price').innerText = car.price;
})

requests
car.requests
async function getAllCars(){
    const responce = await fetch('/api/car', {
        method: 'GET'
    });
    const result = await responce.json();
    return result;
}
async function getOneCar(id){
    const responce = await fetch('/api/car/' + id, {
        method: 'GET'
    });
    const result = await responce.json();
    return result;
}
async function addCar(name, description, price, img){
    await fetch('/api/car', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
            name: name,
            description: description,
            price: price,
            img: img
        })
    });
}
async function deleteCar(id){
    await fetch('/api/car/' + id, {
        method: 'DELETE'
    });
}
async function updateCar(id, name, description, price, img){
    await fetch('/api/car', {
        method: 'PUT',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
            id: id,
            name: name,
            description: description,
            price: price,
            img: img
        })
    });
}
export {getAllCars, getOneCar, deleteCar, updateCar, addCar}

routes
car.routes
const Router = require('express');
const router = Router();
const carController = require('../controllers/car.controller.js');

router.post('/api/car', carController.createCar);
router.get('/api/car', carController.getCars);
router.get('/api/car/:id', carController.getCar);
router.delete('/api/car/:id', carController.deleteCar);
router.put('/api/car', carController.updateCar);

module.exports = router;

static html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Client-server app</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <script type="module" src="../frontend/main.js"></script>
</head>
<body>
    <div class="container">
        <form id="add-form" class="row g-3">
            <div class="col-md-6">
              <input type="text" class="form-control" id="car-name" placeholder="Название автомобиля">
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" id="car-price" placeholder="Цена">
            </div>
            <div class="col-12">
              <input type="text" class="form-control" id="car-description" placeholder="Описание">
            </div>
            <div class="col-12">
                <input type="text" class="form-control" id="car-img" placeholder="Вставьте ссылку на фото">
            </div>
            <div class="col-12">
              <button type="submit" class="btn btn-primary">Добавить</button>
            </div>
          </form>

          <div class="row mt-5 mb-2" id="car-list">
                <!--Тут будут генерироваться элементы-->
          </div>
    </div>
</body>
</html>

singlecar
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
    <script type="module" src="../frontend/singecar.js"></script>
</head>
<body>
    <div class="card mb-3" style="max-width: 540px;">
        <div class="row g-0">
          <div class="col-md-4">
            <img class="img-fluid rounded-start" id="car-img">
          </div>
          <div class="col-md-8">
            <div class="card-body">
              <h5 class="card-title" id="car-name"></h5>
              <p class="card-text" id="car-description"></p>
              <p class="card-text" id="car-price"></p>
            </div>
          </div>
        </div>
      </div>
</body>
</html>

database
CREATE TABLE cars (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255),
    description VARCHAR(255),
    price VARCHAR(255),
    img VARCHAR(255)
);

db.js
const Pool = require('pg').Pool;
const pool = new Pool({
    user: "postgres",
    password: "root",
    host: "localhost",
    port: 5432,
    database: "testis31"
});
module.exports = pool;

index.js
const express = require('express');
const PORT = process.env.PORT || 8080;
const carRouter = require('./routes/car.routes.js');
const app = express();

app.use(express.json());
app.use(carRouter);
app.use(express.static(__dirname));

app.get('/', (req, res)=>{
    res.sendFile(__dirname + '/static/index.html');
})
app.get('/car/:id', (req, res)=>{
    res.sendFile(__dirname + '/static/singlecar.html');
})
app.get('/help', (req, res)=>{
    res.send('Hello from help');
})

app.listen(PORT, ()=>console.log(`Сервер запущен на порту ${PORT}...`))