Skip to content

Commit

Permalink
purchasing shirts and displaying in profile now works
Browse files Browse the repository at this point in the history
  • Loading branch information
singharaj-usai committed Oct 11, 2024
1 parent d594596 commit 4198461
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 81 deletions.
24 changes: 4 additions & 20 deletions client/html/pages/catalog/catalog.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,6 @@
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-6563673001934226"
crossorigin="anonymous"></script>

<style>
.coming-soon-item {
height: 200px;
background-color: rgba(245, 245, 245, 0.8);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
.excitement-text {
font-size: 18px;
font-weight: bold;
color: #4a4a4a;
}
#content {
position: relative;
z-index: 1;
}
</style>
</head>
<body>
<div id="particles-js"></div>
Expand All @@ -50,9 +31,12 @@

<!-- Main Content -->
<div class="container" style="margin-top: 70px;">
<h1>Shirt Catalog</h1>
<div class="page-header">
<h1>Shirt Catalog</h1>
</div>
<div id="shirts-container" class="row"></div>
</div>
</div>

<!-- Scripts -->
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
Expand Down
4 changes: 3 additions & 1 deletion client/html/pages/catalog/shirt-details.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@

<!-- Main Content -->
<div class="container" style="margin-top: 70px;">
<div id="shirt-details"></div>
<div id="shirt-details" class="row">
<!-- Shirt details will be dynamically inserted here -->
</div>
</div>

