Skip to content

Commit

Permalink
add review command and make product photo larger using inventory command
Browse files Browse the repository at this point in the history
  • Loading branch information
radekm2000 committed May 24, 2024
1 parent b7bfe8f commit 93be66d
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 39 deletions.
22 changes: 7 additions & 15 deletions client/ecommerce/src/components/DisplayUserProducts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ProductWithImageAndUser } from "../types/types";
import { useMediaQuery } from "../hooks/useMediaQuery";
import { Link, useLocation } from "wouter";
import { calculateGridWidth } from "../utils/calculateGridWidth";
import { RenderAvatar } from "./RenderAvatar";

export const DisplayUserProducts = ({
products,
Expand Down Expand Up @@ -92,21 +93,12 @@ export const DisplayUserProducts = ({
cursor: "pointer",
}}
>
{product.user.avatar ? (
<Avatar
sx={{ width: "24px", height: "24px" }}
alt="user-avatar"
src={product.user.avatar}
/>
) : (
<AccountCircle
sx={{
color: "grey",
width: "24px",
height: "24px",
}}
/>
)}
<RenderAvatar
height="24px"
width="24px"
user={product.user}
/>

<Typography
sx={{
fontSize: "12px",
Expand Down
14 changes: 4 additions & 10 deletions client/ecommerce/src/components/ProductPage/DisplayUserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Link, useLocation } from "wouter";
import { useUserInfo } from "../../hooks/useUserInfo";
import { calculateMedian } from "../../utils/calculateMedian";
import { FallbackProgress } from "../../utils/FallbackProgress";
import { RenderAvatar } from "../RenderAvatar";
export const DisplayUserInfo = ({
userId,
product,
Expand Down Expand Up @@ -136,6 +137,7 @@ export const DisplayUserInfo = ({
flexDirection: "row",
padding: "16px",
backgroundColor: "white",
gap: "10px",

alignItems: "center",
justifyContent: "flex-start",
Expand All @@ -144,16 +146,8 @@ export const DisplayUserInfo = ({
cursor: "pointer",
}}
>
{user?.avatar ? (
<Avatar
src={user.avatar}
sx={{ width: "48px", height: "48px", marginRight: "8px" }}
/>
) : (
<AccountCircle
sx={{ width: "48px", height: "48px", color: "grey" }}
/>
)}
<RenderAvatar height="48px" width="48px" user={user} />

<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography sx={{ fontSize: "16px", color: "#171717" }}>
{user?.username}
Expand Down
15 changes: 4 additions & 11 deletions client/ecommerce/src/components/ratingSystem/ReviewForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
import { UserWithAvatar } from "../../types/types";
import { AccountCircle } from "@mui/icons-material";
import { Controller, SubmitHandler, useForm } from "react-hook-form";
import { useState } from "react";
import { useState } from "react";
import { useAddReview } from "../../hooks/useAddReview";
import { useMediaQuery } from "../../hooks/useMediaQuery";
import { RenderAvatar } from "../RenderAvatar";

type FormFields = {
rating: number;
Expand Down Expand Up @@ -74,16 +75,8 @@ export const ReviewForm = ({ user }: { user: UserWithAvatar }) => {
alignItems: "center",
}}
>
{user.avatar ? (
<Avatar
sx={{ width: "64px", height: "64px" }}
src={user.avatar}
/>
) : (
<AccountCircle
sx={{ width: "64px", height: "64px", color: "grey" }}
/>
)}
<RenderAvatar height="64px" width="64px " user={user} />

<Typography sx={{ marginLeft: "5px" }}>{user.username}</Typography>
</Box>
<Box sx={{ marginTop: "10px" }}>
Expand Down
2 changes: 2 additions & 0 deletions server/ecommerce/src/discord-bot/discord-bot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ProfileCommand } from './src/commands/profile';
import { UsersService } from 'src/users/users.service';
import { InventoryCommand } from './src/commands/inventory';
import { ProductsService } from 'src/products/products.service';
import { ReviewsCommand } from './src/commands/reviews';

@Injectable()
export class DiscordBotService implements OnModuleInit {
Expand Down Expand Up @@ -42,6 +43,7 @@ export class DiscordBotService implements OnModuleInit {
productsService: this.productsService,
usersService: this.userService,
}),
new ReviewsCommand({ usersService: this.userService }),
],
});
}
Expand Down
2 changes: 1 addition & 1 deletion server/ecommerce/src/discord-bot/src/commands/inventory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class InventoryCommand implements SlashCommand {
{ name: 'Brand', value: product.brand, inline: true },
{ name: 'Category', value: product.category, inline: true },
])
.setThumbnail(productImage);
.setImage(productImage);
});

