← Back to lessons
DESIGN SYSTEMS

Lesson — Review System

Goal: Create a review system where clients can submit feedback about designers using a modal.

Lesson Overview

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.

Video Lesson

Notes — Understanding the Code

SlashCommandBuilder

Creates the /review slash command that users run to submit feedback.

ModalBuilder

Creates the popup form (modal) where the user fills in the review information.

TextInputStyle

Controls the type of input field.
Short → small field
Paragraph → large field for longer text

User Select Menu

Allows the user to select another Discord user. In this system it lets the client select which designer they are reviewing.

StringSelectMenuBuilder

Creates the dropdown rating menu where the user selects a rating from 1–5.

interaction.showModal()

This opens the modal popup when the command is executed.

interaction.fields

This retrieves the values the user entered inside the modal. For example:
• Designer selected
• Product name
• Rating
• Feedback text

EmbedBuilder

Creates a styled message embed which formats the review nicely in Discord.

client.channels.cache.get()

Finds the Discord channel where the review will be sent. You must replace CHANNEL_ID with your review channel ID.

MessageFlags.Ephemeral

Sends a private message only visible to the user confirming their review was submitted.

Step-by-Step

Create the command file

Create a new command file: commands/review.js This command will open the review modal.

Add the Review Command

Show Code


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 the modal handler

Create: modals/reviewModal.js This file will handle the modal submission and send the review embed.

Add the Modal Code

Show Code

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,
    });

  },
};

Restart the bot


node index.js

Your review system should now be working.

Challenge

Completion Checklist

← Course Home Next Lesson →