diff --git a/client/html/pages/my/avatar.html b/client/html/pages/my/avatar.html index 78b04c8..f1c3058 100644 --- a/client/html/pages/my/avatar.html +++ b/client/html/pages/my/avatar.html @@ -173,6 +173,8 @@

Customize Your Avatar

+
+
diff --git a/client/js/avatar.js b/client/js/avatar.js index 3ec77b0..1a7e4a8 100644 --- a/client/js/avatar.js +++ b/client/js/avatar.js @@ -1,4 +1,3 @@ -// client/js/avatar.js $(document).ready(function () { initializeAvatarEditor(); loadUserAvatar(); @@ -7,6 +6,8 @@ $(document).ready(function () { function initializeAvatarEditor() { loadAvatarsItems(); setupItemSelection(); + Pagination(); + } function loadAvatarsItems() { @@ -16,19 +17,24 @@ function loadAvatarsItems() { // loadHats(); } -function loadShirts() { +let currentPage = 1; +let totalPages = 1; + +function loadShirts(page = 1) { const token = localStorage.getItem('token'); - console.log('Loading shirts for user'); + console.log('Loading shirts for user, page:', page); $.ajax({ - url: '/api/shirts/user', // Correct server route + url: `/api/shirts/user?page=${page}&limit=4`, method: 'GET', headers: { Authorization: `Bearer ${token}`, }, - success: function (shirts) { - console.log('Shirts loaded successfully:', shirts.length); - displayUserShirts(shirts); + success: function (res) { + console.log('Shirts loaded successfully:', res.shirts.length); + displayUserShirts(res.shirts); + updatePagination(res.currentPage, res.totalPages); + totalPages = res.totalPages; }, error: function (xhr, status, error) { console.error('Error fetching shirts:', error); @@ -67,6 +73,67 @@ function displayUserShirts(shirts) { }); } + + +function updatePagination(currentPage, totalPages) { + const paginationContainer = $('#pagination-container'); + paginationContainer.empty(); + + if (totalPages <= 1) { + return; + } + + const paginationHtml = ` + + `; + + paginationContainer.html(paginationHtml); +} + +function generatePageNumbers(currentPage, totalPages) { + let pageNumbers = ''; + const maxVisiblePages = 5; + let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2)); + let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1); + + if (endPage - startPage + 1 < maxVisiblePages) { + startPage = Math.max(1, endPage - maxVisiblePages + 1); + } + + for (let i = startPage; i <= endPage; i++) { + pageNumbers += ` +
  • + ${i} +
  • + `; + } + + return pageNumbers; +} + +function Pagination() { + $('#pagination-container').on('click', 'a', function (e) { + e.preventDefault(); + const page = parseInt($(this).data('page')); + if (page && page !== currentPage && page >= 1 && page <= totalPages) { + currentPage = page; + loadShirts(currentPage); + } + }); +} + function generateItemHtml(name, imageSrc, creator, price, id, type) { const priceDisplay = price === 0 ? 'Free' : `$${price}`; return ` diff --git a/server/functions/api/routes/shirt.js b/server/functions/api/routes/shirt.js index b35321d..c81a6ff 100644 --- a/server/functions/api/routes/shirt.js +++ b/server/functions/api/routes/shirt.js @@ -10,7 +10,7 @@ const Counter = require('../models/Counter'); const thumbnailQueue = require('../queues/thumbnailQueue'); const jwt = require('jsonwebtoken'); const Filter = require('bad-words'); -const crypto = require('crypto'); // Add this line to import the crypto module +const crypto = require('crypto'); const AWS = require('aws-sdk'); @@ -44,7 +44,10 @@ const authenticateToken = (req, res, next) => { if (err) { return res.sendStatus(403); } - req.user = user; + req.user = { + _id: user._id, + userId: user.userId + }; next(); }); }; @@ -67,6 +70,85 @@ async function getNextAssetId() { return counter.seq; } + +router.get('/user', authenticateToken, async (req, res) => { + try { + console.log('Fetching shirts for userId:', req.user.userId); + const user = await User.findOne({ userId: req.user.userId }).populate('inventory'); + + if (!user) { + console.error('User not found for userId:', req.user.userId); + return res.status(404).json({ error: 'User not found' }); + } + + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 4; + const skip = (page - 1) * limit; + + // Fetch shirts created by user + const createdShirts = await Asset.find({ + creator: user._id, + AssetType: 'Shirt', + }).populate('creator', 'username'); + + console.log('Created shirts found:', createdShirts.length); + + // Fetch shirts owned by user + const ownedShirts = await Asset.find({ + _id: { $in: user.inventory }, + AssetType: 'Shirt', + }).populate('creator', 'username'); + + console.log('Owned shirts found:', ownedShirts.length); + + // combine and remove duplicates + 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)); + + const totalShirts = uniqueShirts.length; + const totalPages = Math.ceil(totalShirts / limit); + const paginatedShirts = uniqueShirts.slice(skip, skip + limit); + + + console.log('Total shirts:', uniqueShirts.length); + console.log('Paginated shirts:', paginatedShirts.length); + + res.json({ + shirts: paginatedShirts, + currentPage: page, + totalPages: totalPages, + totalShirts: totalShirts + }); + + } catch (error) { + console.error('Error fetching user shirts:', error); + res.status(500).json({ error: 'Internal server error', details: error.message }); + } +}); + + +router.get('/:id', async (req, res) => { + try { + const id = req.params.id; + const shirt = await Asset.findOne({ _id: id, AssetType: 'Shirt' }).populate( + 'creator', + 'username' + ); + if (!shirt) { + return res.status(404).json({ error: 'Shirt not found' }); + } + res.json(shirt); + } catch (error) { + console.error('Error fetching shirt:', error); + res + .status(500) + .json({ error: 'Error fetching shirt', details: error.message }); + } +}); + + router.post( '/upload', authenticateToken, @@ -109,19 +191,12 @@ router.post( const assetId = await getNextAssetId(); try { - const thumbnailUrl = `/uploads/${Date.now()}-${ - req.files.thumbnail[0].originalname - }`; + const thumbnailUrl = `/uploads/${Date.now()}-${req.files.thumbnail[0].originalname}`; fs.writeFileSync( - path.join( - __dirname, - '../../../../uploads', - path.basename(thumbnailUrl) - ), + path.join(__dirname, '../../../../uploads', path.basename(thumbnailUrl)), req.files.thumbnail[0].buffer ); - // upload image first const s3Key = `shirts/${assetHash}`; const assetLocation = `https://c2.rblx18.com/${s3Key}`; await s3 @@ -134,11 +209,11 @@ router.post( }) .promise(); - // make a new asset for the image + // Create a new asset for the image const asset = new Asset({ assetId: assetId, FileLocation: assetLocation, - creator: req.user.userId, + creator: req.user._id, AssetType: 'Image', Name: filter.clean(title), Description: filter.clean(description), @@ -151,15 +226,15 @@ router.post( await asset.save(); - // get the next asset id for the shirt + // Get the next asset id for the shirt const shirtassetId = await getNextAssetId(); const shirtassetHash = generateAssetId(); - // generate xml for shirttemplate + // Generate XML for shirttemplate const shirtAssetUrl = `http://www.rblx18.com/asset/?id=${assetId}`; const shirtAssetXml = generateXml(shirtAssetUrl); - // upload the xml + // Upload the XML const shirts3Key = `${shirtassetHash}`; const shirtassetLocation = `https://c2.rblx18.com/${shirtassetHash}`; @@ -173,18 +248,17 @@ router.post( }) .promise(); - const isForSale = parseInt(price) > 0 ? 1 : 0; - + const isForSale = parseInt(price) > 0 ? 1 : 0; const shirt = new Asset({ assetId: shirtassetId, FileLocation: shirtassetLocation, - creator: req.user.userId, + creator: req.user._id, AssetType: 'Shirt', Name: filter.clean(title), Description: filter.clean(description), ThumbnailLocation: thumbnailUrl, Price: parseInt(price), - IsForSale: isForSale, //why is there 2 isforsale? + IsForSale: isForSale, Sales: 0, IsPublicDomain: 0, }); @@ -193,16 +267,7 @@ router.post( await thumbnailQueue.addToQueue(shirtassetId, 'Shirt'); - /*const shirt = new Shirt({ - title: filter.clean(title), - description: filter.clean(description), - thumbnailUrl, - creator: req.user.userId, - assetId: assetId - }); - - await shirt.save();*/ - await User.findByIdAndUpdate(req.user.userId, { + await User.findByIdAndUpdate(req.user._id, { $push: { shirts: shirt._id }, }); @@ -357,45 +422,6 @@ router.get('/user/id/:id', authenticateToken, async (req, res) => { -router.get('/user', authenticateToken, async (req, res) => { - try { - console.log('Fetching shirts for userId:', req.user.userId); - const user = await User.findOne({ userId: req.user.userId }).populate('inventory'); - - if (!user) { - console.error('User not found for userId:', req.user.userId); - return res.status(404).json({ error: 'User not found' }); - } - - // Fetch shirts created by user - const createdShirts = await Asset.find({ - creator: user._id, // Using ObjectId from User model - AssetType: 'Shirt', - }).populate('creator', 'username'); - - console.log('Created shirts found:', createdShirts.length); - - // Fetch shirts owned by user - const ownedShirts = await Asset.find({ - _id: { $in: user.inventory }, - AssetType: 'Shirt', - }).populate('creator', 'username'); - - console.log('Owned shirts found:', ownedShirts.length); - - // combine and remove duplicates - 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)); - - console.log('Total shirts:', uniqueShirts.length); - res.json(uniqueShirts); - } catch (error) { - console.error('Error fetching user shirts:', error); - res.status(500).json({ error: 'Internal server error', details: error.message }); - } -}); router.put('/:shirtId', authenticateToken, async (req, res) => { try { @@ -441,7 +467,6 @@ router.put('/:shirtId', authenticateToken, async (req, res) => { } }); -// New route to update a game router.put('/:id', authenticateToken, async (req, res) => { try { const { id } = req.params; @@ -476,25 +501,6 @@ router.put('/:id', authenticateToken, async (req, res) => { } }); -router.get('/:id', async (req, res) => { - try { - const id = req.params.id; - const shirt = await Asset.findOne({ _id: id, AssetType: 'Shirt' }).populate( - 'creator', - 'username' - ); - if (!shirt) { - return res.status(404).json({ error: 'Shirt not found' }); - } - res.json(shirt); - } catch (error) { - console.error('Error fetching shirt:', error); - res - .status(500) - .json({ error: 'Error fetching shirt', details: error.message }); - } -}); - router.get('/user/:username', authenticateToken, async (req, res) => { try { const username = req.params.username; diff --git a/uploads/1729115415035-573616139c1e4a9ef51962a243f26007.png b/uploads/1729115415035-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729115415035-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729115579129-573616139c1e4a9ef51962a243f26007.png b/uploads/1729115579129-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729115579129-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729115632165-573616139c1e4a9ef51962a243f26007.png b/uploads/1729115632165-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729115632165-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729115739684-573616139c1e4a9ef51962a243f26007.png b/uploads/1729115739684-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729115739684-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729115880999-573616139c1e4a9ef51962a243f26007.png b/uploads/1729115880999-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729115880999-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729116186301-573616139c1e4a9ef51962a243f26007.png b/uploads/1729116186301-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729116186301-573616139c1e4a9ef51962a243f26007.png differ diff --git a/uploads/1729116331254-573616139c1e4a9ef51962a243f26007.png b/uploads/1729116331254-573616139c1e4a9ef51962a243f26007.png new file mode 100644 index 0000000..eb04efb Binary files /dev/null and b/uploads/1729116331254-573616139c1e4a9ef51962a243f26007.png differ