Goal: Create a review system where clients can submit feedback about designers using a modal.
In this lesson you will build a **professional review system** using Discord modals.
Users will run the /review command which opens a modal where they can submit feedback.
The system will then send the review to a specific channel with a formatted embed.
Creates the /review slash command that users run to submit feedback.
Creates the popup form (modal) where the user fills in the review information.
Controls the type of input field.
Short → small field
Paragraph → large field for longer text
Allows the user to select another Discord user. In this system it lets the client select which designer they are reviewing.
Creates the dropdown rating menu where the user selects a rating from 1–5.
This opens the modal popup when the command is executed.
This retrieves the values the user entered inside the modal.
For example:
• Designer selected
• Product name
• Rating
• Feedback text
Creates a styled message embed which formats the review nicely in Discord.
Finds the Discord channel where the review will be sent.
You must replace CHANNEL_ID with your review channel ID.
Sends a private message only visible to the user confirming their review was submitted.
Create a new command file:
commands/review.js
This command will open the review modal.
const {
SlashCommandBuilder,
ModalBuilder,
TextInputStyle,
StringSelectMenuBuilder,
StringSelectMenuOptionBuilder,
MessageFlags,
} = require("discord.js");
module.exports = {
data: new SlashCommandBuilder()
.setName("review")
.setDescription("Submit a review"),
async execute(interaction) {
const memberRoles = interaction.member.roles.cache;
if (!memberRoles.has(""))
return interaction.reply({
content:
"You must have the `Client` role to be able to leave feedback.",
flags: MessageFlags.Ephemeral,
});
const modal = new ModalBuilder()
.setCustomId("reviewModal")
.setTitle("Submit Review")
.addLabelComponents(
(label) =>
label
.setLabel("Designer")
.setUserSelectMenuComponent((menu) =>
menu
.setCustomId("reviewdesigner")
.setPlaceholder("Select the designer")
.setRequired(true)
.setMaxValues(1),
),
(label) =>
label
.setLabel("Product")
.setTextInputComponent((input) =>
input
.setCustomId("reviewProduct")
.setPlaceholder("Custom Bot, Clothing Pack, etc")
.setRequired(true)
.setStyle(TextInputStyle.Short),
),
(label) =>
label
.setLabel("Rating")
.setStringSelectMenuComponent(
new StringSelectMenuBuilder()
.setCustomId("reviewRating")
.setPlaceholder("Select rating")
.setRequired(true)
.addOptions(
new StringSelectMenuOptionBuilder()
.setLabel("1")
.setValue("1"),
new StringSelectMenuOptionBuilder()
.setLabel("2")
.setValue("2"),
new StringSelectMenuOptionBuilder()
.setLabel("3")
.setValue("3"),
new StringSelectMenuOptionBuilder()
.setLabel("4")
.setValue("4"),
new StringSelectMenuOptionBuilder()
.setLabel("5")
.setValue("5"),
),
),
(label) =>
label
.setLabel("Feedback")
.setTextInputComponent((input) =>
input
.setCustomId("reviewFeedback")
.setPlaceholder("Your feedback about this designer")
.setRequired(true)
.setStyle(TextInputStyle.Paragraph),
),
);
await interaction.showModal(modal);
},
};
Create:
modals/reviewModal.js
This file will handle the modal submission and send the review embed.
const { EmbedBuilder, MessageFlags } = require("discord.js");
module.exports = {
customID: "reviewModal",
async execute(interaction, client, args) {
const designer =
interaction.fields.getSelectedUsers("reviewdesigner")?.first() ||
null;
const product =
interaction.fields.getTextInputValue("reviewProduct");
const rawRating =
interaction.fields.getStringSelectValues("reviewRating");
const note =
interaction.fields.getTextInputValue("reviewFeedback");
const ratingNum = Math.min(Math.max(parseInt(rawRating, 10) || 1, 1), 5);
const stars = "".repeat(ratingNum); // Enter your emoji for star id between ""
const target = client.channels.cache.get("CHANNEL_ID");
const embed = new EmbedBuilder()
.setColor(2237223)
.setAuthor({
name: `${interaction.user.username}'s feedback`,
iconURL: interaction.user.displayAvatarURL({ dynamic: true }),
})
.setTitle("Feedback Submitted")
.addFields(
{
name: "Designer",
value: designer ? `<@${designer.id}>` : "Unknown",
inline: true,
},
{
name: "Product",
value: product,
inline: true,
},
{
name: "Rating",
value: stars,
inline: true,
},
{
name: "Feedback",
value: note,
}
)
.setTimestamp();
await target.send({
embeds: [embed],
});
await interaction.reply({
content: "Your review has been submitted.",
flags: MessageFlags.Ephemeral,
});
},
};
node index.js
Your review system should now be working.