<!-- Scripts -->
Expand Down
38 changes: 25 additions & 13 deletions client/js/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,37 @@ function displayShirts(shirts) {
shirtsContainer.empty();

if (shirts.length === 0) {
shirtsContainer.append('<p>No shirts available in the catalog.</p>');
shirtsContainer.append('<div class="col-xs-12"><div class="alert alert-info">No shirts available in the catalog.</div></div>');
return;
}

shirts.forEach(shirt => {
const shirtCard = `
<div class="col-md-3 mb-4">
<div class="card">
<img src="${shirt.ThumbnailLocation}" class="card-img-top" alt="${shirt.Name}">
<div class="card-body">
<h5 class="card-title">${shirt.Name}</h5>
<p class="card-text">Creator: ${shirt.creator ? shirt.creator.username : 'Unknown'}</p>
<p class="card-text">Price: ${shirt.Price} currency</p>
<p class="card-text">For Sale: ${shirt.IsForSale ? 'Yes' : 'No'}</p>
<a href="/catalog/${shirt._id}/${encodeURIComponent(shirt.Name)}" class="btn btn-primary">View Details</a>
shirts.forEach((shirt, index) => {
const shirtPanel = `
<div class="col-md-3 col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">${shirt.Name}</h3>
</div>
<div class="panel-body">
<img src="${shirt.ThumbnailLocation}" class="img-responsive center-block" alt="${shirt.Name}" style="max-height: 150px;">
<hr>
<p><strong>Creator:</strong> ${shirt.creator ? shirt.creator.username : 'Unknown'}</p>
<p><strong>Price:</strong> ${shirt.Price} currency</p>
<p><strong>For Sale:</strong> ${shirt.IsForSale ? 'Yes' : 'No'}</p>
</div>
<div class="panel-footer">
<a href="/catalog/${shirt._id}/${encodeURIComponent(shirt.Name)}" class="btn btn-primary btn-block">View Details</a>
</div>
</div>
</div>
`;
shirtsContainer.append(shirtCard);
shirtsContainer.append(shirtPanel);

if ((index + 1) % 4 === 0) {
shirtsContainer.append('<div class="clearfix visible-md visible-lg"></div>');
}
if ((index + 1) % 2 === 0) {
shirtsContainer.append('<div class="clearfix visible-sm"></div>');
}
});
}
86 changes: 72 additions & 14 deletions client/js/shirt-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,66 @@ function displayShirtDetails(shirt) {
const shirtDetailsContainer = $('#shirt-details');
const isOwner = shirt.creator._id === localStorage.getItem('userId');
const detailsHtml = `
<h1>${shirt.Name}</h1>
<img src="${shirt.ThumbnailLocation}" alt="${shirt.Name}" style="max-width: 300px;">
<p>${shirt.Description}</p>
<p>Creator: ${shirt.creator ? shirt.creator.username : 'Unknown'}</p>
<p>Price: ${shirt.Price} currency</p>
<p>For Sale: ${shirt.IsForSale ? 'Yes' : 'No'}</p>
${isOwner ? '<p>You own this shirt</p>' : (shirt.IsForSale ? '<button id="purchase-btn" class="btn btn-primary">Purchase</button>' : '')}
<div class="col-md-6">
<div class="thumbnail">
<img src="${shirt.ThumbnailLocation}" alt="${shirt.Name}" class="img-responsive">
</div>
</div>
<div class="col-md-6">
<h1>${shirt.Name}</h1>
<p class="lead">By <a href="/user-profile?username=${encodeURIComponent(shirt.creator.username)}">${shirt.creator ? shirt.creator.username : 'Unknown'}</a></p>
<hr>
<div class="well">
<h3>Description</h3>
<p>${shirt.Description}</p>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Shirt Details</h3>
</div>
<div class="panel-body">
<p><strong>Price:</strong> ${shirt.Price} currency</p>
<p><strong>For Sale:</strong> ${shirt.IsForSale ? 'Yes' : 'No'}</p>
</div>
</div>
<div id="purchase-section"></div>
</div>
`;
shirtDetailsContainer.html(detailsHtml);

if (!isOwner && shirt.IsForSale) {
$('#purchase-btn').on('click', function() {
purchaseShirt(shirt._id);
});
}
checkOwnership(shirt._id);
}

function checkOwnership(shirtId) {
$.ajax({
url: `/api/shirts/check-ownership/${shirtId}`,
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
success: function(response) {
if (response.owned) {
$('#purchase-section').html('<div class="alert alert-info">You own this shirt</div>');
} else if (response.isCreator) {
$('#purchase-section').html('<div class="alert alert-info">You are the creator of this shirt</div>');
} else {
// Use response.price instead of shirt.Price
$('#purchase-section').html(`
<button id="purchase-btn" class="btn btn-primary btn-lg btn-block">
<i class="fa fa-shopping-cart"></i> Purchase for ${response.price} currency
</button>
`);
$('#purchase-btn').on('click', function() {
purchaseShirt(shirtId);
});
}
},
error: function(xhr, status, error) {
console.error('Error checking shirt ownership:', error);
$('#purchase-section').html('<div class="alert alert-danger">Error checking ownership status</div>');
}
});
}
function purchaseShirt(shirtId) {
$.ajax({
url: `/api/shirts/purchase/${shirtId}`,
Expand All @@ -47,16 +90,31 @@ function purchaseShirt(shirtId) {
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
success: function(response) {
alert('Shirt purchased successfully!');
showAlert('success', 'Shirt purchased successfully!');
updateCurrency(response.newBalance);
loadShirtDetails(shirtId); // Reload shirt details to update the UI
},
error: function(xhr, status, error) {
alert('Error purchasing shirt: ' + xhr.responseJSON.error);
console.error('Error purchasing shirt:', xhr.responseJSON);
let errorMessage = 'Error purchasing shirt. Please try again later.';
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMessage = xhr.responseJSON.error;
}
showAlert('danger', errorMessage);
}
});
}

function updateCurrency(newBalance) {
$('#currency-amount').text(newBalance);
}

function showAlert(type, message) {
const alertHtml = `
<div class="alert alert-${type} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
${message}
</div>
`;
$('#shirt-details').prepend(alertHtml);
}
27 changes: 14 additions & 13 deletions client/js/user-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,21 +465,22 @@ $(document).ready(function () {

function loadUserShirts(userId) {
$.ajax({
url: `/api/shirts/user/${userId}`,
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
success: function(shirts) {
displayUserShirts(shirts);
},
error: function(xhr, status, error) {
console.error('Error fetching user shirts:', error);
}
url: `/api/shirts/user/id/${userId}`, // Updated URL
method: 'GET',
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
success: function(shirts) {
displayUserShirts(shirts);
},
error: function(xhr, status, error) {
console.error('Error fetching user shirts:', error);
$('#user-shirts').html('<p>Error loading your shirts. Please try again later.</p>');
}
});
}
}

function displayUserShirts(shirts) {
function displayUserShirts(shirts) {
const shirtsContainer = $('#user-shirts');
shirtsContainer.empty();

Expand Down
5 changes: 5 additions & 0 deletions server/functions/api/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ forumPostCount: {
default: 0
},

inventory: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Asset'
}],

});


Expand Down
96 changes: 76 additions & 20 deletions server/functions/api/routes/shirt.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,34 +213,90 @@ router.get('/catalog', async (req, res) => {

router.post('/purchase/:id', authenticateToken, async (req, res) => {
try {
const shirt = await Asset.findOne({ _id: req.params.id, AssetType: 'Shirt', IsForSale: 1 });
if (!shirt) {
return res.status(404).json({ error: 'Shirt not found or not for sale' });
}
const shirt = await Asset.findOne({ _id: req.params.id, AssetType: 'Shirt', IsForSale: 1 });
if (!shirt) {
return res.status(404).json({ error: 'Shirt not found or not for sale' });
}

const user = await User.findById(req.user.userId);
if (user.currency < shirt.Price) {
return res.status(400).json({ error: 'Insufficient funds' });
}
const user = await User.findById(req.user.userId);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}

if (shirt.creator.toString() === user._id.toString()) {
return res.status(400).json({ error: 'You already own this shirt' });
}
if (user.inventory && user.inventory.includes(shirt._id)) {
return res.status(400).json({ error: 'You already own this shirt' });
}

user.currency -= shirt.Price;
user.inventory.push(shirt._id);
await user.save();
if (user.currency < shirt.Price) {
return res.status(400).json({ error: 'Insufficient funds' });
}

shirt.Sales += 1;
await shirt.save();
if (shirt.creator.toString() === user._id.toString()) {
return res.status(400).json({ error: 'You already own this shirt' });
}

user.currency -= shirt.Price;

if (!user.inventory) {
user.inventory = [];
}

user.inventory.push(shirt._id);
await user.save();

res.json({ success: true, newBalance: user.currency });
shirt.Sales += 1;
await shirt.save();

res.json({ success: true, newBalance: user.currency });
} catch (error) {
console.error('Error purchasing shirt:', error);
res.status(500).json({ error: 'Internal server error' });
console.error('Error purchasing shirt:', error);
res.status(500).json({ error: 'Internal server error', details: error.message });
}
});

router.get('/check-ownership/:id', authenticateToken, async (req, res) => {
try {
const shirt = await Asset.findOne({ _id: req.params.id, AssetType: 'Shirt' });
if (!shirt) {
return res.status(404).json({ error: 'Shirt not found' });
}

const user = await User.findById(req.user.userId);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}

const owned = user.inventory && user.inventory.includes(shirt._id);
const isCreator = shirt.creator.toString() === user._id.toString();

// Include the shirt's price in the response
res.json({ owned, isCreator, price: shirt.Price });
} catch (error) {
console.error('Error checking shirt ownership:', error);
res.status(500).json({ error: 'Internal server error', details: error.message });
}
});

router.get('/user/id/:id', authenticateToken, async (req, res) => {
try {
const userId = req.params.id;
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}

const createdShirts = await Asset.find({ creator: userId, AssetType: 'Shirt' }).sort({ createdAt: -1 });
const ownedShirts = await Asset.find({ _id: { $in: user.inventory }, AssetType: 'Shirt' }).sort({ createdAt: -1 });
const allShirts = [...createdShirts, ...ownedShirts];
const uniqueShirts = Array.from(new Set(allShirts.map(s => s._id.toString())))
.map(_id => allShirts.find(s => s._id.toString() === _id));

res.json(uniqueShirts);
} catch (error) {
console.error('Error fetching user shirts by ID:', error);
res.status(500).json({ error: 'Internal server error' });
}
});

router.get('/user', authenticateToken, async (req, res) => {
try {
const shirts = await Asset.find({ creator: req.user.userId, AssetType: 'Shirt' }).sort({ updatedAt: -1 });
Expand Down

0 comments on commit 4198461

Please sign in to comment.