return [headerEmbed, ...productEmbeds];
Expand Down
105 changes: 105 additions & 0 deletions server/ecommerce/src/discord-bot/src/commands/reviews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
ChatInputCommandInteraction,
EmbedBuilder,
SlashCommandBuilder,
} from 'discord.js';
import { SlashCommand } from './slash-command';
import { UsersService } from 'src/users/users.service';
import { Review } from 'src/utils/entities/review.entity';
import { DiscordEmbedColors } from '../discord-embeds/colors';

type Config = {
usersService: UsersService;
};

export class ReviewsCommand implements SlashCommand {
private readonly usersService: UsersService;

public readonly config = new SlashCommandBuilder()
.setName('reviews')
.setDescription('Displays reviews that are listed on your profile');

constructor(config: Config) {
this.usersService = config.usersService;
}

public execute = async (interaction: ChatInputCommandInteraction) => {
const userId = interaction.user.id;
const userAvatar = interaction.user.avatarURL();

await interaction.deferReply({ ephemeral: true });

const user = await this.usersService.getUserWithReviews(userId);

const totalReviews = this.calculateTotalReviews(user.reviews);
const averageRating = this.calculateAverageReviewsRating(user.reviews);

if (totalReviews === 0) {
await interaction.editReply('You have no reviews yet');
}

const embed = await this.createEmbed(
totalReviews,
averageRating,
user.reviews,
userAvatar,
);

await interaction.editReply({ embeds: [embed] });
};

private createEmbed = async (
totalReviews: number,
averageRating: number,
reviews: Review[],
userAvatar: string,
) => {
const embed = new EmbedBuilder()
.setTitle(
`You have a total of ${totalReviews} reviews with an average rating of ⭐ ${averageRating.toFixed(
2,
)}`,
)
.setColor(DiscordEmbedColors.default)
.setThumbnail(userAvatar);

reviews.forEach((review) => {
embed.addFields([
{
name: 'Reviewer',
value: review.reviewCreator.username,
inline: true,
},
{
name: 'Rating',
value: `⭐ ${review.rating.toString()}`,
inline: true,
},
{ name: 'Comment', value: review.comment },
]);
});

return embed;
};

private calculateTotalReviews = (reviews: Review[]) => {
return reviews.length;
};

private calculateAverageReviewsRating = (reviews: Review[]): number => {
if (reviews.length === 0) {
return 0;
}

const ratings = reviews.map((review) => review.rating);
const sortedRatings = ratings.sort((a, b) => a - b);

const middleIndex = Math.floor(sortedRatings.length / 2);

if (sortedRatings.length % 2 === 0) {
return (sortedRatings[middleIndex - 1] + sortedRatings[middleIndex]) / 2;
} else {
return sortedRatings[middleIndex];
}
};
}
19 changes: 19 additions & 0 deletions server/ecommerce/src/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,25 @@ export class UsersService {
return user;
}

public getUserWithReviews = async (discordId: string) => {
const user = await this.usersRepository.findOne({
where: {
discordId,
},
relations: {
reviews: {
reviewCreator: true,
},
avatarEntity: true,
},
});
if (!user) {
throw new HttpException('User not found', HttpStatus.NOT_FOUND);
}

return user;
};

public findUserByDiscordId = async (discordId: string) => {
const user = await this.usersRepository.findOne({
where: {
Expand Down
5 changes: 3 additions & 2 deletions server/ecommerce/src/utils/dtos/product.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ const User = z.object({
id: z.number(),
username: z.string(),
googleId: z.string().or(z.null()),
email: z.string(),
role: z.enum(['user', 'admin']),
email: z.string().or(z.null()),
role: z.enum(['user', 'admin', 'discordUser']),
avatar: z.string().or(z.null()),
discordId: z.string().or(z.null()),
});

export const ProductWithImageAndUserSchema = z.object({
Expand Down

0 comments on commit 93be66d

Please sign in to comment.