Added db and more routes
This commit is contained in:
parent
2ea38ef091
commit
17e918da47
|
|
@ -0,0 +1,21 @@
|
||||||
|
import pg from "pg";
|
||||||
|
import "dotenv/config";
|
||||||
|
|
||||||
|
const { Pool } = pg;
|
||||||
|
|
||||||
|
const baseConfig = {};
|
||||||
|
|
||||||
|
baseConfig.host = process.env.PGHOST || "127.0.0.1";
|
||||||
|
baseConfig.port = Number(process.env.PGPORT || 5432);
|
||||||
|
baseConfig.user = process.env.PGUSER || "postgres";
|
||||||
|
baseConfig.password = process.env.PGPASSWORD || "postgres";
|
||||||
|
baseConfig.database = process.env.PGDATABASE || "postgres";
|
||||||
|
|
||||||
|
console.log("Base Config:", baseConfig);
|
||||||
|
const pool = new Pool(baseConfig);
|
||||||
|
|
||||||
|
pool.on("error", (err) => {
|
||||||
|
console.error("Unexpected Postgres client error", err);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default pool;
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
-- Livestock Marketplace schema (PostgreSQL)
|
||||||
|
-- Generated from specs in README.md
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
phone VARCHAR(50) UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS species (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(100) UNIQUE NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS breeds (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
species_id INT NOT NULL REFERENCES species(id) ON DELETE RESTRICT,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS locations (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||||
|
is_saved_address BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
location_type VARCHAR(50),
|
||||||
|
country VARCHAR(100),
|
||||||
|
state VARCHAR(100),
|
||||||
|
district VARCHAR(100),
|
||||||
|
city_village VARCHAR(150),
|
||||||
|
pincode VARCHAR(20),
|
||||||
|
lat DECIMAL(10,7),
|
||||||
|
lng DECIMAL(10,7),
|
||||||
|
source_type VARCHAR(50) NOT NULL DEFAULT 'unknown',
|
||||||
|
source_confidence VARCHAR(50) NOT NULL DEFAULT 'medium',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS animals (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
species_id INT NOT NULL REFERENCES species(id) ON DELETE RESTRICT,
|
||||||
|
breed_id INT REFERENCES breeds(id) ON DELETE SET NULL,
|
||||||
|
sex VARCHAR(20) NOT NULL,
|
||||||
|
age_months INT,
|
||||||
|
weight_kg DECIMAL(10,2),
|
||||||
|
color_markings VARCHAR(200),
|
||||||
|
quantity INT NOT NULL DEFAULT 1,
|
||||||
|
purpose VARCHAR(50) NOT NULL,
|
||||||
|
health_status VARCHAR(50) NOT NULL,
|
||||||
|
vaccinated BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
dewormed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
previous_pregnancies_count INT,
|
||||||
|
pregnancy_status VARCHAR(50),
|
||||||
|
milk_yield_litre_per_day DECIMAL(10,2),
|
||||||
|
ear_tag_no VARCHAR(100),
|
||||||
|
description TEXT,
|
||||||
|
suggested_care TEXT,
|
||||||
|
location_id UUID REFERENCES locations(id) ON DELETE SET NULL,
|
||||||
|
created_from VARCHAR(50) NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS listings (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
seller_id UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||||
|
animal_id UUID NOT NULL UNIQUE REFERENCES animals(id) ON DELETE CASCADE,
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
price NUMERIC(12,2) NOT NULL,
|
||||||
|
currency VARCHAR(10) NOT NULL,
|
||||||
|
is_negotiable BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
listing_type VARCHAR(50) NOT NULL,
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'active',
|
||||||
|
listing_score INT NOT NULL DEFAULT 0,
|
||||||
|
views_count INT NOT NULL DEFAULT 0,
|
||||||
|
bookmarks_count INT NOT NULL DEFAULT 0,
|
||||||
|
enquiries_call_count INT NOT NULL DEFAULT 0,
|
||||||
|
enquiries_whatsapp_count INT NOT NULL DEFAULT 0,
|
||||||
|
clicks_count INT NOT NULL DEFAULT 0,
|
||||||
|
listing_score_status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS listing_media (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
listing_id UUID NOT NULL REFERENCES listings(id) ON DELETE CASCADE,
|
||||||
|
media_url VARCHAR(500) NOT NULL,
|
||||||
|
media_type VARCHAR(50) NOT NULL,
|
||||||
|
is_primary BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
sort_order INT NOT NULL DEFAULT 0,
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS custom_requirements (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||||
|
requirement_text TEXT NOT NULL,
|
||||||
|
animal_id UUID REFERENCES animals(id) ON DELETE SET NULL,
|
||||||
|
status VARCHAR(50) NOT NULL DEFAULT 'open',
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^17.2.3",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"pg": "^8.16.3"
|
"pg": "^8.16.3"
|
||||||
}
|
}
|
||||||
|
|
@ -156,6 +157,17 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "17.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
||||||
|
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dunder-proto": {
|
"node_modules/dunder-proto": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
"homepage": "https://github.com/schari2509/BuySellService_LivingAI#readme",
|
"homepage": "https://github.com/schari2509/BuySellService_LivingAI#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^17.2.3",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"pg": "^8.16.3"
|
"pg": "^8.16.3"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
const router = express.Router();
|
import pool from "../db/pool.js";
|
||||||
import { Pool } from "pg";
|
|
||||||
|
|
||||||
const pool = new Pool({
|
const router = express.Router();
|
||||||
user: process.env.DB_USER,
|
|
||||||
host: process.env.DB_HOST,
|
|
||||||
database: process.env.DB_NAME,
|
|
||||||
password: process.env.DB_PASSWORD_D,
|
|
||||||
port: process.env.DB_PORT,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get all listings
|
// Get all listings
|
||||||
router.get("/", async (req, res) => {
|
router.get("/", async (req, res) => {
|
||||||
|
|
@ -19,37 +12,43 @@ router.get("/", async (req, res) => {
|
||||||
const minPrice = req.query.min_price;
|
const minPrice = req.query.min_price;
|
||||||
const listingType = req.query.listing_type;
|
const listingType = req.query.listing_type;
|
||||||
|
|
||||||
let baseQuery = "SELECT * FROM listings WHERE 1=1";
|
let baseQuery = `
|
||||||
|
SELECT l.*, a.species_id, a.breed_id, loc.state, loc.district
|
||||||
|
FROM listings l
|
||||||
|
LEFT JOIN animals a ON a.id = l.animal_id
|
||||||
|
LEFT JOIN locations loc ON loc.id = a.location_id
|
||||||
|
WHERE 1=1
|
||||||
|
`;
|
||||||
const queryParams = [];
|
const queryParams = [];
|
||||||
let paramIndex = 1;
|
let paramIndex = 1;
|
||||||
|
|
||||||
if (speciesId) {
|
if (speciesId) {
|
||||||
baseQuery += ` AND species_id = $${paramIndex}`;
|
baseQuery += ` AND a.species_id = $${paramIndex}`;
|
||||||
queryParams.push(speciesId);
|
queryParams.push(speciesId);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
if (breedId) {
|
if (breedId) {
|
||||||
baseQuery += ` AND breed_id = $${paramIndex}`;
|
baseQuery += ` AND a.breed_id = $${paramIndex}`;
|
||||||
queryParams.push(breedId);
|
queryParams.push(breedId);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
if (state) {
|
if (state) {
|
||||||
baseQuery += ` AND state = $${paramIndex}`;
|
baseQuery += ` AND loc.state = $${paramIndex}`;
|
||||||
queryParams.push(state);
|
queryParams.push(state);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
if (district) {
|
if (district) {
|
||||||
baseQuery += ` AND district = $${paramIndex}`;
|
baseQuery += ` AND loc.district = $${paramIndex}`;
|
||||||
queryParams.push(district);
|
queryParams.push(district);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
if (minPrice) {
|
if (minPrice) {
|
||||||
baseQuery += ` AND price >= $${paramIndex}`;
|
baseQuery += ` AND l.price >= $${paramIndex}`;
|
||||||
queryParams.push(minPrice);
|
queryParams.push(minPrice);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
if (listingType) {
|
if (listingType) {
|
||||||
baseQuery += ` AND listing_type = $${paramIndex}`;
|
baseQuery += ` AND l.listing_type = $${paramIndex}`;
|
||||||
queryParams.push(listingType);
|
queryParams.push(listingType);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +77,7 @@ router.get("/:id", async (req, res) => {
|
||||||
res.status(200).json(listingResult.rows[0]);
|
res.status(200).json(listingResult.rows[0]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
error: `Internal Server Error in fetching the specified ${id} listing`,
|
error: `Internal Server Error in fetching the specified ${listingId} listing`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -89,7 +88,7 @@ router.put("/:id", async (req, res) => {
|
||||||
const { title, description, price } = req.body;
|
const { title, description, price } = req.body;
|
||||||
try {
|
try {
|
||||||
const updateResult = await pool.query(
|
const updateResult = await pool.query(
|
||||||
"UPDATE listings SET title = $1, description = $2, price = $3 WHERE id = $5 RETURNING *",
|
"UPDATE listings SET title = $1, description = $2, price = $3, updated_at = NOW() WHERE id = $4 RETURNING *",
|
||||||
[title, description, price, listingId]
|
[title, description, price, listingId]
|
||||||
);
|
);
|
||||||
if (updateResult.rows.length === 0) {
|
if (updateResult.rows.length === 0) {
|
||||||
|
|
@ -100,7 +99,7 @@ router.put("/:id", async (req, res) => {
|
||||||
res.status(200).json(updateResult.rows[0]);
|
res.status(200).json(updateResult.rows[0]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
error: `Internal Server Error in updating the specified ${id} listing`,
|
error: `Internal Server Error in updating the specified ${listingId} listing`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -123,10 +122,25 @@ router.post("/", async (req, res) => {
|
||||||
|
|
||||||
// Add a new location if provided
|
// Add a new location if provided
|
||||||
if (!animal.location_id && req.body.new_location) {
|
if (!animal.location_id && req.body.new_location) {
|
||||||
animal.location_id = addNewLocation(req.body.new_location);
|
const newLocation = {
|
||||||
|
...req.body.new_location,
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
newLocation.save_as_address &&
|
||||||
|
!newLocation.user_id &&
|
||||||
|
seller_id
|
||||||
|
) {
|
||||||
|
newLocation.user_id = seller_id;
|
||||||
|
}
|
||||||
|
if (typeof newLocation.is_saved_address === "undefined") {
|
||||||
|
newLocation.is_saved_address = Boolean(
|
||||||
|
newLocation.save_as_address
|
||||||
|
);
|
||||||
|
}
|
||||||
|
animal.location_id = await addNewLocation(client, newLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
const animalId = await addAnimalToListing(animal);
|
const animalId = await addAnimalToListing(client, animal);
|
||||||
|
|
||||||
const listingInsertQuery =
|
const listingInsertQuery =
|
||||||
"INSERT INTO listings (seller_id, animal_id, title, price, currency, is_negotiable, listing_type, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW()) RETURNING *";
|
"INSERT INTO listings (seller_id, animal_id, title, price, currency, is_negotiable, listing_type, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW()) RETURNING *";
|
||||||
|
|
@ -156,10 +170,10 @@ router.post("/", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const addAnimalToListing = async (animal) => {
|
const addAnimalToListing = async (client, animal) => {
|
||||||
try {
|
try {
|
||||||
const animalInsertQuery =
|
const animalInsertQuery =
|
||||||
"INSERT INTO animals (species_id, breed_id, sex, age_months, weight_kg, color_markings, quantity, purpose, health_status, vaccinated, dewormed, previous_pregnancies_count, pregnancy_status, milk_yield_litre_per_day, ear_tag_no, description, suggested_care, location_id, created_from, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, NOW(), NOW()) RETURNING id";
|
"INSERT INTO animals (species_id, breed_id, sex, age_months, weight_kg, color_markings, quantity, purpose, health_status, vaccinated, dewormed, previous_pregnancies_count, pregnancy_status, milk_yield_litre_per_day, ear_tag_no, description, suggested_care, location_id, created_from, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, NOW(), NOW()) RETURNING id";
|
||||||
const animalValues = [
|
const animalValues = [
|
||||||
animal.species_id,
|
animal.species_id,
|
||||||
animal.breed_id,
|
animal.breed_id,
|
||||||
|
|
@ -179,6 +193,7 @@ const addAnimalToListing = async (animal) => {
|
||||||
animal.description,
|
animal.description,
|
||||||
animal.suggested_care,
|
animal.suggested_care,
|
||||||
animal.location_id,
|
animal.location_id,
|
||||||
|
animal.created_from || "listing",
|
||||||
];
|
];
|
||||||
const animalResult = await client.query(
|
const animalResult = await client.query(
|
||||||
animalInsertQuery,
|
animalInsertQuery,
|
||||||
|
|
@ -191,23 +206,38 @@ const addAnimalToListing = async (animal) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addNewLocation = async (location) => {
|
const addNewLocation = async (client, location) => {
|
||||||
try {
|
try {
|
||||||
|
const {
|
||||||
|
user_id = null,
|
||||||
|
is_saved_address = false,
|
||||||
|
location_type = null,
|
||||||
|
country = null,
|
||||||
|
state = null,
|
||||||
|
district = null,
|
||||||
|
city_village = null,
|
||||||
|
pincode = null,
|
||||||
|
lat = null,
|
||||||
|
lng = null,
|
||||||
|
source_type = "unknown",
|
||||||
|
source_confidence = "medium",
|
||||||
|
} = location;
|
||||||
|
|
||||||
const locationInsertQuery =
|
const locationInsertQuery =
|
||||||
"INSERT INTO locations (user_id, is_saved_address, location_type, country, state, district, city_village, pincode, lat, lng, source_type, source_confidence, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, NOW(), NOW()) RETURNING id";
|
"INSERT INTO locations (user_id, is_saved_address, location_type, country, state, district, city_village, pincode, lat, lng, source_type, source_confidence, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, NOW(), NOW()) RETURNING id";
|
||||||
const locationValues = [
|
const locationValues = [
|
||||||
location.user_id,
|
user_id,
|
||||||
location.is_saved_address,
|
is_saved_address,
|
||||||
location.location_type,
|
location_type,
|
||||||
location.country,
|
country,
|
||||||
location.state,
|
state,
|
||||||
location.district,
|
district,
|
||||||
location.city_village,
|
city_village,
|
||||||
location.pincode,
|
pincode,
|
||||||
location.lat,
|
lat,
|
||||||
location.lng,
|
lng,
|
||||||
location.source_type,
|
source_type,
|
||||||
location.source_confidence,
|
source_confidence,
|
||||||
];
|
];
|
||||||
const locationResult = await client.query(
|
const locationResult = await client.query(
|
||||||
locationInsertQuery,
|
locationInsertQuery,
|
||||||
|
|
@ -219,4 +249,72 @@ const addNewLocation = async (location) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Delete listing by ID
|
||||||
|
router.delete("/:id", async (req, res) => {
|
||||||
|
const listingId = req.params.id;
|
||||||
|
try {
|
||||||
|
const deleteResult = await pool.query(
|
||||||
|
"DELETE FROM listings WHERE id = $1 RETURNING *",
|
||||||
|
[listingId]
|
||||||
|
);
|
||||||
|
if (deleteResult.rows.length === 0) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ error: "Listing not found or already deleted" });
|
||||||
|
}
|
||||||
|
res.status(200).json({
|
||||||
|
message: "Listing deleted successfully",
|
||||||
|
listing: deleteResult.rows[0],
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: `Internal Server Error in deleting the specified ${listingId} listing`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get all listings for a user
|
||||||
|
router.get("/user/:user_id", async (req, res) => {
|
||||||
|
const userId = req.params.user_id;
|
||||||
|
try {
|
||||||
|
const listingsResult = await pool.query(
|
||||||
|
"SELECT * FROM listings WHERE seller_id = $1 ORDER BY created_at DESC",
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
res.status(200).json(listingsResult.rows);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Internal Server Error in fetching user listings",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mark listing as sold or update listing status
|
||||||
|
router.patch("/:id/status", async (req, res) => {
|
||||||
|
const listingId = req.params.id;
|
||||||
|
const { status } = req.body;
|
||||||
|
if (!status) {
|
||||||
|
return res.status(400).json({ error: "Status must be provided" });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const updateResult = await pool.query(
|
||||||
|
"UPDATE listings SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *",
|
||||||
|
[status, listingId]
|
||||||
|
);
|
||||||
|
if (updateResult.rows.length === 0) {
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ error: "Listing not found for status update" });
|
||||||
|
}
|
||||||
|
res.status(200).json({
|
||||||
|
message: "Listing status updated",
|
||||||
|
listing: updateResult.rows[0],
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({
|
||||||
|
error: `Internal Server Error updating listing status for ${listingId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { Pool } from "pg";
|
import pool from "../db/pool.js";
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const pool = new Pool({
|
const router = express.Router();
|
||||||
user: process.env.DB_USER,
|
|
||||||
host: process.env.DB_HOST,
|
|
||||||
database: process.env.DB_NAME,
|
|
||||||
password: process.env.DB_PASSWORD_D,
|
|
||||||
port: process.env.DB_PORT,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add a new location
|
// Add a new location
|
||||||
router.post("/", async (req, res) => {
|
router.post("/", async (req, res) => {
|
||||||
|
|
@ -112,6 +105,54 @@ router.put("/:id", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get all locations for a user
|
||||||
|
router.get("/user/:user_id", async (req, res) => {
|
||||||
|
const userId = req.params.user_id;
|
||||||
|
try {
|
||||||
|
const result = await pool.query(
|
||||||
|
"SELECT * FROM locations WHERE user_id = $1 ORDER BY created_at DESC",
|
||||||
|
[userId]
|
||||||
|
);
|
||||||
|
res.status(200).json(result.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching user's locations:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Internal server error fetching user's locations",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: Remove this route later
|
||||||
|
// Get all users
|
||||||
|
router.get("/users", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await pool.query(
|
||||||
|
"SELECT * FROM users ORDER BY created_at DESC"
|
||||||
|
);
|
||||||
|
res.status(200).json(result.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching all users:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Internal server error fetching users",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get all locations
|
||||||
|
router.get("/", async (req, res) => {
|
||||||
|
try {
|
||||||
|
const result = await pool.query(
|
||||||
|
"SELECT * FROM locations ORDER BY created_at DESC"
|
||||||
|
);
|
||||||
|
res.status(200).json(result.rows);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching all locations:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Internal server error fetching locations",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Get location by ID
|
// Get location by ID
|
||||||
router.get("/:id", async (req, res) => {
|
router.get("/:id", async (req, res) => {
|
||||||
const locationId = req.params.id;
|
const locationId = req.params.id;
|
||||||
|
|
@ -133,4 +174,27 @@ router.get("/:id", async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Delete a location by ID
|
||||||
|
router.delete("/:id", async (req, res) => {
|
||||||
|
const locationId = req.params.id;
|
||||||
|
try {
|
||||||
|
const deleteQuery = "DELETE FROM locations WHERE id = $1 RETURNING *";
|
||||||
|
const result = await pool.query(deleteQuery, [locationId]);
|
||||||
|
|
||||||
|
if (result.rows.length === 0) {
|
||||||
|
return res.status(404).json({ error: "Location not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
message: "Location deleted successfully",
|
||||||
|
location: result.rows[0],
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting location:", error);
|
||||||
|
res.status(500).json({
|
||||||
|
error: "Internal server error deleting location",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue