Pixel Panda is an innovative online marketplace that connects game artists with developers and buyers. Our platform offers a wide range of game assets, organized into categories for easy browsing. Users can add their favorite artworks to their shopping carts or save them to their wish lists for future reference. Our review system allows buyers to share their experiences and provide valuable feedback to artists, helping others make informed decisions when selecting assets. With the ability to write, edit, or delete reviews, users have complete control over their contributions to the Pixel Panda community.
- Frontend: React, Redux
- Backend: Node, Express, MongoDB
- AWS
- Stripe
router.post('/users/:userId', requireUser, validateWishlistItemInput, async (req, res, next) => {
try {
const newWishlistItem = new WishlistItem({
user: req.params.userId,
artwork: req.body.artwork
});
let wishlistItem = await newWishlistItem.save();
wishlistItem = await wishlistItem.populate('user', 'artwork');
return res.json(wishlistItem);
}
catch (err) {
next(err);
}
});
const singleFileUpload = async ({ file, public = false }) => {
const { originalname, buffer } = file;
const path = require("path");
const Key = new Date().getTime().toString() + path.extname(originalname);
const uploadParams = {
Bucket: NAME_OF_BUCKET,
Key: public ? `public/${Key}` : Key,
Body: buffer
};
const result = await s3.upload(uploadParams).promise();
return public ? result.Location : result.Key;
};
router.post('/', async (req, res) => {
let success_url = `${process.env.CLIENT_URL}/checkout`;
let cancel_url = `${process.env.CLIENT_URL}/cart`;
const website = "https://pixelpanda.onrender.com";
if (isProduction) {
success_url = `${website}/checkout`;
cancel_url = `${website}/cart`;
}
const session = await stripe.checkout.sessions.create({
line_items: req.body.cartItems.map(cartItem => {
return {
price_data: {
currency: 'usd',
product_data: {
name: cartItem.name,
images: [cartItem.ArtworkImageUrl],
},
unit_amount: parseFloat((cartItem.price * 100).toFixed(2)),
},
adjustable_quantity: {
enabled: false,
},
quantity: 1,
}
}),
submit_type: 'pay',
mode: 'payment',
payment_method_types: ['card'],
success_url: success_url,
cancel_url: cancel_url,
});
res.send(session);
});
const handleSubmit = (e) => {
e.preventDefault();
if (image.length === 0) {
alert('Please upload an image');
return;
}
const formData = new FormData();
const errorData = {
name: "",
description: "",
price: "",
category: ""
};
if (name.trim()) formData.append("name", name.trim());
else errorData.name = "Please enter a name";
if (description.trim()) formData.append("description", description.trim());
else errorData.description = "Please enter a description";
if (price && !isNaN(price) && price > 0 && price < 100000) {
const formattedPrice = parseFloat(parseFloat(price).toFixed(2));
formData.append("price", formattedPrice);
}
else errorData.price = "Please enter a valid price";
formData.append("image", image);
if (category) formData.append("category", category);
else errorData.category = "Please select a category";
formData.append("author", sessionUser._id)
setErrors(errorData);
if (errorData.name || errorData.description || errorData.price || errorData.category) return;
else {
dispatch(createArtwork(formData)).then(() => {
if (updateShouldFetchArtworks) {
updateShouldFetchArtworks(true);
}
setImage([]);
setImageUrl([]);
setPrice("0")
setName('');
setDescription('');
setCategory("");
fileRef.current.value = null;
onClose();
dispatch(fetchArtworks());
});
}
};
const handleSubmit = (e) => {
e.preventDefault();
const reviewData = {
...review,
content,
rating,
author,
artworkId
}
setErrors([]);
if (formType === "Edit Review") {
dispatch(updateReview(reviewData,reviewId))
.then(() => {
history.push(`/artworks/${artworkId}`)
})
} else {
dispatch(createReview({ artworkId, author, content, rating }))
.then(() => {
history.push(`/artworks/${artworkId}`)
})
}
}
export const checkoutCartItems = (cartItems) => async dispatch => {
const stripe = await loadStripe(STRIPE_PUBLISHABLE_KEY);
const res = await jwtFetch(`/api/stripe/`, {
method: 'POST',
body: JSON.stringify({ cartItems })
})
const session = await res.json();
stripe.redirectToCheckout({ sessionId: session.id });
}