getting to payment screen. Bug fixes and formatting changes for item detail
This commit is contained in:
@@ -1,127 +1,123 @@
|
||||
const { DataTypes } = require('sequelize');
|
||||
const sequelize = require('../config/database');
|
||||
const { DataTypes } = require("sequelize");
|
||||
const sequelize = require("../config/database");
|
||||
|
||||
const Item = sequelize.define('Item', {
|
||||
const Item = sequelize.define("Item", {
|
||||
id: {
|
||||
type: DataTypes.UUID,
|
||||
defaultValue: DataTypes.UUIDV4,
|
||||
primaryKey: true
|
||||
primaryKey: true,
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
allowNull: false,
|
||||
},
|
||||
description: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: false
|
||||
allowNull: false,
|
||||
},
|
||||
pickUpAvailable: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
localDeliveryAvailable: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
localDeliveryRadius: {
|
||||
type: DataTypes.INTEGER,
|
||||
validate: {
|
||||
min: 1,
|
||||
max: 100
|
||||
}
|
||||
max: 100,
|
||||
},
|
||||
},
|
||||
shippingAvailable: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
inPlaceUseAvailable: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
pricePerHour: {
|
||||
type: DataTypes.DECIMAL(10, 2)
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
},
|
||||
pricePerDay: {
|
||||
type: DataTypes.DECIMAL(10, 2)
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
},
|
||||
replacementCost: {
|
||||
type: DataTypes.DECIMAL(10, 2),
|
||||
allowNull: false
|
||||
},
|
||||
location: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
allowNull: false,
|
||||
},
|
||||
address1: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
address2: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
city: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
state: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
zipCode: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
country: {
|
||||
type: DataTypes.STRING
|
||||
type: DataTypes.STRING,
|
||||
},
|
||||
latitude: {
|
||||
type: DataTypes.DECIMAL(10, 8)
|
||||
type: DataTypes.DECIMAL(10, 8),
|
||||
},
|
||||
longitude: {
|
||||
type: DataTypes.DECIMAL(11, 8)
|
||||
type: DataTypes.DECIMAL(11, 8),
|
||||
},
|
||||
images: {
|
||||
type: DataTypes.ARRAY(DataTypes.STRING),
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
},
|
||||
availability: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: true
|
||||
defaultValue: true,
|
||||
},
|
||||
specifications: {
|
||||
type: DataTypes.JSONB,
|
||||
defaultValue: {}
|
||||
defaultValue: {},
|
||||
},
|
||||
rules: {
|
||||
type: DataTypes.TEXT
|
||||
type: DataTypes.TEXT,
|
||||
},
|
||||
minimumRentalDays: {
|
||||
type: DataTypes.INTEGER,
|
||||
defaultValue: 1
|
||||
defaultValue: 1,
|
||||
},
|
||||
maximumRentalDays: {
|
||||
type: DataTypes.INTEGER
|
||||
type: DataTypes.INTEGER,
|
||||
},
|
||||
needsTraining: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
unavailablePeriods: {
|
||||
type: DataTypes.JSONB,
|
||||
defaultValue: []
|
||||
defaultValue: [],
|
||||
},
|
||||
availableAfter: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: '09:00'
|
||||
defaultValue: "09:00",
|
||||
},
|
||||
availableBefore: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: '17:00'
|
||||
defaultValue: "17:00",
|
||||
},
|
||||
specifyTimesPerDay: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false
|
||||
defaultValue: false,
|
||||
},
|
||||
weeklyTimes: {
|
||||
type: DataTypes.JSONB,
|
||||
@@ -132,17 +128,17 @@ const Item = sequelize.define('Item', {
|
||||
wednesday: { availableAfter: "09:00", availableBefore: "17:00" },
|
||||
thursday: { availableAfter: "09:00", availableBefore: "17:00" },
|
||||
friday: { availableAfter: "09:00", availableBefore: "17:00" },
|
||||
saturday: { availableAfter: "09:00", availableBefore: "17:00" }
|
||||
}
|
||||
saturday: { availableAfter: "09:00", availableBefore: "17:00" },
|
||||
},
|
||||
},
|
||||
ownerId: {
|
||||
type: DataTypes.UUID,
|
||||
allowNull: false,
|
||||
references: {
|
||||
model: 'Users',
|
||||
key: 'id'
|
||||
}
|
||||
}
|
||||
model: "Users",
|
||||
key: "id",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = Item;
|
||||
module.exports = Item;
|
||||
|
||||
@@ -9,7 +9,6 @@ router.get("/", async (req, res) => {
|
||||
const {
|
||||
minPrice,
|
||||
maxPrice,
|
||||
location,
|
||||
city,
|
||||
zipCode,
|
||||
search,
|
||||
@@ -24,7 +23,6 @@ router.get("/", async (req, res) => {
|
||||
if (minPrice) where.pricePerDay[Op.gte] = minPrice;
|
||||
if (maxPrice) where.pricePerDay[Op.lte] = maxPrice;
|
||||
}
|
||||
if (location) where.location = { [Op.iLike]: `%${location}%` };
|
||||
if (city) where.city = { [Op.iLike]: `%${city}%` };
|
||||
if (zipCode) where.zipCode = { [Op.iLike]: `%${zipCode}%` };
|
||||
if (search) {
|
||||
@@ -83,6 +81,42 @@ router.get("/recommendations", authenticateToken, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Public endpoint to get reviews for a specific item (must come before /:id route)
|
||||
router.get('/:id/reviews', async (req, res) => {
|
||||
try {
|
||||
const { Rental, User } = require('../models');
|
||||
|
||||
const reviews = await Rental.findAll({
|
||||
where: {
|
||||
itemId: req.params.id,
|
||||
status: 'completed',
|
||||
rating: { [Op.not]: null },
|
||||
review: { [Op.not]: null }
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'renter',
|
||||
attributes: ['id', 'firstName', 'lastName']
|
||||
}
|
||||
],
|
||||
order: [['createdAt', 'DESC']]
|
||||
});
|
||||
|
||||
const averageRating = reviews.length > 0
|
||||
? reviews.reduce((sum, review) => sum + review.rating, 0) / reviews.length
|
||||
: 0;
|
||||
|
||||
res.json({
|
||||
reviews,
|
||||
averageRating,
|
||||
totalReviews: reviews.length
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
router.get("/:id", async (req, res) => {
|
||||
try {
|
||||
const item = await Item.findByPk(req.params.id, {
|
||||
|
||||
Reference in New Issue
Block a user